mDNSResponder-1807.101.2

Imported from mDNSResponder-1807.101.2.tar.gz
diff --git a/Clients/BonjourExample/BonjourExample.cpp b/Clients/BonjourExample/BonjourExample.cpp
deleted file mode 100644
index f517456..0000000
--- a/Clients/BonjourExample/BonjourExample.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2005 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.
- */
-
-#include	"stdafx.h"
-
-#include	<assert.h>
-#include	<stdio.h>
-
-#include	"dns_sd.h"
-
-// Constants
-
-#define BONJOUR_EVENT		( WM_USER + 0x100 )	// Message sent to the Window when a Bonjour event occurs.
-
-// Prototypes
-
-static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam );
-
-static void DNSSD_API
-	BrowserCallBack( 
-		DNSServiceRef		inServiceRef, 
-		DNSServiceFlags		inFlags,
-		uint32_t			inIFI, 
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain, 
-		void *				inContext );
-
-// Globals
-
-DNSServiceRef		gServiceRef = NULL;
-
-// Main entry point for application.
-
-int _tmain( int argc, _TCHAR *argv[] )
-{
-	HINSTANCE				instance;
-	WNDCLASSEX				wcex;
-	HWND					wind;
-	MSG						msg;
-	DNSServiceErrorType		err;
-	
-	(void) argc; // Unused
-	(void) argv; // Unused
-	
-	// Create the window. This window won't actually be shown, but it demonstrates how to use Bonjour
-	// with Windows GUI applications by having Bonjour events processed as messages to a Window.
-	
-	instance = GetModuleHandle( NULL );
-	assert( instance );
-	
-	wcex.cbSize			= sizeof( wcex );
-	wcex.style			= 0;
-	wcex.lpfnWndProc	= (WNDPROC) WndProc;
-	wcex.cbClsExtra		= 0;
-	wcex.cbWndExtra		= 0;
-	wcex.hInstance		= instance;
-	wcex.hIcon			= NULL;
-	wcex.hCursor		= NULL;
-	wcex.hbrBackground	= NULL;
-	wcex.lpszMenuName	= NULL;
-	wcex.lpszClassName	= TEXT( "BonjourExample" );
-	wcex.hIconSm		= NULL;
-	RegisterClassEx( &wcex );
-	
-	wind = CreateWindow( wcex.lpszClassName, wcex.lpszClassName, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 
-		0, NULL, NULL, instance, NULL );
-	assert( wind );
-	
-	// Start browsing for services and associate the Bonjour browser with our window using the 
-	// WSAAsyncSelect mechanism. Whenever something related to the Bonjour browser occurs, our 
-	// private Windows message will be sent to our window so we can give Bonjour a chance to 
-	// process it. This allows Bonjour to avoid using a secondary thread (and all the issues 
-	// with synchronization that would introduce), but still process everything asynchronously.
-	// This also simplifies app code because Bonjour will only run when we explicitly call it.
-	
-	err = DNSServiceBrowse( 
-		&gServiceRef, 					// Receives reference to Bonjour browser object.
-		0,								// No flags.
-		kDNSServiceInterfaceIndexAny,	// Browse on all network interfaces.
-		"_http._tcp",					// Browse for HTTP service types.
-		NULL,							// Browse on the default domain (e.g. local.).
-		BrowserCallBack, 				// Callback function when Bonjour events occur.
-		NULL );							// No callback context needed.
-	assert( err == kDNSServiceErr_NoError );
-	
-	err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, FD_READ | FD_CLOSE );
-	assert( err == kDNSServiceErr_NoError );
-	
-	fprintf( stderr, "Browsing for _http._tcp\n" );
-	
-	// Main event loop for the application. All Bonjour events are dispatched while in this loop.
-	
-	while( GetMessage( &msg, NULL, 0, 0 ) ) 
-	{
-		TranslateMessage( &msg );
-		DispatchMessage( &msg );
-	}
-	
-	// Clean up Bonjour. This is not strictly necessary since the normal process cleanup will 
-	// close Bonjour socket(s) and release memory, but it's here to demonstrate how to do it.
-	
-	if( gServiceRef )
-	{
-		WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), wind, BONJOUR_EVENT, 0 );
-		DNSServiceRefDeallocate( gServiceRef );
-	}
-	return( 0 );
-}
-
-// Callback for the Window. Bonjour events are delivered here.
-
-static LRESULT CALLBACK WndProc( HWND inWindow, UINT inMsg, WPARAM inWParam, LPARAM inLParam )
-{
-	LRESULT					result;
-	DNSServiceErrorType		err;
-	
-	switch( inMsg )
-	{
-		case BONJOUR_EVENT:
-			
-			// Process the Bonjour event. All Bonjour callbacks occur from within this function.
-			// If an error occurs while trying to process the result, it most likely means that
-			// something serious has gone wrong with Bonjour, such as it being terminated. This 
-			// does not normally occur, but code should be prepared to handle it. If the error 
-			// is ignored, the window will receive a constant stream of BONJOUR_EVENT messages so
-			// if an error occurs, we disassociate the DNSServiceRef from the window, deallocate
-			// it, and invalidate the reference so we don't try to deallocate it again on quit. 
-			// Since this is a simple example app, if this error occurs, we quit the app too.
-			
-			err = DNSServiceProcessResult( gServiceRef );
-			if( err != kDNSServiceErr_NoError )
-			{
-				fprintf( stderr, "### ERROR! serious Bonjour error: %d\n", err );
-				
-				WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( gServiceRef ), inWindow, BONJOUR_EVENT, 0 );
-				DNSServiceRefDeallocate( gServiceRef );
-				gServiceRef = NULL;
-				
-				PostQuitMessage( 0 );
-			}
-			result = 0;
-			break;
-		
-		default:
-			result = DefWindowProc( inWindow, inMsg, inWParam, inLParam );
-			break;
-	}
-	return( result );
-}
-
-// Callback for Bonjour browser events. Called when services are added or removed.
-
-static void DNSSD_API
-	BrowserCallBack( 
-		DNSServiceRef		inServiceRef, 
-		DNSServiceFlags		inFlags,
-		uint32_t			inIFI, 
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain, 
-		void *				inContext )
-{
-	(void) inServiceRef;	// Unused
-	(void) inContext;		// Unused
-	
-	if( inError == kDNSServiceErr_NoError )
-	{
-		const char *		action;
-		const char *		more;
-		
-		if( inFlags & kDNSServiceFlagsAdd )			action	= "ADD";
-		else										action	= "RMV";
-		if( inFlags & kDNSServiceFlagsMoreComing )	more	= " (MORE)";
-		else										more	= "";
-		
-		fprintf( stderr, "%s %30s.%s%s on interface %d%s\n", action, inName, inType, inDomain, (int) inIFI, more );
-	}
-	else
-	{
-		fprintf( stderr, "Bonjour browser error occurred: %d\n", inError );
-	}
-}
diff --git a/Clients/BonjourExample/stdafx.cpp b/Clients/BonjourExample/stdafx.cpp
deleted file mode 100644
index a28f2b5..0000000
--- a/Clients/BonjourExample/stdafx.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2005 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.
- */
-
-// Standard source file to build the pre-compiled header.
-
-#include	"stdafx.h"
diff --git a/Clients/BonjourExample/stdafx.h b/Clients/BonjourExample/stdafx.h
deleted file mode 100644
index d820f4a..0000000
--- a/Clients/BonjourExample/stdafx.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2005 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.
- */
-
-// Standard Windows pre-compiled header file.
-
-#pragma once
-
-#define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
-
-#include    <windows.h>
-#include    <winsock2.h>
-
-#include    <stdlib.h>
-#include    <malloc.h>
-#include    <memory.h>
-#include    <tchar.h>
diff --git a/Clients/ClientCommon.c b/Clients/ClientCommon.c
deleted file mode 100644
index f96319c..0000000
--- a/Clients/ClientCommon.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
- *
- * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.
- * ("Apple") in consideration of your agreement to the following terms, and your
- * use, installation, modification or redistribution of this Apple software
- * constitutes acceptance of these terms.  If you do not agree with these terms,
- * please do not use, install, modify or redistribute this Apple software.
- *
- * In consideration of your agreement to abide by the following terms, and subject
- * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- * copyrights in this original Apple software (the "Apple Software"), to use,
- * reproduce, modify and redistribute the Apple Software, with or without
- * modifications, in source and/or binary forms; provided that if you redistribute
- * the Apple Software in its entirety and without modifications, 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.
- *
- * 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.
- */
-
-#include <ctype.h>
-#include <stdio.h>          // For stdout, stderr
-
-#include "ClientCommon.h"
-
-const char *GetNextLabel(const char *cstr, char label[64])
-{
-    char *ptr = label;
-    while (*cstr && *cstr != '.')               // While we have characters in the label...
-    {
-        char c = *cstr++;
-        if (c == '\\')                          // If escape character, check next character
-        {
-            if (*cstr == '\0') break;           // If this is the end of the string, then break
-            c = *cstr++;
-            if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
-            {
-                int v0 = cstr[-1] - '0';                        // then interpret as three-digit decimal
-                int v1 = cstr[ 0] - '0';
-                int v2 = cstr[ 1] - '0';
-                int val = v0 * 100 + v1 * 10 + v2;
-                // If valid three-digit decimal value, use it
-                // Note that although ascii nuls are possible in DNS labels
-                // we're building a C string here so we have no way to represent that
-                if (val == 0) val = '-';
-                if (val <= 255) { c = (char)val; cstr += 2; }
-            }
-        }
-        *ptr++ = c;
-        if (ptr >= label+64) { label[63] = 0; return(NULL); }   // Illegal label more than 63 bytes
-    }
-    *ptr = 0;                                                   // Null-terminate label text
-    if (ptr == label) return(NULL);                             // Illegal empty label
-    if (*cstr) cstr++;                                          // Skip over the trailing dot (if present)
-    return(cstr);
-}
diff --git a/Clients/ClientCommon.h b/Clients/ClientCommon.h
deleted file mode 100644
index afe5b7a..0000000
--- a/Clients/ClientCommon.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2008 Apple Inc. All rights reserved.
- *
- * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
- * ("Apple") in consideration of your agreement to the following terms, and your
- * use, installation, modification or redistribution of this Apple software
- * constitutes acceptance of these terms.  If you do not agree with these terms,
- * please do not use, install, modify or redistribute this Apple software.
- *
- * In consideration of your agreement to abide by the following terms, and subject
- * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- * copyrights in this original Apple software (the "Apple Software"), to use,
- * reproduce, modify and redistribute the Apple Software, with or without
- * modifications, in source and/or binary forms; provided that if you redistribute
- * the Apple Software in its entirety and without modifications, 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 Computer, 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.
- *
- * 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.
- */
-
-extern const char *GetNextLabel(const char *cstr, char label[64]);
diff --git a/Clients/DNS-SD.VisualStudio/resource.h b/Clients/DNS-SD.VisualStudio/resource.h
deleted file mode 100644
index 593b5f9..0000000
--- a/Clients/DNS-SD.VisualStudio/resource.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by dns-sd.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/ExplorerPlugin/About.cpp b/Clients/ExplorerPlugin/About.cpp
deleted file mode 100644
index 4a63f2c..0000000
--- a/Clients/ExplorerPlugin/About.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// About.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "ExplorerPlugin.h"
-#include "About.h"
-#include "WinVersRes.h"
-#include <DebugServices.h>
-
-
-// CAbout dialog
-
-IMPLEMENT_DYNAMIC(CAbout, CDialog)
-CAbout::CAbout(CWnd* pParent /*=NULL*/)
-	: CDialog(CAbout::IDD, pParent)
-{
-	// Initialize brush with the desired background color
-	m_bkBrush.CreateSolidBrush(RGB(255, 255, 255));
-}
-
-CAbout::~CAbout()
-{
-}
-
-void CAbout::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_COMPONENT, m_componentCtrl);
-	DDX_Control(pDX, IDC_LEGAL, m_legalCtrl);
-}
-
-
-BEGIN_MESSAGE_MAP(CAbout, CDialog)
-ON_WM_CTLCOLOR()
-END_MESSAGE_MAP()
-
-
-// CAbout message handlers
-BOOL
-CAbout::OnInitDialog()
-{
-	BOOL b = CDialog::OnInitDialog();
-
-	CStatic * control = (CStatic*) GetDlgItem( IDC_ABOUT_BACKGROUND );
-	check( control );
-
-	if ( control )
-	{
-		control->SetBitmap( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_ABOUT ) ) );
-	}
-
-	control = ( CStatic* ) GetDlgItem( IDC_COMPONENT_VERSION );
-	check( control );
-
-	if ( control )
-	{
-		control->SetWindowText( TEXT( MASTER_PROD_VERS_STR2 ) );
-	}
-
-	return b;
-}
-
-
-HBRUSH CAbout::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
-{ 
-	switch (nCtlColor)
-	{
-		case CTLCOLOR_STATIC:
-	
-			if ( pWnd->GetDlgCtrlID() == IDC_COMPONENT )
-			{
-				pDC->SetTextColor(RGB(64, 64, 64));
-			}
-			else
-			{
-				pDC->SetTextColor(RGB(0, 0, 0));
-			}
-
-			pDC->SetBkColor(RGB(255, 255, 255));
-			return (HBRUSH)(m_bkBrush.GetSafeHandle());
-
-		case CTLCOLOR_DLG:
-	
-			return (HBRUSH)(m_bkBrush.GetSafeHandle());
-
-		default:
-	
-			return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
-	}
-}
diff --git a/Clients/ExplorerPlugin/About.h b/Clients/ExplorerPlugin/About.h
deleted file mode 100644
index 494d1f1..0000000
--- a/Clients/ExplorerPlugin/About.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include "Resource.h"
-#include "afxwin.h"
-
-// CAbout dialog
-
-class CAbout : public CDialog
-{
-DECLARE_DYNAMIC(CAbout)
-
-public:
-CAbout(CWnd* pParent = NULL);       // standard constructor
-virtual ~CAbout();
-
-// Dialog Data
-enum { IDD = IDD_ABOUT };
-
-protected:
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-virtual HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
-virtual BOOL    OnInitDialog();
-DECLARE_MESSAGE_MAP()
-public:
-CStatic m_componentCtrl;
-CStatic m_legalCtrl;
-CBrush m_bkBrush;
-};
diff --git a/Clients/ExplorerPlugin/ClassFactory.cpp b/Clients/ExplorerPlugin/ClassFactory.cpp
deleted file mode 100644
index e578e23..0000000
--- a/Clients/ExplorerPlugin/ClassFactory.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
-*/
-
-#include	"StdAfx.h"
-
-#include	"DebugServices.h"
-
-#include	"ExplorerBar.h"
-#include	"ExplorerPlugin.h"
-
-#include	"ClassFactory.h"
-
-// MFC Debugging
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	ClassFactory
-//===========================================================================================================================
-
-ClassFactory::ClassFactory( CLSID inCLSID )
-{
-	mCLSIDObject 	= inCLSID;
-	mRefCount		= 1;
-	++gDLLRefCount;
-}
-
-//===========================================================================================================================
-//	~ClassFactory
-//===========================================================================================================================
-
-ClassFactory::~ClassFactory( void )
-{
-	check( gDLLRefCount > 0 );
-	
-	--gDLLRefCount;
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IUnknown methods ==
-#endif
-
-//===========================================================================================================================
-//	QueryInterface
-//===========================================================================================================================
-
-STDMETHODIMP	ClassFactory::QueryInterface( REFIID inID, LPVOID *outResult )
-{
-	HRESULT		err;
-	
-	check( outResult );
-	
-	if( IsEqualIID( inID, IID_IUnknown ) )
-	{
-		*outResult = this;
-	}
-	else if( IsEqualIID( inID, IID_IClassFactory ) )
-	{
-		*outResult = (IClassFactory *) this;
-	}   
-	else
-	{
-		*outResult = NULL;
-		err = E_NOINTERFACE;
-		goto exit;
-	}
-	
-	( *( (LPUNKNOWN *) outResult ) )->AddRef();
-	err = S_OK;
-	
-exit:
-	return( err );
-}                                             
-
-//===========================================================================================================================
-//	AddRef
-//===========================================================================================================================
-
-STDMETHODIMP_( DWORD )	ClassFactory::AddRef( void )
-{
-	return( ++mRefCount );
-}
-
-//===========================================================================================================================
-//	Release
-//===========================================================================================================================
-
-STDMETHODIMP_( DWORD )	ClassFactory::Release( void )
-{
-	DWORD		count;
-	
-	count = --mRefCount;
-	if( count == 0 )
-	{
-		delete this;
-	}
-	return( count );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IClassFactory methods ==
-#endif
-
-//===========================================================================================================================
-//	CreateInstance
-//===========================================================================================================================
-
-STDMETHODIMP	ClassFactory::CreateInstance( LPUNKNOWN inUnknown, REFIID inID, LPVOID *outObject )
-{
-	HRESULT		err;
-	LPVOID		obj;
-	
-	check( outObject );
-	
-	obj 		= NULL;
-	*outObject 	= NULL;
-	require_action( !inUnknown, exit, err = CLASS_E_NOAGGREGATION );
-	
-	// Create the object based on the CLSID.
-	
-	if( IsEqualCLSID( mCLSIDObject, CLSID_ExplorerBar ) )
-	{
-		try
-		{
-			obj = new ExplorerBar();
-		}
-		catch( ... )
-		{
-			// Don't let exception escape.
-		}
-		require_action( obj, exit, err = E_OUTOFMEMORY );
-	}
-	else
-	{
-		err = E_FAIL;
-		goto exit;
-	}
-	
-	// Query for the specified interface. Release the factory since QueryInterface retains it.
-		
-	err = ( (LPUNKNOWN ) obj )->QueryInterface( inID, outObject );
-	( (LPUNKNOWN ) obj )->Release();
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	LockServer
-//===========================================================================================================================
-
-STDMETHODIMP	ClassFactory::LockServer( BOOL inLock )
-{
-	DEBUG_UNUSED( inLock );
-	
-	return( E_NOTIMPL );
-}
diff --git a/Clients/ExplorerPlugin/ClassFactory.h b/Clients/ExplorerPlugin/ClassFactory.h
deleted file mode 100644
index cbf5630..0000000
--- a/Clients/ExplorerPlugin/ClassFactory.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __CLASS_FACTORY__
-#define __CLASS_FACTORY__
-
-#include    "StdAfx.h"
-
-//===========================================================================================================================
-//	ClassFactory
-//===========================================================================================================================
-
-class ClassFactory : public IClassFactory
-{
-protected:
-
-DWORD mRefCount;
-CLSID mCLSIDObject;
-
-public:
-
-ClassFactory( CLSID inCLSID );
-~ClassFactory( void );
-
-// IUnknown methods
-
-STDMETHODIMP            QueryInterface( REFIID inID, LPVOID *outResult );
-STDMETHODIMP_( DWORD )  AddRef( void );
-STDMETHODIMP_( DWORD )  Release( void );
-
-// IClassFactory methods
-
-STDMETHODIMP    CreateInstance( LPUNKNOWN inUnknown, REFIID inID, LPVOID *outObject );
-STDMETHODIMP    LockServer( BOOL inLock );
-};
-
-#endif  // __CLASS_FACTORY__
diff --git a/Clients/ExplorerPlugin/ExplorerBar.cpp b/Clients/ExplorerPlugin/ExplorerBar.cpp
deleted file mode 100644
index 644515f..0000000
--- a/Clients/ExplorerPlugin/ExplorerBar.cpp
+++ /dev/null
@@ -1,659 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	"StdAfx.h"
-
-#include	"comutil.h"
-#include	"ShObjIdl.h"
-
-#include	"DebugServices.h"
-
-#include	"Resource.h"
-
-#include	"ExplorerBar.h"
-
-#include	"About.h"
-// MFC Debugging
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-#define LENGTHOF(a) (sizeof(a) == sizeof(&*a)) ? 0 : (sizeof(a) / sizeof(*a))
-#define MIN_SIZE_X		10
-#define MIN_SIZE_Y		10
-
-//===========================================================================================================================
-//	ExplorerBar
-//===========================================================================================================================
-
-ExplorerBar::ExplorerBar( void )
-{
-	++gDLLRefCount;
-	
-	mRefCount		= 1;
-	mSite 			= NULL;
-	mWebBrowser		= NULL;
-	mParentWindow	= NULL;
-	mFocus			= FALSE;
-	mViewMode		= 0;
-	mBandID			= 0;
-}
-
-//===========================================================================================================================
-//	~ExplorerBar
-//===========================================================================================================================
-
-ExplorerBar::~ExplorerBar( void )
-{
-	if( mWebBrowser )
-	{
-		mWebBrowser->Release();
-		mWebBrowser = NULL;
-	}
-	if( mSite )
-	{
-		mSite->Release();
-		mSite = NULL;
-	}
-	
-	--gDLLRefCount;
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IUnknown implementation ==
-#endif
-
-//===========================================================================================================================
-//	QueryInterface
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::QueryInterface( REFIID inID, LPVOID *outResult )
-{
-	HRESULT		err;
-	
-	if( IsEqualIID( inID, IID_IUnknown ) )				// IUnknown
-	{
-		*outResult = this;
-	}
-	else if( IsEqualIID( inID, IID_IOleWindow ) )		// IOleWindow
-	{
-		*outResult = (IOleWindow *) this;
-	}
-	else if( IsEqualIID( inID, IID_IDockingWindow ) )	// IDockingWindow
-	{
-		*outResult = (IDockingWindow *) this;
-	}
-	else if( IsEqualIID( inID, IID_IDeskBand ) )		// IDeskBand
-	{
-		*outResult = (IDeskBand *) this;
-	}
-	else if( IsEqualIID( inID, IID_IInputObject ) )		// IInputObject
-	{
-		*outResult = (IInputObject *) this;
-	}
-	else if( IsEqualIID( inID, IID_IObjectWithSite ) )	// IObjectWithSite
-	{
-		*outResult = (IObjectWithSite *) this;
-	}
-	else if( IsEqualIID( inID, IID_IPersistStream ) )	// IPersistStream
-	{
-		*outResult = (IPersistStream *) this;
-	}
-	else if( IsEqualIID( inID, IID_IContextMenu ) )     // IContextMenu
-	{
-		*outResult = (IContextMenu *) this;
-	}
-	else
-	{
-		*outResult = NULL;
-		err = E_NOINTERFACE;
-		goto exit;
-	}
-	
-	( *( (LPUNKNOWN *) outResult ) )->AddRef();
-	err = S_OK;
-
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	AddRef
-//===========================================================================================================================
-
-STDMETHODIMP_( DWORD )	ExplorerBar::AddRef( void )
-{
-	return( ++mRefCount );
-}
-
-//===========================================================================================================================
-//	Release
-//===========================================================================================================================
-
-STDMETHODIMP_( DWORD )	ExplorerBar::Release( void )
-{
-	DWORD		count;
-
-	count = --mRefCount;
-	if( count == 0 )
-	{
-		delete this;
-	}
-	return( count );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IOleWindow implementation ==
-#endif
-
-//===========================================================================================================================
-//	GetWindow
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::GetWindow( HWND *outWindow )
-{
-	*outWindow = mWindow.GetSafeHwnd();
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	ContextSensitiveHelp
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::ContextSensitiveHelp( BOOL inEnterMode )
-{
-	DEBUG_UNUSED( inEnterMode );
-	
-	return( E_NOTIMPL );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IDockingWindow implementation ==
-#endif
-
-//===========================================================================================================================
-//	ShowDW
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::ShowDW( BOOL inShow )
-{
-	if( mWindow.GetSafeHwnd() )
-	{
-		mWindow.ShowWindow( inShow ? SW_SHOW : SW_HIDE );
-	}
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	CloseDW
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::CloseDW( DWORD inReserved )
-{
-	DEBUG_UNUSED( inReserved );
-
-	ShowDW( FALSE );
-	if( mWindow.GetSafeHwnd() )
-	{
-		mWindow.SendMessage( WM_CLOSE );
-	}
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	ResizeBorderDW
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::ResizeBorderDW( LPCRECT inBorder, IUnknown *inPunkSite, BOOL inReserved )
-{
-	DEBUG_UNUSED( inBorder );
-	DEBUG_UNUSED( inPunkSite );
-	DEBUG_UNUSED( inReserved );
-	
-	return( E_NOTIMPL );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IDeskBand implementation ==
-#endif
-
-//===========================================================================================================================
-//	GetBandInfo
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::GetBandInfo( DWORD inBandID, DWORD inViewMode, DESKBANDINFO *outInfo )
-{
-	HRESULT		err;
-	
-	require_action( outInfo, exit, err = E_INVALIDARG );
-	
-	mBandID   = inBandID;
-	mViewMode = inViewMode;
-	
-	if( outInfo->dwMask & DBIM_MINSIZE )
-	{
-		outInfo->ptMinSize.x = 100;
-		outInfo->ptMinSize.y = 100;
-	}
-	if( outInfo->dwMask & DBIM_MAXSIZE )
-	{
-		// Unlimited max size.
-		
-		outInfo->ptMaxSize.x = -1;
-		outInfo->ptMaxSize.y = -1;
-	}
-	if( outInfo->dwMask & DBIM_INTEGRAL )
-	{
-		outInfo->ptIntegral.x = 1;
-		outInfo->ptIntegral.y = 1;
-	}
-	if( outInfo->dwMask & DBIM_ACTUAL )
-	{
-		outInfo->ptActual.x = 0;
-		outInfo->ptActual.y = 0;
-	}
-	if( outInfo->dwMask & DBIM_TITLE )
-	{
-		CString		s;
-		BOOL		ok;
-		
-		ok = s.LoadString( IDS_NAME );
-		require_action( ok, exit, err = kNoResourcesErr );
-		
-		#ifdef UNICODE
-			lstrcpyn( outInfo->wszTitle, s, sizeof_array( outInfo->wszTitle ) );
-		#else
-			DWORD		nChars;
-			
-			nChars = MultiByteToWideChar( CP_ACP, 0, s, -1, outInfo->wszTitle, sizeof_array( outInfo->wszTitle ) );
-			err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
-			require_noerr( err, exit );
-		#endif
-	}
-	if( outInfo->dwMask & DBIM_MODEFLAGS )
-	{
-		outInfo->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
-	}
-	
-	// Force the default background color.
-	
-	outInfo->dwMask &= ~DBIM_BKCOLOR;
-	err = S_OK;
-	
-exit:
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IInputObject implementation ==
-#endif
-
-//===========================================================================================================================
-//	UIActivateIO
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::UIActivateIO( BOOL inActivate, LPMSG inMsg )
-{
-	DEBUG_UNUSED( inMsg );
-	
-	if( inActivate )
-	{
-		mWindow.SetFocus();
-	}
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	HasFocusIO
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::HasFocusIO( void )
-{
-	if( mWindow.GetFocus()->GetSafeHwnd() == mWindow.GetSafeHwnd() )
-	{
-		return( S_OK );
-	}
-	return( S_FALSE );
-}
-
-//===========================================================================================================================
-//	TranslateAcceleratorIO
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::TranslateAcceleratorIO( LPMSG inMsg )
-{
-	DEBUG_UNUSED( inMsg );
-		
-	return( S_FALSE );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IObjectWithSite implementation ==
-#endif
-
-//===========================================================================================================================
-//	SetSite
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::SetSite( IUnknown *inPunkSite )
-{
-	AFX_MANAGE_STATE( AfxGetStaticModuleState() );
-	
-	HRESULT		err;
-	
-	// Release the old interfaces.
-	
-	if( mWebBrowser )
-	{
-		mWebBrowser->Release();
-		mWebBrowser = NULL;
-	}
-	if( mSite )
-	{
-		mSite->Release();
-		mSite = NULL;
-	}
-	
-	// A non-NULL site means we're setting the site. Otherwise, the site is being released (done above).
-	
-	if( !inPunkSite )
-	{
-		err = S_OK;
-		goto exit;
-	}
-	
-	// Get the parent window.
-	
-	IOleWindow *		oleWindow;
-		
-	mParentWindow = NULL;
-	err = inPunkSite->QueryInterface( IID_IOleWindow, (LPVOID *) &oleWindow );
-	require( SUCCEEDED( err ), exit );
-	
-	err = oleWindow->GetWindow( &mParentWindow );
-	oleWindow->Release();
-	require_noerr( err, exit );
-	require_action( mParentWindow, exit, err = E_FAIL );
-	
-	// Get the IInputObject interface.
-	
-	err = inPunkSite->QueryInterface( IID_IInputObjectSite, (LPVOID *) &mSite );
-	require( SUCCEEDED( err ), exit );
-	check( mSite );
-	
-	// Get the IWebBrowser2 interface.
-	
-	IOleCommandTarget *		oleCommandTarget;
-	
-	err = inPunkSite->QueryInterface( IID_IOleCommandTarget, (LPVOID *) &oleCommandTarget );
-	require( SUCCEEDED( err ), exit );
-	
-	IServiceProvider *		serviceProvider;
-	
-	err = oleCommandTarget->QueryInterface( IID_IServiceProvider, (LPVOID *) &serviceProvider );
-	oleCommandTarget->Release();
-	require( SUCCEEDED( err ), exit );
-	
-	err = serviceProvider->QueryService( SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *) &mWebBrowser );
-	serviceProvider->Release();
-	require( SUCCEEDED( err ), exit );
-	
-	// Create the main window.
-	
-	err = SetupWindow();
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	GetSite
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::GetSite( REFIID inID, LPVOID *outResult )
-{
-	HRESULT		err;
-	
-	*outResult = NULL;
-	require_action( mSite, exit, err = E_FAIL );
-	
-	err = mSite->QueryInterface( inID, outResult );
-	
-exit:
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == IPersistStream implementation ==
-#endif
-
-//
-// IPersistStream implementation
-// 
-// This is only supported to allow the desk band to be dropped on the desktop and to prevent multiple instances of 
-// the desk band from showing up in the context menu. This desk band doesn't actually persist any data.
-//
-
-//===========================================================================================================================
-//	GetClassID
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::GetClassID( LPCLSID outClassID )
-{
-	*outClassID = CLSID_ExplorerBar;
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	IsDirty
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::IsDirty( void )
-{
-	return( S_FALSE );
-}
-
-//===========================================================================================================================
-//	Load
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::Load( LPSTREAM inStream )
-{
-	DEBUG_UNUSED( inStream );
-	
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	Save
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::Save( LPSTREAM inStream, BOOL inClearDirty )
-{
-	DEBUG_UNUSED( inStream );
-	DEBUG_UNUSED( inClearDirty );
-	
-	return( S_OK );
-}
-
-//===========================================================================================================================
-//	GetSizeMax
-//===========================================================================================================================
-
-STDMETHODIMP	ExplorerBar::GetSizeMax( ULARGE_INTEGER *outSizeMax )
-{
-	DEBUG_UNUSED( outSizeMax );
-	
-	return( E_NOTIMPL );
-}
-
-
-//===========================================================================================================================
-//	QueryContextMenu
-//===========================================================================================================================
-
-STDMETHODIMP  ExplorerBar::QueryContextMenu(HMENU hShellContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
-{
-	DEBUG_UNUSED( idCmdLast );
-	DEBUG_UNUSED( uFlags );
-
-	CMenu menubar;
-
-	menubar.LoadMenu(IDR_CONTEXT_MENU);
-	CMenu * menu = menubar.GetSubMenu(0);
-
-	CMenu shellmenu;
-
-	shellmenu.Attach(hShellContextMenu);
-
-	UINT iShellItem = iContextMenuFirstItem;	//! remove plus one
-	UINT idShellCmd = idCmdFirst;
-
-	int n = menu->GetMenuItemCount();
-
-	for (int i=0; i<n; ++i)
-	{
-		MENUITEMINFO	mii;
-		TCHAR				sz[128] = {0};
-		
-		ZeroMemory(&mii, sizeof(mii));
-		mii.fMask		= MIIM_TYPE | MIIM_ID;
-		mii.fType		= MFT_STRING;
-		mii.cbSize		= sizeof(mii);
-		mii.cch			= LENGTHOF(sz);
-		mii.dwTypeData	= sz;
-		
-		menu->GetMenuItemInfo(i, &mii, TRUE);
-
-		mii.wID = idShellCmd++;
-
-		shellmenu.InsertMenuItem(iShellItem++, &mii, TRUE);
-	}
-
-	shellmenu.Detach();
-
-	return n;
-}
-
-
-//===========================================================================================================================
-//	GetCommandString
-//===========================================================================================================================
-
-// Not called for explorer bars
-STDMETHODIMP ExplorerBar::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
-{
-	DEBUG_UNUSED( idCmd );
-	DEBUG_UNUSED( uType );
-	DEBUG_UNUSED( pwReserved );
-	DEBUG_UNUSED( pszName );
-	DEBUG_UNUSED( cchMax );
-
-	return E_NOTIMPL;
-}
-
-//===========================================================================================================================
-//	InvokeCommand
-//===========================================================================================================================
-
-//	The shell sends either strings or indexes
-//	IE never sends strings
-//	The indexes are into an array of my commands
-//	So the verb for the first command I added to the menu is always 0x0000
-//	Here - because I don't have any submenus - 
-//		I can treat the 'verb' as an menu item position	
-STDMETHODIMP ExplorerBar::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
-{
-	// IE doesn't send string commands
-	if (HIWORD(lpici->lpVerb) != 0) return 0;
-
-	CAbout dlg;
-
-	dlg.DoModal();
-
-	return S_OK;
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Other ==
-#endif
-
-//===========================================================================================================================
-//	SetupWindow
-//===========================================================================================================================
-
-OSStatus	ExplorerBar::SetupWindow( void )
-{
-	OSStatus		err;
-	CWnd *			window;
-	CRect			rect;
-	CString			s;
-	BOOL			ok;
-	
-	window = CWnd::FromHandle( mParentWindow );
-	check( window );
-	window->GetClientRect( rect );
-	
-	ok = s.LoadString( IDS_NAME );
-	require_action( ok, exit, err = kNoResourcesErr );
-	
-	ok = mWindow.Create( NULL, s, WS_CHILD | WS_VISIBLE, rect, window, 100 ) != 0;
-	require_action( ok, exit, err = kNoResourcesErr );
-	
-	mWindow.SetOwner( this );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	GoToURL
-//===========================================================================================================================
-
-OSStatus	ExplorerBar::GoToURL( const CString &inURL )
-{
-	OSStatus		err;
-	BSTR			s;
-	VARIANT			empty;
-	
-	s = inURL.AllocSysString();
-	require_action( s, exit, err = kNoMemoryErr );
-	
-	VariantInit( &empty );
-	err = mWebBrowser->Navigate( s, &empty, &empty, &empty, &empty );
-	SysFreeString( s );
-	require_noerr( err, exit );
-
-exit:
-	return( err );
-}
diff --git a/Clients/ExplorerPlugin/ExplorerBar.h b/Clients/ExplorerPlugin/ExplorerBar.h
deleted file mode 100644
index 01d1bee..0000000
--- a/Clients/ExplorerPlugin/ExplorerBar.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __EXPLORER_BAR__
-#define __EXPLORER_BAR__
-
-#include    "StdAfx.h"
-
-#include    "ExplorerBarWindow.h"
-#include    "ExplorerPlugin.h"
-
-//===========================================================================================================================
-//	ExplorerBar
-//===========================================================================================================================
-
-class ExplorerBar : public IDeskBand,
-    public IInputObject,
-    public IObjectWithSite,
-    public IPersistStream,
-    public IContextMenu
-{
-protected:
-
-DWORD mRefCount;
-IInputObjectSite *      mSite;
-IWebBrowser2 *          mWebBrowser;
-HWND mParentWindow;
-BOOL mFocus;
-DWORD mViewMode;
-DWORD mBandID;
-ExplorerBarWindow mWindow;
-
-public:
-
-ExplorerBar( void );
-~ExplorerBar( void );
-
-// IUnknown methods
-
-STDMETHODIMP            QueryInterface( REFIID inID, LPVOID *outResult );
-STDMETHODIMP_( DWORD )  AddRef( void );
-STDMETHODIMP_( DWORD )  Release( void );
-
-// IOleWindow methods
-
-STDMETHOD( GetWindow ) ( HWND *outWindow );
-STDMETHOD( ContextSensitiveHelp ) ( BOOL inEnterMode );
-
-// IDockingWindow methods
-
-STDMETHOD( ShowDW ) ( BOOL inShow );
-STDMETHOD( CloseDW ) ( DWORD inReserved );
-STDMETHOD( ResizeBorderDW ) ( LPCRECT inBorder, IUnknown *inPunkSite, BOOL inReserved );
-
-// IDeskBand methods
-
-STDMETHOD( GetBandInfo ) ( DWORD inBandID, DWORD inViewMode, DESKBANDINFO *outInfo );
-
-// IInputObject methods
-
-STDMETHOD( UIActivateIO ) ( BOOL inActivate, LPMSG inMsg );
-STDMETHOD( HasFocusIO ) ( void );
-STDMETHOD( TranslateAcceleratorIO ) ( LPMSG inMsg );
-
-// IObjectWithSite methods
-
-STDMETHOD( SetSite ) ( IUnknown *inPunkSite );
-STDMETHOD( GetSite ) ( REFIID inID, LPVOID *outResult );
-
-// IPersistStream methods
-
-STDMETHOD( GetClassID ) ( LPCLSID outClassID );
-STDMETHOD( IsDirty ) ( void );
-STDMETHOD( Load ) ( LPSTREAM inStream );
-STDMETHOD( Save ) ( LPSTREAM inStream, BOOL inClearDirty );
-STDMETHOD( GetSizeMax ) ( ULARGE_INTEGER *outSizeMax );
-
-// IContextMenu methods
-
-STDMETHOD( QueryContextMenu ) ( HMENU hContextMenu, UINT iContextMenuFirstItem, UINT idCmdFirst, UINT idCmdLast, UINT uFlags );
-STDMETHOD( GetCommandString ) ( UINT_PTR idCmd, UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax );
-STDMETHOD( InvokeCommand ) ( LPCMINVOKECOMMANDINFO lpici );
-
-// Other
-
-OSStatus    SetupWindow( void );
-OSStatus    GoToURL( const CString &inURL );
-};
-
-#endif  // __EXPLORER_BAR__
diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp
deleted file mode 100644
index 5e0692a..0000000
--- a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp
+++ /dev/null
@@ -1,794 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	"StdAfx.h"
-
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-#include	"WinServices.h"
-#include	"dns_sd.h"
-
-#include	"ExplorerBar.h"
-#include	"LoginDialog.h"
-#include	"Resource.h"
-
-#include	"ExplorerBarWindow.h"
-#include	"ExplorerPlugin.h"
-
-// MFC Debugging
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-// Control IDs
-
-#define	IDC_EXPLORER_TREE				1234
-
-// Private Messages
-
-#define WM_PRIVATE_SERVICE_EVENT				( WM_USER + 0x100 )
-
-// TXT records
-
-#define	kTXTRecordKeyPath				"path"
-
-// IE Icon resource
-
-#define kIEIconResource					32529
-
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-DEBUG_LOCAL int			FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex );
-
-#if 0
-#pragma mark == Message Map ==
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP( ExplorerBarWindow, CWnd )
-	ON_WM_CREATE()
-	ON_WM_DESTROY()
-	ON_WM_SIZE()
-	ON_NOTIFY( NM_DBLCLK, IDC_EXPLORER_TREE, OnDoubleClick )
-	ON_MESSAGE( WM_PRIVATE_SERVICE_EVENT, OnServiceEvent )
-END_MESSAGE_MAP()
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	ExplorerBarWindow
-//===========================================================================================================================
-
-ExplorerBarWindow::ExplorerBarWindow( void )
-{
-	mOwner				= NULL;
-	mResolveServiceRef	= NULL;
-}
-
-//===========================================================================================================================
-//	~ExplorerBarWindow
-//===========================================================================================================================
-
-ExplorerBarWindow::~ExplorerBarWindow( void )
-{
-	//
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	OnCreate
-//===========================================================================================================================
-
-int	ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct )
-{
-	AFX_MANAGE_STATE( AfxGetStaticModuleState() );
-	
-	HINSTANCE		module = NULL;
-	OSStatus		err;
-	CRect			rect;
-	CBitmap			bitmap;
-	CString			s;
-	
-	err = CWnd::OnCreate( inCreateStruct );
-	require_noerr( err, exit );
-	
-	GetClientRect( rect );
-	mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_NOHSCROLL , rect, this, 
-		IDC_EXPLORER_TREE );
-	
-	ServiceHandlerEntry *		e;
-	
-	s.LoadString( IDS_ABOUT );
-	m_about = mTree.InsertItem( s, 0, 0 );
-
-	// Web Site Handler
-	
-	e = new ServiceHandlerEntry;
-	check( e );
-	e->type				= "_http._tcp";
-	e->urlScheme		= "http://";
-	e->ref				= NULL;
-	e->obj				= this;
-	e->needsLogin		= false;
-	mServiceHandlers.Add( e );
-
-	err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
-	require_noerr( err, exit );
-
-	err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
-	require_noerr( err, exit );
-
-	m_serviceRefs.push_back(e->ref);
-
-#if defined( _BROWSE_FOR_HTTPS_ )
-	e = new ServiceHandlerEntry;
-	check( e );
-	e->type				= "_https._tcp";
-	e->urlScheme		= "https://";
-	e->ref				= NULL;
-	e->obj				= this;
-	e->needsLogin		= false;
-	mServiceHandlers.Add( e );
-
-	err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );
-	require_noerr( err, exit );
-
-	err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
-	require_noerr( err, exit );
-
-	m_serviceRefs.push_back(e->ref);
-#endif
-	
-	m_imageList.Create( 16, 16, ILC_MASK | ILC_COLOR16, 2, 0);
-
-	bitmap.Attach( ::LoadBitmap( GetNonLocalizedResources(), MAKEINTRESOURCE( IDB_LOGO ) ) );
-	m_imageList.Add( &bitmap, (CBitmap*) NULL );
-	bitmap.Detach();
-
-	mTree.SetImageList(&m_imageList, TVSIL_NORMAL);
-	
-exit:
-
-	if ( module )
-	{
-		FreeLibrary( module );
-		module = NULL;
-	}
-
-	// Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it).
-	if ( err )
-	{
-		if ( err == kDNSServiceErr_Firewall )
-		{
-			s.LoadString( IDS_FIREWALL );
-		}
-		else
-		{
-			s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
-		}
-		
-		mTree.DeleteAllItems();
-		mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST );
-		
-		err = kNoErr;
-	}
-
-	return( err );
-}
-
-//===========================================================================================================================
-//	OnDestroy
-//===========================================================================================================================
-
-void	ExplorerBarWindow::OnDestroy( void ) 
-{
-	// Stop any resolves that may still be pending (shouldn't be any).
-	
-	StopResolve();
-	
-	// Clean up the extant browses
-	while (m_serviceRefs.size() > 0)
-	{
-		//
-		// take the head of the list
-		//
-		DNSServiceRef ref = m_serviceRefs.front();
-
-		//
-		// Stop will remove it from the list
-		//
-		Stop( ref );
-	}
-
-	// Clean up the service handlers.
-	
-	int		i;
-	int		n;
-	
-	n = (int) mServiceHandlers.GetSize();
-	for( i = 0; i < n; ++i )
-	{
-		delete mServiceHandlers[ i ];
-	}
-	
-	CWnd::OnDestroy();
-}
-
-//===========================================================================================================================
-//	OnSize
-//===========================================================================================================================
-
-void	ExplorerBarWindow::OnSize( UINT inType, int inX, int inY ) 
-{
-	CWnd::OnSize( inType, inX, inY );
-	mTree.MoveWindow( 0, 0, inX, inY );
-}
-
-//===========================================================================================================================
-//	OnDoubleClick
-//===========================================================================================================================
-
-void	ExplorerBarWindow::OnDoubleClick( NMHDR *inNMHDR, LRESULT *outResult )
-{
-	HTREEITEM			item;
-	ServiceInfo *		service;
-	OSStatus			err;
-	
-	DEBUG_UNUSED( inNMHDR );
-	
-	item = mTree.GetSelectedItem();
-	require( item, exit );
-	
-	// Tell Internet Explorer to go to the URL if it's about item
-	
-	if ( item == m_about )
-	{
-		CString url;
-
-		check( mOwner );
-
-		url.LoadString( IDS_ABOUT_URL );
-		mOwner->GoToURL( url );
-	}
-	else
-	{
-		service = reinterpret_cast < ServiceInfo * > ( mTree.GetItemData( item ) );
-		require_quiet( service, exit );
-		
-		err = StartResolve( service );
-		require_noerr( err, exit );
-	}
-
-exit:
-	*outResult = 0;
-}
-
-
-//===========================================================================================================================
-//	OnServiceEvent
-//===========================================================================================================================
-
-LRESULT
-ExplorerBarWindow::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
-{
-	if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
-    {
-		dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
-    }
-    else
-    {
-		SOCKET sock = (SOCKET) inWParam;
-
-		// iterate thru list
-		ServiceRefList::iterator it;
-
-		for (it = m_serviceRefs.begin(); it != m_serviceRefs.end(); it++)
-		{
-			DNSServiceRef ref = *it;
-
-			check(ref != NULL);
-
-			if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
-			{
-				DNSServiceErrorType err;
-
-				err = DNSServiceProcessResult(ref);
-
-				if (err != 0)
-				{
-					CString s;
-
-					s.LoadString( IDS_MDNSRESPONDER_NOT_AVAILABLE );
-					mTree.DeleteAllItems();
-					mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST );
-
-					Stop(ref);
-				}
-
-				break;
-			}
-		}
-	}
-
-	return ( 0 );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	BrowseCallBack
-//===========================================================================================================================
-
-void DNSSD_API
-	ExplorerBarWindow::BrowseCallBack(
-		DNSServiceRef 			inRef,
-		DNSServiceFlags 		inFlags,
-		uint32_t 				inInterfaceIndex,
-		DNSServiceErrorType 	inErrorCode,
-		const char *			inName,	
-		const char *			inType,	
-		const char *			inDomain,	
-		void *					inContext )
-{
-	ServiceHandlerEntry *		obj;
-	ServiceInfo *				service;
-	OSStatus					err;
-	
-	DEBUG_UNUSED( inRef );
-	
-	obj		=	NULL;
-	service = NULL;
-	
-	require_noerr( inErrorCode, exit );
-	obj = reinterpret_cast < ServiceHandlerEntry * > ( inContext );
-	check( obj );
-	check( obj->obj );
-	
-	//
-	// set the UI to hold off on updates
-	//
-	obj->obj->mTree.SetRedraw(FALSE);
-
-	try
-	{
-		service = new ServiceInfo;
-		require_action( service, exit, err = kNoMemoryErr );
-		
-		err = UTF8StringToStringObject( inName, service->displayName );
-		check_noerr( err );
-
-		service->name = _strdup( inName );
-		require_action( service->name, exit, err = kNoMemoryErr );
-		
-		service->type = _strdup( inType );
-		require_action( service->type, exit, err = kNoMemoryErr );
-		
-		service->domain = _strdup( inDomain );
-		require_action( service->domain, exit, err = kNoMemoryErr );
-		
-		service->ifi 		= inInterfaceIndex;
-		service->handler	= obj;
-
-		service->refs		= 1;
-		
-		if (inFlags & kDNSServiceFlagsAdd) obj->obj->OnServiceAdd   (service);
-		else                               obj->obj->OnServiceRemove(service);
-	
-		service = NULL;
-	}
-	catch( ... )
-	{
-		dlog( kDebugLevelError, "BrowseCallBack: exception thrown\n" );
-	}
-	
-exit:
-	//
-	// If no more coming, then update UI
-	//
-	if (obj && obj->obj && ((inFlags & kDNSServiceFlagsMoreComing) == 0))
-	{
-		obj->obj->mTree.SetRedraw(TRUE);
-		obj->obj->mTree.Invalidate();
-	}
-
-	if( service )
-	{
-		delete service;
-	}
-}
-
-//===========================================================================================================================
-//	OnServiceAdd
-//===========================================================================================================================
-
-LONG	ExplorerBarWindow::OnServiceAdd( ServiceInfo * service )
-{
-	ServiceHandlerEntry *		handler;
-	int							cmp;
-	int							index;
-	
-	
-	check( service );
-	handler = service->handler; 
-	check( handler );
-	
-	cmp = FindServiceArrayIndex( handler->array, *service, index );
-	if( cmp == 0 )
-	{
-		// Found a match so update the item. The index is index + 1 so subtract 1.
-		
-		index -= 1;
-		check( index < handler->array.GetSize() );
-
-		handler->array[ index ]->refs++;
-
-		delete service;
-	}
-	else
-	{
-		HTREEITEM		afterItem;
-		
-		// Insert the new item in sorted order.
-		
-		afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : m_about;
-		handler->array.InsertAt( index, service );
-		service->item = mTree.InsertItem( service->displayName, 0, 0, NULL, afterItem );
-		mTree.SetItemData( service->item, (DWORD_PTR) service );
-	}
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnServiceRemove
-//===========================================================================================================================
-
-LONG	ExplorerBarWindow::OnServiceRemove( ServiceInfo * service )
-{
-	ServiceHandlerEntry *		handler;
-	int							cmp;
-	int							index;
-	
-	
-	check( service );
-	handler = service->handler; 
-	check( handler );
-	
-	// Search to see if we know about this service instance. If so, remove it from the list.
-	
-	cmp = FindServiceArrayIndex( handler->array, *service, index );
-	check( cmp == 0 );
-
-	if( cmp == 0 )
-	{
-		// Possibly found a match remove the item. The index
-		// is index + 1 so subtract 1.
-		index -= 1;
-		check( index < handler->array.GetSize() );
-
-		if ( --handler->array[ index ]->refs == 0 )
-		{
-			mTree.DeleteItem( handler->array[ index ]->item );
-			delete handler->array[ index ];
-			handler->array.RemoveAt( index );
-		}
-	}
-
-	delete service;
-	return( 0 );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	StartResolve
-//===========================================================================================================================
-
-OSStatus	ExplorerBarWindow::StartResolve( ServiceInfo *inService )
-{
-	OSStatus		err;
-	
-	check( inService );
-	
-	// Stop any current resolve that may be in progress.
-	
-	StopResolve();
-	
-	// Resolve the service.
-	err = DNSServiceResolve( &mResolveServiceRef, 0, 0, 
-		inService->name, inService->type, inService->domain, (DNSServiceResolveReply) ResolveCallBack, inService->handler );
-	require_noerr( err, exit );
-
-	err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(mResolveServiceRef), m_hWnd, WM_PRIVATE_SERVICE_EVENT, FD_READ|FD_CLOSE);
-	require_noerr( err, exit );
-	
-	m_serviceRefs.push_back(mResolveServiceRef);
-
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	StopResolve
-//===========================================================================================================================
-
-void	ExplorerBarWindow::StopResolve( void )
-{
-	if( mResolveServiceRef )
-	{
-		Stop( mResolveServiceRef );
-		mResolveServiceRef = NULL;
-	}
-}
-
-//===========================================================================================================================
-//	ResolveCallBack
-//===========================================================================================================================
-
-void DNSSD_API
-	ExplorerBarWindow::ResolveCallBack(
-		DNSServiceRef			inRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inErrorCode,
-		const char *			inFullName,	
-		const char *			inHostName, 
-		uint16_t 				inPort,
-		uint16_t 				inTXTSize,
-		const char *			inTXT,
-		void *					inContext )
-{
-	ExplorerBarWindow *			obj;
-	ServiceHandlerEntry *		handler;
-	OSStatus					err;
-	
-	DEBUG_UNUSED( inRef );
-	DEBUG_UNUSED( inFlags );
-	DEBUG_UNUSED( inErrorCode );
-	DEBUG_UNUSED( inFullName );
-	
-	require_noerr( inErrorCode, exit );
-	handler = (ServiceHandlerEntry *) inContext;
-	check( handler );
-	obj = handler->obj;
-	check( obj );
-	
-	try
-	{
-		ResolveInfo *		resolve;
-		int					idx;
-		
-		dlog( kDebugLevelNotice, "resolved %s on ifi %d to %s\n", inFullName, inInterfaceIndex, inHostName );
-		
-		// Stop resolving after the first good result.
-		
-		obj->StopResolve();
-		
-		// Post a message to the main thread so it can handle it since MFC is not thread safe.
-		
-		resolve = new ResolveInfo;
-		require_action( resolve, exit, err = kNoMemoryErr );
-		
-		UTF8StringToStringObject( inHostName, resolve->host );
-
-		// rdar://problem/3841564
-		// 
-		// strip trailing dot from hostname because some flavors of Windows
-		// have trouble parsing it.
-
-		idx = resolve->host.ReverseFind('.');
-
-		if ((idx > 1) && ((resolve->host.GetLength() - 1) == idx))
-		{
-			resolve->host.Delete(idx, 1);
-		}
-
-		resolve->port		= ntohs( inPort );
-		resolve->ifi		= inInterfaceIndex;
-		resolve->handler	= handler;
-		
-		err = resolve->txt.SetData( inTXT, inTXTSize );
-		check_noerr( err );
-		
-		obj->OnResolve(resolve);
-	}
-	catch( ... )
-	{
-		dlog( kDebugLevelError, "ResolveCallBack: exception thrown\n" );
-	}
-
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	OnResolve
-//===========================================================================================================================
-
-LONG	ExplorerBarWindow::OnResolve( ResolveInfo * resolve )
-{
-	CString				url;
-	uint8_t *			path;
-	uint8_t				pathSize;
-	char *				pathPrefix;
-	CString				username;
-	CString				password;
-	
-	
-	check( resolve );
-		
-	// Get login info if needed.
-	
-	if( resolve->handler->needsLogin )
-	{
-		LoginDialog		dialog;
-		
-		if( !dialog.GetLogin( username, password ) )
-		{
-			goto exit;
-		}
-	}
-	
-	// If the HTTP TXT record is a "path=" entry, use it as the resource path. Otherwise, use "/".
-	
-	pathPrefix = "";
-	if( strcmp( resolve->handler->type, "_http._tcp" ) == 0 )
-	{
-		uint8_t	*	txtData;
-		uint16_t	txtLen;	
-
-		resolve->txt.GetData( &txtData, &txtLen );
-
-		path	 = (uint8_t*) TXTRecordGetValuePtr(txtLen, txtData, kTXTRecordKeyPath, &pathSize);
-
-		if (path == NULL)
-		{
-			path = (uint8_t*) "";
-			pathSize = 1;
-		}
-	}
-	else
-	{
-		path		= (uint8_t *) "";
-		pathSize	= 1;
-	}
-
-	// Build the URL in the following format:
-	//
-	// <urlScheme>[<username>[:<password>]@]<name/ip>[<path>]
-
-	url.AppendFormat( TEXT( "%S" ), resolve->handler->urlScheme );					// URL Scheme
-	if( username.GetLength() > 0 )
-	{
-		url.AppendFormat( TEXT( "%s" ), username );									// Username
-		if( password.GetLength() > 0 )
-		{
-			url.AppendFormat( TEXT( ":%s" ), password );							// Password
-		}
-		url.AppendFormat( TEXT( "@" ) );
-	}
-	
-	url += resolve->host;															// Host
-	url.AppendFormat( TEXT( ":%d" ), resolve->port );								// :Port
-	url.AppendFormat( TEXT( "%S" ), pathPrefix );									// Path Prefix ("/" or empty).
-	url.AppendFormat( TEXT( "%.*S" ), (int) pathSize, (char *) path );				// Path (possibly empty).
-	
-	// Tell Internet Explorer to go to the URL.
-	
-	check( mOwner );
-	mOwner->GoToURL( url );
-
-exit:
-	delete resolve;
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	Stop
-//===========================================================================================================================
-void ExplorerBarWindow::Stop( DNSServiceRef ref )
-{
-	m_serviceRefs.remove( ref );
-
-	WSAAsyncSelect(DNSServiceRefSockFD( ref ), m_hWnd, WM_PRIVATE_SERVICE_EVENT, 0);
-
-	DNSServiceRefDeallocate( ref );
-}
-
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	FindServiceArrayIndex
-//===========================================================================================================================
-
-DEBUG_LOCAL int	FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex )
-{
-	int		result;
-	int		lo;
-	int		hi;
-	int		mid;
-	
-	result 	= -1;
-	mid		= 0;
-	lo 		= 0;
-	hi 		= (int)( inArray.GetSize() - 1 );
-	while( lo <= hi )
-	{
-		mid = ( lo + hi ) / 2;
-		result = inService.displayName.CompareNoCase( inArray[ mid ]->displayName );
-#if 0
-		if( result == 0 )
-		{
-			result = ( (int) inService.ifi ) - ( (int) inArray[ mid ]->ifi );
-		}
-#endif
-		if( result == 0 )
-		{
-			break;
-		}
-		else if( result < 0 )
-		{
-			hi = mid - 1;
-		}
-		else
-		{
-			lo = mid + 1;
-		}
-	}
-	if( result == 0 )
-	{
-		mid += 1;	// Bump index so new item is inserted after matching item.
-	}
-	else if( result > 0 )
-	{
-		mid += 1;
-	}
-	outIndex = mid;
-	return( result );
-}
diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.h b/Clients/ExplorerPlugin/ExplorerBarWindow.h
deleted file mode 100644
index e816318..0000000
--- a/Clients/ExplorerPlugin/ExplorerBarWindow.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __EXPLORER_BAR_WINDOW__
-#define __EXPLORER_BAR_WINDOW__
-
-#pragma once
-
-#include    "afxtempl.h"
-
-#include    "dns_sd.h"
-#include    <list>
-
-//===========================================================================================================================
-//	Structures
-//===========================================================================================================================
-
-// Forward Declarations
-
-struct  ServiceHandlerEntry;
-class ExplorerBarWindow;
-
-// ServiceInfo
-
-struct  ServiceInfo
-{
-    CString displayName;
-    char *                      name;
-    char *                      type;
-    char *                      domain;
-    uint32_t ifi;
-    HTREEITEM item;
-    ServiceHandlerEntry *       handler;
-    DWORD refs;
-
-    ServiceInfo( void )
-    {
-        item    = NULL;
-        type    = NULL;
-        domain  = NULL;
-        handler = NULL;
-    }
-
-    ~ServiceInfo( void )
-    {
-        if( name )
-        {
-            free( name );
-        }
-        if( type )
-        {
-            free( type );
-        }
-        if( domain )
-        {
-            free( domain );
-        }
-    }
-};
-
-typedef CArray < ServiceInfo *, ServiceInfo * >     ServiceInfoArray;
-
-// TextRecord
-
-struct  TextRecord
-{
-    uint8_t *       mData;
-    uint16_t mSize;
-
-    TextRecord( void )
-    {
-        mData = NULL;
-        mSize = 0;
-    }
-
-    ~TextRecord( void )
-    {
-        if( mData )
-        {
-            free( mData );
-        }
-    }
-
-    void    GetData( void *outData, uint16_t *outSize )
-    {
-        if( outData )
-        {
-            *( (void **) outData ) = mData;
-        }
-        if( outSize )
-        {
-            *outSize = mSize;
-        }
-    }
-
-    OSStatus    SetData( const void *inData, uint16_t inSize )
-    {
-        OSStatus err;
-        uint8_t *       newData;
-
-        newData = (uint8_t *) malloc( inSize );
-        require_action( newData, exit, err = kNoMemoryErr );
-        memcpy( newData, inData, inSize );
-
-        if( mData )
-        {
-            free( mData );
-        }
-        mData = newData;
-        mSize = inSize;
-        err  = kNoErr;
-
-exit:
-        return( err );
-    }
-};
-
-// ResolveInfo
-
-struct  ResolveInfo
-{
-    CString host;
-    uint16_t port;
-    uint32_t ifi;
-    TextRecord txt;
-    ServiceHandlerEntry *       handler;
-};
-
-// ServiceHandlerEntry
-
-struct  ServiceHandlerEntry
-{
-    const char *            type;
-    const char *            urlScheme;
-    DNSServiceRef ref;
-    ServiceInfoArray array;
-    ExplorerBarWindow *     obj;
-    bool needsLogin;
-
-    ServiceHandlerEntry( void )
-    {
-        type        = NULL;
-        urlScheme   = NULL;
-        ref         = NULL;
-        obj         = NULL;
-        needsLogin  = false;
-    }
-
-    ~ServiceHandlerEntry( void )
-    {
-        int i;
-        int n;
-
-        n = (int) array.GetSize();
-        for( i = 0; i < n; ++i )
-        {
-            delete array[ i ];
-        }
-    }
-};
-
-typedef CArray < ServiceHandlerEntry *, ServiceHandlerEntry * >     ServiceHandlerArray;
-
-//===========================================================================================================================
-//	ExplorerBarWindow
-//===========================================================================================================================
-
-class ExplorerBar;      // Forward Declaration
-
-class ExplorerBarWindow : public CWnd
-{
-protected:
-
-ExplorerBar *           mOwner;
-CTreeCtrl mTree;
-
-ServiceHandlerArray mServiceHandlers;
-DNSServiceRef mResolveServiceRef;
-
-public:
-
-ExplorerBarWindow( void );
-virtual ~ExplorerBarWindow( void );
-
-protected:
-
-// General
-
-afx_msg int     OnCreate( LPCREATESTRUCT inCreateStruct );
-afx_msg void    OnDestroy( void );
-afx_msg void    OnSize( UINT inType, int inX, int inY );
-afx_msg void    OnDoubleClick( NMHDR *inNMHDR, LRESULT *outResult );
-afx_msg LRESULT OnServiceEvent( WPARAM inWParam, LPARAM inLParam );
-
-// Browsing
-
-static void DNSSD_API
-BrowseCallBack(
-    DNSServiceRef inRef,
-    DNSServiceFlags inFlags,
-    uint32_t inInterfaceIndex,
-    DNSServiceErrorType inErrorCode,
-    const char *            inName,
-    const char *            inType,
-    const char *            inDomain,
-    void *                  inContext );
-LONG OnServiceAdd( ServiceInfo * service );
-LONG OnServiceRemove( ServiceInfo * service );
-
-// Resolving
-
-OSStatus    StartResolve( ServiceInfo *inService );
-void        StopResolve( void );
-
-
-void        Stop( DNSServiceRef ref );
-
-
-static void DNSSD_API
-ResolveCallBack(
-    DNSServiceRef inRef,
-    DNSServiceFlags inFlags,
-    uint32_t inInterfaceIndex,
-    DNSServiceErrorType inErrorCode,
-    const char *            inFullName,
-    const char *            inHostName,
-    uint16_t inPort,
-    uint16_t inTXTSize,
-    const char *            inTXT,
-    void *                  inContext );
-LONG OnResolve( ResolveInfo * resolve );
-
-// Accessors
-
-public:
-
-ExplorerBar *   GetOwner( void ) const { return( mOwner ); }
-void            SetOwner( ExplorerBar *inOwner )    { mOwner = inOwner; }
-
-DECLARE_MESSAGE_MAP()
-private:
-
-typedef std::list< DNSServiceRef >  ServiceRefList;
-
-HTREEITEM m_about;
-ServiceRefList m_serviceRefs;
-CImageList m_imageList;
-};
-
-#endif  // __EXPLORER_BAR_WINDOW__
diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.cpp b/Clients/ExplorerPlugin/ExplorerPlugin.cpp
deleted file mode 100644
index fb1b7c2..0000000
--- a/Clients/ExplorerPlugin/ExplorerPlugin.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	"StdAfx.h"
-
-// The following 2 includes have to be in this order and INITGUID must be defined here, before including the file
-// that specifies the GUID(s), and nowhere else. The reason for this is that initguid.h doesn't provide separate 
-// define and declare macros for GUIDs so you have to #define INITGUID in the single file where you want to define 
-// your GUID then in all the other files that just need the GUID declared, INITGUID must not be defined.
-
-#define	INITGUID
-#include	<initguid.h>
-#include	"ExplorerPlugin.h"
-
-#include	<comcat.h>
-#include	<Shlwapi.h>
-
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-
-#include	"ClassFactory.h"
-#include	"Resource.h"
-
-#include	"loclibrary.h"
-
-// MFC Debugging
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-// Utilities
-
-DEBUG_LOCAL OSStatus	RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName );
-DEBUG_LOCAL OSStatus	RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister );
-DEBUG_LOCAL OSStatus	UnregisterServer( CLSID inCLSID );
-DEBUG_LOCAL OSStatus	MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey );
-
-// Stash away pointers to our resource DLLs
-
-static HINSTANCE g_nonLocalizedResources	= NULL;
-static CString	 g_nonLocalizedResourcesName;
-static HINSTANCE g_localizedResources		= NULL;
-
-HINSTANCE
-GetNonLocalizedResources()
-{
-	return g_nonLocalizedResources;
-}
-
-HINSTANCE
-GetLocalizedResources()
-{
-	return g_localizedResources;
-}
-
-// This is the class GUID for an undocumented hook into IE that will allow us to register
-// and have IE notice our new ExplorerBar without rebooting.
-// {8C7461EF-2B13-11d2-BE35-3078302C2030}
-
-DEFINE_GUID(CLSID_CompCatCacheDaemon, 
-0x8C7461EF, 0x2b13, 0x11d2, 0xbe, 0x35, 0x30, 0x78, 0x30, 0x2c, 0x20, 0x30);
-
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-HINSTANCE			gInstance		= NULL;
-int					gDLLRefCount	= 0;
-CExplorerPluginApp	gApp;
-
-#if 0
-#pragma mark -
-#pragma mark == DLL Exports ==
-#endif
-
-//===========================================================================================================================
-//	CExplorerPluginApp::CExplorerPluginApp
-//===========================================================================================================================
-
-IMPLEMENT_DYNAMIC(CExplorerPluginApp, CWinApp);
-
-CExplorerPluginApp::CExplorerPluginApp()
-{
-}
-
-
-//===========================================================================================================================
-//	CExplorerPluginApp::~CExplorerPluginApp
-//===========================================================================================================================
-
-CExplorerPluginApp::~CExplorerPluginApp()
-{
-}
-
-
-//===========================================================================================================================
-//	CExplorerPluginApp::InitInstance
-//===========================================================================================================================
-
-BOOL
-CExplorerPluginApp::InitInstance()
-{
-	wchar_t					resource[MAX_PATH];
-	OSStatus				err;
-	int						res;
-	HINSTANCE inInstance;
-
-	inInstance = AfxGetInstanceHandle();
-	gInstance = inInstance;
-
-	debug_initialize( kDebugOutputTypeWindowsEventLog, "DNSServices Bar", inInstance );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
-	dlog( kDebugLevelTrace, "\nCCPApp::InitInstance\n" );
-
-	res = PathForResource( inInstance, L"ExplorerPluginResources.dll", resource, MAX_PATH );
-
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_nonLocalizedResources = LoadLibrary( resource );
-	translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	g_nonLocalizedResourcesName = resource;
-
-	res = PathForResource( inInstance, L"ExplorerPluginLocalized.dll", resource, MAX_PATH );
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_localizedResources = LoadLibrary( resource );
-	translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	AfxSetResourceHandle( g_localizedResources );
-
-exit:
-
-	return TRUE;
-}
-
-
-//===========================================================================================================================
-//	CExplorerPluginApp::ExitInstance
-//===========================================================================================================================
-
-int
-CExplorerPluginApp::ExitInstance()
-{
-	return 0;
-}
-
-
-
-//===========================================================================================================================
-//	DllCanUnloadNow
-//===========================================================================================================================
-
-STDAPI	DllCanUnloadNow( void )
-{
-	dlog( kDebugLevelTrace, "DllCanUnloadNow (refCount=%d)\n", gDLLRefCount );
-	
-	return( gDLLRefCount == 0 );
-}
-
-//===========================================================================================================================
-//	DllGetClassObject
-//===========================================================================================================================
-
-STDAPI	DllGetClassObject( REFCLSID inCLSID, REFIID inIID, LPVOID *outResult )
-{
-	HRESULT				err;
-	BOOL				ok;
-	ClassFactory *		factory;
-	
-	dlog( kDebugLevelTrace, "DllGetClassObject\n" );
-	
-	*outResult = NULL;
-	
-	// Check if the class ID is supported.
-	
-	ok = IsEqualCLSID( inCLSID, CLSID_ExplorerBar );
-	require_action_quiet( ok, exit, err = CLASS_E_CLASSNOTAVAILABLE );
-	
-	// Create the ClassFactory object.
-	
-	factory = NULL;
-	try
-	{
-		factory = new ClassFactory( inCLSID );
-	}
-	catch( ... )
-	{
-		// Do not let exception escape.
-	}
-	require_action( factory, exit, err = E_OUTOFMEMORY );
-	
-	// Query for the specified interface. Release the factory since QueryInterface retains it.
-	
-	err = factory->QueryInterface( inIID, outResult );
-	factory->Release();
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DllRegisterServer
-//===========================================================================================================================
-
-STDAPI	DllRegisterServer( void )
-{
-	IRunnableTask * pTask = NULL;
-	HRESULT			err;
-	BOOL			ok;
-	CString			s;
-	
-	dlog( kDebugLevelTrace, "DllRegisterServer\n" );
-	
-	ok = s.LoadString( IDS_NAME );
-	require_action( ok, exit, err = E_UNEXPECTED );
-	
-	err = RegisterServer( gInstance, CLSID_ExplorerBar, s );
-	require_noerr( err, exit );
-	
-	err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, TRUE );
-	require_noerr( err, exit );
-
-	// <rdar://problem/4130635> Clear IE cache so it will rebuild the cache when it runs next.  This
-	// will allow us to install and not reboot
-
-	err = CoCreateInstance(CLSID_CompCatCacheDaemon, NULL, CLSCTX_INPROC, IID_IRunnableTask, (void**) &pTask);
-	require_noerr( err, exit );
-
-	pTask->Run();
-	pTask->Release();
-
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DllUnregisterServer
-//===========================================================================================================================
-
-STDAPI	DllUnregisterServer( void )
-{
-	HRESULT		err;
-	
-	dlog( kDebugLevelTrace, "DllUnregisterServer\n" );
-	
-	err = RegisterCOMCategory( CLSID_ExplorerBar, CATID_InfoBand, FALSE );
-	require_noerr( err, exit );
-
-	err = UnregisterServer( CLSID_ExplorerBar );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-
-#if 0
-#pragma mark -
-#pragma mark == Utilities ==
-#endif
-
-//===========================================================================================================================
-//	RegisterServer
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	RegisterServer( HINSTANCE inInstance, CLSID inCLSID, LPCTSTR inName )
-{
-	typedef struct	RegistryBuilder		RegistryBuilder;
-	struct	RegistryBuilder
-	{
-		HKEY		rootKey;
-		LPCTSTR		subKey;
-		LPCTSTR		valueName;
-		LPCTSTR		data;
-	};
-	
-	OSStatus			err;
-	LPWSTR				clsidWideString;
-	TCHAR				clsidString[ 64 ];
-	DWORD				nChars;
-	size_t				n;
-	size_t				i;
-	HKEY				key;
-	TCHAR				keyName[ MAX_PATH ];
-	TCHAR				moduleName[ MAX_PATH ] = TEXT( "" );
-	TCHAR				data[ MAX_PATH ];
-	RegistryBuilder		entries[] = 
-	{
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),					NULL,						inName },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\InprocServer32" ),	NULL,						moduleName },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\InprocServer32" ),  	TEXT( "ThreadingModel" ),	TEXT( "Apartment" ) }
-	};
-	DWORD				size;
-	OSVERSIONINFO		versionInfo;
-	
-	// Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
-	
-	err = StringFromIID( inCLSID, &clsidWideString );
-	require_noerr( err, exit );
-	require_action( clsidWideString, exit, err = kNoMemoryErr );
-	
-	#ifdef UNICODE
-		lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
-		CoTaskMemFree( clsidWideString );
-	#else
-		nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL );
-		err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
-		CoTaskMemFree( clsidWideString );
-		require_noerr( err, exit );
-	#endif
-	
-	// Register the CLSID entries.
-	
-	nChars = GetModuleFileName( inInstance, moduleName, sizeof_array( moduleName ) );
-	err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	n = sizeof_array( entries );
-	for( i = 0; i < n; ++i )
-	{
-		wsprintf( keyName, entries[ i ].subKey, clsidString );		
-		err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
-		require_noerr( err, exit );
-		
-		size = (DWORD)( ( lstrlen( entries[ i ].data ) + 1 ) * sizeof( TCHAR ) );
-		err = RegSetValueEx( key, entries[ i ].valueName, 0, REG_SZ, (LPBYTE) entries[ i ].data, size );
-		RegCloseKey( key );
-		require_noerr( err, exit );
-	}
-	
-	// If running on NT, register the extension as approved.
-	
-	versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
-	GetVersionEx( &versionInfo );
-	if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
-	{
-		lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) );
-		err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
-		require_noerr( err, exit );
-		
-		lstrcpyn( data, inName, sizeof_array( data ) );
-		size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-		err = RegSetValueEx( key, clsidString, 0, REG_SZ, (LPBYTE) data, size );
-		RegCloseKey( key );
-	}
-
-	// register toolbar button
-	lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) );
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	lstrcpyn( data, L"Yes", sizeof_array( data ) );
-	size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-	RegSetValueEx( key, L"Default Visible", 0, REG_SZ, (LPBYTE) data, size );
-
-	lstrcpyn( data, inName, sizeof_array( data ) );
-	size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-	RegSetValueEx( key, L"ButtonText", 0, REG_SZ, (LPBYTE) data, size );
-	
-	lstrcpyn( data, L"{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}", sizeof_array( data ) );
-	size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-	RegSetValueEx( key, L"CLSID", 0, REG_SZ, (LPBYTE) data, size );
-
-	lstrcpyn( data, clsidString, sizeof_array( data ) );
-	size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-	RegSetValueEx( key, L"BandCLSID", 0, REG_SZ, (LPBYTE) data, size );
-
-	// check if we're running XP or later
-	if ( ( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
-		 ( versionInfo.dwMajorVersion == 5 ) &&
-	     ( versionInfo.dwMinorVersion >= 1 ) )
-	{
-		wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
-		size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-		RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
-
-		wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_XP );
-		size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-		RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
-	}
-	else
-	{
-		wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
-		size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-		RegSetValueEx( key, L"Icon", 0, REG_SZ, (LPBYTE) data, size);
-
-		wsprintf( data, L"%s,%d", (LPCTSTR) g_nonLocalizedResourcesName, IDI_BUTTON_2K );
-		size = (DWORD)( ( lstrlen( data ) + 1 ) * sizeof( TCHAR ) );
-		RegSetValueEx( key, L"HotIcon", 0, REG_SZ, (LPBYTE) data, size);
-	}
-
-	RegCloseKey( key );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	RegisterCOMCategory
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	RegisterCOMCategory( CLSID inCLSID, CATID inCategoryID, BOOL inRegister )
-{
-	HRESULT				err;
-	ICatRegister *		cat;
-
-	err = CoInitialize( NULL );
-	require( SUCCEEDED( err ), exit );
-	
-	err = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID *) &cat );
-	check( SUCCEEDED( err ) );
-	if( SUCCEEDED( err ) )
-	{
-		if( inRegister )
-		{
-			err = cat->RegisterClassImplCategories( inCLSID, 1, &inCategoryID );
-			check_noerr( err );
-		}
-		else
-		{
-			err = cat->UnRegisterClassImplCategories( inCLSID, 1, &inCategoryID );
-			check_noerr( err );
-		}
-		cat->Release();
-	}
-	CoUninitialize();
-
-exit:
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	UnregisterServer
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	UnregisterServer( CLSID inCLSID )
-{
-	OSStatus			err = 0;
-	LPWSTR				clsidWideString;
-	TCHAR				clsidString[ 64 ];
-	HKEY				key;
-	TCHAR				keyName[ MAX_PATH * 2 ];
-	OSVERSIONINFO		versionInfo;
-
-	// Convert the CLSID to a string based on the encoding of this code (ANSI or Unicode).
-	
-	err = StringFromIID( inCLSID, &clsidWideString );
-	require_noerr( err, exit );
-	require_action( clsidWideString, exit, err = kNoMemoryErr );
-	
-	#ifdef UNICODE
-		lstrcpyn( clsidString, clsidWideString, sizeof_array( clsidString ) );
-		CoTaskMemFree( clsidWideString );
-	#else
-		nChars = WideCharToMultiByte( CP_ACP, 0, clsidWideString, -1, clsidString, sizeof_array( clsidString ), NULL, NULL );
-		err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
-		CoTaskMemFree( clsidWideString );
-		require_noerr( err, exit );
-	#endif
-
-	wsprintf( keyName, L"CLSID\\%s", clsidString );
-	MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
-	
-	// If running on NT, de-register the extension as approved.
-	
-	versionInfo.dwOSVersionInfoSize = sizeof( versionInfo );
-	GetVersionEx( &versionInfo );
-	if( versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
-	{
-		lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" ), sizeof_array( keyName ) );
-		err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
-		require_noerr( err, exit );
-
-		RegDeleteValue( key, clsidString );
-
-		err = RegCloseKey( key );
-		require_noerr( err, exit );
-	}
-
-	// de-register toolbar button
-
-	lstrcpyn( keyName, TEXT( "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\{7F9DB11C-E358-4ca6-A83D-ACC663939424}"), sizeof_array( keyName ) );
-	MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
-	
-exit:
-	return( err );
-}
-
-
-
-//===========================================================================================================================
-//	MyRegDeleteKey
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey )
-{
-    LPTSTR lpEnd;
-    OSStatus err;
-    DWORD dwSize;
-    TCHAR szName[MAX_PATH];
-    HKEY hKey;
-    FILETIME ftWrite;
-
-    // First, see if we can delete the key without having to recurse.
-
-    err = RegDeleteKey( hKeyRoot, lpSubKey );
-
-    if ( !err )
-	{
-		goto exit;
-	}
-
-    err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
-	require_noerr( err, exit );
-
-    // Check for an ending slash and add one if it is missing.
-
-    lpEnd = lpSubKey + lstrlen(lpSubKey);
-
-    if ( *( lpEnd - 1 ) != TEXT( '\\' ) ) 
-    {
-        *lpEnd =  TEXT('\\');
-        lpEnd++;
-        *lpEnd =  TEXT('\0');
-    }
-
-    // Enumerate the keys
-
-    dwSize = MAX_PATH;
-    err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
-
-    if ( !err ) 
-    {
-        do
-		{
-            lstrcpy (lpEnd, szName);
-
-            if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) )
-			{
-                break;
-            }
-
-            dwSize = MAX_PATH;
-
-            err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
-
-        }
-		while ( !err );
-    }
-
-    lpEnd--;
-    *lpEnd = TEXT('\0');
-
-    RegCloseKey( hKey );
-
-    // Try again to delete the key.
-
-    err = RegDeleteKey(hKeyRoot, lpSubKey);
-	require_noerr( err, exit );
-
-exit:
-
-	return err;
-}
diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.h b/Clients/ExplorerPlugin/ExplorerPlugin.h
deleted file mode 100644
index 9fa56ae..0000000
--- a/Clients/ExplorerPlugin/ExplorerPlugin.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#pragma once
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-// {9999A076-A9E2-4c99-8A2B-632FC9429223}
-DEFINE_GUID(CLSID_ExplorerBar,
-            0x9999a076, 0xa9e2, 0x4c99, 0x8a, 0x2b, 0x63, 0x2f, 0xc9, 0x42, 0x92, 0x23);
-
-extern HINSTANCE gInstance;
-extern int gDLLRefCount;
-extern HINSTANCE        GetNonLocalizedResources();
-extern HINSTANCE        GetLocalizedResources();
-
-
-class CExplorerPluginApp : public CWinApp
-{
-public:
-
-CExplorerPluginApp();
-virtual ~CExplorerPluginApp();
-
-protected:
-
-virtual BOOL    InitInstance();
-virtual int     ExitInstance();
-
-DECLARE_DYNAMIC(CExplorerPluginApp);
-};
diff --git a/Clients/ExplorerPlugin/LoginDialog.cpp b/Clients/ExplorerPlugin/LoginDialog.cpp
deleted file mode 100644
index a2cc89e..0000000
--- a/Clients/ExplorerPlugin/LoginDialog.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	<assert.h>
-#include	<stdlib.h>
-
-#include	"stdafx.h"
-
-#include	"LoginDialog.h"
-
-// MFC Debugging
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP( LoginDialog, CDialog )
-END_MESSAGE_MAP()
-
-//===========================================================================================================================
-//	LoginDialog
-//===========================================================================================================================
-
-LoginDialog::LoginDialog( CWnd *inParent )
-	: CDialog( LoginDialog::IDD, inParent )
-{
-	//
-}
-
-//===========================================================================================================================
-//	OnInitDialog
-//===========================================================================================================================
-
-BOOL	LoginDialog::OnInitDialog( void )
-{
-	CDialog::OnInitDialog();
-	return( TRUE );
-}
-
-//===========================================================================================================================
-//	DoDataExchange
-//===========================================================================================================================
-
-void	LoginDialog::DoDataExchange( CDataExchange *inDX )
-{
-	CDialog::DoDataExchange( inDX );
-}
-
-//===========================================================================================================================
-//	OnOK
-//===========================================================================================================================
-
-void	LoginDialog::OnOK( void )
-{
-	const CWnd *		control;
-		
-	// Username
-	
-	control = GetDlgItem( IDC_LOGIN_USERNAME_TEXT );
-	assert( control );
-	if( control )
-	{
-		control->GetWindowText( mUsername );
-	}
-	
-	// Password
-	
-	control = GetDlgItem( IDC_LOGIN_PASSWORD_TEXT );
-	assert( control );
-	if( control )
-	{
-		control->GetWindowText( mPassword );
-	}
-	
-	CDialog::OnOK();
-}
-
-//===========================================================================================================================
-//	GetLogin
-//===========================================================================================================================
-
-BOOL	LoginDialog::GetLogin( CString &outUsername, CString &outPassword )
-{
-	if( DoModal() == IDOK )
-	{
-		outUsername = mUsername;
-		outPassword = mPassword;
-		return( TRUE );
-	}
-	return( FALSE );
-}
diff --git a/Clients/ExplorerPlugin/LoginDialog.h b/Clients/ExplorerPlugin/LoginDialog.h
deleted file mode 100644
index 3aeb696..0000000
--- a/Clients/ExplorerPlugin/LoginDialog.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __LOGIN_DIALOG__
-#define __LOGIN_DIALOG__
-
-#pragma once
-
-#include    "Resource.h"
-
-//===========================================================================================================================
-//	LoginDialog
-//===========================================================================================================================
-
-class LoginDialog : public CDialog
-{
-protected:
-
-CString mUsername;
-CString mPassword;
-
-public:
-
-enum { IDD = IDD_LOGIN };
-
-LoginDialog( CWnd *inParent = NULL );
-
-virtual BOOL    GetLogin( CString &outUsername, CString &outPassword );
-
-protected:
-
-virtual BOOL    OnInitDialog( void );
-virtual void    DoDataExchange( CDataExchange *inDX );
-virtual void    OnOK( void );
-
-DECLARE_MESSAGE_MAP()
-};
-
-#endif  // __LOGIN_DIALOG__
diff --git a/Clients/ExplorerPlugin/Resource.h b/Clients/ExplorerPlugin/Resource.h
deleted file mode 100644
index aff47a4..0000000
--- a/Clients/ExplorerPlugin/Resource.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-// Include the core resources
-
-#include "resource_dll.h"
-
-// Include the non-localizable resources
-
-#include "resource_res.h"
-
-// Include the localizable resources
-
-#include "resource_loc_res.h"
diff --git a/Clients/ExplorerPlugin/StdAfx.cpp b/Clients/ExplorerPlugin/StdAfx.cpp
deleted file mode 100644
index 768fa3f..0000000
--- a/Clients/ExplorerPlugin/StdAfx.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	"StdAfx.h"
diff --git a/Clients/ExplorerPlugin/StdAfx.h b/Clients/ExplorerPlugin/StdAfx.h
deleted file mode 100644
index 2960892..0000000
--- a/Clients/ExplorerPlugin/StdAfx.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __STDAFX__
-#define __STDAFX__
-
-#pragma once
-
-#ifndef VC_EXTRALEAN
-#define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers
-#endif
-
-#if !defined(_WSPIAPI_COUNTOF)
-#   define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-#endif
-
-#include <afxwin.h>         // MFC core and standard components
-#include <afxext.h>         // MFC extensions
-#include <afxdtctl.h>       // MFC support for Internet Explorer 4 Common Controls
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-    #include <afxcmn.h>     // MFC support for Windows Common Controls
-#endif
-
-#include <winsock2.h>
-#include <afxsock.h>        // MFC socket extensions
-
-#endif  // __STDAFX__
diff --git a/Clients/ExplorerPlugin/resource_dll.h b/Clients/ExplorerPlugin/resource_dll.h
deleted file mode 100644
index fc3c0a9..0000000
--- a/Clients/ExplorerPlugin/resource_dll.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by ExplorerPlugin.rc
-//
-#define IDS_NAME                        106
-#define IDS_WEB_SITES                   107
-#define IDS_PRINTERS                    109
-#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110
-#define IDS_FIREWALL                    111
-#define IDC_COMPONENT                   1001
-#define IDC_LEGAL                       1002
-#define IDC_COMPONENT_VERSION           1003
-#define IDC_LOGIN_USERNAME_TEXT         1182
-#define IDC_LOGIN_PASSWORD_TEXT         1183
-#define ID_Menu                         40001
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        119
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/ExplorerPlugin/resource_loc_res.h b/Clients/ExplorerPlugin/resource_loc_res.h
deleted file mode 100644
index 6fc2d09..0000000
--- a/Clients/ExplorerPlugin/resource_loc_res.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by ExplorerPluginLocRes.rc
-//
-#define IDS_NAME                        106
-#define IDS_WEB_SITES                   107
-#define IDS_PRINTERS                    109
-#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110
-#define IDS_FIREWALL                    111
-#define IDD_ABOUT                       118
-#define IDR_CONTEXT_MENU                120
-#define IDD_LOGIN                       145
-#define IDC_ABOUT_BACKGROUND                146
-#define IDS_ABOUT                       147
-#define IDS_ABOUT_URL                   148
-#define IDC_COMPONENT                   1001
-#define IDC_LEGAL                       1002
-#define IDC_COMPONENT_VERSION           1003
-#define IDC_LOGIN_USERNAME_TEXT         1182
-#define IDC_LOGIN_PASSWORD_TEXT         1183
-#define ID_Menu                         40001
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        119
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/ExplorerPlugin/resource_res.h b/Clients/ExplorerPlugin/resource_res.h
deleted file mode 100644
index f2d4abd..0000000
--- a/Clients/ExplorerPlugin/resource_res.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by ExplorerPluginRes.rc
-//
-#define IDS_NAME                        106
-#define IDS_WEB_SITES                   107
-#define IDS_PRINTERS                    109
-#define IDS_MDNSRESPONDER_NOT_AVAILABLE 110
-#define IDS_FIREWALL                    111
-#define IDB_LOGO                        115
-#define IDI_BUTTON_2K                   115
-#define IDI_BUTTON_XP                   118
-#define IDB_ABOUT                       119
-#define IDC_COMPONENT                   1001
-#define IDC_LEGAL                       1002
-#define IDC_COMPONENT_VERSION           1003
-#define IDC_LOGIN_USERNAME_TEXT         1182
-#define IDC_LOGIN_PASSWORD_TEXT         1183
-#define ID_Menu                         40001
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        119
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/PrinterSetupWizard/About.cpp b/Clients/PrinterSetupWizard/About.cpp
deleted file mode 100644
index 6fda710..0000000
--- a/Clients/PrinterSetupWizard/About.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// About.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "About.h"
-
-
-// CAbout dialog
-
-IMPLEMENT_DYNAMIC(CAbout, CDialog)
-CAbout::CAbout(CWnd* pParent /*=NULL*/)
-	: CDialog(CAbout::IDD, pParent)
-{
-}
-
-CAbout::~CAbout()
-{
-}
-
-void CAbout::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-}
-
-
-BEGIN_MESSAGE_MAP(CAbout, CDialog)
-END_MESSAGE_MAP()
-
-
-// CAbout message handlers
diff --git a/Clients/PrinterSetupWizard/About.h b/Clients/PrinterSetupWizard/About.h
deleted file mode 100644
index 72e893d..0000000
--- a/Clients/PrinterSetupWizard/About.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-
-// CAbout dialog
-
-class CAbout : public CDialog
-{
-DECLARE_DYNAMIC(CAbout)
-
-public:
-CAbout(CWnd* pParent = NULL);       // standard constructor
-virtual ~CAbout();
-
-// Dialog Data
-enum { IDD = IDD_DIALOG1 };
-
-protected:
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-
-DECLARE_MESSAGE_MAP()
-};
diff --git a/Clients/PrinterSetupWizard/FirstPage.cpp b/Clients/PrinterSetupWizard/FirstPage.cpp
deleted file mode 100644
index a4e6e43..0000000
--- a/Clients/PrinterSetupWizard/FirstPage.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "FirstPage.h"
-
-#include <DebugServices.h>
-
-
-// CFirstPage dialog
-
-IMPLEMENT_DYNAMIC(CFirstPage, CPropertyPage)
-CFirstPage::CFirstPage()
-	: CPropertyPage(CFirstPage::IDD)
-{
-	CString fontName;
-
-	m_psp.dwFlags &= ~(PSP_HASHELP);
-	m_psp.dwFlags |= PSP_DEFAULT|PSP_HIDEHEADER;
-
-	fontName.LoadString(IDS_LARGE_FONT);
-
-	// create the large font
-	m_largeFont.CreateFont(-16, 0, 0, 0, 
-		FW_BOLD, FALSE, FALSE, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 
-		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, fontName);
-}
-
-CFirstPage::~CFirstPage()
-{
-}
-
-void CFirstPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_GREETING, m_greeting);
-}
-
-
-BOOL
-CFirstPage::OnSetActive()
-{
-	CPrinterSetupWizardSheet * psheet;
-	CString greetingText;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );   
-   
-	psheet->SetWizardButtons(PSWIZB_NEXT);
-
-	m_greeting.SetFont(&m_largeFont);
-
-	greetingText.LoadString(IDS_GREETING);
-	m_greeting.SetWindowText(greetingText);
-
-exit:
-
-	return CPropertyPage::OnSetActive();
-}
-
-
-BOOL
-CFirstPage::OnKillActive()
-{
-	CPrinterSetupWizardSheet * psheet;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );   
-   
-	psheet->SetLastPage(this);
-
-exit:
-
-	return CPropertyPage::OnKillActive();
-}
-
-
-BEGIN_MESSAGE_MAP(CFirstPage, CPropertyPage)
-END_MESSAGE_MAP()
-
-
-// CFirstPage message handlers
diff --git a/Clients/PrinterSetupWizard/FirstPage.h b/Clients/PrinterSetupWizard/FirstPage.h
deleted file mode 100644
index 0186c02..0000000
--- a/Clients/PrinterSetupWizard/FirstPage.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-#include "afxwin.h"
-
-
-// CFirstPage dialog
-
-class CFirstPage : public CPropertyPage
-{
-DECLARE_DYNAMIC(CFirstPage)
-
-public:
-CFirstPage();
-virtual ~CFirstPage();
-
-// Dialog Data
-enum { IDD = IDD_FIRST_PAGE };
-
-protected:
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-virtual BOOL OnSetActive();
-virtual BOOL OnKillActive();
-
-
-DECLARE_MESSAGE_MAP()
-
-private:
-
-CFont m_largeFont;
-
-public:
-
-CStatic m_greeting;
-};
diff --git a/Clients/PrinterSetupWizard/FourthPage.cpp b/Clients/PrinterSetupWizard/FourthPage.cpp
deleted file mode 100644
index 3817246..0000000
--- a/Clients/PrinterSetupWizard/FourthPage.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "FourthPage.h"
-
-#if !defined( PBS_MARQUEE )
-#	define PBS_MARQUEE  0x08
-#endif
-
-#if !defined( PBM_SETMARQUEE )
-#	define PBM_SETMARQUEE WM_USER + 10
-#endif
-
-
-
-// CFourthPage dialog
-
-IMPLEMENT_DYNAMIC(CFourthPage, CPropertyPage)
-CFourthPage::CFourthPage()
-	: CPropertyPage(CFourthPage::IDD),
-		m_initialized(false)
-{
-	CString fontName;
-
-	m_psp.dwFlags &= ~(PSP_HASHELP);
-	m_psp.dwFlags |= PSP_DEFAULT|PSP_HIDEHEADER;
-
-	fontName.LoadString(IDS_LARGE_FONT);
-
-	// create the large font
-	m_largeFont.CreateFont(-16, 0, 0, 0, 
-		FW_BOLD, FALSE, FALSE, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 
-		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, fontName);
-}
-
-CFourthPage::~CFourthPage()
-{
-}
-
-void CFourthPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_GOODBYE, m_goodbye);
-	DDX_Control(pDX, IDC_PRINTER_NAME, m_printerNameCtrl);
-	DDX_Control(pDX, IDC_PRINTER_MANUFACTURER, m_printerManufacturerCtrl);
-	DDX_Control(pDX, IDC_PRINTER_MODEL, m_printerModelCtrl);
-	DDX_Control(pDX, IDC_PRINTER_PROTOCOL, m_printerProtocolCtrl);
-	DDX_Control(pDX, IDC_PRINTER_DEFAULT, m_printerDefault);
-}
-
-
-BEGIN_MESSAGE_MAP(CFourthPage, CPropertyPage)
-END_MESSAGE_MAP()
-
-
-// CFourthPage message handlers
-OSStatus 
-CFourthPage::OnInitPage()
-{
-	CWnd * window; 
-	OSStatus err = kNoErr;
-
-	window = GetDlgItem( IDC_INSTALLING );
-	require_action( window, exit, err = kUnknownErr );
-	window->ShowWindow( SW_HIDE );
-
-	window = GetDlgItem( IDC_PROGRESS );
-	require_action( window, exit, err = kUnknownErr );
-	SetWindowLong( *window, GWL_STYLE, GetWindowLong( *window, GWL_STYLE ) | PBS_MARQUEE );
-	SetWindowLongPtr( *window, GWL_STYLE, GetWindowLongPtr( *window, GWL_STYLE ) | PBS_MARQUEE );
-	window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) FALSE,( LPARAM ) 35 );
-	window->ShowWindow( SW_HIDE );
-
-exit:
-
-	return err;
-}
-
-
-BOOL
-CFourthPage::OnSetActive()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	CString							goodbyeText;
-	Printer						*	printer;
-	CString							defaultText;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-   
-	printer = psheet->GetSelectedPrinter();
-	require_quiet( psheet, exit );
-	
-	psheet->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);
-
-	if (m_initialized == false)
-	{
-		m_initialized = true;
-		OnInitPage();
-	}
-
-	m_goodbye.SetFont(&m_largeFont);
-
-	goodbyeText.LoadString(IDS_GOODBYE);
-	m_goodbye.SetWindowText(goodbyeText);
-
-	m_printerNameCtrl.SetWindowText( printer->actualName );
-	m_printerManufacturerCtrl.SetWindowText ( printer->manufacturer );
-	m_printerModelCtrl.SetWindowText ( printer->displayModelName );
-
-	Service * service = printer->services.front();
-	require_quiet( service, exit );
-	m_printerProtocolCtrl.SetWindowText ( service->protocol );
-
-	if (printer->deflt)
-	{
-		defaultText.LoadString(IDS_YES);
-	}
-	else
-	{
-		defaultText.LoadString(IDS_NO);
-	}
-
-	m_printerDefault.SetWindowText ( defaultText );
-
-exit:
-
-	return CPropertyPage::OnSetActive();
-}
-
-
-BOOL
-CFourthPage::OnKillActive()
-{
-	CPrinterSetupWizardSheet * psheet;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );   
-   
-	psheet->SetLastPage(this);
-
-exit:
-
-	return CPropertyPage::OnKillActive();
-}
-
-
-BOOL
-CFourthPage::StartActivityIndicator()
-{
-	CWnd * window; 
-	BOOL ok = TRUE;
-
-	window = GetDlgItem( IDC_COMPLETE1 );
-	require_action( window, exit, ok = FALSE );
-	window->ShowWindow( SW_HIDE );
-
-	window = GetDlgItem( IDC_COMPLETE2 );
-	require_action( window, exit, ok = FALSE );
-	window->ShowWindow( SW_HIDE );
-
-	window = GetDlgItem( IDC_INSTALLING );
-	require_action( window, exit, ok = FALSE );
-	window->ShowWindow( SW_SHOW );
-
-	window = GetDlgItem( IDC_PROGRESS );
-	require_action( window, exit, ok = FALSE );
-	window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) TRUE,( LPARAM ) 50 );
-	window->ShowWindow( SW_SHOW );
-
-exit:
-
-	return ok;
-}
-
-
-BOOL
-CFourthPage::StopActivityIndicator()
-{
-	CWnd * window; 
-	BOOL ok = TRUE;
-
-	window = GetDlgItem( IDC_INSTALLING );
-	require_action( window, exit, ok = FALSE );
-	window->ShowWindow( SW_HIDE );
-
-	window = GetDlgItem( IDC_PROGRESS );
-	require_action( window, exit, ok = FALSE );
-	window->SendMessage( ( UINT ) PBM_SETMARQUEE, ( WPARAM ) FALSE,( LPARAM ) 35 );
-	window->ShowWindow( SW_HIDE );
-
-exit:
-
-	return ok;
-}
diff --git a/Clients/PrinterSetupWizard/FourthPage.h b/Clients/PrinterSetupWizard/FourthPage.h
deleted file mode 100644
index 5b4ea99..0000000
--- a/Clients/PrinterSetupWizard/FourthPage.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-#include "afxwin.h"
-
-
-// CFourthPage dialog
-
-class CFourthPage : public CPropertyPage
-{
-DECLARE_DYNAMIC(CFourthPage)
-
-public:
-CFourthPage();
-virtual ~CFourthPage();
-
-// Dialog Data
-enum { IDD = IDD_FOURTH_PAGE };
-
-virtual BOOL OnSetActive();
-virtual BOOL OnKillActive();
-
-BOOL StartActivityIndicator();
-BOOL StopActivityIndicator();
-
-protected:
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-
-DECLARE_MESSAGE_MAP()
-
-private:
-
-OSStatus    OnInitPage();
-CFont m_largeFont;
-bool m_initialized;
-
-
-public:
-CStatic m_goodbye;
-private:
-CStatic m_printerNameCtrl;
-CStatic m_printerManufacturerCtrl;
-CStatic m_printerModelCtrl;
-CStatic m_printerProtocolCtrl;
-CStatic m_printerDefault;
-};
diff --git a/Clients/PrinterSetupWizard/Logger.cpp b/Clients/PrinterSetupWizard/Logger.cpp
deleted file mode 100644
index 3385d31..0000000
--- a/Clients/PrinterSetupWizard/Logger.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "Logger.h"
-#include "DebugServices.h"
-#include <string>
-
-
-Logger::Logger()
-{
-	std::string	tmp;
-	char		path[ MAX_PATH ];
-	HRESULT		err;
-	BOOL		ok;
-
-	err = SHGetFolderPathA( NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path );
-	require_noerr( err, exit );
-
-	tmp = path;
-
-	// Create Logs subdir
-	tmp += "\\Apple";
-	ok = CreateDirectoryA( tmp.c_str(), NULL );
-	require_action( ( ok || ( GetLastError() == ERROR_ALREADY_EXISTS ) ), exit, err = -1 );
-
-	// Create Logs subdir
-	tmp += "\\Bonjour";
-	ok = CreateDirectoryA( tmp.c_str(), NULL );
-	require_action( ( ok || ( GetLastError() == ERROR_ALREADY_EXISTS ) ), exit, err = -1 );
-
-	// Create log file
-	tmp += "\\PrinterSetupLog.txt";
-	open( tmp.c_str());
-
-	*this << currentTime() << " Log started" << std::endl;
-
-exit:
-
-	return;
-}
-
-
-Logger::~Logger()
-{
-	*this << currentTime() << " Log finished" << std::endl;
-	flush();
-}
-
-
-std::string
-Logger::currentTime()
-{
-	time_t					ltime;
-	struct tm				now;
-	int						err;
-	std::string				ret;
-	
-	time( &ltime );
-	err = localtime_s( &now, &ltime );
-
-	if ( !err )
-	{
-		char temp[ 64 ];
-		
-		strftime( temp, sizeof( temp ), "%m/%d/%y %I:%M:%S %p", &now );
-		ret = temp;
-	}
-
-	return ret;
-}
diff --git a/Clients/PrinterSetupWizard/Logger.h b/Clients/PrinterSetupWizard/Logger.h
deleted file mode 100644
index 2f338c1..0000000
--- a/Clients/PrinterSetupWizard/Logger.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#ifndef _Logger_h
-#define _Logger_h
-
-#include <fstream>
-#include <string>
-
-
-class Logger : public std::ofstream
-{
-public:
-
-Logger();
-~Logger();
-
-std::string
-currentTime();
-};
-
-
-#define require_noerr_with_log( LOG, MESSAGE, ERR, LABEL )  \
-    do                      \
-    {                       \
-        int_least32_t localErr;         \
-        localErr = (int_least32_t)( ERR );  \
-        if( localErr != 0 )             \
-        {                   \
-            log << log.currentTime() << " [ERROR] " << MESSAGE << " returned " << ERR << std::endl;                     \
-            log << log.currentTime() << " [WHERE] " << "\"" << __FILE__ << "\", \"" << __FUNCTION__ << "\", line " << __LINE__ << std::endl << std::endl;   \
-            goto LABEL;         \
-        }                   \
-    } while( 0 )
-
-
-#define require_action_with_log( LOG, X, LABEL, ACTION )    \
-    do                      \
-    {                       \
-        if( !( X ) )                \
-        {                   \
-            log << log.currentTime() << " [ERROR] " << # X << std::endl; \
-            log << log.currentTime() << " [WHERE] " << "\"" << __FILE__ << "\", \"" << __FUNCTION__ << "\", line " << __LINE__ << std::endl << std::endl;   \
-            { ACTION; }         \
-            goto LABEL;         \
-        }                   \
-    } while( 0 )
-
-#endif
diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp
deleted file mode 100644
index d2a896d..0000000
--- a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "DebugServices.h"
-#include "loclibrary.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#endif
-
-#ifndef HeapEnableTerminationOnCorruption
-#	define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS) 1
-#endif
-
-
-// Stash away pointers to our resource DLLs
-
-static HINSTANCE g_nonLocalizedResources	= NULL;
-static HINSTANCE g_localizedResources		= NULL;
-
-
-HINSTANCE
-GetNonLocalizedResources()
-{
-	return g_nonLocalizedResources;
-}
-
-
-HINSTANCE
-GetLocalizedResources()
-{
-	return g_localizedResources;
-}
-
-
-// CPrinterSetupWizardApp
-
-BEGIN_MESSAGE_MAP(CPrinterSetupWizardApp, CWinApp)
-	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
-END_MESSAGE_MAP()
-
-
-// CPrinterSetupWizardApp construction
-
-CPrinterSetupWizardApp::CPrinterSetupWizardApp()
-{
-	// TODO: add construction code here,
-	// Place all significant initialization in InitInstance
-}
-
-
-// The one and only CPrinterSetupWizardApp object
-
-CPrinterSetupWizardApp theApp;
-
-
-// CPrinterSetupWizardApp initialization
-
-BOOL CPrinterSetupWizardApp::InitInstance()
-{
-	CString		errorMessage;
-	CString		errorCaption;
-	wchar_t		resource[MAX_PATH];
-	int			res;
-	OSStatus	err = kNoErr;
-
-	HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
-
-	//
-	// initialize the debugging framework
-	//
-	debug_initialize( kDebugOutputTypeWindowsDebugger, "PrinterSetupWizard", NULL );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
-
-	// Before we load the resources, let's load the error string
-
-	errorMessage.LoadString( IDS_REINSTALL );
-	errorCaption.LoadString( IDS_REINSTALL_CAPTION );
-
-	// Load Resources
-
-	res = PathForResource( NULL, L"PrinterWizardResources.dll", resource, MAX_PATH );
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_nonLocalizedResources = LoadLibrary( resource );
-	translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	res = PathForResource( NULL, L"PrinterWizardLocalized.dll", resource, MAX_PATH );
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_localizedResources = LoadLibrary( resource );
-	translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	AfxSetResourceHandle( g_localizedResources );
-
-	// InitCommonControls() is required on Windows XP if an application
-	// manifest specifies use of ComCtl32.dll version 6 or later to enable
-	// visual styles.  Otherwise, any window creation will fail.
-	InitCommonControls();
-
-	CWinApp::InitInstance();
-
-	AfxEnableControlContainer();
-
-	{
-		CPrinterSetupWizardSheet dlg(IDS_CAPTION);
-
-		m_pMainWnd = &dlg;
-
-		try
-		{
-			INT_PTR nResponse = dlg.DoModal();
-		
-			if (nResponse == IDOK)
-			{
-				// TODO: Place code here to handle when the dialog is
-				//  dismissed with OK
-			}
-			else if (nResponse == IDCANCEL)
-			{
-				// TODO: Place code here to handle when the dialog is
-				//  dismissed with Cancel
-			}
-		}
-		catch (CPrinterSetupWizardSheet::WizardException & exc)
-		{
-			MessageBox(NULL, exc.text, exc.caption, MB_OK|MB_ICONEXCLAMATION);
-		}
-	}
-
-exit:
-
-	if ( err )
-	{
-		MessageBox( NULL, errorMessage, errorCaption, MB_ICONERROR | MB_OK );
-	}
-
-	if ( g_nonLocalizedResources )
-	{
-		FreeLibrary( g_nonLocalizedResources );
-	}
-
-	if ( g_localizedResources )
-	{
-		FreeLibrary( g_localizedResources );
-	}
-
-	// Since the dialog has been closed, return FALSE so that we exit the
-	//  application, rather than start the application's message pump.
-	return FALSE;
-}
diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h
deleted file mode 100644
index 379c9e4..0000000
--- a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#ifndef __AFXWIN_H__
-    #error include 'stdafx.h' before including this file for PCH
-#endif
-
-#include "resource.h"       // main symbols
-
-
-// CWiz97_3App:
-// See Wiz97_3.cpp for the implementation of this class
-//
-
-class CPrinterSetupWizardApp : public CWinApp
-{
-public:
-CPrinterSetupWizardApp();
-
-// Overrides
-public:
-virtual BOOL InitInstance();
-
-// Implementation
-
-DECLARE_MESSAGE_MAP()
-};
-
-
-extern CPrinterSetupWizardApp theApp;
-extern HINSTANCE                GetNonLocalizedResources();
-extern HINSTANCE                GetLocalizedResources();
diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp
deleted file mode 100644
index 47e5f91..0000000
--- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp
+++ /dev/null
@@ -1,1949 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "CommonServices.h"
-#include "DebugServices.h"
-#include "WinServices.h"
-#include "About.h"
-#include "tcpxcv.h"
-#include <winspool.h>
-#include <string>
-#include <shlwapi.h>
-
-// unreachable code
-#pragma warning(disable:4702)
-
-
-#if( !TARGET_OS_WINDOWS_CE )
-#	include	<mswsock.h>
-#	include	<process.h>
-#endif
-
-
-#if defined( UNICODE ) || defined( _UNICODE )
-#	define GetEnv	_wgetenv
-#else
-#	define GetEnv	getenv
-#endif
-
-static TCHAR*
-g_printerDriverFiles[] =		// Printer driver files
-{
-	TEXT( "ps5ui.dll" ),
-	TEXT( "pscript.hlp" ),
-	TEXT( "pscript.ntf" ),
-	TEXT( "pscript5.dll" ),
-	TEXT( "cups6.ini" ),
-	TEXT( "cupsui6.dll" ),
-	TEXT( "cupsps6.dll" )
-};
-
-
-// Private Messages
-
-#define WM_SOCKET_EVENT		( WM_USER + 0x100 )
-#define WM_PROCESS_EVENT	( WM_USER + 0x101 )
-
-
-static BOOL
-Is64BitWindows()
-{
-#if defined(_WIN64)
-	return TRUE;  // 64-bit programs run only on Win64
-#else
-	typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)( HANDLE, PBOOL );
-	LPFN_ISWOW64PROCESS fnIsWow64Process;
-	BOOL bIsWow64 = FALSE;
-
-    fnIsWow64Process = ( LPFN_ISWOW64PROCESS ) GetProcAddress( GetModuleHandle( TEXT( "kernel32" ) ), "IsWow64Process" );
-  
-    if ( fnIsWow64Process != NULL )
-    {
-		BOOL ok;
-
-        ok = fnIsWow64Process( GetCurrentProcess(), &bIsWow64 );
-
-		if ( !ok )
-		{
-			bIsWow64 = FALSE;
-		}
-	}
-
-	return bIsWow64;
-#endif
-}
-
-
-// CPrinterSetupWizardSheet
-CPrinterSetupWizardSheet * CPrinterSetupWizardSheet::m_self;
-
-IMPLEMENT_DYNAMIC(CPrinterSetupWizardSheet, CPropertySheet)
-CPrinterSetupWizardSheet::CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
-	:CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
-	m_selectedPrinter(NULL),
-	m_driverThreadExitCode( 0 ),
-	m_driverThreadFinished( false ),
-	m_pdlBrowser( NULL ),
-	m_ippBrowser( NULL ),
-	m_lprBrowser( NULL ),
-	m_lastPage( NULL )
-{
-	m_arrow		=	LoadCursor(0, IDC_ARROW);
-	m_wait		=	LoadCursor(0, IDC_APPSTARTING);
-	m_active	=	m_arrow;
-	m_self		=	this;
-	
-	Init();
-
-	LoadPrinterNames();
-}
-
-
-CPrinterSetupWizardSheet::~CPrinterSetupWizardSheet()
-{
-	Printer * printer;
-
-	while ( m_printers.size() > 0 )
-	{
-		printer = m_printers.front();
-		m_printers.pop_front();
-
-		delete printer;
-	}
-
-	m_self = NULL;
-}
-
-
-// ------------------------------------------------------
-// SetSelectedPrinter
-//
-// Manages setting a printer as the printer to install.  Stops
-// any pending resolves.  
-//	
-void
-CPrinterSetupWizardSheet::SetSelectedPrinter(Printer * printer)
-{
-	check( !printer || ( printer != m_selectedPrinter ) );
-
-	m_selectedPrinter = printer;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::LoadPrinterNames()
-{
-	PBYTE		buffer	=	NULL;
-	OSStatus	err		= 0;
-
-	//
-	// rdar://problem/3701926 - Printer can't be installed twice
-	//
-	// First thing we want to do is make sure the printer isn't already installed.
-	// If the printer name is found, we'll try and rename it until we
-	// find a unique name
-	//
-	DWORD dwNeeded = 0, dwNumPrinters = 0;
-
-	BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
-	err = translate_errno( ok, errno_compat(), kUnknownErr );
-
-	if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
-	{
-		try
-		{
-			buffer = new unsigned char[dwNeeded];
-		}
-		catch (...)
-		{
-			buffer = NULL;
-		}
-	
-		require_action( buffer, exit, kNoMemoryErr );
-		ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
-		err = translate_errno( ok, errno_compat(), kUnknownErr );
-		require_noerr( err, exit );
-
-		for (DWORD index = 0; index < dwNumPrinters; index++)
-		{
-			PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
-
-			m_printerNames.push_back( lppi4->pPrinterName );
-		}
-	}
-
-exit:
-
-	if (buffer != NULL)
-	{
-		delete [] buffer;
-	}
-
-	return err;
-}
-
-
-
-// ------------------------------------------------------
-// InstallPrinter
-//
-// Installs a printer with Windows.
-//
-// Note: this works one of two ways, depending on whether
-// there are drivers already installed for this printer.
-// If there are, then we can just create a port with XcvData,
-// and then call AddPrinter.  If not, we use the printui.dll
-// to install the printer. Actually installing drivers that
-// are not currently installed is painful, and it's much
-// easier and less error prone to just let printui.dll do
-// the hard work for us.
-//	
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinter(Printer * printer)
-{
-	Logger		log;
-	CUPSLibrary	cupsLib;
-	Service	*	service		= NULL;
-	BOOL		ok;
-	OSStatus	err = 0;
-
-	service = printer->services.front();
-	check( service );
-
-	if ( printer->isCUPSPrinter && cupsLib.IsInstalled() )
-	{
-		err = InstallPrinterCUPS( printer, service, cupsLib );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		//
-		// if the driver isn't installed, then install it
-		//
-
-		if ( !printer->driverInstalled )
-		{
-			DWORD		dwResult;
-			HANDLE		hThread;
-			unsigned	threadID;
-
-			m_driverThreadFinished = false;
-		
-			//
-			// create the thread
-			//
-			hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID );
-			err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr );
-			require_noerr_with_log( log, "_beginthreadex_compat()", err, exit );
-				
-			//
-			// go modal
-			//
-			while (!m_driverThreadFinished)
-			{
-				MSG msg;
-		
-				GetMessage( &msg, m_hWnd, 0, 0 );
-				TranslateMessage(&msg);
-				DispatchMessage(&msg);
-			}
-
-			//
-			// Wait until child process exits.
-			//
-			dwResult = WaitForSingleObject( hThread, INFINITE );
-			err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
-			require_noerr_with_log( log, "WaitForSingleObject()", err, exit );
-
-			//
-			// check the return value of thread
-			//
-			require_noerr_with_log( log, "thread exit code", m_driverThreadExitCode, exit );
-
-			//
-			// now we know that the driver was successfully installed
-			//
-			printer->driverInstalled = true;
-		}
-
-		if ( service->type == kPDLServiceType )
-		{
-			err = InstallPrinterPort( printer, service, PROTOCOL_RAWTCP_TYPE, log );
-			require_noerr_with_log( log, "InstallPrinterPort()", err, exit );
-			err = InstallPrinterPDLAndLPR( printer, service, log );
-			require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
-		}
-		else if ( service->type == kLPRServiceType )
-		{
-			err = InstallPrinterPort( printer, service, PROTOCOL_LPR_TYPE, log );
-			require_noerr_with_log( log, "InstallPrinterPort()", err, exit );
-			err = InstallPrinterPDLAndLPR( printer, service, log );
-			require_noerr_with_log( log, "InstallPrinterPDLAndLPR()", err, exit );
-		}
-		else if ( service->type == kIPPServiceType )
-		{
-			// There's no need to install a printer port for IPP printers, because
-			// the call to AddPrinter() will do that for us.
-
-			err = InstallPrinterIPP( printer, service, log );
-			require_noerr_with_log( log, "InstallPrinterIPP()", err, exit );
-		}
-		else
-		{
-			require_action_with_log( log, ( service->type == kPDLServiceType ) || ( service->type == kLPRServiceType ) || ( service->type == kIPPServiceType ), exit, err = kUnknownErr );
-		}
-	}
-
-	printer->installed = true;
-
-	//
-	// if the user specified a default printer, set it
-	//
-	if (printer->deflt)
-	{
-		ok = SetDefaultPrinter( printer->actualName );
-		err = translate_errno( ok, errno_compat(), err = kUnknownErr );
-		require_noerr_with_log( log, "SetDefaultPrinter()", err, exit );
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinterPort( Printer * printer, Service * service, DWORD protocol, Logger & log )
-{
-	PRINTER_DEFAULTS	printerDefaults =	{ NULL,  NULL, SERVER_ACCESS_ADMINISTER };
-	PORT_DATA_1			portData;
-	DWORD				dwStatus;
-	DWORD				cbInputData		=	100;
-	PBYTE				pOutputData		=	NULL;
-	DWORD				cbOutputNeeded	=	0;
-	HANDLE				hXcv			=	NULL;
-	Queue			*	q;
-	BOOL				ok;
-	OSStatus			err;
-
-	ZeroMemory(&portData, sizeof(PORT_DATA_1));
-
-	require_action_with_log( log, wcslen(printer->portName) < sizeof_array(portData.sztPortName), exit, err = kSizeErr );
-	wcscpy_s(portData.sztPortName, printer->portName);
-
-	q = service->queues.front();
-	check( q );
-
-	ok = OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hXcv, &printerDefaults);
-	err = translate_errno( ok, errno_compat(), kUnknownErr );
-	require_noerr_with_log( log, "OpenPrinter()", err, exit );
-
-	//
-	// BUGBUG: MSDN said this is not required, but my experience shows it is required
-	//
-	try
-	{
-		pOutputData = new BYTE[cbInputData];
-	}
-	catch (...)
-	{
-		pOutputData = NULL;
-	}
-
-	require_action_with_log( log, pOutputData, exit, err = kNoMemoryErr );
-    	
-	portData.dwPortNumber	=	service->portNumber;
-	portData.dwVersion		=	1;
-	portData.dwDoubleSpool	=	1;
-    	
-	portData.dwProtocol	= protocol;
-	portData.cbSize		= sizeof PORT_DATA_1;
-	portData.dwReserved	= 0L;
-
-	require_action_with_log( log, wcslen(q->name) < sizeof_array(portData.sztQueue), exit, err = kSizeErr );
-	wcscpy_s(portData.sztQueue, q->name);
-
-	require_action_with_log( log, wcslen( service->hostname ) < sizeof_array(portData.sztHostAddress), exit, err = kSizeErr );
-	wcscpy_s( portData.sztHostAddress, service->hostname );
-
-	ok = XcvData(hXcv, L"AddPort", (PBYTE) &portData, sizeof(PORT_DATA_1), pOutputData, cbInputData,  &cbOutputNeeded, &dwStatus);
-	err = translate_errno( ok, errno_compat(), kUnknownErr );
-	require_noerr_with_log( log, "XcvData()", err, exit );
-
-exit:
-
-	if (hXcv != NULL)
-	{
-		ClosePrinter(hXcv);
-	}
-
-	if (pOutputData != NULL)
-	{
-		delete [] pOutputData;
-	}
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, Logger & log )
-{
-	PRINTER_INFO_2		pInfo;
-	HANDLE				hPrinter = NULL;
-	Queue			*	q;
-	OSStatus			err;
-
-	check(printer != NULL);
-	check(printer->installed == false);
-
-	q = service->queues.front();
-	check( q );
-
-	//
-	// add the printer
-	//
-	ZeroMemory(&pInfo, sizeof(pInfo));
-		
-	pInfo.pPrinterName			=	printer->actualName.GetBuffer();
-	pInfo.pServerName			=	NULL;
-	pInfo.pShareName			=	NULL;
-	pInfo.pPortName				=	printer->portName.GetBuffer();
-	pInfo.pDriverName			=	printer->modelName.GetBuffer();
-	pInfo.pComment				=	printer->displayModelName.GetBuffer();
-	pInfo.pLocation				=	q->location.GetBuffer();
-	pInfo.pDevMode				=	NULL;
-	pInfo.pDevMode				=	NULL;
-	pInfo.pSepFile				=	L"";
-	pInfo.pPrintProcessor		=	L"winprint";
-	pInfo.pDatatype				=	L"RAW";
-	pInfo.pParameters			=	L"";
-	pInfo.pSecurityDescriptor	=	NULL;
-	pInfo.Attributes			=	PRINTER_ATTRIBUTE_QUEUED;
-	pInfo.Priority				=	0;
-	pInfo.DefaultPriority		=	0;
-	pInfo.StartTime				=	0;
-	pInfo.UntilTime				=	0;
-
-	hPrinter = AddPrinter(NULL, 2, (LPBYTE) &pInfo);
-	err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
-	require_noerr_with_log( log, "AddPrinter()", err, exit );
-
-exit:
-
-	if (hPrinter != NULL)
-	{
-		ClosePrinter(hPrinter);
-	}
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service, Logger & log)
-{
-	DEBUG_UNUSED( service );
-
-	Queue		*	q		 = service->SelectedQueue();
-	HANDLE			hPrinter = NULL;
-	PRINTER_INFO_2	pInfo;
-	OSStatus		err;
-
-	check( q );
-	
-	//
-	// add the printer
-	//
-	ZeroMemory(&pInfo, sizeof(PRINTER_INFO_2));
-	
-	pInfo.pPrinterName		= printer->actualName.GetBuffer();
-	pInfo.pPortName			= printer->portName.GetBuffer();
-	pInfo.pDriverName		= printer->modelName.GetBuffer();
-	pInfo.pPrintProcessor	= L"winprint";
-	pInfo.pLocation			= q->location.GetBuffer();
-	pInfo.pComment			= printer->displayModelName.GetBuffer();
-	pInfo.Attributes		= PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
-	
-	hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo);
-	err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
-	require_noerr_with_log( log, "AddPrinter()", err, exit );
-
-exit:
-
-	if ( hPrinter != NULL )
-	{
-		ClosePrinter(hPrinter);
-	}
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib )
-{
-	OSStatus err = kNoErr;
-
-	check( printer );
-	check( service );
-	check( cupsLib.IsInstalled() );
-
-	err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows NT x86" ) );
-	require_noerr( err, exit );
-
-	if ( Is64BitWindows() )
-	{
-		err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows x64" ) );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib, TCHAR * env )
-{
-	
-	Queue		*	q;
-	CString			ppdfile;				// PPD file for printer drivers
-	TCHAR			driverdir[1024];		// Directory for driver files
-	DWORD			needed;					// Bytes needed
-	DRIVER_INFO_3	driverinfo;				// Driver information
-	PRINTER_INFO_2	printerinfo;			// Printer information
-	HANDLE			printerHandle = NULL;	// Handle to printer
-	CString			filename;				// Driver filename
-	CString			dependentFiles;			// List of dependent files
-	CString			portName;				// Port Name
-	int				bytes;					// Bytes copied
-	TCHAR			datadir[ MAX_PATH ];	// Driver files location
-	CFile			in;						// Input file
-	CFile			out;					// Output file
-	void		*	http;					// Connection to server
-	char			buffer[4096];			// Copy/error buffer
-	CString			platform;
-	char			hostname[ 1024 ];
-	CString			dest;
-	char			destANSI[ 1024 ];
-	int				i;
-	DWORD			num;
-	OSStatus		err	= 0;
-	BOOL			ok;
-
-	check( printer );
-	check( service );
-	check( cupsLib.IsInstalled() );
-	check( env );
-
-	// What do we do here for multiple queues?
-	q = service->queues.front();
-	require_action( q != NULL, exit, err = kUnknownErr );
-
-	num = GetModuleFileName( NULL, datadir, MAX_PATH );
-	err = translate_errno( num > 0, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	ok = PathRemoveFileSpec( datadir );
-	require_action( ok, exit, err = kUnknownErr );
-
-	ok = GetPrinterDriverDirectory(NULL, env, 1, ( LPBYTE ) driverdir, sizeof( driverdir ), &needed );
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	platform = env;
-	platform = platform.Right( 3 );
-
-	// Append the supported banner pages to the PPD file...
-	err = StringObjectToUTF8String( service->hostname, hostname, sizeof( hostname ) );
-	require_noerr( err, exit );
-	http = cupsLib.httpConnectEncrypt( hostname, service->portNumber, cupsLib.cupsEncryption() );
-	err = translate_errno( http != NULL, errno, kUnknownErr );
-	require_noerr( err, exit );
-
-	if ( ( service->portNumber == 443 ) || ( cupsLib.cupsEncryption() >= HTTP_ENCRYPT_REQUIRED ) )
-	{
-		// This forces the use the https: URLs below...
-		cupsLib.cupsSetEncryption( HTTP_ENCRYPT_ALWAYS );
-	}
-
-	// Strip the leading "printers/" or "classes/" from the beginning
-	// of the name
-
-	dest = q->name;
-	dest.Replace( TEXT( "printers/" ), TEXT( "" ) );
-	dest.Replace( TEXT( "classes/" ), TEXT( "" ) );
-
-	err = StringObjectToUTF8String( dest, destANSI, sizeof( destANSI ) );
-	require_noerr( err, exit );
-
-	// Get the PPD file...
-	for ( i = 0; i < 10; i++ )
-	{
-		char ppdfileANSI[ 1024 ];
-
-		if ( cupsLib.cupsAdminCreateWindowsPPD( http, destANSI, ppdfileANSI, sizeof( ppdfileANSI ) ) )
-		{
-			err = UTF8StringToStringObject( ppdfileANSI, ppdfile );
-			require_noerr( err, exit );
-			break;
-		}
-	}
-
-	err = translate_errno( i < 10, errno, kUnknownErr );
-	require_noerr( err, exit );
-
-	// Copy the PPD file to the Windows driver directory...
-	filename.Format( TEXT( "%s/%s.ppd" ), driverdir, dest );
-
-	ok = in.Open( ppdfile, CFile::modeRead | CFile::typeBinary );
-	translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	ok = out.Open( filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
-	translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	while ( ( bytes = in.Read( buffer, sizeof(buffer) ) ) > 0 )
-	{
-		out.Write(buffer, bytes );
-	}
-
-	in.Close();
-	out.Close();
-
-	// Cleanup temp file...
-	CFile::Remove( ppdfile );
-
-	// Copy the driver files to the driver directory...
-	for ( i = 0; i < ( sizeof( g_printerDriverFiles ) / sizeof( g_printerDriverFiles[0] ) ); i++ )
-	{
-		filename.Format( TEXT( "%s/drivers/%s/%s" ), datadir, platform, g_printerDriverFiles[i]);
-	
-		ok = in.Open(filename, CFile::modeRead | CFile::typeBinary );
-		err = translate_errno( ok, GetLastError(), kUnknownErr );
-		require_noerr( err, exit );
-
-		filename.Format( TEXT( "%s/%s" ), driverdir, g_printerDriverFiles[i] );
-		ok = out.Open(filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
-		err = translate_errno( ok, errno, kUnknownErr );
-
-		while ( ( bytes = in.Read(buffer, sizeof( buffer ) ) ) > 0 )
-		{
-			out.Write( buffer, bytes );
-		}
-
-		in.Close();
-		out.Close();
-	}
-
-	// Do the Windows system calls needed to add the printer driver...
-	filename.Format( TEXT( "%s.ppd" ), dest);
-	dependentFiles.Format( TEXT( "pscript5.dll%c" ) TEXT( "%s.ppd%c" ) TEXT( "ps5ui.dll%c" ) TEXT( "pscript.hlp%c" ) TEXT( "pscript.ntf%c" ) TEXT( "cups6.ini%c" ) TEXT( "cupsps6.dll%c" ) TEXT( "cupsui6.dll%c" ), 0, dest, 0, 0, 0, 0, 0, 0, 0);
-
-	driverinfo.cVersion         = 3;
-	driverinfo.pName            = printer->actualName.GetBuffer();
-	driverinfo.pEnvironment     = env;
-	driverinfo.pDriverPath      = TEXT( "pscript5.dll" );
-	driverinfo.pDataFile        = filename.GetBuffer();
-	driverinfo.pConfigFile      = TEXT( "ps5ui.dll" );
-	driverinfo.pHelpFile        = TEXT( "pscript.hlp" );
-	driverinfo.pDependentFiles  = dependentFiles.GetBuffer();
-	driverinfo.pMonitorName     = NULL;
-	driverinfo.pDefaultDataType = TEXT( "raw" );
-
-	ok = AddPrinterDriverEx(NULL, 3, (LPBYTE) &driverinfo, APD_COPY_ALL_FILES );
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// See if the printer has already been added?
-	if ( OpenPrinter( printer->actualName.GetBuffer(), &printerHandle, NULL ) )
-    {
-		// Printer already exists, so we are done now...
-		goto exit;
-    }
-
-    // Add the printer using the HTTP/IPP port...
-	portName.Format( TEXT( "%s://%s:%d/printers/%s" ), cupsLib.cupsEncryption() == HTTP_ENCRYPT_ALWAYS ? TEXT( "https" ) : TEXT( "http" ), service->hostname.GetBuffer(), service->portNumber, dest );
-
-    memset(&printerinfo, 0, sizeof(printerinfo));
-    printerinfo.pPrinterName	= printer->actualName.GetBuffer();
-    printerinfo.pPortName		= portName.GetBuffer();
-    printerinfo.pDriverName		= printer->actualName.GetBuffer();
-    printerinfo.Attributes		= PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
-	printerinfo.pComment		= q->description.GetBuffer();
-	printerinfo.pLocation		= q->location.GetBuffer();
-	printerinfo.pPrintProcessor = TEXT( "winprint" );
-
-    printerHandle = AddPrinter( NULL, 2, (LPBYTE) &printerinfo );
-	err = translate_errno( printerHandle, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( printerHandle != NULL )
-	{
-		ClosePrinter( printerHandle );
-		printerHandle = NULL;
-	}
-
-	return err;
-}
-
-BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
-ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent )
-ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
-ON_WM_SETCURSOR()
-ON_WM_TIMER()
-END_MESSAGE_MAP()
-
-
-// ------------------------------------------------------
-// OnCommand
-//
-// Traps when the user hits Finish  
-//	
-BOOL CPrinterSetupWizardSheet::OnCommand(WPARAM wParam, LPARAM lParam)
-{
-	//
-	// Check if this is OK
-	//
-	if (wParam == ID_WIZFINISH)              // If OK is hit...
-	{
-		OnOK();
-	}
- 
-	return CPropertySheet::OnCommand(wParam, lParam);
-}
-
-
-// ------------------------------------------------------
-// OnInitDialog
-//
-// Initializes this Dialog object.
-//	
-BOOL CPrinterSetupWizardSheet::OnInitDialog()
-{
-	OSStatus err;
-
-	CPropertySheet::OnInitDialog();
-
-	err = StartBrowse();
-	require_noerr( err, exit );
-
-exit:
-
-	if ( err )
-	{
-		StopBrowse();
-
-		if ( err == kDNSServiceErr_Firewall )
-		{
-			CString text, caption;
-
-			text.LoadString( IDS_FIREWALL );
-			caption.LoadString( IDS_FIREWALL_CAPTION );
-
-			MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
-		}
-		else
-		{
-			CString text, caption;
-
-			text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
-			caption.LoadString( IDS_ERROR_CAPTION );
-
-			MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
-
-			_exit( 0 );
-		}
-	}
-
-	return TRUE;
-}
-
-
-// ------------------------------------------------------
-// OnSetCursor
-//
-// This is called when Windows wants to know what cursor
-// to display.  So we tell it.  
-//	
-BOOL
-CPrinterSetupWizardSheet::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
-{
-	DEBUG_UNUSED(pWnd);
-	DEBUG_UNUSED(nHitTest);
-	DEBUG_UNUSED(message);
-
-	SetCursor(m_active);
-	return TRUE;
-}
-
-
-// ------------------------------------------------------
-// OnContextMenu
-//
-// This is not fully implemented yet.  
-//	
-
-void
-CPrinterSetupWizardSheet::OnContextMenu(CWnd * pWnd, CPoint pos)
-{
-	DEBUG_UNUSED(pWnd);
-	DEBUG_UNUSED(pos);
-
-	CAbout dlg;
-
-	dlg.DoModal();
-}
-
-
-// ------------------------------------------------------
-// OnOK
-//
-// This is called when the user hits the "Finish" button  
-//	
-void
-CPrinterSetupWizardSheet::OnOK()
-{
-	CWnd * window;
-	OSStatus err;
-
-	check ( m_selectedPrinter != NULL );
-
-	SetWizardButtons( PSWIZB_DISABLEDFINISH );
-
-	window = GetDlgItem( IDCANCEL );
- 
-	if ( window )
-	{
-		window->EnableWindow( FALSE );
-	}
-
-	m_pgFourth.StartActivityIndicator();
-	
-	err = InstallPrinter( m_selectedPrinter );
-
-	m_pgFourth.StopActivityIndicator();
-
-	if ( err != kNoErr )
-	{
-		CString caption;
-		CString message;
-
-		caption.LoadString(IDS_INSTALL_ERROR_CAPTION);
-		caption.AppendFormat( TEXT( " (%d)" ), err );
-		message.LoadString(IDS_INSTALL_ERROR_MESSAGE);
-		MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
-	}
-
-	StopBrowse();
-}
-
-
-// CPrinterSetupWizardSheet message handlers
-
-void CPrinterSetupWizardSheet::Init(void)
-{
-	AddPage(&m_pgSecond);
-	AddPage(&m_pgThird);
-	AddPage(&m_pgFourth);
-
-	m_psh.dwFlags &= (~PSH_HASHELP);
-
-	m_psh.dwFlags |= PSH_WIZARD97|PSH_WATERMARK|PSH_HEADER;
-	m_psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
-	m_psh.pszbmHeader = MAKEINTRESOURCE(IDB_BANNER_ICON);
-
-	m_psh.hInstance = GetNonLocalizedResources();
-
-	SetWizardMode();
-}
-
-
-LRESULT
-CPrinterSetupWizardSheet::OnSocketEvent(WPARAM inWParam, LPARAM inLParam)
-{
-	if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
-    {
-		dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
-    }
-    else
-    {
-		SOCKET sock = (SOCKET) inWParam;
-
-		// iterate thru list
-		ServiceRefList::iterator begin = m_serviceRefList.begin();
-		ServiceRefList::iterator end   = m_serviceRefList.end();
-
-		while (begin != end)
-		{
-			DNSServiceRef ref = *begin++;
-
-			check(ref != NULL);
-
-			if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
-			{
-				DNSServiceProcessResult(ref);
-				break;
-			}
-		}
-	}
-
-	return ( 0 );
-}
-
-
-LRESULT
-CPrinterSetupWizardSheet::OnProcessEvent(WPARAM inWParam, LPARAM inLParam)
-{
-	DEBUG_UNUSED(inLParam);
-
-	m_driverThreadExitCode	=	(DWORD) inWParam;
-	m_driverThreadFinished	=	true;
-
-	return 0;
-}
-
-
-unsigned WINAPI
-CPrinterSetupWizardSheet::InstallDriverThread( LPVOID inParam )
-{	
-	Printer			*	printer = (Printer*) inParam;
-	DWORD				exitCode = 0;
-	DWORD				dwResult;
-	OSStatus			err;
-	STARTUPINFO			si;
-	PROCESS_INFORMATION pi;
-	BOOL				ok;
-
-	check( printer );
-	check( m_self );
-
-	//
-	// because we're calling endthreadex(), C++ objects won't be cleaned up
-	// correctly.  we'll nest the CString 'command' inside a block so
-	// that it's destructor will be invoked.
-	//
-	{
-		CString command;
-
-		ZeroMemory( &si, sizeof(si) );
-		si.cb = sizeof(si);
-		ZeroMemory( &pi, sizeof(pi) );
-
-		command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->modelName, (LPCTSTR) printer->infFileName );
-
-		ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
-		err = translate_errno( ok, errno_compat(), kUnknownErr );
-		require_noerr( err, exit );
-
-		dwResult = WaitForSingleObject( pi.hProcess, INFINITE );
-		translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr );
-		require_noerr( err, exit );
-
-		ok = GetExitCodeProcess( pi.hProcess, &exitCode );
-		err = translate_errno( ok, errno_compat(), kUnknownErr );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	//
-	// Close process and thread handles. 
-	//
-	if ( pi.hProcess )
-	{
-		CloseHandle( pi.hProcess );
-	}
-
-	if ( pi.hThread )
-	{
-		CloseHandle( pi.hThread );
-	}
-
-	//
-	// alert the main thread
-	//
-	m_self->PostMessage( WM_PROCESS_EVENT, err, exitCode );
-
-	_endthreadex_compat( 0 );
-
-	return 0;
-}
-
-
-void DNSSD_API
-CPrinterSetupWizardSheet::OnBrowse(
-							DNSServiceRef 			inRef,
-							DNSServiceFlags 		inFlags,
-							uint32_t 				inInterfaceIndex,
-							DNSServiceErrorType 	inErrorCode,
-							const char *			inName,	
-							const char *			inType,	
-							const char *			inDomain,	
-							void *					inContext )
-{
-	DEBUG_UNUSED(inRef);
-
-	CPrinterSetupWizardSheet	*	self;
-	bool							moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
-	CPropertyPage				*	active;
-	Printer						*	printer = NULL;
-	Service						*	service = NULL;
-	OSStatus						err = kNoErr;
-
-	require_noerr( inErrorCode, exit );
-
-	self = reinterpret_cast <CPrinterSetupWizardSheet*>( inContext );
-	require_quiet( self, exit );
-
-	active = self->GetActivePage();
-	require_quiet( active, exit );
-
-	// Have we seen this printer before?
-
-	printer = self->Lookup( inName );
-
-	if ( printer )
-	{
-		service = printer->LookupService( inType );
-	}
-
-	if ( inFlags & kDNSServiceFlagsAdd )
-	{
-		BOOL newPrinter = FALSE;
-
-		if ( !printer )
-		{
-			printer = self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
-			require_action( printer, exit, err = kUnknownErr );
-			newPrinter = TRUE;
-		}
-		
-		// If we're looking at the browse list on page 2, then we need to call
-		// CPage2::OnAddPrinter() regardless of whether we've seen the printer
-		// or not because the moreComing flag might have changed from a previous
-		// call. If we only call CPage2::OnAddPrinter() when there's a new printer,
-		// we might not correctly update our UI, so if we've seen the printer before,
-		// call OnAddPrinter with a NULL parameter.
-
-		if ( self->GetActivePage() == &self->m_pgSecond )
-		{
-			self->m_pgSecond.OnAddPrinter( newPrinter ? printer : NULL, moreComing );
-		}
-
-		if ( !service )
-		{
-			err = self->OnAddService( printer, inInterfaceIndex, inName, inType, inDomain );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			service->refs++;
-		}
-	}
-	else if ( printer )
-	{
-		check( service );
-
-		err = self->OnRemoveService( service );
-		require_noerr( err, exit );
-
-		if ( printer->services.size() == 0 )
-		{
-			err = self->OnRemovePrinter( printer, moreComing );
-			require_noerr( err, exit );
-		}
-	}
-
-exit:
-	
-	return;
-}
-
-
-void DNSSD_API
-CPrinterSetupWizardSheet::OnResolve(
-								DNSServiceRef			inRef,
-								DNSServiceFlags			inFlags,
-								uint32_t				inInterfaceIndex,
-								DNSServiceErrorType		inErrorCode,
-								const char *			inFullName,	
-								const char *			inHostName, 
-								uint16_t 				inPort,
-								uint16_t 				inTXTSize,
-								const char *			inTXT,
-								void *					inContext )
-{
-	DEBUG_UNUSED(inFullName);
-	DEBUG_UNUSED(inInterfaceIndex);
-	DEBUG_UNUSED(inFlags);
-	DEBUG_UNUSED(inRef);
-
-	CPrinterSetupWizardSheet	*	self;
-	Service						*	service;
-	Queue						*	q;
-	int								idx;
-	OSStatus						err;
-
-	require_noerr( inErrorCode, exit );
-
-	service = reinterpret_cast<Service*>( inContext );
-	require_quiet( service, exit);
-
-	check( service->refs != 0 );
-
-	self = service->printer->window;
-	require_quiet( self, exit );
-
-	err = self->StopOperation( service->serviceRef );
-	require_noerr( err, exit );
-	
-	//
-	// hold on to the hostname...
-	//
-	err = UTF8StringToStringObject( inHostName, service->hostname );
-	require_noerr( err, exit );
-
-	//
-	// <rdar://problem/3739200> remove the trailing dot on hostname
-	//
-	idx = service->hostname.ReverseFind('.');
-
-	if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx))
-	{
-		service->hostname.Delete(idx, 1);
-	}
-
-	//
-	// hold on to the port
-	//
-	service->portNumber = ntohs(inPort);
-
-	if ( service->qtotal == 1 )
-	{	
-		//
-		// create a new queue
-		//
-		try
-		{
-			q = new Queue;
-		}
-		catch (...)
-		{
-			q = NULL;
-		}
-
-		require_action( q, exit, err = E_OUTOFMEMORY );
-
-		//
-		// parse the text record.
-		//
-
-		err = self->ParseTextRecord( service, q, inTXTSize, inTXT );
-		require_noerr( err, exit );
-
-		service->queues.push_back( q );
-
-		//
-		// we've completely resolved this service
-		//
-
-		self->OnResolveService( service );
-	}
-	else
-	{
-		//
-		// if qtotal is more than 1, then we need to get additional
-		// text records.  if not, then this service is considered
-		// resolved
-		//
-
-		err = DNSServiceQueryRecord(&service->serviceRef, 0, inInterfaceIndex, inFullName, kDNSServiceType_TXT, kDNSServiceClass_IN, OnQuery, (void*) service );
-		require_noerr( err, exit );
-
-		err = self->StartOperation( service->serviceRef );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CPrinterSetupWizardSheet::OnQuery(
-							DNSServiceRef		inRef, 
-							DNSServiceFlags		inFlags, 
-							uint32_t			inInterfaceIndex, 
-							DNSServiceErrorType inErrorCode,
-							const char		*	inFullName, 
-							uint16_t			inRRType, 
-							uint16_t			inRRClass, 
-							uint16_t			inRDLen, 
-							const void		*	inRData, 
-							uint32_t			inTTL, 
-							void			*	inContext)
-{
-	DEBUG_UNUSED( inTTL );
-	DEBUG_UNUSED( inRRClass );
-	DEBUG_UNUSED( inRRType );
-	DEBUG_UNUSED( inFullName );
-	DEBUG_UNUSED( inInterfaceIndex );
-	DEBUG_UNUSED( inRef );
-
-	Service						*	service = NULL;
-	Queue						*	q;
-	CPrinterSetupWizardSheet	*	self;
-	OSStatus						err = kNoErr;
-
-	require_noerr( inErrorCode, exit );
-
-	service = reinterpret_cast<Service*>( inContext );
-	require_quiet( service, exit);
-
-	self = service->printer->window;
-	require_quiet( self, exit );
-
-	if ( ( inFlags & kDNSServiceFlagsAdd ) && ( inRDLen > 0 ) && ( inRData != NULL ) )
-	{
-		const char * inTXT = ( const char * ) inRData;
-
-		//
-		// create a new queue
-		//
-		try
-		{
-			q = new Queue;
-		}
-		catch (...)
-		{
-			q = NULL;
-		}
-
-		require_action( q, exit, err = E_OUTOFMEMORY );
-
-		err = service->printer->window->ParseTextRecord( service, q, inRDLen, inTXT );
-		require_noerr( err, exit );
-
-		//
-		// add this queue
-		//
-
-		service->queues.push_back( q );
-
-		if ( service->queues.size() == service->qtotal )
-		{
-			//
-			// else if moreComing is not set, then we're going
-			// to assume that we're done
-			//
-
-			self->StopOperation( service->serviceRef );
-
-			//
-			// sort the queues
-			//
-
-			service->queues.sort( OrderQueueFunc );
-
-			//
-			// we've completely resolved this service
-			//
-
-			self->OnResolveService( service );
-		}
-	}
-
-exit:
-
-	if ( err && service && ( service->serviceRef != NULL ) )
-	{
-		service->printer->window->StopOperation( service->serviceRef );
-	}
-
-	return;
-}
-
-
-Printer*
-CPrinterSetupWizardSheet::OnAddPrinter(
-								uint32_t 		inInterfaceIndex,
-								const char *	inName,	
-								const char *	inType,	
-								const char *	inDomain,
-								bool			moreComing)
-{
-	Printer	*	printer = NULL;
-	DWORD		printerNameCount;
-	OSStatus	err;
-
-	DEBUG_UNUSED( inInterfaceIndex );
-	DEBUG_UNUSED( inType );
-	DEBUG_UNUSED( inDomain );
-	DEBUG_UNUSED( moreComing );
-
-	try
-	{
-		printer = new Printer;
-	}
-	catch (...)
-	{
-		printer = NULL;
-	}
-
-	require_action( printer, exit, err = E_OUTOFMEMORY );
-
-	printer->window		=	this;
-	printer->name		=	inName;
-	
-	err = UTF8StringToStringObject(inName, printer->displayName);
-	check_noerr( err );
-	printer->actualName	=	printer->displayName;
-	printer->installed	=	false;
-	printer->deflt		=	false;
-	printer->resolving	=	0;
-
-	// Compare this name against printers that are already installed
-	// to avoid name clashes.  Rename as necessary
-	// to come up with a unique name.
-
-	printerNameCount = 2;
-
-	for (;;)
-	{
-		CPrinterSetupWizardSheet::PrinterNames::iterator it;
-
-		// <rdar://problem/4141221> Don't use find to do comparisons because we need to
-		// do a case insensitive string comparison
-
-		for ( it = m_printerNames.begin(); it != m_printerNames.end(); it++ )
-		{
-			if ( (*it).CompareNoCase( printer->actualName ) == 0 )
-			{
-				break;
-			}
-		}
-
-		if (it != m_printerNames.end())
-		{
-			printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
-		}
-		else
-		{
-			break;
-		}
-
-		printerNameCount++;
-	}
-
-	m_printers.push_back( printer );
-
-exit:
-
-	return printer;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::OnAddService(
-								Printer		*	printer,
-								uint32_t 		inInterfaceIndex,
-								const char	*	inName,	
-								const char	*	inType,	
-								const char	*	inDomain)
-{
-	Service	*	service = NULL;
-	OSStatus	err     = kNoErr;
-
-	DEBUG_UNUSED( inName );
-	DEBUG_UNUSED( inDomain );
-
-	try
-	{
-		service = new Service;
-	}
-	catch (...)
-	{
-		service = NULL;
-	}
-
-	require_action( service, exit, err = E_OUTOFMEMORY );
-	
-	service->printer	=	printer;
-	service->ifi		=	inInterfaceIndex;
-	service->type		=	inType;
-	service->domain		=	inDomain;
-	service->qtotal		=	1;
-	service->refs		=	1;
-	service->serviceRef	=	NULL;
-
-	printer->services.push_back( service );
-
-	//
-	// if the printer is selected, then we'll want to start a
-	// resolve on this guy
-	//
-
-	if ( printer == m_selectedPrinter )
-	{
-		StartResolve( service );
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::OnRemovePrinter( Printer * printer, bool moreComing )
-{
-	CPropertyPage	*	active	= GetActivePage();
-	OSStatus			err		= kNoErr;
-
-	if ( active == &m_pgSecond )
-	{
-		m_pgSecond.OnRemovePrinter( printer, moreComing );
-	}
-
-	m_printers.remove( printer );
-
-	if ( m_selectedPrinter == printer )
-	{
-		m_selectedPrinter = NULL;
-
-		if ( ( active == &m_pgThird ) || ( active == &m_pgFourth ) )
-		{
-			CString caption;
-			CString message;
-
-			caption.LoadString( IDS_ERROR_CAPTION );
-			message.LoadString( IDS_PRINTER_UNAVAILABLE );
-
-			MessageBox(message, caption, MB_OK|MB_ICONEXCLAMATION);
-
-			SetActivePage( &m_pgSecond );
-		}
-	}
-
-	delete printer;
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::OnRemoveService( Service * service )
-{
-	OSStatus err = kNoErr;
-
-	if ( service && ( --service->refs == 0 ) )
-	{
-		if ( service->serviceRef != NULL )
-		{
-			err = StopResolve( service );
-			require_noerr( err, exit );
-		}
-
-		service->printer->services.remove( service );
-
-		delete service;
-	}
-
-exit:
-
-	return err;	
-}
-
-
-void
-CPrinterSetupWizardSheet::OnResolveService( Service * service )
-{
-	// Make sure that the active page is page 2
-
-	require_quiet( GetActivePage() == &m_pgSecond, exit );
-
-	if ( !--service->printer->resolving )
-	{
-		// sort the services now.  we want the service that
-		// has the highest priority queue to be first in
-		// the list.
-
-		service->printer->services.sort( OrderServiceFunc );
-
-		// Now we can hit next
-
-		SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
-	
-		// Reset the cursor	
-		
-		m_active = m_arrow;
-
-		// And tell page 2 about it
-
-		m_pgSecond.OnResolveService( service );
-	}		
-
-exit:
-
-	return;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StartBrowse()
-{
-	OSStatus err;
-
-	//
-	// setup the DNS-SD browsing
-	//
-	err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLServiceType, NULL, OnBrowse, this );
-	require_noerr( err, exit );
-
-	err = StartOperation( m_pdlBrowser );
-	require_noerr( err, exit );
-
-	err = DNSServiceBrowse( &m_lprBrowser, 0, 0, kLPRServiceType, NULL, OnBrowse, this );
-	require_noerr( err, exit );
-
-	err = StartOperation( m_lprBrowser );
-	require_noerr( err, exit );
-
-	err = DNSServiceBrowse( &m_ippBrowser, 0, 0, kIPPServiceType, NULL, OnBrowse, this );
-	require_noerr( err, exit );
-
-	err = StartOperation( m_ippBrowser );
-	require_noerr( err, exit );
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StopBrowse()
-{
-	OSStatus err;
-
-	err = StopOperation( m_pdlBrowser );
-	require_noerr( err, exit );
-
-	err = StopOperation( m_lprBrowser );
-	require_noerr( err, exit );
-
-	err = StopOperation( m_ippBrowser );
-	require_noerr( err, exit );
-
-	while ( m_printers.size() > 0 )
-	{
-		Printer * printer = m_printers.front();
-
-		m_printers.pop_front();
-
-		if ( printer->resolving )
-		{
-			StopResolve( printer );
-		}
-
-		delete printer;
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StartResolve( Printer * printer )
-{
-	OSStatus			err = kNoErr;
-	Services::iterator	it;
-
-	check( printer );
-
-	for ( it = printer->services.begin(); it != printer->services.end(); it++ )
-	{
-		if ( (*it)->serviceRef == NULL )
-		{
-			err = StartResolve( *it );
-			require_noerr( err, exit );
-		}
-	}
-
-	m_selectedPrinter = printer;
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StartResolve( Service * service )
-{
-	OSStatus err = kNoErr;
-
-	check( service->serviceRef == NULL );
-
-	//
-	// clean out any queues that were collected during a previous
-	// resolve
-	//
-
-	service->EmptyQueues();
-
-	//
-	// now start the new resolve
-	//
-
-	err = DNSServiceResolve( &service->serviceRef, 0, 0, service->printer->name.c_str(), service->type.c_str(), service->domain.c_str(), (DNSServiceResolveReply) OnResolve, service );
-	require_noerr( err, exit );
-
-	err = StartOperation( service->serviceRef );
-	require_noerr( err, exit );
-
-	//
-	// If we're not currently resolving, then disable the next button
-	// and set the cursor to hourglass
-	//
-
-	if ( !service->printer->resolving )
-	{
-		SetWizardButtons( PSWIZB_BACK );
-
-		m_active = m_wait;
-		SetCursor(m_active);
-	}
-
-	service->printer->resolving++;
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StopResolve(Printer * printer)
-{
-	OSStatus err = kNoErr;
-
-	check( printer );
-
-	Services::iterator it;
-
-	for ( it = printer->services.begin(); it != printer->services.end(); it++ )
-	{
-		if ( (*it)->serviceRef )
-		{
-			err = StopResolve( *it );
-			require_noerr( err, exit );
-		}
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StopResolve( Service * service )
-{
-	OSStatus err;
-
-	check( service->serviceRef );
-
-	err = StopOperation( service->serviceRef );
-	require_noerr( err, exit );
-
-	service->printer->resolving--;
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StartOperation( DNSServiceRef ref )
-{
-	OSStatus err;
-
-	err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SOCKET_EVENT, FD_READ|FD_CLOSE);
-	require_noerr( err, exit );
-
-	m_serviceRefList.push_back( ref );
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::StopOperation( DNSServiceRef & ref )
-{
-	OSStatus err = kNoErr;
-
-	if ( ref )
-	{
-		m_serviceRefList.remove( ref );
-
-		if ( IsWindow( m_hWnd ) )
-		{
-			err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 );
-			require_noerr( err, exit );
-		}
-
-		DNSServiceRefDeallocate( ref );
-		ref = NULL;
-	}
-
-exit:
-
-	return err;
-}
-
-
-OSStatus
-CPrinterSetupWizardSheet::ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT )
-{
-	check( service );
-	check( q );
-
-	// <rdar://problem/3946587> Use TXTRecord APIs declared in dns_sd.h
-	
-	bool			qtotalDefined	= false;
-	const void	*	val;
-	char			buf[256];
-	uint8_t			len;
-	OSStatus		err				= kNoErr;
-
-	// <rdar://problem/3987680> Default to queue "lp"
-
-	q->name = L"lp";
-
-	// <rdar://problem/4003710> Default pdl key to be "application/postscript"
-
-	q->pdl = L"application/postscript";
-
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "rp", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->name );
-		require_noerr( err, exit );
-	}
-	
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "pdl", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->pdl );
-		require_noerr( err, exit );
-	}
-	
-	if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mfg", &len ) ) != NULL ) ||
-	     ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_manufacturer", &len ) ) != NULL ) )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->usb_MFG );
-		require_noerr( err, exit );
-	}
-	
-	if ( ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_mdl", &len ) ) != NULL ) ||
-	     ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "usb_model", &len ) ) != NULL ) )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->usb_MDL );
-		require_noerr( err, exit );
-	}
-
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "ty", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->description );
-		require_noerr( err, exit );
-	}
-		
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "product", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->product );
-		require_noerr( err, exit );
-	}
-
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "note", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		err = UTF8StringToStringObject( buf, q->location );
-		require_noerr( err, exit );
-	}
-
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "qtotal", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		service->qtotal = (unsigned short) atoi( buf );
-		qtotalDefined = true;
-	}
-
-	if ( ( val = TXTRecordGetValuePtr( inTXTSize, inTXT, "priority", &len ) ) != NULL )
-	{
-		// Stringize val ( doesn't have trailing '\0' yet )
-
-		memcpy( buf, val, len );
-		buf[len] = '\0';
-
-		q->priority = atoi( buf );
-	}
-
-	// <rdar://problem/4124524> Was this printer discovered via OS X Printer Sharing?
-
-	if ( TXTRecordContainsKey( inTXTSize, inTXT, "printer-state" ) || TXTRecordContainsKey( inTXTSize, inTXT, "printer-type" ) )
-	{
-		service->printer->isCUPSPrinter = true;
-	}
-
-exit:
-
-	// The following code is to fix a problem with older HP 
-	// printers that don't include "qtotal" in their text
-	// record.  We'll check to see if the q->name is "TEXT"
-	// and if so, we're going to modify it to be "lp" so
-	// that we don't use the wrong queue
-
-	if ( !err && !qtotalDefined && ( q->name == L"TEXT" ) )
-	{
-		q->name = "lp";
-	}
-
-	return err;
-}
-
-
-Printer*
-CPrinterSetupWizardSheet::Lookup(const char * inName)
-{
-	check( inName );
-
-	Printer			*	printer = NULL;
-	Printers::iterator	it;
-
-	for ( it = m_printers.begin(); it != m_printers.end(); it++ )
-	{
-		if ( (*it)->name == inName )
-		{
-			printer = *it;
-			break;
-		}
-	}
-
-	return printer;
-}
-
-
-bool
-CPrinterSetupWizardSheet::OrderServiceFunc( const Service * a, const Service * b )
-{
-	Queue * q1, * q2;
-
-	q1 = (a->queues.size() > 0) ? a->queues.front() : NULL;
-
-	q2 = (b->queues.size() > 0) ? b->queues.front() : NULL;
-
-	if ( !q1 && !q2 )
-	{
-		return true;
-	}
-	else if ( q1 && !q2 )
-	{
-		return true;
-	}
-	else if ( !q1 && q2 )
-	{
-		return false;
-	}
-	else if ( q1->priority < q2->priority )
-	{
-		return true;
-	}
-	else if ( q1->priority > q2->priority )
-	{
-		return false;
-	}
-	else if ( ( a->type == kPDLServiceType ) || ( ( a->type == kLPRServiceType ) && ( b->type == kIPPServiceType ) ) )
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-
-bool
-CPrinterSetupWizardSheet::OrderQueueFunc( const Queue * q1, const Queue * q2 )
-{
-	return ( q1->priority <= q2->priority ) ? true : false;
-}
-
-
-
diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h
deleted file mode 100644
index 4511043..0000000
--- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-
-#include "secondpage.h"
-#include "thirdpage.h"
-#include "fourthpage.h"
-#include "UtilTypes.h"
-#include "Logger.h"
-#include "dns_sd.h"
-#include <stdexcept>
-#include <map>
-
-using namespace PrinterSetupWizard;
-
-// CPrinterSetupWizardSheet
-
-class CPrinterSetupWizardSheet : public CPropertySheet
-{
-DECLARE_DYNAMIC(CPrinterSetupWizardSheet)
-
-public:
-
-struct WizardException
-{
-    CString text;
-    CString caption;
-};
-
-public:
-
-CPrinterSetupWizardSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
-virtual ~CPrinterSetupWizardSheet();
-
-CPropertyPage*
-GetLastPage();
-
-void
-SetLastPage(CPropertyPage * page );
-
-void
-SetSelectedPrinter(Printer * printer);
-
-Printer*
-GetSelectedPrinter();
-
-OSStatus
-LoadPrinterDriver(const CString & filename);
-
-HCURSOR
-GetCursor();
-
-//
-// handles end of process event
-//
-virtual LRESULT
-OnProcessEvent(WPARAM inWParam, LPARAM inLParam);
-
-virtual LRESULT
-OnSocketEvent(WPARAM inWParam, LPARAM inLParam);
-
-virtual BOOL
-OnCommand(WPARAM wParam, LPARAM lParam);
-
-virtual BOOL
-OnInitDialog();
-
-virtual BOOL
-OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message);
-
-virtual void
-OnContextMenu(CWnd * pWnd, CPoint pos);
-
-afx_msg void
-OnOK();
-
-OSStatus
-StartResolve( Printer * printer );
-
-OSStatus
-StopResolve( Printer * printer );
-
-Printers m_printers;
-
-HCURSOR m_active;
-HCURSOR m_arrow;
-HCURSOR m_wait;
-
-protected:
-DECLARE_MESSAGE_MAP()
-CSecondPage m_pgSecond;
-CThirdPage m_pgThird;
-CFourthPage m_pgFourth;
-
-void
-OnServiceResolved(
-    Service             *   service);
-
-void Init(void);
-
-private:
-
-// This is from <cups/http.h>
-typedef enum http_encryption_e          /**** HTTP encryption values ****/
-{
-    HTTP_ENCRYPT_IF_REQUESTED,          /* Encrypt if requested (TLS upgrade) */
-    HTTP_ENCRYPT_NEVER,             /* Never encrypt */
-    HTTP_ENCRYPT_REQUIRED,          /* Encryption is required (TLS upgrade) */
-    HTTP_ENCRYPT_ALWAYS             /* Always encrypt (SSL) */
-} http_encryption_t;
-
-typedef void*               ( *httpConnectEncryptFunc )( const char* host, int port, http_encryption_t encryption );
-typedef http_encryption_t ( *cupsEncryptionFunc )( void );
-typedef void ( *cupsSetEncryptionFunc )( http_encryption_t e );
-typedef char*               ( *cupsAdminCreateWindowsPPDFunc )( void * http, const char *dest, char *buffer, int bufsize );
-
-class CUPSLibrary
-{
-public:
-
-CUPSLibrary()
-    :
-    httpConnectEncrypt( NULL ),
-    cupsEncryption( NULL ),
-    cupsSetEncryption( NULL ),
-    cupsAdminCreateWindowsPPD( NULL ),
-    library( NULL )
-{
-#if defined( LIBCUPS_ENABLED )
-    if ( ( library = LoadLibrary( TEXT( "libcups2.dll" ) ) ) != NULL )
-    {
-        httpConnectEncrypt = ( httpConnectEncryptFunc ) GetProcAddress( library, "httpConnectEncrypt" );
-        cupsEncryption = ( cupsEncryptionFunc ) GetProcAddress( library, "cupsEncryption" );
-        cupsSetEncryption = ( cupsSetEncryptionFunc ) GetProcAddress( library, "cupsSetEncryption" );
-        cupsAdminCreateWindowsPPD = ( cupsAdminCreateWindowsPPDFunc ) GetProcAddress( library, "cupsAdminCreateWindowsPPD" );
-    }
-#endif
-}
-
-~CUPSLibrary()
-{
-    if ( library )
-    {
-        FreeLibrary( library );
-        library = NULL;
-    }
-}
-
-BOOL
-IsInstalled()
-{
-    return ( ( httpConnectEncrypt != NULL ) && ( cupsEncryption != NULL ) && ( cupsSetEncryption != NULL ) && ( cupsAdminCreateWindowsPPD != NULL ) );
-}
-
-httpConnectEncryptFunc httpConnectEncrypt;
-cupsEncryptionFunc cupsEncryption;
-cupsSetEncryptionFunc cupsSetEncryption;
-cupsAdminCreateWindowsPPDFunc cupsAdminCreateWindowsPPD;
-
-private:
-
-HMODULE library;
-};
-
-
-static void DNSSD_API
-OnBrowse(
-    DNSServiceRef inRef,
-    DNSServiceFlags inFlags,
-    uint32_t inInterfaceIndex,
-    DNSServiceErrorType inErrorCode,
-    const char *            inName,
-    const char *            inType,
-    const char *            inDomain,
-    void *                  inContext );
-
-static void DNSSD_API
-OnResolve(
-    DNSServiceRef inRef,
-    DNSServiceFlags inFlags,
-    uint32_t inInterfaceIndex,
-    DNSServiceErrorType inErrorCode,
-    const char *            inFullName,
-    const char *            inHostName,
-    uint16_t inPort,
-    uint16_t inTXTSize,
-    const char *            inTXT,
-    void *                  inContext );
-
-static void DNSSD_API
-OnQuery(
-    DNSServiceRef inRef,
-    DNSServiceFlags inFlags,
-    uint32_t inInterfaceIndex,
-    DNSServiceErrorType inErrorCode,
-    const char          *   inFullName,
-    uint16_t inRRType,
-    uint16_t inRRClass,
-    uint16_t inRDLen,
-    const void          *   inRData,
-    uint32_t inTTL,
-    void                *   inContext);
-
-Printer*
-OnAddPrinter(
-    uint32_t inInterfaceIndex,
-    const char          *   inName,
-    const char          *   inType,
-    const char          *   inDomain,
-    bool moreComing);
-
-OSStatus
-OnRemovePrinter(
-    Printer             *   printer,
-    bool moreComing);
-
-OSStatus
-OnAddService(
-    Printer             *   printer,
-    uint32_t inInterfaceIndex,
-    const char          *   inName,
-    const char          *   inType,
-    const char          *   inDomain);
-
-OSStatus
-OnRemoveService(
-    Service             *   service);
-
-void
-OnResolveService(
-    Service             *   service );
-
-static bool
-OrderServiceFunc( const Service * a, const Service * b );
-
-static bool
-OrderQueueFunc( const Queue * q1, const Queue * q2 );
-
-OSStatus
-StartOperation( DNSServiceRef ref );
-
-OSStatus
-StopOperation( DNSServiceRef & ref );
-
-OSStatus
-StartBrowse();
-
-OSStatus
-StopBrowse();
-
-OSStatus
-StartResolve( Service * service );
-
-OSStatus
-StopResolve( Service * service );
-
-OSStatus
-ParseTextRecord( Service * service, Queue * q, uint16_t inTXTSize, const char * inTXT );
-
-OSStatus
-LoadPrinterNames();
-
-Printer*
-Lookup( const char * name );
-
-OSStatus
-InstallPrinter(Printer * printer);
-
-OSStatus
-InstallPrinterPort( Printer * printer, Service * service, DWORD protocol, Logger & log );
-
-OSStatus
-InstallPrinterPDLAndLPR(Printer * printer, Service * service, Logger & log);
-
-OSStatus
-InstallPrinterIPP(Printer * printer, Service * service, Logger & log);
-
-OSStatus
-InstallPrinterCUPS( Printer * printer, Service * service, CUPSLibrary & cupsLib );
-
-OSStatus
-InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib, TCHAR * env );
-
-static unsigned WINAPI
-InstallDriverThread( LPVOID inParam );
-
-typedef std::list<CString>          PrinterNames;
-typedef std::list<DNSServiceRef>    ServiceRefList;
-static CPrinterSetupWizardSheet *   m_self;
-PrinterNames m_printerNames;
-Printer                         *   m_selectedPrinter;
-bool m_driverThreadFinished;
-DWORD m_driverThreadExitCode;
-ServiceRefList m_serviceRefList;
-DNSServiceRef m_pdlBrowser;
-DNSServiceRef m_lprBrowser;
-DNSServiceRef m_ippBrowser;
-DNSServiceRef m_resolver;
-
-CPropertyPage                   *   m_lastPage;
-};
-
-
-inline Printer*
-CPrinterSetupWizardSheet::GetSelectedPrinter()
-{
-    return m_selectedPrinter;
-}
-
-
-inline HCURSOR
-CPrinterSetupWizardSheet::GetCursor()
-{
-    return m_active;
-}
-
-
-inline CPropertyPage*
-CPrinterSetupWizardSheet::GetLastPage()
-{
-    return m_lastPage;
-}
-
-
-inline void
-CPrinterSetupWizardSheet::SetLastPage(CPropertyPage * lastPage)
-{
-    m_lastPage = lastPage;
-}
-
-
-// Service Types
-
-#define kPDLServiceType     "_pdl-datastream._tcp."
-#define kLPRServiceType     "_printer._tcp."
-#define kIPPServiceType     "_ipp._tcp."
diff --git a/Clients/PrinterSetupWizard/SecondPage.cpp b/Clients/PrinterSetupWizard/SecondPage.cpp
deleted file mode 100644
index 1521d0d..0000000
--- a/Clients/PrinterSetupWizard/SecondPage.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "SecondPage.h"
-#include "DebugServices.h"
-#include "WinServices.h"
-#include <winspool.h>
-
-// local variable is initialize but not referenced
-#pragma warning(disable:4189)
-
-// CSecondPage dialog
-
-IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
-CSecondPage::CSecondPage()
-	: CPropertyPage(CSecondPage::IDD)
-{
-	m_psp.dwFlags &= ~(PSP_HASHELP);
-	m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
-
-	m_psp.pszHeaderTitle	= MAKEINTRESOURCE(IDS_BROWSE_TITLE);
-	m_psp.pszHeaderSubTitle	= MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
-
-	m_emptyListItem		=	NULL;
-	m_initialized		=	false;
-	m_waiting			=	false;
-}
-
-
-CSecondPage::~CSecondPage()
-{
-}
-
-
-void
-CSecondPage::InitBrowseList()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	CString							text;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	// Initialize so that nothing is selected when we add to the list
-
-	psheet->SetSelectedPrinter( NULL );
-	m_gotChoice = false;
-	m_browseList.Select( NULL, TVGN_FIRSTVISIBLE );
-
-	//
-	// load the no printers message until something shows up in the browse list
-	//
-	text.LoadString(IDS_NO_PRINTERS);
-
-	LoadTextAndDisableWindow( text );
-
-	//
-	// disable the next button until there's a printer to select
-	//
-	psheet->SetWizardButtons(PSWIZB_BACK);
-
-	//
-	// disable the printer information box
-	//
-	SetPrinterInformationState( FALSE );
-	m_descriptionField.SetWindowText( L"" );
-	m_locationField.SetWindowText( L"" );
-
-exit:
-
-	return;
-}
-
-
-void CSecondPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
-	DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
-
-	DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
-
-	DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
-
-	DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
-
-	DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
-
-}
-
-
-afx_msg BOOL
-CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
-{
-	DEBUG_UNUSED(pWnd);
-	DEBUG_UNUSED(nHitTest);
-	DEBUG_UNUSED(message);
-
-	CPrinterSetupWizardSheet * psheet;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	SetCursor(psheet->GetCursor());
-
-exit:
-
-	return TRUE;
-}
-
-
-BOOL
-CSecondPage::OnSetActive()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-	CWnd						*	pWnd;
-	Printers::iterator				it;
-	OSStatus						err = kNoErr;
-	BOOL							b;
-
-	b = CPropertyPage::OnSetActive();
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_action( psheet, exit, err = kUnknownErr );
-
-	// Stash the selected printer if any
-
-	printer = psheet->GetSelectedPrinter();
-
-	// initialize the browse list...this will remove everything currently
-	// in it, and add the no printers item
-
-	InitBrowseList();
-
-	// Populate the list with any printers that we currently know about
-
-	for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
-	{
-		OnAddPrinter( *it, false );
-	}
-
-	if ( ( !printer && ( psheet->m_printers.size() > 0 ) ) || ( printer != psheet->GetSelectedPrinter() ) )
-	{
-		if ( !printer )
-		{
-			printer = psheet->m_printers.front();
-		}
-
-		psheet->SetSelectedPrinter( printer );
-	}
-	
-	if ( printer )
-	{
-		m_browseList.SelectItem( printer->item );
-		::SetFocus( m_browseList );
-	}
-
-	// Hide the back button
-	pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);
-	if ( pWnd != NULL )
-	{
-		pWnd->ShowWindow(SW_HIDE);
-	}
-
-exit:
-
-	return b;
-}
-
-
-BOOL
-CSecondPage::OnKillActive()
-{
-	CPrinterSetupWizardSheet	* psheet;
-	CWnd						* pWnd;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );   
-   
-	psheet->SetLastPage(this);
-
-	// Show the back button
-	pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);
-	if ( pWnd != NULL )
-	{
-		pWnd->ShowWindow(SW_SHOW);
-	}
-
-exit:
-
-	return CPropertyPage::OnKillActive();
-}
-
-
-BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
-	ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
-	ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
-	ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
-	ON_WM_SETCURSOR()
-END_MESSAGE_MAP()
-
-
-// Printer::EventHandler implementation
-OSStatus
-CSecondPage::OnAddPrinter(
-					Printer	*	printer,
-					bool		moreComing )
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	selectedPrinter;
-	OSStatus						err = kNoErr;
-
-	check( IsWindow( m_hWnd ) );
-
-	m_browseList.SetRedraw(FALSE);
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	if ( printer )
-	{
-		selectedPrinter = psheet->GetSelectedPrinter();
-
-		printer->item = m_browseList.InsertItem(printer->displayName);
-
-		m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
-
-		m_browseList.SortChildren(TVI_ROOT);
-
-		//
-		// if the searching item is still in the list
-		// get rid of it
-		//
-		// note that order is important here.  Insert the printer
-		// item before removing the placeholder so we always have
-		// an item in the list to avoid experiencing the bug
-		// in Microsoft's implementation of CTreeCtrl
-		//
-		if (m_emptyListItem != NULL)
-		{
-			m_browseList.DeleteItem(m_emptyListItem);
-			m_emptyListItem = NULL;
-			m_browseList.EnableWindow(TRUE);
-		}
-
-		if ( !selectedPrinter )
-		{
-			psheet->SetSelectedPrinter( printer );
-			m_browseList.SelectItem( printer->item );
-			::SetFocus( m_browseList );
-		}
-	}
-
-exit:
-
-	if (!moreComing)
-	{
-		m_browseList.SetRedraw(TRUE);
-		m_browseList.Invalidate();
-	}
-
-	return err;
-}
-
-
-OSStatus
-CSecondPage::OnRemovePrinter(
-				Printer	*	printer,
-				bool		moreComing)
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	OSStatus						err = kNoErr;
-
-	check( IsWindow( m_hWnd ) );
-	check( printer );
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	m_browseList.SetRedraw(FALSE);
-
-	if ( printer )
-	{
-		//
-		// check to make sure if we're the only item in the control...i.e.
-		// the list size is 1.
-		//
-		if (m_browseList.GetCount() > 1)
-		{
-			//
-			// if we're not the only thing in the list, then
-			// simply remove it from the list
-			//
-			m_browseList.DeleteItem( printer->item );
-		}
-		else
-		{
-			//
-			// if we're the only thing in the list, then redisplay
-			// it with the no printers message
-			//
-			InitBrowseList();
-		}
-	}
-
-exit:
-
-	if ( !moreComing )
-	{
-		m_browseList.SetRedraw(TRUE);
-		m_browseList.Invalidate();
-	}
-
-	return err;
-}
-
-
-void
-CSecondPage::OnResolveService( Service * service )
-{
-	CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	check( service );
-
-	Queue *	q = service->SelectedQueue();
-
-	check( q );
-	
-
-	//
-	// and set it to selected
-	//
-
-	m_selectedName	= service->printer->name;
-
-	//
-	// and update the printer information box
-	//
-	SetPrinterInformationState( TRUE );
-
-	m_descriptionField.SetWindowText( q->description );
-	m_locationField.SetWindowText( q->location );
-
-	//
-	// reset the cursor
-	//
-
-	SetCursor(psheet->m_active);
-
-exit:
-
-	return;
-}
-
-
-void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
-{
-	LPNMTREEVIEW					pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-	int								err = 0;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_action( psheet, exit, err = kUnknownErr );
-
-	// The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
-	// we selected isn't passed through correctly to this callback routine.
-
-	if ( !m_gotChoice )
-	{
-		printer = psheet->GetSelectedPrinter();
-
-		// If we really haven't selected a printer, then re-select NULL and exit
-
-		if ( !printer )
-		{
-			m_browseList.SelectItem( NULL );
-
-			goto exit;
-		}
-
-		// If we already have selected a printer, fake like we've clicked on it, but only
-		// if the CTreeCtrl hasn't already selected it
-		
-		else if ( printer->item != m_browseList.GetSelectedItem() )
-		{
-			m_gotChoice = true;
-
-			m_browseList.SelectItem( printer->item );
-
-			goto exit;
-		}
-	}
-
-	HTREEITEM item = m_browseList.GetSelectedItem();
-	require_quiet( item, exit );
-
-	printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
-	require_quiet( printer, exit );
-
-	//
-	// this call will trigger a resolve.  When the resolve is complete,
-	// our OnResolve will be called.
-	//
-	err = psheet->StartResolve( printer );
-	require_noerr( err, exit );
-
-	//
-	// And clear out the printer information box
-	//
-	SetPrinterInformationState( FALSE );
-	m_descriptionField.SetWindowText(L"");
-	m_locationField.SetWindowText(L"");
-
-exit:
-
-	if (err != 0)
-	{
-		CString text;
-		CString caption;
-
-		text.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT);
-		caption.LoadString(IDS_ERROR_SELECTING_PRINTER_CAPTION);
-
-		MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
-	}
-
-	*pResult = 0;
-}
-
-
-void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
-{
-	DEBUG_UNUSED( pNMHDR );
-
-	m_gotChoice = true;
-
-	*pResult = 0;
-}
-
-
-void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
-{
-	DEBUG_UNUSED( pNMHDR );
-
-	m_gotChoice = true;
-
-	*pResult = 0;
-}
-
-
-void
-CSecondPage::LoadTextAndDisableWindow( CString & text )
-{
-	m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
-	m_browseList.SelectItem( NULL );
-
-	//
-	// this will remove everything else in the list...we might be navigating
-	// back to this window, and the browse list might have changed since
-	// we last displayed it.
-	//
-	if ( m_emptyListItem )
-	{
-		HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
-  
-		while ( item )
-		{
-			m_browseList.DeleteItem( item );
-			item = m_browseList.GetNextVisibleItem( m_emptyListItem );
-		}
-	}
-
-	m_browseList.EnableWindow( FALSE );
-}
-
-
-void
-CSecondPage::SetPrinterInformationState( BOOL state )
-{
-	m_printerInformation.EnableWindow( state );
-
-	m_descriptionLabel.EnableWindow( state );
-
-	m_descriptionField.EnableWindow( state );
-
-	m_locationLabel.EnableWindow( state );
-
-	m_locationField.EnableWindow( state );
-
-}
-
-
-
diff --git a/Clients/PrinterSetupWizard/SecondPage.h b/Clients/PrinterSetupWizard/SecondPage.h
deleted file mode 100644
index 3fb4c46..0000000
--- a/Clients/PrinterSetupWizard/SecondPage.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#include "PrinterSetupWizardSheet.h"
-#include "CommonServices.h"
-#include "UtilTypes.h"
-#include "afxcmn.h"
-#include "dns_sd.h"
-#include "afxwin.h"
-#include <map>
-
-using namespace PrinterSetupWizard;
-
-// CSecondPage dialog
-
-class CSecondPage : public CPropertyPage
-{
-DECLARE_DYNAMIC(CSecondPage)
-
-public:
-CSecondPage();
-virtual ~CSecondPage();
-
-// Dialog Data
-enum { IDD = IDD_SECOND_PAGE };
-
-protected:
-
-void         InitBrowseList();
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-afx_msg BOOL OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message);
-virtual BOOL OnSetActive();
-virtual BOOL OnKillActive();
-
-DECLARE_MESSAGE_MAP()
-
-public:
-
-HTREEITEM m_emptyListItem;
-bool m_selectOkay;
-CTreeCtrl m_browseList;
-bool m_initialized;
-bool m_waiting;
-
-afx_msg void    OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
-afx_msg void    OnNmClickBrowseList(NMHDR * pNMHDR, LRESULT * pResult);
-afx_msg void    OnTvnKeyDownBrowseList(NMHDR * pNMHDR, LRESULT * pResult );
-
-OSStatus
-OnAddPrinter(
-    Printer     *   printer,
-    bool moreComing);
-
-OSStatus
-OnRemovePrinter(
-    Printer     *   printer,
-    bool moreComing);
-
-void
-OnResolveService( Service * service );
-
-private:
-
-void
-LoadTextAndDisableWindow( CString & text );
-
-void
-SetPrinterInformationState( BOOL state );
-
-std::string m_selectedName;
-
-
-private:
-
-
-
-CStatic m_printerInformation;
-
-CStatic m_descriptionLabel;
-
-CStatic m_descriptionField;
-
-CStatic m_locationLabel;
-
-CStatic m_locationField;
-
-
-bool m_gotChoice;
-};
diff --git a/Clients/PrinterSetupWizard/ThirdPage.cpp b/Clients/PrinterSetupWizard/ThirdPage.cpp
deleted file mode 100644
index 6caf55c..0000000
--- a/Clients/PrinterSetupWizard/ThirdPage.cpp
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-#include "PrinterSetupWizardApp.h"
-#include "PrinterSetupWizardSheet.h"
-#include "ThirdPage.h"
-#include "tcpxcv.h"
-#include <dns_sd.h>
-#include <winspool.h>
-#include <setupapi.h>
-
-// local variable is initialize but not referenced
-#pragma warning(disable:4189)
-
-//
-// This is the printer description file that is shipped
-// with Windows XP and below
-//
-#define kNTPrintFile		L"inf\\ntprint.inf"
-
-//
-// Windows Vista ships with a set of prn*.inf files
-//
-#define kVistaPrintFiles	L"inf\\prn*.inf"
-
-//
-// These are pre-defined names for Generic manufacturer and model
-//
-#define kGenericManufacturer		L"Generic"
-#define kGenericText				L"Generic / Text Only"
-#define kGenericPostscript			L"Generic / Postscript"
-#define kGenericPCL					L"Generic / PCL"
-#define kPDLPostscriptKey			L"application/postscript"
-#define kPDLPCLKey					L"application/vnd.hp-pcl"
-#define kGenericPSColorDriver		L"HP Color LaserJet 4550 PS"
-#define kGenericPSDriver			L"HP LaserJet 4050 Series PS"
-#define kGenericPCLColorDriver		L"HP Color LaserJet 4550 PCL"
-#define kGenericPCLDriver			L"HP LaserJet 4050 Series PCL"
-
-
-// CThirdPage dialog
-
-IMPLEMENT_DYNAMIC(CThirdPage, CPropertyPage)
-CThirdPage::CThirdPage()
-	: CPropertyPage(CThirdPage::IDD),
-		m_manufacturerSelected( NULL ),
-		m_modelSelected( NULL ),
-		m_genericPostscript( NULL ),
-		m_genericPCL( NULL ),
-		m_initialized(false),
-		m_printerImage( NULL )
-{
-	static const int	bufferSize	= 32768;
-	TCHAR				windowsDirectory[bufferSize];
-	CString				header;
-	WIN32_FIND_DATA		findFileData;
-	HANDLE				findHandle;
-	CString				prnFiles;
-	CString				ntPrint;
-	OSStatus			err;
-	BOOL				ok;
-
-	m_psp.dwFlags &= ~(PSP_HASHELP);
-	m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
-	
-	m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_INSTALL_TITLE);
-	m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_INSTALL_SUBTITLE);
-
-	//
-	// load printers from ntprint.inf
-	//
-	ok = GetWindowsDirectory( windowsDirectory, bufferSize );
-	err = translate_errno( ok, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
- 
-	//
-	// <rdar://problem/4826126>
-	//
-	// If there are no *prn.inf files, we'll assume that the information
-	// is in ntprint.inf
-	//
-	prnFiles.Format( L"%s\\%s", windowsDirectory, kVistaPrintFiles );
-	findHandle = FindFirstFile( prnFiles, &findFileData );
- 
-	if ( findHandle != INVALID_HANDLE_VALUE )
-	{
-		CString absolute;
-
-		absolute.Format( L"%s\\inf\\%s", windowsDirectory, findFileData.cFileName );
-		err = LoadPrintDriverDefsFromFile( m_manufacturers, absolute, false );
-		require_noerr( err, exit );
-
-		while ( FindNextFile( findHandle, &findFileData ) )
-		{
-			absolute.Format( L"%s\\inf\\%s", windowsDirectory, findFileData.cFileName );
-			err = LoadPrintDriverDefsFromFile( m_manufacturers, absolute, false );
-			require_noerr( err, exit );
-		}
-
-		FindClose( findHandle );
-	}
-	else
-	{
-		ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile);
-		err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false );
-		require_noerr(err, exit);
-	}
-
-	//
-	// load printer drivers that have been installed on this machine
-	//
-	err = LoadPrintDriverDefs( m_manufacturers );
-	require_noerr(err, exit);
-
-	//
-	// load our own special generic printer defs
-	//
-	err = LoadGenericPrintDriverDefs( m_manufacturers );
-	require_noerr( err, exit );
-
-exit:
-
-	return;
-}
-
-
-void
-CThirdPage::FreeManufacturers( Manufacturers & manufacturers )
-{
-	for ( Manufacturers::iterator it = manufacturers.begin(); it != manufacturers.end(); it++ )
-	{
-		for ( Models::iterator it2 = it->second->models.begin(); it2 != it->second->models.end(); it2++ )
-		{
-			delete *it2;
-		}
-
-		delete it->second;
-	}
-}
-
-
-CThirdPage::~CThirdPage()
-{
-	FreeManufacturers( m_manufacturers );
-}
-
-// ----------------------------------------------------
-// SelectMatch
-//
-// SelectMatch will do all the UI work associated with
-// selected a manufacturer and model of printer.  It also
-// makes sure the printer object is update with the
-// latest settings
-//
-// ----------------------------------------------------
-void
-CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
-{
-	LVFINDINFO	info;
-	int			nIndex;
-
-	check( printer != NULL );
-	check( manufacturer != NULL );
-	check( model != NULL );
-
-	//
-	// select the manufacturer
-	//
-	info.flags	= LVFI_STRING;
-	info.psz	= manufacturer->name;
-
-	nIndex = m_manufacturerListCtrl.FindItem(&info);
-	
-	if (nIndex != -1)
-	{
-		m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
-		//
-		//<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-		//
-		AutoScroll(m_manufacturerListCtrl, nIndex);
-	}
-
-	//
-	// select the model
-	//
-	info.flags	= LVFI_STRING;
-	info.psz	= model->displayName;
-
-	nIndex = m_modelListCtrl.FindItem(&info);
-
-	if (nIndex != -1)
-	{
-		m_modelListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
-		AutoScroll( m_modelListCtrl, nIndex );
-
-		m_modelListCtrl.SetFocus();
-	}
-
-	CopyPrinterSettings( printer, service, manufacturer, model );
-}
-
-void
-CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
-{
-	PopulateUI( manufacturers );
-
-	SelectMatch( printer, service, manufacturer, model );
-}
-
-// --------------------------------------------------------
-// CopyPrinterSettings
-//
-// This function makes sure that the printer object has the
-// latest settings from the manufacturer and model objects
-// --------------------------------------------------------
-
-void
-CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model )
-{
-	DWORD portNameLen;
-
-	printer->manufacturer		=	manufacturer->name;
-	printer->displayModelName	=	model->displayName;
-	printer->modelName			=	model->name;
-	printer->driverInstalled	=	model->driverInstalled;
-	printer->infFileName		=	model->infFileName;
-
-	if ( service->type == kPDLServiceType )
-	{
-		printer->portName.Format(L"IP_%s.%d", static_cast<LPCTSTR>(service->hostname), service->portNumber);
-		service->protocol = L"Raw";
-	}
-	else if ( service->type == kLPRServiceType )
-	{
-		Queue * q = service->queues.front();
-		check( q );
-
-		if ( q->name.GetLength() > 0 )
-		{
-			printer->portName.Format(L"LPR_%s.%d.%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
-		}
-		else
-		{
-			printer->portName.Format(L"LPR_%s.%d", static_cast<LPCTSTR>(service->hostname), service->portNumber);
-		}
-
-		service->protocol = L"LPR";
-	}
-	else if ( service->type == kIPPServiceType )
-	{
-		Queue * q = service->queues.front();
-		check( q );
-
-		if ( q->name.GetLength() > 0 )
-		{
-			printer->portName.Format(L"http://%s:%d/%s", static_cast<LPCTSTR>(service->hostname), service->portNumber, static_cast<LPCTSTR>(q->name) );
-		}
-		else
-		{
-			printer->portName.Format(L"http://%s:%d/", static_cast<LPCTSTR>(service->hostname), service->portNumber );
-		}
-
-		service->protocol = L"IPP";
-	}
-
-	// If it's not an IPP printr, truncate the portName so that it's valid
-
-	if ( service->type != kIPPServiceType )
-	{
-		portNameLen = printer->portName.GetLength() + 1;
-		
-		if ( portNameLen > MAX_PORTNAME_LEN )
-		{
-			printer->portName.Delete( MAX_PORTNAME_LEN - 1, ( portNameLen - MAX_PORTNAME_LEN ) );
-		}
-	}
-}
-
-// --------------------------------------------------------
-// DefaultPrinterExists
-//
-// Checks to see if a default printer has been configured
-// on this machine
-// --------------------------------------------------------
-BOOL
-CThirdPage::DefaultPrinterExists()
-{
-	CPrintDialog dlg(FALSE);
-	
-	dlg.m_pd.Flags |= PD_RETURNDEFAULT;
-
-	return dlg.GetDefaults();
-}
-
-// --------------------------------------------------------
-// AutoScroll
-//
-// Ensure selected item is in middle of list
-// --------------------------------------------------------
-void
-CThirdPage::AutoScroll( CListCtrl & list, int nIndex )
-{
-	//
-	//<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-	//
-
-	int		top;
-	int		count;
-
-	list.EnsureVisible( nIndex, FALSE );
-	
-	top		= list.GetTopIndex();
-	count	= list.GetCountPerPage();
-
-	if ( ( nIndex == top ) || ( ( nIndex + 1 ) == ( top + count ) ) )
-	{
-		CRect	rect;
-		int		rows;
-		
-		rows = ( count / 2 );
-
-		if ( nIndex == top )
-		{
-			list.GetItemRect(0, rect, LVIR_BOUNDS);
-			list.Scroll( CPoint( 0, rows * rect.Height() * -1 ) );
-		}
-		else
-		{
-			list.GetItemRect(0, rect, LVIR_BOUNDS);
-			list.Scroll( CPoint( 0, rows * rect.Height() ) );
-		}
-	}
-}
-
-// ------------------------------------------------------
-// LoadPrintDriverDefsFromFile
-//
-// The only potentially opaque thing about this function is the
-// checkForDuplicateModels flag.  The problem here is that ntprint.inf
-// doesn't contain duplicate models, and it has hundreds of models
-// listed.  You wouldn't check for duplicates there.  But oftentimes,
-// loading different windows print driver files contain multiple
-// entries for the same printer.  You don't want the UI to display
-// the same printer multiple times, so in that case, you would ask
-// this function to check for multiple models.
-
-OSStatus
-CThirdPage::LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CString & filename, bool checkForDuplicateModels )
-{
-	HINF			handle	= INVALID_HANDLE_VALUE;
-	const TCHAR *	section = TEXT( "Manufacturer" );
-	LONG			sectionCount;
-	TCHAR			line[ 1000 ];
-	CString			klass;
-	INFCONTEXT		manufacturerContext;
-	BOOL			ok;
-	OSStatus		err		= 0;
-	
-	// Make sure we can open the file
-	handle = SetupOpenInfFile( filename, NULL, INF_STYLE_WIN4, NULL );
-	translate_errno( handle != INVALID_HANDLE_VALUE, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// Make sure it's a printer file
-	ok = SetupGetLineText( NULL, handle, TEXT( "Version" ), TEXT( "Class" ), line, sizeof( line ), NULL );
-	translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	klass = line;
-	require_action( klass == TEXT( "Printer" ), exit, err = kUnknownErr );
-
-	sectionCount = SetupGetLineCount( handle, section );
-	translate_errno( sectionCount != -1, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	memset( &manufacturerContext, 0, sizeof( manufacturerContext ) );
-			
-	for ( LONG i = 0; i < sectionCount; i++ )
-	{
-		Manufacturers::iterator	iter;
-		Manufacturer	*	manufacturer;
-		CString				manufacturerName;
-		CString				temp;
-		CStringList			modelSectionNameDecl;
-		CString				modelSectionName;
-		CString				baseModelName;
-		CString				model;
-		INFCONTEXT			modelContext;
-		LONG				modelCount;
-		POSITION			p;
-
-		if ( i == 0 )
-		{
-			ok = SetupFindFirstLine( handle, section, NULL, &manufacturerContext );
-			err = translate_errno( ok, GetLastError(), kUnknownErr );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			ok = SetupFindNextLine( &manufacturerContext, &manufacturerContext );
-			err = translate_errno( ok, GetLastError(), kUnknownErr );
-			require_noerr( err, exit );
-		}
-
-		ok = SetupGetStringField( &manufacturerContext, 0, line, sizeof( line ), NULL );
-		err = translate_errno( ok, GetLastError(), kUnknownErr );
-		require_noerr( err, exit );
-		manufacturerName = line;
-
-		ok = SetupGetLineText( &manufacturerContext, handle, NULL, NULL, line, sizeof( line ), NULL );
-		err = translate_errno( ok, GetLastError(), kUnknownErr );
-		require_noerr( err, exit );
-
-		// Try to find some model section name that has entries. Explanation of int file structure
-		// can be found at:
-		//
-		// <http://msdn.microsoft.com/en-us/library/ms794359.aspx>
-		Split( line, ',', modelSectionNameDecl );
-
-		p					= modelSectionNameDecl.GetHeadPosition();
-		modelSectionName	= modelSectionNameDecl.GetNext( p );
-		modelCount			= SetupGetLineCount( handle, modelSectionName );
-		baseModelName		= modelSectionName;
-		
-		while ( modelCount <= 0 && p )
-		{
-			CString targetOSVersion;
-
-			targetOSVersion		= modelSectionNameDecl.GetNext( p );
-			modelSectionName	= baseModelName + TEXT( "." ) + targetOSVersion;
-			modelCount			= SetupGetLineCount( handle, modelSectionName );
-		}
-
-		if ( modelCount > 0 )
-		{
-			manufacturerName = NormalizeManufacturerName( manufacturerName );
-
-			iter = manufacturers.find( manufacturerName );
-
-			if ( iter != manufacturers.end() )
-			{
-				manufacturer = iter->second;
-				require_action( manufacturer, exit, err = kUnknownErr );
-			}
-			else
-			{
-				try
-				{
-					manufacturer = new Manufacturer;
-				}
-				catch (...)
-				{
-					manufacturer = NULL;
-				}
-
-				require_action( manufacturer, exit, err = kNoMemoryErr );
-
-				manufacturer->name					= manufacturerName;
-				manufacturers[ manufacturerName ]	= manufacturer;
-			}
-
-			memset( &modelContext, 0, sizeof( modelContext ) );
-
-			for ( LONG j = 0; j < modelCount; j++ )
-			{
-				CString modelName;
-				Model * model;
-
-				if ( j == 0 )
-				{
-					ok = SetupFindFirstLine( handle, modelSectionName, NULL, &modelContext );
-					err = translate_errno( ok, GetLastError(), kUnknownErr );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					SetupFindNextLine( &modelContext, &modelContext );
-					err = translate_errno( ok, GetLastError(), kUnknownErr );
-					require_noerr( err, exit );
-				}
-
-				ok = SetupGetStringField( &modelContext, 0, line, sizeof( line ), NULL );
-				err = translate_errno( ok, GetLastError(), kUnknownErr );
-				require_noerr( err, exit );
-
-				modelName = line;
-
-				if (checkForDuplicateModels == true)
-				{
-					if ( MatchModel( manufacturer, ConvertToModelName( modelName ) ) != NULL )
-					{
-						continue;
-					}
-				}
-
-				//
-				// Stock Vista printer inf files embed guids in the model
-				// declarations for Epson printers. Let's ignore those.
-				//
-				if ( modelName.Find( TEXT( "{" ), 0 ) != -1 )
-				{
-					continue;
-				}
-
-				try
-				{
-					model = new Model;
-				}
-				catch (...)
-				{
-					model = NULL;
-				}
-
-				require_action( model, exit, err = kNoMemoryErr );
-
-				model->infFileName		=	filename;
-				model->displayName		=	modelName;
-				model->name				=	modelName;
-				model->driverInstalled	=	false;
-
-				manufacturer->models.push_back(model);
-			}
-		}
-	}
-
-exit:
-
-	if ( handle != INVALID_HANDLE_VALUE )
-	{
-		SetupCloseInfFile( handle );
-		handle = NULL;
-	}
-
-	return err;
-}
-
-
-// -------------------------------------------------------
-// LoadPrintDriverDefs
-//
-// This function is responsible for loading the print driver
-// definitions of all print drivers that have been installed
-// on this machine.
-// -------------------------------------------------------
-OSStatus
-CThirdPage::LoadPrintDriverDefs( Manufacturers & manufacturers )
-{
-	BYTE	*	buffer			=	NULL;
-	DWORD		bytesReceived	=	0;
-	DWORD		numPrinters		=	0;
-	OSStatus	err				=	0;
-	BOOL		ok;
-
-	//
-	// like a lot of win32 calls, we call this first to get the
-	// size of the buffer we need.
-	//
-	EnumPrinterDrivers(NULL, L"all", 6, NULL, 0, &bytesReceived, &numPrinters);
-
-	if (bytesReceived > 0)
-	{
-		try
-		{
-			buffer = new BYTE[bytesReceived];
-		}
-		catch (...)
-		{
-			buffer = NULL;
-		}
-	
-		require_action( buffer, exit, err = kNoMemoryErr );
-		
-		//
-		// this call gets the real info
-		//
-		ok = EnumPrinterDrivers(NULL, L"all", 6, buffer, bytesReceived, &bytesReceived, &numPrinters);
-		err = translate_errno( ok, errno_compat(), kUnknownErr );
-		require_noerr( err, exit );
-	
-		DRIVER_INFO_6 * info = (DRIVER_INFO_6*) buffer;
-	
-		for (DWORD i = 0; i < numPrinters; i++)
-		{
-			Manufacturer	*	manufacturer;
-			Model			*	model;
-			CString				name;
-	
-			//
-			// skip over anything that doesn't have a manufacturer field.  This
-			// fixes a bug that I noticed that occurred after I installed
-			// ProComm.  This program add a print driver with no manufacturer
-			// that screwed up this wizard.
-			//
-			if (info[i].pszMfgName == NULL)
-			{
-				continue;
-			}
-	
-			//
-			// look for manufacturer
-			//
-			Manufacturers::iterator iter;
-	
-			//
-			// save the name
-			//
-			name = NormalizeManufacturerName( info[i].pszMfgName );
-	
-			iter = manufacturers.find(name);
-	
-			if (iter != manufacturers.end())
-			{
-				manufacturer = iter->second;
-			}
-			else
-			{
-				try
-				{
-					manufacturer = new Manufacturer;
-				}
-				catch (...)
-				{
-					manufacturer = NULL;
-				}
-	
-				require_action( manufacturer, exit, err = kNoMemoryErr );
-	
-				manufacturer->name	=	name;
-	
-				manufacturers[name]	=	manufacturer;
-			}
-	
-			//
-			// now look to see if we have already seen this guy.  this could
-			// happen if we have already installed printers that are described
-			// in ntprint.inf.  the extant drivers will show up in EnumPrinterDrivers
-			// but we have already loaded their info
-			//
-			//
-			if ( MatchModel( manufacturer, ConvertToModelName( info[i].pName ) ) == NULL )
-			{
-				try
-				{
-					model = new Model;
-				}
-				catch (...)
-				{
-					model = NULL;
-				}
-	
-				require_action( model, exit, err = kNoMemoryErr );
-	
-				model->displayName		=	info[i].pName;
-				model->name				=	info[i].pName;
-				model->driverInstalled	=	true;
-	
-				manufacturer->models.push_back(model);
-			}
-		}
-	}
-
-exit:
-
-	if (buffer != NULL)
-	{
-		delete [] buffer;
-	}
-
-	return err;
-}
-
-// -------------------------------------------------------
-// LoadGenericPrintDriverDefs
-//
-// This function is responsible for loading polymorphic
-// generic print drivers defs.  The UI will read
-// something like "Generic / Postscript" and we can map
-// that to any print driver we want.
-// -------------------------------------------------------
-OSStatus
-CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers )
-{
-	Manufacturer		*	manufacturer;
-	Model				*	model;
-	Manufacturers::iterator	iter;
-	CString					psDriverName;
-	CString					pclDriverName;
-	OSStatus				err	= 0;
-
-	// <rdar://problem/4030388> Generic drivers don't do color
-
-	// First try and find our generic driver names
-
-	iter = m_manufacturers.find(L"HP");
-	require_action( iter != m_manufacturers.end(), exit, err = kUnknownErr );
-	manufacturer = iter->second;
-
-	// Look for Postscript
-
-	model = manufacturer->find( kGenericPSColorDriver );
-
-	if ( !model )
-	{
-		model = manufacturer->find( kGenericPSDriver );
-	}
-
-	if ( model )
-	{
-		psDriverName = model->name;
-	}
-
-	// Look for PCL
-	
-	model = manufacturer->find( kGenericPCLColorDriver );
-
-	if ( !model )
-	{
-		model = manufacturer->find( kGenericPCLDriver );
-	}
-
-	if ( model )
-	{
-		pclDriverName = model->name;
-	}
-
-	// If we found either a generic PS driver, or a generic PCL driver,
-	// then add them to the list
-
-	if ( psDriverName.GetLength() || pclDriverName.GetLength() )
-	{
-		// Try and find generic manufacturer if there is one
-
-		iter = manufacturers.find(L"Generic");
-		
-		if (iter != manufacturers.end())
-		{
-			manufacturer = iter->second;
-		}
-		else
-		{
-			try
-			{
-				manufacturer = new Manufacturer;
-			}
-			catch (...)
-			{
-				manufacturer = NULL;
-			}
-		
-			require_action( manufacturer, exit, err = kNoMemoryErr );
-		
-			manufacturer->name					=	"Generic";
-			manufacturers[manufacturer->name]	=	manufacturer;
-		}
-
-		if ( psDriverName.GetLength() > 0 )
-		{
-			try
-			{
-				m_genericPostscript = new Model;
-			}
-			catch (...)
-			{
-				m_genericPostscript = NULL;
-			}
-			
-			require_action( m_genericPostscript, exit, err = kNoMemoryErr );
-
-			m_genericPostscript->displayName		=	kGenericPostscript;
-			m_genericPostscript->name				=	psDriverName;
-			m_genericPostscript->driverInstalled	=	false;
-
-			manufacturer->models.push_back( m_genericPostscript );
-		}
-
-		if ( pclDriverName.GetLength() > 0 )
-		{
-			try
-			{
-				m_genericPCL = new Model;
-			}
-			catch (...)
-			{
-				m_genericPCL = NULL;
-			}
-			
-			require_action( m_genericPCL, exit, err = kNoMemoryErr );
-
-			m_genericPCL->displayName		=	kGenericPCL;
-			m_genericPCL->name				=	pclDriverName;
-			m_genericPCL->driverInstalled	=	false;
-
-			manufacturer->models.push_back( m_genericPCL );
-		}
-	}
-
-exit:
-
-	return err;
-}
-
-// ------------------------------------------------------
-// ConvertToManufacturerName
-//
-// This function is responsible for tweaking the
-// name so that subsequent string operations won't fail because
-// of capitalizations/different names for the same manufacturer
-// (i.e.  Hewlett-Packard/HP/Hewlett Packard)
-//
-CString
-CThirdPage::ConvertToManufacturerName( const CString & name )
-{
-	//
-	// first we're going to convert all the characters to lower
-	// case
-	//
-	CString lower = name;
-	lower.MakeLower();
-
-	//
-	// now we're going to check to see if the string says "hewlett-packard",
-	// because sometimes they refer to themselves as "hewlett-packard", and
-	// sometimes they refer to themselves as "hp".
-	//
-	if ( lower == L"hewlett-packard")
-	{
-		lower = "hp";
-	}
-
-	//
-	// tweak for Xerox Phaser, which doesn't announce itself
-	// as a xerox
-	//
-	else if ( lower.Find( L"phaser", 0 ) != -1 )
-	{
-		lower = "xerox";
-	}
-
-	return lower;
-}
-
-// ------------------------------------------------------
-// ConvertToModelName
-//
-// This function is responsible for ensuring that subsequent
-// string operations don't fail because of differing capitalization
-// schemes and the like
-// ------------------------------------------------------
-
-CString
-CThirdPage::ConvertToModelName( const CString & name )
-{
-	//
-	// convert it to lowercase
-	//
-	CString lower = name;
-	lower.MakeLower();
-
-	return lower;
-}
-
-// ------------------------------------------------------
-// NormalizeManufacturerName
-//
-// This function is responsible for tweaking the manufacturer
-// name so that there are no aliases for vendors
-//
-CString
-CThirdPage::NormalizeManufacturerName( const CString & name )
-{
-	CString normalized = name;
-
-	//
-	// now we're going to check to see if the string says "hewlett-packard",
-	// because sometimes they refer to themselves as "hewlett-packard", and
-	// sometimes they refer to themselves as "hp".
-	//
-	if ( normalized == L"Hewlett-Packard")
-	{
-		normalized = "HP";
-	}
-
-	return normalized;
-}
-
-// -------------------------------------------------------
-// MatchPrinter
-//
-// This function is responsible for matching a printer
-// to a list of manufacturers and models.  It calls
-// MatchManufacturer and MatchModel in turn.
-//
-
-OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service, bool useCUPSWorkaround)
-{
-	CString					normalizedProductName;
-	Manufacturer		*	manufacturer		=	NULL;
-	Manufacturer		*	genericManufacturer	=	NULL;
-	Model				*	model				=	NULL;
-	Model				*	genericModel		=	NULL;
-	bool					found				=	false;
-	CString					text;
-	OSStatus				err					=	kNoErr;
-
-	check( printer );
-	check( service );
-
-	Queue * q = service->SelectedQueue();
-
-	check( q );
-
-	//
-	// first look to see if we have a usb_MFG descriptor
-	//
-	if ( q->usb_MFG.GetLength() > 0)
-	{
-		manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->usb_MFG ) );
-	}
-
-	if ( manufacturer == NULL )
-	{
-		q->product.Remove('(');
-		q->product.Remove(')');
-
-		manufacturer = MatchManufacturer( manufacturers, ConvertToManufacturerName ( q->product ) );
-	}
-	
-	//
-	// if we found the manufacturer, then start looking for the model
-	//
-	if ( manufacturer != NULL )
-	{
-		if ( q->usb_MDL.GetLength() > 0 )
-		{
-			model = MatchModel ( manufacturer, ConvertToModelName ( q->usb_MDL ) );
-		}
-
-		if ( ( model == NULL ) && ( q->product.GetLength() > 0 ) )
-		{
-			q->product.Remove('(');
-			q->product.Remove(')');
-
-			model = MatchModel ( manufacturer, ConvertToModelName ( q->product ) );
-		}
-
-		if ( model != NULL )
-		{
-			// <rdar://problem/4124524> Offer Generic printers if printer advertises Postscript or PCL.  Workaround
-			// bug in OS X CUPS printer sharing by selecting Generic driver instead of matched printer.
- 
-			bool hasGenericDriver = false;
-
-			if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
-			{
-				hasGenericDriver = true;
-			}
-
-			// <rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS
-			// shared queue supports raw
-
-			if ( q->pdl.Find( L"application/octet-stream" ) != -1 )
-			{
-				useCUPSWorkaround = false;
-			}
-
-			if ( useCUPSWorkaround && printer->isCUPSPrinter && hasGenericDriver )
-			{
-				//
-				// <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
-				//
-				Manufacturers genericManufacturers;
-
-				LoadGenericPrintDriverDefs( genericManufacturers );
-
-				SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
-
-				FreeManufacturers( genericManufacturers );
-			}
-			else
-			{
-				SelectMatch(manufacturers, printer, service, manufacturer, model);
-			}
-
-			found = true;
-		}
-	}
-
-	//
-	// display a message to the user based on whether we could match
-	// this printer
-	//
-	if (found)
-	{
-		text.LoadString(IDS_PRINTER_MATCH_GOOD);
-		err = kNoErr;
-	}
-	else if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
-	{
-		if ( printer->isCUPSPrinter )
-		{
-			//
-			// <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
-			//
-			Manufacturers genericManufacturers;
-
-			LoadGenericPrintDriverDefs( genericManufacturers );
-
-			SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
-			
-			text.LoadString(IDS_PRINTER_MATCH_GOOD);
-
-			FreeManufacturers( genericManufacturers );
-		}
-		else
-		{
-			SelectMatch( manufacturers, printer, service, genericManufacturer, genericModel );
-			text.LoadString(IDS_PRINTER_MATCH_MAYBE);
-		}
-
-		err = kNoErr;
-	}
-	else
-	{
-		text.LoadString(IDS_PRINTER_MATCH_BAD);
-
-		//
-		// if there was any crud in this list from before, get rid of it now
-		//
-		m_modelListCtrl.DeleteAllItems();
-		
-		//
-		// select the manufacturer if we found one
-		//
-		if (manufacturer != NULL)
-		{
-			LVFINDINFO	info;
-			int			nIndex;
-
-			//
-			// select the manufacturer
-			//
-			info.flags	= LVFI_STRING;
-			info.psz	= manufacturer->name;
-
-			nIndex = m_manufacturerListCtrl.FindItem(&info);
-	
-			if (nIndex != -1)
-			{
-				m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
-
-				//
-				//<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-				//
-				AutoScroll(m_manufacturerListCtrl, nIndex);
-			}
-		}
-
-		err = kUnknownErr;
-	}
-
-	m_printerSelectionText.SetWindowText(text);
-
-	return err;
-}
-
-// ------------------------------------------------------
-// MatchManufacturer
-//
-// This function is responsible for finding a manufacturer
-// object from a string name.  It does a CString::Find, which
-// is like strstr, so it doesn't have to do an exact match
-//
-// If it can't find a match, NULL is returned
-// ------------------------------------------------------
-
-Manufacturer*
-CThirdPage::MatchManufacturer( Manufacturers & manufacturers, const CString & name)
-{
-	Manufacturers::iterator iter;
-
-	for (iter = manufacturers.begin(); iter != manufacturers.end(); iter++)
-	{
-		//
-		// we're going to convert all the manufacturer names to lower case,
-		// so we match the name passed in.
-		//
-		CString lower = iter->second->name;
-		lower.MakeLower();
-
-		//
-		// now try and find the lowered string in the name passed in.
-		//
-		if (name.Find(lower) != -1)
-		{
-			return iter->second;
-		}
-	}
-
-	return NULL;
-}
-
-// -------------------------------------------------------
-// MatchModel
-//
-// This function is responsible for matching a model from
-// a name.  It does a CString::Find(), which works like strstr,
-// so it doesn't rely on doing an exact string match.
-//
-
-Model*
-CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name)
-{
-	Models::iterator iter;
-
-	iter = manufacturer->models.begin();
-
-	for (iter = manufacturer->models.begin(); iter != manufacturer->models.end(); iter++)
-	{
-		Model * model = *iter;
-
-		//
-		// convert the model name to lower case
-		//
-		CString lowered = model->name;
-		lowered.MakeLower();
-
-		if (lowered.Find( name ) != -1)
-		{
-			return model;
-		}
-
-		//
-		// <rdar://problem/3841218>
-		// try removing the first substring and search again
-		//
-
-		if ( name.Find(' ') != -1 )
-		{
-			CString altered = name;
-			altered.Delete( 0, altered.Find(' ') + 1 );
-
-			if ( lowered.Find( altered ) != -1 )
-			{
-				return model;
-			}
-		}
-	}
-
-	return NULL;
-}
-
-// -------------------------------------------------------
-// MatchGeneric
-//
-// This function will attempt to find a generic printer
-// driver for a printer that we weren't able to match
-// specifically
-//
-BOOL
-CThirdPage::MatchGeneric( Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model )
-{
-	CString	pdl;
-	BOOL	ok = FALSE;
-
-	DEBUG_UNUSED( printer );
-
-	check( service );
-
-	Queue * q = service->SelectedQueue();
-
-	check( q );
-
-	Manufacturers::iterator iter = manufacturers.find( kGenericManufacturer );
-	require_action_quiet( iter != manufacturers.end(), exit, ok = FALSE );
-
-	*manufacturer = iter->second;
-
-	pdl = q->pdl;
-	pdl.MakeLower();
-
-	if ( m_genericPCL && ( pdl.Find( kPDLPCLKey ) != -1 ) )
-	{
-		*model	= m_genericPCL;
-		ok		= TRUE;
-	}
-	else if ( m_genericPostscript && ( pdl.Find( kPDLPostscriptKey ) != -1 ) )
-	{
-		*model	= m_genericPostscript;
-		ok		= TRUE;
-	}
-
-exit:
-
-	return ok;
-}
-
-// -----------------------------------------------------------
-// OnInitPage
-//
-// This function is responsible for doing initialization that
-// only occurs once during a run of the wizard
-//
-
-OSStatus CThirdPage::OnInitPage()
-{
-	CString		header;
-	CString		ntPrint;
-	OSStatus	err = kNoErr;
-
-	// Load printer icon
-	check( m_printerImage == NULL );
-	
-	m_printerImage = (CStatic*) GetDlgItem( 1 );	// 1 == IDR_MANIFEST
-	check( m_printerImage );
-
-	if ( m_printerImage != NULL )
-	{
-		m_printerImage->SetIcon( LoadIcon( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_PRINTER ) ) );
-	}
-
-	//
-	// The CTreeCtrl widget automatically sends a selection changed
-	// message which initially we want to ignore, because the user
-	// hasn't selected anything
-	//
-	// this flag gets reset in the message handler.  Every subsequent
-	// message gets handled.
-	//
-
-	//
-	// we have to make sure that we only do this once.  Typically,
-	// we would do this in something like OnInitDialog, but we don't
-	// have this in Wizards, because the window is a PropertySheet.
-	// We're considered fully initialized when we receive the first
-	// selection notice
-	//
-	header.LoadString(IDS_MANUFACTURER_HEADING);
-	m_manufacturerListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 );
-	m_manufacturerSelected = NULL;
-
-	header.LoadString(IDS_MODEL_HEADING);
-	m_modelListCtrl.InsertColumn(0, header, LVCFMT_LEFT, -1 );
-	m_modelSelected = NULL;
-
-	return (err);
-}
-
-void CThirdPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_PRINTER_MANUFACTURER, m_manufacturerListCtrl);
-	DDX_Control(pDX, IDC_PRINTER_MODEL, m_modelListCtrl);
-	DDX_Control(pDX, IDC_PRINTER_NAME, m_printerName);
-	DDX_Control(pDX, IDC_DEFAULT_PRINTER, m_defaultPrinterCtrl);
-	DDX_Control(pDX, IDC_PRINTER_SELECTION_TEXT, m_printerSelectionText);
-
-}
-
-// ----------------------------------------------------------
-// OnSetActive
-//
-// This function is called by MFC after the window has been
-// activated.
-//
-
-BOOL
-CThirdPage::OnSetActive()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-	Service						*	service;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-   
-	psheet->SetWizardButtons( PSWIZB_BACK );
-
-	printer = psheet->GetSelectedPrinter();
-	require_quiet( printer, exit );
-
-	service = printer->services.front();
-	require_quiet( service, exit );
-
-	//
-	// call OnInitPage once
-	//
-	if (!m_initialized)
-	{
-		OnInitPage();
-		m_initialized = true;
-	}
-
-	//
-	// <rdar://problem/4580061> mDNS: Printers added using Bonjour should be set as the default printer.
-	//
-	if ( DefaultPrinterExists() )
-	{
-		m_defaultPrinterCtrl.SetCheck( BST_UNCHECKED );
-		printer->deflt = false;
-	}
-	else
-	{
-		m_defaultPrinterCtrl.SetCheck( BST_CHECKED );
-		printer->deflt = true;
-	}
-
-	//
-	// update the UI with the printer name
-	//
-	m_printerName.SetWindowText(printer->displayName);
-
-	//
-	// populate the list controls with the manufacturers and models
-	// from ntprint.inf
-	//
-	PopulateUI( m_manufacturers );
-
-	//
-	// and try and match the printer
-	//
-
-	if ( psheet->GetLastPage() == psheet->GetPage(0) )
-	{
-		MatchPrinter( m_manufacturers, printer, service, true );
-
-		if ( ( m_manufacturerSelected != NULL ) && ( m_modelSelected != NULL  ) )
-		{
-			GetParent()->PostMessage(PSM_SETCURSEL, 2 );
-		}
-	}
-	else
-	{
-		SelectMatch(printer, service, m_manufacturerSelected, m_modelSelected);
-	}
-
-exit:
-
-	return CPropertyPage::OnSetActive();
-}
-
-BOOL
-CThirdPage::OnKillActive()
-{
-	CPrinterSetupWizardSheet * psheet;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-   
-	psheet->SetLastPage(this);
-
-exit:
-
-	return CPropertyPage::OnKillActive();
-}
-
-// -------------------------------------------------------
-// PopulateUI
-//
-// This function is called to populate the list of manufacturers
-//
-OSStatus
-CThirdPage::PopulateUI(Manufacturers & manufacturers)
-{
-	Manufacturers::iterator iter;
-	
-	m_manufacturerListCtrl.DeleteAllItems();
-
-	for (iter = manufacturers.begin(); iter != manufacturers.end(); iter++)
-	{
-		int nIndex;
-
-		Manufacturer * manufacturer = iter->second;
-
-		nIndex = m_manufacturerListCtrl.InsertItem(0, manufacturer->name);
-
-		m_manufacturerListCtrl.SetItemData(nIndex, (DWORD_PTR) manufacturer);
-
-		m_manufacturerListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER );
-	}
-
-	return 0;
-}
-
-BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage)
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MANUFACTURER, OnLvnItemchangedManufacturer)
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MODEL, OnLvnItemchangedPrinterModel)
-	ON_BN_CLICKED(IDC_DEFAULT_PRINTER, OnBnClickedDefaultPrinter)
-	ON_BN_CLICKED(IDC_HAVE_DISK, OnBnClickedHaveDisk)
-END_MESSAGE_MAP()
-
-// CThirdPage message handlers
-void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult)
-{
-	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
-
-	POSITION p = m_manufacturerListCtrl.GetFirstSelectedItemPosition();
-	int nSelected = m_manufacturerListCtrl.GetNextSelectedItem(p);
-
-	if (nSelected != -1)
-	{
-		m_manufacturerSelected = (Manufacturer*) m_manufacturerListCtrl.GetItemData(nSelected);
-
-		m_modelListCtrl.SetRedraw(FALSE);
-		
-		m_modelListCtrl.DeleteAllItems();
-		m_modelSelected = NULL;
-
-		Models::iterator iter;
-
-		for (iter = m_manufacturerSelected->models.begin(); iter != m_manufacturerSelected->models.end(); iter++)
-		{
-			Model * model = *iter;
-
-			int nItem = m_modelListCtrl.InsertItem( 0, model->displayName );
-
-			m_modelListCtrl.SetItemData(nItem, (DWORD_PTR) model);
-
-			m_modelListCtrl.SetColumnWidth( 0, LVSCW_AUTOSIZE_USEHEADER );
-		}
-
-		m_modelListCtrl.SetRedraw(TRUE);
-	}
-
-	*pResult = 0;
-}
-
-void CThirdPage::OnLvnItemchangedPrinterModel(NMHDR *pNMHDR, LRESULT *pResult)
-{
-	LPNMLISTVIEW					pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
-	
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-	Service						*	service;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	printer = psheet->GetSelectedPrinter();
-	require_quiet( printer, exit );
-
-	service = printer->services.front();
-	require_quiet( service, exit );
-
-	check ( m_manufacturerSelected );
-
-	POSITION p = m_modelListCtrl.GetFirstSelectedItemPosition();
-	int nSelected = m_modelListCtrl.GetNextSelectedItem(p);
-
-	if (nSelected != -1)
-	{
-		m_modelSelected = (Model*) m_modelListCtrl.GetItemData(nSelected);
-
-		CopyPrinterSettings( printer, service, m_manufacturerSelected, m_modelSelected );
-
-		psheet->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
-	}
-	else
-	{
-		psheet->SetWizardButtons(PSWIZB_BACK);
-	}
-
-exit:
-
-	*pResult = 0;
-}
-
-void CThirdPage::OnBnClickedDefaultPrinter()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	printer = psheet->GetSelectedPrinter();
-	require_quiet( printer, exit );
-
-	printer->deflt = ( m_defaultPrinterCtrl.GetCheck() == BST_CHECKED ) ? true : false;
-
-exit:
-
-	return;
-}
-
-void CThirdPage::OnBnClickedHaveDisk()
-{
-	CPrinterSetupWizardSheet	*	psheet;
-	Printer						*	printer;
-	Service						*	service;
-	Manufacturers					manufacturers;
-
-	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, L"Setup Information (*.inf)|*.inf||", this);
-
-	psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	printer = psheet->GetSelectedPrinter();
-	require_quiet( printer, exit );
-	
-	service = printer->services.front();
-	require_quiet( service, exit );
-
-	for ( ;; )
-	{
-		if ( dlg.DoModal() == IDOK )
-		{
-			CString filename = dlg.GetPathName();
-
-			LoadPrintDriverDefsFromFile( manufacturers, filename, true );
-   
-			// Sanity check
-
-			if ( manufacturers.size() > 0 )
-			{
-				PopulateUI( manufacturers );
-
-				if ( MatchPrinter( manufacturers, printer, service, false ) != kNoErr )
-				{
-					CString errorMessage;
-					CString errorCaption;
-					
-					errorMessage.LoadString( IDS_NO_MATCH_INF_FILE );
-					errorCaption.LoadString( IDS_NO_MATCH_INF_FILE_CAPTION );
-
-					MessageBox( errorMessage, errorCaption, MB_OK );
-				}
-
-				break;
-			}
-			else
-			{
-				CString errorMessage;
-				CString errorCaption;
-
-				errorMessage.LoadString( IDS_BAD_INF_FILE );
-				errorCaption.LoadString( IDS_BAD_INF_FILE_CAPTION );
-
-				MessageBox( errorMessage, errorCaption, MB_OK );
-			}
-		}
-		else
-		{
-			break;
-		}
-	}
-
-exit:
-
-	FreeManufacturers( manufacturers );
-	return;
-}
-
-
-void
-CThirdPage::Split( const CString & string, TCHAR ch, CStringList & components )
-{
-	CString	temp;
-	int		n;
-
-	temp = string;
-	
-	while ( ( n = temp.Find( ch ) ) != -1 )
-	{
-		components.AddTail( temp.Left( n ) );
-		temp = temp.Right( temp.GetLength() - ( n + 1 ) );
-	}
-
-	components.AddTail( temp );
-}
diff --git a/Clients/PrinterSetupWizard/ThirdPage.h b/Clients/PrinterSetupWizard/ThirdPage.h
deleted file mode 100644
index 476e233..0000000
--- a/Clients/PrinterSetupWizard/ThirdPage.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-#include "afxcmn.h"
-#include "UtilTypes.h"
-#include <CommonServices.h>
-#include <DebugServices.h>
-#include <dns_sd.h>
-#include <map>
-#include "afxwin.h"
-
-
-// CThirdPage dialog
-
-class CThirdPage : public CPropertyPage
-{
-DECLARE_DYNAMIC(CThirdPage)
-
-public:
-CThirdPage();
-virtual ~CThirdPage();
-
-// Dialog Data
-enum { IDD = IDD_THIRD_PAGE };
-
-protected:
-virtual void DoDataExchange(CDataExchange* pDX);        // DDX/DDV support
-virtual BOOL OnSetActive();
-virtual BOOL OnKillActive();
-
-DECLARE_MESSAGE_MAP()
-
-private:
-
-//
-//<rdar://problem/4189721> mDNS: Epson shows up twice in the list.  Use case insensitive compare
-//
-struct compare_func
-{
-    bool operator()( const CString & s1, const CString & s2 ) const
-    {
-        return s1.CompareNoCase( s2 ) < 0;
-    }
-};
-
-typedef std::map<CString, Manufacturer*, compare_func> Manufacturers;
-
-//
-// LoadPrintDriverDefsFromFile
-//
-// Parses INF file and populates manufacturers
-//
-OSStatus LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CString & filename, bool checkForDuplicateModels );
-
-//
-// LoadPrintDriverDefs
-//
-// Loads extant print driver definitions
-//
-OSStatus LoadPrintDriverDefs(Manufacturers & manufacturers);
-
-//
-// LoadGenericPrintDriversDefs
-//
-// Loads generic postscript and pcl print driver defs
-//
-OSStatus LoadGenericPrintDriverDefs( Manufacturers & manufacturers );
-
-//
-// PopulateUI
-//
-// Load print driver defs into UI for browsing/selection
-//
-OSStatus PopulateUI(Manufacturers & manufacturers);
-
-//
-// MatchPrinter
-//
-// Tries to match printer based on manufacturer and model
-//
-OSStatus MatchPrinter(Manufacturers & manufacturers, Printer * printer, Service * service, bool useCUPSWorkaround);
-
-//
-// OnInitPage
-//
-// Called first time page is activated.
-OSStatus OnInitPage();
-
-//
-// these functions will tweak the names so that everything is
-// consistent
-//
-CString             ConvertToManufacturerName( const CString & name );
-CString             ConvertToModelName( const CString & name );
-CString             NormalizeManufacturerName( const CString & name );
-
-Manufacturer    *   MatchManufacturer( Manufacturers & manufacturer, const CString & name );
-Model           *   MatchModel( Manufacturer * manufacturer, const CString & name );
-BOOL                MatchGeneric( Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer ** manufacturer, Model ** model );
-void                SelectMatch(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
-void                SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
-void                CopyPrinterSettings(Printer * printer, Service * service, Manufacturer * manufacturer, Model * model);
-//
-// <rdar://problem/4580061> mDNS: Printers added using Bonjour should be set as the default printer.
-//
-BOOL                DefaultPrinterExists();
-//
-//<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-//
-void                AutoScroll(CListCtrl & list, int nIndex);
-
-void                FreeManufacturers( Manufacturers & manufacturers );
-
-Manufacturers m_manufacturers;
-
-CListCtrl m_manufacturerListCtrl;
-Manufacturer    *   m_manufacturerSelected;
-
-CListCtrl m_modelListCtrl;
-Model           *   m_modelSelected;
-
-Model           *   m_genericPostscript;
-Model           *   m_genericPCL;
-
-bool m_initialized;
-
-public:
-
-afx_msg void OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult);
-CStatic m_printerName;
-afx_msg void OnLvnItemchangedPrinterModel(NMHDR *pNMHDR, LRESULT *pResult);
-afx_msg void OnBnClickedDefaultPrinter();
-private:
-
-void
-Split( const CString & string, TCHAR ch, CStringList & components );
-
-CButton m_defaultPrinterCtrl;
-
-public:
-CStatic m_printerSelectionText;
-CStatic *   m_printerImage;
-afx_msg void OnBnClickedHaveDisk();
-};
diff --git a/Clients/PrinterSetupWizard/UtilTypes.h b/Clients/PrinterSetupWizard/UtilTypes.h
deleted file mode 100644
index dc0ae10..0000000
--- a/Clients/PrinterSetupWizard/UtilTypes.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#include <dns_sd.h>
-#include <string>
-#include <list>
-#include <DebugServices.h>
-
-class CPrinterSetupWizardSheet;
-
-#define kDefaultPriority    50
-#define kDefaultQTotal      1
-
-namespace PrinterSetupWizard
-{
-struct Printer;
-struct Service;
-struct Queue;
-struct Manufacturer;
-struct Model;
-
-typedef std::list<Queue*>   Queues;
-typedef std::list<Printer*> Printers;
-typedef std::list<Service*> Services;
-typedef std::list<Model*>   Models;
-
-struct Printer
-{
-    Printer();
-
-    ~Printer();
-
-    Service*
-    LookupService
-    (
-        const std::string   &   type
-    );
-
-    CPrinterSetupWizardSheet    *   window;
-    HTREEITEM item;
-
-    //
-    // These are from the browse reply
-    //
-    std::string name;
-    CString displayName;
-    CString actualName;
-
-    //
-    // These keep track of the different services associated with this printer.
-    // the services are ordered according to preference.
-    //
-    Services services;
-
-    //
-    // these are derived from the printer matching code
-    //
-    // if driverInstalled is false, then infFileName should
-    // have an absolute path to the printers inf file.  this
-    // is used to install the printer from printui.dll
-    //
-    // if driverInstalled is true, then model is the name
-    // of the driver to use in AddPrinter
-    //
-    bool driverInstalled;
-    CString infFileName;
-    CString manufacturer;
-    CString displayModelName;
-    CString modelName;
-    CString portName;
-    bool deflt;
-
-    // This let's us know that this printer was discovered via OSX Printer Sharing.
-    // We use this knowledge to workaround a problem with OS X Printer sharing.
-
-    bool isCUPSPrinter;
-
-    //
-    // state
-    //
-    unsigned resolving;
-    bool installed;
-};
-
-
-struct Service
-{
-    Service();
-
-    ~Service();
-
-    Queue*
-    SelectedQueue();
-
-    void
-    EmptyQueues();
-
-    Printer     *   printer;
-    uint32_t ifi;
-    std::string type;
-    std::string domain;
-
-    //
-    // these are from the resolve
-    //
-    DNSServiceRef serviceRef;
-    CString hostname;
-    unsigned short portNumber;
-    CString protocol;
-    unsigned short qtotal;
-
-    //
-    // There will usually one be one of these, however
-    // this will handle printers that have multiple
-    // queues.  These are ordered according to preference.
-    //
-    Queues queues;
-
-    //
-    // Reference count
-    //
-    unsigned refs;
-};
-
-
-struct Queue
-{
-    Queue();
-
-    ~Queue();
-
-    CString name;
-    uint32_t priority;
-    CString pdl;
-    CString usb_MFG;
-    CString usb_MDL;
-    CString description;
-    CString location;
-    CString product;
-};
-
-
-struct Manufacturer
-{
-    CString name;
-    Models models;
-
-    Model*
-    find( const CString & name );
-};
-
-
-struct Model
-{
-    bool driverInstalled;
-    CString infFileName;
-    CString displayName;
-    CString name;
-};
-
-
-inline
-Printer::Printer()
-    :
-    isCUPSPrinter( false )
-{
-}
-
-inline
-Printer::~Printer()
-{
-    while ( services.size() > 0 )
-    {
-        Service * service = services.front();
-        services.pop_front();
-        delete service;
-    }
-}
-
-inline Service*
-Printer::LookupService
-(
-    const std::string   &   type
-)
-{
-    Services::iterator it;
-
-    for ( it = services.begin(); it != services.end(); it++ )
-    {
-        Service * service = *it;
-
-        if ( strcmp(service->type.c_str(), type.c_str()) == 0 )
-        {
-            return service;
-        }
-    }
-
-    return NULL;
-}
-
-inline
-Service::Service()
-    :
-    qtotal(kDefaultQTotal)
-{
-}
-
-inline
-Service::~Service()
-{
-    check( serviceRef == NULL );
-
-    EmptyQueues();
-}
-
-inline Queue*
-Service::SelectedQueue()
-{
-    return queues.front();
-}
-
-inline void
-Service::EmptyQueues()
-{
-    while ( queues.size() > 0 )
-    {
-        Queue * q = queues.front();
-        queues.pop_front();
-        delete q;
-    }
-}
-
-inline
-Queue::Queue()
-    :
-    priority(kDefaultPriority)
-{
-}
-
-inline
-Queue::~Queue()
-{
-}
-
-inline Model*
-Manufacturer::find( const CString & name )
-{
-    Models::iterator it;
-
-    for ( it = models.begin(); it != models.end(); it++ )
-    {
-        Model * model = *it;
-
-        if ( model->name == name )
-        {
-            return model;
-        }
-    }
-
-    return NULL;
-}
-}
-
-
diff --git a/Clients/PrinterSetupWizard/resource.h b/Clients/PrinterSetupWizard/resource.h
deleted file mode 100644
index b1190fb..0000000
--- a/Clients/PrinterSetupWizard/resource.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-
-// Include resources for Wizard app
-
-#include "resource_exe.h"
-
-// Include resources for non-localizable resource DLL
-
-#include "resource_res.h"
-
-// Include resources for localizable resource DLL
-
-#include "resource_loc_res.h"
diff --git a/Clients/PrinterSetupWizard/resource_exe.h b/Clients/PrinterSetupWizard/resource_exe.h
deleted file mode 100644
index 33c0c28..0000000
--- a/Clients/PrinterSetupWizard/resource_exe.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by PrinterSetupWizard.rc
-//
-#define IDM_ABOUTBOX                    0x0010
-#define IDD_ABOUTBOX                    100
-#define IDS_ABOUTBOX                    101
-#define IDD_PRINTERSETUPWIZARD_DIALOG   102
-#define IDS_GOODBYE                     102
-#define IDS_GREETING                    103
-#define IDS_BROWSE_TITLE                104
-#define IDS_BROWSE_SUBTITLE             105
-#define IDS_CAPTION                     106
-#define IDD_FIRST_PAGE                  107
-#define IDS_GOODBYE_GOOD1               107
-#define IDS_SEARCHING                   108
-#define IDD_SECOND_PAGE                 109
-#define IDS_GOODBYTE_GOOD2              109
-#define IDS_INSTALL_TITLE               110
-#define IDS_INSTALL_SUBTITLE            111
-#define IDS_ERROR_SELECTING_PRINTER_TEXT 112
-#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113
-#define IDS_INSTALL_ERROR_CAPTION       114
-#define IDS_INSTALL_ERROR_MESSAGE       115
-#define IDS_MANUFACTURER_HEADING        116
-#define IDS_MODEL_HEADING               117
-#define IDS_NO_PRINTERS                 118
-#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119
-#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120
-#define IDS_PRINTER_MATCH_GOOD          121
-#define IDS_PRINTER_MATCH_BAD           122
-#define IDS_YES                         123
-#define IDS_NO                          124
-#define IDS_LARGE_FONT                  125
-#define IDS_FIREWALL                    126
-#define IDS_ERROR_CAPTION               127
-#define IDR_MAINFRAME                   128
-#define IDS_FIREWALL_CAPTION            128
-#define IDB_BANNER_ICON                 129
-#define IDD_THIRD_PAGE                  130
-#define IDB_WATERMARK                   131
-#define IDD_FOURTH_PAGE                 132
-#define IDI_INFO                        136
-#define IDB_ABOUT                       138
-#define IDD_DIALOG1                     139
-#define IDI_ICON2                       141
-#define IDI_PRINTER                     141
-#define IDS_REINSTALL                   142
-#define IDS_REINSTALL_CAPTION           143
-#define IDC_INFO                        144
-#define IDS_PRINTER_UNAVAILABLE         145
-#define IDS_BAD_INF_FILE                150
-#define IDS_BAD_INF_FILE_CAPTION        151
-#define IDS_NO_MATCH_INF_FILE           152
-#define IDS_NO_MATCH_INF_FILE_CAPTION   153
-#define IDC_BUTTON1                     1000
-#define IDC_LIST1                       1000
-#define IDC_BROWSE_LIST                 1000
-#define IDC_RADIO1                      1001
-#define IDC_COMBO1                      1001
-#define IDC_RADIO2                      1002
-#define IDC_GREETING                    1003
-#define IDC_CHECK1                      1016
-#define IDC_DEFAULT_PRINTER             1016
-#define IDC_PRINTER_IMAGE               1017
-#define IDC_PRINTER_NAME                1018
-#define IDC_PRINTER_MANUFACTURER        1019
-#define IDC_PRINTER_MODEL               1020
-#define IDC_GOODBYE                     1021
-#define IDC_PRINTER_PORT                1022
-#define IDC_PRINTER_PROTOCOL            1022
-#define IDC_PRINTER_DEFAULT             1023
-#define IDC_PRINTER_SELECTION_TEXT      1024
-#define IDC_HAVE_DISK                   1025
-#define IDC_PRINTER_INFORMATION         1026
-#define IDC_LOCATION_LABEL              1029
-#define IDC_DESCRIPTION_FIELD           1030
-#define IDC_LOCATION_FIELD              1032
-#define IDC_DESCRIPTION_LABEL           1033
-#define IDC_COMPLETE1                   1034
-#define IDC_COMPLETE2                   1035
-#define IDC_INSTALLING                  1036
-#define IDC_PROGRESS                    1037
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        142
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1034
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/PrinterSetupWizard/resource_loc_res.h b/Clients/PrinterSetupWizard/resource_loc_res.h
deleted file mode 100644
index deb2e6e..0000000
--- a/Clients/PrinterSetupWizard/resource_loc_res.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by PrinterSetupWizardLocRes.rc
-//
-#define IDM_ABOUTBOX                    0x0010
-#define IDD_ABOUTBOX                    100
-#define IDS_ABOUTBOX                    101
-#define IDD_PRINTERSETUPWIZARD_DIALOG   102
-#define IDS_GOODBYE                     102
-#define IDS_GREETING                    103
-#define IDS_BROWSE_TITLE                104
-#define IDS_BROWSE_SUBTITLE             105
-#define IDS_CAPTION                     106
-#define IDD_FIRST_PAGE                  107
-#define IDS_GOODBYE_GOOD1               107
-#define IDS_SEARCHING                   108
-#define IDD_SECOND_PAGE                 109
-#define IDS_GOODBYTE_GOOD2              109
-#define IDS_INSTALL_TITLE               110
-#define IDS_INSTALL_SUBTITLE            111
-#define IDS_ERROR_SELECTING_PRINTER_TEXT 112
-#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113
-#define IDS_INSTALL_ERROR_CAPTION       114
-#define IDS_INSTALL_ERROR_MESSAGE       115
-#define IDS_MANUFACTURER_HEADING        116
-#define IDS_MODEL_HEADING               117
-#define IDS_NO_PRINTERS                 118
-#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119
-#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120
-#define IDS_PRINTER_MATCH_GOOD          121
-#define IDS_PRINTER_MATCH_BAD           122
-#define IDS_PRINTER_MATCH_MAYBE         146
-#define IDS_YES                         123
-#define IDS_NO                          124
-#define IDS_LARGE_FONT                  125
-#define IDS_FIREWALL                    126
-#define IDS_ERROR_CAPTION               127
-#define IDR_MAINFRAME                   128
-#define IDS_FIREWALL_CAPTION            128
-#define IDB_BANNER_ICON                 129
-#define IDD_THIRD_PAGE                  130
-#define IDB_WATERMARK                   131
-#define IDD_FOURTH_PAGE                 132
-#define IDI_INFO                        136
-#define IDB_ABOUT                       138
-#define IDD_DIALOG1                     139
-#define IDI_ICON2                       141
-#define IDI_PRINTER                     141
-#define IDS_REINSTALL                   142
-#define IDS_REINSTALL_CAPTION           143
-#define IDC_INFO                                 144
-#define IDS_PRINTER_UNAVAILABLE         145
-#define IDS_BAD_INF_FILE                150
-#define IDS_BAD_INF_FILE_CAPTION        151
-#define IDS_NO_MATCH_INF_FILE           152
-#define IDS_NO_MATCH_INF_FILE_CAPTION   153
-#define IDC_BUTTON1                     1000
-#define IDC_LIST1                       1000
-#define IDC_BROWSE_LIST                 1000
-#define IDC_RADIO1                      1001
-#define IDC_COMBO1                      1001
-#define IDC_RADIO2                      1002
-#define IDC_GREETING                    1003
-#define IDC_CHECK1                      1016
-#define IDC_DEFAULT_PRINTER             1016
-#define IDC_PRINTER_IMAGE               1017
-#define IDC_PRINTER_NAME                1018
-#define IDC_PRINTER_MANUFACTURER        1019
-#define IDC_PRINTER_MODEL               1020
-#define IDC_GOODBYE                     1021
-#define IDC_PRINTER_PORT                1022
-#define IDC_PRINTER_PROTOCOL            1022
-#define IDC_PRINTER_DEFAULT             1023
-#define IDC_PRINTER_SELECTION_TEXT      1024
-#define IDC_HAVE_DISK                   1025
-#define IDC_PRINTER_INFORMATION         1026
-#define IDC_LOCATION_LABEL              1029
-#define IDC_DESCRIPTION_FIELD           1030
-#define IDC_LOCATION_FIELD              1032
-#define IDC_DESCRIPTION_LABEL           1033
-#define IDC_COMPLETE1                   1034
-#define IDC_COMPLETE2                   1035
-#define IDC_INSTALLING                  1036
-#define IDC_PROGRESS                    1037
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        142
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1034
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/PrinterSetupWizard/resource_res.h b/Clients/PrinterSetupWizard/resource_res.h
deleted file mode 100644
index 33c0c28..0000000
--- a/Clients/PrinterSetupWizard/resource_res.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by PrinterSetupWizard.rc
-//
-#define IDM_ABOUTBOX                    0x0010
-#define IDD_ABOUTBOX                    100
-#define IDS_ABOUTBOX                    101
-#define IDD_PRINTERSETUPWIZARD_DIALOG   102
-#define IDS_GOODBYE                     102
-#define IDS_GREETING                    103
-#define IDS_BROWSE_TITLE                104
-#define IDS_BROWSE_SUBTITLE             105
-#define IDS_CAPTION                     106
-#define IDD_FIRST_PAGE                  107
-#define IDS_GOODBYE_GOOD1               107
-#define IDS_SEARCHING                   108
-#define IDD_SECOND_PAGE                 109
-#define IDS_GOODBYTE_GOOD2              109
-#define IDS_INSTALL_TITLE               110
-#define IDS_INSTALL_SUBTITLE            111
-#define IDS_ERROR_SELECTING_PRINTER_TEXT 112
-#define IDS_ERROR_SELECTING_PRINTER_CAPTION 113
-#define IDS_INSTALL_ERROR_CAPTION       114
-#define IDS_INSTALL_ERROR_MESSAGE       115
-#define IDS_MANUFACTURER_HEADING        116
-#define IDS_MODEL_HEADING               117
-#define IDS_NO_PRINTERS                 118
-#define IDS_NO_MDNSRESPONDER_SERVICE_TEXT 119
-#define IDS_NO_MDNSRESPONDER_SERVICE_CAPTION 120
-#define IDS_PRINTER_MATCH_GOOD          121
-#define IDS_PRINTER_MATCH_BAD           122
-#define IDS_YES                         123
-#define IDS_NO                          124
-#define IDS_LARGE_FONT                  125
-#define IDS_FIREWALL                    126
-#define IDS_ERROR_CAPTION               127
-#define IDR_MAINFRAME                   128
-#define IDS_FIREWALL_CAPTION            128
-#define IDB_BANNER_ICON                 129
-#define IDD_THIRD_PAGE                  130
-#define IDB_WATERMARK                   131
-#define IDD_FOURTH_PAGE                 132
-#define IDI_INFO                        136
-#define IDB_ABOUT                       138
-#define IDD_DIALOG1                     139
-#define IDI_ICON2                       141
-#define IDI_PRINTER                     141
-#define IDS_REINSTALL                   142
-#define IDS_REINSTALL_CAPTION           143
-#define IDC_INFO                        144
-#define IDS_PRINTER_UNAVAILABLE         145
-#define IDS_BAD_INF_FILE                150
-#define IDS_BAD_INF_FILE_CAPTION        151
-#define IDS_NO_MATCH_INF_FILE           152
-#define IDS_NO_MATCH_INF_FILE_CAPTION   153
-#define IDC_BUTTON1                     1000
-#define IDC_LIST1                       1000
-#define IDC_BROWSE_LIST                 1000
-#define IDC_RADIO1                      1001
-#define IDC_COMBO1                      1001
-#define IDC_RADIO2                      1002
-#define IDC_GREETING                    1003
-#define IDC_CHECK1                      1016
-#define IDC_DEFAULT_PRINTER             1016
-#define IDC_PRINTER_IMAGE               1017
-#define IDC_PRINTER_NAME                1018
-#define IDC_PRINTER_MANUFACTURER        1019
-#define IDC_PRINTER_MODEL               1020
-#define IDC_GOODBYE                     1021
-#define IDC_PRINTER_PORT                1022
-#define IDC_PRINTER_PROTOCOL            1022
-#define IDC_PRINTER_DEFAULT             1023
-#define IDC_PRINTER_SELECTION_TEXT      1024
-#define IDC_HAVE_DISK                   1025
-#define IDC_PRINTER_INFORMATION         1026
-#define IDC_LOCATION_LABEL              1029
-#define IDC_DESCRIPTION_FIELD           1030
-#define IDC_LOCATION_FIELD              1032
-#define IDC_DESCRIPTION_LABEL           1033
-#define IDC_COMPLETE1                   1034
-#define IDC_COMPLETE2                   1035
-#define IDC_INSTALLING                  1036
-#define IDC_PROGRESS                    1037
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        142
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1034
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/PrinterSetupWizard/stdafx.cpp b/Clients/PrinterSetupWizard/stdafx.cpp
deleted file mode 100644
index e05ec3d..0000000
--- a/Clients/PrinterSetupWizard/stdafx.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-
-
diff --git a/Clients/PrinterSetupWizard/stdafx.h b/Clients/PrinterSetupWizard/stdafx.h
deleted file mode 100644
index 1eec4c3..0000000
--- a/Clients/PrinterSetupWizard/stdafx.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#ifndef VC_EXTRALEAN
-#define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers
-#endif
-
-// Modify the following defines if you have to target a platform prior to the ones specified below.
-// Refer to MSDN for the latest info on corresponding values for different platforms.
-#ifndef WINVER              // Allow use of features specific to Windows 95 and Windows NT 4 or later.
-#define WINVER 0x0400       // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
-#endif
-
-#ifndef _WIN32_WINNT        // Allow use of features specific to Windows NT 4 or later.
-#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
-#endif
-
-#ifndef _WIN32_WINDOWS      // Allow use of features specific to Windows 98 or later.
-#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
-#endif
-
-// Step 3: We want to see one image, but not a tile
-#ifndef _WIN32_IE           // Allow use of features specific to IE 4.0 or later.
-#define _WIN32_IE 0x0500    // Change this to the appropriate value to target IE 5.0 or later.
-#endif
-
-#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // some CString constructors will be explicit
-
-// turns off MFC's hiding of some common and often safely ignored warning messages
-#define _AFX_ALL_WARNINGS
-
-#if !defined(_WSPIAPI_COUNTOF)
-#   define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-#endif
-
-#include <afxwin.h>         // MFC core and standard components
-#include <afxext.h>         // MFC extensions
-#include <afxdisp.h>        // MFC Automation classes
-
-#include <afxdtctl.h>       // MFC support for Internet Explorer 4 Common Controls
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-#include <afxcmn.h>         // MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
-#include <afxdlgs.h>
-
diff --git a/Clients/PrinterSetupWizard/tcpxcv.h b/Clients/PrinterSetupWizard/tcpxcv.h
deleted file mode 100644
index a4b7b5f..0000000
--- a/Clients/PrinterSetupWizard/tcpxcv.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*++
-
-   Copyright (c) 1997 - 1999  Hewlett-Packard Company.
-   Copyright (c) 1997 - 1999  Microsoft Corporation
-   All rights reserved
-
-   Module Name:
-
-   tcpxcv.h
-
-   --*/
-/*
- * This file is contained in WinDDK 6001.18002
- */
-
-#ifndef _TCPXCV_
-#define _TCPXCV_
-
-#if (!defined(UNKNOWN_PROTOCOL))
-    #define UNKNOWN_PROTOCOL        0
-    #define PROTOCOL_UNKNOWN_TYPE   UNKNOWN_PROTOCOL
-#endif
-
-#if (!defined(RAWTCP))
-#define RAWTCP                          1
-#define PROTOCOL_RAWTCP_TYPE            RAWTCP
-#endif
-
-#if (!defined(LPR))
-#define LPR                             2
-#define PROTOCOL_LPR_TYPE               LPR
-#endif
-
-#define MAX_PORTNAME_LEN                63 +1       // port name length
-#define MAX_NETWORKNAME_LEN             48 +1       // host name length
-#define MAX_NETWORKNAME2_LEN            128         // host name or IPv6 address
-#define MAX_SNMP_COMMUNITY_STR_LEN      32 +1       // SNMP Community String Name
-#define MAX_QUEUENAME_LEN               32 +1       // lpr print que name
-#define MAX_IPADDR_STR_LEN              15 +1       // ip address; string version
-#define MAX_ADDRESS_STR_LEN             12 +1       // hw address length
-#define MAX_DEVICEDESCRIPTION_STR_LEN   256+1
-
-
-
-typedef struct _PORT_DATA_1
-{
-    WCHAR sztPortName[MAX_PORTNAME_LEN];
-    DWORD dwVersion;
-    DWORD dwProtocol;
-    DWORD cbSize;
-    DWORD dwReserved;
-    WCHAR sztHostAddress[MAX_NETWORKNAME_LEN];
-    WCHAR sztSNMPCommunity[MAX_SNMP_COMMUNITY_STR_LEN];
-    DWORD dwDoubleSpool;
-    WCHAR sztQueue[MAX_QUEUENAME_LEN];
-    WCHAR sztIPAddress[MAX_IPADDR_STR_LEN];
-    BYTE Reserved[540];
-    DWORD dwPortNumber;
-    DWORD dwSNMPEnabled;
-    DWORD dwSNMPDevIndex;
-}   PORT_DATA_1, *PPORT_DATA_1;
-
-typedef struct _PORT_DATA_2
-{
-    WCHAR sztPortName[MAX_PORTNAME_LEN];
-    DWORD dwVersion;
-    DWORD dwProtocol;
-    DWORD cbSize;
-    DWORD dwReserved;
-    WCHAR sztHostAddress [MAX_NETWORKNAME2_LEN];
-    WCHAR sztSNMPCommunity[MAX_SNMP_COMMUNITY_STR_LEN];
-    DWORD dwDoubleSpool;
-    WCHAR sztQueue[MAX_QUEUENAME_LEN];
-    BYTE Reserved[514];
-    DWORD dwPortNumber;
-    DWORD dwSNMPEnabled;
-    DWORD dwSNMPDevIndex;
-    DWORD dwPortMonitorMibIndex;
-}   PORT_DATA_2, *PPORT_DATA_2;
-
-
-typedef struct _PORT_DATA_LIST_1
-{
-    DWORD dwVersion;
-    DWORD cPortData;
-    PORT_DATA_2 pPortData[1];
-}   PORT_DATA_LIST_1, *PPORT_DATA_LIST_1;
-
-
-typedef struct _DELETE_PORT_DATA_1
-{
-    WCHAR psztPortName[MAX_PORTNAME_LEN];
-    BYTE Reserved[98];
-    DWORD dwVersion;
-    DWORD dwReserved;
-}   DELETE_PORT_DATA_1, *PDELETE_PORT_DATA_1;
-
-
-typedef struct _CONFIG_INFO_DATA_1
-{
-    BYTE Reserved[128];
-    DWORD dwVersion;
-}   CONFIG_INFO_DATA_1, *PCONFIG_INFO_DATA_1;
-
-
-
-#endif
diff --git a/Clients/dns-sd.c b/Clients/dns-sd.c
deleted file mode 100644
index e4feff3..0000000
--- a/Clients/dns-sd.c
+++ /dev/null
@@ -1,2473 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple Inc. All rights reserved.
- *
- * Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.
- * ("Apple") in consideration of your agreement to the following terms, and your
- * use, installation, modification or redistribution of this Apple software
- * constitutes acceptance of these terms.  If you do not agree with these terms,
- * please do not use, install, modify or redistribute this Apple software.
- *
- * In consideration of your agreement to abide by the following terms, and subject
- * to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- * copyrights in this original Apple software (the "Apple Software"), to use,
- * reproduce, modify and redistribute the Apple Software, with or without
- * modifications, in source and/or binary forms; provided that if you redistribute
- * the Apple Software in its entirety and without modifications, 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.
- *
- * 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.
- *
-   To build this tool, copy and paste the following into a command line:
-
-   OS X:
-   gcc dns-sd.c -o dns-sd
-
-   POSIX systems:
-   gcc dns-sd.c -o dns-sd -I../mDNSShared -ldns_sd
-
-   Windows:
-   cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Release\dnssd.lib
-   (may require that you run a Visual Studio script such as vsvars32.bat first)
- */
-
-// For testing changes to dnssd_clientstub.c, uncomment this line and the code will be compiled
-// with an embedded copy of the client stub instead of linking the system library version at runtime.
-// This also useful to work around link errors when you're working on an older version of Mac OS X,
-// and trying to build a newer version of the "dns-sd" command which uses new API entry points that
-// aren't in the system's /usr/lib/libSystem.dylib.
-//#define TEST_NEW_CLIENTSTUB 1
-
-#include <ctype.h>
-#include <stdio.h>          // For stdout, stderr
-#include <stdlib.h>         // For exit()
-#include <string.h>         // For strlen(), strcpy()
-#include <stdarg.h>         // For va_start, va_arg, va_end, etc.
-#include <errno.h>          // For errno, EINTR
-#include <time.h>
-#include <sys/types.h>      // For u_char
-
-
-#ifndef __printflike
-    #define __printflike(A, B)
-#endif
-
-#ifdef _WIN32
-    #include <winsock2.h>
-    #include <ws2tcpip.h>
-    #include <Iphlpapi.h>
-    #include <process.h>
-    #include <stdint.h>
-typedef int pid_t;
-typedef int suseconds_t;
-    #define getpid     _getpid
-    #define strcasecmp _stricmp
-    #define snprintf   _snprintf
-static const char kFilePathSep = '\\';
-    #ifndef HeapEnableTerminationOnCorruption
-    #     define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
-    #endif
-    #if !defined(IFNAMSIZ)
-     #define IFNAMSIZ 16
-    #endif
-    #define if_nametoindex if_nametoindex_win
-    #define if_indextoname if_indextoname_win
-
-typedef PCHAR (WINAPI * if_indextoname_funcptr_t)(ULONG index, PCHAR name);
-typedef ULONG (WINAPI * if_nametoindex_funcptr_t)(PCSTR name);
-
-unsigned if_nametoindex_win(const char *ifname)
-{
-    HMODULE library;
-    unsigned index = 0;
-
-    // Try and load the IP helper library dll
-    if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
-    {
-        if_nametoindex_funcptr_t if_nametoindex_funcptr;
-
-        // On Vista and above there is a Posix like implementation of if_nametoindex
-        if ((if_nametoindex_funcptr = (if_nametoindex_funcptr_t) GetProcAddress(library, "if_nametoindex")) != NULL )
-        {
-            index = if_nametoindex_funcptr(ifname);
-        }
-
-        FreeLibrary(library);
-    }
-
-    return index;
-}
-
-char * if_indextoname_win( unsigned ifindex, char *ifname)
-{
-    HMODULE library;
-    char * name = NULL;
-
-    // Try and load the IP helper library dll
-    if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
-    {
-        if_indextoname_funcptr_t if_indextoname_funcptr;
-
-        // On Vista and above there is a Posix like implementation of if_indextoname
-        if ((if_indextoname_funcptr = (if_indextoname_funcptr_t) GetProcAddress(library, "if_indextoname")) != NULL )
-        {
-            name = if_indextoname_funcptr(ifindex, ifname);
-        }
-
-        FreeLibrary(library);
-    }
-
-    return name;
-}
-
-static size_t _sa_len(const struct sockaddr *addr)
-{
-    if (addr->sa_family == AF_INET) return (sizeof(struct sockaddr_in));
-    else if (addr->sa_family == AF_INET6) return (sizeof(struct sockaddr_in6));
-    else return (sizeof(struct sockaddr));
-}
-
-#   define SA_LEN(addr) (_sa_len(addr))
-
-typedef void (WINAPI* SystemTimeFunc)(LPFILETIME);
-
-static const uint64_t epoch_diff = (UINT64)11644473600000000ULL;
-static SystemTimeFunc fpTimeFunc;
-
-int gettimeofday(struct timeval* tp, struct timezone* tzp)
-{
-    FILETIME ft;
-    UINT64 us;
-
-    if (!fpTimeFunc)
-    {
-        /* available on Windows 7 */
-        fpTimeFunc = GetSystemTimeAsFileTime;
-
-        HMODULE hKernel32 = LoadLibraryW(L"kernel32.dll");
-        if (hKernel32)
-        {
-            FARPROC fp;
-
-            /* available on Windows 8+ */
-            fp = GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime");
-            if (fp)
-            {
-                fpTimeFunc = (SystemTimeFunc)fp;
-            }
-        }
-    }
-
-    fpTimeFunc(&ft);
-
-    us = (((uint64_t)ft.dwHighDateTime << 32) | (uint64_t)ft.dwLowDateTime) / 10;
-    us -= epoch_diff;
-
-    tp->tv_sec = (long)(us / 1000000);
-    tp->tv_usec = (long)(us % 1000000);
-
-    return 0;
-}
-
-#else
-    #include <unistd.h>         // For getopt() and optind
-    #include <netdb.h>          // For getaddrinfo()
-    #include <sys/time.h>       // For struct timeval
-    #include <sys/socket.h>     // For AF_INET
-    #include <netinet/in.h>     // For struct sockaddr_in()
-    #include <arpa/inet.h>      // For inet_addr()
-    #include <net/if.h>         // For if_nametoindex()
-static const char kFilePathSep = '/';
-// #ifndef NOT_HAVE_SA_LEN
-//  #define SA_LEN(addr) ((addr)->sa_len)
-// #else
-    #define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-// #endif
-#endif
-
-#if (TEST_NEW_CLIENTSTUB && !defined(__APPLE_API_PRIVATE))
-#define __APPLE_API_PRIVATE 1
-#endif
-
-// DNSServiceSetDispatchQueue is not supported on 10.6 & prior
-#if !TEST_NEW_CLIENTSTUB && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ % 10) <= 1060)
-#undef _DNS_SD_LIBDISPATCH
-#endif
-#include "dns_sd.h"
-#include "ClientCommon.h"
-
-
-#if TEST_NEW_CLIENTSTUB
-#include "../mDNSShared/dnssd_ipc.c"
-#include "../mDNSShared/dnssd_clientlib.c"
-#include "../mDNSShared/dnssd_clientstub.c"
-#endif
-
-//*************************************************************************************************************
-// Globals
-
-#define DS_FIXED_SIZE   4
-typedef struct
-{
-    unsigned short keyTag;
-    unsigned char alg;
-    unsigned char digestType;
-    unsigned char  *digest;
-} rdataDS;
-
-#define DNSKEY_FIXED_SIZE    4
-typedef struct
-{
-    unsigned short flags;
-    unsigned char proto;
-    unsigned char alg;
-    unsigned char *data;
-} rdataDNSKey;
-
-//size of rdataRRSIG excluding signerName and signature (which are variable fields)
-#define RRSIG_FIXED_SIZE      18
-typedef struct
-{
-    unsigned short typeCovered;
-    unsigned char alg;
-    unsigned char labels;
-    unsigned int origTTL;
-    unsigned int sigExpireTime;
-    unsigned int sigInceptTime;
-    unsigned short keyTag;
-    char signerName[256];
-    //unsigned char *signature
-} rdataRRSig;
-
-#define RR_TYPE_SIZE 16
-
-typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
-
-static int operation;
-static uint32_t opinterface = kDNSServiceInterfaceIndexAny;
-static DNSServiceRef client    = NULL;
-static DNSServiceRef client_pa = NULL;  // DNSServiceRef for RegisterProxyAddressRecord
-static DNSServiceRef sc1, sc2, sc3;     // DNSServiceRefs for kDNSServiceFlagsShareConnection testing
-
-static int num_printed;
-static char addtest = 0;
-static DNSRecordRef record = NULL;
-static char myhinfoW[14] = "\002PC\012Windows XP";
-static char myhinfoX[ 9] = "\003Mac\004OS X";
-static char updatetest[3] = "\002AA";
-static char bigNULL[8192];       // 8K is maximum rdata we support
-static int exitTimeout;          // If nonzero, we exit immediately if kDNSServiceFlagsMoreComing is not set, and after that many seconds otherwise.
-static int exitWhenNoMoreComing; // If true, then when we get a callback with the kDNSServiceFlagsMoreComing bit clear, exit after printing the result.
-
-#if _DNS_SD_LIBDISPATCH
-dispatch_queue_t main_queue;
-dispatch_source_t timer_source;
-#endif
-
-// Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this
-#define LONG_TIME 100000000
-
-static volatile int stopNow = 0;
-static volatile int timeOut = LONG_TIME;
-
-#if _DNS_SD_LIBDISPATCH
-#define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E) \
-    if (main_queue && (E) == kDNSServiceErr_ServiceNotRunning) { fprintf(stderr, "Error code %d\n", (E)); exit(0); }
-#else
-#define EXIT_IF_LIBDISPATCH_FATAL_ERROR(E)
-#endif
-
-//*************************************************************************************************************
-// Supporting Utility Functions
-static uint16_t GetRRClass(const char *s)
-{
-    if (!strcasecmp(s, "IN"))
-        return kDNSServiceClass_IN;
-    else
-        return(atoi(s));
-}
-
-static uint16_t GetRRType(const char *s)
-{
-    if      (!strcasecmp(s, "A"       )) return(kDNSServiceType_A);
-    else if (!strcasecmp(s, "NS"      )) return(kDNSServiceType_NS);
-    else if (!strcasecmp(s, "MD"      )) return(kDNSServiceType_MD);
-    else if (!strcasecmp(s, "MF"      )) return(kDNSServiceType_MF);
-    else if (!strcasecmp(s, "CNAME"   )) return(kDNSServiceType_CNAME);
-    else if (!strcasecmp(s, "SOA"     )) return(kDNSServiceType_SOA);
-    else if (!strcasecmp(s, "MB"      )) return(kDNSServiceType_MB);
-    else if (!strcasecmp(s, "MG"      )) return(kDNSServiceType_MG);
-    else if (!strcasecmp(s, "MR"      )) return(kDNSServiceType_MR);
-    else if (!strcasecmp(s, "NULL"    )) return(kDNSServiceType_NULL);
-    else if (!strcasecmp(s, "WKS"     )) return(kDNSServiceType_WKS);
-    else if (!strcasecmp(s, "PTR"     )) return(kDNSServiceType_PTR);
-    else if (!strcasecmp(s, "HINFO"   )) return(kDNSServiceType_HINFO);
-    else if (!strcasecmp(s, "MINFO"   )) return(kDNSServiceType_MINFO);
-    else if (!strcasecmp(s, "MX"      )) return(kDNSServiceType_MX);
-    else if (!strcasecmp(s, "TXT"     )) return(kDNSServiceType_TXT);
-    else if (!strcasecmp(s, "RP"      )) return(kDNSServiceType_RP);
-    else if (!strcasecmp(s, "AFSDB"   )) return(kDNSServiceType_AFSDB);
-    else if (!strcasecmp(s, "X25"     )) return(kDNSServiceType_X25);
-    else if (!strcasecmp(s, "ISDN"    )) return(kDNSServiceType_ISDN);
-    else if (!strcasecmp(s, "RT"      )) return(kDNSServiceType_RT);
-    else if (!strcasecmp(s, "NSAP"    )) return(kDNSServiceType_NSAP);
-    else if (!strcasecmp(s, "NSAP_PTR")) return(kDNSServiceType_NSAP_PTR);
-    else if (!strcasecmp(s, "SIG"     )) return(kDNSServiceType_SIG);
-    else if (!strcasecmp(s, "KEY"     )) return(kDNSServiceType_KEY);
-    else if (!strcasecmp(s, "PX"      )) return(kDNSServiceType_PX);
-    else if (!strcasecmp(s, "GPOS"    )) return(kDNSServiceType_GPOS);
-    else if (!strcasecmp(s, "AAAA"    )) return(kDNSServiceType_AAAA);
-    else if (!strcasecmp(s, "LOC"     )) return(kDNSServiceType_LOC);
-    else if (!strcasecmp(s, "NXT"     )) return(kDNSServiceType_NXT);
-    else if (!strcasecmp(s, "EID"     )) return(kDNSServiceType_EID);
-    else if (!strcasecmp(s, "NIMLOC"  )) return(kDNSServiceType_NIMLOC);
-    else if (!strcasecmp(s, "SRV"     )) return(kDNSServiceType_SRV);
-    else if (!strcasecmp(s, "ATMA"    )) return(kDNSServiceType_ATMA);
-    else if (!strcasecmp(s, "NAPTR"   )) return(kDNSServiceType_NAPTR);
-    else if (!strcasecmp(s, "KX"      )) return(kDNSServiceType_KX);
-    else if (!strcasecmp(s, "CERT"    )) return(kDNSServiceType_CERT);
-    else if (!strcasecmp(s, "A6"      )) return(kDNSServiceType_A6);
-    else if (!strcasecmp(s, "DNAME"   )) return(kDNSServiceType_DNAME);
-    else if (!strcasecmp(s, "SINK"    )) return(kDNSServiceType_SINK);
-    else if (!strcasecmp(s, "OPT"     )) return(kDNSServiceType_OPT);
-    else if (!strcasecmp(s, "TKEY"    )) return(kDNSServiceType_TKEY);
-    else if (!strcasecmp(s, "TSIG"    )) return(kDNSServiceType_TSIG);
-    else if (!strcasecmp(s, "IXFR"    )) return(kDNSServiceType_IXFR);
-    else if (!strcasecmp(s, "AXFR"    )) return(kDNSServiceType_AXFR);
-    else if (!strcasecmp(s, "MAILB"   )) return(kDNSServiceType_MAILB);
-    else if (!strcasecmp(s, "MAILA"   )) return(kDNSServiceType_MAILA);
-    else if (!strcasecmp(s, "dnskey"  )) return(kDNSServiceType_DNSKEY);
-    else if (!strcasecmp(s, "ds"      )) return(kDNSServiceType_DS);
-    else if (!strcasecmp(s, "rrsig"   )) return(kDNSServiceType_RRSIG);
-    else if (!strcasecmp(s, "nsec"    )) return(kDNSServiceType_NSEC);
-    else if (!strcasecmp(s, "SVCB"    )) return(kDNSServiceType_SVCB);
-    else if (!strcasecmp(s, "HTTPS"   )) return(kDNSServiceType_HTTPS);
-    else if (!strcasecmp(s, "ANY"     )) return(kDNSServiceType_ANY);
-    else return(atoi(s));
-}
-
-static char *DNSTypeName(unsigned short rr_type)
-{
-    switch (rr_type)
-    {
-        case kDNSServiceType_A:          return("Addr");
-        case kDNSServiceType_NS:         return("NS");
-        case kDNSServiceType_MD:         return("MD");
-        case kDNSServiceType_MF:         return("MF");
-        case kDNSServiceType_CNAME:      return("CNAME");
-        case kDNSServiceType_SOA:        return("SOA");
-        case kDNSServiceType_MB:         return("MB");
-        case kDNSServiceType_MG:         return("MG");
-        case kDNSServiceType_MR:         return("MR");
-        case kDNSServiceType_NULL:       return("NULL");
-        case kDNSServiceType_WKS:        return("WKS");
-        case kDNSServiceType_PTR:        return("PTR");
-        case kDNSServiceType_HINFO:      return("HINFO");
-        case kDNSServiceType_MINFO:      return("MINFO");
-        case kDNSServiceType_MX:         return("MX");
-        case kDNSServiceType_TXT:        return("TXT");
-        case kDNSServiceType_RP:         return("RP");
-        case kDNSServiceType_AFSDB:      return("AFSDB");
-        case kDNSServiceType_X25:        return("X25");
-        case kDNSServiceType_ISDN:       return("ISDN");
-        case kDNSServiceType_RT:         return("RT");
-        case kDNSServiceType_NSAP:       return("NSAP");
-        case kDNSServiceType_NSAP_PTR:   return("NSAP_PTR");
-        case kDNSServiceType_SIG:        return("SIG");
-        case kDNSServiceType_KEY:        return("KEY");
-        case kDNSServiceType_PX:         return("PX");
-        case kDNSServiceType_GPOS:       return("GPOS");
-        case kDNSServiceType_AAAA:       return("AAAA");
-        case kDNSServiceType_LOC:        return("LOC");
-        case kDNSServiceType_NXT:        return("NXT");
-        case kDNSServiceType_EID:        return("EID");
-        case kDNSServiceType_NIMLOC:     return("NIMLOC");
-        case kDNSServiceType_SRV:        return("SRV");
-        case kDNSServiceType_ATMA:       return("ATMA");
-        case kDNSServiceType_NAPTR:      return("NAPTR");
-        case kDNSServiceType_KX:         return("KX");
-        case kDNSServiceType_CERT:       return("CERT");
-        case kDNSServiceType_A6:         return("A6");
-        case kDNSServiceType_DNAME:      return("DNAME");
-        case kDNSServiceType_SINK:       return("SINK");
-        case kDNSServiceType_OPT:        return("OPT");
-        case kDNSServiceType_APL:        return("APL");
-        case kDNSServiceType_DS:         return("DS");
-        case kDNSServiceType_SSHFP:      return("SSHFP");
-        case kDNSServiceType_IPSECKEY:   return("IPSECKEY");
-        case kDNSServiceType_RRSIG:      return("RRSIG");
-        case kDNSServiceType_NSEC:       return("NSEC");
-        case kDNSServiceType_DNSKEY:     return("DNSKEY");
-        case kDNSServiceType_DHCID:      return("DHCID");
-        case kDNSServiceType_NSEC3:      return("NSEC3");
-        case kDNSServiceType_NSEC3PARAM: return("NSEC3PARAM");
-        case kDNSServiceType_HIP:        return("HIP");
-        case kDNSServiceType_SPF:        return("SPF");
-        case kDNSServiceType_UINFO:      return("UINFO");
-        case kDNSServiceType_UID:        return("UID");
-        case kDNSServiceType_GID:        return("GID");
-        case kDNSServiceType_UNSPEC:     return("UNSPEC");
-        case kDNSServiceType_TKEY:       return("TKEY");
-        case kDNSServiceType_TSIG:       return("TSIG");
-        case kDNSServiceType_IXFR:       return("IXFR");
-        case kDNSServiceType_AXFR:       return("AXFR");
-        case kDNSServiceType_MAILB:      return("MAILB");
-        case kDNSServiceType_MAILA:      return("MAILA");
-        case kDNSServiceType_SVCB:       return("SVCB");
-        case kDNSServiceType_HTTPS:      return("HTTPS");
-        case kDNSServiceType_ANY:        return("ANY");
-        default:
-        {
-            static char buffer[RR_TYPE_SIZE];
-            snprintf(buffer, sizeof(buffer), "TYPE%d", rr_type);
-            return(buffer);
-        }
-    }
-}
-
-static unsigned short swap16(unsigned short x)
-{
-    unsigned char *ptr = (unsigned char *)&x;
-    return (unsigned short)((unsigned short)ptr[0] << 8 | ptr[1]);
-}
-
-static unsigned int swap32(unsigned int x)
-{
-    unsigned char *ptr = (unsigned char *)&x;
-    return (unsigned int)((unsigned int)ptr[0] << 24 | (unsigned int)ptr[1] << 16 | (unsigned int)ptr[2] << 8 | ptr[3]);
-}
-static unsigned int keytag(unsigned char *key, unsigned int keysize)
-{
-    unsigned long ac;
-    unsigned int i;
-
-    for (ac = 0, i = 0; i < keysize; ++i)
-        ac += (i & 1) ? key[i] : key[i] << 8;
-    ac += (ac >> 16) & 0xFFFF;
-    return ac & 0xFFFF;
-}
-
-// Base 64 encoding according to <https://tools.ietf.org/html/rfc4648#section-4>.
-#define kBase64EncodingTable "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-
-static void base64Encode(char *buffer, size_t buflen, void *rdata, size_t rdlen)
-{
-    const uint8_t *src = (const uint8_t *)rdata;
-    const uint8_t *const end = &src[rdlen];
-    char *dst = buffer;
-    const char *lim;
-
-    if (buflen == 0) return;
-    lim = &buffer[buflen - 1];
-    while ((src < end) && (dst < lim))
-    {
-        uint32_t i;
-        const size_t rem = (size_t)(end - src);
-
-        // Form a 24-bit input group. If less than 24 bits remain, pad with zero bits.
-        if (     rem >= 3) i = (src[0] << 16) | (src[1] << 8) | src[2]; // 24 bits are equal to 4 6-bit groups.
-        else if (rem == 2) i = (src[0] << 16) | (src[1] << 8);          // 16 bits are treated as 3 6-bit groups + 1 pad
-        else               i =  src[0] << 16;                           //  8 bits are treated as 2 6-bit groups + 2 pads
-
-        // Encode each 6-bit group.
-                       *dst++ =              kBase64EncodingTable[(i >> 18) & 0x3F];
-        if (dst < lim) *dst++ =              kBase64EncodingTable[(i >> 12) & 0x3F];
-        if (dst < lim) *dst++ = (rem >= 2) ? kBase64EncodingTable[(i >>  6) & 0x3F] : '=';
-        if (dst < lim) *dst++ = (rem >= 3) ? kBase64EncodingTable[ i        & 0x3F] : '=';
-        src += (rem > 3) ? 3 : rem;
-    }
-    *dst = '\0';
-}
-
-static DNSServiceProtocol GetProtocol(const char *s)
-{
-    if      (!strcasecmp(s, "v4"      )) return(kDNSServiceProtocol_IPv4);
-    else if (!strcasecmp(s, "v6"      )) return(kDNSServiceProtocol_IPv6);
-    else if (!strcasecmp(s, "v4v6"    )) return(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
-    else if (!strcasecmp(s, "v6v4"    )) return(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6);
-    else if (!strcasecmp(s, "udp"     )) return(kDNSServiceProtocol_UDP);
-    else if (!strcasecmp(s, "tcp"     )) return(kDNSServiceProtocol_TCP);
-    else if (!strcasecmp(s, "udptcp"  )) return(kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP);
-    else if (!strcasecmp(s, "tcpudp"  )) return(kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP);
-    else return(atoi(s));
-}
-
-static char
-DNSSECResultToCharRepresentation(const DNSServiceFlags flags)
-{
-    char dnssec_result;
-    if ((flags & kDNSServiceFlagsValidate) == 0)
-    {
-        dnssec_result = ' ';
-    }
-    else if ((flags & kDNSServiceFlagsSecure) == kDNSServiceFlagsSecure)
-    {
-        dnssec_result = 'S';
-    }
-    else if ((flags & kDNSServiceFlagsInsecure) == kDNSServiceFlagsInsecure)
-    {
-        dnssec_result = 'I';
-    }
-    else
-    {
-        dnssec_result = 'E';
-    }
-    return dnssec_result;
-}
-
-//*************************************************************************************************************
-// Sample callback functions for each of the operation types
-
-#define printtimestamp() printtimestamp_F(stdout)
-
-static void printtimestamp_F(FILE *outstream)
-{
-    struct tm tm;
-    int ms;
-    static char date[16];
-    static char new_date[16];
-#ifdef _WIN32
-    SYSTEMTIME sysTime;
-    time_t uct = time(NULL);
-    tm = *localtime(&uct);
-    GetLocalTime(&sysTime);
-    ms = sysTime.wMilliseconds;
-#else
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    localtime_r((time_t*)&tv.tv_sec, &tm);
-    ms = tv.tv_usec/1000;
-#endif
-    strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
-    if (strncmp(date, new_date, sizeof(new_date)))
-    {
-        fprintf(outstream, "DATE: ---%s---\n", new_date); //display date only if it has changed
-        strncpy(date, new_date, sizeof(date));
-    }
-    fprintf(outstream, "%2d:%02d:%02d.%03d  ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
-}
-
-// formating time to RFC 4034 format
-static void FormatTime(unsigned long te, unsigned char *buf, int bufsize)
-{
-    struct tm tmTime;
-#ifdef _WIN32
-    __time32_t t = (__time32_t) te;
-    _gmtime32_s(&tmTime, &t);
-#else
-    // Time since epoch : strftime takes "tm". Convert seconds to "tm" using
-    // gmtime_r first and then use strftime
-    time_t t = (time_t)te;
-    gmtime_r(&t, &tmTime);
-#endif
-    strftime((char *)buf, bufsize, "%Y%m%d%H%M%S", &tmTime);
-}
-
-static void print_usage(const char *arg0, int print_all)
-{
-    // Print the commonly used command line options.  These are listed in "the order they have been in historically".
-    fprintf(stderr, "%s -E                          (Enumerate recommended registration domains)\n", arg0);
-    fprintf(stderr, "%s -F                          (Enumerate recommended browsing     domains)\n", arg0);
-    fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...]         (Register a service)\n", arg0);
-    fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Register Proxy)\n", arg0);
-    fprintf(stderr, "%s -B        <Type> <Domain>                 (Browse for service instances)\n", arg0);
-    fprintf(stderr, "%s -Z        <Type> <Domain>           (Output results in Zone File format)\n", arg0);
-    fprintf(stderr, "%s -L <Name> <Type> <Domain>        (Resolve (‘lookup’) a service instance)\n", arg0);
-    fprintf(stderr, "%s -Q <name> <rrtype> <rrclass>         (Generic query for any record type)\n", arg0);
-    fprintf(stderr, "%s -q <name> <rrtype> <rrclass>     (Generic query, using SuppressUnusable)\n", arg0);
-    fprintf(stderr, "%s -G v4/v6/v4v6 <hostname>          (Get address information for hostname)\n", arg0);
-    fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL>           (NAT Port Mapping)\n", arg0);
-    fprintf(stderr, "%s -H                               (Print usage for complete command list)\n", arg0);
-    fprintf(stderr, "%s -V            (Get version of currently running daemon / system service)\n", arg0);
-
-    if (print_all)  // Print all available options for dns-sd tool.  Keep these in alphabetical order for easier maintenance.
-    {
-        fprintf(stderr, "\n");
-        fprintf(stderr, "%s -A                              (Test Adding/Updating/Deleting a record)\n", arg0);
-        fprintf(stderr, "%s -C <name> <rrtype> <rrclass>           (Query; reconfirming each result)\n", arg0);
-        fprintf(stderr, "%s -D                               (Set kDNSServiceFlagsEnableDNSSEC flag)\n", arg0);
-        fprintf(stderr, "%s -I           (Test registering and then immediately updating TXT record)\n", arg0);
-        fprintf(stderr, "%s -N                                     (Test adding a large NULL record)\n", arg0);
-        fprintf(stderr, "%s -M              (Test creating a registration with multiple TXT records)\n", arg0);
-        fprintf(stderr, "%s -S                         (Test multiple operations on a shared socket)\n", arg0);
-        fprintf(stderr, "%s -T                                    (Test creating a large TXT record)\n", arg0);
-        fprintf(stderr, "%s -U                                          (Test updating a TXT record)\n", arg0);
-        fprintf(stderr, "%s -ble                                  (Use kDNSServiceInterfaceIndexBLE)\n", arg0);
-        fprintf(stderr, "%s -fmc                      (Force multicast--use mDNS even if not .local)\n", arg0);
-        fprintf(stderr, "%s -i <Interface>         (Run dns-sd cmd on a specific interface (en0/en1)\n", arg0);
-        fprintf(stderr, "%s -includep2p                        (Set kDNSServiceFlagsIncludeP2P flag)\n", arg0);
-        fprintf(stderr, "%s -includeAWDL                      (Set kDNSServiceFlagsIncludeAWDL flag)\n", arg0);
-        fprintf(stderr, "%s -intermediates            (Set kDNSServiceFlagsReturnIntermediates flag)\n", arg0);
-        fprintf(stderr, "%s -ku                               (Set kDNSServiceFlagsKnownUnique flag)\n", arg0);
-        fprintf(stderr, "%s -lo                          (Run dns-sd cmd using local only interface)\n", arg0);
-        fprintf(stderr, "%s -m                    (Exit when no more results are coming immediately)\n", arg0);
-        fprintf(stderr, "%s -p2p                                  (Use kDNSServiceInterfaceIndexP2P)\n", arg0);
-        fprintf(stderr, "%s -sh                                    (Set kDNSServiceFlagsShared flag)\n", arg0);
-        fprintf(stderr, "%s -t <seconds>                                      (Exit after <seconds>)\n", arg0);
-        fprintf(stderr, "%s -tc                    (Set kDNSServiceFlagsBackgroundTrafficClass flag)\n", arg0);
-        fprintf(stderr, "%s -test                                  (Run basic API input range tests)\n", arg0);
-        fprintf(stderr, "%s -t1                              (Set kDNSServiceFlagsThresholdOne flag)\n", arg0);
-        fprintf(stderr, "%s -tFinder                      (Set kDNSServiceFlagsThresholdFinder flag)\n", arg0);
-        fprintf(stderr, "%s -timeout                              (Set kDNSServiceFlagsTimeout flag)\n", arg0);
-        fprintf(stderr, "%s -unicastResponse              (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0);
-        fprintf(stderr, "%s -autoTrigger                      (Set kDNSServiceFlagsAutoTrigger flag)\n", arg0);
-    }
-}
-
-#define DomainMsg(X) (((X) &kDNSServiceFlagsDefault) ? "(Default)" : \
-                      ((X) &kDNSServiceFlagsAdd)     ? "Added"     : "Removed")
-
-#define MAX_LABELS 128
-
-static void DNSSD_API enum_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex,
-                                 DNSServiceErrorType errorCode, const char *replyDomain, void *context)
-{
-    DNSServiceFlags partialflags = flags & ~(kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault);
-    int labels = 0, depth = 0, i, initial = 0;
-    char text[64];
-    const char *label[MAX_LABELS];
-
-    (void)sdref;        // Unused
-    (void)ifIndex;      // Unused
-    (void)context;      // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    // 1. Print the header
-    if (num_printed++ == 0) printf("Timestamp     Recommended %s domain\n", operation == 'E' ? "Registration" : "Browsing");
-    printtimestamp();
-    if (errorCode)
-        printf("Error code %d\n", errorCode);
-    else if (!*replyDomain)
-        printf("Error: No reply domain\n");
-    else
-    {
-        printf("%-10s", DomainMsg(flags));
-        printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : "");
-        if (partialflags) printf("Flags: %4X  ", partialflags);
-        else printf("             ");
-
-        // 2. Count the labels
-        while (replyDomain && *replyDomain && labels < MAX_LABELS)
-        {
-            label[labels++] = replyDomain;
-            replyDomain = GetNextLabel(replyDomain, text);
-        }
-
-        // 3. Decide if we're going to clump the last two or three labels (e.g. "apple.com", or "nicta.com.au")
-        if      (labels >= 3 && replyDomain - label[labels-1] <= 3 && label[labels-1] - label[labels-2] <= 4) initial = 3;
-        else if (labels >= 2 && replyDomain - label[labels-1] <= 4) initial = 2;
-        else initial = 1;
-        labels -= initial;
-
-        // 4. Print the initial one-, two- or three-label clump
-        for (i=0; i<initial; i++)
-        {
-            GetNextLabel(label[labels+i], text);
-            if (i>0) printf(".");
-            printf("%s", text);
-        }
-        printf("\n");
-
-        // 5. Print the remainder of the hierarchy
-        for (depth=0; depth<labels; depth++)
-        {
-            printf("                                             ");
-            for (i=0; i<=depth; i++) printf("- ");
-            GetNextLabel(label[labels-1-depth], text);
-            printf("> %s\n", text);
-        }
-    }
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static int CopyLabels(char *dst, const char *lim, const char **srcp, int labels)
-{
-    const char *src = *srcp;
-    while (*src != '.' || --labels > 0)
-    {
-        if (*src == '\\') *dst++ = *src++;  // Make sure "\." doesn't confuse us
-        if (!*src || dst >= lim) return -1;
-        *dst++ = *src++;
-        if (!*src || dst >= lim) return -1;
-    }
-    *dst++ = 0;
-    *srcp = src + 1;    // skip over final dot
-    return 0;
-}
-
-static void DNSSD_API zonedata_resolve(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
-                                       const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txt, void *context)
-{
-    union { uint16_t s; u_char b[2]; } port = { opaqueport };
-    uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
-
-    const char *p = fullname;
-    char n[kDNSServiceMaxDomainName];
-    char t[kDNSServiceMaxDomainName];
-
-    const unsigned char *max = txt + txtLen;
-
-    (void)sdref;        // Unused
-    (void)ifIndex;      // Unused
-    (void)context;      // Unused
-
-    //if (!(flags & kDNSServiceFlagsAdd)) return;
-    if (errorCode) { printf("Error code %d\n", errorCode); return; }
-
-    if (CopyLabels(n, n + kDNSServiceMaxDomainName, &p, 3)) return;     // Fetch name+type
-    p = fullname;
-    if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 1)) return;     // Skip first label
-    if (CopyLabels(t, t + kDNSServiceMaxDomainName, &p, 2)) return;     // Fetch next two labels (service type)
-
-    if (num_printed++ == 0)
-    {
-        printf("\n");
-        printf("; To direct clients to browse a different domain, substitute that domain in place of '@'\n");
-        printf("%-47s PTR     %s\n", "lb._dns-sd._udp", "@");
-        printf("\n");
-        printf("; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.\n");
-        printf("; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local\n");
-        printf("; names with the correct fully-qualified (unicast) domain name of the target host offering the service.\n");
-    }
-
-    printf("\n");
-    printf("%-47s PTR     %s\n", t, n);
-    printf("%-47s SRV     0 0 %d %s ; Replace with unicast FQDN of target host\n", n, PortAsNumber, hosttarget);
-    printf("%-47s TXT    ", n);
-
-    while (txt < max)
-    {
-        const unsigned char *const end = txt + 1 + txt[0];
-        txt++;      // Skip over length byte
-        printf(" \"");
-        while (txt<end)
-        {
-            if (*txt == '\\' || *txt == '\"') printf("\\");
-            printf("%c", *txt++);
-        }
-        printf("\"");
-    }
-    printf("\n");
-
-    DNSServiceRefDeallocate(sdref);
-    free(context);
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static void DNSSD_API zonedata_browse(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
-                                      const char *replyName, const char *replyType, const char *replyDomain, void *context)
-{
-    DNSServiceRef *newref;
-
-    (void)sdref;        // Unused
-    (void)context;      // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    if (!(flags & kDNSServiceFlagsAdd)) return;
-    if (errorCode) { printf("Error code %d\n", errorCode); return; }
-
-    newref = malloc(sizeof(*newref));
-    *newref = client;
-    DNSServiceResolve(newref, kDNSServiceFlagsShareConnection, ifIndex, replyName, replyType, replyDomain, zonedata_resolve, newref);
-}
-
-static void DNSSD_API browse_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
-                                   const char *replyName, const char *replyType, const char *replyDomain, void *context)
-{
-    char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
-    (void)sdref;        // Unused
-    (void)context;      // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    if (num_printed++ == 0) printf("Timestamp     A/R    Flags  if %-20s %-20s %s\n", "Domain", "Service Type", "Instance Name");
-    printtimestamp();
-    if (errorCode)
-        printf("Error code %d\n", errorCode);
-    else
-        printf("%s %8X %3d %-20s %-20s %s\n",
-                op, flags, ifIndex, replyDomain, replyType, replyName);
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-
-    // To test selective cancellation of operations of shared sockets,
-    // cancel the current operation when we've got a multiple of five results
-    //if (operation == 'S' && num_printed % 5 == 0) DNSServiceRefDeallocate(sdref);
-}
-
-static void ShowTXTRecord(uint16_t txtLen, const unsigned char *txtRecord)
-{
-    const unsigned char *ptr = txtRecord;
-    const unsigned char *max = txtRecord + txtLen;
-    while (ptr < max)
-    {
-        const unsigned char *const end = ptr + 1 + ptr[0];
-        if (end > max) { printf("<< invalid data >>"); break; }
-        if (++ptr < end) printf(" ");   // As long as string is non-empty, begin with a space
-        while (ptr<end)
-        {
-            // We'd like the output to be shell-friendly, so that it can be copied and pasted unchanged into a "dns-sd -R" command.
-            // However, this is trickier than it seems. Enclosing a string in double quotes doesn't necessarily make it
-            // shell-safe, because shells still expand variables like $foo even when they appear inside quoted strings.
-            // Enclosing a string in single quotes is better, but when using single quotes even backslash escapes are ignored,
-            // meaning there's simply no way to represent a single quote (or apostrophe) inside a single-quoted string.
-            // The only remaining solution is not to surround the string with quotes at all, but instead to use backslash
-            // escapes to encode spaces and all other known shell metacharacters.
-            // (If we've missed any known shell metacharacters, please let us know.)
-            // In addition, non-printing ascii codes (0-31) are displayed as \xHH, using a two-digit hex value.
-            // Because '\' is itself a shell metacharacter (the shell escape character), it has to be escaped as "\\" to survive
-            // the round-trip to the shell and back. This means that a single '\' is represented here as EIGHT backslashes:
-            // The C compiler eats half of them, resulting in four appearing in the output.
-            // The shell parses those four as a pair of "\\" sequences, passing two backslashes to the "dns-sd -R" command.
-            // The "dns-sd -R" command interprets this single "\\" pair as an escaped literal backslash. Sigh.
-            if (strchr(" &;`'\"|*?~<>^()[]{}$", *ptr)) printf("\\");
-            if      (*ptr == '\\') printf("\\\\\\\\");
-            else if (*ptr >= ' ' ) printf("%c",        *ptr);
-            else printf("\\\\x%02X", *ptr);
-            ptr++;
-        }
-    }
-}
-
-static void DNSSD_API resolve_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
-                                    const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txtRecord, void *context)
-{
-    union { uint16_t s; u_char b[2]; } port = { opaqueport };
-    uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1];
-
-    (void)sdref;        // Unused
-    (void)ifIndex;      // Unused
-    (void)context;      // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    printtimestamp();
-
-    printf("%s ", fullname);
-
-    if (errorCode == kDNSServiceErr_NoSuchRecord) printf("No Such Record");
-    else if (errorCode) printf("error code %d\n", errorCode);
-    else printf("can be reached at %s:%u (interface %d)", hosttarget, PortAsNumber, ifIndex);
-
-    if (flags) printf(" Flags: %X", flags);
-
-    // Don't show degenerate TXT records containing nothing but a single empty string
-    if (!errorCode && txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
-
-    printf("\n");
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static void myTimerCallBack(void)
-{
-    DNSServiceErrorType err = kDNSServiceErr_Unknown;
-
-    switch (operation)
-    {
-    case 'A':
-    {
-        switch (addtest)
-        {
-        case 0: printf("Adding Test HINFO record\n");
-            err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_HINFO, sizeof(myhinfoW), &myhinfoW[0], 0);
-            addtest = 1;
-            break;
-        case 1: printf("Updating Test HINFO record\n");
-            err = DNSServiceUpdateRecord(client, record, 0, sizeof(myhinfoX), &myhinfoX[0], 0);
-            addtest = 2;
-            break;
-        case 2: printf("Removing Test HINFO record\n");
-            err = DNSServiceRemoveRecord(client, record, 0);
-            addtest = 0;
-            break;
-        }
-    }
-    break;
-
-    case 'U':
-    {
-        if (updatetest[1] != 'Z') updatetest[1]++;
-        else updatetest[1] = 'A';
-        // The following line toggles the string length between 1 and 2 characters.
-        updatetest[0] = 3 - updatetest[0];
-        updatetest[2] = updatetest[1];
-        printtimestamp();
-        printf("Updating Test TXT record to %c\n", updatetest[1]);
-        err = DNSServiceUpdateRecord(client, NULL, 0, 1+updatetest[0], &updatetest[0], 0);
-    }
-    break;
-
-    case 'N':
-    {
-        printf("Adding big NULL record\n");
-        err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_NULL, sizeof(bigNULL), &bigNULL[0], 0);
-        if (err) printf("Failed: %d\n", err);else printf("Succeeded\n");
-        timeOut = LONG_TIME;
-#if _DNS_SD_LIBDISPATCH
-        if (timer_source)
-            dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
-                                      (uint64_t)timeOut * NSEC_PER_SEC, 0);
-#endif
-    }
-    break;
-    }
-
-    if (err != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "DNSService add/update/remove failed %ld\n", (long int)err);
-        stopNow = 1;
-    }
-}
-
-static void DNSSD_API reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                                const char *name, const char *regtype, const char *domain, void *context)
-{
-    (void)sdref;    // Unused
-    (void)flags;    // Unused
-    (void)context;  // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    printtimestamp();
-    printf("Got a reply for service %s.%s%s: ", name, regtype, domain);
-
-    if (errorCode == kDNSServiceErr_NoError)
-    {
-        if (flags & kDNSServiceFlagsAdd) printf("Name now registered and active\n");
-        else printf("Name registration removed\n");
-        if (operation == 'A' || operation == 'U' || operation == 'N')
-        {
-            timeOut = 5;
-#if _DNS_SD_LIBDISPATCH
-            if (timer_source)
-                dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
-                                          (uint64_t)timeOut * NSEC_PER_SEC, 0);
-#endif
-        }
-    }
-    else if (errorCode == kDNSServiceErr_NameConflict)
-    {
-        printf("Name in use, please choose another\n");
-        exit(-1);
-    }
-    else
-        printf("Error %d\n", errorCode);
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-__printflike(3, 4)
-static int snprintf_safe(char *str, size_t size, const char *format, ...)
-{
-    int length = 0;
-    va_list ptr;
-    va_start(ptr, format);
-    int result = vsnprintf(str, size, format, ptr);
-    va_end(ptr);
-    if (result > 0 && size > 0)
-    {
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-        length = (int)MIN((size_t)result, size-1);
-    }
-    return length;
-}
-
-// Output the wire-format domainname pointed to by rd
-static size_t snprintd(char *p, size_t max, const unsigned char **rd)
-{
-    const char *const buf = p;
-    const char *const end = p + max;
-    while (**rd)
-    {
-        p += snprintf_safe(p, end-p, "%.*s.", **rd, *rd+1);
-        *rd += 1 + **rd;
-    }
-    *rd += 1;   // Advance over the final zero byte
-    return(p-buf);
-}
-
-static void ParseDNSSECRecords(uint16_t rrtype, char *rdb, size_t rdb_size, unsigned const char *rd, uint16_t rdlen)
-{
-    char *p = rdb;
-    switch (rrtype)
-    {
-        case kDNSServiceType_DS:
-        {
-            unsigned char *ptr;
-            int i;
-            rdataDS *rrds = (rdataDS *)rd;
-            p += snprintf_safe(p, rdb + rdb_size - p, "%d  %d  %d  ",
-                          rrds->alg, swap16(rrds->keyTag), rrds->digestType);
-            ptr = (unsigned char *)(rd + DS_FIXED_SIZE);
-            for (i = 0; i < (rdlen - DS_FIXED_SIZE); i++)
-                p += snprintf_safe(p, rdb + rdb_size - p, "%x", ptr[i]);
-            break;
-        }
-
-        case kDNSServiceType_DNSKEY:
-        {
-            rdataDNSKey *rrkey = (rdataDNSKey *)rd;
-            p += snprintf_safe(p, rdb + rdb_size - p, "%d  %d  %d  %u ", swap16(rrkey->flags), rrkey->proto,
-                          rrkey->alg, (unsigned int)keytag((unsigned char *)rrkey, rdlen));
-            base64Encode(p, rdb + rdb_size - p, (unsigned char *)(rd + DNSKEY_FIXED_SIZE), rdlen - DNSKEY_FIXED_SIZE);
-            break;
-        }
-
-        case kDNSServiceType_NSEC:
-        {
-            unsigned char *next = (unsigned char *)rd;
-            size_t len, bitmaplen;
-            size_t win, wlen, type;
-            unsigned char *bmap;
-            char *l = NULL;
-
-            l = p;
-            p += snprintd(p, rdb + rdb_size - p, &rd);
-            len = p - l + 1;
-
-            bitmaplen = rdlen - len;
-            bmap = (unsigned char *)((unsigned char *)next + len);
-
-            while (bitmaplen > 0)
-            {
-                size_t i;
-
-                if (bitmaplen < 3)
-                {
-                    printf("Case NSEC: malformed nsec, bitmaplen %zu short\n", bitmaplen);
-                    break;
-                }
-
-                win = *bmap++;
-                wlen = *bmap++;
-                bitmaplen -= 2;
-                if (bitmaplen < wlen || wlen < 1 || wlen > 32)
-                {
-                    printf("Case NSEC: malformed nsec, bitmaplen %zu wlen %zu\n", bitmaplen, wlen);
-                    break;
-                }
-                if (win >= 256)
-                {
-                    printf("Case NSEC: malformed nsec, bad window win %zu\n", win);
-                    break;
-                }
-                type = win * 256;
-                for (i = 0; i < wlen * 8; i++)
-                {
-                    if (bmap[i>>3] & (128 >> (i&7)))
-                        p += snprintf_safe(p, rdb + rdb_size - p, " %s ", DNSTypeName(type + i));
-                }
-                bmap += wlen;
-                bitmaplen -= wlen;
-            }
-            break;
-        }
-
-        case kDNSServiceType_RRSIG:
-        {
-            rdataRRSig *rrsig = (rdataRRSig *)rd;
-            unsigned char expTimeBuf[64];
-            unsigned char inceptTimeBuf[64];
-            unsigned long inceptClock;
-            unsigned long expClock;
-            const unsigned char *q = NULL;
-            char *k = NULL;
-            size_t len;
-
-            expClock = (unsigned long)swap32(rrsig->sigExpireTime);
-            FormatTime(expClock, expTimeBuf, sizeof(expTimeBuf));
-
-            inceptClock = (unsigned long)swap32(rrsig->sigInceptTime);
-            FormatTime(inceptClock, inceptTimeBuf, sizeof(inceptTimeBuf));
-
-            p += snprintf_safe(p, rdb + rdb_size - p, " %-7s  %d  %d  %d  %s  %s  %7d  ",
-                          DNSTypeName(swap16(rrsig->typeCovered)), rrsig->alg, rrsig->labels, swap32(rrsig->origTTL),
-                          expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag));
-
-            q = (const unsigned char *)&rrsig->signerName;
-            k = p;
-            p += snprintd(p, rdb + rdb_size - p, &q);
-            len = p - k + 1;
-
-            if ((&rdb[rdb_size] - p) >= 2)
-            {
-                *p++ = ' ';
-                *p   = '\0';
-            }
-            base64Encode(p, rdb + rdb_size - p, (unsigned char *)(rd + len + RRSIG_FIXED_SIZE), rdlen - (len + RRSIG_FIXED_SIZE));
-            break;
-        }
-    }
-    return;
-}
-
-static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
-                               const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
-{
-    char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
-    const unsigned char *rd  = rdata;
-    const unsigned char *end = (const unsigned char *) rdata + rdlen;
-    char rdb[1000] = "0.0.0.0", *p = rdb;
-    int unknowntype = 0;
-    char rr_type[RR_TYPE_SIZE];
-    char rr_class[6];
-
-    (void)sdref;    // Unused
-    (void)ifIndex;  // Unused
-    (void)ttl;      // Unused
-    (void)context;  // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    if (num_printed++ == 0)
-    {
-        printf("Timestamp     %3s  %-11s  %3s  %-29s %-6s %-6s Rdata\n", "A/R", "Flags", "IF", "Name", "Type", "Class");
-    }
-    printtimestamp();
-
-    switch (rrclass)
-    {
-        case kDNSServiceClass_IN:
-            strncpy(rr_class, "IN", sizeof(rr_class));
-            break;
-        default:
-            snprintf(rr_class, sizeof(rr_class), "%d", rrclass);
-            break;
-    }
-    strncpy(rr_type, DNSTypeName(rrtype), sizeof(rr_type));
-
-    if (!errorCode) //to avoid printing garbage in rdata
-    {
-        switch (rrtype)
-        {
-            case kDNSServiceType_A:
-                snprintf_safe(rdb, sizeof(rdb), "%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]);
-                break;
-
-            case kDNSServiceType_NS:
-            case kDNSServiceType_CNAME:
-            case kDNSServiceType_PTR:
-            case kDNSServiceType_DNAME:
-                snprintd(p, sizeof(rdb), &rd);
-                break;
-
-            case kDNSServiceType_SOA:
-                p += snprintd(p, rdb + sizeof(rdb) - p, &rd);           // mname
-                p += snprintf_safe(p, rdb + sizeof(rdb) - p, " ");
-                p += snprintd(p, rdb + sizeof(rdb) - p, &rd);           // rname
-                     snprintf(p, rdb + sizeof(rdb) - p, " Ser %d Ref %d Ret %d Exp %d Min %d",
-                         ntohl(((uint32_t*)rd)[0]), ntohl(((uint32_t*)rd)[1]), ntohl(((uint32_t*)rd)[2]), ntohl(((uint32_t*)rd)[3]), ntohl(((uint32_t*)rd)[4]));
-                break;
-
-            case kDNSServiceType_AAAA:
-                snprintf(rdb, sizeof(rdb), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X",
-                    rd[0x0], rd[0x1], rd[0x2], rd[0x3], rd[0x4], rd[0x5], rd[0x6], rd[0x7],
-                    rd[0x8], rd[0x9], rd[0xA], rd[0xB], rd[0xC], rd[0xD], rd[0xE], rd[0xF]);
-                break;
-
-            case kDNSServiceType_SRV:
-                p += snprintf_safe(p, rdb + sizeof(rdb) - p, "%d %d %d ",        // priority, weight, port
-                         ntohs(*(unsigned short*)rd), ntohs(*(unsigned short*)(rd+2)), ntohs(*(unsigned short*)(rd+4)));
-                rd += 6;
-                     snprintd(p, rdb + sizeof(rdb) - p, &rd);               // target host
-                break;
-
-            case kDNSServiceType_DS:
-            case kDNSServiceType_DNSKEY:
-            case kDNSServiceType_NSEC:
-            case kDNSServiceType_RRSIG:
-                ParseDNSSECRecords(rrtype, rdb, sizeof(rdb), rd, rdlen);
-                break;
-
-            default:
-                snprintf(rdb, sizeof(rdb), "%d bytes%s", rdlen, rdlen ? ":" : "");
-                unknowntype = 1;
-                break;
-        }
-    }
-
-    const char dnssec_result = DNSSECResultToCharRepresentation(flags);
-
-    printf("%-3s  %-9X %c  %3d  %-29s %-6s %-6s %s",
-        op, flags, dnssec_result, ifIndex, fullname, rr_type, rr_class, rdb);
-
-    if (unknowntype)
-    {
-        while (rd < end)
-            printf(" %02X", *rd++);
-    }
-    if (errorCode)
-    {
-        if (errorCode == kDNSServiceErr_NoSuchRecord)
-            printf("    No Such Record");
-        else if (errorCode == kDNSServiceErr_NoAuth)
-            printf("    No Authorization");
-        else if (errorCode == kDNSServiceErr_Timeout)
-        {
-            printf("    No Such Record\n");
-            printf("Query Timed Out\n");
-            exit(1);
-        }
-    }
-    printf("\n");
-
-    if (operation == 'C')
-        if (flags & kDNSServiceFlagsAdd)
-            DNSServiceReconfirmRecord(flags, ifIndex, fullname, rrtype, rrclass, rdlen, rdata);
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, uint32_t publicAddress, uint32_t protocol, uint16_t privatePort, uint16_t publicPort, uint32_t ttl, void *context)
-{
-    (void)sdref;       // Unused
-    (void)flags;       // Unused
-    (void)context;     // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    if (num_printed++ == 0) printf("Timestamp     if   %-20s %-15s %-15s %-15s %-6s\n", "External Address", "Protocol", "Internal Port", "External Port", "TTL");
-    printtimestamp();
-    if (errorCode && errorCode != kDNSServiceErr_DoubleNAT) printf("Error code %d\n", errorCode);
-    else
-    {
-        const unsigned char *digits = (const unsigned char *)&publicAddress;
-        char addr[256];
-
-        snprintf(addr, sizeof(addr), "%d.%d.%d.%d", digits[0], digits[1], digits[2], digits[3]);
-        printf("%-4d %-20s %-15d %-15d %-15d %-6d%s\n", ifIndex, addr, protocol, ntohs(privatePort), ntohs(publicPort), ttl, errorCode == kDNSServiceErr_DoubleNAT ? " Double NAT" : "");
-    }
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static void DNSSD_API addrinfo_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context)
-{
-    char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv";
-    char addr[256] = "";
-    (void) sdref;
-    (void) context;
-
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    if (num_printed++ == 0)
-    {
-        printf("Timestamp     %3s  %-11s  %3s  %-38s %-44s %s\n", "A/R", "Flags", "IF", "Hostname", "Address", "TTL");
-    }
-    printtimestamp();
-
-    if (address && address->sa_family == AF_INET)
-    {
-        const unsigned char *b = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr;
-        snprintf(addr, sizeof(addr), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
-    }
-    else if (address && address->sa_family == AF_INET6)
-    {
-        char if_name[IFNAMSIZ];     // Older Linux distributions don't define IF_NAMESIZE
-        const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *)address;
-        const unsigned char       *b  = (const unsigned char *      )&s6->sin6_addr;
-        if (!if_indextoname(s6->sin6_scope_id, if_name))
-            snprintf(if_name, sizeof(if_name), "<%d>", s6->sin6_scope_id);
-        snprintf(addr, sizeof(addr), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%%%s",
-            b[0x0], b[0x1], b[0x2], b[0x3], b[0x4], b[0x5], b[0x6], b[0x7],
-            b[0x8], b[0x9], b[0xA], b[0xB], b[0xC], b[0xD], b[0xE], b[0xF], if_name);
-    }
-
-    const char dnssec_result = DNSSECResultToCharRepresentation(flags);
-
-    printf("%-3s  %-9X %c  %3d  %-38s %-44s %d", op, flags, dnssec_result, interfaceIndex, hostname, addr, ttl);
-
-    if (errorCode)
-    {
-        if (errorCode == kDNSServiceErr_NoSuchRecord)
-            printf("   No Such Record");
-        else
-            printf("   Error code %d", errorCode);
-    }
-    printf("\n");
-
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-//*************************************************************************************************************
-// The main test function
-
-static void HandleEvents(void)
-#if _DNS_SD_LIBDISPATCH
-{
-    main_queue = dispatch_get_main_queue();
-    if (client) DNSServiceSetDispatchQueue(client, main_queue);
-    if (client_pa) DNSServiceSetDispatchQueue(client_pa, main_queue);
-    if (operation == 'A' || operation == 'U' || operation == 'N')
-    {
-        timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_queue);
-        if (timer_source)
-        {
-            // Start the timer "timeout" seconds into the future and repeat it every "timeout" seconds
-            dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)timeOut * NSEC_PER_SEC),
-                                      (uint64_t)timeOut * NSEC_PER_SEC, 0);
-            dispatch_source_set_event_handler(timer_source, ^{myTimerCallBack();});
-            dispatch_resume(timer_source);
-        }
-    }
-    if (exitTimeout > 0)
-    {
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (uint64_t)exitTimeout * NSEC_PER_SEC), main_queue,
-                       ^{
-                           exit(0);
-                       });
-    }
-    dispatch_main();
-}
-#else
-{
-    int dns_sd_fd  = client    ? DNSServiceRefSockFD(client   ) : -1;
-    int dns_sd_fd2 = client_pa ? DNSServiceRefSockFD(client_pa) : -1;
-    int nfds = dns_sd_fd + 1;
-    fd_set readfds;
-    struct timeval tv;
-    int result;
-    uint64_t timeout_when, now;
-    int expectingMyTimer;
-
-    if (dns_sd_fd2 > dns_sd_fd) nfds = dns_sd_fd2 + 1;
-
-    if (exitTimeout != 0) {
-        gettimeofday(&tv, NULL);
-        timeout_when = tv.tv_sec * 1000ULL * 1000ULL + tv.tv_usec + exitTimeout * 1000ULL * 1000ULL;
-    }
-
-    while (!stopNow)
-    {
-        // 1. Set up the fd_set as usual here.
-        // This example client has no file descriptors of its own,
-        // but a real application would call FD_SET to add them to the set here
-        FD_ZERO(&readfds);
-
-        // 2. Add the fd for our client(s) to the fd_set
-        if (client   ) FD_SET(dns_sd_fd, &readfds);
-        if (client_pa) FD_SET(dns_sd_fd2, &readfds);
-
-        // 3. Set up the timeout.
-        expectingMyTimer = 1;
-        if (exitTimeout > 0) {
-            gettimeofday(&tv, NULL);
-            now = tv.tv_sec * 1000ULL * 1000ULL + tv.tv_usec;
-            if (timeout_when <= now) {
-                exit(0);
-            }
-            if (timeout_when - now < timeOut * 1000ULL * 1000ULL) {
-                tv.tv_sec = (time_t)(timeout_when - now) / 1000 / 1000;
-                tv.tv_usec = (suseconds_t)(timeout_when % (1000 * 1000));
-                expectingMyTimer = 0;
-            }
-        }
-        if (expectingMyTimer) {
-            tv.tv_sec  = timeOut;
-            tv.tv_usec = 0;
-        }
-        result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
-        if (result > 0)
-        {
-            DNSServiceErrorType err = kDNSServiceErr_NoError;
-            if      (client    && FD_ISSET(dns_sd_fd, &readfds)) err = DNSServiceProcessResult(client   );
-            else if (client_pa && FD_ISSET(dns_sd_fd2, &readfds)) err = DNSServiceProcessResult(client_pa);
-            if (err) { printtimestamp_F(stderr); fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; }
-        }
-        else if (result == 0)
-        {
-            if (expectingMyTimer)
-            {
-                myTimerCallBack();
-            }
-            else
-            {
-                // exitTimeout has elapsed.
-                exit(0);
-            }
-        }
-        else
-        {
-            printf("select() returned %d errno %d %s\n", result, errno, strerror(errno));
-            if (errno != EINTR) stopNow = 1;
-        }
-    }
-}
-#endif
-
-static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptInd)
-// Return the recognized option in optstr and the option index of the next arg.
-#if NOT_HAVE_GETOPT
-{
-    int i;
-    for (i=1; i < argc; i++)
-    {
-        if (argv[i][0] == '-' && &argv[i][1] &&
-            NULL != strchr(optstr, argv[i][1]))
-        {
-            *pOptInd = i + 1;
-            return argv[i][1];
-        }
-    }
-    return -1;
-}
-#else
-{
-    int o = getopt(argc, (char *const *)argv, optstr);
-    *pOptInd = optind;
-    return o;
-}
-#endif
-
-static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef rec, const DNSServiceFlags flags,
-                                               DNSServiceErrorType errorCode, void *context)
-{
-    char *name = (char *)context;
-
-    (void)service;  // Unused
-    (void)rec;      // Unused
-    (void)flags;    // Unused
-    EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
-
-    printtimestamp();
-    printf("Got a reply for record %s: ", name);
-
-    switch (errorCode)
-    {
-    case kDNSServiceErr_NoError:      printf("Name now registered and active\n"); break;
-    case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1);
-    default:                          printf("Error %d\n", errorCode); break;
-    }
-    if (!(flags & kDNSServiceFlagsMoreComing))
-    {
-        fflush(stdout);
-        if (exitWhenNoMoreComing) exit(0);
-    }
-}
-
-static void getip(const char *const name, struct sockaddr_storage *result)
-{
-    struct addrinfo *addrs = NULL;
-    int err = getaddrinfo(name, NULL, NULL, &addrs);
-    if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
-    else memcpy(result, addrs->ai_addr, SA_LEN(addrs->ai_addr));
-    if (addrs) freeaddrinfo(addrs);
-}
-
-static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const char *host, const char *ip, DNSServiceFlags flags)
-{
-    // Call getip() after the call DNSServiceCreateConnection().
-    // On the Win32 platform, WinSock must be initialized for getip() to succeed.
-    // Any DNSService* call will initialize WinSock for us, so we make sure
-    // DNSServiceCreateConnection() is called before getip() is.
-    struct sockaddr_storage hostaddr;
-    memset(&hostaddr, 0, sizeof(hostaddr));
-    getip(ip, &hostaddr);
-    if (!(flags & kDNSServiceFlagsShared))
-    {
-        flags |= kDNSServiceFlagsUnique;
-    }
-    if (hostaddr.ss_family == AF_INET)
-        return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
-                                        kDNSServiceType_A,    kDNSServiceClass_IN,  4, &((struct sockaddr_in *)&hostaddr)->sin_addr,  240, MyRegisterRecordCallback, (void*)host));
-    else if (hostaddr.ss_family == AF_INET6)
-        return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
-                                        kDNSServiceType_AAAA, kDNSServiceClass_IN, 16, &((struct sockaddr_in6*)&hostaddr)->sin6_addr, 240, MyRegisterRecordCallback, (void*)host));
-    else return(kDNSServiceErr_BadParam);
-}
-
-#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :  \
-                    ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :  \
-                    ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : 0)
-
-#define HexPair(P) ((HexVal((P)[0]) << 4) | HexVal((P)[1]))
-
-#define MAXTXTRecordSize 8900
-static DNSServiceErrorType RegisterService(DNSServiceRef *sdref,
-                                           const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv, DNSServiceFlags flags, const char **callName)
-{
-    uint16_t PortAsNumber = atoi(port);
-    Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } };
-    unsigned char txt[MAXTXTRecordSize];
-    txt[0] = '\0';
-    unsigned char *ptr = txt;
-    int i;
-
-    if (nam[0] == '.' && nam[1] == 0) nam = "";   // We allow '.' on the command line as a synonym for empty string
-    if (dom[0] == '.' && dom[1] == 0) dom = "";   // We allow '.' on the command line as a synonym for empty string
-
-    printf("Registering Service %s.%s%s%s", nam[0] ? nam : "<<Default>>", typ, dom[0] ? "." : "", dom);
-    if (host && *host) printf(" host %s", host);
-    printf(" port %s", port);
-
-    *callName = "Constructing TXT record";
-    if (argc)
-    {
-        for (i = 0; i < argc; i++)
-        {
-            const char *p = argv[i];
-            if (ptr >= txt + sizeof(txt))
-                return kDNSServiceErr_BadParam;
-            *ptr = 0;
-            while (*p && *ptr < 255)
-            {
-                if (ptr + 1 + *ptr >= txt + sizeof(txt))
-                    return kDNSServiceErr_BadParam;
-                if      (p[0] != '\\' || p[1] == 0)                       { ptr[++*ptr] = *p;           p+=1; }
-                else if (p[1] == 'x' && isxdigit(p[2]) && isxdigit(p[3])) { ptr[++*ptr] = HexPair(p+2); p+=4; }
-                else                                                      { ptr[++*ptr] = p[1];         p+=2; }
-            }
-            ptr += 1 + *ptr;
-        }
-        printf(" TXT");
-        ShowTXTRecord(ptr-txt, txt);
-    }
-    printf("\n");
-
-    //flags |= kDNSServiceFlagsAllowRemoteQuery;
-    //flags |= kDNSServiceFlagsNoAutoRename;
-
-    *callName = "DNSServiceRegister";
-    return(DNSServiceRegister(sdref, flags, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL));
-}
-
-#define TypeBufferSize 80
-static char *gettype(char *buffer, char *typ)
-{
-    if (!typ || !*typ || (typ[0] == '.' && typ[1] == 0)) typ = "_http._tcp";
-    if (!strchr(typ, '.')) { snprintf(buffer, TypeBufferSize, "%s._tcp", typ); typ = buffer; }
-    return(typ);
-}
-
-// Do some basic tests to verify API handles > 63 byte strings gracefully with
-// a returned error code.
-
-#define STRING_64_BYTES "_123456789012345678901234567890123456789012345678901234567890123"
-
-static int API_string_limit_test()
-{
-    const char * regtype;
-    DNSServiceRef sdRef = NULL;
-    const char * longHost = STRING_64_BYTES ".local";
-    const char * longDomain = "hostname." STRING_64_BYTES;
-
-    printf("Testing for error returns when various strings are > 63 bytes.\n");
-
-    printf("DNSServiceGetAddrInfo(), hostname = %s\n", longHost);
-    if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longHost, addrinfo_reply, 0) == 0)
-    {
-        printf("DNSServiceGetAddrInfo(): expected error return\n");
-        return 1;
-    };
-
-    printf("DNSServiceGetAddrInfo(), hostname = %s\n", longDomain);
-    if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longDomain, addrinfo_reply, 0) == 0)
-    {
-        printf("DNSServiceGetAddrInfo(): expected error return\n");
-        return 1;
-    };
-
-    printf("DNSServiceResolve(), name = %s\n", STRING_64_BYTES);
-    if (DNSServiceResolve(&sdRef, 0, 0, STRING_64_BYTES, "_test._tcp", "local", resolve_reply, NULL) == 0)
-    {
-        printf("DNSServiceResolve(): expected error return\n");
-        return 1;
-    };
-
-    regtype = STRING_64_BYTES "._tcp";
-    printf("DNSServiceResolve(), regtype = %s\n", regtype);
-    if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", regtype, "local", resolve_reply, NULL) == 0)
-    {
-        printf("DNSServiceResolve(): expected error return\n");
-        return 1;
-    };
-
-    printf("DNSServiceResolve(), domain = %s\n", STRING_64_BYTES);
-    if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", "_test._tcp", STRING_64_BYTES, resolve_reply, NULL) == 0)
-    {
-        printf("DNSServiceResolve(): expected error return\n");
-        return 1;
-    };
-
-    printf("Testing for error returns when various strings are > 63 bytes: PASSED\n");
-    return 0;
-}
-
-static int API_NULL_input_test()
-{
-    printf("Running basic API input range tests with various pointer parameters set to NULL:\n");
-
-    // Test that API's handle NULL pointers by returning an error when appropriate.
-
-    // DNSServiceRefSockFD()
-    if (DNSServiceRefSockFD(0) != -1)
-    {
-        printf("DNSServiceRefSockFD(): expected dnssd_InvalidSocket return\n");
-        return 1;
-    }
-
-    // DNSServiceProcessResult()
-    if (DNSServiceProcessResult(0) == 0)
-    {
-        printf("DNSServiceProcessResult(): expected error return\n");
-        return 1;
-    }
-
-    // DNSServiceRefDeallocate(): no return value, just verify it doesn't crash
-    DNSServiceRefDeallocate(0);
-
-    // DNSServiceGetProperty()
-    {
-        uint32_t   result;
-        uint32_t   size;
-
-        if (    (DNSServiceGetProperty(                                0, &result, &size) == 0)
-             || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion,       0, &size) == 0)
-             || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &result, 0) == 0)
-           )
-        {
-            printf("DNSServiceGetProperty(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceResolve()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *name = "name";
-        const char          *regtype = "_test._tcp";
-        const char          *domain = "local";
-        DNSServiceResolveReply callBack = 0;
-        void                *context = 0;   // can be a NULL pointer
-
-        if (    (DNSServiceResolve(    0,  flags, interfaceIndex, name, regtype, domain, callBack, context) == 0)
-            ||  (DNSServiceResolve(&sdRef, flags, interfaceIndex,    0, regtype, domain, callBack, context) == 0)
-            ||  (DNSServiceResolve(&sdRef, flags, interfaceIndex, name,       0, domain, callBack, context) == 0)
-            ||  (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype,      0, callBack, context) == 0)
-            ||  (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context) == 0)
-           )
-        {
-            printf("DNSServiceResolve(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceQueryRecord()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *fullname = "fullname";
-        uint16_t            rrtype = 0;
-        uint16_t            rrclass = 0;
-        DNSServiceQueryRecordReply callBack = 0;
-        void                *context = 0;  /* may be NULL */
-
-        if (    (DNSServiceQueryRecord(     0, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context) == 0)
-            ||  (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, 0,        rrtype, rrclass, callBack, context) == 0)
-            ||  (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, fullname, rrtype, rrclass,        0, context) == 0)
-           )
-        {
-            printf("DNSServiceQueryRecord(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceGetAddrInfo()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        DNSServiceProtocol  protocol = kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6;
-        const char          *hostname = "host.local";
-        DNSServiceGetAddrInfoReply callBack = 0;
-        void                *context = 0;   // may be NULL
-
-        if (    (DNSServiceGetAddrInfo(     0, flags, interfaceIndex, protocol, hostname, callBack, context) == 0)
-            ||  (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol,        0, callBack, context) == 0)
-            ||  (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol, hostname,        0, context) == 0)
-           )
-        {
-            printf("DNSServiceGetAddrInfo(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceBrowse()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *regtype = "_test._tcp";
-        const char          *domain = 0;    /* may be NULL */
-        DNSServiceBrowseReply callBack = 0;
-        void                *context = 0;   /* may be NULL */
-
-        if (    (DNSServiceBrowse(     0, flags, interfaceIndex, regtype, domain, callBack, context) == 0)
-            ||  (DNSServiceBrowse(&sdRef, flags, interfaceIndex,       0, domain, callBack, context) == 0)
-            ||  (DNSServiceBrowse(&sdRef, flags, interfaceIndex, regtype, domain,        0, context) == 0)
-           )
-        {
-            printf("DNSServiceBrowse(): expected error return\n");
-            return 1;
-        }
-    }
-
-
-    // DNSServiceRegister()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *name = 0;         /* may be NULL */
-        const char          *regtype = "_test._tcp";
-        const char          *domain = 0;       /* may be NULL */
-        const char          *host = 0;         /* may be NULL */
-        uint16_t            port = 0x2211;     /* In network byte order */
-        uint16_t            txtLen = 1;
-        const void          *txtRecord = "\0";    /* may be NULL */
-        DNSServiceRegisterReply callBack = 0;  /* may be NULL */
-        void                *context = 0;      /* may be NULL */
-
-        if (    (DNSServiceRegister(     0, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context) == 0)
-            ||  (DNSServiceRegister(&sdRef, flags, interfaceIndex, name,       0, domain, host, port, txtLen, txtRecord, callBack, context) == 0)
-           )
-        {
-            printf("DNSServiceRegister(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceEnumerateDomains()
-    {
-        DNSServiceRef       sdRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        DNSServiceDomainEnumReply callBack = 0;
-        void                *context = 0;  /* may be NULL */
-
-        if (    (DNSServiceEnumerateDomains(     0, flags, interfaceIndex, callBack, context) == 0)
-            ||  (DNSServiceEnumerateDomains(&sdRef, flags, interfaceIndex,        0, context) == 0)
-           )
-        {
-            printf("DNSServiceEnumerateDomains(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceCreateConnection()
-    if (DNSServiceCreateConnection(0) == 0)
-    {
-        printf("DNSServiceCreateConnection(): expected error return\n");
-        return 1;
-    }
-
-
-    // DNSServiceRegisterRecord()
-    {
-        DNSServiceRef       sdRef;
-        DNSRecordRef        RecordRef;
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *fullname = "test1._test._tcp.local";
-        uint16_t            rrtype = kDNSServiceType_TXT;
-        uint16_t            rrclass = kDNSServiceClass_IN;
-        uint16_t            rdlen = 1;
-        const void          *rdata = "\0";
-        uint32_t            ttl = 0;
-        DNSServiceRegisterRecordReply callBack = 0;
-        void                *context = 0;    /* may be NULL */
-
-        // Need an initialize sdRef
-        if (DNSServiceCreateConnection(&sdRef))
-        {
-            printf("DNSServiceCreateConnection(): failed\n");
-            return 1;
-        }
-
-        if (    (DNSServiceRegisterRecord(     0, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0)
-            ||  (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex,         0, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0)
-            ||  (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex,  fullname, rrtype, rrclass, rdlen,     0, ttl, callBack, context) == 0)
-            ||  (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex,  fullname, rrtype, rrclass, rdlen, rdata, ttl,        0, context) == 0)
-           )
-        {
-            printf("DNSServiceRegisterRecord(): expected error return\n");
-            return 1;
-        }
-    }
-
-    // DNSServiceAddRecord(), DNSServiceUpdateRecord(), and DNSServiceRemoveRecord() verify that they
-    // get a valid DNSServiceRef returned from DNSServiceRegister()
-    {
-        DNSServiceErrorType err;
-        Opaque16            registerPort = { { 0x12, 0x34 } };
-        static const char   TXT[] = "\xC" "First String";
-        DNSServiceRef       sdRef;
-
-        DNSRecordRef        RecordRef;
-        DNSServiceFlags     flags = 0;
-        uint16_t            rrtype = kDNSServiceType_TXT;
-        uint16_t            rdlen = 1;
-        const void          *rdata = "\0";
-        uint32_t            ttl = 100;
-
-        err = DNSServiceRegister(&sdRef, 0, 0, "Test", "_test._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
-        if (err)
-        {
-            printf("DNSServiceRegister() failed with: %d\n", err);
-            return 1;
-        }
-
-        // DNSServiceAddRecord()
-        if (    (DNSServiceAddRecord(    0, &RecordRef, flags, rrtype, rdlen, rdata, ttl) == 0)
-            ||  (DNSServiceAddRecord(sdRef,          0, flags, rrtype, rdlen, rdata, ttl) == 0)
-            ||  (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, rdlen,     0, ttl) == 0)
-           )
-
-        {
-            printf("DNSServiceAddRecord(): expected error return\n");
-            return 1;
-        }
-
-        // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
-        if (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, 0, 0, ttl) == kDNSServiceErr_BadParam)
-        {
-            printf("DNSServiceAddRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
-            return 1;
-        }
-
-        // DNSServiceUpdateRecord()
-        // Note, RecordRef can be NULL per explanation with declaration in dns_sd.h
-        if (    (DNSServiceUpdateRecord(    0, RecordRef, flags, rdlen, rdata, ttl) == 0)
-            ||  (DNSServiceUpdateRecord(sdRef, RecordRef, flags, rdlen,     0, ttl) == 0)
-           )
-        {
-            printf("DNSServiceUpdateRecord(): expected error return\n");
-            return 1;
-        }
-
-        // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
-        if (DNSServiceUpdateRecord(sdRef, RecordRef, flags, 0, 0, ttl) == kDNSServiceErr_BadParam)
-        {
-            printf("DNSServiceUpdateRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
-            return 1;
-        }
-
-        // DNSServiceRemoveRecord()
-        if (    (DNSServiceRemoveRecord(    0, RecordRef, flags) == 0)
-            ||  (DNSServiceRemoveRecord(sdRef,         0, flags) == 0)
-           )
-        {
-            printf("DNSServiceRemoveRecord(): expected error return\n");
-            return 1;
-        }
-
-        DNSServiceRefDeallocate(sdRef);
-    }
-
-    // DNSServiceReconfirmRecord()
-    {
-        DNSServiceFlags     flags = 0;
-        uint32_t            interfaceIndex = 0;
-        const char          *fullname = "aaa._test._tcp.local";
-        uint16_t            rrtype = kDNSServiceType_TXT;
-        uint16_t            rrclass = kDNSServiceClass_IN;
-        uint16_t            rdlen = 1;
-        const void          *rdata = "\0";
-
-        if (    (DNSServiceReconfirmRecord(flags, interfaceIndex,        0, rrtype, rrclass, rdlen, rdata) == 0)
-            ||  (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, rdlen,     0) == 0)
-           )
-        {
-            printf("DNSServiceReconfirmRecord(): expected error return\n");
-            return 1;
-        }
-        // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte.
-        if (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, 0, 0) == kDNSServiceErr_BadParam)
-        {
-            printf("DNSServiceReconfirmRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n");
-            return 1;
-        }
-    }
-
-
-    printf("Basic API input range tests: PASSED\n");
-    return 0;
-}
-
-static int API_input_range_test()
-{
-
-    if (API_string_limit_test())
-        return 1;
-
-    if (API_NULL_input_test())
-        return 1;
-
-    return 0;
-}
-
-int main(int argc, char **argv)
-{
-    DNSServiceErrorType err;
-    char buffer[TypeBufferSize], *typ, *dom;
-    int opi;
-    DNSServiceFlags flags = 0;
-    unsigned char enable_dnssec = 0;
-    const char *callName = "DNS Service call";
-
-    // Extract the program name from argv[0], which by convention contains the path to this executable.
-    // Note that this is just a voluntary convention, not enforced by the kernel --
-    // the process calling exec() can pass bogus data in argv[0] if it chooses to.
-    const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
-    if (a0 == (const char *)1) a0 = argv[0];
-
-#if defined(_WIN32)
-    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
-#endif
-
-#if TEST_NEW_CLIENTSTUB
-    printf("Using embedded copy of dnssd_clientstub instead of system library\n");
-    if (sizeof(argv) == 8) printf("Running in 64-bit mode\n");
-#endif
-
-    // Test code for TXTRecord functions
-    //TXTRecordRef txtRecord;
-    //TXTRecordCreate(&txtRecord, 0, NULL);
-    //TXTRecordSetValue(&txtRecord, "aaa", 1, "b");
-    //printf("%d\n", TXTRecordContainsKey(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), "Aaa"));
-
-    while (argc > 1)
-    {
-        int entryCount;
-
-        // record current argc to see if we process an argument in this pass
-        entryCount = argc;
-
-        if (argc > 1 && !strcmp(argv[1], "-test"))
-        {
-            argc--;
-            argv++;
-            return API_input_range_test();
-        }
-
-        if (argc > 1 && !strcmp(argv[1], "-lo"))
-        {
-            argc--;
-            argv++;
-            opinterface = kDNSServiceInterfaceIndexLocalOnly;
-            printf("Using LocalOnly\n");
-        }
-
-        if (argc > 1 && (!strcasecmp(argv[1], "-p2p")))
-        {
-            argc--;
-            argv++;
-            opinterface = kDNSServiceInterfaceIndexP2P;
-        }
-
-        if (argc > 1 && (!strcasecmp(argv[1], "-ble")))
-        {
-            argc--;
-            argv++;
-            opinterface = kDNSServiceInterfaceIndexBLE;
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-allowexpired"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsAllowExpiredAnswers;
-            printf("Setting kDNSServiceFlagsAllowExpiredAnswers\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-includep2p"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsIncludeP2P;
-            printf("Setting kDNSServiceFlagsIncludeP2P\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-fmc"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsForceMulticast;
-            printf("Setting kDNSServiceFlagsForceMulticast flag for this request\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsIncludeAWDL;
-            printf("Setting kDNSServiceFlagsIncludeAWDL\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-intermediates"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsReturnIntermediates;
-            printf("Setting kDNSServiceFlagsReturnIntermediates\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-tc"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsBackgroundTrafficClass;
-            printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-t1"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsThresholdOne;
-            printf("Setting kDNSServiceFlagsThresholdOne\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-tFinder"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsThresholdFinder;
-            printf("Setting kDNSServiceFlagsThresholdFinder\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-wo"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsWakeOnlyService;
-            printf("Setting kDNSServiceFlagsWakeOnlyService\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-ku"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsKnownUnique;
-            printf("Setting kDNSServiceFlagsKnownUnique\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-sh"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsShared;
-            printf("Setting kDNSServiceFlagsShared\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsUnicastResponse;
-            printf("Setting kDNSServiceFlagsUnicastResponse\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-timeout"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsTimeout;
-            printf("Setting kDNSServiceFlagsTimeout\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-autoTrigger"))
-        {
-            argc--;
-            argv++;
-            flags |= kDNSServiceFlagsAutoTrigger;
-            printf("Setting kDNSServiceFlagsAutoTrigger\n");
-        }
-
-        if (argc > 1 && !strcasecmp(argv[1], "-D"))
-        {
-            argc--;
-            argv++;
-            enable_dnssec = 1;
-            printf("Setting kDNSServiceFlagsEnableDNSSEC\n");
-        }
-
-        if (argc > 2 && !strcmp(argv[1], "-i"))
-        {
-            opinterface = if_nametoindex(argv[2]);
-            if (!opinterface) opinterface = atoi(argv[2]);
-            if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; }
-            argc -= 2;
-            argv += 2;
-        }
-
-        if (argc > 2 && !strcmp(argv[1], "-t"))
-        {
-            exitTimeout = atoi(argv[2]);
-            argc -= 2;
-            argv += 2;
-        }
-
-        if (argc > 2 && !strcmp(argv[1], "-m"))
-        {
-            exitWhenNoMoreComing = 1;
-            argc -= 1;
-            argv += 1;
-        }
-
-        // Exit loop if if we didn't match one of the multi character options.
-        if (argc == entryCount)
-            break;
-    }
-
-    if (argc < 2) goto Fail;        // Minimum command line is the command name and one argument
-    operation = getfirstoption(argc, argv, "ABCDEFHILMNPQRSTUVZhlq"
-                               "X"
-                               "Gg"
-                               , &opi);
-    if (operation == -1) goto Fail;
-
-    if (opinterface) printf("Using interface %d\n", opinterface);
-
-    switch (operation)
-    {
-    case 'E':   printf("Looking for recommended registration domains:\n");
-        callName = "DNSServiceEnumerateDomains";
-        err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsRegistrationDomains, opinterface, enum_reply, NULL);
-        break;
-
-    case 'F':   printf("Looking for recommended browsing domains:\n");
-        callName = "DNSServiceEnumerateDomains";
-        err = DNSServiceEnumerateDomains(&client, kDNSServiceFlagsBrowseDomains, opinterface, enum_reply, NULL);
-        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "nicta.com.au.", NULL);
-        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "bonjour.nicta.com.au.", NULL);
-        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "ibm.com.", NULL);
-        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
-        break;
-
-    case 'B':   typ = (argc < opi+1) ? "" : argv[opi+0];
-        dom = (argc < opi+2) ? "" : argv[opi+1];              // Missing domain argument is the same as empty string i.e. use system default(s)
-        typ = gettype(buffer, typ);
-        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;               // We allow '.' on the command line as a synonym for empty string
-        printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
-        callName = "DNSServiceBrowse";
-        err = DNSServiceBrowse(&client, flags, opinterface, typ, dom, browse_reply, NULL);
-        break;
-
-    case 'Z':   typ = (argc < opi+1) ? "" : argv[opi+0];
-        dom = (argc < opi+2) ? "" : argv[opi+1];              // Missing domain argument is the same as empty string i.e. use system default(s)
-        typ = gettype(buffer, typ);
-        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;               // We allow '.' on the command line as a synonym for empty string
-        printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
-        err = DNSServiceCreateConnection(&client);
-        if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
-        sc1 = client;
-        callName = "DNSServiceBrowse";
-        err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL);
-        break;
-
-    case 'l':
-    case 'L':   {
-        if (argc < opi+2) goto Fail;
-        typ = (argc < opi+2) ? ""      : argv[opi+1];
-        dom = (argc < opi+3) ? "local" : argv[opi+2];
-        typ = gettype(buffer, typ);
-        if (dom[0] == '.' && dom[1] == 0) dom = "local";               // We allow '.' on the command line as a synonym for "local"
-        printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
-        if (operation == 'l') flags |= kDNSServiceFlagsWakeOnResolve;
-        callName = "DNSServiceResolve";
-        err = DNSServiceResolve(&client, flags, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
-        break;
-    }
-
-    case 'R':   if (argc < opi+4) goto Fail;
-        typ = (argc < opi+2) ? "" : argv[opi+1];
-        dom = (argc < opi+3) ? "" : argv[opi+2];
-        typ = gettype(buffer, typ);
-        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;               // We allow '.' on the command line as a synonym for empty string
-        err = RegisterService(&client, argv[opi+0], typ, dom, NULL, argv[opi+3], argc-(opi+4), argv+(opi+4), flags, &callName);
-        break;
-
-
-    case 'P':   if (argc < opi+6) goto Fail;
-        err = DNSServiceCreateConnection(&client_pa);
-        if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
-        callName = "DNSServiceRegisterRecord";
-        err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5], flags);
-        if (err) break;
-        err = RegisterService(&client, argv[opi+0], gettype(buffer, argv[opi+1]), argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6), flags, &callName);
-        break;
-
-    case 'q':
-    case 'Q':
-    case 'C':   {
-        uint16_t rrtype, rrclass;
-        flags |= kDNSServiceFlagsReturnIntermediates;
-        if (operation == 'q')
-            flags |= kDNSServiceFlagsSuppressUnusable;
-        if (enable_dnssec)
-            flags |= kDNSServiceFlagsEnableDNSSEC;
-        if (argc < opi+1)
-            goto Fail;
-        rrtype = (argc <= opi+1) ? kDNSServiceType_A  : GetRRType(argv[opi+1]);
-        rrclass = (argc <= opi+2) ? kDNSServiceClass_IN : GetRRClass(argv[opi+2]);
-        if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR)
-            flags |= kDNSServiceFlagsLongLivedQuery;
-        callName = "DNSServiceQueryRecord";
-        err = DNSServiceQueryRecord(&client, flags, opinterface, argv[opi+0], rrtype, rrclass, qr_reply, NULL);
-        break;
-    }
-
-    case 'A':
-    case 'U':
-    case 'N':   {
-        Opaque16 registerPort = { { 0x12, 0x34 } };
-        static const char TXT[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
-        printf("Registering Service Test._testupdate._tcp.local.\n");
-        callName = "DNSServiceRegister";
-        err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testupdate._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL);
-        break;
-    }
-
-    case 'T':   {
-        Opaque16 registerPort = { { 0x23, 0x45 } };
-        char TXT[1024];
-        unsigned int i;
-        for (i=0; i<sizeof(TXT); i++)
-            if ((i & 0x1F) == 0) TXT[i] = 0x1F;else TXT[i] = 'A' + (i >> 5);
-        printf("Registering Service Test._testlargetxt._tcp.local.\n");
-        callName = "DNSServiceRegister";
-        err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testlargetxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT), TXT, reg_reply, NULL);
-        break;
-    }
-
-    case 'M':   {
-        pid_t pid = getpid();
-        Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
-        static const char TXT1[] = "\xC" "First String"  "\xD" "Second String" "\xC" "Third String";
-        static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String"  "\xC" "Sixth String";
-        printf("Registering Service Test._testdualtxt._tcp.local.\n");
-        callName = "DNSServiceRegister";
-        err = DNSServiceRegister(&client, flags, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
-        if (!err)
-        {
-            callName = "DNSServiceAddRecord";
-            err = DNSServiceAddRecord(client, &record, flags, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
-        }
-        break;
-    }
-
-    case 'I':   {
-        pid_t pid = getpid();
-        Opaque16 registerPort = { { pid >> 8, pid & 0xFF } };
-        static const char TXT[] = "\x09" "Test Data";
-        printf("Registering Service Test._testtxt._tcp.local.\n");
-        callName = "DNSServiceRegister";
-        err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testtxt._tcp.", "", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
-        if (!err)
-        {
-            callName = "DNSServiceUpdateRecord";
-            err = DNSServiceUpdateRecord(client, NULL, 0, sizeof(TXT)-1, TXT, 0);
-        }
-        break;
-    }
-
-    case 'X':   {
-        if (argc == opi)                // If no arguments, just fetch IP address
-        {
-            callName = "DNSServiceNATPortMappingCreate";
-            err = DNSServiceNATPortMappingCreate(&client, 0, 0, 0, 0, 0, 0, port_mapping_create_reply, NULL);
-        }
-        else if (argc >= opi+2 && atoi(argv[opi+0]) == 0)
-        {
-            DNSServiceProtocol prot  = GetProtocol(argv[opi+0]);                                    // Must specify TCP or UDP
-            uint16_t IntPortAsNumber = atoi(argv[opi+1]);                                       // Must specify internal port
-            uint16_t ExtPortAsNumber = (argc < opi+3) ? 0 : atoi(argv[opi+2]);              // Optional desired external port
-            uint32_t ttl             = (argc < opi+4) ? 0 : atoi(argv[opi+3]);              // Optional desired lease lifetime
-            Opaque16 intp = { { IntPortAsNumber >> 8, IntPortAsNumber & 0xFF } };
-            Opaque16 extp = { { ExtPortAsNumber >> 8, ExtPortAsNumber & 0xFF } };
-            callName = "DNSServiceNATPortMappingCreate";
-            err = DNSServiceNATPortMappingCreate(&client, 0, 0, prot, intp.NotAnInteger, extp.NotAnInteger, ttl, port_mapping_create_reply, NULL);
-        }
-        else goto Fail;
-        break;
-    }
-
-    case 'G':   {
-        flags |= kDNSServiceFlagsReturnIntermediates;
-        if (enable_dnssec)
-            flags |= kDNSServiceFlagsEnableDNSSEC;
-
-        if (argc != opi+2)
-            goto Fail;
-        else
-        {
-            callName = "DNSServiceGetAddrInfo";
-            err = DNSServiceGetAddrInfo(&client, flags, opinterface, GetProtocol(argv[opi+0]), argv[opi+1], addrinfo_reply, NULL);
-        }
-        break;
-    }
-
-    case 'S':   {
-        Opaque16 registerPort = { { 0x23, 0x45 } };                 // 9029 decimal
-        unsigned char txtrec[16] = "\xF" "/path=test.html";
-        DNSRecordRef rec;
-        unsigned char nulrec[4] = "1234";
-
-        err = DNSServiceCreateConnection(&client);
-        if (err) { fprintf(stderr, "DNSServiceCreateConnection failed %ld\n", (long int)err); return (-1); }
-
-        sc1 = client;
-        err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, "_http._tcp", "", browse_reply, NULL);
-        if (err) { fprintf(stderr, "DNSServiceBrowse _http._tcp failed %ld\n", (long int)err); return (-1); }
-
-        sc2 = client;
-        err = DNSServiceBrowse(&sc2, kDNSServiceFlagsShareConnection, opinterface, "_ftp._tcp", "", browse_reply, NULL);
-        if (err) { fprintf(stderr, "DNSServiceBrowse _ftp._tcp failed %ld\n", (long int)err); return (-1); }
-
-        sc3 = client;
-        err = DNSServiceRegister(&sc3, kDNSServiceFlagsShareConnection, opinterface, "kDNSServiceFlagsShareConnection",
-                                 "_http._tcp", "local", NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, NULL);
-        if (err) { fprintf(stderr, "SharedConnection DNSServiceRegister failed %ld\n", (long int)err); return (-1); }
-
-        err = DNSServiceUpdateRecord(sc3, NULL, 0, sizeof(txtrec), txtrec, 0);
-        if (err) { fprintf(stderr, "SharedConnection DNSServiceUpdateRecord failed %ld\n", (long int)err); return (-1); }
-
-        err = DNSServiceAddRecord(sc3, &rec, 0, kDNSServiceType_NULL, sizeof(nulrec), nulrec, 0);
-        if (err) { fprintf(stderr, "SharedConnection DNSServiceAddRecord failed %ld\n", (long int)err); return (-1); }
-
-        err = DNSServiceRemoveRecord(sc3, rec, 0);
-        if (err) { fprintf(stderr, "SharedConnection DNSServiceRemoveRecord failed %ld\n", (long int)err); return (-1); }
-
-        break;
-    }
-
-    case 'V':   {
-        uint32_t v;
-        uint32_t size = sizeof(v);
-        err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &v, &size);
-        if (err)
-        {
-            fprintf(stderr, "DNSServiceGetProperty failed %ld\n", (long int)err);
-        }
-        else
-        {
-            // Version strings are of the form x[.y[.z]].
-            // Newer version strings are encoded as (x * 1000000) + (y * 1000) + z, where 0 ≤ y,z ≤ 999.
-            // Older version strings were encoded as (x * 10000) + (y * 100) + z, where 0 ≤ y,z ≤ 99.
-            uint32_t x, y, z;
-            if (v > DNS_SD_ORIGINAL_ENCODING_VERSION_NUMBER_MAX)
-            {
-                x = v / 1000000;
-                y = (v / 1000) % 1000;
-                z = v % 1000;
-            }
-            else
-            {
-                x = v / 10000;
-                y = (v / 100) % 100;
-                z = v % 100;
-            }
-            printf("Currently running daemon (system service) is version %u.%u.%u\n", x, y, z);
-        }
-        exit(0);
-    }
-
-    case 'H': goto Fail;
-
-    default: goto Fail;
-    }
-
-    if (!client || err != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "%s failed %ld%s\n", callName, (long int)err,
-            (err == kDNSServiceErr_ServiceNotRunning) ? " (Service Not Running)" : "");
-        return (-1);
-    }
-    printtimestamp();
-    printf("...STARTING...\n");
-    HandleEvents();
-
-    // Be sure to deallocate the DNSServiceRef when you're finished
-    if (client   ) DNSServiceRefDeallocate(client   );
-    if (client_pa) DNSServiceRefDeallocate(client_pa);
-    return 0;
-
-Fail:
-    if (operation == 'H') print_usage(a0,1);
-    else print_usage(a0,0);
-    return 0;
-}
-
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// NOT static -- otherwise the compiler may optimize it out
-// The "@(#) " pattern is a special prefix the "what" command looks for
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdate-time"
-    const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-#pragma GCC diagnostic pop
-
-#if _BUILDING_XCODE_PROJECT_
-// If the process crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = VersionString_SCCS + 5;
-asm (".desc ___crashreporter_info__, 0x10");
-#endif
diff --git a/Clients/dnssdutil/DNSServerDNSSEC.c b/Clients/dnssdutil/DNSServerDNSSEC.c
deleted file mode 100644
index 9331613..0000000
--- a/Clients/dnssdutil/DNSServerDNSSEC.c
+++ /dev/null
@@ -1,3674 +0,0 @@
-/*
-	Copyright (c) 2020 Apple Inc. All rights reserved.
-*/
-
-#include "DNSServerDNSSEC.h"
-
-#include <mdns/DNSMessage.h>
-#include <Security/SecKeyPriv.h>
-
-//===========================================================================================================================
-// MARK: - DNS Key Infos -
-
-// The first member of each algorithm-specific DNS Key info data structure must be of type dns_fixed_fields_dnskey, and
-// must be immediately followed by its public key member variable. This is so that together they can be used as DNSKEY
-// record data. See <https://tools.ietf.org/html/rfc4034#section-2.1>.
-
-#define _DNSKeyInfoCompileTimeChecks( ALG_NAME )																\
-	check_compile_time( offsetof( DNSKey ## ALG_NAME ## Info, fixedFields ) == 0 );								\
-	check_compile_time( offsetof( DNSKey ## ALG_NAME ## Info, pubKey ) == sizeof( dns_fixed_fields_dnskey ) );	\
-	check_compile_time( kDNSServerSignatureLengthMax >= k ## ALG_NAME ## _SignatureBytes )
-
-//===========================================================================================================================
-// MARK: - RSA/SHA-1 DNS Key Info
-// See <https://tools.ietf.org/html/rfc3110>.
-
-#define kRSASHA1_PublicKeyBytes		260
-#define kRSASHA1_SecretKeyBytes		1190
-#define kRSASHA1_SignatureBytes		256
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;						// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kRSASHA1_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kRSASHA1_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyRSASHA1Info;
-
-_DNSKeyInfoCompileTimeChecks( RSASHA1 );
-
-//===========================================================================================================================
-// MARK: - RSA/SHA-256 DNS Key Info
-// See <https://tools.ietf.org/html/rfc5702>.
-
-#define kRSASHA256_PublicKeyBytes		260
-#define kRSASHA256_SecretKeyBytes		1190
-#define kRSASHA256_SignatureBytes		256
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;							// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kRSASHA256_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kRSASHA256_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyRSASHA256Info;
-
-_DNSKeyInfoCompileTimeChecks( RSASHA256 );
-
-//===========================================================================================================================
-// MARK: - RSA/SHA-512 DNS Key Info
-// See <https://tools.ietf.org/html/rfc5702>.
-
-#define kRSASHA512_PublicKeyBytes		260
-#define kRSASHA512_SecretKeyBytes		1190
-#define kRSASHA512_SignatureBytes		256
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;							// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kRSASHA512_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kRSASHA512_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyRSASHA512Info;
-
-_DNSKeyInfoCompileTimeChecks( RSASHA512 );
-
-//===========================================================================================================================
-// MARK: - ECDSA Curve P-256 with SHA-256 DNS Key Info
-// See <https://tools.ietf.org/html/rfc6605>.
-
-#define kECDSAP256SHA256_PublicKeyBytes		64
-#define kECDSAP256SHA256_SecretKeyBytes		96
-#define kECDSAP256SHA256_SignatureBytes		64
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;								// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kECDSAP256SHA256_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kECDSAP256SHA256_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyECDSAP256SHA256Info;
-
-_DNSKeyInfoCompileTimeChecks( ECDSAP256SHA256 );
-
-//===========================================================================================================================
-// MARK: - ECDSA Curve P-384 with SHA-384 DNS Key Info
-// See <https://tools.ietf.org/html/rfc6605>.
-
-#define kECDSAP384SHA384_PublicKeyBytes		64
-#define kECDSAP384SHA384_SecretKeyBytes		96
-#define kECDSAP384SHA384_SignatureBytes		64
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;								// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kECDSAP384SHA384_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kECDSAP384SHA384_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyECDSAP384SHA384Info;
-
-_DNSKeyInfoCompileTimeChecks( ECDSAP384SHA384 );
-
-//===========================================================================================================================
-// MARK: - Ed25519 DNS Key Info
-// See <https://tools.ietf.org/html/rfc8080>.
-
-typedef struct
-{
-	dns_fixed_fields_dnskey		fixedFields;						// DNSKEY RDATA fixed fields.
-	uint8_t						pubKey[ kEd25519_PublicKeyBytes ];	// Public key.
-	uint8_t						secKey[ kEd25519_SecretKeyBytes ];	// Secret key.
-	
-}	DNSKeyEd25519Info;
-
-_DNSKeyInfoCompileTimeChecks( Ed25519 );
-
-//===========================================================================================================================
-// MARK: - DNS Key Info Union
-
-#define _DNSKeyInfoUnionMember( ALG_NAME )		DNSKey ## ALG_NAME ## Info ALG_NAME
-
-union DNSKeyInfo
-{
-	dns_fixed_fields_dnskey		fixedFields;
-	_DNSKeyInfoUnionMember( RSASHA1 );
-	_DNSKeyInfoUnionMember( RSASHA256 );
-	_DNSKeyInfoUnionMember( RSASHA512 );
-	_DNSKeyInfoUnionMember( ECDSAP256SHA256 );
-	_DNSKeyInfoUnionMember( ECDSAP384SHA384 );
-	_DNSKeyInfoUnionMember( Ed25519 );
-};
-
-//===========================================================================================================================
-// MARK: - DNS Keys -
-
-#define _DNSKeyInfoFixedFieldsInitKSK( ALGORITHM )	\
-	{												\
-		.flags		= { 0x01, 0x01 },				\
-		.protocol	= { kDNSKeyProtocol_DNSSEC },	\
-		.algorithm	= { (ALGORITHM) }				\
-	}
-
-#define _DNSKeyInfoFixedFieldsInitZSK( ALGORITHM )	\
-	{												\
-		.flags		= { 0x01, 0x00 },				\
-		.protocol	= { kDNSKeyProtocol_DNSSEC },	\
-		.algorithm	= { (ALGORITHM) }				\
-	}
-
-// The Zone Label argument is an integer used to index into a DNS Key sets array, so the number of DNSKEY sets should be
-// one more than the maximum allowable Zone Label argument.
-
-#define _DNSKeySetsCompileTimeChecks( ALG_NAME ) \
-	check_compile_time( countof( kDNSKey ## ALG_NAME ## Sets ) == ( kZoneLabelIndexArgMax + 1 ) )
-
-//===========================================================================================================================
-// MARK: - RSA/SHA1 DNS Keys
-
-typedef struct
-{
-	DNSKeyRSASHA1Info		ksk;	// Key-Signing Key
-	DNSKeyRSASHA1Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyRSASHA1Set;
-
-static const DNSKeyRSASHA1Set		kDNSKeyRSASHA1Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xbe, 0x7b, 0xba, 0xa1, 0x0c, 0xdf, 0x40, 0xf7, 0xcc, 0x73, 0xae, 0x5a,
-				0xba, 0xeb, 0x34, 0x18, 0x50, 0xbc, 0x4b, 0x74, 0x14, 0x8c, 0xf9, 0xc1, 0x6c, 0x7d, 0xb0, 0x0d,
-				0xa7, 0x93, 0x13, 0x56, 0x40, 0xef, 0x0b, 0x35, 0x31, 0xd9, 0x6f, 0x11, 0x96, 0xec, 0x2a, 0x65,
-				0x50, 0xd5, 0xeb, 0x51, 0xa4, 0x95, 0xfb, 0x0f, 0x9f, 0xc5, 0x71, 0x22, 0x00, 0xc2, 0x59, 0xc6,
-				0x97, 0x8d, 0xe0, 0x5e, 0x5b, 0x49, 0xdc, 0xc9, 0xfb, 0x36, 0xe1, 0x88, 0xb9, 0x65, 0xf3, 0xff,
-				0xa0, 0x4e, 0x26, 0xe5, 0x00, 0x41, 0x99, 0x04, 0xa4, 0x64, 0x93, 0x77, 0x57, 0xee, 0x57, 0x55,
-				0xd7, 0xba, 0x2f, 0x8c, 0x7a, 0x39, 0x66, 0x93, 0x38, 0x5f, 0x9b, 0x3b, 0xb1, 0xe3, 0xab, 0xa2,
-				0x62, 0xd2, 0x88, 0x34, 0xcf, 0x12, 0x39, 0x5a, 0x3b, 0xf1, 0x72, 0x8d, 0xbe, 0x43, 0x2e, 0xb1,
-				0xb0, 0x27, 0x81, 0x32, 0x3f, 0x3e, 0xfa, 0x73, 0x47, 0x1e, 0x32, 0x41, 0x69, 0x91, 0xc7, 0x9a,
-				0x69, 0x27, 0xda, 0x3d, 0x9a, 0x45, 0x5c, 0x83, 0xf4, 0xea, 0x34, 0xb8, 0xcc, 0xf6, 0xb0, 0x37,
-				0x1f, 0x7f, 0x9e, 0x5a, 0x57, 0x0f, 0xb0, 0x02, 0x35, 0x15, 0x67, 0xfb, 0x9d, 0x3f, 0x08, 0x9c,
-				0x3a, 0xcb, 0x81, 0x2c, 0x03, 0x2d, 0x44, 0x83, 0xd2, 0xff, 0x75, 0x4e, 0xb0, 0xec, 0x23, 0x0b,
-				0x8c, 0x7b, 0x52, 0x42, 0x75, 0x94, 0x66, 0xdf, 0x90, 0x7e, 0xa1, 0x3f, 0x33, 0x5c, 0x8f, 0xe4,
-				0xb9, 0x7c, 0xc9, 0x08, 0xef, 0xbb, 0x9a, 0x6e, 0x91, 0x8d, 0x80, 0xda, 0xc5, 0x37, 0x2c, 0xab,
-				0x26, 0xc9, 0xd6, 0xc4, 0x69, 0x52, 0x9e, 0x46, 0xc9, 0xce, 0xf2, 0x0b, 0xea, 0x71, 0x28, 0x1f,
-				0xb3, 0x61, 0x62, 0x5c, 0x7e, 0x56, 0x8b, 0x3f, 0x1c, 0xb0, 0x3c, 0x92, 0x28, 0x87, 0xa1, 0x5b,
-				0xf2, 0x9a, 0x31, 0x21
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbe, 0x7b, 0xba, 0xa1,
-				0x0c, 0xdf, 0x40, 0xf7, 0xcc, 0x73, 0xae, 0x5a, 0xba, 0xeb, 0x34, 0x18, 0x50, 0xbc, 0x4b, 0x74,
-				0x14, 0x8c, 0xf9, 0xc1, 0x6c, 0x7d, 0xb0, 0x0d, 0xa7, 0x93, 0x13, 0x56, 0x40, 0xef, 0x0b, 0x35,
-				0x31, 0xd9, 0x6f, 0x11, 0x96, 0xec, 0x2a, 0x65, 0x50, 0xd5, 0xeb, 0x51, 0xa4, 0x95, 0xfb, 0x0f,
-				0x9f, 0xc5, 0x71, 0x22, 0x00, 0xc2, 0x59, 0xc6, 0x97, 0x8d, 0xe0, 0x5e, 0x5b, 0x49, 0xdc, 0xc9,
-				0xfb, 0x36, 0xe1, 0x88, 0xb9, 0x65, 0xf3, 0xff, 0xa0, 0x4e, 0x26, 0xe5, 0x00, 0x41, 0x99, 0x04,
-				0xa4, 0x64, 0x93, 0x77, 0x57, 0xee, 0x57, 0x55, 0xd7, 0xba, 0x2f, 0x8c, 0x7a, 0x39, 0x66, 0x93,
-				0x38, 0x5f, 0x9b, 0x3b, 0xb1, 0xe3, 0xab, 0xa2, 0x62, 0xd2, 0x88, 0x34, 0xcf, 0x12, 0x39, 0x5a,
-				0x3b, 0xf1, 0x72, 0x8d, 0xbe, 0x43, 0x2e, 0xb1, 0xb0, 0x27, 0x81, 0x32, 0x3f, 0x3e, 0xfa, 0x73,
-				0x47, 0x1e, 0x32, 0x41, 0x69, 0x91, 0xc7, 0x9a, 0x69, 0x27, 0xda, 0x3d, 0x9a, 0x45, 0x5c, 0x83,
-				0xf4, 0xea, 0x34, 0xb8, 0xcc, 0xf6, 0xb0, 0x37, 0x1f, 0x7f, 0x9e, 0x5a, 0x57, 0x0f, 0xb0, 0x02,
-				0x35, 0x15, 0x67, 0xfb, 0x9d, 0x3f, 0x08, 0x9c, 0x3a, 0xcb, 0x81, 0x2c, 0x03, 0x2d, 0x44, 0x83,
-				0xd2, 0xff, 0x75, 0x4e, 0xb0, 0xec, 0x23, 0x0b, 0x8c, 0x7b, 0x52, 0x42, 0x75, 0x94, 0x66, 0xdf,
-				0x90, 0x7e, 0xa1, 0x3f, 0x33, 0x5c, 0x8f, 0xe4, 0xb9, 0x7c, 0xc9, 0x08, 0xef, 0xbb, 0x9a, 0x6e,
-				0x91, 0x8d, 0x80, 0xda, 0xc5, 0x37, 0x2c, 0xab, 0x26, 0xc9, 0xd6, 0xc4, 0x69, 0x52, 0x9e, 0x46,
-				0xc9, 0xce, 0xf2, 0x0b, 0xea, 0x71, 0x28, 0x1f, 0xb3, 0x61, 0x62, 0x5c, 0x7e, 0x56, 0x8b, 0x3f,
-				0x1c, 0xb0, 0x3c, 0x92, 0x28, 0x87, 0xa1, 0x5b, 0xf2, 0x9a, 0x31, 0x21, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x13, 0x91, 0xa8, 0xda, 0x8b, 0x1f, 0x7e, 0x7b, 0x01, 0x52, 0x9b,
-				0x1a, 0xc5, 0x71, 0x8c, 0xc5, 0xb8, 0xb9, 0xa2, 0x1e, 0x22, 0xa4, 0x59, 0xb3, 0x96, 0x33, 0xe8,
-				0x11, 0x27, 0x0c, 0xe9, 0x8e, 0x26, 0xc2, 0x9d, 0x74, 0xa6, 0xbd, 0x39, 0xf7, 0x65, 0x24, 0x0d,
-				0xb6, 0x4b, 0x3d, 0x31, 0x87, 0xe4, 0x30, 0x3c, 0xfd, 0x88, 0x6c, 0xf8, 0xd2, 0x9a, 0x4b, 0x07,
-				0xd2, 0x6a, 0xac, 0x7a, 0x87, 0x47, 0x0f, 0xf4, 0xb2, 0x52, 0xc5, 0x7b, 0x1b, 0x18, 0x42, 0x3c,
-				0x9f, 0x1f, 0x8c, 0x17, 0xdb, 0xd6, 0x90, 0x66, 0xaa, 0x29, 0x97, 0x64, 0x3c, 0xfd, 0x02, 0xc6,
-				0x8f, 0x27, 0x9d, 0x55, 0x98, 0x34, 0x25, 0xa4, 0x7f, 0x98, 0x69, 0x88, 0xb6, 0xf3, 0xc4, 0xba,
-				0x29, 0x1c, 0x72, 0x43, 0x92, 0xfa, 0xa3, 0xaf, 0xd2, 0x5b, 0x83, 0xd2, 0x6b, 0x1f, 0x1c, 0xf8,
-				0xca, 0xec, 0x18, 0x20, 0x37, 0x68, 0x92, 0x07, 0xa0, 0xf3, 0x3b, 0x61, 0xb8, 0xa0, 0x8c, 0x5f,
-				0xd9, 0x14, 0x28, 0x4d, 0xa3, 0x83, 0xf2, 0x83, 0x13, 0xde, 0x03, 0x4c, 0xa8, 0xab, 0xa9, 0x1f,
-				0x66, 0x4c, 0xf6, 0xb2, 0x0d, 0x90, 0xae, 0x08, 0xa7, 0x8c, 0x2d, 0xe9, 0x2b, 0xce, 0x9c, 0x2d,
-				0x56, 0x0e, 0x7b, 0x7b, 0x14, 0x20, 0x8b, 0x2b, 0x2f, 0x1a, 0x26, 0x63, 0xa4, 0xd4, 0x0c, 0x86,
-				0xac, 0x5d, 0x0f, 0x8e, 0x80, 0x27, 0x10, 0x42, 0xd6, 0x38, 0x63, 0x0e, 0x59, 0xa2, 0x61, 0xf1,
-				0xde, 0xda, 0x3f, 0x77, 0x44, 0x13, 0xd6, 0x1a, 0x01, 0x59, 0xb7, 0xc3, 0xda, 0x52, 0xf4, 0x46,
-				0x69, 0xed, 0x4f, 0xc2, 0xe7, 0x69, 0x0a, 0x02, 0xff, 0x2f, 0x80, 0x63, 0x0a, 0xf5, 0xf8, 0xe4,
-				0xb9, 0x43, 0x26, 0x5b, 0xf8, 0xc2, 0xa6, 0xe4, 0xd2, 0x46, 0x12, 0x7b, 0x7e, 0xe1, 0xe4, 0xc4,
-				0x74, 0xfc, 0x8c, 0xe8, 0xbf, 0x02, 0x81, 0x81, 0x00, 0xf1, 0x40, 0x2b, 0x43, 0xa2, 0x49, 0x60,
-				0x1a, 0xca, 0x88, 0xa2, 0x7a, 0xb0, 0xf7, 0xb4, 0xc1, 0x1d, 0x0a, 0xc5, 0xd3, 0x6a, 0xb0, 0xe0,
-				0xd3, 0xce, 0x99, 0x84, 0x91, 0xea, 0x9b, 0x48, 0xf1, 0x22, 0x37, 0x29, 0xfd, 0xa0, 0xf7, 0xc1,
-				0x94, 0x5f, 0xe2, 0x24, 0xa3, 0x1d, 0x0a, 0x5f, 0xea, 0x06, 0x3b, 0xaf, 0x42, 0xc3, 0x7d, 0x1d,
-				0x22, 0xaf, 0xb4, 0x64, 0x50, 0x35, 0xac, 0xed, 0x65, 0xac, 0x6f, 0x60, 0xf0, 0xa2, 0xa5, 0x20,
-				0xab, 0xff, 0xb3, 0x93, 0xb0, 0x51, 0x6d, 0xb5, 0x1b, 0x2a, 0x17, 0x06, 0x07, 0x1f, 0xa2, 0x57,
-				0x4c, 0xf0, 0x02, 0x13, 0xfc, 0x76, 0x8f, 0xae, 0x7e, 0x0e, 0x66, 0xc2, 0xc7, 0x39, 0xed, 0x7e,
-				0x0d, 0x74, 0xaa, 0xbc, 0xfb, 0xb4, 0x25, 0x1c, 0x72, 0xd1, 0x65, 0x9f, 0x91, 0xe3, 0xfd, 0xd1,
-				0x38, 0xea, 0x89, 0x8c, 0x32, 0x7a, 0xfd, 0x64, 0x7f, 0x02, 0x81, 0x81, 0x00, 0xca, 0x20, 0xff,
-				0x2b, 0xe2, 0x8a, 0xc7, 0xab, 0x40, 0xbe, 0xf2, 0xa3, 0x52, 0x69, 0x8e, 0x40, 0x79, 0x39, 0x07,
-				0x5c, 0x90, 0x43, 0x60, 0xcf, 0x87, 0xc5, 0xdd, 0x0e, 0x34, 0x77, 0xad, 0x50, 0xd1, 0x98, 0xbd,
-				0x92, 0x7a, 0x9f, 0x8c, 0x1d, 0x72, 0x33, 0xc5, 0x66, 0x7e, 0xc6, 0x28, 0xc4, 0xfb, 0xe9, 0x83,
-				0x79, 0x7f, 0xb1, 0xfb, 0x60, 0x30, 0x97, 0xd8, 0x59, 0xbe, 0xc0, 0x1d, 0x39, 0xe8, 0x33, 0x20,
-				0x84, 0xa7, 0x58, 0x5c, 0xaf, 0xe4, 0xc9, 0x15, 0xed, 0xaa, 0xce, 0xe5, 0x27, 0x29, 0xce, 0x83,
-				0x12, 0xec, 0xc5, 0x8a, 0xe6, 0xb7, 0xd3, 0x27, 0xb8, 0x0f, 0x09, 0x28, 0x2f, 0x98, 0x2d, 0xc1,
-				0x6e, 0xbf, 0xf0, 0x42, 0xdf, 0xe2, 0x09, 0x90, 0xbb, 0x94, 0x3a, 0x93, 0x93, 0x67, 0x62, 0xb1,
-				0x10, 0x92, 0x82, 0x63, 0x49, 0x5f, 0x36, 0x56, 0x23, 0xab, 0x23, 0x1a, 0x5f, 0x02, 0x81, 0x80,
-				0x2a, 0xa8, 0x31, 0xfe, 0x2f, 0x7f, 0xd1, 0xe2, 0x6a, 0xd5, 0x66, 0x05, 0x53, 0xad, 0x38, 0xe4,
-				0xbc, 0x81, 0xdf, 0x20, 0xd6, 0xc8, 0x97, 0xb8, 0x5b, 0xdb, 0x81, 0x39, 0x5b, 0xc6, 0x41, 0x4b,
-				0x81, 0xc5, 0x47, 0x43, 0x75, 0x66, 0xd9, 0x6f, 0xa6, 0xd4, 0x91, 0xad, 0xd5, 0xc0, 0xb3, 0xdc,
-				0xe9, 0x65, 0x3c, 0x44, 0x0d, 0xd4, 0xdd, 0x85, 0xf8, 0x93, 0x68, 0xf9, 0x55, 0xc4, 0x51, 0xe5,
-				0x9c, 0x6b, 0xc5, 0x34, 0x47, 0x4d, 0xf3, 0x4c, 0xf6, 0x55, 0x86, 0x53, 0xb2, 0xd2, 0x37, 0x27,
-				0xaa, 0x75, 0x8f, 0xb7, 0x4a, 0xbc, 0xa5, 0xbb, 0x10, 0xe5, 0x0d, 0x2b, 0xa2, 0xbb, 0x1d, 0x1b,
-				0x64, 0xe8, 0x7e, 0xa0, 0x43, 0x79, 0xde, 0xc3, 0xfa, 0x51, 0x06, 0x41, 0x6b, 0x44, 0xf4, 0x96,
-				0xc8, 0xb7, 0xb3, 0x53, 0x54, 0x80, 0xd8, 0xb1, 0xbb, 0xa6, 0xbe, 0x87, 0x5e, 0x7f, 0xd7, 0x79,
-				0x02, 0x81, 0x80, 0x3c, 0xf2, 0x60, 0x1e, 0xaa, 0x6b, 0x70, 0x33, 0x4a, 0x0d, 0x89, 0x7a, 0x07,
-				0x92, 0x7e, 0x6b, 0x20, 0x62, 0x3a, 0xbf, 0x05, 0x5c, 0xdb, 0xa7, 0x17, 0xe8, 0x68, 0x74, 0x2d,
-				0x0b, 0xdc, 0xfd, 0x9e, 0x85, 0x70, 0xbb, 0xe7, 0x2f, 0x8e, 0x7f, 0x1e, 0x7d, 0x4f, 0xcb, 0x4c,
-				0xf4, 0x91, 0x3c, 0x7c, 0x3c, 0xf8, 0x00, 0xbd, 0xa9, 0x3c, 0x03, 0xd0, 0x03, 0x29, 0x20, 0x3e,
-				0x6d, 0x0d, 0x22, 0xf5, 0xc9, 0xdc, 0xc7, 0x42, 0xf2, 0x58, 0xd8, 0x4c, 0xa2, 0xf9, 0x72, 0xb5,
-				0x6b, 0x37, 0x1b, 0x6c, 0xf6, 0xb0, 0xfd, 0x16, 0xd9, 0xa5, 0xbd, 0x55, 0xb6, 0x5c, 0xa6, 0x9a,
-				0x1a, 0x07, 0xbc, 0xfa, 0x24, 0xe9, 0xcb, 0x6c, 0x22, 0x94, 0xf7, 0x8e, 0xdf, 0x95, 0x7d, 0x89,
-				0xff, 0x73, 0x9a, 0x21, 0xb5, 0x57, 0x70, 0x88, 0xcc, 0xba, 0x05, 0x58, 0xa9, 0x38, 0xa5, 0xfe,
-				0xa7, 0x51, 0xff, 0x02, 0x81, 0x80, 0x14, 0x3f, 0x61, 0x7b, 0x6b, 0x32, 0xed, 0xcd, 0x65, 0x10,
-				0x54, 0x4e, 0xa3, 0x6b, 0xda, 0x4e, 0x48, 0x20, 0xeb, 0xc5, 0x41, 0x86, 0x39, 0x36, 0x6e, 0xc5,
-				0x1a, 0xf0, 0x17, 0x07, 0xac, 0xfb, 0xb0, 0x73, 0xb7, 0x15, 0x7f, 0x1c, 0xd2, 0xb8, 0xf2, 0x55,
-				0x96, 0x70, 0xa1, 0xf7, 0xe3, 0x48, 0x39, 0x41, 0x9c, 0x5d, 0xe8, 0x50, 0x16, 0xed, 0xec, 0x1e,
-				0xc3, 0xfd, 0x5d, 0x72, 0xd0, 0x42, 0x44, 0x35, 0xda, 0x1b, 0x07, 0x02, 0x19, 0x0b, 0xc4, 0xb2,
-				0xc4, 0x0e, 0x08, 0x7d, 0x6c, 0x17, 0x8e, 0x75, 0x41, 0x8f, 0x56, 0xb8, 0x5e, 0x28, 0xf9, 0x30,
-				0x80, 0x45, 0x5f, 0x2b, 0x5d, 0xe6, 0x67, 0x30, 0xac, 0x51, 0xf9, 0x64, 0x14, 0x6d, 0x51, 0xd0,
-				0x4a, 0x05, 0xb5, 0xf3, 0xee, 0x7e, 0xa0, 0x77, 0x40, 0x0e, 0xe2, 0xbb, 0x5d, 0x4c, 0x0c, 0x92,
-				0xb1, 0x91, 0x35, 0x1c, 0x49, 0xa1
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xa2, 0xa2, 0x7c, 0x04, 0x40, 0x00, 0x36, 0x2f, 0x5d, 0xd4, 0x23, 0x87,
-				0x8b, 0x4d, 0xd2, 0xb3, 0x0f, 0xfd, 0xbd, 0xc0, 0x0f, 0xcb, 0xf8, 0xce, 0xa1, 0x5d, 0x90, 0xd3,
-				0x6d, 0x4c, 0xce, 0xbb, 0xe0, 0xde, 0x11, 0xd9, 0xbb, 0x08, 0x86, 0x24, 0x48, 0xd8, 0x9d, 0x33,
-				0xff, 0xb0, 0x0e, 0xfb, 0x8d, 0xe9, 0xb8, 0x21, 0x1a, 0x2e, 0xb4, 0xd1, 0xd1, 0xcf, 0xc2, 0xb3,
-				0x7d, 0xce, 0x82, 0xd2, 0xf9, 0x32, 0x45, 0x13, 0x1a, 0x84, 0xce, 0xa1, 0xef, 0x70, 0x9b, 0x74,
-				0x3f, 0xb3, 0x92, 0x0e, 0xed, 0xe7, 0x7d, 0x3d, 0x0c, 0xf9, 0xb5, 0x94, 0x11, 0x8f, 0x06, 0xd1,
-				0x0f, 0xdf, 0xf5, 0x27, 0x9d, 0xf7, 0xa1, 0x8f, 0xc9, 0x3f, 0x34, 0x09, 0x87, 0x4e, 0x2f, 0xe8,
-				0xcf, 0x8e, 0x40, 0x2b, 0x55, 0xde, 0xe3, 0xbb, 0x7e, 0xb7, 0x97, 0xdf, 0xfe, 0xa5, 0x30, 0x21,
-				0xc3, 0x84, 0xe3, 0x25, 0xb7, 0x5a, 0xf9, 0x24, 0xe8, 0xbe, 0x48, 0x97, 0xbc, 0xaa, 0x8a, 0x1a,
-				0x9e, 0xea, 0xb3, 0x2d, 0x3c, 0x40, 0xf7, 0x31, 0xe2, 0xf6, 0x02, 0xf4, 0x72, 0x05, 0x70, 0x34,
-				0x45, 0xf3, 0xcc, 0x7f, 0xf9, 0x76, 0x06, 0x10, 0xfc, 0x8c, 0x56, 0x54, 0x68, 0x76, 0x82, 0x7b,
-				0x20, 0xfc, 0x70, 0x7d, 0xb5, 0x98, 0x5d, 0x33, 0x69, 0xf3, 0xea, 0x64, 0x44, 0x7e, 0xe7, 0x09,
-				0x77, 0x61, 0xe0, 0xbf, 0x82, 0x87, 0xa1, 0x4f, 0x9e, 0x96, 0x90, 0xb7, 0xc7, 0x0b, 0xf4, 0x20,
-				0x0d, 0x37, 0x27, 0x82, 0x4d, 0x84, 0xb3, 0x3d, 0x44, 0xe8, 0x49, 0x05, 0xeb, 0xd2, 0x07, 0xbf,
-				0xd7, 0xcc, 0x90, 0x62, 0x3d, 0x42, 0x16, 0x62, 0x78, 0xe4, 0xdc, 0x77, 0x41, 0xc4, 0xa6, 0xc0,
-				0xa3, 0x63, 0xef, 0x7d, 0xce, 0xd1, 0x71, 0x8d, 0xb1, 0x96, 0xdc, 0xa0, 0x7d, 0x86, 0xb2, 0x59,
-				0x19, 0xcb, 0x9e, 0x4b
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa2, 0xa2, 0x7c, 0x04,
-				0x40, 0x00, 0x36, 0x2f, 0x5d, 0xd4, 0x23, 0x87, 0x8b, 0x4d, 0xd2, 0xb3, 0x0f, 0xfd, 0xbd, 0xc0,
-				0x0f, 0xcb, 0xf8, 0xce, 0xa1, 0x5d, 0x90, 0xd3, 0x6d, 0x4c, 0xce, 0xbb, 0xe0, 0xde, 0x11, 0xd9,
-				0xbb, 0x08, 0x86, 0x24, 0x48, 0xd8, 0x9d, 0x33, 0xff, 0xb0, 0x0e, 0xfb, 0x8d, 0xe9, 0xb8, 0x21,
-				0x1a, 0x2e, 0xb4, 0xd1, 0xd1, 0xcf, 0xc2, 0xb3, 0x7d, 0xce, 0x82, 0xd2, 0xf9, 0x32, 0x45, 0x13,
-				0x1a, 0x84, 0xce, 0xa1, 0xef, 0x70, 0x9b, 0x74, 0x3f, 0xb3, 0x92, 0x0e, 0xed, 0xe7, 0x7d, 0x3d,
-				0x0c, 0xf9, 0xb5, 0x94, 0x11, 0x8f, 0x06, 0xd1, 0x0f, 0xdf, 0xf5, 0x27, 0x9d, 0xf7, 0xa1, 0x8f,
-				0xc9, 0x3f, 0x34, 0x09, 0x87, 0x4e, 0x2f, 0xe8, 0xcf, 0x8e, 0x40, 0x2b, 0x55, 0xde, 0xe3, 0xbb,
-				0x7e, 0xb7, 0x97, 0xdf, 0xfe, 0xa5, 0x30, 0x21, 0xc3, 0x84, 0xe3, 0x25, 0xb7, 0x5a, 0xf9, 0x24,
-				0xe8, 0xbe, 0x48, 0x97, 0xbc, 0xaa, 0x8a, 0x1a, 0x9e, 0xea, 0xb3, 0x2d, 0x3c, 0x40, 0xf7, 0x31,
-				0xe2, 0xf6, 0x02, 0xf4, 0x72, 0x05, 0x70, 0x34, 0x45, 0xf3, 0xcc, 0x7f, 0xf9, 0x76, 0x06, 0x10,
-				0xfc, 0x8c, 0x56, 0x54, 0x68, 0x76, 0x82, 0x7b, 0x20, 0xfc, 0x70, 0x7d, 0xb5, 0x98, 0x5d, 0x33,
-				0x69, 0xf3, 0xea, 0x64, 0x44, 0x7e, 0xe7, 0x09, 0x77, 0x61, 0xe0, 0xbf, 0x82, 0x87, 0xa1, 0x4f,
-				0x9e, 0x96, 0x90, 0xb7, 0xc7, 0x0b, 0xf4, 0x20, 0x0d, 0x37, 0x27, 0x82, 0x4d, 0x84, 0xb3, 0x3d,
-				0x44, 0xe8, 0x49, 0x05, 0xeb, 0xd2, 0x07, 0xbf, 0xd7, 0xcc, 0x90, 0x62, 0x3d, 0x42, 0x16, 0x62,
-				0x78, 0xe4, 0xdc, 0x77, 0x41, 0xc4, 0xa6, 0xc0, 0xa3, 0x63, 0xef, 0x7d, 0xce, 0xd1, 0x71, 0x8d,
-				0xb1, 0x96, 0xdc, 0xa0, 0x7d, 0x86, 0xb2, 0x59, 0x19, 0xcb, 0x9e, 0x4b, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x29, 0x53, 0x09, 0x19, 0x19, 0x5c, 0x14, 0x68, 0x97, 0xba, 0x5a,
-				0x26, 0xcc, 0x56, 0x43, 0x75, 0xfd, 0x57, 0xb7, 0xb9, 0xd0, 0x29, 0xbf, 0x78, 0x5d, 0x97, 0x45,
-				0x3f, 0xfb, 0xd3, 0x5a, 0xea, 0x71, 0x5a, 0x6c, 0x05, 0xbb, 0x99, 0x10, 0x60, 0xb2, 0xe3, 0xdb,
-				0x9a, 0x05, 0x5b, 0xaa, 0x8a, 0xef, 0xc5, 0xd5, 0xe4, 0x0f, 0x5f, 0x93, 0xd1, 0x86, 0xb2, 0xf8,
-				0x61, 0x9c, 0x53, 0x77, 0x79, 0x7d, 0x19, 0x71, 0x64, 0xc7, 0xc5, 0xbc, 0x2d, 0x78, 0x86, 0x4f,
-				0xf1, 0xcb, 0x67, 0xe8, 0xf2, 0x83, 0x2f, 0xe1, 0x6a, 0x3c, 0x5c, 0x4c, 0xef, 0xa9, 0x40, 0x82,
-				0xf6, 0x67, 0x46, 0xbc, 0x67, 0xcb, 0x23, 0x4b, 0x79, 0x9a, 0x24, 0xc5, 0xa7, 0xb0, 0x2a, 0x45,
-				0x51, 0x2e, 0x40, 0x12, 0x7d, 0x10, 0x6e, 0x38, 0xc6, 0x81, 0x0d, 0xcc, 0x78, 0xfd, 0x9e, 0xe2,
-				0xaa, 0x89, 0xa0, 0x40, 0x09, 0x02, 0x8d, 0x9a, 0x8a, 0x77, 0x7a, 0xb9, 0xef, 0xdb, 0xa2, 0x8e,
-				0xbb, 0x97, 0xfc, 0xb0, 0x0b, 0x92, 0x96, 0xc7, 0xa0, 0x70, 0x92, 0xbf, 0xbf, 0x99, 0x9a, 0x90,
-				0x9f, 0x11, 0xa6, 0x60, 0xb3, 0x1f, 0x7d, 0xb8, 0x15, 0x42, 0x67, 0x70, 0xd2, 0xc1, 0x0c, 0xdf,
-				0x6d, 0xc1, 0xad, 0x61, 0x76, 0x6d, 0x32, 0x60, 0xa2, 0xb6, 0x6e, 0x06, 0xde, 0xd5, 0x56, 0x6e,
-				0x27, 0x1d, 0x49, 0xda, 0x6f, 0x67, 0xfc, 0x4c, 0xf0, 0xa2, 0x13, 0xc4, 0x76, 0x18, 0x80, 0x30,
-				0xb3, 0x6d, 0xcd, 0x71, 0xfc, 0x16, 0xb1, 0x85, 0xf6, 0xe5, 0xdf, 0x01, 0xc1, 0x6a, 0xe8, 0x19,
-				0x32, 0x9e, 0x6d, 0xff, 0xd0, 0x1e, 0xaa, 0xcd, 0x2e, 0x6c, 0xc1, 0xc0, 0x67, 0x52, 0xdc, 0xf7,
-				0x2d, 0x56, 0xbf, 0x12, 0xe3, 0xf9, 0x85, 0xfd, 0x4d, 0x71, 0x2d, 0x55, 0x5c, 0xa4, 0xc7, 0xa3,
-				0x70, 0xc4, 0xc3, 0xdb, 0x65, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x7c, 0x82, 0x4d, 0x5d, 0xcd, 0x1e,
-				0x71, 0x6e, 0x9f, 0xeb, 0x57, 0x93, 0x25, 0x8a, 0xd0, 0xe0, 0xee, 0x3a, 0xb7, 0xd7, 0xd1, 0x1c,
-				0x68, 0xc8, 0x65, 0x3c, 0x2c, 0x79, 0x94, 0x36, 0x41, 0x51, 0xae, 0x17, 0x4b, 0xc5, 0x83, 0x00,
-				0x13, 0x96, 0xd7, 0x8e, 0x17, 0xe1, 0x86, 0x3f, 0x9d, 0x4f, 0xea, 0x10, 0x84, 0xa6, 0x63, 0xc6,
-				0x8d, 0x09, 0x11, 0xaa, 0x32, 0x92, 0xa6, 0xed, 0x4c, 0x8f, 0xf8, 0x5c, 0xee, 0x6b, 0x32, 0xf3,
-				0x8e, 0xb8, 0xc0, 0x65, 0xd9, 0x41, 0xed, 0x7b, 0x0d, 0x1e, 0xdb, 0x17, 0xe4, 0xea, 0x20, 0x15,
-				0xc8, 0x35, 0xfd, 0x3b, 0xc0, 0x66, 0x7c, 0x8c, 0xc6, 0x02, 0xed, 0x74, 0x64, 0x30, 0xfa, 0x8d,
-				0xe5, 0x29, 0x84, 0x8a, 0x6b, 0x6a, 0x93, 0x38, 0x4c, 0x56, 0xda, 0x5b, 0xb7, 0xe7, 0x44, 0x45,
-				0x4b, 0x7f, 0xef, 0xae, 0xcd, 0xa7, 0xc5, 0x8a, 0xcd, 0x02, 0x81, 0x81, 0x00, 0xb7, 0x05, 0x0a,
-				0x9f, 0x46, 0xe9, 0xcb, 0x67, 0x74, 0x6d, 0xe8, 0xbe, 0x11, 0xc4, 0xdd, 0x75, 0x8d, 0x16, 0x8c,
-				0x20, 0x04, 0x09, 0xf4, 0x4e, 0x88, 0xab, 0xcc, 0x7b, 0xad, 0x24, 0xd1, 0x66, 0x79, 0xf4, 0xd0,
-				0x2f, 0x9c, 0xb7, 0xf2, 0xcb, 0x4d, 0x26, 0x35, 0x0b, 0x79, 0x47, 0x15, 0xf0, 0x2e, 0xd1, 0x40,
-				0xb6, 0x9e, 0x59, 0x4e, 0xae, 0x11, 0x4a, 0xf2, 0xbb, 0x9d, 0x68, 0x4d, 0x4a, 0xfc, 0x86, 0xa0,
-				0xeb, 0x3c, 0x38, 0xf3, 0xfb, 0x5c, 0x27, 0xc3, 0xa0, 0x7e, 0xf2, 0x73, 0x3d, 0x19, 0x3d, 0x0a,
-				0x2f, 0xa8, 0x2d, 0xe0, 0x2c, 0x81, 0x5c, 0xda, 0xc6, 0x93, 0x60, 0xa0, 0xef, 0xb8, 0x23, 0x26,
-				0x32, 0xbc, 0x1a, 0x29, 0x2a, 0xb6, 0xe5, 0x62, 0xca, 0x69, 0x78, 0xee, 0xeb, 0x7b, 0xea, 0xa6,
-				0xb2, 0x53, 0x31, 0x46, 0xf0, 0x5b, 0x37, 0x19, 0x0f, 0x8c, 0xfa, 0x7d, 0x77, 0x02, 0x81, 0x80,
-				0x7c, 0x16, 0xbd, 0xe9, 0x3f, 0xe2, 0x94, 0xd9, 0xa1, 0x53, 0x80, 0x87, 0xbb, 0xcf, 0x7d, 0xc2,
-				0x64, 0xff, 0xee, 0x6d, 0xbc, 0x3e, 0xe7, 0xf5, 0x4c, 0x62, 0xd4, 0x89, 0x1a, 0x24, 0xbb, 0xd7,
-				0xb3, 0x9b, 0x78, 0x3f, 0xaf, 0xd4, 0xbe, 0xa4, 0xf0, 0xe2, 0x52, 0x33, 0x3a, 0xa5, 0x05, 0x6c,
-				0x65, 0x5c, 0x33, 0x78, 0x78, 0x5e, 0xf2, 0xbe, 0x9a, 0x14, 0xd5, 0xb7, 0x52, 0x81, 0xd5, 0xed,
-				0xae, 0x96, 0xf6, 0xf2, 0x62, 0xed, 0x5f, 0x28, 0x1a, 0x25, 0x71, 0x29, 0x2a, 0xaa, 0x45, 0x36,
-				0x29, 0xff, 0xaf, 0x30, 0x02, 0x7a, 0x50, 0x07, 0x6f, 0x53, 0xdc, 0x55, 0x1e, 0x52, 0x90, 0x63,
-				0xae, 0xd3, 0x22, 0x6b, 0x48, 0xc0, 0x53, 0xc8, 0x8e, 0x76, 0x2b, 0x1f, 0x5e, 0xfa, 0x41, 0x7a,
-				0x7a, 0xe2, 0x0f, 0xa7, 0xe8, 0x72, 0x38, 0x2e, 0x6f, 0xf2, 0x29, 0x73, 0x2b, 0x32, 0x39, 0x7d,
-				0x02, 0x81, 0x80, 0x1d, 0x1f, 0x14, 0x3d, 0x9b, 0xce, 0xff, 0xaa, 0x8a, 0x80, 0x22, 0x94, 0x7b,
-				0xc7, 0x53, 0x65, 0xac, 0xf9, 0x75, 0x7a, 0x72, 0xaa, 0x12, 0xd1, 0x9c, 0x35, 0x99, 0xe7, 0xe3,
-				0xf9, 0x03, 0xc8, 0xc6, 0x87, 0x09, 0xc9, 0x49, 0xaa, 0x8b, 0x5b, 0x85, 0xff, 0x1a, 0x59, 0xa5,
-				0x06, 0x86, 0x9b, 0x1d, 0x17, 0xf6, 0xb0, 0x18, 0x2a, 0x25, 0xb6, 0xd4, 0xd1, 0x94, 0x25, 0xfe,
-				0x39, 0xe6, 0x72, 0x94, 0x13, 0xe7, 0xef, 0x06, 0x3a, 0x19, 0xb8, 0x59, 0x45, 0x8a, 0x7f, 0x33,
-				0x33, 0xe8, 0xda, 0x43, 0xf5, 0xce, 0x75, 0x1e, 0xd1, 0x8d, 0xe6, 0x06, 0xff, 0x7b, 0x60, 0x35,
-				0x7b, 0x1e, 0xa0, 0x86, 0x30, 0x31, 0x97, 0xc9, 0x0e, 0x70, 0x96, 0x77, 0x5b, 0xb0, 0x88, 0x7c,
-				0x97, 0xdd, 0x8c, 0x62, 0xbf, 0x47, 0x9f, 0x00, 0x55, 0xca, 0xef, 0xdb, 0xd3, 0xbc, 0x8d, 0x18,
-				0xe5, 0x92, 0xa9, 0x02, 0x81, 0x80, 0x26, 0x9a, 0x9b, 0x49, 0x63, 0xac, 0x76, 0x83, 0xc5, 0x06,
-				0xa0, 0x5a, 0x5c, 0x5b, 0xd8, 0x1e, 0x07, 0x72, 0xa9, 0xa2, 0xeb, 0x6d, 0xd6, 0x29, 0xea, 0xb4,
-				0x4e, 0x0e, 0x77, 0x7b, 0x4f, 0xe4, 0x93, 0x5b, 0xb8, 0x14, 0x1f, 0x69, 0x82, 0x1e, 0x6d, 0x1d,
-				0x4c, 0x77, 0xe4, 0xe8, 0xa0, 0x10, 0x82, 0xf2, 0x24, 0xa4, 0x09, 0x86, 0x70, 0xea, 0x40, 0x7b,
-				0xcf, 0xbc, 0x2a, 0xf4, 0x06, 0xde, 0x2c, 0xe6, 0x07, 0x01, 0xa4, 0x08, 0xe5, 0xe2, 0xd5, 0x54,
-				0x8c, 0x15, 0x68, 0xce, 0x04, 0xa6, 0xf6, 0x9b, 0x90, 0xd9, 0xd2, 0x53, 0x5c, 0xba, 0xba, 0x2a,
-				0x86, 0xe1, 0xa8, 0x80, 0x14, 0xc6, 0x9f, 0xe0, 0xcf, 0x1a, 0x89, 0xef, 0x20, 0xe4, 0x6b, 0xc9,
-				0xec, 0x66, 0xeb, 0xa2, 0xf9, 0xae, 0xd6, 0x20, 0xd7, 0x7a, 0x44, 0xc7, 0x75, 0x7d, 0x43, 0x29,
-				0x4f, 0x8d, 0x07, 0xc9, 0x46, 0x1c
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xd3, 0x65, 0xb1, 0x2d, 0x81, 0x6a, 0x8d, 0x12, 0x4a, 0x78, 0x96, 0x04,
-				0x7e, 0x89, 0xd4, 0x0f, 0xee, 0xf6, 0x06, 0xe0, 0x76, 0xe4, 0x6f, 0x86, 0x60, 0x23, 0x87, 0xd0,
-				0x42, 0x9f, 0x9d, 0x80, 0xe2, 0xa6, 0x70, 0x63, 0xdf, 0x46, 0x30, 0x70, 0x57, 0x50, 0x02, 0x20,
-				0x5d, 0x34, 0x43, 0x21, 0x02, 0x5b, 0x85, 0x21, 0xc8, 0x22, 0xb1, 0x03, 0x9d, 0x63, 0x10, 0x0f,
-				0x0c, 0x54, 0x93, 0x36, 0x46, 0xca, 0x52, 0x38, 0x2a, 0xe4, 0xf7, 0xa1, 0xe8, 0x2a, 0xbb, 0x0f,
-				0xb2, 0x17, 0x25, 0xb4, 0x46, 0x84, 0x95, 0x21, 0xbe, 0xbe, 0xdc, 0x6a, 0xa1, 0x67, 0x30, 0x62,
-				0xed, 0x4c, 0x4c, 0xdb, 0x34, 0x10, 0x39, 0xf6, 0x88, 0xdc, 0xa4, 0x5c, 0x53, 0x18, 0x59, 0xa2,
-				0x19, 0x36, 0xc0, 0xbe, 0x24, 0x10, 0xd9, 0x37, 0xf9, 0xdb, 0xf8, 0xde, 0xaa, 0x2f, 0x28, 0x3d,
-				0xfc, 0x3c, 0x18, 0xd5, 0xc0, 0xcb, 0xc9, 0x3d, 0x20, 0x6a, 0x3e, 0xeb, 0x9b, 0xe8, 0xdc, 0x70,
-				0x6f, 0xc7, 0x4d, 0x13, 0xa3, 0xac, 0xe9, 0x3a, 0x1f, 0xe4, 0x64, 0x16, 0x75, 0xa1, 0x56, 0xe4,
-				0x43, 0x9c, 0xf7, 0xc2, 0x45, 0xea, 0xaa, 0x83, 0x3d, 0x0c, 0x50, 0x75, 0xd8, 0xfa, 0x24, 0x3b,
-				0xdb, 0x95, 0x0a, 0xa9, 0x25, 0x58, 0x63, 0x44, 0x4a, 0x21, 0xcc, 0x6a, 0xbb, 0xa6, 0xa8, 0x38,
-				0xf5, 0xd7, 0xd3, 0xd5, 0x4c, 0x60, 0xd2, 0x8d, 0xf8, 0x5b, 0xd3, 0xb1, 0x38, 0x1e, 0xaf, 0xab,
-				0x78, 0x1d, 0x07, 0xda, 0x91, 0x4c, 0xf0, 0x7b, 0xf5, 0x75, 0xe4, 0xb3, 0x3b, 0xca, 0x8a, 0xc5,
-				0x6f, 0x29, 0xc9, 0x16, 0xdd, 0xeb, 0x50, 0x8b, 0xbb, 0x02, 0x6d, 0x01, 0xfa, 0xde, 0x55, 0x53,
-				0xb0, 0x59, 0xa2, 0x63, 0x70, 0x99, 0x0a, 0xd7, 0xb6, 0x96, 0x30, 0xd0, 0x6a, 0x4e, 0x15, 0xa0,
-				0x39, 0x90, 0x7b, 0x4d
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd3, 0x65, 0xb1, 0x2d,
-				0x81, 0x6a, 0x8d, 0x12, 0x4a, 0x78, 0x96, 0x04, 0x7e, 0x89, 0xd4, 0x0f, 0xee, 0xf6, 0x06, 0xe0,
-				0x76, 0xe4, 0x6f, 0x86, 0x60, 0x23, 0x87, 0xd0, 0x42, 0x9f, 0x9d, 0x80, 0xe2, 0xa6, 0x70, 0x63,
-				0xdf, 0x46, 0x30, 0x70, 0x57, 0x50, 0x02, 0x20, 0x5d, 0x34, 0x43, 0x21, 0x02, 0x5b, 0x85, 0x21,
-				0xc8, 0x22, 0xb1, 0x03, 0x9d, 0x63, 0x10, 0x0f, 0x0c, 0x54, 0x93, 0x36, 0x46, 0xca, 0x52, 0x38,
-				0x2a, 0xe4, 0xf7, 0xa1, 0xe8, 0x2a, 0xbb, 0x0f, 0xb2, 0x17, 0x25, 0xb4, 0x46, 0x84, 0x95, 0x21,
-				0xbe, 0xbe, 0xdc, 0x6a, 0xa1, 0x67, 0x30, 0x62, 0xed, 0x4c, 0x4c, 0xdb, 0x34, 0x10, 0x39, 0xf6,
-				0x88, 0xdc, 0xa4, 0x5c, 0x53, 0x18, 0x59, 0xa2, 0x19, 0x36, 0xc0, 0xbe, 0x24, 0x10, 0xd9, 0x37,
-				0xf9, 0xdb, 0xf8, 0xde, 0xaa, 0x2f, 0x28, 0x3d, 0xfc, 0x3c, 0x18, 0xd5, 0xc0, 0xcb, 0xc9, 0x3d,
-				0x20, 0x6a, 0x3e, 0xeb, 0x9b, 0xe8, 0xdc, 0x70, 0x6f, 0xc7, 0x4d, 0x13, 0xa3, 0xac, 0xe9, 0x3a,
-				0x1f, 0xe4, 0x64, 0x16, 0x75, 0xa1, 0x56, 0xe4, 0x43, 0x9c, 0xf7, 0xc2, 0x45, 0xea, 0xaa, 0x83,
-				0x3d, 0x0c, 0x50, 0x75, 0xd8, 0xfa, 0x24, 0x3b, 0xdb, 0x95, 0x0a, 0xa9, 0x25, 0x58, 0x63, 0x44,
-				0x4a, 0x21, 0xcc, 0x6a, 0xbb, 0xa6, 0xa8, 0x38, 0xf5, 0xd7, 0xd3, 0xd5, 0x4c, 0x60, 0xd2, 0x8d,
-				0xf8, 0x5b, 0xd3, 0xb1, 0x38, 0x1e, 0xaf, 0xab, 0x78, 0x1d, 0x07, 0xda, 0x91, 0x4c, 0xf0, 0x7b,
-				0xf5, 0x75, 0xe4, 0xb3, 0x3b, 0xca, 0x8a, 0xc5, 0x6f, 0x29, 0xc9, 0x16, 0xdd, 0xeb, 0x50, 0x8b,
-				0xbb, 0x02, 0x6d, 0x01, 0xfa, 0xde, 0x55, 0x53, 0xb0, 0x59, 0xa2, 0x63, 0x70, 0x99, 0x0a, 0xd7,
-				0xb6, 0x96, 0x30, 0xd0, 0x6a, 0x4e, 0x15, 0xa0, 0x39, 0x90, 0x7b, 0x4d, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x81, 0xff, 0x3c, 0xe6, 0x4e, 0xe4, 0x8d, 0x23, 0xe5, 0x00, 0x1f, 0xf4, 0x1d, 0x43,
-				0xae, 0x30, 0x86, 0xa7, 0x10, 0x70, 0x50, 0x0a, 0xda, 0x35, 0x74, 0xeb, 0x81, 0x46, 0xbb, 0x19,
-				0x84, 0x17, 0xf7, 0x87, 0xe9, 0xc3, 0x89, 0x1d, 0x3c, 0x75, 0x3b, 0xff, 0x21, 0x28, 0x2b, 0x74,
-				0xa7, 0x65, 0x26, 0xf1, 0x9b, 0x7c, 0x42, 0x1e, 0x39, 0x49, 0xc5, 0x35, 0x05, 0x62, 0x44, 0x7e,
-				0x11, 0x4f, 0x4c, 0x19, 0x96, 0xcb, 0x32, 0x64, 0x7b, 0xf6, 0xfa, 0x5f, 0xea, 0x42, 0x65, 0x21,
-				0x60, 0x6c, 0xca, 0xaf, 0xe4, 0xa0, 0xcd, 0x55, 0xab, 0x5d, 0xd0, 0xa1, 0xe7, 0x5d, 0x92, 0xd2,
-				0xed, 0x09, 0xce, 0x1a, 0x58, 0x25, 0x54, 0x8d, 0x71, 0x60, 0x1e, 0xf9, 0x79, 0xf6, 0xc9, 0xdb,
-				0xa8, 0xe7, 0xdd, 0x1e, 0xe9, 0xc4, 0xf0, 0xce, 0xef, 0x6c, 0x2f, 0x85, 0xf6, 0x01, 0x1f, 0xd6,
-				0xbb, 0x93, 0x94, 0x93, 0x79, 0x72, 0xaa, 0x48, 0x17, 0x2e, 0xa7, 0x44, 0xa9, 0xa8, 0x02, 0xb7,
-				0xd1, 0x04, 0x76, 0x4e, 0x74, 0x27, 0x5d, 0x8a, 0xe3, 0xaa, 0x1d, 0x8c, 0xd4, 0xc0, 0xd6, 0xd1,
-				0x6c, 0x65, 0xee, 0xd0, 0xba, 0x1a, 0x39, 0x97, 0x61, 0x45, 0xca, 0xfb, 0xdc, 0xc8, 0xa9, 0x43,
-				0x9f, 0x0e, 0xf8, 0xcb, 0x68, 0xd9, 0x35, 0x3e, 0x4f, 0x82, 0xac, 0x96, 0xd1, 0x20, 0xb7, 0x82,
-				0x00, 0xda, 0x7c, 0x22, 0xd8, 0x5c, 0x55, 0x41, 0x16, 0xda, 0x71, 0xf0, 0x1b, 0xf5, 0x97, 0x4f,
-				0x45, 0x72, 0x9c, 0xad, 0xbe, 0x28, 0x9c, 0xf3, 0xe2, 0x50, 0x85, 0x07, 0x1c, 0x5d, 0xee, 0xd6,
-				0x4b, 0xcc, 0x2c, 0xaa, 0xa3, 0xfe, 0xb9, 0x4d, 0xcc, 0x23, 0xa3, 0x94, 0x5e, 0x98, 0x35, 0xf3,
-				0xa7, 0x65, 0x3b, 0x54, 0xcb, 0x81, 0x56, 0xc7, 0x8a, 0x11, 0xcb, 0xf3, 0x37, 0x9f, 0xf9, 0xa7,
-				0xc9, 0x4c, 0x71, 0x02, 0x81, 0x81, 0x00, 0xf6, 0xb8, 0x8d, 0x85, 0xec, 0xdc, 0x21, 0x33, 0xef,
-				0x72, 0xe3, 0x81, 0xa8, 0xe8, 0x38, 0xe3, 0x61, 0x56, 0xe2, 0x47, 0x73, 0x86, 0xff, 0x7e, 0x8a,
-				0xe0, 0xdc, 0x18, 0x16, 0x8c, 0x0c, 0x01, 0x31, 0xb5, 0x85, 0xc7, 0xab, 0xef, 0x7d, 0x77, 0x92,
-				0x4f, 0x78, 0x61, 0xcd, 0x50, 0x62, 0x1f, 0xc2, 0x31, 0x70, 0x70, 0xba, 0xd2, 0x12, 0x2c, 0xb8,
-				0xa5, 0xb2, 0x8b, 0x66, 0x55, 0x2b, 0x2c, 0x50, 0xf6, 0x75, 0xc8, 0xad, 0xaf, 0x54, 0xf9, 0x92,
-				0x56, 0xc4, 0x45, 0x19, 0x8f, 0xe3, 0x43, 0x0c, 0xcf, 0x94, 0xbe, 0x75, 0x1b, 0x6c, 0x0b, 0x0d,
-				0xcd, 0xaf, 0x65, 0x6d, 0x21, 0xce, 0xf0, 0xba, 0x4d, 0x40, 0x71, 0x94, 0x43, 0x64, 0x09, 0x9d,
-				0xb6, 0x65, 0x47, 0x98, 0xa7, 0x2b, 0xc1, 0xd5, 0x9e, 0xca, 0x2e, 0x3f, 0x41, 0xd2, 0xea, 0x9e,
-				0x9e, 0x07, 0xe1, 0xe7, 0x56, 0xfb, 0x9d, 0x02, 0x81, 0x81, 0x00, 0xdb, 0x59, 0x0a, 0x52, 0x84,
-				0x62, 0xbf, 0x4c, 0xb4, 0x88, 0x76, 0x54, 0xe8, 0xc4, 0x13, 0xee, 0x99, 0x40, 0xf5, 0xc7, 0x44,
-				0x60, 0xd9, 0x00, 0x3d, 0x01, 0xd7, 0x67, 0x77, 0xd0, 0x55, 0xc0, 0x86, 0x2c, 0xa1, 0xe3, 0xfd,
-				0x31, 0x0d, 0x1c, 0xfa, 0x3d, 0x3f, 0x35, 0xed, 0xe8, 0x59, 0x35, 0x9f, 0x66, 0xc1, 0xe9, 0x30,
-				0xb5, 0x50, 0x06, 0x80, 0xf2, 0xf5, 0x35, 0x0a, 0x59, 0xe9, 0xc7, 0xf1, 0xe1, 0x7f, 0xf3, 0x8d,
-				0xfd, 0x14, 0xb3, 0xfc, 0xea, 0xcd, 0xd4, 0x30, 0x88, 0x57, 0x5a, 0x68, 0x6a, 0xc4, 0x5b, 0x73,
-				0x46, 0xd8, 0xa9, 0x76, 0x61, 0x5e, 0x92, 0x69, 0xb3, 0x09, 0x06, 0xac, 0x2b, 0x1d, 0xd1, 0x2e,
-				0xc0, 0xfd, 0xcc, 0x13, 0xa8, 0x17, 0xce, 0x14, 0xc1, 0x9c, 0xe5, 0x33, 0x68, 0xdd, 0x9c, 0xdf,
-				0x1f, 0x21, 0xf3, 0xa1, 0xc5, 0xf2, 0xbc, 0x8b, 0xa8, 0xa7, 0x71, 0x02, 0x81, 0x81, 0x00, 0x92,
-				0x2a, 0x1f, 0xdd, 0xd9, 0xc7, 0x47, 0xfc, 0x66, 0xbd, 0x5f, 0xbf, 0x2e, 0xfb, 0xf4, 0xc7, 0xf0,
-				0xa0, 0xf2, 0x89, 0x76, 0x0d, 0xe2, 0x4b, 0x6b, 0xa7, 0x6f, 0x7c, 0xed, 0xce, 0xa6, 0x46, 0x06,
-				0xd7, 0x0d, 0x9c, 0x8f, 0x65, 0xe0, 0xa4, 0xf8, 0x0f, 0x10, 0xb8, 0x90, 0x54, 0x30, 0xed, 0xb3,
-				0xb4, 0x6a, 0x72, 0xbe, 0x9b, 0x39, 0x9d, 0x38, 0xff, 0x21, 0x59, 0xa8, 0x94, 0x88, 0x71, 0x46,
-				0xbd, 0xdc, 0x65, 0xb9, 0x50, 0x08, 0x3d, 0x9a, 0xce, 0xc0, 0x94, 0x57, 0x62, 0x81, 0x36, 0xf5,
-				0xdd, 0xfc, 0xb7, 0x20, 0xd5, 0xd0, 0x1a, 0x74, 0x61, 0x08, 0xaa, 0x44, 0x0f, 0x25, 0x74, 0x44,
-				0x4b, 0x04, 0x04, 0xc5, 0xdb, 0x6e, 0xe6, 0xab, 0x82, 0xa5, 0x59, 0xd7, 0x3c, 0x22, 0x96, 0x41,
-				0x22, 0x43, 0x91, 0x46, 0x74, 0x8e, 0xa9, 0xe4, 0xb2, 0xa6, 0xe4, 0xd4, 0x93, 0x19, 0x99, 0x02,
-				0x81, 0x81, 0x00, 0xad, 0x0b, 0x03, 0x9f, 0xb1, 0x9d, 0x0d, 0x79, 0xff, 0xfa, 0xa0, 0x0f, 0xc0,
-				0x49, 0xdf, 0xc7, 0x9d, 0xd3, 0xa7, 0x91, 0xfa, 0x99, 0xc4, 0xd7, 0xf1, 0x49, 0x20, 0x9c, 0x19,
-				0xe3, 0x9b, 0xa2, 0xf4, 0xb7, 0x05, 0x48, 0x8d, 0x98, 0x42, 0xd6, 0x17, 0x7c, 0x75, 0xff, 0x9f,
-				0x9e, 0x6b, 0xb2, 0x67, 0xfc, 0x73, 0x01, 0xfa, 0x51, 0x2f, 0xbe, 0xd1, 0xbf, 0xda, 0x3e, 0x6b,
-				0xda, 0x1f, 0x1a, 0x83, 0xf1, 0xf8, 0x35, 0x36, 0x50, 0xf0, 0x22, 0x46, 0x67, 0x1e, 0xd6, 0x45,
-				0x2b, 0x6a, 0x6e, 0x82, 0x6d, 0xa8, 0x56, 0xd5, 0x0c, 0x91, 0x24, 0xaf, 0xa5, 0x85, 0x2c, 0x50,
-				0x82, 0xd3, 0x9e, 0x15, 0xf9, 0x35, 0xde, 0xae, 0xd9, 0xc5, 0xdf, 0x57, 0xaa, 0x86, 0x8d, 0x27,
-				0xc6, 0xce, 0x75, 0xeb, 0x26, 0xd1, 0x9e, 0x4e, 0x4f, 0x8b, 0x43, 0x5e, 0xde, 0x80, 0xee, 0xc9,
-				0xe6, 0xd5, 0xa1, 0x02, 0x81, 0x80, 0x02, 0xec, 0xcf, 0x34, 0xa2, 0x1f, 0x12, 0xc8, 0x27, 0x66,
-				0x9f, 0x07, 0xb4, 0x55, 0x72, 0x67, 0x0b, 0xc2, 0xba, 0x1c, 0x6e, 0xc9, 0x25, 0x04, 0xed, 0x51,
-				0x53, 0x21, 0x3c, 0xcd, 0x3c, 0xe7, 0x1f, 0xeb, 0x17, 0x7d, 0x97, 0xde, 0xe4, 0x57, 0xb1, 0x89,
-				0x3b, 0xf1, 0x01, 0xb9, 0x2a, 0x4f, 0x74, 0xa8, 0x25, 0x0d, 0x92, 0xef, 0xbb, 0x0f, 0xf3, 0x57,
-				0x70, 0xb3, 0x58, 0x20, 0x75, 0x1e, 0xdb, 0x88, 0x96, 0x67, 0x44, 0x93, 0x27, 0x75, 0xc0, 0xa0,
-				0x33, 0xde, 0x53, 0xc0, 0x55, 0xc5, 0x52, 0x05, 0x71, 0x99, 0x61, 0xad, 0x77, 0x64, 0xb5, 0x85,
-				0x3e, 0xfa, 0xf6, 0xfe, 0xcd, 0x41, 0xae, 0x89, 0x48, 0xc3, 0x4f, 0x7a, 0x3e, 0x8e, 0x79, 0x32,
-				0xe2, 0xee, 0x83, 0x99, 0xb5, 0x73, 0xd9, 0xb6, 0x28, 0xb7, 0x51, 0x12, 0x4e, 0xbe, 0xde, 0x9e,
-				0xf4, 0x70, 0x65, 0x54, 0xff, 0x4f
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xe5, 0xcd, 0xb9, 0x78, 0x07, 0xfa, 0x23, 0x40, 0xf4, 0x35, 0x7f, 0x00,
-				0x4e, 0x99, 0xc5, 0xb6, 0xf5, 0xc0, 0x80, 0x37, 0xef, 0x1a, 0xec, 0xeb, 0x1e, 0xc2, 0xa4, 0x53,
-				0x28, 0x4f, 0x90, 0x43, 0xeb, 0x7b, 0xb7, 0x05, 0xae, 0xef, 0xda, 0x1f, 0x14, 0x74, 0xac, 0xa3,
-				0x5f, 0xca, 0x83, 0xb3, 0x0c, 0xa1, 0x78, 0x53, 0xc3, 0x76, 0xc3, 0xd3, 0x11, 0xf2, 0xb2, 0xde,
-				0x83, 0x69, 0xc7, 0xff, 0x54, 0x78, 0xab, 0xf5, 0x31, 0x07, 0xe2, 0xda, 0xa5, 0xff, 0xb1, 0xe0,
-				0x0a, 0x25, 0x9f, 0xe5, 0x3e, 0x9e, 0x43, 0xf0, 0x76, 0xb5, 0xab, 0x9a, 0x68, 0x71, 0x3f, 0x9c,
-				0xd5, 0xe4, 0x5c, 0x60, 0x12, 0x9e, 0x6d, 0x9f, 0x44, 0xec, 0xa1, 0xca, 0xf8, 0xcd, 0x2a, 0xe5,
-				0x17, 0x16, 0x1b, 0xf8, 0xa5, 0xf1, 0xc3, 0x72, 0x6d, 0x7d, 0xa5, 0x77, 0xa5, 0x1b, 0x66, 0xfb,
-				0x9c, 0xdb, 0xde, 0xb6, 0x25, 0x05, 0x35, 0x14, 0xc4, 0x71, 0x7b, 0x1d, 0x9d, 0x35, 0xb3, 0xa6,
-				0x53, 0xfb, 0x56, 0xf6, 0xab, 0x92, 0xbc, 0x82, 0x27, 0xfd, 0x1f, 0x87, 0xd9, 0x56, 0xf1, 0xb3,
-				0xac, 0x88, 0xc4, 0x65, 0x55, 0x7e, 0x4a, 0x38, 0x4d, 0x24, 0xc2, 0xa2, 0xc8, 0x2c, 0x00, 0xb2,
-				0x92, 0xfb, 0x71, 0x13, 0x20, 0x1d, 0x5e, 0x61, 0x01, 0x22, 0x76, 0x0d, 0x17, 0xbf, 0x13, 0x0f,
-				0xff, 0x6c, 0xcf, 0xe8, 0x4a, 0x2c, 0x00, 0x30, 0x57, 0x49, 0xb5, 0xd0, 0xe5, 0xef, 0x86, 0x9f,
-				0x50, 0xfe, 0x0f, 0xc3, 0x56, 0x68, 0x0e, 0xea, 0xb1, 0x39, 0xac, 0x1f, 0x4c, 0xdf, 0xbe, 0x0b,
-				0xbc, 0xca, 0x0a, 0x33, 0xdb, 0xdb, 0x3e, 0x0f, 0x32, 0x3d, 0xb6, 0x4d, 0x53, 0x20, 0xf2, 0x87,
-				0x8e, 0x14, 0xbc, 0x8e, 0xf1, 0xed, 0x61, 0x8f, 0x82, 0xca, 0xad, 0x07, 0x52, 0xf4, 0x86, 0x55,
-				0x2f, 0x33, 0xfe, 0x31
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe5, 0xcd, 0xb9, 0x78,
-				0x07, 0xfa, 0x23, 0x40, 0xf4, 0x35, 0x7f, 0x00, 0x4e, 0x99, 0xc5, 0xb6, 0xf5, 0xc0, 0x80, 0x37,
-				0xef, 0x1a, 0xec, 0xeb, 0x1e, 0xc2, 0xa4, 0x53, 0x28, 0x4f, 0x90, 0x43, 0xeb, 0x7b, 0xb7, 0x05,
-				0xae, 0xef, 0xda, 0x1f, 0x14, 0x74, 0xac, 0xa3, 0x5f, 0xca, 0x83, 0xb3, 0x0c, 0xa1, 0x78, 0x53,
-				0xc3, 0x76, 0xc3, 0xd3, 0x11, 0xf2, 0xb2, 0xde, 0x83, 0x69, 0xc7, 0xff, 0x54, 0x78, 0xab, 0xf5,
-				0x31, 0x07, 0xe2, 0xda, 0xa5, 0xff, 0xb1, 0xe0, 0x0a, 0x25, 0x9f, 0xe5, 0x3e, 0x9e, 0x43, 0xf0,
-				0x76, 0xb5, 0xab, 0x9a, 0x68, 0x71, 0x3f, 0x9c, 0xd5, 0xe4, 0x5c, 0x60, 0x12, 0x9e, 0x6d, 0x9f,
-				0x44, 0xec, 0xa1, 0xca, 0xf8, 0xcd, 0x2a, 0xe5, 0x17, 0x16, 0x1b, 0xf8, 0xa5, 0xf1, 0xc3, 0x72,
-				0x6d, 0x7d, 0xa5, 0x77, 0xa5, 0x1b, 0x66, 0xfb, 0x9c, 0xdb, 0xde, 0xb6, 0x25, 0x05, 0x35, 0x14,
-				0xc4, 0x71, 0x7b, 0x1d, 0x9d, 0x35, 0xb3, 0xa6, 0x53, 0xfb, 0x56, 0xf6, 0xab, 0x92, 0xbc, 0x82,
-				0x27, 0xfd, 0x1f, 0x87, 0xd9, 0x56, 0xf1, 0xb3, 0xac, 0x88, 0xc4, 0x65, 0x55, 0x7e, 0x4a, 0x38,
-				0x4d, 0x24, 0xc2, 0xa2, 0xc8, 0x2c, 0x00, 0xb2, 0x92, 0xfb, 0x71, 0x13, 0x20, 0x1d, 0x5e, 0x61,
-				0x01, 0x22, 0x76, 0x0d, 0x17, 0xbf, 0x13, 0x0f, 0xff, 0x6c, 0xcf, 0xe8, 0x4a, 0x2c, 0x00, 0x30,
-				0x57, 0x49, 0xb5, 0xd0, 0xe5, 0xef, 0x86, 0x9f, 0x50, 0xfe, 0x0f, 0xc3, 0x56, 0x68, 0x0e, 0xea,
-				0xb1, 0x39, 0xac, 0x1f, 0x4c, 0xdf, 0xbe, 0x0b, 0xbc, 0xca, 0x0a, 0x33, 0xdb, 0xdb, 0x3e, 0x0f,
-				0x32, 0x3d, 0xb6, 0x4d, 0x53, 0x20, 0xf2, 0x87, 0x8e, 0x14, 0xbc, 0x8e, 0xf1, 0xed, 0x61, 0x8f,
-				0x82, 0xca, 0xad, 0x07, 0x52, 0xf4, 0x86, 0x55, 0x2f, 0x33, 0xfe, 0x31, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x08, 0x06, 0x23, 0x3d, 0x66, 0x07, 0x3d, 0x91, 0xe2, 0xb5, 0x0c,
-				0xd1, 0x30, 0x42, 0xbd, 0x9c, 0xec, 0xd4, 0x78, 0x3a, 0xfb, 0xc0, 0xa9, 0xed, 0xc5, 0x18, 0xdb,
-				0x6f, 0x57, 0xe4, 0xa7, 0x4f, 0x3d, 0x25, 0x5d, 0xb7, 0xa2, 0x15, 0xc2, 0x92, 0x51, 0x3e, 0xdd,
-				0xae, 0xfa, 0xaf, 0x9c, 0x8c, 0xf4, 0xef, 0x9d, 0x14, 0x4c, 0xff, 0xe9, 0x9d, 0xdb, 0x6e, 0x3e,
-				0x56, 0xa1, 0xff, 0x60, 0x8f, 0x5c, 0x1e, 0x0b, 0xe0, 0x62, 0x2c, 0xe4, 0xa6, 0x93, 0xcd, 0xeb,
-				0x77, 0xbc, 0xd8, 0x4c, 0x23, 0xfa, 0x08, 0x16, 0xab, 0xdf, 0xc9, 0x3f, 0x76, 0x58, 0x6d, 0x3e,
-				0x8b, 0xb5, 0xb5, 0x8f, 0xe5, 0x7e, 0xe0, 0xef, 0x47, 0x9f, 0x65, 0x7a, 0x7a, 0x16, 0xd9, 0x3b,
-				0x1a, 0x88, 0x05, 0x7f, 0xf1, 0x32, 0x57, 0x7b, 0x11, 0x3f, 0x72, 0x22, 0xae, 0x9c, 0x77, 0x94,
-				0xcf, 0x4b, 0xa3, 0xd5, 0xbb, 0xdf, 0x76, 0x47, 0x05, 0x8c, 0x00, 0x12, 0xb9, 0x04, 0x88, 0x29,
-				0xe2, 0x9b, 0xd0, 0xfd, 0xa8, 0xfb, 0x4d, 0x2b, 0xac, 0x9c, 0x67, 0x8e, 0x56, 0x19, 0xff, 0x69,
-				0xe7, 0xb3, 0x26, 0x11, 0xc0, 0xc2, 0x10, 0x5c, 0x70, 0xdd, 0x72, 0x07, 0x99, 0x3f, 0xbc, 0x53,
-				0x4c, 0x5a, 0xda, 0xc3, 0x27, 0x3d, 0xdd, 0x3e, 0x40, 0x91, 0x5f, 0x4a, 0x8c, 0x3d, 0x4d, 0x15,
-				0x84, 0xc7, 0x5d, 0xfb, 0x8a, 0x40, 0x25, 0xba, 0xce, 0x28, 0x63, 0x24, 0x2d, 0x98, 0x45, 0xa1,
-				0x9b, 0xf7, 0xed, 0x76, 0xbf, 0x2d, 0xe5, 0x3f, 0x8e, 0x2a, 0xed, 0xd7, 0xaa, 0x15, 0x7e, 0xae,
-				0xc9, 0x86, 0xa1, 0x02, 0x86, 0x6a, 0x0b, 0x7d, 0x44, 0x41, 0x35, 0x0a, 0x57, 0x26, 0x9b, 0x68,
-				0x0a, 0x56, 0xbe, 0x26, 0x54, 0xe8, 0x72, 0x54, 0x57, 0x56, 0xad, 0xe7, 0xcb, 0xaa, 0xc6, 0xe8,
-				0x8f, 0x2c, 0xb0, 0x0a, 0x51, 0x02, 0x81, 0x81, 0x00, 0xfe, 0xc7, 0xda, 0xf5, 0x28, 0x30, 0x06,
-				0x33, 0x00, 0x85, 0xa7, 0xea, 0x9e, 0x87, 0xc0, 0xdc, 0xd7, 0x1d, 0x31, 0x31, 0xa5, 0x04, 0x0f,
-				0x84, 0x9e, 0x73, 0x3f, 0x1d, 0x88, 0xfd, 0x64, 0xaf, 0x71, 0xca, 0xaf, 0x9a, 0x78, 0x89, 0xf6,
-				0xe8, 0x56, 0x45, 0x89, 0xf0, 0x57, 0xa5, 0x71, 0x37, 0x3e, 0x02, 0x34, 0x46, 0x1d, 0xb7, 0xe9,
-				0x92, 0xaf, 0xb3, 0x58, 0x36, 0xa8, 0xe5, 0xa8, 0x5a, 0x40, 0x86, 0x57, 0x4f, 0x6b, 0x7e, 0x48,
-				0xe2, 0xba, 0x28, 0xd0, 0xd7, 0xad, 0x60, 0xbd, 0x73, 0x83, 0xaf, 0x3d, 0x60, 0x61, 0x79, 0xa4,
-				0xfd, 0x20, 0x65, 0xba, 0xdb, 0x18, 0x7a, 0x34, 0x49, 0xc5, 0xf4, 0xe5, 0x41, 0xcd, 0x53, 0x4a,
-				0x53, 0x19, 0x7a, 0x7e, 0x3d, 0x5d, 0x64, 0xe7, 0x6a, 0xa1, 0x2f, 0x90, 0x74, 0xfd, 0x46, 0x59,
-				0xec, 0x51, 0x8b, 0xbf, 0x02, 0x44, 0xff, 0x12, 0x1d, 0x02, 0x81, 0x81, 0x00, 0xe6, 0xe7, 0x44,
-				0xbd, 0x02, 0xf5, 0x90, 0x63, 0xb4, 0x15, 0xfd, 0x2d, 0x97, 0x24, 0x4a, 0x5d, 0xe3, 0xbb, 0x34,
-				0xac, 0xf2, 0x3a, 0xb9, 0x16, 0xd8, 0x45, 0xd1, 0xef, 0x68, 0x12, 0xb6, 0x64, 0xa7, 0x5a, 0x1f,
-				0xe7, 0xb7, 0x44, 0xcc, 0x7a, 0xf0, 0x5c, 0xee, 0xaf, 0x0c, 0x1c, 0xe8, 0x1a, 0xb7, 0x47, 0x90,
-				0x86, 0xb3, 0x40, 0xa4, 0x9e, 0xd1, 0xa7, 0x66, 0xa9, 0x81, 0xc6, 0x42, 0xb6, 0xae, 0x9f, 0x79,
-				0x88, 0x38, 0xf3, 0xe5, 0xab, 0x68, 0x62, 0xac, 0x34, 0x21, 0xcb, 0x7c, 0x87, 0x04, 0x15, 0x8c,
-				0x0f, 0x03, 0x0a, 0xcd, 0xc0, 0x61, 0x44, 0xd7, 0x7f, 0xd6, 0x7b, 0x7c, 0x55, 0x0b, 0xba, 0xf1,
-				0x6c, 0x92, 0x73, 0xaa, 0x1e, 0x96, 0xe3, 0x93, 0x61, 0xa2, 0x08, 0x6d, 0x3e, 0x68, 0x05, 0x83,
-				0x5a, 0x3f, 0xb8, 0x07, 0xe6, 0x9f, 0x6b, 0x76, 0x94, 0x97, 0xe1, 0xe0, 0x25, 0x02, 0x81, 0x80,
-				0x19, 0xa9, 0x75, 0xa3, 0x65, 0xc5, 0xd8, 0x8a, 0x00, 0x8e, 0x75, 0xc8, 0x4a, 0xe9, 0x6f, 0x82,
-				0x8e, 0xe4, 0x30, 0xd5, 0x48, 0x42, 0xad, 0x71, 0x75, 0x28, 0x34, 0x7e, 0x3c, 0x13, 0x11, 0xb6,
-				0x1e, 0x27, 0x05, 0x22, 0xf0, 0xeb, 0x2c, 0x84, 0x60, 0x54, 0x26, 0xbd, 0x9f, 0x86, 0x59, 0x6d,
-				0xef, 0xff, 0xf6, 0xd5, 0xed, 0x1e, 0x5e, 0x17, 0x59, 0x3d, 0x1e, 0x30, 0x7b, 0x38, 0x8e, 0x89,
-				0x70, 0xa0, 0x57, 0x60, 0xf7, 0x79, 0xc3, 0xcb, 0x9a, 0x66, 0x8c, 0x0a, 0x7d, 0x3b, 0x16, 0x39,
-				0xf1, 0x54, 0x90, 0x41, 0x09, 0xf0, 0x5f, 0xae, 0xe3, 0x39, 0x7b, 0xe5, 0x9f, 0x84, 0x87, 0x89,
-				0xba, 0xb7, 0x9c, 0xf3, 0xd0, 0xc3, 0x87, 0xe3, 0xf0, 0xd8, 0x06, 0xa9, 0x15, 0xa4, 0x19, 0x2f,
-				0x03, 0x47, 0x30, 0x2c, 0xa8, 0x6a, 0x12, 0x9a, 0x9b, 0xe8, 0x10, 0x78, 0x21, 0x0c, 0xf3, 0xfd,
-				0x02, 0x81, 0x80, 0x08, 0xf1, 0x27, 0xde, 0x52, 0x01, 0x04, 0x88, 0x77, 0xee, 0xea, 0x11, 0x1b,
-				0xeb, 0x51, 0xdd, 0xf4, 0xf5, 0xc9, 0x02, 0x71, 0x97, 0x08, 0x97, 0xf3, 0xe4, 0x30, 0x4f, 0x1f,
-				0x2e, 0xaa, 0x55, 0x97, 0x8d, 0x8b, 0xf2, 0xc3, 0x4c, 0x2c, 0xc7, 0x0e, 0x0b, 0xeb, 0x4a, 0x68,
-				0x23, 0xae, 0x71, 0x6a, 0x6b, 0xa1, 0x13, 0x36, 0x59, 0xe8, 0x86, 0x26, 0x04, 0x5f, 0x9b, 0x6c,
-				0xe5, 0x2a, 0xac, 0x3c, 0x72, 0xfc, 0x97, 0xe3, 0xec, 0xbe, 0x16, 0x37, 0x42, 0xaa, 0xfc, 0x91,
-				0xda, 0x79, 0x86, 0x19, 0x08, 0x64, 0x96, 0x28, 0x3e, 0x00, 0xdd, 0xd4, 0x66, 0x80, 0x19, 0xf9,
-				0x4a, 0x6a, 0xf4, 0x38, 0x32, 0x13, 0x2b, 0x6b, 0x38, 0x83, 0x7c, 0x0f, 0xc7, 0xdc, 0x6b, 0x49,
-				0x85, 0x1e, 0x05, 0xee, 0xad, 0x57, 0xfa, 0xe4, 0xc0, 0xd1, 0xbd, 0x82, 0xaa, 0xfc, 0xba, 0xa0,
-				0x6f, 0x24, 0xe9, 0x02, 0x81, 0x80, 0x63, 0xd1, 0xac, 0xa7, 0xf1, 0xd3, 0x59, 0x18, 0xc7, 0x6a,
-				0xb9, 0x07, 0xd3, 0xc1, 0x66, 0xed, 0x87, 0x53, 0x31, 0xbf, 0xfa, 0xf1, 0x91, 0x97, 0x39, 0xf3,
-				0x8a, 0x8d, 0xe3, 0x2c, 0x35, 0x02, 0x27, 0xa9, 0x58, 0xf3, 0x9f, 0x4f, 0x04, 0x5b, 0xd0, 0xe1,
-				0x11, 0xa8, 0x41, 0xec, 0x9d, 0x06, 0x51, 0xb5, 0xb8, 0x7e, 0xff, 0x3b, 0xcd, 0xe1, 0x06, 0xf3,
-				0xd6, 0xa2, 0x2d, 0x22, 0x01, 0x97, 0xb4, 0x82, 0x34, 0x7d, 0x4b, 0x73, 0x55, 0xd5, 0x03, 0xf0,
-				0xd3, 0x8c, 0xb8, 0x9e, 0xdc, 0x3a, 0x97, 0x2a, 0x2b, 0x51, 0x07, 0x69, 0x7a, 0x59, 0x4b, 0xb4,
-				0x75, 0xb8, 0x9d, 0x24, 0xb4, 0xed, 0x44, 0xe4, 0xec, 0x66, 0xdc, 0x18, 0x5e, 0xe3, 0x20, 0x5a,
-				0xde, 0x68, 0x51, 0x8b, 0xe2, 0xae, 0xe2, 0x0c, 0xa5, 0x04, 0xe2, 0xa1, 0xe4, 0xef, 0xfe, 0xff,
-				0x06, 0x8d, 0x6e, 0xf8, 0x02, 0x2d
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0x84, 0x17, 0x45, 0x53, 0x09, 0x42, 0x7b, 0x20, 0x4e, 0xda, 0x1a, 0x0e,
-				0x80, 0xf8, 0xf1, 0xc3, 0x54, 0xc2, 0xcf, 0xad, 0xa9, 0xad, 0x60, 0x88, 0xf0, 0x4b, 0xa0, 0x4d,
-				0x6c, 0x78, 0xe5, 0x34, 0x1f, 0x28, 0xbc, 0xdc, 0x80, 0x48, 0x7d, 0xfc, 0x70, 0x9c, 0xd0, 0x2f,
-				0xc0, 0xaa, 0xc2, 0x37, 0xe3, 0x56, 0x0a, 0x53, 0x42, 0x74, 0x5b, 0x4a, 0x5e, 0xfb, 0xe9, 0x9c,
-				0x25, 0x3c, 0x18, 0xc9, 0xb7, 0x2b, 0xb6, 0xa9, 0xe1, 0xcf, 0x4f, 0xeb, 0x0a, 0xf6, 0x02, 0x85,
-				0x48, 0xc1, 0xc0, 0x91, 0xe2, 0x86, 0xe7, 0xb2, 0xfe, 0xdc, 0x10, 0x42, 0x37, 0xbb, 0xa6, 0x8d,
-				0x82, 0x6a, 0xbb, 0xa9, 0x77, 0xa6, 0x1f, 0xa4, 0x9f, 0xd2, 0x9e, 0xdd, 0xe3, 0xa0, 0x07, 0x82,
-				0xdd, 0xae, 0x32, 0x70, 0xe4, 0x7a, 0x9c, 0xb2, 0x2d, 0x52, 0xd2, 0x0a, 0x58, 0xb3, 0x78, 0x96,
-				0x83, 0x02, 0x32, 0x84, 0x4f, 0x06, 0x98, 0x3b, 0x26, 0x0c, 0x82, 0x0b, 0x36, 0x64, 0xc2, 0xe4,
-				0x05, 0xa4, 0x95, 0x47, 0x07, 0xc8, 0xcc, 0x66, 0xd4, 0x64, 0x01, 0x18, 0x27, 0x94, 0x00, 0x1b,
-				0x32, 0x9b, 0x9e, 0xf6, 0x2f, 0x63, 0xd7, 0x0c, 0x65, 0x73, 0x1d, 0x93, 0x7a, 0xec, 0x8d, 0x15,
-				0xde, 0x98, 0x5e, 0x2b, 0xbf, 0x42, 0x78, 0xaa, 0xbe, 0xf8, 0xd8, 0x2a, 0x66, 0x2c, 0x15, 0xf1,
-				0xae, 0x3b, 0xe7, 0x0b, 0x26, 0x25, 0xda, 0x23, 0x22, 0x0d, 0x37, 0x7a, 0x7d, 0x5d, 0xf6, 0x53,
-				0x70, 0x27, 0xaa, 0x1e, 0x1f, 0x0e, 0x2f, 0x5b, 0xcd, 0xa0, 0xf6, 0x8b, 0xbd, 0x6b, 0x89, 0x82,
-				0xe5, 0x52, 0x96, 0x1b, 0x5c, 0xac, 0xdb, 0xeb, 0x11, 0x77, 0xc0, 0x67, 0x56, 0x5d, 0x67, 0xd6,
-				0xa8, 0xad, 0x9a, 0xb4, 0xc2, 0x16, 0x45, 0x6b, 0x48, 0x9f, 0x8c, 0xca, 0x26, 0x12, 0xcc, 0x91,
-				0x88, 0xbc, 0x61, 0xdf
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x84, 0x17, 0x45, 0x53,
-				0x09, 0x42, 0x7b, 0x20, 0x4e, 0xda, 0x1a, 0x0e, 0x80, 0xf8, 0xf1, 0xc3, 0x54, 0xc2, 0xcf, 0xad,
-				0xa9, 0xad, 0x60, 0x88, 0xf0, 0x4b, 0xa0, 0x4d, 0x6c, 0x78, 0xe5, 0x34, 0x1f, 0x28, 0xbc, 0xdc,
-				0x80, 0x48, 0x7d, 0xfc, 0x70, 0x9c, 0xd0, 0x2f, 0xc0, 0xaa, 0xc2, 0x37, 0xe3, 0x56, 0x0a, 0x53,
-				0x42, 0x74, 0x5b, 0x4a, 0x5e, 0xfb, 0xe9, 0x9c, 0x25, 0x3c, 0x18, 0xc9, 0xb7, 0x2b, 0xb6, 0xa9,
-				0xe1, 0xcf, 0x4f, 0xeb, 0x0a, 0xf6, 0x02, 0x85, 0x48, 0xc1, 0xc0, 0x91, 0xe2, 0x86, 0xe7, 0xb2,
-				0xfe, 0xdc, 0x10, 0x42, 0x37, 0xbb, 0xa6, 0x8d, 0x82, 0x6a, 0xbb, 0xa9, 0x77, 0xa6, 0x1f, 0xa4,
-				0x9f, 0xd2, 0x9e, 0xdd, 0xe3, 0xa0, 0x07, 0x82, 0xdd, 0xae, 0x32, 0x70, 0xe4, 0x7a, 0x9c, 0xb2,
-				0x2d, 0x52, 0xd2, 0x0a, 0x58, 0xb3, 0x78, 0x96, 0x83, 0x02, 0x32, 0x84, 0x4f, 0x06, 0x98, 0x3b,
-				0x26, 0x0c, 0x82, 0x0b, 0x36, 0x64, 0xc2, 0xe4, 0x05, 0xa4, 0x95, 0x47, 0x07, 0xc8, 0xcc, 0x66,
-				0xd4, 0x64, 0x01, 0x18, 0x27, 0x94, 0x00, 0x1b, 0x32, 0x9b, 0x9e, 0xf6, 0x2f, 0x63, 0xd7, 0x0c,
-				0x65, 0x73, 0x1d, 0x93, 0x7a, 0xec, 0x8d, 0x15, 0xde, 0x98, 0x5e, 0x2b, 0xbf, 0x42, 0x78, 0xaa,
-				0xbe, 0xf8, 0xd8, 0x2a, 0x66, 0x2c, 0x15, 0xf1, 0xae, 0x3b, 0xe7, 0x0b, 0x26, 0x25, 0xda, 0x23,
-				0x22, 0x0d, 0x37, 0x7a, 0x7d, 0x5d, 0xf6, 0x53, 0x70, 0x27, 0xaa, 0x1e, 0x1f, 0x0e, 0x2f, 0x5b,
-				0xcd, 0xa0, 0xf6, 0x8b, 0xbd, 0x6b, 0x89, 0x82, 0xe5, 0x52, 0x96, 0x1b, 0x5c, 0xac, 0xdb, 0xeb,
-				0x11, 0x77, 0xc0, 0x67, 0x56, 0x5d, 0x67, 0xd6, 0xa8, 0xad, 0x9a, 0xb4, 0xc2, 0x16, 0x45, 0x6b,
-				0x48, 0x9f, 0x8c, 0xca, 0x26, 0x12, 0xcc, 0x91, 0x88, 0xbc, 0x61, 0xdf, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x34, 0x54, 0x2f, 0xbf, 0x8c, 0x9c, 0x8c, 0xc0, 0xa8, 0xdc, 0x58,
-				0x94, 0x44, 0x5d, 0xdb, 0x11, 0x42, 0x04, 0x07, 0x58, 0x4a, 0x2f, 0x08, 0x5e, 0x57, 0xab, 0xee,
-				0x2e, 0x9d, 0xf9, 0x6a, 0xfb, 0xf2, 0x18, 0x26, 0x71, 0xc8, 0x54, 0x6f, 0xac, 0xd1, 0x44, 0x1e,
-				0x69, 0xbc, 0x8f, 0x29, 0x70, 0x10, 0x9c, 0xe6, 0x6c, 0x43, 0x98, 0x6b, 0x0e, 0x14, 0x81, 0x01,
-				0xf4, 0x3d, 0x00, 0x08, 0xe5, 0xe8, 0xad, 0xe5, 0xa8, 0x79, 0x6f, 0xb2, 0xbe, 0x6f, 0xd2, 0x33,
-				0xff, 0x6f, 0x6a, 0x6a, 0x8a, 0xa0, 0xce, 0x46, 0xfe, 0x2f, 0x5f, 0x29, 0x05, 0xc2, 0xa4, 0x91,
-				0x7f, 0xe0, 0x19, 0xbe, 0x8c, 0x8d, 0x7c, 0xff, 0x6e, 0x2d, 0x6e, 0xb8, 0x47, 0x39, 0x45, 0x0d,
-				0x94, 0xb7, 0x93, 0xaa, 0x21, 0xf5, 0x31, 0xe9, 0xdf, 0xe0, 0x7a, 0xbe, 0x01, 0x21, 0x50, 0xc0,
-				0x46, 0x08, 0x52, 0x97, 0x86, 0x27, 0x41, 0x1d, 0x88, 0xd9, 0xae, 0xd9, 0xad, 0x4e, 0x37, 0x3b,
-				0xe9, 0x5b, 0x2b, 0x83, 0x5c, 0xcb, 0xc1, 0x8e, 0x09, 0x0a, 0x6e, 0xb7, 0xe1, 0x4b, 0x1d, 0x31,
-				0x49, 0x22, 0xb3, 0x05, 0x51, 0x60, 0xa9, 0x78, 0xfd, 0xae, 0xe8, 0xe0, 0xd8, 0xc3, 0xbb, 0xb0,
-				0xe2, 0xee, 0x9c, 0x40, 0x52, 0x56, 0xed, 0xed, 0x4c, 0x85, 0x79, 0xd2, 0x6b, 0x40, 0xcd, 0x5f,
-				0x2b, 0x96, 0x35, 0xcf, 0xe2, 0xfc, 0xf5, 0xb1, 0xcc, 0x3e, 0x89, 0xb4, 0xad, 0x08, 0x46, 0x00,
-				0x78, 0x3e, 0x83, 0x44, 0xd5, 0x76, 0x5f, 0x1b, 0x48, 0xdd, 0xf7, 0x8c, 0x19, 0xf1, 0x79, 0xa0,
-				0x63, 0x98, 0x66, 0x84, 0x8e, 0x84, 0xa3, 0xfb, 0x0b, 0xaf, 0x88, 0xc7, 0x10, 0xe3, 0x36, 0x86,
-				0x19, 0xea, 0x4a, 0x04, 0xc2, 0x81, 0x53, 0xb0, 0x9f, 0x44, 0xdb, 0xbc, 0xb6, 0xaf, 0xe2, 0x59,
-				0x70, 0x97, 0x6d, 0xbf, 0x61, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x00, 0x69, 0x39, 0x0a, 0x0e, 0xc4,
-				0x1c, 0x46, 0x5a, 0xb9, 0xdb, 0x8a, 0xac, 0xd7, 0xa3, 0x4f, 0xcc, 0x30, 0x18, 0xfb, 0x28, 0x38,
-				0x3d, 0x2e, 0x7b, 0xe7, 0x30, 0xeb, 0xe3, 0x67, 0x29, 0xbc, 0x93, 0x46, 0x02, 0x04, 0x2f, 0x26,
-				0x04, 0xe6, 0x21, 0xaf, 0xac, 0x09, 0xea, 0xdf, 0xc6, 0xfd, 0xb1, 0x4c, 0x60, 0xd1, 0xdf, 0x6e,
-				0x83, 0x3d, 0x5e, 0xa6, 0x6b, 0x56, 0xe9, 0x30, 0xf1, 0x9d, 0xaa, 0xf5, 0x6c, 0xb7, 0x36, 0x8a,
-				0x68, 0x3f, 0xcc, 0x48, 0xd0, 0x14, 0x52, 0x71, 0x96, 0x7b, 0x0a, 0xbb, 0x99, 0x7d, 0x67, 0xc2,
-				0xe8, 0xa1, 0xd2, 0x04, 0x0b, 0xc1, 0xdf, 0xb9, 0x5d, 0x29, 0x85, 0x6f, 0x18, 0xf4, 0x7b, 0x23,
-				0x71, 0x63, 0x4f, 0x58, 0xd8, 0xd3, 0xb6, 0xd4, 0xf4, 0x9e, 0x3c, 0x6a, 0xb9, 0x35, 0x43, 0xfe,
-				0x8d, 0x91, 0x90, 0x42, 0x5b, 0xcc, 0xc3, 0x6d, 0x4f, 0x02, 0x81, 0x81, 0x00, 0xb7, 0xc6, 0xec,
-				0x39, 0xbd, 0x05, 0x54, 0xaa, 0x1a, 0xd1, 0x35, 0xb4, 0x2c, 0xc9, 0xa1, 0x19, 0xe1, 0xca, 0x5d,
-				0x78, 0x18, 0x48, 0x2c, 0xfe, 0xcb, 0x8e, 0x14, 0x92, 0xcb, 0xfd, 0x03, 0x26, 0xb2, 0xef, 0xdd,
-				0xc0, 0x52, 0x31, 0x8f, 0x79, 0xf2, 0xaf, 0xbe, 0x47, 0x55, 0xbe, 0xe8, 0x50, 0xd3, 0x82, 0x8e,
-				0xd6, 0x3f, 0xaa, 0x42, 0x86, 0xea, 0x15, 0xe5, 0xfe, 0xcc, 0x9b, 0x27, 0x35, 0x38, 0xd7, 0xab,
-				0x97, 0xd6, 0x6c, 0x6e, 0x32, 0x07, 0xbd, 0xf1, 0x54, 0x3c, 0xb0, 0x7a, 0x75, 0x2b, 0xa7, 0x89,
-				0xf6, 0xe5, 0x2f, 0xe2, 0x16, 0xac, 0x61, 0x8b, 0xe1, 0xd6, 0x6d, 0xfd, 0xe4, 0x7e, 0xad, 0x98,
-				0x81, 0x31, 0xe0, 0x3d, 0x4c, 0xee, 0xe8, 0xda, 0x5d, 0x07, 0x33, 0xc6, 0xe6, 0x26, 0x73, 0xc0,
-				0xa7, 0xbf, 0x4c, 0xab, 0xc3, 0x82, 0xc7, 0xec, 0x3d, 0x8e, 0x00, 0x3e, 0x71, 0x02, 0x81, 0x80,
-				0x24, 0x67, 0xf8, 0x69, 0xcf, 0xc2, 0xa2, 0x2c, 0xd2, 0x02, 0xcb, 0x79, 0x53, 0xd3, 0xe5, 0x0a,
-				0xac, 0x14, 0x43, 0x83, 0xfd, 0xd5, 0xb4, 0x62, 0xee, 0x9a, 0x97, 0x60, 0xc7, 0x9b, 0x83, 0xe2,
-				0xef, 0x2b, 0xd8, 0x93, 0x37, 0x8e, 0xb8, 0xa0, 0x09, 0x84, 0xaa, 0xc4, 0x88, 0x65, 0xcf, 0x87,
-				0x08, 0xd5, 0x16, 0xbe, 0xa5, 0x67, 0xe6, 0xee, 0xd2, 0xaa, 0xb2, 0x94, 0xd4, 0x6a, 0x69, 0x43,
-				0xb5, 0x25, 0x89, 0x4f, 0xcc, 0x64, 0x5f, 0x38, 0x47, 0x3f, 0x3d, 0x3c, 0xe6, 0x78, 0x75, 0x7f,
-				0x07, 0xb3, 0x54, 0xf1, 0x06, 0xae, 0x0c, 0x13, 0x89, 0x49, 0x0b, 0x81, 0xe4, 0x07, 0x47, 0x1e,
-				0xd6, 0xc3, 0x4e, 0xfb, 0x0a, 0x0c, 0x7f, 0x33, 0xc5, 0x29, 0x82, 0xf3, 0xcb, 0xd8, 0x06, 0x04,
-				0xac, 0x76, 0x59, 0xcb, 0x71, 0x6d, 0x95, 0xa5, 0x1f, 0x23, 0x02, 0xee, 0x34, 0xf2, 0x89, 0xe3,
-				0x02, 0x81, 0x80, 0x04, 0xf8, 0x0f, 0xf3, 0x0f, 0xb5, 0x51, 0x30, 0xb8, 0x40, 0xe7, 0xde, 0xd3,
-				0x47, 0x30, 0x5f, 0xee, 0xc6, 0xf5, 0xf8, 0x05, 0x50, 0x0e, 0x47, 0x65, 0x61, 0x96, 0x14, 0xd2,
-				0x07, 0x29, 0x4a, 0xa6, 0x93, 0xed, 0xbf, 0x01, 0x79, 0xed, 0x93, 0x32, 0x88, 0xa5, 0xf0, 0x6f,
-				0xd5, 0x15, 0x9a, 0xf9, 0xdd, 0x11, 0xd7, 0xa1, 0x29, 0x0d, 0x5b, 0x70, 0x80, 0xdf, 0x13, 0x20,
-				0x9d, 0x21, 0x56, 0x43, 0x0f, 0x31, 0xc8, 0x8d, 0x37, 0xa9, 0x53, 0x18, 0xfa, 0x7d, 0xc7, 0xf5,
-				0x4c, 0x20, 0x43, 0x82, 0xc6, 0xa8, 0xe8, 0x50, 0x12, 0x17, 0x5e, 0xdd, 0x92, 0x55, 0xa1, 0xe9,
-				0x96, 0x57, 0xc3, 0x11, 0xd9, 0xc7, 0xc1, 0xd6, 0x83, 0x65, 0xa4, 0xea, 0xe0, 0xc8, 0xe6, 0xb3,
-				0x07, 0x27, 0x5d, 0x99, 0xb4, 0x8f, 0x84, 0xf9, 0x9b, 0x2d, 0x19, 0xc0, 0x33, 0x7f, 0xa3, 0xba,
-				0x6f, 0x2f, 0x41, 0x02, 0x81, 0x80, 0x65, 0xbf, 0x15, 0xf0, 0x83, 0xb3, 0xea, 0x05, 0xd6, 0xe6,
-				0x0d, 0x46, 0xc4, 0x26, 0xf0, 0x19, 0x64, 0x6d, 0x60, 0x4e, 0x5f, 0xf9, 0x02, 0x49, 0x44, 0x2b,
-				0x7a, 0x93, 0x34, 0x23, 0x70, 0x1b, 0x15, 0x6e, 0xc6, 0xd3, 0x2e, 0xde, 0xe2, 0xea, 0x6f, 0xf3,
-				0x3d, 0x2f, 0xc2, 0xc2, 0xad, 0xea, 0x23, 0x90, 0x2f, 0xcb, 0x41, 0xd9, 0x3e, 0x4e, 0x67, 0x84,
-				0x79, 0x6f, 0x38, 0xea, 0xea, 0x14, 0x3d, 0x70, 0x17, 0x09, 0x2a, 0x78, 0x35, 0xd6, 0xb5, 0x71,
-				0x64, 0x0d, 0x25, 0xa5, 0xae, 0xf4, 0xdc, 0x37, 0xc5, 0xa8, 0x90, 0xea, 0x3e, 0xd2, 0x09, 0x4b,
-				0x57, 0x7a, 0x4e, 0xd5, 0x48, 0xbe, 0x0d, 0xfe, 0x9b, 0x45, 0x8d, 0x29, 0x55, 0x94, 0x81, 0xc5,
-				0x88, 0xfa, 0xf3, 0x42, 0xd0, 0x26, 0x67, 0xa8, 0xc5, 0xf1, 0x49, 0x93, 0x9f, 0x7d, 0x19, 0xd7,
-				0xe9, 0x23, 0x57, 0xb4, 0x45, 0x4c
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xa5, 0xb9, 0xfb, 0xc3, 0xbe, 0xf4, 0x0b, 0x60, 0x08, 0x16, 0xec, 0x98,
-				0xed, 0x42, 0x5e, 0xcd, 0xe6, 0xd8, 0xe9, 0x5f, 0xf8, 0xa3, 0x4e, 0xe8, 0x5d, 0x39, 0x65, 0x42,
-				0xa4, 0x61, 0xbc, 0xa0, 0x54, 0x9d, 0xda, 0x0c, 0xd6, 0xbd, 0x68, 0x6c, 0xef, 0x3c, 0xcf, 0xd0,
-				0xac, 0xd5, 0xa4, 0x17, 0xb9, 0x49, 0xde, 0x6f, 0x36, 0xb1, 0x04, 0xb5, 0xb7, 0x4d, 0x3c, 0x9d,
-				0xca, 0xd5, 0xe0, 0xd3, 0x95, 0xe7, 0xe5, 0xf9, 0xb4, 0xb0, 0xa5, 0xa0, 0x1a, 0xd6, 0x5c, 0x6d,
-				0xf4, 0x3a, 0x69, 0xe6, 0x7e, 0x44, 0x00, 0x1e, 0x27, 0x8f, 0x56, 0xc0, 0x69, 0xcd, 0xac, 0x94,
-				0x3f, 0x95, 0xa5, 0xd6, 0x15, 0x6e, 0x66, 0x64, 0x35, 0xc6, 0x75, 0xc6, 0xe8, 0x19, 0x96, 0x18,
-				0xd3, 0xb9, 0xba, 0x0f, 0xfd, 0x01, 0x21, 0x95, 0x27, 0xa6, 0x6b, 0xd7, 0x67, 0x3c, 0x36, 0x46,
-				0xe0, 0x08, 0x59, 0xa7, 0x97, 0x46, 0x07, 0xfc, 0x38, 0x57, 0xd0, 0xec, 0x53, 0x80, 0xa8, 0x9b,
-				0x83, 0xbf, 0x4f, 0x10, 0x35, 0x05, 0xe8, 0x63, 0x39, 0x1a, 0x29, 0x19, 0x98, 0xa4, 0x32, 0xa5,
-				0xf6, 0x23, 0xb0, 0x75, 0xa8, 0x11, 0x9e, 0x26, 0xda, 0x44, 0xe3, 0x36, 0x57, 0x80, 0x8b, 0x11,
-				0x7c, 0xf9, 0x65, 0xfe, 0x7f, 0x7f, 0x10, 0xbb, 0x16, 0xff, 0xe3, 0x66, 0x78, 0x78, 0x1c, 0xf2,
-				0xee, 0x22, 0x43, 0x2d, 0x76, 0x56, 0x43, 0xdc, 0x07, 0x1d, 0x08, 0x24, 0x9d, 0x2d, 0x52, 0x1f,
-				0xdc, 0xfc, 0x08, 0xb8, 0xd0, 0xda, 0xfa, 0x5f, 0x76, 0x48, 0x09, 0xf8, 0x88, 0xa1, 0x1e, 0x3f,
-				0x5b, 0xcf, 0x94, 0x44, 0x0b, 0x70, 0x30, 0x45, 0x84, 0x3c, 0x8b, 0xdd, 0x4d, 0x2f, 0x44, 0x1f,
-				0xe4, 0x20, 0xaf, 0x3a, 0x91, 0xb9, 0xd1, 0x4e, 0xb2, 0x96, 0xc3, 0x64, 0xfb, 0x2e, 0x28, 0x3e,
-				0x0e, 0x36, 0x89, 0xcf
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0xb9, 0xfb, 0xc3,
-				0xbe, 0xf4, 0x0b, 0x60, 0x08, 0x16, 0xec, 0x98, 0xed, 0x42, 0x5e, 0xcd, 0xe6, 0xd8, 0xe9, 0x5f,
-				0xf8, 0xa3, 0x4e, 0xe8, 0x5d, 0x39, 0x65, 0x42, 0xa4, 0x61, 0xbc, 0xa0, 0x54, 0x9d, 0xda, 0x0c,
-				0xd6, 0xbd, 0x68, 0x6c, 0xef, 0x3c, 0xcf, 0xd0, 0xac, 0xd5, 0xa4, 0x17, 0xb9, 0x49, 0xde, 0x6f,
-				0x36, 0xb1, 0x04, 0xb5, 0xb7, 0x4d, 0x3c, 0x9d, 0xca, 0xd5, 0xe0, 0xd3, 0x95, 0xe7, 0xe5, 0xf9,
-				0xb4, 0xb0, 0xa5, 0xa0, 0x1a, 0xd6, 0x5c, 0x6d, 0xf4, 0x3a, 0x69, 0xe6, 0x7e, 0x44, 0x00, 0x1e,
-				0x27, 0x8f, 0x56, 0xc0, 0x69, 0xcd, 0xac, 0x94, 0x3f, 0x95, 0xa5, 0xd6, 0x15, 0x6e, 0x66, 0x64,
-				0x35, 0xc6, 0x75, 0xc6, 0xe8, 0x19, 0x96, 0x18, 0xd3, 0xb9, 0xba, 0x0f, 0xfd, 0x01, 0x21, 0x95,
-				0x27, 0xa6, 0x6b, 0xd7, 0x67, 0x3c, 0x36, 0x46, 0xe0, 0x08, 0x59, 0xa7, 0x97, 0x46, 0x07, 0xfc,
-				0x38, 0x57, 0xd0, 0xec, 0x53, 0x80, 0xa8, 0x9b, 0x83, 0xbf, 0x4f, 0x10, 0x35, 0x05, 0xe8, 0x63,
-				0x39, 0x1a, 0x29, 0x19, 0x98, 0xa4, 0x32, 0xa5, 0xf6, 0x23, 0xb0, 0x75, 0xa8, 0x11, 0x9e, 0x26,
-				0xda, 0x44, 0xe3, 0x36, 0x57, 0x80, 0x8b, 0x11, 0x7c, 0xf9, 0x65, 0xfe, 0x7f, 0x7f, 0x10, 0xbb,
-				0x16, 0xff, 0xe3, 0x66, 0x78, 0x78, 0x1c, 0xf2, 0xee, 0x22, 0x43, 0x2d, 0x76, 0x56, 0x43, 0xdc,
-				0x07, 0x1d, 0x08, 0x24, 0x9d, 0x2d, 0x52, 0x1f, 0xdc, 0xfc, 0x08, 0xb8, 0xd0, 0xda, 0xfa, 0x5f,
-				0x76, 0x48, 0x09, 0xf8, 0x88, 0xa1, 0x1e, 0x3f, 0x5b, 0xcf, 0x94, 0x44, 0x0b, 0x70, 0x30, 0x45,
-				0x84, 0x3c, 0x8b, 0xdd, 0x4d, 0x2f, 0x44, 0x1f, 0xe4, 0x20, 0xaf, 0x3a, 0x91, 0xb9, 0xd1, 0x4e,
-				0xb2, 0x96, 0xc3, 0x64, 0xfb, 0x2e, 0x28, 0x3e, 0x0e, 0x36, 0x89, 0xcf, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x3e, 0x8a, 0x2a, 0x57, 0xaa, 0xaa, 0x56, 0xd6, 0x95, 0x06, 0xed,
-				0x9f, 0x22, 0x3d, 0xdf, 0x1f, 0xed, 0x83, 0x22, 0xc2, 0x9c, 0x46, 0x28, 0x83, 0x68, 0x96, 0xbd,
-				0xbf, 0x41, 0xe0, 0x3e, 0x39, 0xf4, 0xe4, 0xa2, 0xc2, 0x20, 0x91, 0x56, 0xa4, 0x71, 0x3d, 0xae,
-				0x20, 0xcd, 0xf0, 0x4b, 0x5d, 0xc6, 0x86, 0xf9, 0x41, 0x57, 0xce, 0xc2, 0x7b, 0xbe, 0xa2, 0x0f,
-				0x83, 0x6e, 0x65, 0x7a, 0xd3, 0xed, 0xe8, 0x96, 0xb1, 0x3e, 0x3e, 0x41, 0x2a, 0x63, 0xa6, 0x4c,
-				0x38, 0x14, 0x27, 0xad, 0x0a, 0x15, 0xd1, 0x1c, 0x88, 0x44, 0x9e, 0x83, 0x7a, 0xd6, 0x12, 0x8f,
-				0x13, 0x5c, 0xd1, 0x60, 0xc5, 0x22, 0xce, 0x48, 0x26, 0x7d, 0xe2, 0x98, 0x54, 0x89, 0x07, 0x0a,
-				0xcc, 0xf0, 0xad, 0x50, 0x69, 0x33, 0x2d, 0x67, 0x9a, 0x6d, 0x5d, 0x90, 0xa9, 0xb7, 0x64, 0x12,
-				0x09, 0x7a, 0x06, 0xbc, 0xa9, 0xf5, 0xe6, 0x83, 0xd5, 0xde, 0xee, 0x7c, 0xda, 0xaf, 0xa5, 0xde,
-				0x93, 0xd7, 0x9a, 0xd5, 0x9f, 0x37, 0xd8, 0xdc, 0x39, 0x63, 0xa1, 0x73, 0xbd, 0x91, 0xeb, 0xc6,
-				0xff, 0x87, 0xc8, 0x0c, 0xc3, 0xfc, 0x69, 0x4e, 0x80, 0x5b, 0x50, 0x88, 0xd5, 0x1b, 0xc9, 0x00,
-				0x8f, 0xeb, 0x9d, 0x66, 0xf4, 0xf4, 0x4d, 0x3c, 0x41, 0xe5, 0xbf, 0xdc, 0x9c, 0x0f, 0x35, 0x83,
-				0x88, 0x2d, 0xd7, 0x81, 0x70, 0x22, 0xfa, 0x6d, 0x77, 0x53, 0x17, 0x13, 0x38, 0x7a, 0xb0, 0x0a,
-				0x14, 0x15, 0xbf, 0xa2, 0x27, 0xc1, 0xfd, 0x07, 0x24, 0x63, 0x5a, 0xbb, 0x0d, 0x26, 0xad, 0x4d,
-				0x52, 0x62, 0x84, 0xe2, 0xc2, 0x03, 0xea, 0x61, 0xd0, 0x73, 0x3d, 0x5d, 0x5b, 0x1a, 0x86, 0xc7,
-				0x92, 0x29, 0x4d, 0x22, 0xf6, 0xf2, 0x59, 0x17, 0xed, 0xf0, 0x83, 0xdb, 0x5c, 0xf2, 0xf4, 0xe6,
-				0xe1, 0x58, 0xd2, 0xa5, 0xfd, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x1f, 0x3d, 0xb3, 0xec, 0x8b, 0x8e,
-				0xaa, 0x1f, 0xfb, 0x03, 0xd3, 0x95, 0xb4, 0xbe, 0x61, 0xed, 0xc5, 0x30, 0x2f, 0xc4, 0x20, 0xd8,
-				0xc6, 0x14, 0x17, 0x55, 0xac, 0x06, 0x0b, 0x02, 0x8c, 0x18, 0xd0, 0xe1, 0x0c, 0xce, 0x14, 0xe4,
-				0xf1, 0xb0, 0x2a, 0x3f, 0x6e, 0x3b, 0x57, 0x60, 0x7b, 0x22, 0xbd, 0xbe, 0xa7, 0x41, 0x33, 0x84,
-				0x17, 0xb8, 0xd8, 0x92, 0x9e, 0xe2, 0x1e, 0xf2, 0xa5, 0x03, 0x68, 0x86, 0xe3, 0x42, 0x86, 0x0f,
-				0xd8, 0xcf, 0x19, 0x51, 0x35, 0x77, 0xa0, 0xcd, 0x20, 0x4c, 0x7b, 0xaf, 0x4b, 0xb6, 0x5a, 0x36,
-				0xdc, 0xb0, 0x4f, 0xcf, 0x04, 0xf2, 0xba, 0x83, 0x27, 0xdc, 0x7f, 0x7a, 0xd5, 0x24, 0x1c, 0x4e,
-				0xcc, 0xf3, 0xd8, 0x44, 0xf5, 0xb3, 0x88, 0x42, 0xa6, 0xc7, 0xaa, 0x95, 0xac, 0x63, 0xeb, 0x88,
-				0xfd, 0x5e, 0xf7, 0xb3, 0x89, 0xad, 0xe3, 0x7f, 0xe3, 0x02, 0x81, 0x81, 0x00, 0xcc, 0xd5, 0xef,
-				0x49, 0xfd, 0xac, 0x83, 0x95, 0x42, 0x50, 0x34, 0x13, 0x42, 0x34, 0x6e, 0xec, 0xd0, 0xb4, 0x88,
-				0x6a, 0xdb, 0x9f, 0x77, 0x89, 0x47, 0xb3, 0xd4, 0xbd, 0x20, 0x84, 0xb2, 0xd1, 0x84, 0x64, 0x37,
-				0xdd, 0x6d, 0x89, 0x43, 0xf0, 0xc0, 0x42, 0xf6, 0x07, 0x76, 0xd8, 0x4d, 0x65, 0xf9, 0x01, 0x0e,
-				0xad, 0xfc, 0x16, 0xfd, 0x7c, 0x14, 0x03, 0xfa, 0xfe, 0x5f, 0x20, 0x32, 0x56, 0x50, 0x5c, 0x3a,
-				0x26, 0xaa, 0x18, 0xd1, 0x24, 0x6a, 0x20, 0x85, 0x43, 0xaf, 0xd9, 0xfb, 0xe0, 0x05, 0x80, 0x09,
-				0xb0, 0x8d, 0xf2, 0x77, 0xd6, 0xaa, 0x6e, 0x6d, 0x66, 0x5f, 0xa0, 0xfd, 0xb9, 0x2e, 0xd6, 0x7b,
-				0x4e, 0xfb, 0x67, 0xe0, 0xc4, 0x99, 0xaf, 0x15, 0x8e, 0x14, 0x77, 0xdb, 0x49, 0x92, 0xc6, 0x02,
-				0xd4, 0xe4, 0xe0, 0x77, 0x29, 0xb6, 0x49, 0xf2, 0xe5, 0xf8, 0xc8, 0x1a, 0x25, 0x02, 0x81, 0x80,
-				0x31, 0x13, 0x0d, 0xe3, 0x9b, 0xa0, 0x55, 0x65, 0x29, 0xbe, 0xa7, 0xe1, 0x72, 0x0f, 0x29, 0x2c,
-				0xba, 0xd1, 0x85, 0xe1, 0x4b, 0x6f, 0x1c, 0xed, 0x91, 0xc5, 0x15, 0x9f, 0x74, 0xaf, 0x17, 0x23,
-				0x6a, 0x9d, 0xd3, 0x34, 0xdd, 0x7f, 0x45, 0xdf, 0x9e, 0x05, 0xe4, 0x91, 0x91, 0xad, 0xda, 0x46,
-				0x52, 0xac, 0xf2, 0x87, 0x5e, 0x83, 0x7e, 0x40, 0xc0, 0xa3, 0x4f, 0xda, 0x25, 0x69, 0x7f, 0xc4,
-				0x69, 0x52, 0x52, 0xe3, 0x75, 0xd7, 0x9d, 0xd9, 0x98, 0xf8, 0x3e, 0xad, 0x94, 0x72, 0x9d, 0x27,
-				0x91, 0xf7, 0x9c, 0x49, 0x2c, 0x23, 0xa3, 0xec, 0x16, 0x3a, 0x52, 0xaa, 0xb1, 0x78, 0x4f, 0xab,
-				0x1a, 0x2b, 0x7a, 0x47, 0x16, 0x0f, 0x3e, 0xfc, 0x80, 0xaa, 0x35, 0x6c, 0xa1, 0xe5, 0x1f, 0x25,
-				0xb5, 0x19, 0x4d, 0xed, 0x52, 0x9f, 0x74, 0x0d, 0xd4, 0x7a, 0x8c, 0x27, 0x8a, 0xf3, 0xe4, 0x51,
-				0x02, 0x81, 0x80, 0x53, 0xf0, 0x37, 0x26, 0xb2, 0xf5, 0x46, 0xd6, 0x9b, 0x5e, 0x12, 0x78, 0xf1,
-				0xe0, 0x5a, 0xb4, 0x60, 0xb2, 0x1a, 0x54, 0xef, 0xba, 0xe1, 0x59, 0x38, 0x30, 0xd1, 0x34, 0xcf,
-				0x66, 0x91, 0x80, 0x9a, 0x28, 0x17, 0x5c, 0x7d, 0xce, 0x8a, 0x30, 0xd6, 0x18, 0x9a, 0x89, 0x64,
-				0x82, 0x2e, 0xf5, 0x62, 0x9c, 0xb4, 0x4f, 0x47, 0xc6, 0x84, 0x09, 0x9c, 0x8a, 0x25, 0x08, 0xa8,
-				0x22, 0xa1, 0x7e, 0x0d, 0x60, 0x3d, 0xd4, 0x2a, 0x50, 0x11, 0x24, 0x42, 0xf9, 0x20, 0xa3, 0x24,
-				0x24, 0xc7, 0xba, 0x7d, 0x86, 0x82, 0x71, 0xff, 0x39, 0x25, 0x32, 0xaa, 0x94, 0xa5, 0xf0, 0x15,
-				0xaf, 0xfb, 0x49, 0x2f, 0x90, 0x64, 0xe7, 0x70, 0xce, 0x98, 0xa4, 0xf7, 0xf5, 0x6f, 0x77, 0xd1,
-				0x9b, 0x6c, 0x19, 0x32, 0x34, 0x42, 0x64, 0xcb, 0x85, 0xd0, 0x4f, 0x1f, 0x8c, 0x1e, 0x25, 0x6f,
-				0x55, 0x50, 0xa1, 0x02, 0x81, 0x80, 0x35, 0x46, 0x32, 0xc6, 0x88, 0xf4, 0x98, 0xea, 0x25, 0xbe,
-				0xd8, 0xae, 0x45, 0x82, 0xf5, 0x8f, 0x68, 0x37, 0x76, 0x8f, 0x3e, 0x79, 0x18, 0x8d, 0x89, 0x82,
-				0xfd, 0x3c, 0x55, 0x6c, 0x50, 0xe9, 0xd4, 0x62, 0xc0, 0x8a, 0xf5, 0x0b, 0x7f, 0x05, 0x30, 0x85,
-				0x16, 0x4f, 0x44, 0x69, 0x10, 0xef, 0x15, 0x6d, 0xfc, 0x1f, 0xd3, 0xbd, 0x87, 0x27, 0x86, 0xb5,
-				0x56, 0xbd, 0x51, 0x13, 0xa5, 0x3c, 0xe5, 0xc4, 0x3a, 0x57, 0x4e, 0x4a, 0xfe, 0xfa, 0x7a, 0x1a,
-				0xad, 0x27, 0x5c, 0x64, 0x1d, 0x7f, 0xd0, 0xf4, 0x10, 0xc5, 0x8d, 0xb2, 0x3e, 0xe2, 0x35, 0xe7,
-				0x8e, 0xdb, 0x4e, 0x53, 0x9c, 0x4f, 0x4f, 0x19, 0x97, 0x50, 0x9c, 0x90, 0x60, 0xd7, 0x03, 0xfc,
-				0xa1, 0xea, 0x72, 0x22, 0x43, 0x15, 0x2e, 0x6c, 0x91, 0xfa, 0xaf, 0xe0, 0x32, 0x99, 0xb6, 0xa3,
-				0x32, 0x51, 0xfa, 0xd4, 0x1f, 0x3c
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xb7, 0xd1, 0x77, 0xd7, 0x84, 0xf2, 0x21, 0x2b, 0x40, 0x0b, 0x7a, 0x4c,
-				0x91, 0x95, 0x36, 0xfa, 0x41, 0xc8, 0xc8, 0xe4, 0xba, 0xb2, 0xec, 0x68, 0xdc, 0x12, 0x2c, 0x0b,
-				0x61, 0xc4, 0x9d, 0x4d, 0xa7, 0x47, 0x05, 0x92, 0x77, 0x44, 0xc9, 0x29, 0xa3, 0x30, 0x95, 0x02,
-				0x2f, 0xc2, 0xa7, 0xab, 0x63, 0xa2, 0xfc, 0x37, 0x13, 0x80, 0xb9, 0xc9, 0xb7, 0x79, 0xf6, 0xfd,
-				0x6f, 0xfd, 0x43, 0x4a, 0xd4, 0x4e, 0x58, 0x8f, 0x4d, 0x8b, 0xcc, 0xff, 0x41, 0x7a, 0x93, 0x3d,
-				0x66, 0x2b, 0x95, 0xf5, 0x59, 0xef, 0x29, 0x22, 0x57, 0x72, 0x2e, 0x7d, 0xa7, 0x67, 0x03, 0x9e,
-				0x38, 0x05, 0xa8, 0x59, 0x9c, 0x03, 0x9c, 0x33, 0x15, 0x16, 0x12, 0xd4, 0x8c, 0x8e, 0x9f, 0x3f,
-				0xa3, 0x24, 0x62, 0x2c, 0x19, 0xea, 0xd8, 0x45, 0xae, 0x64, 0x64, 0x1b, 0x14, 0x92, 0xd8, 0x68,
-				0xb3, 0xf7, 0xe5, 0xb8, 0x01, 0x12, 0x5e, 0x8f, 0xf9, 0x18, 0x6f, 0x29, 0xe2, 0xff, 0xb8, 0x68,
-				0x2d, 0x68, 0x3c, 0xe6, 0x2e, 0xee, 0xcc, 0x11, 0x90, 0x62, 0x8c, 0x76, 0x08, 0x75, 0xdb, 0x77,
-				0xe1, 0x4d, 0xdf, 0xbf, 0x6e, 0xa4, 0x11, 0x9f, 0xa4, 0x1b, 0xf4, 0xfa, 0xff, 0xbb, 0x5b, 0xed,
-				0x4f, 0xb1, 0xdc, 0xef, 0x11, 0x1f, 0x99, 0xc3, 0xa1, 0xa7, 0x6e, 0x06, 0xe6, 0x1e, 0xd1, 0x4e,
-				0x4e, 0x9a, 0x70, 0x9e, 0xbb, 0xc5, 0xa3, 0xb5, 0x77, 0xdc, 0xa8, 0xc8, 0x9f, 0x5a, 0x61, 0x5f,
-				0x01, 0x18, 0x39, 0xe0, 0x7f, 0x8a, 0x52, 0x0f, 0x4e, 0x94, 0xb3, 0x03, 0x9a, 0x41, 0x5e, 0x52,
-				0x9b, 0x30, 0xc4, 0x64, 0x3f, 0xb4, 0x71, 0xec, 0x2a, 0x6c, 0x63, 0x64, 0x8f, 0x16, 0xe3, 0xdf,
-				0xfc, 0x01, 0x31, 0x8a, 0xfc, 0x08, 0x8d, 0x7c, 0xcd, 0xe9, 0x64, 0x87, 0x19, 0xe1, 0x0e, 0xfa,
-				0x75, 0xee, 0xe3, 0x87
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb7, 0xd1, 0x77, 0xd7,
-				0x84, 0xf2, 0x21, 0x2b, 0x40, 0x0b, 0x7a, 0x4c, 0x91, 0x95, 0x36, 0xfa, 0x41, 0xc8, 0xc8, 0xe4,
-				0xba, 0xb2, 0xec, 0x68, 0xdc, 0x12, 0x2c, 0x0b, 0x61, 0xc4, 0x9d, 0x4d, 0xa7, 0x47, 0x05, 0x92,
-				0x77, 0x44, 0xc9, 0x29, 0xa3, 0x30, 0x95, 0x02, 0x2f, 0xc2, 0xa7, 0xab, 0x63, 0xa2, 0xfc, 0x37,
-				0x13, 0x80, 0xb9, 0xc9, 0xb7, 0x79, 0xf6, 0xfd, 0x6f, 0xfd, 0x43, 0x4a, 0xd4, 0x4e, 0x58, 0x8f,
-				0x4d, 0x8b, 0xcc, 0xff, 0x41, 0x7a, 0x93, 0x3d, 0x66, 0x2b, 0x95, 0xf5, 0x59, 0xef, 0x29, 0x22,
-				0x57, 0x72, 0x2e, 0x7d, 0xa7, 0x67, 0x03, 0x9e, 0x38, 0x05, 0xa8, 0x59, 0x9c, 0x03, 0x9c, 0x33,
-				0x15, 0x16, 0x12, 0xd4, 0x8c, 0x8e, 0x9f, 0x3f, 0xa3, 0x24, 0x62, 0x2c, 0x19, 0xea, 0xd8, 0x45,
-				0xae, 0x64, 0x64, 0x1b, 0x14, 0x92, 0xd8, 0x68, 0xb3, 0xf7, 0xe5, 0xb8, 0x01, 0x12, 0x5e, 0x8f,
-				0xf9, 0x18, 0x6f, 0x29, 0xe2, 0xff, 0xb8, 0x68, 0x2d, 0x68, 0x3c, 0xe6, 0x2e, 0xee, 0xcc, 0x11,
-				0x90, 0x62, 0x8c, 0x76, 0x08, 0x75, 0xdb, 0x77, 0xe1, 0x4d, 0xdf, 0xbf, 0x6e, 0xa4, 0x11, 0x9f,
-				0xa4, 0x1b, 0xf4, 0xfa, 0xff, 0xbb, 0x5b, 0xed, 0x4f, 0xb1, 0xdc, 0xef, 0x11, 0x1f, 0x99, 0xc3,
-				0xa1, 0xa7, 0x6e, 0x06, 0xe6, 0x1e, 0xd1, 0x4e, 0x4e, 0x9a, 0x70, 0x9e, 0xbb, 0xc5, 0xa3, 0xb5,
-				0x77, 0xdc, 0xa8, 0xc8, 0x9f, 0x5a, 0x61, 0x5f, 0x01, 0x18, 0x39, 0xe0, 0x7f, 0x8a, 0x52, 0x0f,
-				0x4e, 0x94, 0xb3, 0x03, 0x9a, 0x41, 0x5e, 0x52, 0x9b, 0x30, 0xc4, 0x64, 0x3f, 0xb4, 0x71, 0xec,
-				0x2a, 0x6c, 0x63, 0x64, 0x8f, 0x16, 0xe3, 0xdf, 0xfc, 0x01, 0x31, 0x8a, 0xfc, 0x08, 0x8d, 0x7c,
-				0xcd, 0xe9, 0x64, 0x87, 0x19, 0xe1, 0x0e, 0xfa, 0x75, 0xee, 0xe3, 0x87, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x12, 0x8c, 0x53, 0x70, 0x6e, 0xdc, 0xd3, 0xd5, 0xfe, 0x67, 0x6a,
-				0x16, 0xd1, 0xd5, 0xe1, 0xaf, 0x4c, 0xf6, 0x0a, 0xb7, 0x71, 0xd3, 0x5e, 0x21, 0x92, 0x9b, 0x4e,
-				0xd0, 0x73, 0x34, 0x18, 0xbf, 0x5e, 0x32, 0xbf, 0x70, 0x31, 0x12, 0xc2, 0xcd, 0xad, 0xc6, 0xd8,
-				0x32, 0x59, 0x49, 0x66, 0x0b, 0xd8, 0x48, 0xf8, 0xf4, 0x41, 0xc6, 0x8a, 0x78, 0xbd, 0x47, 0xd4,
-				0x51, 0x6c, 0x7c, 0x7c, 0xce, 0xcf, 0x2f, 0x7c, 0xa6, 0x31, 0x27, 0xfb, 0x2e, 0x82, 0x97, 0xf0,
-				0xc5, 0x90, 0x4a, 0xb3, 0x9e, 0x07, 0x4e, 0x27, 0xb3, 0x6c, 0x69, 0x7c, 0x21, 0x77, 0xc3, 0xe0,
-				0x4c, 0x95, 0xd0, 0x94, 0x55, 0x3e, 0x75, 0xea, 0xcc, 0x08, 0xc3, 0xaa, 0x70, 0xc2, 0x22, 0x1e,
-				0x15, 0x98, 0xcb, 0xb2, 0x10, 0x4b, 0x29, 0x34, 0x5b, 0x8b, 0xa6, 0x5b, 0xa7, 0x93, 0xe2, 0xe1,
-				0x6d, 0x67, 0x43, 0x8b, 0x6d, 0x62, 0x8c, 0xaf, 0x58, 0x30, 0x90, 0x8f, 0x52, 0x3c, 0xf8, 0x9b,
-				0xd7, 0x19, 0x4a, 0x39, 0xa3, 0x23, 0x24, 0x3c, 0xab, 0xe2, 0x0c, 0x0f, 0x06, 0x86, 0xf9, 0x26,
-				0x67, 0xd3, 0xbe, 0x05, 0x46, 0xe2, 0x20, 0xd2, 0x13, 0x9e, 0xf9, 0xc5, 0x91, 0x2a, 0x29, 0xf8,
-				0x51, 0x99, 0xdd, 0x93, 0x72, 0x48, 0xa4, 0x1a, 0xfc, 0x4d, 0x44, 0x0f, 0xad, 0x96, 0xba, 0x73,
-				0x8a, 0x6f, 0xc3, 0xa1, 0xde, 0xfc, 0xb4, 0x9c, 0xfe, 0xb8, 0xa4, 0x94, 0x53, 0xf5, 0x7f, 0x15,
-				0xbd, 0x25, 0xa8, 0xec, 0x30, 0x31, 0x31, 0x93, 0xe5, 0x6b, 0xc6, 0xca, 0x1b, 0x6d, 0x8c, 0x02,
-				0xdf, 0xc5, 0x07, 0xab, 0x58, 0xb0, 0x25, 0x5e, 0x3b, 0x11, 0xb2, 0xd1, 0x51, 0xca, 0x84, 0x2e,
-				0x68, 0x77, 0x2e, 0x27, 0x77, 0xa7, 0x3e, 0xf6, 0x2e, 0x95, 0xdc, 0x83, 0xe1, 0xd9, 0x6d, 0x4a,
-				0x5e, 0xc9, 0xc1, 0x2a, 0xa9, 0x02, 0x81, 0x81, 0x00, 0xfa, 0x31, 0xef, 0x94, 0xe0, 0xc0, 0x17,
-				0xb6, 0xc5, 0x3e, 0xc2, 0x75, 0x98, 0x80, 0x61, 0x04, 0x7c, 0x4f, 0xa6, 0xda, 0x14, 0xab, 0xab,
-				0x8f, 0xe0, 0x31, 0xd7, 0xb6, 0x89, 0x46, 0x20, 0x87, 0x1d, 0xde, 0x54, 0x31, 0x3c, 0x6c, 0xaa,
-				0xad, 0x0b, 0x54, 0x17, 0x95, 0x07, 0x9d, 0xa1, 0x24, 0xe7, 0xca, 0xa3, 0x71, 0xa9, 0xc5, 0x63,
-				0x6d, 0xc7, 0x0a, 0x12, 0xfc, 0xeb, 0xc7, 0x7f, 0x77, 0xdf, 0xbe, 0xc4, 0x14, 0x70, 0xb5, 0x6d,
-				0xd8, 0x4f, 0x15, 0x9c, 0x1d, 0x06, 0x77, 0x80, 0x1a, 0xb7, 0x41, 0xde, 0x41, 0xa4, 0x12, 0xe3,
-				0xec, 0x51, 0x12, 0xfd, 0x31, 0x1a, 0x19, 0x63, 0xcf, 0x5a, 0x34, 0xc2, 0xfb, 0xdc, 0x13, 0xa5,
-				0xf5, 0x82, 0xa7, 0xd4, 0x84, 0x3e, 0x2c, 0xce, 0x09, 0x8d, 0x9b, 0x47, 0x99, 0x84, 0x03, 0x9c,
-				0x35, 0xa0, 0x2f, 0x4f, 0x72, 0x2d, 0x1a, 0xfd, 0xcb, 0x02, 0x81, 0x81, 0x00, 0xbc, 0x15, 0x47,
-				0x6c, 0x22, 0xf6, 0x36, 0x48, 0x18, 0xa6, 0x55, 0x9d, 0x86, 0xf4, 0xfc, 0x27, 0x31, 0x94, 0xd1,
-				0x0d, 0x91, 0xc8, 0x41, 0xd9, 0x58, 0x02, 0x76, 0x12, 0x52, 0xa7, 0xbd, 0xca, 0x97, 0x51, 0x04,
-				0x37, 0xbd, 0xff, 0x17, 0xb5, 0xfb, 0xb6, 0xf4, 0x9d, 0x91, 0x78, 0x2c, 0xc6, 0x67, 0x2d, 0x91,
-				0x75, 0xeb, 0xf2, 0x1b, 0xe0, 0x87, 0x54, 0x73, 0xcd, 0x68, 0x02, 0x39, 0x17, 0xbd, 0x58, 0x10,
-				0x3c, 0xe5, 0x1d, 0x34, 0x7d, 0xe3, 0x86, 0xa6, 0x0c, 0x13, 0xb5, 0xd4, 0x53, 0x06, 0xbb, 0xd9,
-				0x26, 0x85, 0x9b, 0x53, 0x0c, 0xec, 0xae, 0x9d, 0x5f, 0xe9, 0x3f, 0x50, 0x27, 0x70, 0x8c, 0x7b,
-				0x79, 0x59, 0x12, 0xfb, 0x1d, 0xd6, 0x82, 0x75, 0x1b, 0x2f, 0xbb, 0xe5, 0xda, 0xe7, 0xaf, 0xc3,
-				0x54, 0xc0, 0x32, 0x49, 0x5e, 0x64, 0xa1, 0x39, 0xe5, 0x93, 0x1d, 0xf9, 0xb5, 0x02, 0x81, 0x80,
-				0x23, 0x4b, 0x3a, 0x0d, 0xd9, 0x6a, 0x9f, 0xad, 0xc3, 0xc3, 0x67, 0xb1, 0x29, 0x13, 0x2b, 0x1c,
-				0x73, 0xe0, 0xd4, 0x9b, 0xbd, 0x00, 0xbe, 0x91, 0xec, 0x41, 0x7b, 0xb9, 0x9f, 0x41, 0xca, 0x42,
-				0xe5, 0x3e, 0xc0, 0xc7, 0xb5, 0x4b, 0x6b, 0x04, 0x40, 0x2d, 0xdb, 0xa9, 0xc5, 0x4a, 0x42, 0x3a,
-				0x2f, 0x8c, 0x91, 0x63, 0xee, 0x5c, 0x0e, 0xfb, 0xa4, 0x71, 0x52, 0x5e, 0x65, 0x70, 0x5e, 0x15,
-				0xed, 0xf5, 0x3e, 0x39, 0xd7, 0xf0, 0x70, 0x0f, 0x6c, 0x90, 0x92, 0xd6, 0x31, 0x5c, 0x58, 0x30,
-				0xec, 0x9b, 0x19, 0x1c, 0x4f, 0x65, 0xee, 0xcb, 0x1e, 0x60, 0xbc, 0x60, 0xd9, 0xda, 0xad, 0x0e,
-				0xca, 0x1d, 0xd9, 0x47, 0xa8, 0x33, 0x09, 0x5d, 0x49, 0xd2, 0x1d, 0x13, 0x8e, 0xa5, 0xc9, 0x66,
-				0xe5, 0x97, 0xfb, 0x10, 0xb7, 0xe3, 0xbe, 0x7c, 0x7e, 0x1d, 0x4e, 0x6a, 0xbf, 0xdc, 0x27, 0xe3,
-				0x02, 0x81, 0x80, 0x16, 0x5b, 0x39, 0x28, 0x23, 0x67, 0xbc, 0xc0, 0x09, 0x1e, 0x0c, 0x63, 0x33,
-				0x1d, 0x7f, 0xb3, 0x70, 0xf3, 0x4d, 0x7e, 0x1d, 0x6b, 0xfe, 0x57, 0xc5, 0x5c, 0x55, 0x88, 0x8c,
-				0x06, 0xa0, 0x4a, 0xaa, 0x7d, 0xd8, 0xd0, 0x7f, 0x67, 0x08, 0xfc, 0x7a, 0xb5, 0x1e, 0x92, 0x74,
-				0x2e, 0x22, 0xb4, 0x5a, 0xa3, 0x51, 0xfd, 0x00, 0x54, 0xc0, 0xf7, 0x89, 0x5e, 0x82, 0x7d, 0x51,
-				0xf5, 0xa1, 0xaf, 0xae, 0xb3, 0xff, 0x0a, 0x1d, 0xf9, 0xc0, 0xb9, 0x8e, 0x07, 0xfd, 0x48, 0xc6,
-				0x37, 0x00, 0xcb, 0xf5, 0xaa, 0xf2, 0x7e, 0xdf, 0xb6, 0xbc, 0xc2, 0x76, 0x87, 0xb2, 0xf1, 0x29,
-				0x9a, 0x7a, 0xfe, 0x95, 0x24, 0x3d, 0xb1, 0x08, 0xe3, 0x76, 0xb1, 0xef, 0x43, 0x86, 0x83, 0xfa,
-				0xc2, 0x8c, 0xe9, 0xde, 0x4c, 0x48, 0x1d, 0x94, 0xd2, 0xe5, 0x61, 0xb0, 0xf8, 0x71, 0x17, 0x56,
-				0xcb, 0x63, 0x59, 0x02, 0x81, 0x80, 0x1d, 0x65, 0x4a, 0xca, 0x46, 0x9c, 0x27, 0x9c, 0xae, 0x8d,
-				0x07, 0x74, 0xc1, 0xc1, 0xf7, 0x48, 0xe6, 0x57, 0x71, 0xb1, 0x60, 0x14, 0x65, 0xdd, 0x21, 0x3b,
-				0xd0, 0xe1, 0x3f, 0xd2, 0x72, 0x72, 0x85, 0x6d, 0x07, 0x99, 0x84, 0x81, 0x46, 0x1d, 0x2e, 0x7e,
-				0x2a, 0x85, 0x76, 0xc6, 0xee, 0x82, 0xef, 0x87, 0x8d, 0xcf, 0x9a, 0xa7, 0x60, 0x92, 0xe9, 0x38,
-				0x8f, 0xdd, 0x56, 0x84, 0x1f, 0x4b, 0x56, 0x77, 0x8f, 0x2f, 0x2f, 0x1d, 0xb7, 0xdb, 0xef, 0xc9,
-				0x4f, 0x2a, 0xda, 0x76, 0x0a, 0x14, 0x41, 0x60, 0x5d, 0xb7, 0x3a, 0x1c, 0x48, 0x2c, 0x17, 0xb4,
-				0xe1, 0x1b, 0x9c, 0x4f, 0xe4, 0x34, 0x89, 0x59, 0xa7, 0x58, 0xc3, 0x90, 0x5e, 0x1c, 0xef, 0x83,
-				0xca, 0xd6, 0xc9, 0x4c, 0xa4, 0x4a, 0xac, 0xe4, 0x7b, 0x3d, 0xe1, 0x47, 0xa7, 0x65, 0x67, 0xd2,
-				0x55, 0xa7, 0x30, 0x85, 0xea, 0xf4
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA1 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xe0, 0x93, 0xa6, 0x85, 0x5f, 0x32, 0x37, 0x1c, 0xc5, 0x16, 0x25, 0x70,
-				0xe3, 0x7c, 0x60, 0xd7, 0x5b, 0x6d, 0x64, 0x39, 0xd1, 0x76, 0xdf, 0x06, 0x58, 0x78, 0xa7, 0x5e,
-				0xa7, 0xbc, 0x53, 0x51, 0x14, 0xf8, 0x01, 0x82, 0x75, 0xf8, 0x1e, 0x17, 0x80, 0xb7, 0xbf, 0xb8,
-				0x3d, 0xf8, 0xa1, 0x52, 0xcc, 0xc9, 0xc9, 0x07, 0xb7, 0x17, 0x5a, 0xc9, 0x8b, 0xf2, 0x44, 0x2b,
-				0x2e, 0x18, 0x61, 0x28, 0x2a, 0xf7, 0x04, 0xdb, 0xad, 0xc4, 0xdc, 0x25, 0xf9, 0xb4, 0x86, 0x23,
-				0x6a, 0xf5, 0x41, 0x6b, 0x76, 0xe6, 0x5a, 0x6f, 0xfe, 0xf3, 0x93, 0x48, 0xf1, 0x01, 0x69, 0x62,
-				0xc0, 0xda, 0x23, 0x26, 0x7f, 0x1d, 0xf5, 0x3e, 0xbe, 0x7e, 0xb7, 0xb1, 0xeb, 0xd9, 0x3f, 0x20,
-				0xf1, 0x0e, 0x75, 0xdf, 0x62, 0x77, 0xec, 0x6c, 0xf8, 0x8c, 0x32, 0xb9, 0x2a, 0x5c, 0xfe, 0x93,
-				0xa0, 0x4d, 0x86, 0x5c, 0x35, 0x97, 0x70, 0x44, 0x1d, 0x8d, 0x59, 0x30, 0xc8, 0xe1, 0x42, 0x74,
-				0x1b, 0xe1, 0x7f, 0xe1, 0x6d, 0xc3, 0xa0, 0xb7, 0xc3, 0x60, 0x37, 0x9b, 0xce, 0xf5, 0xb3, 0xf5,
-				0xf8, 0xe2, 0xa3, 0x56, 0x3d, 0x5a, 0x14, 0x09, 0xd5, 0xd1, 0x09, 0x21, 0x93, 0xde, 0x79, 0x4d,
-				0xad, 0xf3, 0x8a, 0x19, 0x46, 0xaa, 0xe1, 0x3d, 0xf6, 0x11, 0xa0, 0x1d, 0x58, 0x82, 0xf0, 0xcd,
-				0x54, 0xd4, 0x76, 0x3f, 0x20, 0x85, 0x10, 0x15, 0x19, 0x22, 0x86, 0xb2, 0xc6, 0xc4, 0x48, 0xa5,
-				0x19, 0x4e, 0x1e, 0xdc, 0x43, 0xba, 0x4d, 0xa6, 0xba, 0xf6, 0x26, 0xee, 0xed, 0xe5, 0xce, 0x4d,
-				0x5a, 0x25, 0xf6, 0xb5, 0x24, 0x9c, 0x8b, 0xc0, 0xa1, 0xb4, 0x97, 0x56, 0x13, 0x76, 0x2c, 0xed,
-				0x3b, 0x52, 0x82, 0x1e, 0x92, 0x06, 0xfd, 0x03, 0x32, 0x91, 0xf8, 0x1b, 0xd8, 0xa4, 0xbe, 0x8a,
-				0x51, 0x7c, 0x21, 0x91
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe0, 0x93, 0xa6, 0x85,
-				0x5f, 0x32, 0x37, 0x1c, 0xc5, 0x16, 0x25, 0x70, 0xe3, 0x7c, 0x60, 0xd7, 0x5b, 0x6d, 0x64, 0x39,
-				0xd1, 0x76, 0xdf, 0x06, 0x58, 0x78, 0xa7, 0x5e, 0xa7, 0xbc, 0x53, 0x51, 0x14, 0xf8, 0x01, 0x82,
-				0x75, 0xf8, 0x1e, 0x17, 0x80, 0xb7, 0xbf, 0xb8, 0x3d, 0xf8, 0xa1, 0x52, 0xcc, 0xc9, 0xc9, 0x07,
-				0xb7, 0x17, 0x5a, 0xc9, 0x8b, 0xf2, 0x44, 0x2b, 0x2e, 0x18, 0x61, 0x28, 0x2a, 0xf7, 0x04, 0xdb,
-				0xad, 0xc4, 0xdc, 0x25, 0xf9, 0xb4, 0x86, 0x23, 0x6a, 0xf5, 0x41, 0x6b, 0x76, 0xe6, 0x5a, 0x6f,
-				0xfe, 0xf3, 0x93, 0x48, 0xf1, 0x01, 0x69, 0x62, 0xc0, 0xda, 0x23, 0x26, 0x7f, 0x1d, 0xf5, 0x3e,
-				0xbe, 0x7e, 0xb7, 0xb1, 0xeb, 0xd9, 0x3f, 0x20, 0xf1, 0x0e, 0x75, 0xdf, 0x62, 0x77, 0xec, 0x6c,
-				0xf8, 0x8c, 0x32, 0xb9, 0x2a, 0x5c, 0xfe, 0x93, 0xa0, 0x4d, 0x86, 0x5c, 0x35, 0x97, 0x70, 0x44,
-				0x1d, 0x8d, 0x59, 0x30, 0xc8, 0xe1, 0x42, 0x74, 0x1b, 0xe1, 0x7f, 0xe1, 0x6d, 0xc3, 0xa0, 0xb7,
-				0xc3, 0x60, 0x37, 0x9b, 0xce, 0xf5, 0xb3, 0xf5, 0xf8, 0xe2, 0xa3, 0x56, 0x3d, 0x5a, 0x14, 0x09,
-				0xd5, 0xd1, 0x09, 0x21, 0x93, 0xde, 0x79, 0x4d, 0xad, 0xf3, 0x8a, 0x19, 0x46, 0xaa, 0xe1, 0x3d,
-				0xf6, 0x11, 0xa0, 0x1d, 0x58, 0x82, 0xf0, 0xcd, 0x54, 0xd4, 0x76, 0x3f, 0x20, 0x85, 0x10, 0x15,
-				0x19, 0x22, 0x86, 0xb2, 0xc6, 0xc4, 0x48, 0xa5, 0x19, 0x4e, 0x1e, 0xdc, 0x43, 0xba, 0x4d, 0xa6,
-				0xba, 0xf6, 0x26, 0xee, 0xed, 0xe5, 0xce, 0x4d, 0x5a, 0x25, 0xf6, 0xb5, 0x24, 0x9c, 0x8b, 0xc0,
-				0xa1, 0xb4, 0x97, 0x56, 0x13, 0x76, 0x2c, 0xed, 0x3b, 0x52, 0x82, 0x1e, 0x92, 0x06, 0xfd, 0x03,
-				0x32, 0x91, 0xf8, 0x1b, 0xd8, 0xa4, 0xbe, 0x8a, 0x51, 0x7c, 0x21, 0x91, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x07, 0xa3, 0x25, 0xd0, 0xd7, 0xd3, 0xb0, 0x99, 0x9f, 0x1f, 0x39,
-				0x6f, 0x3d, 0x21, 0x43, 0xf6, 0xd6, 0xf2, 0x61, 0xab, 0xf0, 0xb2, 0x6a, 0xf3, 0xbf, 0x8a, 0xfc,
-				0xe0, 0x24, 0x72, 0xac, 0x5f, 0xaf, 0xc7, 0x9e, 0x5f, 0x86, 0x2d, 0x05, 0xb2, 0xf5, 0x6a, 0xea,
-				0x4f, 0x74, 0xf6, 0x11, 0x60, 0x6c, 0x3b, 0xf9, 0x84, 0xf4, 0x66, 0x4c, 0x2d, 0x59, 0xff, 0xc7,
-				0x6f, 0x33, 0x7e, 0x5b, 0x41, 0x7f, 0x32, 0x8e, 0xdc, 0xfc, 0xac, 0x1a, 0xf3, 0x84, 0xaa, 0x2d,
-				0xbc, 0xa3, 0x1c, 0xcb, 0x98, 0x80, 0xbe, 0xe5, 0x38, 0xf5, 0x51, 0xe9, 0xc2, 0x9b, 0x85, 0x99,
-				0x84, 0xa4, 0xfb, 0xd6, 0x21, 0xaf, 0x45, 0x80, 0xcb, 0x5d, 0x35, 0x98, 0x80, 0x29, 0xbd, 0xe5,
-				0xde, 0x74, 0x2c, 0x32, 0x78, 0x82, 0x14, 0x03, 0x7b, 0x92, 0x39, 0x4c, 0x59, 0x4d, 0x36, 0x43,
-				0xe7, 0x17, 0xd6, 0xc3, 0x18, 0xab, 0xdc, 0xea, 0x70, 0xa0, 0x74, 0x70, 0xa8, 0xbd, 0x46, 0xbe,
-				0x96, 0x1d, 0x8f, 0xd8, 0x91, 0x7c, 0x4d, 0x1c, 0x66, 0x57, 0x93, 0x63, 0x16, 0xb5, 0x8e, 0xb7,
-				0x7c, 0xed, 0x90, 0x4f, 0xdd, 0xf9, 0x7d, 0x92, 0x4c, 0xea, 0x3d, 0x5d, 0xc0, 0xeb, 0x04, 0x21,
-				0x88, 0x87, 0xa8, 0x43, 0x12, 0x8c, 0x31, 0xde, 0x17, 0x09, 0x83, 0x2f, 0x4b, 0xa4, 0x9e, 0x75,
-				0x88, 0x51, 0x61, 0x50, 0xd8, 0xa5, 0x17, 0x77, 0x0d, 0x53, 0x47, 0x89, 0xbf, 0x04, 0x4b, 0x55,
-				0x5d, 0x32, 0x34, 0x63, 0x05, 0xfd, 0x68, 0x36, 0xe0, 0xbf, 0x75, 0x5b, 0x58, 0x19, 0x28, 0xb1,
-				0x76, 0x09, 0xfd, 0xde, 0xc2, 0xa3, 0x5a, 0xcd, 0xd9, 0x76, 0xdc, 0x79, 0x6a, 0xf8, 0xae, 0x33,
-				0x1a, 0x25, 0x20, 0x14, 0x1b, 0x15, 0xf8, 0x0c, 0x8e, 0xc2, 0x4d, 0x95, 0x2d, 0x54, 0x59, 0x0b,
-				0x10, 0xf7, 0xbe, 0xb8, 0x75, 0x02, 0x81, 0x81, 0x00, 0xf9, 0x0d, 0xab, 0x91, 0xd7, 0x52, 0xe9,
-				0xf2, 0xbe, 0xd4, 0x57, 0xa7, 0x16, 0x38, 0x85, 0x5b, 0xbb, 0x0e, 0xa9, 0x3b, 0x39, 0x2a, 0x25,
-				0xbd, 0x85, 0xca, 0x15, 0x3d, 0x41, 0x54, 0x45, 0x95, 0x5b, 0xc4, 0x49, 0xe2, 0x52, 0xf2, 0x6e,
-				0x8c, 0xf4, 0xd7, 0xcf, 0xfd, 0x4f, 0x77, 0xc4, 0xd3, 0x21, 0x5a, 0x8c, 0x16, 0xd0, 0x3d, 0xd5,
-				0xb0, 0xeb, 0xf3, 0x22, 0x6a, 0x23, 0x04, 0x70, 0xf5, 0xde, 0x94, 0xc2, 0x76, 0x01, 0xea, 0x97,
-				0x40, 0xf8, 0x48, 0x7b, 0x59, 0xea, 0x3a, 0xf5, 0x37, 0x6f, 0x6f, 0xf2, 0x13, 0xf9, 0x7c, 0x3c,
-				0x50, 0x7c, 0x49, 0x20, 0x0e, 0x78, 0xd9, 0x98, 0x60, 0x87, 0xc5, 0xcf, 0x36, 0x58, 0x98, 0x19,
-				0xc6, 0xff, 0xfe, 0x53, 0xe9, 0x61, 0x55, 0x13, 0x6b, 0xe3, 0x01, 0x59, 0xeb, 0xf0, 0xe8, 0x13,
-				0x50, 0x0c, 0x00, 0x84, 0x8b, 0xf7, 0xa0, 0x6e, 0xd5, 0x02, 0x81, 0x81, 0x00, 0xe6, 0xd7, 0x35,
-				0x57, 0xcd, 0xac, 0x1b, 0x50, 0x8a, 0x1f, 0xc5, 0x3a, 0x69, 0x64, 0xd9, 0xa2, 0x2b, 0x96, 0xb4,
-				0xc1, 0xb7, 0xfc, 0x81, 0x37, 0x6e, 0x5d, 0x9b, 0xd5, 0x57, 0x30, 0x03, 0xb9, 0xc6, 0xac, 0x5a,
-				0xff, 0x64, 0x0d, 0xd7, 0x82, 0xdf, 0x66, 0x9f, 0x96, 0xee, 0x24, 0x9e, 0xf5, 0xe2, 0x2f, 0xb5,
-				0x29, 0x07, 0xfe, 0xb6, 0xc5, 0xe9, 0x6f, 0x32, 0x50, 0x98, 0xcc, 0xdd, 0x58, 0xe2, 0xd1, 0xe0,
-				0x77, 0xf8, 0x7a, 0xcf, 0xa6, 0x68, 0xb4, 0x2e, 0x68, 0x17, 0xb8, 0x31, 0xab, 0x71, 0x1c, 0xa3,
-				0x6c, 0x95, 0x2f, 0x47, 0x4a, 0x1b, 0x07, 0x93, 0x41, 0x44, 0xd6, 0x51, 0x77, 0x07, 0x8d, 0x84,
-				0x50, 0x15, 0x5f, 0x6c, 0x5d, 0x4c, 0xef, 0xee, 0xcc, 0xa2, 0x48, 0xde, 0xdf, 0x03, 0x16, 0x00,
-				0x7f, 0x05, 0xaa, 0x87, 0x1b, 0x65, 0x73, 0xbc, 0x55, 0x26, 0xc0, 0x5d, 0xcd, 0x02, 0x81, 0x80,
-				0x13, 0xfc, 0x37, 0xd7, 0x55, 0x2b, 0x0f, 0x20, 0xee, 0x95, 0x45, 0x8f, 0x5f, 0xe6, 0x1b, 0x35,
-				0x78, 0x36, 0x3d, 0xf8, 0x45, 0xa7, 0x0f, 0x2e, 0x3d, 0x2d, 0x31, 0x35, 0x20, 0x27, 0xee, 0x09,
-				0x85, 0x3a, 0xa4, 0x1f, 0x28, 0x3e, 0xd2, 0x06, 0x37, 0xa3, 0x95, 0xca, 0x22, 0xf5, 0x5e, 0x72,
-				0xfe, 0xcb, 0x30, 0x50, 0xa8, 0x57, 0x3d, 0xed, 0x9b, 0x91, 0x80, 0x22, 0x7a, 0x3a, 0xe2, 0x01,
-				0xa8, 0xe1, 0xd1, 0x14, 0xfd, 0x24, 0x61, 0x0c, 0xd2, 0x9f, 0xa6, 0x5e, 0x59, 0xc0, 0x6f, 0x6b,
-				0x0a, 0x63, 0x36, 0x4e, 0xca, 0x07, 0x61, 0x23, 0xa8, 0x45, 0x89, 0xef, 0xff, 0x5c, 0x9e, 0xb0,
-				0xa8, 0x54, 0x84, 0x43, 0x3d, 0x2a, 0xbf, 0x6e, 0xcb, 0x9e, 0x12, 0x07, 0xb9, 0x4a, 0xc5, 0x6b,
-				0x33, 0xe5, 0x28, 0xdd, 0x19, 0x10, 0xd6, 0x73, 0xe6, 0xf2, 0xa7, 0xb0, 0x3f, 0xa7, 0xbd, 0x1d,
-				0x02, 0x81, 0x80, 0x28, 0x3d, 0x1b, 0x6f, 0x52, 0xca, 0xcd, 0x78, 0x1c, 0x9b, 0xad, 0x25, 0xa1,
-				0x79, 0x92, 0xf6, 0x51, 0xe2, 0xd3, 0x5f, 0x71, 0x52, 0xf2, 0xb3, 0x56, 0xe9, 0xba, 0x60, 0x55,
-				0xf2, 0x68, 0xb3, 0xd9, 0x8d, 0xf1, 0xce, 0xd3, 0x02, 0x16, 0xaf, 0x19, 0x82, 0x2a, 0x0f, 0x85,
-				0x33, 0x9d, 0x01, 0xff, 0x8b, 0x91, 0x68, 0xb5, 0x9c, 0x11, 0x00, 0x2e, 0xd0, 0xd3, 0x54, 0x79,
-				0x4e, 0x3c, 0xc7, 0x61, 0xc2, 0x73, 0xfe, 0x75, 0xb1, 0xf2, 0xc0, 0x6f, 0x3f, 0xf9, 0x56, 0xeb,
-				0xcb, 0x8f, 0xdc, 0xf2, 0xba, 0xab, 0x42, 0x22, 0x3f, 0x3b, 0x8e, 0x0f, 0x68, 0x22, 0xa3, 0x1d,
-				0xfc, 0xbd, 0xf6, 0xa1, 0xba, 0x69, 0x76, 0x0c, 0x43, 0xb6, 0x00, 0x0d, 0x89, 0x45, 0x77, 0x26,
-				0x52, 0xcd, 0x86, 0xd2, 0x62, 0xe3, 0x73, 0x40, 0xe9, 0x98, 0xe3, 0x8d, 0xab, 0xbf, 0x08, 0x98,
-				0xd8, 0xaf, 0x81, 0x02, 0x81, 0x80, 0x35, 0xc4, 0xeb, 0x22, 0x1c, 0xa8, 0x64, 0xd2, 0x8e, 0x3f,
-				0x43, 0x71, 0xfb, 0xbe, 0xa6, 0xc4, 0xb4, 0x35, 0xcb, 0x12, 0x8d, 0x92, 0xba, 0x59, 0x10, 0x9c,
-				0x0a, 0x49, 0xb3, 0x02, 0x25, 0xe5, 0x0c, 0x9d, 0x8b, 0xe6, 0x88, 0x54, 0x4a, 0x63, 0xe4, 0xd3,
-				0x15, 0x7e, 0x43, 0xe9, 0x0c, 0xf0, 0xaf, 0x48, 0xfe, 0x04, 0xb7, 0x95, 0x9c, 0xc3, 0xc4, 0x90,
-				0x9f, 0x56, 0xff, 0xbc, 0x49, 0x25, 0x4f, 0xb9, 0x43, 0xa8, 0xbe, 0x94, 0x8d, 0xb7, 0xeb, 0x5e,
-				0x84, 0xf9, 0x6c, 0xe8, 0x50, 0xa0, 0xd5, 0x85, 0x50, 0xeb, 0x46, 0x0c, 0x8d, 0xf9, 0xc9, 0x82,
-				0x1d, 0x6a, 0x3e, 0x5c, 0x1c, 0xfe, 0xc6, 0x7b, 0xee, 0x6e, 0xb2, 0x26, 0x3d, 0x11, 0x3a, 0x16,
-				0xd0, 0x8f, 0x7b, 0x14, 0x94, 0xd2, 0x3a, 0x7b, 0xbd, 0xd5, 0x3a, 0x33, 0xe8, 0x12, 0xff, 0x97,
-				0x27, 0xf1, 0xca, 0xe1, 0xf3, 0x90
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( RSASHA1 );
-
-//===========================================================================================================================
-// MARK: - RSA/SHA-256 DNS Keys
-
-typedef struct
-{
-	DNSKeyRSASHA256Info		ksk;	// Key-Signing Key
-	DNSKeyRSASHA256Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyRSASHA256Set;
-
-static const DNSKeyRSASHA256Set		kDNSKeyRSASHA256Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xdd, 0x64, 0xb2, 0x1e, 0x99, 0xac, 0x71, 0xca, 0x9a, 0x99, 0x14, 0xd5,
-				0xb8, 0x5e, 0xd3, 0xa6, 0x7f, 0x1f, 0xe6, 0x7f, 0x07, 0xf8, 0x6f, 0xe3, 0x1c, 0xf3, 0x63, 0x5e,
-				0x06, 0x4a, 0x0e, 0x5b, 0xca, 0xcd, 0xe8, 0xfa, 0xd3, 0x67, 0x42, 0x52, 0x94, 0x54, 0x30, 0x3e,
-				0x54, 0x55, 0x4d, 0x91, 0xea, 0x0a, 0xbf, 0x5d, 0xfa, 0x7e, 0xd9, 0x27, 0x67, 0xdd, 0x8f, 0x01,
-				0x44, 0x53, 0x95, 0x3f, 0xe4, 0x62, 0xd0, 0xfe, 0x18, 0x6d, 0xf2, 0x2b, 0xfc, 0x4e, 0x09, 0x28,
-				0xa0, 0x52, 0xc9, 0xae, 0x3a, 0x4a, 0xc6, 0xc8, 0x08, 0xad, 0x1d, 0xa7, 0x6d, 0x9b, 0xfe, 0xc6,
-				0x9c, 0xcf, 0x46, 0x8d, 0x0e, 0x20, 0xed, 0xad, 0x40, 0x60, 0x0d, 0x91, 0x0b, 0x48, 0x82, 0x30,
-				0xa8, 0xcf, 0x92, 0x4e, 0x8b, 0xda, 0x6a, 0x2d, 0xe4, 0x4e, 0x1c, 0x74, 0x44, 0x33, 0x84, 0xc3,
-				0xa9, 0xb4, 0xea, 0x71, 0x61, 0x6b, 0x4b, 0x0b, 0x0f, 0xcf, 0x58, 0x38, 0xfc, 0x10, 0xd1, 0x37,
-				0x88, 0x54, 0x99, 0xd4, 0xc2, 0xe9, 0xc9, 0xba, 0x72, 0x23, 0xe0, 0xd4, 0x85, 0xfd, 0x67, 0x75,
-				0xca, 0x41, 0xe8, 0x69, 0x00, 0x4b, 0x86, 0xd9, 0x74, 0xcf, 0x3f, 0xce, 0x66, 0x13, 0x3a, 0xc0,
-				0xc5, 0x20, 0x51, 0xd7, 0x9c, 0xbc, 0xbf, 0xc7, 0x56, 0x32, 0x18, 0x4a, 0x98, 0x8b, 0x34, 0x0b,
-				0x2f, 0x5c, 0x2d, 0xd9, 0x7a, 0x5b, 0xa6, 0xff, 0x59, 0xf2, 0x89, 0xd2, 0x8d, 0xef, 0x0a, 0x35,
-				0xbf, 0x8f, 0x70, 0xfa, 0x36, 0xac, 0xd2, 0x6e, 0x71, 0xc6, 0x8d, 0x4a, 0xc5, 0x39, 0x4b, 0xb0,
-				0x5e, 0xad, 0x32, 0x0d, 0x5b, 0x3f, 0x1a, 0x45, 0x0c, 0x43, 0x49, 0x99, 0x89, 0xd0, 0xc1, 0x1c,
-				0xf9, 0x5f, 0xc2, 0x07, 0xe6, 0x62, 0xf1, 0xad, 0xc2, 0xb2, 0x4d, 0xe7, 0xd2, 0x4e, 0xf0, 0x94,
-				0xe0, 0x4a, 0xc8, 0x91
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xdd, 0x64, 0xb2, 0x1e,
-				0x99, 0xac, 0x71, 0xca, 0x9a, 0x99, 0x14, 0xd5, 0xb8, 0x5e, 0xd3, 0xa6, 0x7f, 0x1f, 0xe6, 0x7f,
-				0x07, 0xf8, 0x6f, 0xe3, 0x1c, 0xf3, 0x63, 0x5e, 0x06, 0x4a, 0x0e, 0x5b, 0xca, 0xcd, 0xe8, 0xfa,
-				0xd3, 0x67, 0x42, 0x52, 0x94, 0x54, 0x30, 0x3e, 0x54, 0x55, 0x4d, 0x91, 0xea, 0x0a, 0xbf, 0x5d,
-				0xfa, 0x7e, 0xd9, 0x27, 0x67, 0xdd, 0x8f, 0x01, 0x44, 0x53, 0x95, 0x3f, 0xe4, 0x62, 0xd0, 0xfe,
-				0x18, 0x6d, 0xf2, 0x2b, 0xfc, 0x4e, 0x09, 0x28, 0xa0, 0x52, 0xc9, 0xae, 0x3a, 0x4a, 0xc6, 0xc8,
-				0x08, 0xad, 0x1d, 0xa7, 0x6d, 0x9b, 0xfe, 0xc6, 0x9c, 0xcf, 0x46, 0x8d, 0x0e, 0x20, 0xed, 0xad,
-				0x40, 0x60, 0x0d, 0x91, 0x0b, 0x48, 0x82, 0x30, 0xa8, 0xcf, 0x92, 0x4e, 0x8b, 0xda, 0x6a, 0x2d,
-				0xe4, 0x4e, 0x1c, 0x74, 0x44, 0x33, 0x84, 0xc3, 0xa9, 0xb4, 0xea, 0x71, 0x61, 0x6b, 0x4b, 0x0b,
-				0x0f, 0xcf, 0x58, 0x38, 0xfc, 0x10, 0xd1, 0x37, 0x88, 0x54, 0x99, 0xd4, 0xc2, 0xe9, 0xc9, 0xba,
-				0x72, 0x23, 0xe0, 0xd4, 0x85, 0xfd, 0x67, 0x75, 0xca, 0x41, 0xe8, 0x69, 0x00, 0x4b, 0x86, 0xd9,
-				0x74, 0xcf, 0x3f, 0xce, 0x66, 0x13, 0x3a, 0xc0, 0xc5, 0x20, 0x51, 0xd7, 0x9c, 0xbc, 0xbf, 0xc7,
-				0x56, 0x32, 0x18, 0x4a, 0x98, 0x8b, 0x34, 0x0b, 0x2f, 0x5c, 0x2d, 0xd9, 0x7a, 0x5b, 0xa6, 0xff,
-				0x59, 0xf2, 0x89, 0xd2, 0x8d, 0xef, 0x0a, 0x35, 0xbf, 0x8f, 0x70, 0xfa, 0x36, 0xac, 0xd2, 0x6e,
-				0x71, 0xc6, 0x8d, 0x4a, 0xc5, 0x39, 0x4b, 0xb0, 0x5e, 0xad, 0x32, 0x0d, 0x5b, 0x3f, 0x1a, 0x45,
-				0x0c, 0x43, 0x49, 0x99, 0x89, 0xd0, 0xc1, 0x1c, 0xf9, 0x5f, 0xc2, 0x07, 0xe6, 0x62, 0xf1, 0xad,
-				0xc2, 0xb2, 0x4d, 0xe7, 0xd2, 0x4e, 0xf0, 0x94, 0xe0, 0x4a, 0xc8, 0x91, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x02, 0xeb, 0x68, 0x46, 0xeb, 0x87, 0x60, 0xe3, 0xc7, 0x58, 0xa3,
-				0xf3, 0xf2, 0x8f, 0xbb, 0x92, 0x4b, 0x44, 0x60, 0x2d, 0x86, 0x2d, 0x22, 0x4a, 0x98, 0x2f, 0xe4,
-				0x7c, 0x51, 0xb0, 0x69, 0xd2, 0x8f, 0x90, 0xda, 0x14, 0xee, 0xb3, 0x42, 0xa6, 0x64, 0xa2, 0xdc,
-				0x95, 0x01, 0xd7, 0x33, 0x23, 0xec, 0xb6, 0x72, 0x12, 0x1a, 0xf2, 0xcf, 0xc9, 0xcb, 0x7e, 0x9a,
-				0x3b, 0x6d, 0xcb, 0x7d, 0x61, 0x1f, 0x91, 0xa7, 0x08, 0x66, 0xc9, 0x92, 0x63, 0x3e, 0x9b, 0x47,
-				0xd7, 0x23, 0x90, 0x1b, 0xed, 0x42, 0x83, 0x08, 0x6e, 0x8c, 0x60, 0xbe, 0x0e, 0x9e, 0x6d, 0x2b,
-				0x75, 0xb2, 0x8d, 0x30, 0x34, 0xbd, 0x7e, 0x35, 0x2c, 0x2e, 0xf8, 0x65, 0x4d, 0x67, 0x9c, 0xef,
-				0xec, 0x94, 0xd9, 0x51, 0xe8, 0x5b, 0xc3, 0x48, 0x59, 0xad, 0x14, 0x53, 0x9f, 0x3b, 0xe4, 0x03,
-				0x08, 0xf2, 0x84, 0xba, 0x7f, 0xb8, 0x7a, 0xc7, 0x7e, 0xa0, 0x81, 0x53, 0xe8, 0x6a, 0x91, 0x27,
-				0x0f, 0x36, 0x11, 0x22, 0x45, 0x85, 0xc6, 0x79, 0x35, 0xae, 0x0b, 0x52, 0x86, 0x56, 0xd3, 0xe3,
-				0x6d, 0x16, 0xa5, 0xb3, 0xf7, 0x90, 0xd7, 0x60, 0x99, 0x79, 0x9d, 0x94, 0xcd, 0x89, 0xe2, 0xb7,
-				0x2c, 0xfc, 0xfa, 0x0d, 0x38, 0x8d, 0x40, 0x0d, 0x78, 0x5c, 0xb4, 0x90, 0x4a, 0x22, 0xc0, 0x5f,
-				0xd7, 0xe2, 0xb3, 0x09, 0xd8, 0x49, 0x12, 0x78, 0x19, 0x0a, 0xd9, 0x1c, 0x65, 0xb6, 0xd1, 0x7a,
-				0x96, 0xf4, 0x61, 0x59, 0x48, 0x6e, 0xbf, 0x7a, 0x81, 0xb6, 0x46, 0x17, 0x56, 0x0d, 0x6f, 0x79,
-				0xd1, 0x6e, 0x3d, 0xb6, 0x2c, 0x49, 0x92, 0xaa, 0x61, 0x33, 0x7b, 0x88, 0x1b, 0x7d, 0x16, 0x89,
-				0xef, 0x6f, 0xab, 0xc6, 0x73, 0x7f, 0x08, 0x5b, 0xe6, 0x38, 0xe3, 0x50, 0xd1, 0xf5, 0x8b, 0x64,
-				0x44, 0xd7, 0xae, 0xe6, 0x7d, 0x02, 0x81, 0x81, 0x00, 0xfd, 0x96, 0x66, 0x13, 0x8b, 0x27, 0x88,
-				0x67, 0x0c, 0x96, 0x49, 0x3b, 0x12, 0x3e, 0x5d, 0xe7, 0x6a, 0xc0, 0x04, 0xdd, 0x96, 0xca, 0x15,
-				0x29, 0xf0, 0xee, 0x43, 0x35, 0xf2, 0xc9, 0xe3, 0x29, 0x2a, 0xea, 0xc2, 0x5e, 0xa2, 0xa0, 0x9b,
-				0xfa, 0x27, 0x99, 0xa0, 0xa6, 0x68, 0x4c, 0x5a, 0x48, 0x0e, 0x4e, 0xd5, 0xc8, 0xfa, 0xc9, 0x44,
-				0x9b, 0x00, 0x6d, 0xaa, 0x1f, 0xc8, 0x7a, 0xc6, 0x80, 0xba, 0xa8, 0xf3, 0x56, 0x5a, 0x17, 0x75,
-				0x23, 0x5d, 0xec, 0xca, 0x97, 0xaf, 0x2b, 0x1b, 0x14, 0x1a, 0x9c, 0xb6, 0x0f, 0x74, 0x22, 0xf8,
-				0xfe, 0x27, 0xe2, 0x59, 0x9a, 0x0b, 0x47, 0x32, 0x72, 0x82, 0x58, 0x03, 0xdd, 0xe5, 0xa5, 0x55,
-				0xac, 0xfb, 0x02, 0x3a, 0xf9, 0x56, 0x7d, 0xb8, 0x5d, 0xc6, 0x99, 0x6b, 0x03, 0x99, 0x3b, 0xac,
-				0xc9, 0x6a, 0x90, 0xac, 0x4f, 0x92, 0xe9, 0xfe, 0xed, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x7f, 0xe3,
-				0xbc, 0x59, 0xa4, 0xf3, 0x12, 0x25, 0x84, 0x44, 0xc9, 0x66, 0xcd, 0xc8, 0xcd, 0x8f, 0xda, 0x17,
-				0xc1, 0x9a, 0xb3, 0xbf, 0xc5, 0x23, 0x06, 0x54, 0x05, 0x2b, 0x94, 0x92, 0x2a, 0x7d, 0x32, 0xb9,
-				0x6a, 0x64, 0x45, 0x78, 0xea, 0xc6, 0x36, 0x58, 0x0f, 0xcd, 0x4d, 0x5a, 0xd5, 0xb1, 0x59, 0xed,
-				0xb8, 0xb2, 0x12, 0xb4, 0x86, 0x55, 0xaf, 0xe9, 0xaa, 0xaa, 0xcf, 0x2c, 0x73, 0xf3, 0x62, 0xac,
-				0xb2, 0x1f, 0xba, 0x20, 0xf4, 0x6f, 0xdb, 0xea, 0x9f, 0xec, 0x9b, 0xd3, 0xa1, 0x87, 0x18, 0x67,
-				0x41, 0x82, 0x40, 0x63, 0xe6, 0x7d, 0x57, 0x2a, 0xb0, 0xee, 0x20, 0x57, 0x22, 0xa9, 0x3a, 0x0a,
-				0x5f, 0x31, 0xa7, 0xec, 0x5d, 0x5b, 0x2f, 0x14, 0xeb, 0x8c, 0x03, 0x1a, 0x64, 0xe3, 0xc5, 0xfd,
-				0xdd, 0x8b, 0x20, 0xaa, 0xaa, 0x08, 0xda, 0x17, 0x79, 0x3a, 0x33, 0x57, 0xb5, 0x02, 0x81, 0x80,
-				0x12, 0x04, 0x0d, 0x5c, 0x76, 0x16, 0x68, 0xea, 0x69, 0x4a, 0x84, 0x09, 0x5e, 0x52, 0x6f, 0xf9,
-				0x70, 0xec, 0x13, 0x6c, 0x6a, 0xba, 0x10, 0xa6, 0xda, 0x27, 0x13, 0x3f, 0x51, 0xf0, 0x65, 0xe3,
-				0x16, 0xd9, 0x76, 0xd5, 0xa2, 0x58, 0x26, 0xbc, 0xae, 0xf3, 0x8b, 0x26, 0x47, 0x62, 0xa5, 0x47,
-				0x59, 0x3c, 0xe0, 0x93, 0x56, 0xbd, 0xd5, 0xd1, 0xed, 0x45, 0xdd, 0x40, 0x44, 0xcd, 0xf4, 0x2c,
-				0x51, 0x16, 0x8f, 0xb3, 0x22, 0xd3, 0x67, 0xcf, 0x0b, 0x6d, 0x37, 0x37, 0x6f, 0x8a, 0x70, 0x72,
-				0x0d, 0x31, 0xf4, 0xfd, 0x44, 0x12, 0xf7, 0xfd, 0x96, 0x77, 0xce, 0x45, 0xd3, 0x67, 0x4b, 0x7e,
-				0x37, 0x24, 0x69, 0xa1, 0xea, 0x1e, 0xc4, 0xe7, 0x75, 0x2d, 0xc3, 0x62, 0xd3, 0x72, 0x3b, 0x16,
-				0xee, 0x75, 0x17, 0xd5, 0x39, 0x9d, 0xb3, 0xb8, 0xdb, 0x89, 0x4b, 0xb4, 0x9b, 0x8b, 0x64, 0x41,
-				0x02, 0x81, 0x80, 0x4a, 0x82, 0xdf, 0x90, 0xd6, 0xae, 0x18, 0x5f, 0x6f, 0x64, 0x86, 0x6e, 0x42,
-				0xb8, 0xce, 0x7e, 0x41, 0xbc, 0x2a, 0xf9, 0x5f, 0xb3, 0x17, 0x77, 0x08, 0xb3, 0x3e, 0x65, 0xae,
-				0xde, 0xcc, 0x50, 0x20, 0x07, 0x3e, 0x2b, 0x8b, 0x1c, 0x62, 0x30, 0x9b, 0x3e, 0x58, 0xe3, 0x83,
-				0xc5, 0x8b, 0x47, 0xfc, 0xe5, 0x87, 0x4c, 0x71, 0x09, 0xad, 0x67, 0xaf, 0xbf, 0x82, 0xfe, 0x64,
-				0x0d, 0xc7, 0xbb, 0x2c, 0x64, 0x34, 0x40, 0xfa, 0x34, 0xda, 0x71, 0xc3, 0xad, 0x24, 0xae, 0x86,
-				0x7a, 0x78, 0xf6, 0xbc, 0x0c, 0x55, 0xb8, 0x50, 0x4d, 0x59, 0x40, 0xe9, 0x7e, 0x9a, 0xfb, 0xfb,
-				0x97, 0x8a, 0x95, 0x42, 0xa7, 0xd7, 0xf7, 0x5e, 0x9d, 0xa6, 0x3e, 0x85, 0x7c, 0xcf, 0xd3, 0xab,
-				0x8d, 0x09, 0x4a, 0xa3, 0x69, 0x49, 0xb6, 0x87, 0x80, 0xaf, 0x85, 0x1a, 0x88, 0x63, 0x15, 0x06,
-				0x63, 0x41, 0x95, 0x02, 0x81, 0x80, 0x58, 0x6e, 0x61, 0xdf, 0x0e, 0x2f, 0x22, 0x91, 0xa4, 0xec,
-				0x85, 0x6c, 0xec, 0xcc, 0x96, 0xb5, 0xf3, 0xd6, 0x4e, 0xd5, 0x3c, 0x61, 0xb1, 0x37, 0x50, 0x48,
-				0x9c, 0xff, 0x80, 0x6d, 0x1e, 0x6e, 0xa0, 0xe2, 0x4b, 0xeb, 0x39, 0x05, 0xc0, 0xf3, 0xa8, 0xfc,
-				0x3b, 0x16, 0x9d, 0xd3, 0x97, 0xa1, 0xb3, 0xdb, 0x73, 0xc5, 0x2a, 0xf8, 0x39, 0x60, 0x49, 0xf7,
-				0x50, 0x4b, 0x08, 0x6c, 0xc4, 0x24, 0xb0, 0x1b, 0x9f, 0x55, 0x50, 0xc8, 0xb2, 0x62, 0x3e, 0xe2,
-				0x11, 0x7f, 0x9f, 0xfa, 0x9a, 0x46, 0x41, 0xa1, 0x9c, 0x13, 0xbf, 0x68, 0x7d, 0x40, 0x40, 0x37,
-				0xbc, 0x44, 0x3c, 0x8f, 0x46, 0x2e, 0x96, 0xb0, 0x0e, 0xbd, 0x66, 0x0e, 0x7d, 0xe9, 0x35, 0x8c,
-				0x7a, 0xdd, 0xb3, 0x13, 0xd1, 0xd1, 0xff, 0x60, 0x57, 0x94, 0x30, 0xd8, 0x8a, 0x48, 0x24, 0x7d,
-				0xeb, 0xae, 0xb0, 0xde, 0x53, 0x8a
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xc6, 0x96, 0xd5, 0x2a, 0xef, 0x43, 0x79, 0xc1, 0x8c, 0x5c, 0x75, 0xb7,
-				0xe5, 0x2a, 0x92, 0x63, 0x28, 0x16, 0x89, 0x1d, 0xb5, 0x71, 0xf5, 0xe7, 0xa8, 0x32, 0xc3, 0x93,
-				0xb3, 0x93, 0xfc, 0xd4, 0x38, 0x5a, 0xba, 0x11, 0xea, 0x18, 0xc6, 0xe0, 0x01, 0xfb, 0xc6, 0x9b,
-				0x0e, 0xf1, 0xf7, 0x9e, 0xb6, 0x1a, 0xf3, 0x60, 0xfb, 0x92, 0x73, 0x80, 0xa3, 0xc8, 0xf6, 0x2a,
-				0x6e, 0x0e, 0x08, 0x85, 0xe6, 0x58, 0x35, 0xaa, 0x49, 0x71, 0x5e, 0xca, 0x77, 0xac, 0x95, 0x1e,
-				0xbf, 0xd6, 0x0a, 0x1d, 0x1c, 0x6e, 0x12, 0x77, 0xb9, 0x1c, 0xf3, 0xe4, 0xa8, 0xff, 0x06, 0xd9,
-				0x53, 0x30, 0x41, 0x89, 0x17, 0x8f, 0x25, 0x3a, 0x2d, 0x5a, 0xfc, 0x47, 0x0b, 0x4b, 0xcd, 0xb8,
-				0x3c, 0x18, 0x0d, 0x27, 0x15, 0x6e, 0x21, 0xae, 0x3f, 0x50, 0x1b, 0x7f, 0x32, 0x0a, 0x08, 0x8d,
-				0xf2, 0x71, 0xc3, 0xa9, 0xf2, 0x57, 0xb7, 0xf3, 0xdb, 0x12, 0xec, 0xee, 0x85, 0xa7, 0xa9, 0x7f,
-				0x35, 0x0a, 0xb6, 0xaf, 0xe4, 0xb5, 0x91, 0xe9, 0x77, 0x87, 0xb7, 0x87, 0x05, 0xed, 0x10, 0xbb,
-				0xe8, 0x5c, 0xb7, 0x1c, 0x3b, 0x11, 0xda, 0x7d, 0xbe, 0xa5, 0xa0, 0x0f, 0x6c, 0xcd, 0x9c, 0x14,
-				0xac, 0x44, 0xe2, 0xc0, 0x3f, 0x40, 0x10, 0x3e, 0x99, 0xd1, 0x4e, 0xd6, 0x6d, 0x11, 0x73, 0x4a,
-				0xdd, 0xa1, 0xf5, 0x42, 0xcf, 0x2e, 0x6c, 0x37, 0x4a, 0xe3, 0x81, 0x7c, 0xdf, 0x3e, 0x4e, 0x10,
-				0x5f, 0x66, 0x64, 0x66, 0x23, 0x5d, 0x8d, 0x16, 0xcb, 0x71, 0x80, 0x4d, 0xb7, 0x73, 0xb9, 0x46,
-				0xcc, 0x40, 0x5e, 0x3d, 0x1e, 0x4c, 0xae, 0x72, 0xd1, 0x5e, 0xd6, 0x3a, 0xcb, 0x40, 0x8a, 0x15,
-				0x83, 0x57, 0x20, 0x3d, 0x4a, 0xa0, 0x02, 0x2d, 0x87, 0x2e, 0xec, 0x40, 0x16, 0xff, 0xba, 0x03,
-				0x62, 0x1d, 0xa7, 0xf5
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0x96, 0xd5, 0x2a,
-				0xef, 0x43, 0x79, 0xc1, 0x8c, 0x5c, 0x75, 0xb7, 0xe5, 0x2a, 0x92, 0x63, 0x28, 0x16, 0x89, 0x1d,
-				0xb5, 0x71, 0xf5, 0xe7, 0xa8, 0x32, 0xc3, 0x93, 0xb3, 0x93, 0xfc, 0xd4, 0x38, 0x5a, 0xba, 0x11,
-				0xea, 0x18, 0xc6, 0xe0, 0x01, 0xfb, 0xc6, 0x9b, 0x0e, 0xf1, 0xf7, 0x9e, 0xb6, 0x1a, 0xf3, 0x60,
-				0xfb, 0x92, 0x73, 0x80, 0xa3, 0xc8, 0xf6, 0x2a, 0x6e, 0x0e, 0x08, 0x85, 0xe6, 0x58, 0x35, 0xaa,
-				0x49, 0x71, 0x5e, 0xca, 0x77, 0xac, 0x95, 0x1e, 0xbf, 0xd6, 0x0a, 0x1d, 0x1c, 0x6e, 0x12, 0x77,
-				0xb9, 0x1c, 0xf3, 0xe4, 0xa8, 0xff, 0x06, 0xd9, 0x53, 0x30, 0x41, 0x89, 0x17, 0x8f, 0x25, 0x3a,
-				0x2d, 0x5a, 0xfc, 0x47, 0x0b, 0x4b, 0xcd, 0xb8, 0x3c, 0x18, 0x0d, 0x27, 0x15, 0x6e, 0x21, 0xae,
-				0x3f, 0x50, 0x1b, 0x7f, 0x32, 0x0a, 0x08, 0x8d, 0xf2, 0x71, 0xc3, 0xa9, 0xf2, 0x57, 0xb7, 0xf3,
-				0xdb, 0x12, 0xec, 0xee, 0x85, 0xa7, 0xa9, 0x7f, 0x35, 0x0a, 0xb6, 0xaf, 0xe4, 0xb5, 0x91, 0xe9,
-				0x77, 0x87, 0xb7, 0x87, 0x05, 0xed, 0x10, 0xbb, 0xe8, 0x5c, 0xb7, 0x1c, 0x3b, 0x11, 0xda, 0x7d,
-				0xbe, 0xa5, 0xa0, 0x0f, 0x6c, 0xcd, 0x9c, 0x14, 0xac, 0x44, 0xe2, 0xc0, 0x3f, 0x40, 0x10, 0x3e,
-				0x99, 0xd1, 0x4e, 0xd6, 0x6d, 0x11, 0x73, 0x4a, 0xdd, 0xa1, 0xf5, 0x42, 0xcf, 0x2e, 0x6c, 0x37,
-				0x4a, 0xe3, 0x81, 0x7c, 0xdf, 0x3e, 0x4e, 0x10, 0x5f, 0x66, 0x64, 0x66, 0x23, 0x5d, 0x8d, 0x16,
-				0xcb, 0x71, 0x80, 0x4d, 0xb7, 0x73, 0xb9, 0x46, 0xcc, 0x40, 0x5e, 0x3d, 0x1e, 0x4c, 0xae, 0x72,
-				0xd1, 0x5e, 0xd6, 0x3a, 0xcb, 0x40, 0x8a, 0x15, 0x83, 0x57, 0x20, 0x3d, 0x4a, 0xa0, 0x02, 0x2d,
-				0x87, 0x2e, 0xec, 0x40, 0x16, 0xff, 0xba, 0x03, 0x62, 0x1d, 0xa7, 0xf5, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x18, 0x16, 0xa4, 0xad, 0xcc, 0x0e, 0xfd, 0xbe, 0x5d, 0xf5, 0xbb,
-				0x2b, 0xbe, 0xc6, 0xfe, 0xb1, 0xbb, 0x63, 0x9c, 0x67, 0x37, 0xa2, 0xa6, 0xa6, 0xde, 0x6e, 0xa5,
-				0xed, 0x8d, 0x1b, 0x56, 0xd0, 0x31, 0x33, 0xc4, 0x1d, 0x37, 0x2d, 0xa1, 0x35, 0xfb, 0xd7, 0x9b,
-				0xfc, 0x24, 0x00, 0x72, 0xbe, 0x54, 0x2d, 0x89, 0xb7, 0x0a, 0x5c, 0xf5, 0xd8, 0xb5, 0x45, 0x43,
-				0xa2, 0xda, 0xed, 0xa5, 0xd8, 0x04, 0x1c, 0x50, 0x0a, 0x23, 0x55, 0x76, 0x9f, 0x8d, 0x8b, 0xa8,
-				0x1c, 0xee, 0x3d, 0x1a, 0xc5, 0xf4, 0x34, 0x5f, 0xd6, 0x18, 0xe4, 0xab, 0xaa, 0xe1, 0x5a, 0xe9,
-				0xec, 0x43, 0x9c, 0x77, 0x5e, 0x97, 0x36, 0x7c, 0x58, 0x05, 0xb7, 0x63, 0x21, 0x84, 0xfb, 0xc1,
-				0x6c, 0xe7, 0x11, 0x2d, 0xcb, 0x3f, 0x5c, 0xb8, 0x06, 0x28, 0x54, 0xe1, 0xb8, 0xf8, 0x8b, 0x62,
-				0x05, 0x41, 0xd2, 0xcd, 0xde, 0x60, 0xf1, 0xde, 0x11, 0x55, 0x27, 0x8c, 0xdb, 0xf4, 0x93, 0x70,
-				0x2e, 0x6f, 0xbd, 0x75, 0x7e, 0x75, 0xa9, 0x74, 0xba, 0xfc, 0xc2, 0xbd, 0x4c, 0xe5, 0xec, 0xfb,
-				0x10, 0x58, 0x7b, 0xe0, 0x81, 0xdb, 0x51, 0x87, 0xd6, 0xfe, 0xba, 0x44, 0xd9, 0x53, 0x48, 0x7b,
-				0x75, 0x6b, 0xc4, 0xdf, 0x83, 0xac, 0x50, 0xc4, 0x3d, 0x64, 0x00, 0x62, 0x14, 0xa5, 0x88, 0x8e,
-				0x14, 0xfb, 0x96, 0xe4, 0xa1, 0x6b, 0xee, 0xef, 0x7a, 0x69, 0x9f, 0x6f, 0x7c, 0xc9, 0x05, 0x44,
-				0xf6, 0x99, 0x0d, 0x33, 0x5b, 0x9a, 0x69, 0x72, 0x98, 0x29, 0x72, 0x54, 0x12, 0xdf, 0xa7, 0x65,
-				0xd6, 0xae, 0xe1, 0xa7, 0xfa, 0x76, 0x2a, 0xc5, 0xf9, 0xd7, 0xc9, 0xf2, 0x01, 0xac, 0xb0, 0xa3,
-				0x67, 0xe3, 0x8d, 0x24, 0xf3, 0x8b, 0x33, 0x72, 0x2e, 0x2a, 0x33, 0xeb, 0x5f, 0x81, 0x29, 0x48,
-				0x16, 0xf1, 0x15, 0x19, 0xf3, 0x02, 0x81, 0x81, 0x00, 0xfa, 0x20, 0x52, 0xcd, 0x71, 0x10, 0x76,
-				0x95, 0x0e, 0x3f, 0xf2, 0x60, 0xe3, 0x86, 0xce, 0x9b, 0xd3, 0x63, 0xc5, 0x06, 0x6c, 0x2e, 0xc7,
-				0x2c, 0x85, 0x51, 0xb1, 0x50, 0xf6, 0xa5, 0xc8, 0xe6, 0x1c, 0x9e, 0x1b, 0x2d, 0xfe, 0xa6, 0x05,
-				0xa1, 0x8f, 0x06, 0x9a, 0xc5, 0x39, 0xee, 0x68, 0xad, 0x41, 0x5d, 0x27, 0xd9, 0x06, 0xb8, 0x0a,
-				0x04, 0x06, 0x00, 0xbc, 0xf3, 0xca, 0xd6, 0xa8, 0xad, 0x4c, 0x41, 0x61, 0x1a, 0x30, 0xa3, 0xe6,
-				0xb0, 0x4e, 0x95, 0x9d, 0x8d, 0xd1, 0xf0, 0xe2, 0x47, 0x3c, 0x7e, 0xc1, 0x20, 0xd5, 0x84, 0x0c,
-				0x17, 0x67, 0x73, 0xc0, 0xb4, 0xb4, 0xf2, 0xf9, 0xac, 0x98, 0x8d, 0xca, 0x62, 0x04, 0x8e, 0x0a,
-				0xa3, 0x80, 0x63, 0xab, 0x4a, 0x57, 0xfb, 0xd6, 0x9b, 0x0c, 0x11, 0xa2, 0xef, 0x8f, 0xaf, 0x5d,
-				0x60, 0x01, 0x24, 0xac, 0x40, 0xd3, 0x6c, 0x60, 0x7f, 0x02, 0x81, 0x81, 0x00, 0xcb, 0x40, 0xaf,
-				0x73, 0xe3, 0x56, 0xd9, 0xbe, 0xa6, 0xb7, 0x16, 0x8e, 0x90, 0xc4, 0x10, 0x66, 0x47, 0x11, 0xcc,
-				0xbe, 0x69, 0xd3, 0x15, 0x7e, 0xde, 0x63, 0x04, 0x6e, 0xd6, 0xd9, 0x90, 0xbf, 0xfc, 0xa0, 0x4f,
-				0xc2, 0x2e, 0xa3, 0xf3, 0x42, 0x46, 0x61, 0x3c, 0x26, 0x1b, 0x3c, 0x0b, 0x80, 0xb2, 0x9c, 0xf5,
-				0xe2, 0x88, 0x1b, 0xcb, 0x4d, 0x45, 0x42, 0xed, 0xf8, 0x57, 0x89, 0x3a, 0x1f, 0x14, 0xf0, 0xb3,
-				0x8a, 0xaf, 0xe2, 0xca, 0x90, 0xc7, 0x88, 0x15, 0x8d, 0x52, 0xf7, 0xde, 0xbe, 0x61, 0x41, 0xda,
-				0x93, 0xda, 0x1e, 0xce, 0x09, 0x65, 0xcf, 0x12, 0x0e, 0x94, 0xf2, 0xd7, 0x7a, 0x69, 0x03, 0x45,
-				0x1b, 0x41, 0xf2, 0x1d, 0xbc, 0xd9, 0xea, 0x70, 0xdd, 0xe9, 0xbd, 0xc8, 0x02, 0x6e, 0x3f, 0xe1,
-				0x5f, 0x38, 0x6e, 0xf8, 0x91, 0xa7, 0x36, 0x4b, 0x2e, 0x39, 0x39, 0x3d, 0x8b, 0x02, 0x81, 0x80,
-				0x6b, 0xef, 0xb0, 0xeb, 0xb8, 0xc3, 0xca, 0xf8, 0x4d, 0x9a, 0xe8, 0xc4, 0x48, 0xcb, 0x2e, 0xb3,
-				0x6d, 0xc8, 0x5b, 0x08, 0x87, 0x7c, 0xb4, 0x34, 0x91, 0x1f, 0x8c, 0xae, 0x0c, 0x91, 0xc4, 0x1d,
-				0x10, 0xf2, 0x65, 0x76, 0x36, 0xb2, 0x7c, 0x31, 0x98, 0x9f, 0xd8, 0x00, 0x0e, 0x1c, 0xc4, 0x8d,
-				0x27, 0x6c, 0xc4, 0xba, 0x51, 0xbc, 0xef, 0x8d, 0x86, 0xed, 0xa0, 0x9c, 0x6f, 0xc6, 0xac, 0x29,
-				0x84, 0x83, 0x9e, 0x1c, 0x88, 0x2a, 0xe2, 0x6c, 0xe8, 0xac, 0x85, 0xbd, 0xe2, 0x7f, 0xd9, 0x95,
-				0xb6, 0x14, 0x58, 0xd1, 0x0b, 0x72, 0x9d, 0x29, 0x28, 0x5a, 0x7a, 0x29, 0x41, 0x00, 0xad, 0x1f,
-				0x7f, 0x01, 0x88, 0xf9, 0x3d, 0x4f, 0xf2, 0x65, 0x56, 0x0d, 0x2c, 0xa8, 0xbb, 0x49, 0x10, 0xf5,
-				0xfd, 0x82, 0x4a, 0xd6, 0xa8, 0x21, 0x9b, 0xe0, 0xc6, 0xfd, 0x85, 0x5b, 0xc0, 0x20, 0xbf, 0x8f,
-				0x02, 0x81, 0x80, 0x4c, 0x64, 0x6b, 0x8d, 0x6b, 0x0c, 0xe1, 0x9a, 0x3e, 0x9e, 0xe1, 0xe3, 0x83,
-				0x95, 0xad, 0x74, 0x43, 0x91, 0xf5, 0x1a, 0x3c, 0x3c, 0x12, 0x00, 0x35, 0x25, 0x92, 0x2c, 0xf6,
-				0xa3, 0x9f, 0x3c, 0x09, 0x7f, 0x57, 0x7a, 0xec, 0x7c, 0xc2, 0x99, 0x4e, 0x4a, 0x8d, 0x88, 0xe5,
-				0x03, 0x94, 0x6f, 0x32, 0xb2, 0xbb, 0xd8, 0x00, 0xc0, 0x31, 0x91, 0x41, 0x4e, 0xfe, 0x92, 0x30,
-				0x94, 0x6b, 0x3b, 0xf3, 0x6a, 0xe4, 0x90, 0x63, 0xbb, 0x21, 0xd7, 0x78, 0xa7, 0x35, 0x32, 0x80,
-				0xd4, 0x98, 0xeb, 0x85, 0x32, 0x73, 0x2c, 0xce, 0xf6, 0x75, 0x0a, 0x23, 0x31, 0xc8, 0xdf, 0xa2,
-				0x2c, 0x03, 0xc1, 0x06, 0x67, 0x2c, 0x3a, 0x2a, 0x77, 0x0d, 0xa6, 0x45, 0x61, 0x50, 0x3a, 0x97,
-				0xf7, 0xb4, 0x8c, 0xf5, 0x53, 0x1d, 0x29, 0xe4, 0xd4, 0x10, 0xa8, 0xed, 0xe8, 0x02, 0x29, 0xc5,
-				0x68, 0x36, 0x31, 0x02, 0x81, 0x80, 0x4f, 0x72, 0x4c, 0x82, 0x45, 0x35, 0x6f, 0xf8, 0xb8, 0x14,
-				0x8d, 0x8e, 0x61, 0x6f, 0xb1, 0xbc, 0xbe, 0x9d, 0xeb, 0xc9, 0x7c, 0xee, 0x2e, 0x9d, 0x1f, 0xef,
-				0x79, 0xc7, 0xc4, 0x4a, 0x63, 0x2b, 0x34, 0x51, 0xc7, 0xbc, 0xb0, 0xf8, 0x82, 0xc0, 0x25, 0xb4,
-				0x67, 0xa3, 0x56, 0xeb, 0x4f, 0x32, 0xa6, 0x61, 0xdf, 0x45, 0xb4, 0x81, 0x20, 0x3c, 0x59, 0x95,
-				0x8d, 0xfd, 0x4d, 0xdb, 0x6d, 0xb7, 0x58, 0xee, 0xdf, 0x6b, 0xa8, 0xee, 0xfc, 0x28, 0xff, 0xa0,
-				0x01, 0x38, 0xe1, 0xb8, 0xcc, 0xa3, 0x41, 0x69, 0x36, 0x06, 0x60, 0x8c, 0x82, 0x74, 0xbe, 0x74,
-				0xe2, 0x72, 0xb5, 0x31, 0xcc, 0x45, 0x31, 0x07, 0xa4, 0x7b, 0xc9, 0xd9, 0xa3, 0x4f, 0x42, 0x30,
-				0xe1, 0xbb, 0x67, 0x45, 0x82, 0x65, 0xd5, 0x50, 0x0d, 0x2a, 0x87, 0xe0, 0x4e, 0x04, 0x0b, 0xbe,
-				0xd8, 0x76, 0x3e, 0x55, 0x3b, 0xc3
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xc4, 0x0c, 0x94, 0xcf, 0xa8, 0x8e, 0x78, 0x76, 0xee, 0xcf, 0xea, 0x6a,
-				0xb5, 0x2d, 0x7e, 0xea, 0x3e, 0xdc, 0xd4, 0x6c, 0xd2, 0xe5, 0xdc, 0x8e, 0xe3, 0x0e, 0x7f, 0x02,
-				0x5b, 0xd1, 0xbd, 0xe4, 0x3d, 0xe4, 0x84, 0x4b, 0xc4, 0x63, 0xca, 0x5a, 0x42, 0x81, 0x02, 0xa8,
-				0x17, 0xd1, 0xb0, 0xa7, 0x43, 0x97, 0x6b, 0x29, 0xa1, 0x4b, 0xd1, 0x55, 0x78, 0x7f, 0xab, 0x85,
-				0x49, 0xe0, 0x43, 0xf5, 0x18, 0x4c, 0x8b, 0x24, 0x33, 0xd3, 0xc0, 0x90, 0xd1, 0xa8, 0x02, 0xe7,
-				0x55, 0xcb, 0xad, 0x48, 0x2c, 0x16, 0x44, 0xc1, 0x3e, 0x90, 0xf3, 0xa3, 0x22, 0x26, 0x96, 0x66,
-				0xcc, 0x8b, 0x39, 0x1f, 0xc2, 0x99, 0x5d, 0x4d, 0x59, 0x6f, 0x3c, 0x7e, 0xb1, 0x50, 0x9c, 0xb4,
-				0x49, 0xf7, 0xb6, 0x51, 0xdc, 0xbc, 0x2e, 0xff, 0x66, 0x27, 0x31, 0xe5, 0x69, 0x9e, 0x5a, 0x60,
-				0x07, 0x25, 0xed, 0x6e, 0xc1, 0xe4, 0xa3, 0x6f, 0x3f, 0x0d, 0x66, 0xf1, 0x01, 0x58, 0xdb, 0x10,
-				0x42, 0x61, 0x8e, 0x7f, 0x69, 0x66, 0xaf, 0x9e, 0xaf, 0x97, 0x6c, 0xab, 0x81, 0x9d, 0xb8, 0xb8,
-				0x58, 0x84, 0x6c, 0x74, 0x91, 0xe3, 0x57, 0x25, 0xbd, 0xd2, 0x48, 0xc6, 0xe7, 0x94, 0x5e, 0xf7,
-				0xe0, 0xa6, 0x1c, 0xcd, 0xb7, 0xa7, 0xa9, 0xdc, 0xb1, 0xc4, 0x93, 0x89, 0x48, 0x7a, 0x60, 0x3c,
-				0xe2, 0xe9, 0xc8, 0x20, 0xc7, 0x59, 0x67, 0x84, 0xd1, 0x1f, 0x09, 0x0e, 0x66, 0x29, 0x3e, 0x43,
-				0xd2, 0xa3, 0x25, 0xb9, 0xe8, 0x13, 0x01, 0x5b, 0x00, 0xbc, 0xfc, 0x50, 0xc9, 0x0a, 0x5f, 0x76,
-				0xb7, 0xa8, 0x3f, 0x91, 0xb2, 0xb4, 0xc0, 0xe5, 0x9d, 0xf6, 0x0e, 0xde, 0x51, 0x82, 0x4b, 0xc0,
-				0x8d, 0xb2, 0x59, 0x22, 0xc4, 0x9a, 0xc7, 0xa6, 0x55, 0xeb, 0x59, 0xb1, 0x84, 0x08, 0x35, 0x77,
-				0x84, 0x94, 0x9f, 0xb3
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x0c, 0x94, 0xcf,
-				0xa8, 0x8e, 0x78, 0x76, 0xee, 0xcf, 0xea, 0x6a, 0xb5, 0x2d, 0x7e, 0xea, 0x3e, 0xdc, 0xd4, 0x6c,
-				0xd2, 0xe5, 0xdc, 0x8e, 0xe3, 0x0e, 0x7f, 0x02, 0x5b, 0xd1, 0xbd, 0xe4, 0x3d, 0xe4, 0x84, 0x4b,
-				0xc4, 0x63, 0xca, 0x5a, 0x42, 0x81, 0x02, 0xa8, 0x17, 0xd1, 0xb0, 0xa7, 0x43, 0x97, 0x6b, 0x29,
-				0xa1, 0x4b, 0xd1, 0x55, 0x78, 0x7f, 0xab, 0x85, 0x49, 0xe0, 0x43, 0xf5, 0x18, 0x4c, 0x8b, 0x24,
-				0x33, 0xd3, 0xc0, 0x90, 0xd1, 0xa8, 0x02, 0xe7, 0x55, 0xcb, 0xad, 0x48, 0x2c, 0x16, 0x44, 0xc1,
-				0x3e, 0x90, 0xf3, 0xa3, 0x22, 0x26, 0x96, 0x66, 0xcc, 0x8b, 0x39, 0x1f, 0xc2, 0x99, 0x5d, 0x4d,
-				0x59, 0x6f, 0x3c, 0x7e, 0xb1, 0x50, 0x9c, 0xb4, 0x49, 0xf7, 0xb6, 0x51, 0xdc, 0xbc, 0x2e, 0xff,
-				0x66, 0x27, 0x31, 0xe5, 0x69, 0x9e, 0x5a, 0x60, 0x07, 0x25, 0xed, 0x6e, 0xc1, 0xe4, 0xa3, 0x6f,
-				0x3f, 0x0d, 0x66, 0xf1, 0x01, 0x58, 0xdb, 0x10, 0x42, 0x61, 0x8e, 0x7f, 0x69, 0x66, 0xaf, 0x9e,
-				0xaf, 0x97, 0x6c, 0xab, 0x81, 0x9d, 0xb8, 0xb8, 0x58, 0x84, 0x6c, 0x74, 0x91, 0xe3, 0x57, 0x25,
-				0xbd, 0xd2, 0x48, 0xc6, 0xe7, 0x94, 0x5e, 0xf7, 0xe0, 0xa6, 0x1c, 0xcd, 0xb7, 0xa7, 0xa9, 0xdc,
-				0xb1, 0xc4, 0x93, 0x89, 0x48, 0x7a, 0x60, 0x3c, 0xe2, 0xe9, 0xc8, 0x20, 0xc7, 0x59, 0x67, 0x84,
-				0xd1, 0x1f, 0x09, 0x0e, 0x66, 0x29, 0x3e, 0x43, 0xd2, 0xa3, 0x25, 0xb9, 0xe8, 0x13, 0x01, 0x5b,
-				0x00, 0xbc, 0xfc, 0x50, 0xc9, 0x0a, 0x5f, 0x76, 0xb7, 0xa8, 0x3f, 0x91, 0xb2, 0xb4, 0xc0, 0xe5,
-				0x9d, 0xf6, 0x0e, 0xde, 0x51, 0x82, 0x4b, 0xc0, 0x8d, 0xb2, 0x59, 0x22, 0xc4, 0x9a, 0xc7, 0xa6,
-				0x55, 0xeb, 0x59, 0xb1, 0x84, 0x08, 0x35, 0x77, 0x84, 0x94, 0x9f, 0xb3, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x81, 0xff, 0x71, 0xfa, 0x33, 0xdf, 0x31, 0x4a, 0x4d, 0xbe, 0xd7, 0x6d, 0xb4, 0x06,
-				0x00, 0x4f, 0x48, 0x4f, 0x3c, 0x92, 0x26, 0x43, 0x1e, 0x59, 0x84, 0xb6, 0x38, 0x4b, 0x5f, 0xe1,
-				0x29, 0xd5, 0xf1, 0x65, 0x95, 0xeb, 0x6f, 0xa9, 0x47, 0xae, 0xbc, 0x76, 0x12, 0x89, 0x43, 0xd7,
-				0x76, 0x01, 0x9d, 0x87, 0xa0, 0xee, 0xe7, 0x33, 0xcc, 0xbd, 0x1c, 0xcc, 0x14, 0x17, 0x7a, 0xcb,
-				0x2d, 0xa8, 0x09, 0xda, 0x49, 0xc6, 0x36, 0x74, 0x00, 0x58, 0x46, 0x1b, 0xeb, 0xc7, 0xec, 0x92,
-				0xe7, 0x23, 0xad, 0x6f, 0xc8, 0x31, 0xd4, 0xc7, 0x2f, 0x18, 0xc1, 0x37, 0x41, 0x23, 0x83, 0x4d,
-				0x40, 0x9d, 0xb0, 0x6d, 0x9b, 0xdf, 0xe3, 0x33, 0xea, 0x4a, 0xec, 0x0b, 0x66, 0xb5, 0xa1, 0xba,
-				0x84, 0x9b, 0xa9, 0xe3, 0x98, 0x9b, 0xcf, 0x61, 0xac, 0x82, 0x1d, 0x00, 0x18, 0x92, 0x22, 0x4e,
-				0x07, 0x2f, 0x30, 0x59, 0xaf, 0x01, 0x27, 0x02, 0x78, 0xdf, 0x2f, 0xff, 0x09, 0x21, 0xb6, 0x6d,
-				0x5a, 0x56, 0x2e, 0xa4, 0x32, 0x6b, 0xb8, 0xac, 0x71, 0x4b, 0x7a, 0x9c, 0x44, 0x6a, 0x61, 0x8e,
-				0x18, 0x56, 0x38, 0x70, 0x63, 0x7c, 0xae, 0x4e, 0x40, 0x5e, 0x72, 0x1b, 0xa1, 0xec, 0x22, 0xfe,
-				0x65, 0x66, 0x15, 0x13, 0x59, 0xd8, 0xfa, 0x75, 0x66, 0x29, 0xb4, 0x0f, 0xda, 0x75, 0xdd, 0x90,
-				0x0f, 0xbb, 0x29, 0x6a, 0xdf, 0x2a, 0x28, 0xd6, 0x7c, 0xd3, 0xa4, 0x45, 0x62, 0x74, 0x2f, 0x84,
-				0xe2, 0xbc, 0xa2, 0x70, 0xee, 0xf5, 0x13, 0xbb, 0x03, 0x7c, 0x5b, 0x34, 0xcd, 0x2d, 0xe5, 0x14,
-				0x6a, 0xc9, 0x07, 0x35, 0x49, 0x56, 0xaf, 0xf9, 0x7c, 0x96, 0xfe, 0x3d, 0x8f, 0xa2, 0xd8, 0x2d,
-				0xe4, 0x25, 0x7e, 0xd9, 0xfa, 0xa1, 0x73, 0x81, 0x4a, 0xe4, 0xb5, 0x85, 0x8e, 0xcf, 0x75, 0x60,
-				0x4c, 0xaf, 0xa5, 0x02, 0x81, 0x81, 0x00, 0xef, 0x04, 0x58, 0x13, 0x51, 0x21, 0x8d, 0xb3, 0x56,
-				0xc7, 0x5b, 0x05, 0xa6, 0x5d, 0x7e, 0xca, 0xe1, 0xbe, 0x08, 0x46, 0xa5, 0x1b, 0x9a, 0x0e, 0x81,
-				0xab, 0x3c, 0x7a, 0xad, 0xe5, 0xe2, 0x79, 0xfc, 0xfc, 0xda, 0x12, 0xe0, 0xf4, 0x87, 0x66, 0x09,
-				0x75, 0x22, 0xe5, 0xe8, 0x28, 0x0b, 0x27, 0x19, 0x7c, 0xb8, 0xd0, 0x65, 0x07, 0x9d, 0x8b, 0xf4,
-				0x5d, 0x8c, 0x5c, 0x79, 0xe5, 0xe0, 0x98, 0x4d, 0x44, 0x11, 0x10, 0x34, 0xae, 0xbc, 0xe4, 0x09,
-				0x03, 0xb7, 0x9c, 0x51, 0x47, 0x04, 0xe1, 0x9a, 0x5e, 0x71, 0x20, 0xbe, 0x47, 0xf8, 0x19, 0xfd,
-				0xf4, 0xc5, 0xce, 0x26, 0xd3, 0xb9, 0xe0, 0xed, 0x7a, 0x24, 0x25, 0x94, 0xa6, 0xd0, 0x1e, 0xd3,
-				0x87, 0xd8, 0x00, 0xbb, 0x36, 0xcd, 0x2a, 0x9c, 0x10, 0xc3, 0x7a, 0x19, 0xbb, 0x7c, 0xec, 0x50,
-				0x9e, 0xf9, 0x2f, 0x7d, 0x56, 0x14, 0x75, 0x02, 0x81, 0x81, 0x00, 0xd1, 0xfa, 0xa9, 0xef, 0xec,
-				0xfa, 0x7b, 0x26, 0xeb, 0xff, 0x27, 0xee, 0x67, 0x19, 0xc9, 0xcb, 0x62, 0x92, 0x25, 0x9a, 0xd7,
-				0x39, 0x29, 0xa3, 0x74, 0xdd, 0x96, 0xf3, 0xbe, 0xdf, 0x5b, 0xa2, 0xf5, 0x59, 0x9c, 0xad, 0x7f,
-				0x1c, 0x32, 0xa7, 0x8a, 0xa5, 0xcb, 0x8d, 0x2f, 0x25, 0x3c, 0xb2, 0x33, 0x15, 0x72, 0xab, 0xe6,
-				0xc2, 0x84, 0xa7, 0x3a, 0x8f, 0x68, 0x55, 0x7f, 0xba, 0xfd, 0xec, 0xc1, 0x52, 0xeb, 0x3c, 0x2b,
-				0x7e, 0x1f, 0x46, 0xb3, 0x0c, 0x76, 0xef, 0x0d, 0x1a, 0x71, 0xf4, 0x47, 0xdc, 0x1b, 0x3a, 0x63,
-				0xe9, 0xa1, 0x44, 0x91, 0xa8, 0xe6, 0x54, 0x08, 0x9a, 0xfe, 0xad, 0xa6, 0x30, 0x0c, 0xdf, 0xd8,
-				0x2d, 0x73, 0xc9, 0xb8, 0x19, 0x49, 0xec, 0xff, 0x80, 0xe6, 0xd9, 0x3d, 0xc8, 0xa1, 0x9c, 0x31,
-				0x2e, 0x6d, 0x1d, 0x09, 0x8f, 0x0c, 0x5f, 0x60, 0xdd, 0xbe, 0x87, 0x02, 0x81, 0x80, 0x3c, 0xf1,
-				0x38, 0x9b, 0xc4, 0x45, 0xef, 0xe1, 0x58, 0x31, 0x00, 0x6e, 0x52, 0x5a, 0xe8, 0x67, 0x46, 0x63,
-				0xb3, 0xac, 0x7f, 0x90, 0xa8, 0x19, 0x26, 0xca, 0xc8, 0x62, 0xe7, 0x50, 0x04, 0x0c, 0xe2, 0x8a,
-				0x7d, 0xf7, 0xee, 0x4f, 0xaa, 0xee, 0x43, 0x5f, 0x10, 0x84, 0xda, 0x4a, 0xcb, 0x7d, 0x2e, 0xac,
-				0x74, 0x5a, 0xfe, 0x47, 0x90, 0xce, 0x0c, 0x82, 0x85, 0xb5, 0x56, 0x87, 0x5c, 0x5a, 0xb8, 0xe8,
-				0xb0, 0x09, 0x17, 0xc5, 0xad, 0xf7, 0xde, 0xac, 0x89, 0xf6, 0x5b, 0x6a, 0xe6, 0x3d, 0xb7, 0xa4,
-				0x78, 0xe7, 0xc6, 0x5c, 0x87, 0x4f, 0xe9, 0x46, 0xad, 0xe0, 0xc0, 0x59, 0x9f, 0xbd, 0x50, 0x0f,
-				0xa2, 0x83, 0xca, 0x81, 0x35, 0xf3, 0x86, 0x2f, 0xce, 0xcd, 0x70, 0xee, 0xaa, 0x25, 0x41, 0x21,
-				0xad, 0x15, 0xc6, 0xd5, 0xdd, 0x26, 0x4b, 0xf0, 0x1c, 0xcd, 0x15, 0x02, 0x0b, 0xb9, 0x02, 0x81,
-				0x81, 0x00, 0xb0, 0x67, 0x97, 0xf0, 0xda, 0xf4, 0x2c, 0x16, 0x2c, 0xd9, 0xb5, 0xa0, 0x51, 0xb9,
-				0x96, 0x90, 0x69, 0x85, 0x42, 0x56, 0x6d, 0x4d, 0xb6, 0xaf, 0x7d, 0xf4, 0xd3, 0x66, 0x7f, 0x0a,
-				0x82, 0x9f, 0xca, 0xe3, 0xb7, 0xff, 0x01, 0xf4, 0x9c, 0x91, 0xa8, 0xa7, 0x54, 0xf4, 0x8d, 0x91,
-				0x09, 0x06, 0xe4, 0x67, 0xb6, 0x68, 0xb8, 0x7a, 0xde, 0x9a, 0xe7, 0x55, 0xa7, 0x5f, 0x7c, 0xe9,
-				0x89, 0x7e, 0x27, 0x84, 0x13, 0xdf, 0xfe, 0xe1, 0xfc, 0x40, 0x97, 0x17, 0x77, 0xab, 0xa9, 0x24,
-				0x78, 0x6b, 0xb3, 0x1b, 0x35, 0x3c, 0xbe, 0xc7, 0x7e, 0x16, 0x6f, 0x10, 0xa8, 0x40, 0x1c, 0xe2,
-				0xa9, 0xe7, 0x14, 0xe0, 0xf5, 0x4f, 0xf0, 0xfb, 0x6e, 0x75, 0x1f, 0x57, 0x0f, 0x86, 0x2d, 0xb9,
-				0x0b, 0x37, 0xa2, 0xf2, 0x34, 0xe3, 0x55, 0x66, 0x1d, 0x80, 0xf1, 0x90, 0xdd, 0xe2, 0x1b, 0x2c,
-				0xef, 0x6d, 0x02, 0x81, 0x81, 0x00, 0xb4, 0x55, 0xa9, 0x1b, 0x92, 0x42, 0x09, 0x21, 0x81, 0x24,
-				0x4a, 0xf9, 0x85, 0x5d, 0x07, 0x87, 0x54, 0xe3, 0xcc, 0x62, 0x1d, 0x28, 0x6d, 0x95, 0x99, 0x23,
-				0x5d, 0x2f, 0xa7, 0x61, 0x68, 0x43, 0xd7, 0xa0, 0x8f, 0xf8, 0x6b, 0x78, 0xed, 0x29, 0x8e, 0x54,
-				0xef, 0x55, 0x58, 0x87, 0x39, 0xbf, 0xb1, 0x9d, 0xb7, 0x61, 0x08, 0x35, 0x90, 0xe9, 0x2d, 0x95,
-				0xbf, 0x6a, 0x6d, 0xab, 0xb7, 0xcb, 0x44, 0x8f, 0xa7, 0x5d, 0x6c, 0x97, 0x69, 0x75, 0xfa, 0x8f,
-				0xc3, 0x20, 0x5f, 0xea, 0xb8, 0xd8, 0x8a, 0xd1, 0xf6, 0x0a, 0x49, 0xc9, 0xaf, 0xff, 0x79, 0xc7,
-				0x0a, 0xe0, 0xe1, 0x9a, 0xfa, 0x04, 0x7e, 0x72, 0x32, 0xad, 0x86, 0xbe, 0x2e, 0xe9, 0xc3, 0xc9,
-				0xdd, 0x5a, 0xd2, 0x0e, 0x7f, 0xb2, 0xef, 0x44, 0x68, 0xc8, 0x27, 0x92, 0xfc, 0xea, 0x43, 0x63,
-				0x00, 0x6c, 0xbf, 0xc7, 0x5c, 0xa6
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0x8e, 0xa0, 0x5e, 0xea, 0xb3, 0xeb, 0x42, 0xfd, 0x69, 0x9c, 0xcc, 0x18,
-				0x8a, 0xe0, 0x67, 0x04, 0x6f, 0xdd, 0xb8, 0x8f, 0x63, 0xcb, 0xa9, 0x58, 0x9d, 0x7d, 0xdf, 0x5b,
-				0x67, 0xcc, 0x0e, 0xde, 0x69, 0xd1, 0x13, 0x0d, 0x78, 0xff, 0x18, 0x1a, 0xe5, 0xd0, 0x6a, 0x14,
-				0xb3, 0x39, 0x37, 0xd2, 0xd1, 0x8f, 0x85, 0x5d, 0xa9, 0x3c, 0x62, 0x92, 0xe1, 0xc5, 0xe9, 0xe9,
-				0x9a, 0x42, 0x89, 0xb7, 0x87, 0x8a, 0x56, 0x9a, 0x06, 0x0d, 0x01, 0xd8, 0xb2, 0x85, 0xe3, 0x64,
-				0x5e, 0x86, 0x66, 0x6f, 0x21, 0x97, 0xdf, 0x6f, 0xaf, 0xe4, 0x7c, 0x4f, 0xa6, 0x5c, 0x2b, 0x91,
-				0xd1, 0x51, 0x7d, 0x4d, 0x29, 0xc9, 0x6c, 0x6c, 0x9d, 0x7e, 0x02, 0xd7, 0x61, 0xe3, 0xf1, 0x7a,
-				0x66, 0x3b, 0x77, 0x8a, 0xd3, 0x6c, 0xa6, 0xfc, 0x44, 0xb5, 0x8d, 0xfe, 0x0f, 0xd7, 0x0b, 0x37,
-				0x0f, 0x2e, 0x39, 0x2c, 0xa9, 0xf7, 0x55, 0xb6, 0x78, 0x17, 0xd1, 0x49, 0x56, 0xac, 0x87, 0x79,
-				0x9c, 0xa4, 0x48, 0x95, 0xcc, 0x3c, 0x51, 0xee, 0x91, 0x31, 0x09, 0x13, 0x4a, 0xb7, 0x58, 0x71,
-				0x4d, 0xd9, 0xf7, 0x95, 0x66, 0x6a, 0xbf, 0x31, 0xcf, 0x15, 0x53, 0xfa, 0x6f, 0x7b, 0xa4, 0x88,
-				0x2e, 0x08, 0x87, 0x40, 0x99, 0xfd, 0x79, 0xdd, 0x82, 0x6f, 0xc0, 0xda, 0x6c, 0x62, 0x07, 0x5e,
-				0x19, 0xbc, 0x83, 0x05, 0x8b, 0xb3, 0x02, 0x64, 0x64, 0xdc, 0x7d, 0x3d, 0x32, 0x87, 0x5f, 0x25,
-				0xe1, 0xee, 0x6b, 0x97, 0x27, 0x94, 0x0a, 0xd5, 0xb2, 0xba, 0x43, 0x24, 0x40, 0x26, 0x70, 0x30,
-				0xf1, 0x77, 0x28, 0x87, 0xba, 0x5c, 0x10, 0x33, 0x6d, 0x10, 0x34, 0xbf, 0xbb, 0x77, 0x31, 0x4d,
-				0xa7, 0x1c, 0x4b, 0x8f, 0x2f, 0x7c, 0x14, 0x00, 0x0f, 0xb4, 0xc8, 0x29, 0x02, 0x54, 0xeb, 0x2b,
-				0x0c, 0xf6, 0x85, 0xa7
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x8e, 0xa0, 0x5e, 0xea,
-				0xb3, 0xeb, 0x42, 0xfd, 0x69, 0x9c, 0xcc, 0x18, 0x8a, 0xe0, 0x67, 0x04, 0x6f, 0xdd, 0xb8, 0x8f,
-				0x63, 0xcb, 0xa9, 0x58, 0x9d, 0x7d, 0xdf, 0x5b, 0x67, 0xcc, 0x0e, 0xde, 0x69, 0xd1, 0x13, 0x0d,
-				0x78, 0xff, 0x18, 0x1a, 0xe5, 0xd0, 0x6a, 0x14, 0xb3, 0x39, 0x37, 0xd2, 0xd1, 0x8f, 0x85, 0x5d,
-				0xa9, 0x3c, 0x62, 0x92, 0xe1, 0xc5, 0xe9, 0xe9, 0x9a, 0x42, 0x89, 0xb7, 0x87, 0x8a, 0x56, 0x9a,
-				0x06, 0x0d, 0x01, 0xd8, 0xb2, 0x85, 0xe3, 0x64, 0x5e, 0x86, 0x66, 0x6f, 0x21, 0x97, 0xdf, 0x6f,
-				0xaf, 0xe4, 0x7c, 0x4f, 0xa6, 0x5c, 0x2b, 0x91, 0xd1, 0x51, 0x7d, 0x4d, 0x29, 0xc9, 0x6c, 0x6c,
-				0x9d, 0x7e, 0x02, 0xd7, 0x61, 0xe3, 0xf1, 0x7a, 0x66, 0x3b, 0x77, 0x8a, 0xd3, 0x6c, 0xa6, 0xfc,
-				0x44, 0xb5, 0x8d, 0xfe, 0x0f, 0xd7, 0x0b, 0x37, 0x0f, 0x2e, 0x39, 0x2c, 0xa9, 0xf7, 0x55, 0xb6,
-				0x78, 0x17, 0xd1, 0x49, 0x56, 0xac, 0x87, 0x79, 0x9c, 0xa4, 0x48, 0x95, 0xcc, 0x3c, 0x51, 0xee,
-				0x91, 0x31, 0x09, 0x13, 0x4a, 0xb7, 0x58, 0x71, 0x4d, 0xd9, 0xf7, 0x95, 0x66, 0x6a, 0xbf, 0x31,
-				0xcf, 0x15, 0x53, 0xfa, 0x6f, 0x7b, 0xa4, 0x88, 0x2e, 0x08, 0x87, 0x40, 0x99, 0xfd, 0x79, 0xdd,
-				0x82, 0x6f, 0xc0, 0xda, 0x6c, 0x62, 0x07, 0x5e, 0x19, 0xbc, 0x83, 0x05, 0x8b, 0xb3, 0x02, 0x64,
-				0x64, 0xdc, 0x7d, 0x3d, 0x32, 0x87, 0x5f, 0x25, 0xe1, 0xee, 0x6b, 0x97, 0x27, 0x94, 0x0a, 0xd5,
-				0xb2, 0xba, 0x43, 0x24, 0x40, 0x26, 0x70, 0x30, 0xf1, 0x77, 0x28, 0x87, 0xba, 0x5c, 0x10, 0x33,
-				0x6d, 0x10, 0x34, 0xbf, 0xbb, 0x77, 0x31, 0x4d, 0xa7, 0x1c, 0x4b, 0x8f, 0x2f, 0x7c, 0x14, 0x00,
-				0x0f, 0xb4, 0xc8, 0x29, 0x02, 0x54, 0xeb, 0x2b, 0x0c, 0xf6, 0x85, 0xa7, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x12, 0xc4, 0xa7, 0xb8, 0xda, 0xd4, 0x2a, 0x8c, 0x8e, 0x49, 0x43,
-				0xd2, 0x36, 0xf4, 0x30, 0x9a, 0x34, 0xde, 0x48, 0x5b, 0x16, 0x16, 0xc6, 0xc2, 0x12, 0x77, 0x6d,
-				0xdc, 0xe9, 0x5b, 0xc0, 0xd9, 0x23, 0xb3, 0x8f, 0x7e, 0x46, 0x5d, 0xcb, 0x1e, 0x3e, 0xff, 0x9d,
-				0xf5, 0xfb, 0x5f, 0x9c, 0x28, 0xf1, 0xca, 0xa1, 0x12, 0x22, 0x23, 0x00, 0x15, 0xb4, 0x00, 0x07,
-				0x37, 0xe6, 0x44, 0xbb, 0x3a, 0x9b, 0x6b, 0x68, 0xd9, 0xfb, 0xd1, 0xda, 0x5c, 0x59, 0xa1, 0xa4,
-				0xba, 0xa0, 0x75, 0xaf, 0x25, 0x10, 0x96, 0x9b, 0xa0, 0x66, 0xd4, 0xfa, 0x46, 0xc0, 0xed, 0x80,
-				0x0e, 0x40, 0x2d, 0x28, 0xff, 0xee, 0x6f, 0xc3, 0x04, 0xc7, 0xf4, 0xbd, 0x0a, 0xfa, 0xa6, 0xb4,
-				0x30, 0x17, 0x23, 0xdc, 0x27, 0x38, 0x8b, 0x23, 0xae, 0x2e, 0x9c, 0x75, 0x82, 0xe9, 0x32, 0xb3,
-				0x17, 0x1b, 0xb8, 0x49, 0x6d, 0x94, 0xe1, 0x1c, 0x13, 0x92, 0xf4, 0x42, 0xab, 0x62, 0x6b, 0x62,
-				0x74, 0x2e, 0x1c, 0x0a, 0x07, 0x3f, 0x43, 0x01, 0x53, 0x35, 0x7b, 0xc8, 0x22, 0xb7, 0x14, 0x7e,
-				0x2f, 0x57, 0x4d, 0x98, 0x14, 0x1c, 0x80, 0xbe, 0xc8, 0x2b, 0xd6, 0xd7, 0x22, 0xf0, 0xb1, 0xae,
-				0xac, 0x81, 0x93, 0x47, 0x51, 0x2d, 0x4f, 0xfc, 0xf2, 0xb1, 0x94, 0xbf, 0x73, 0x5b, 0x2b, 0xf8,
-				0x67, 0xd8, 0x0b, 0x00, 0x2a, 0x06, 0x3a, 0x37, 0x30, 0x71, 0xe0, 0x20, 0xb8, 0xa3, 0xf1, 0x62,
-				0x12, 0xea, 0x55, 0x52, 0x7d, 0xcf, 0x93, 0xac, 0xf1, 0x80, 0xfe, 0x79, 0x12, 0x23, 0xa8, 0xd3,
-				0x92, 0x71, 0x51, 0x22, 0x64, 0xb5, 0x22, 0x9d, 0x8b, 0x38, 0x52, 0x9c, 0x4a, 0x9d, 0x77, 0x3d,
-				0x45, 0x02, 0x74, 0x4d, 0x6e, 0x2b, 0x70, 0x7f, 0x73, 0x30, 0xc2, 0xa6, 0x8d, 0xe8, 0x7d, 0x13,
-				0x61, 0x63, 0x03, 0x42, 0x01, 0x02, 0x81, 0x81, 0x00, 0xc4, 0x6b, 0x81, 0xad, 0xa2, 0x14, 0xd8,
-				0x29, 0x99, 0x34, 0x3f, 0x44, 0xd6, 0xbd, 0x39, 0x7e, 0x48, 0x3a, 0x64, 0xe1, 0x7d, 0x97, 0x68,
-				0x36, 0x65, 0xc1, 0x8c, 0xa1, 0x38, 0x62, 0x7b, 0x23, 0x89, 0xb5, 0xc1, 0x88, 0xa6, 0xb4, 0xe0,
-				0x75, 0x98, 0x0f, 0x02, 0x7d, 0x4c, 0x4e, 0xab, 0xc2, 0x3b, 0x16, 0x9c, 0x29, 0xdf, 0xc0, 0xf6,
-				0xee, 0x1a, 0xc8, 0xfa, 0xc2, 0x01, 0x71, 0xc7, 0x2e, 0x7f, 0x72, 0x64, 0xe3, 0x22, 0xa6, 0x7f,
-				0xb1, 0xd0, 0x8a, 0x21, 0xe0, 0xd9, 0x1c, 0x92, 0xf1, 0xc5, 0x82, 0xe9, 0x27, 0x20, 0x2a, 0x8e,
-				0xa4, 0x76, 0x9b, 0x42, 0x58, 0x96, 0x2a, 0x2a, 0x5d, 0xb0, 0x8c, 0xdd, 0x7e, 0xf0, 0xf1, 0xa7,
-				0x7e, 0xbb, 0xf2, 0x21, 0xe6, 0xbf, 0xc1, 0x30, 0xf3, 0x79, 0x0e, 0x0e, 0x12, 0x19, 0x04, 0x73,
-				0x1a, 0x4c, 0x3c, 0x52, 0x21, 0xbe, 0x98, 0x2a, 0xb7, 0x02, 0x81, 0x81, 0x00, 0xb9, 0xe3, 0xaa,
-				0x93, 0x13, 0x85, 0xe4, 0xb6, 0x26, 0x3b, 0xd1, 0x7b, 0x0c, 0xaa, 0x05, 0xf8, 0x5e, 0x2e, 0x8d,
-				0xe0, 0x3a, 0x93, 0x86, 0x4f, 0x61, 0xa8, 0xb2, 0x86, 0xc7, 0x30, 0xbc, 0x83, 0x4c, 0xa6, 0xe1,
-				0xd9, 0x49, 0xa7, 0x21, 0x89, 0x5b, 0xcc, 0x97, 0xa5, 0xb5, 0x8f, 0xcc, 0x29, 0xb1, 0x08, 0xc2,
-				0x13, 0x25, 0x12, 0xf9, 0x2d, 0x8c, 0x09, 0x81, 0xcf, 0x60, 0x66, 0x83, 0x2b, 0xdf, 0xf4, 0xb3,
-				0x09, 0x4d, 0x1e, 0x2a, 0x67, 0x9f, 0x6f, 0x86, 0x48, 0xf0, 0xd3, 0xd7, 0x20, 0xcf, 0x43, 0x1a,
-				0xe0, 0xfa, 0x93, 0xae, 0x4e, 0x7d, 0x39, 0xbf, 0x52, 0x46, 0x4b, 0xee, 0xca, 0xd2, 0xf8, 0xea,
-				0x19, 0xf3, 0x65, 0xa8, 0x68, 0x9a, 0xc6, 0x48, 0xfb, 0x92, 0x89, 0xa7, 0x1f, 0x02, 0xef, 0xd6,
-				0x53, 0x1f, 0x5c, 0x85, 0xf6, 0x0a, 0xc9, 0x67, 0x36, 0x3c, 0xa8, 0x4c, 0x91, 0x02, 0x81, 0x80,
-				0x4c, 0x06, 0x28, 0x5d, 0x22, 0x3c, 0xdb, 0x25, 0xce, 0xac, 0x90, 0x48, 0x7e, 0xad, 0x22, 0xd1,
-				0xa3, 0xf7, 0x26, 0x10, 0xb8, 0xe1, 0x9f, 0x6e, 0x5e, 0x98, 0x39, 0x6c, 0x35, 0x3c, 0xb8, 0xd8,
-				0x9a, 0x76, 0x84, 0xff, 0xf5, 0x36, 0x51, 0x22, 0x72, 0xc6, 0x6c, 0x7a, 0x3e, 0xcc, 0xbc, 0x62,
-				0x23, 0x28, 0xaf, 0x2c, 0xed, 0xf3, 0xec, 0x1f, 0x60, 0xb2, 0xa5, 0x8b, 0xed, 0xaf, 0x32, 0x1e,
-				0xe7, 0x29, 0x49, 0xaf, 0x38, 0x3c, 0x25, 0x74, 0x97, 0x78, 0xbf, 0x80, 0x1d, 0xc8, 0x97, 0x7f,
-				0x88, 0xa9, 0x10, 0xc1, 0x1a, 0x0c, 0x1e, 0xc5, 0xbd, 0x3a, 0x7e, 0xc5, 0x76, 0xe9, 0xbf, 0x18,
-				0x20, 0x3b, 0x85, 0x87, 0x9a, 0x8e, 0x8d, 0xfb, 0xd9, 0x96, 0xf0, 0x54, 0x35, 0xa7, 0xfa, 0xe0,
-				0x61, 0xdc, 0x74, 0xc9, 0xc0, 0x71, 0x1e, 0x73, 0xf1, 0x49, 0xef, 0xa8, 0x2b, 0xf3, 0x0d, 0xa5,
-				0x02, 0x81, 0x80, 0x07, 0xbc, 0xda, 0x54, 0xd4, 0xf3, 0x35, 0xd9, 0xff, 0x2d, 0x6e, 0x42, 0xd8,
-				0xfc, 0x1a, 0xd3, 0x83, 0xd8, 0x1c, 0x3f, 0xc1, 0x30, 0x72, 0xde, 0xcb, 0x09, 0xe2, 0xa4, 0x89,
-				0x96, 0x15, 0xc2, 0xc1, 0x66, 0x10, 0xf0, 0xa2, 0x88, 0x3a, 0x75, 0x25, 0x45, 0x16, 0xea, 0xe6,
-				0xeb, 0xdd, 0x6b, 0xbe, 0xda, 0xc6, 0x79, 0x55, 0x89, 0xbc, 0xa5, 0x90, 0xb6, 0xb4, 0x98, 0x95,
-				0x42, 0xaf, 0x23, 0x1c, 0x67, 0x6b, 0x2c, 0x6f, 0xf1, 0x59, 0x82, 0x86, 0xb8, 0x75, 0xb6, 0x83,
-				0x8f, 0xcd, 0xdc, 0xa7, 0xc3, 0xfb, 0x52, 0x72, 0x1b, 0xc3, 0x9d, 0xb0, 0xc8, 0xbe, 0x96, 0x06,
-				0x27, 0x13, 0x01, 0x8e, 0x56, 0x9e, 0x28, 0x06, 0x61, 0xac, 0xe8, 0xed, 0xc8, 0x63, 0x31, 0x55,
-				0xa0, 0x35, 0x3c, 0xad, 0x3a, 0x9e, 0x89, 0x47, 0x3c, 0xea, 0xb6, 0x9b, 0x2c, 0x57, 0x07, 0x82,
-				0xee, 0xde, 0x81, 0x02, 0x81, 0x80, 0x70, 0xbf, 0x51, 0x43, 0x70, 0x8c, 0x33, 0xde, 0x32, 0x51,
-				0x5c, 0x69, 0xc5, 0x22, 0xe5, 0x4f, 0x9b, 0x02, 0xaa, 0x11, 0x0c, 0x71, 0x1a, 0x3d, 0xfa, 0xfc,
-				0x66, 0x40, 0xf8, 0xe9, 0x05, 0xcd, 0x47, 0x44, 0xb1, 0xbf, 0xbd, 0xc2, 0x4e, 0xa5, 0x4f, 0x55,
-				0x9f, 0xaa, 0x5f, 0xf7, 0xce, 0xe7, 0xa9, 0x74, 0x4e, 0x44, 0xed, 0x32, 0x71, 0x81, 0xb4, 0xae,
-				0x07, 0x60, 0xcc, 0x6b, 0x7b, 0x89, 0x24, 0x2e, 0x51, 0xa8, 0xf9, 0x2c, 0xbd, 0xc8, 0x91, 0xcd,
-				0xd6, 0x3a, 0x29, 0x66, 0xf3, 0x64, 0xec, 0xd3, 0x58, 0xa8, 0xc9, 0x2e, 0x9a, 0x1c, 0x41, 0xdf,
-				0xf5, 0x49, 0xe4, 0x17, 0xe3, 0xaf, 0x48, 0xae, 0x03, 0xb2, 0x4d, 0xaf, 0x04, 0x76, 0x3f, 0x8a,
-				0x2c, 0xf5, 0x3c, 0xed, 0x67, 0xef, 0x1d, 0xe2, 0x4e, 0xf5, 0x27, 0x86, 0xd1, 0x32, 0x96, 0xbe,
-				0xf2, 0x12, 0x57, 0x13, 0xe1, 0xe6
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xa0, 0xee, 0xcd, 0x83, 0x3d, 0xd4, 0x51, 0x95, 0x00, 0x98, 0x86, 0x5d,
-				0xd8, 0xe6, 0xd1, 0xf4, 0xbb, 0x69, 0x17, 0x9c, 0xaf, 0xea, 0xfc, 0xa6, 0x5b, 0x9f, 0x6f, 0x50,
-				0x3b, 0x54, 0x73, 0x33, 0x63, 0xc1, 0x26, 0x9e, 0x7b, 0x92, 0xef, 0x34, 0xc2, 0x32, 0xbe, 0x5a,
-				0xa6, 0x64, 0x51, 0x94, 0x83, 0xb2, 0xa2, 0x2c, 0x5e, 0xa5, 0xdd, 0x05, 0x78, 0xb4, 0x69, 0x1b,
-				0xde, 0xc0, 0x4b, 0x18, 0x97, 0xe3, 0x66, 0x4a, 0x89, 0xfb, 0x0d, 0x63, 0x1c, 0xeb, 0x1d, 0x45,
-				0x99, 0xf8, 0x4b, 0xbf, 0xa3, 0x80, 0x96, 0x6c, 0xfa, 0x6d, 0xa9, 0x5d, 0xf4, 0x8e, 0x97, 0x01,
-				0xa1, 0x0b, 0x34, 0x32, 0x87, 0xee, 0x93, 0xb7, 0x9f, 0x88, 0x23, 0x9f, 0xef, 0x4d, 0xef, 0x96,
-				0xe2, 0x31, 0xa2, 0xe8, 0x03, 0x67, 0x16, 0x9b, 0x54, 0xe0, 0x1f, 0x29, 0xb6, 0x31, 0x7e, 0x55,
-				0xa2, 0x0d, 0xfb, 0x52, 0xb5, 0x9a, 0x3f, 0xe9, 0xcd, 0x28, 0xb2, 0xee, 0x72, 0xca, 0xfa, 0x41,
-				0xd6, 0x50, 0x1b, 0xd0, 0xf5, 0xe6, 0x40, 0x5f, 0x21, 0x50, 0x55, 0xbc, 0x94, 0x6a, 0x1a, 0x07,
-				0x33, 0x81, 0x9b, 0x83, 0xe8, 0xe2, 0x44, 0xfc, 0x2c, 0xc7, 0x6f, 0x29, 0x3d, 0x67, 0xca, 0x73,
-				0xcc, 0xe6, 0xeb, 0x8c, 0x3a, 0x8d, 0xe3, 0xfe, 0x43, 0x77, 0x4c, 0xac, 0x07, 0x18, 0x41, 0x0c,
-				0x9b, 0xe8, 0xf8, 0xc5, 0x6b, 0x3e, 0xd6, 0xe0, 0x18, 0x8f, 0x45, 0x7f, 0x85, 0xab, 0xdc, 0x47,
-				0xdd, 0xd8, 0x31, 0x26, 0x87, 0xf6, 0x8e, 0x4d, 0xd4, 0x4f, 0xda, 0xbf, 0xe8, 0xc7, 0x2b, 0x05,
-				0x08, 0xaf, 0x82, 0xea, 0xde, 0x5d, 0xe3, 0x59, 0x09, 0x60, 0xff, 0x1d, 0x35, 0x60, 0xf3, 0xe9,
-				0x9d, 0x11, 0xf2, 0x0b, 0xc4, 0x34, 0xb5, 0xb9, 0x6f, 0xdc, 0x4b, 0x77, 0x4c, 0x8d, 0x75, 0xed,
-				0x1b, 0xbf, 0x20, 0x4d
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa0, 0xee, 0xcd, 0x83,
-				0x3d, 0xd4, 0x51, 0x95, 0x00, 0x98, 0x86, 0x5d, 0xd8, 0xe6, 0xd1, 0xf4, 0xbb, 0x69, 0x17, 0x9c,
-				0xaf, 0xea, 0xfc, 0xa6, 0x5b, 0x9f, 0x6f, 0x50, 0x3b, 0x54, 0x73, 0x33, 0x63, 0xc1, 0x26, 0x9e,
-				0x7b, 0x92, 0xef, 0x34, 0xc2, 0x32, 0xbe, 0x5a, 0xa6, 0x64, 0x51, 0x94, 0x83, 0xb2, 0xa2, 0x2c,
-				0x5e, 0xa5, 0xdd, 0x05, 0x78, 0xb4, 0x69, 0x1b, 0xde, 0xc0, 0x4b, 0x18, 0x97, 0xe3, 0x66, 0x4a,
-				0x89, 0xfb, 0x0d, 0x63, 0x1c, 0xeb, 0x1d, 0x45, 0x99, 0xf8, 0x4b, 0xbf, 0xa3, 0x80, 0x96, 0x6c,
-				0xfa, 0x6d, 0xa9, 0x5d, 0xf4, 0x8e, 0x97, 0x01, 0xa1, 0x0b, 0x34, 0x32, 0x87, 0xee, 0x93, 0xb7,
-				0x9f, 0x88, 0x23, 0x9f, 0xef, 0x4d, 0xef, 0x96, 0xe2, 0x31, 0xa2, 0xe8, 0x03, 0x67, 0x16, 0x9b,
-				0x54, 0xe0, 0x1f, 0x29, 0xb6, 0x31, 0x7e, 0x55, 0xa2, 0x0d, 0xfb, 0x52, 0xb5, 0x9a, 0x3f, 0xe9,
-				0xcd, 0x28, 0xb2, 0xee, 0x72, 0xca, 0xfa, 0x41, 0xd6, 0x50, 0x1b, 0xd0, 0xf5, 0xe6, 0x40, 0x5f,
-				0x21, 0x50, 0x55, 0xbc, 0x94, 0x6a, 0x1a, 0x07, 0x33, 0x81, 0x9b, 0x83, 0xe8, 0xe2, 0x44, 0xfc,
-				0x2c, 0xc7, 0x6f, 0x29, 0x3d, 0x67, 0xca, 0x73, 0xcc, 0xe6, 0xeb, 0x8c, 0x3a, 0x8d, 0xe3, 0xfe,
-				0x43, 0x77, 0x4c, 0xac, 0x07, 0x18, 0x41, 0x0c, 0x9b, 0xe8, 0xf8, 0xc5, 0x6b, 0x3e, 0xd6, 0xe0,
-				0x18, 0x8f, 0x45, 0x7f, 0x85, 0xab, 0xdc, 0x47, 0xdd, 0xd8, 0x31, 0x26, 0x87, 0xf6, 0x8e, 0x4d,
-				0xd4, 0x4f, 0xda, 0xbf, 0xe8, 0xc7, 0x2b, 0x05, 0x08, 0xaf, 0x82, 0xea, 0xde, 0x5d, 0xe3, 0x59,
-				0x09, 0x60, 0xff, 0x1d, 0x35, 0x60, 0xf3, 0xe9, 0x9d, 0x11, 0xf2, 0x0b, 0xc4, 0x34, 0xb5, 0xb9,
-				0x6f, 0xdc, 0x4b, 0x77, 0x4c, 0x8d, 0x75, 0xed, 0x1b, 0xbf, 0x20, 0x4d, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x01, 0xa4, 0x06, 0x64, 0x3d, 0x65, 0x68, 0x49, 0x78, 0xf3, 0x85,
-				0xe5, 0xbe, 0x10, 0xda, 0xc0, 0x3e, 0xd0, 0xf0, 0x9a, 0x76, 0x00, 0x71, 0x70, 0xb4, 0xb3, 0xed,
-				0x80, 0x89, 0xd7, 0x74, 0x46, 0x06, 0xe3, 0x5d, 0xb2, 0x27, 0xb9, 0xf7, 0x2f, 0x9e, 0x8c, 0x6c,
-				0xad, 0x46, 0xd8, 0xa5, 0x3e, 0xcd, 0x01, 0x5b, 0x36, 0x69, 0xa9, 0xb6, 0x2a, 0x66, 0x51, 0x38,
-				0x74, 0x96, 0x70, 0x95, 0xfd, 0x51, 0x6c, 0xb9, 0xed, 0xc3, 0x73, 0x26, 0x23, 0x04, 0x76, 0x72,
-				0x77, 0x76, 0xba, 0x37, 0x48, 0xb9, 0x72, 0xcf, 0x94, 0x45, 0xf8, 0x87, 0xb2, 0x31, 0x64, 0xf7,
-				0x00, 0x16, 0x55, 0xb8, 0xc6, 0xb0, 0xde, 0xdf, 0xd8, 0xa4, 0x0f, 0xac, 0xa0, 0xd4, 0x4f, 0x67,
-				0xb5, 0x43, 0x76, 0xc9, 0xd2, 0xed, 0xf0, 0xb6, 0xa1, 0x47, 0x23, 0xa9, 0x7b, 0x01, 0x84, 0x62,
-				0x4d, 0x80, 0x51, 0x16, 0xc5, 0x3c, 0x5a, 0xae, 0x1f, 0xdd, 0x16, 0xae, 0x66, 0xf8, 0x48, 0x87,
-				0xc6, 0xe2, 0x05, 0x3b, 0x31, 0x15, 0x23, 0xdc, 0x89, 0x2c, 0xb3, 0xcc, 0xfe, 0x6b, 0x24, 0x06,
-				0x32, 0xdf, 0xfd, 0x00, 0x61, 0xa9, 0xe3, 0x56, 0xc7, 0x06, 0xe5, 0x86, 0x3f, 0x2b, 0x84, 0x32,
-				0x29, 0x17, 0xda, 0xa9, 0xc0, 0x12, 0x59, 0xc5, 0x02, 0x08, 0xb3, 0x2a, 0x71, 0x29, 0x3f, 0xaf,
-				0x8b, 0xa9, 0x08, 0xe8, 0x8c, 0x0b, 0x67, 0x94, 0x50, 0x3a, 0x92, 0x23, 0x83, 0x26, 0x4b, 0xcf,
-				0xe0, 0xa9, 0x46, 0xc6, 0xc1, 0x27, 0xbf, 0xc2, 0x6a, 0x18, 0x71, 0x2d, 0x59, 0xc6, 0xfc, 0x25,
-				0xe0, 0x04, 0x6b, 0x3e, 0xda, 0x85, 0xec, 0x78, 0x03, 0x31, 0x64, 0x6d, 0xc6, 0x24, 0xdf, 0xbd,
-				0x55, 0x2e, 0x65, 0x56, 0x5b, 0x1f, 0x6e, 0x09, 0x70, 0x75, 0x5a, 0xcf, 0x2d, 0xcc, 0xa3, 0xe7,
-				0xa2, 0x1e, 0xe1, 0x85, 0x21, 0x02, 0x81, 0x81, 0x00, 0xe1, 0x8d, 0xf2, 0x86, 0xf3, 0xf2, 0x88,
-				0xc6, 0xa3, 0x65, 0x67, 0x49, 0x06, 0x52, 0x54, 0x2a, 0xb8, 0xe9, 0x5a, 0x53, 0x5d, 0x65, 0xb8,
-				0x6e, 0xea, 0x23, 0x1b, 0x6d, 0x26, 0xfd, 0xa1, 0x0f, 0x3f, 0x7e, 0xb0, 0x25, 0xbb, 0x16, 0x89,
-				0xef, 0x30, 0xab, 0xea, 0x6d, 0x9f, 0x4d, 0x0b, 0x86, 0xcd, 0x5f, 0xa1, 0x89, 0x5d, 0x1f, 0x1f,
-				0xb4, 0xd7, 0x2a, 0xbc, 0xd2, 0x97, 0x44, 0x42, 0xc6, 0x5a, 0x21, 0x38, 0xbd, 0x30, 0x64, 0xbf,
-				0x2d, 0x06, 0x10, 0x41, 0xe7, 0xdc, 0xbd, 0x65, 0xc8, 0x46, 0x3c, 0x83, 0xa0, 0x15, 0x1a, 0x64,
-				0x45, 0xe2, 0xab, 0x57, 0x82, 0x14, 0x04, 0x80, 0x83, 0x85, 0xf2, 0x91, 0x11, 0x96, 0x83, 0x1b,
-				0x9b, 0x24, 0x20, 0x7d, 0xeb, 0xdf, 0x2c, 0x0f, 0x56, 0xef, 0x1f, 0x46, 0x8f, 0x7f, 0x56, 0xaf,
-				0x4a, 0xd2, 0xc3, 0x56, 0x5e, 0x65, 0x18, 0xf6, 0x61, 0x02, 0x81, 0x81, 0x00, 0xb6, 0xa7, 0xd9,
-				0x57, 0x20, 0x65, 0x3c, 0x56, 0x89, 0x96, 0x38, 0x34, 0x53, 0xe6, 0x61, 0xa9, 0xad, 0x91, 0x35,
-				0x65, 0xd8, 0x67, 0xe8, 0xe5, 0x1f, 0xe2, 0x37, 0x4b, 0xae, 0xf4, 0xfb, 0xa3, 0x3e, 0x26, 0x04,
-				0xc9, 0x1a, 0xac, 0xb6, 0x6a, 0xf0, 0xf7, 0x59, 0x8e, 0xa8, 0xa1, 0x12, 0xe2, 0x8b, 0x60, 0xb0,
-				0x2c, 0xd7, 0xfb, 0x68, 0xcc, 0x44, 0x08, 0x7d, 0x09, 0xad, 0xdf, 0x0c, 0xc2, 0x9b, 0x99, 0x0d,
-				0x82, 0x44, 0x83, 0x82, 0x98, 0x3f, 0xdd, 0x8b, 0xfd, 0x6e, 0x75, 0x04, 0x87, 0x4f, 0xa8, 0x53,
-				0xb9, 0x2e, 0xa3, 0xfb, 0xd1, 0xc2, 0x31, 0x68, 0xb0, 0x0c, 0xb3, 0x6c, 0xe5, 0xa8, 0x9e, 0x3f,
-				0xd7, 0x01, 0x3c, 0x65, 0xdb, 0xde, 0x04, 0xd3, 0x53, 0x8e, 0x61, 0x84, 0x7a, 0x28, 0x0d, 0x0a,
-				0xa0, 0x6a, 0x2d, 0x61, 0xf5, 0x3c, 0x3f, 0x9d, 0xd5, 0xc1, 0x06, 0xd9, 0x6d, 0x02, 0x81, 0x80,
-				0x61, 0xbe, 0x11, 0x8b, 0x49, 0xcb, 0xa0, 0x59, 0xf4, 0x14, 0xcd, 0x5d, 0x67, 0xcf, 0xe5, 0x89,
-				0x5d, 0xf8, 0x41, 0x9c, 0x3e, 0xad, 0x05, 0xef, 0x8a, 0xa7, 0x0c, 0x0b, 0x91, 0x09, 0xf7, 0xf1,
-				0x93, 0xa2, 0x62, 0xd2, 0xf6, 0xf0, 0x1d, 0x75, 0xf9, 0xb1, 0x86, 0x35, 0x5b, 0x03, 0x18, 0x2b,
-				0xa2, 0x73, 0xfe, 0x9c, 0x78, 0x2e, 0x34, 0x9f, 0x39, 0x5e, 0xdb, 0xd4, 0xa6, 0x98, 0x7e, 0x17,
-				0x56, 0x97, 0x6e, 0xef, 0x0d, 0x39, 0x9b, 0x5e, 0xf7, 0x71, 0xb4, 0x1d, 0xb6, 0x1a, 0x9d, 0x30,
-				0xdc, 0xbe, 0xfc, 0x8b, 0x32, 0x99, 0xed, 0x3a, 0x1b, 0xb0, 0x04, 0x8b, 0xea, 0x00, 0xc9, 0x70,
-				0x35, 0x6b, 0x98, 0x51, 0xf6, 0xd7, 0x79, 0xef, 0x11, 0x08, 0xc3, 0x88, 0xa3, 0x7d, 0x84, 0x68,
-				0x37, 0xd7, 0x65, 0xcc, 0x69, 0x72, 0x37, 0x24, 0x45, 0x91, 0x40, 0xac, 0x47, 0x43, 0x3a, 0x01,
-				0x02, 0x81, 0x80, 0x55, 0xa4, 0x0d, 0x7b, 0x94, 0x6c, 0xe3, 0x05, 0x90, 0x2d, 0x26, 0xdd, 0x22,
-				0x19, 0x7a, 0xe1, 0x1b, 0xc8, 0x61, 0xc9, 0x06, 0xd6, 0x71, 0x94, 0x3c, 0x86, 0xcc, 0x76, 0x67,
-				0xe9, 0xe5, 0xb2, 0x7c, 0x89, 0x46, 0xe5, 0x23, 0xe4, 0xa7, 0x03, 0x2d, 0x48, 0x4c, 0x6d, 0x5f,
-				0x13, 0x66, 0xcf, 0x61, 0x9a, 0x4c, 0x00, 0x3a, 0xa4, 0x5e, 0x56, 0xa7, 0xef, 0x72, 0xf0, 0xfe,
-				0xdc, 0xfe, 0x16, 0xa0, 0xed, 0xfa, 0x2f, 0x82, 0x00, 0x47, 0x53, 0x2b, 0x5e, 0xad, 0x2c, 0x7e,
-				0x85, 0xcf, 0x41, 0xc2, 0x4f, 0xa2, 0x31, 0xc9, 0x74, 0x89, 0xb5, 0xa7, 0xdf, 0x92, 0xbe, 0x38,
-				0xb6, 0x47, 0xf0, 0xc6, 0x46, 0xac, 0x98, 0x1a, 0xb4, 0x3e, 0xee, 0x00, 0x03, 0x33, 0x32, 0x92,
-				0x27, 0x96, 0xfd, 0xcf, 0x99, 0x8d, 0xc9, 0xf8, 0xfe, 0x9e, 0x57, 0x65, 0x90, 0x4e, 0x68, 0xd2,
-				0xc0, 0x6b, 0x61, 0x02, 0x81, 0x80, 0x60, 0x82, 0x40, 0x89, 0x81, 0x7e, 0xdf, 0x45, 0xa6, 0x18,
-				0x04, 0xb0, 0xb8, 0x8a, 0xda, 0xb5, 0xaa, 0xf5, 0xd1, 0x45, 0xf9, 0x87, 0x7b, 0xe2, 0xc3, 0x80,
-				0xc8, 0x6c, 0x2d, 0xf9, 0x5d, 0x29, 0xff, 0xdb, 0xd4, 0xa9, 0x65, 0x4c, 0xa3, 0x3a, 0x63, 0xf5,
-				0xab, 0xa3, 0xe4, 0x3d, 0x26, 0x33, 0x75, 0x89, 0x4d, 0x5e, 0x75, 0xf2, 0x27, 0x19, 0x35, 0xe0,
-				0x82, 0x85, 0x15, 0xf8, 0x0c, 0x94, 0x9e, 0x67, 0xb9, 0xbe, 0xab, 0xe6, 0x0e, 0xad, 0xc1, 0xd5,
-				0x8d, 0x17, 0x9d, 0x01, 0xd6, 0xac, 0xe8, 0xdf, 0x79, 0xdf, 0x56, 0xd2, 0xf9, 0x5a, 0x75, 0x05,
-				0x85, 0x02, 0x16, 0x97, 0xa4, 0x9d, 0xa9, 0x9c, 0xbc, 0x89, 0x6f, 0x05, 0x1a, 0x6d, 0x25, 0xc8,
-				0x96, 0xe1, 0x8a, 0x5a, 0x58, 0x6a, 0xa3, 0x7c, 0xfe, 0xf3, 0x56, 0x32, 0x77, 0xf1, 0xc7, 0xce,
-				0x3d, 0xba, 0x9c, 0xd9, 0xb5, 0x1a
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xd7, 0x0d, 0xf0, 0xf1, 0xd6, 0x32, 0xfa, 0xce, 0x93, 0x1c, 0x28, 0x51,
-				0xab, 0xa6, 0x7b, 0xec, 0x94, 0x0a, 0xa0, 0x96, 0x9a, 0xfe, 0x8a, 0x4f, 0x0a, 0x12, 0xa2, 0xda,
-				0x2d, 0xe5, 0x79, 0xa1, 0xe5, 0xd8, 0x67, 0x12, 0xd0, 0x1e, 0xeb, 0xc1, 0x21, 0x48, 0x9b, 0xf6,
-				0x37, 0xe2, 0x6d, 0x39, 0x02, 0xf5, 0xfa, 0x20, 0x28, 0x19, 0x40, 0x89, 0xf6, 0x55, 0xa2, 0xe5,
-				0xbd, 0xd7, 0x0c, 0xa5, 0x98, 0xb2, 0x64, 0xdb, 0x29, 0xd9, 0x8e, 0x6b, 0xfa, 0xc3, 0x3c, 0xa9,
-				0xa8, 0xfb, 0x36, 0x0b, 0x41, 0xe4, 0x42, 0xea, 0x82, 0xcc, 0xbd, 0xff, 0x1a, 0x8a, 0x74, 0x1e,
-				0xe8, 0xcd, 0xe8, 0x20, 0x5e, 0xc2, 0x7a, 0x17, 0xfb, 0x99, 0x1e, 0xfb, 0xe2, 0x73, 0xff, 0x38,
-				0x7a, 0x63, 0x95, 0x74, 0xb4, 0xe2, 0x1c, 0xb2, 0xc3, 0x62, 0xac, 0x88, 0x92, 0x8a, 0x5a, 0xb7,
-				0xe8, 0x83, 0x09, 0xf9, 0xb5, 0xef, 0x74, 0x4e, 0x4f, 0xce, 0x60, 0xf0, 0x14, 0xcf, 0xc3, 0xc7,
-				0x8f, 0x11, 0x2a, 0x85, 0x5b, 0x9a, 0xe2, 0x4e, 0x14, 0x14, 0xc1, 0x03, 0xf9, 0xc3, 0x00, 0x45,
-				0xd2, 0x44, 0xa9, 0xd6, 0x4a, 0x9c, 0x10, 0x8f, 0x61, 0x6b, 0x7e, 0x21, 0x47, 0x22, 0x93, 0x72,
-				0x81, 0x3e, 0x34, 0x81, 0x0a, 0xae, 0xe4, 0x66, 0x4a, 0xea, 0xaa, 0x38, 0x97, 0x35, 0x01, 0x07,
-				0xab, 0x70, 0x5d, 0x2e, 0x4c, 0x4c, 0x95, 0x41, 0x7c, 0x07, 0x6d, 0x50, 0x60, 0x9c, 0x50, 0xc3,
-				0x22, 0x8c, 0x46, 0xc3, 0x36, 0x70, 0x42, 0xcf, 0x2b, 0x0b, 0x1a, 0xd8, 0x57, 0x17, 0x36, 0x6f,
-				0x59, 0xe8, 0xb7, 0x93, 0x1e, 0x16, 0x08, 0xea, 0xca, 0x2d, 0x19, 0x2f, 0x6b, 0x3c, 0xca, 0xd7,
-				0x0d, 0xd5, 0x0a, 0x07, 0x9d, 0x86, 0xe5, 0xfe, 0xa6, 0x95, 0x24, 0x6e, 0x9d, 0x4d, 0x74, 0x10,
-				0x89, 0x05, 0xf4, 0xa3
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd7, 0x0d, 0xf0, 0xf1,
-				0xd6, 0x32, 0xfa, 0xce, 0x93, 0x1c, 0x28, 0x51, 0xab, 0xa6, 0x7b, 0xec, 0x94, 0x0a, 0xa0, 0x96,
-				0x9a, 0xfe, 0x8a, 0x4f, 0x0a, 0x12, 0xa2, 0xda, 0x2d, 0xe5, 0x79, 0xa1, 0xe5, 0xd8, 0x67, 0x12,
-				0xd0, 0x1e, 0xeb, 0xc1, 0x21, 0x48, 0x9b, 0xf6, 0x37, 0xe2, 0x6d, 0x39, 0x02, 0xf5, 0xfa, 0x20,
-				0x28, 0x19, 0x40, 0x89, 0xf6, 0x55, 0xa2, 0xe5, 0xbd, 0xd7, 0x0c, 0xa5, 0x98, 0xb2, 0x64, 0xdb,
-				0x29, 0xd9, 0x8e, 0x6b, 0xfa, 0xc3, 0x3c, 0xa9, 0xa8, 0xfb, 0x36, 0x0b, 0x41, 0xe4, 0x42, 0xea,
-				0x82, 0xcc, 0xbd, 0xff, 0x1a, 0x8a, 0x74, 0x1e, 0xe8, 0xcd, 0xe8, 0x20, 0x5e, 0xc2, 0x7a, 0x17,
-				0xfb, 0x99, 0x1e, 0xfb, 0xe2, 0x73, 0xff, 0x38, 0x7a, 0x63, 0x95, 0x74, 0xb4, 0xe2, 0x1c, 0xb2,
-				0xc3, 0x62, 0xac, 0x88, 0x92, 0x8a, 0x5a, 0xb7, 0xe8, 0x83, 0x09, 0xf9, 0xb5, 0xef, 0x74, 0x4e,
-				0x4f, 0xce, 0x60, 0xf0, 0x14, 0xcf, 0xc3, 0xc7, 0x8f, 0x11, 0x2a, 0x85, 0x5b, 0x9a, 0xe2, 0x4e,
-				0x14, 0x14, 0xc1, 0x03, 0xf9, 0xc3, 0x00, 0x45, 0xd2, 0x44, 0xa9, 0xd6, 0x4a, 0x9c, 0x10, 0x8f,
-				0x61, 0x6b, 0x7e, 0x21, 0x47, 0x22, 0x93, 0x72, 0x81, 0x3e, 0x34, 0x81, 0x0a, 0xae, 0xe4, 0x66,
-				0x4a, 0xea, 0xaa, 0x38, 0x97, 0x35, 0x01, 0x07, 0xab, 0x70, 0x5d, 0x2e, 0x4c, 0x4c, 0x95, 0x41,
-				0x7c, 0x07, 0x6d, 0x50, 0x60, 0x9c, 0x50, 0xc3, 0x22, 0x8c, 0x46, 0xc3, 0x36, 0x70, 0x42, 0xcf,
-				0x2b, 0x0b, 0x1a, 0xd8, 0x57, 0x17, 0x36, 0x6f, 0x59, 0xe8, 0xb7, 0x93, 0x1e, 0x16, 0x08, 0xea,
-				0xca, 0x2d, 0x19, 0x2f, 0x6b, 0x3c, 0xca, 0xd7, 0x0d, 0xd5, 0x0a, 0x07, 0x9d, 0x86, 0xe5, 0xfe,
-				0xa6, 0x95, 0x24, 0x6e, 0x9d, 0x4d, 0x74, 0x10, 0x89, 0x05, 0xf4, 0xa3, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x1c, 0x54, 0x60, 0x7d, 0x3b, 0x33, 0xbe, 0xb3, 0xca, 0x7a, 0xac,
-				0x6f, 0xb5, 0xd1, 0x04, 0xaf, 0x87, 0x01, 0x04, 0xb9, 0x52, 0x49, 0xb3, 0x26, 0x9e, 0x5e, 0x68,
-				0xc8, 0x47, 0xc0, 0xdc, 0x63, 0xbb, 0x72, 0x3a, 0x81, 0xd1, 0x46, 0x2c, 0x2b, 0x10, 0xf0, 0xb9,
-				0x10, 0x42, 0x64, 0x62, 0xf1, 0xb3, 0xb6, 0x26, 0x46, 0x68, 0xd7, 0x35, 0x6d, 0x4c, 0x8a, 0x13,
-				0x74, 0xcd, 0xac, 0x05, 0x4f, 0xd0, 0x97, 0x0f, 0x8f, 0x8a, 0x2a, 0x78, 0x07, 0x39, 0x78, 0x26,
-				0xb1, 0xa2, 0xea, 0x6a, 0x40, 0x29, 0x64, 0xa1, 0xd1, 0x60, 0x27, 0x0b, 0x3b, 0x0e, 0x8a, 0xab,
-				0xfe, 0xb6, 0x64, 0x5e, 0xee, 0x84, 0xb7, 0xd1, 0xd0, 0x54, 0x50, 0x8e, 0x33, 0x03, 0x03, 0x37,
-				0x87, 0xd5, 0x22, 0x46, 0x8f, 0x4d, 0x3f, 0x76, 0xd0, 0x5b, 0x1f, 0x7b, 0x38, 0x5d, 0x35, 0x8f,
-				0x50, 0x7d, 0x77, 0x65, 0xaf, 0x70, 0x62, 0x27, 0x1a, 0x8c, 0xc0, 0xc9, 0xa3, 0x45, 0x70, 0xcb,
-				0x7a, 0xf0, 0x29, 0x73, 0x06, 0x0c, 0x8d, 0x50, 0x48, 0x40, 0x86, 0x0c, 0x35, 0xc3, 0x4e, 0x50,
-				0x20, 0xce, 0xbc, 0xc9, 0x74, 0x8d, 0x8c, 0xca, 0x0d, 0xc1, 0xbd, 0x34, 0x36, 0xbe, 0x76, 0x4d,
-				0x68, 0x94, 0x37, 0xef, 0x1c, 0x42, 0x74, 0xa4, 0xe7, 0x39, 0x01, 0x08, 0xe0, 0x1d, 0xe9, 0xf8,
-				0x3e, 0x0c, 0x6b, 0x91, 0x4b, 0x65, 0xa4, 0x27, 0x1e, 0x5b, 0xef, 0x35, 0xf0, 0x8a, 0xb8, 0x5b,
-				0x47, 0x53, 0xf3, 0x22, 0xe3, 0x5b, 0x39, 0xb8, 0x1a, 0x61, 0x10, 0x14, 0x42, 0x78, 0xab, 0xf3,
-				0xfe, 0xc8, 0xcc, 0x02, 0xc7, 0x57, 0xbe, 0xf8, 0xa5, 0xc8, 0x7a, 0xe1, 0x1a, 0x30, 0xfd, 0x82,
-				0x25, 0x46, 0x50, 0x13, 0x51, 0x0d, 0x41, 0x7d, 0xc0, 0x98, 0xae, 0x39, 0x13, 0x90, 0x55, 0x50,
-				0x23, 0x09, 0xca, 0xec, 0x21, 0x02, 0x81, 0x81, 0x00, 0xef, 0x38, 0x43, 0x33, 0xaa, 0x87, 0x3d,
-				0x28, 0x52, 0x3c, 0xfc, 0xaf, 0xc4, 0xf3, 0x12, 0xeb, 0x16, 0x31, 0x1e, 0x1d, 0x30, 0xa5, 0xb4,
-				0x1a, 0x43, 0x2d, 0xf7, 0xe4, 0x9f, 0x5c, 0x69, 0xf0, 0xe4, 0x99, 0xd6, 0x72, 0x75, 0xe7, 0x26,
-				0x3e, 0x5f, 0xe8, 0xaf, 0xb0, 0x36, 0xb6, 0x01, 0xbb, 0xec, 0x7f, 0xed, 0x48, 0xbf, 0x51, 0x4e,
-				0x15, 0x6f, 0xdc, 0x41, 0xcc, 0x17, 0xfd, 0xbd, 0xae, 0x4e, 0x1d, 0x12, 0xb8, 0x3b, 0xd4, 0xba,
-				0xf3, 0x96, 0x85, 0xba, 0x88, 0x29, 0x25, 0x0a, 0xe4, 0xf7, 0x53, 0x9a, 0x6b, 0xe2, 0xb0, 0x9b,
-				0xaf, 0x77, 0x13, 0x16, 0x5b, 0xf7, 0x11, 0xf0, 0xed, 0x79, 0xe4, 0xff, 0xad, 0x27, 0x71, 0x12,
-				0x11, 0xd1, 0x36, 0xf3, 0x31, 0x74, 0xbc, 0x2d, 0x50, 0x66, 0x9a, 0x03, 0x8c, 0xd4, 0x8b, 0x4c,
-				0xa0, 0x3e, 0x4d, 0x61, 0x62, 0x7d, 0x06, 0x46, 0xdd, 0x02, 0x81, 0x81, 0x00, 0xe6, 0x23, 0xbc,
-				0x36, 0x7b, 0xd2, 0xd4, 0xbe, 0xa7, 0x87, 0x3e, 0xc7, 0x43, 0x90, 0x0f, 0xa1, 0x8e, 0xf8, 0x63,
-				0xd5, 0x4c, 0x2d, 0x65, 0xd6, 0x28, 0x2b, 0x35, 0xb6, 0xfc, 0xd0, 0x34, 0xa0, 0xc0, 0xb4, 0xa0,
-				0xd5, 0x34, 0xe3, 0x69, 0x20, 0x39, 0x6e, 0x70, 0x11, 0x79, 0x72, 0x64, 0xdb, 0x73, 0x00, 0x9b,
-				0x97, 0x89, 0xda, 0x10, 0xb4, 0xeb, 0xfa, 0xd2, 0xaf, 0x29, 0x5c, 0xc9, 0x99, 0x02, 0xfb, 0x9d,
-				0x81, 0x36, 0x9f, 0x86, 0x71, 0xcd, 0xa8, 0xd0, 0x33, 0x53, 0xb6, 0x06, 0x7f, 0xb0, 0xf2, 0x18,
-				0xbf, 0x86, 0xd3, 0xdf, 0xe8, 0xcc, 0x4b, 0x63, 0xe1, 0x08, 0x4b, 0xd1, 0x2e, 0xd6, 0x7e, 0x1e,
-				0xf6, 0xac, 0x66, 0xbd, 0x63, 0x34, 0x06, 0xef, 0x7b, 0xe9, 0xac, 0x20, 0xa5, 0x53, 0xb6, 0x31,
-				0xf8, 0x54, 0xc8, 0x1e, 0xd7, 0x11, 0x20, 0x66, 0x68, 0x7b, 0xf2, 0xb1, 0x7f, 0x02, 0x81, 0x80,
-				0x09, 0xa2, 0xea, 0x92, 0x1a, 0x3c, 0x78, 0x6a, 0x37, 0x65, 0xdd, 0x87, 0xf7, 0x17, 0x13, 0x9c,
-				0x04, 0xb8, 0xd5, 0xcd, 0xb7, 0x37, 0xf5, 0x99, 0x59, 0x3b, 0x70, 0xd0, 0xf4, 0xda, 0x74, 0x2a,
-				0x10, 0x0b, 0x62, 0x68, 0x19, 0xf7, 0xc5, 0xc2, 0x9d, 0x7a, 0x72, 0x19, 0x57, 0x1a, 0xdd, 0xd7,
-				0x04, 0x1f, 0xe3, 0x1f, 0x1b, 0x15, 0xdb, 0x5f, 0x61, 0xb2, 0x2d, 0xb4, 0x5b, 0x03, 0x0d, 0xb1,
-				0x07, 0xd4, 0x83, 0xfc, 0x87, 0xec, 0x79, 0xdb, 0x76, 0x24, 0xcc, 0xee, 0xcf, 0x39, 0x7e, 0xc6,
-				0xda, 0x6f, 0xb3, 0xb8, 0xc4, 0xd8, 0xf8, 0x6c, 0x89, 0x0f, 0x6b, 0xc7, 0x28, 0x9c, 0xc0, 0x67,
-				0xd0, 0x91, 0x38, 0xfb, 0x70, 0xab, 0x4d, 0x5f, 0x0a, 0x5e, 0x7c, 0x4d, 0x71, 0xb6, 0x62, 0xdc,
-				0xea, 0x45, 0x29, 0xff, 0x72, 0x50, 0x6a, 0x35, 0xca, 0x4c, 0xb3, 0xaf, 0x93, 0xf9, 0xbc, 0xc1,
-				0x02, 0x81, 0x80, 0x34, 0xdf, 0xc6, 0xf1, 0x39, 0x97, 0xa1, 0xbb, 0x3f, 0xe0, 0x29, 0xc3, 0x3c,
-				0x39, 0x8f, 0xed, 0xcd, 0x5c, 0x32, 0x0b, 0xa2, 0x59, 0xd7, 0xc8, 0xd1, 0x27, 0xc4, 0x4a, 0x8b,
-				0x61, 0x06, 0x86, 0x5c, 0x5f, 0xe3, 0x87, 0xb8, 0x83, 0xfa, 0xf6, 0x25, 0x5b, 0xc3, 0x31, 0xb0,
-				0x96, 0x60, 0xa7, 0xae, 0x8f, 0x58, 0x30, 0x03, 0xc2, 0xef, 0x0d, 0xb2, 0x1d, 0xc9, 0x63, 0xe6,
-				0xfb, 0xe3, 0x71, 0x5d, 0x27, 0x13, 0xf3, 0xc8, 0xe9, 0xf3, 0xc8, 0x97, 0xb8, 0x8e, 0x45, 0x0c,
-				0x99, 0x88, 0x7a, 0xb3, 0xdb, 0x9b, 0x65, 0xfd, 0x83, 0x16, 0x31, 0x75, 0x26, 0x69, 0x07, 0x1d,
-				0x91, 0xd5, 0xb8, 0x8e, 0x1d, 0x21, 0xde, 0x08, 0x93, 0xfe, 0x35, 0x19, 0x91, 0xf2, 0x59, 0xa4,
-				0xc1, 0x20, 0x2a, 0xfb, 0xc5, 0xa3, 0x4b, 0x6b, 0xa7, 0x22, 0xb6, 0xc4, 0xbf, 0x8d, 0xe7, 0xb9,
-				0x7a, 0x73, 0xdf, 0x02, 0x81, 0x80, 0x76, 0x65, 0x88, 0x7f, 0xe6, 0xef, 0x64, 0x90, 0xf8, 0x9a,
-				0x2d, 0x3a, 0xd0, 0xff, 0xb1, 0x50, 0x00, 0x9f, 0x3a, 0xfd, 0xa9, 0x22, 0xea, 0x17, 0x03, 0x9f,
-				0xfb, 0x78, 0x3d, 0xb2, 0x60, 0xf9, 0x7a, 0x58, 0xcf, 0x21, 0xdc, 0xb7, 0x18, 0x14, 0x9b, 0xb3,
-				0x54, 0x86, 0x15, 0x0d, 0x47, 0xfc, 0xc8, 0x23, 0x61, 0x47, 0x7b, 0x97, 0xdc, 0x13, 0x01, 0xe5,
-				0x73, 0xd6, 0x75, 0xf3, 0xf3, 0x28, 0x1d, 0xa6, 0x3b, 0xcc, 0x3f, 0xc0, 0x5d, 0xab, 0xb2, 0xe0,
-				0x03, 0xd6, 0x11, 0xe7, 0x0b, 0xc8, 0xfe, 0xb0, 0xcd, 0x21, 0x66, 0x23, 0x48, 0x7f, 0xd0, 0x05,
-				0x56, 0xcf, 0x76, 0x9a, 0xfb, 0x6c, 0x09, 0xb7, 0x84, 0x3c, 0xcc, 0xfb, 0xbc, 0xa1, 0x57, 0xaf,
-				0x9a, 0x70, 0x4d, 0x25, 0x07, 0xc3, 0xa3, 0xc3, 0x38, 0x93, 0x11, 0x7c, 0x9e, 0xb2, 0xd1, 0x57,
-				0xb5, 0x3b, 0x64, 0x7e, 0xa1, 0x9a
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xa9, 0x2a, 0x95, 0x5f, 0x4b, 0x1a, 0x18, 0x95, 0x58, 0xdb, 0xac, 0x74,
-				0x5a, 0x24, 0x0d, 0x1e, 0x29, 0x5f, 0x0e, 0x46, 0x96, 0x84, 0x39, 0x23, 0x63, 0xcc, 0x8c, 0x06,
-				0x49, 0xb2, 0x13, 0x58, 0xf3, 0xe1, 0x5e, 0x16, 0xc4, 0xfe, 0x89, 0xac, 0xcd, 0x7b, 0xd7, 0xbe,
-				0x66, 0x46, 0xba, 0x33, 0x71, 0xbe, 0xd8, 0x5f, 0x4d, 0x97, 0xc6, 0x97, 0xe9, 0x09, 0x18, 0xa0,
-				0x66, 0xe4, 0x74, 0xff, 0x46, 0xf5, 0xab, 0x1e, 0x89, 0xdf, 0x2c, 0x47, 0x2d, 0x9b, 0xc0, 0x2d,
-				0x2e, 0x7b, 0xd2, 0xc4, 0x87, 0xc8, 0x5f, 0x75, 0xb9, 0xb8, 0xf1, 0xfa, 0x8a, 0x32, 0x06, 0x40,
-				0x70, 0x73, 0x4e, 0x34, 0x43, 0x3a, 0x41, 0x4a, 0xff, 0xe4, 0x6c, 0x4d, 0x75, 0xa0, 0x0c, 0x2b,
-				0x9f, 0x22, 0xcc, 0x27, 0x19, 0xc5, 0x93, 0x55, 0x3a, 0x81, 0xaf, 0x4f, 0x9c, 0xa7, 0x09, 0x1e,
-				0xe5, 0x04, 0x22, 0x41, 0xb7, 0x1c, 0x64, 0x1c, 0x9a, 0x1f, 0xf1, 0x52, 0x73, 0xb7, 0x38, 0xa2,
-				0x75, 0xe2, 0x2f, 0x38, 0x71, 0x11, 0x9a, 0x91, 0x8f, 0x62, 0x8e, 0xd3, 0xb3, 0x29, 0x78, 0xe4,
-				0x99, 0xf7, 0xbd, 0x61, 0x92, 0x6f, 0xcc, 0xe9, 0xf8, 0x09, 0xd0, 0xb4, 0x2f, 0x9e, 0x86, 0x4d,
-				0xf3, 0x8a, 0xe0, 0x72, 0x8d, 0x87, 0x44, 0xfd, 0x38, 0xf6, 0x9d, 0x58, 0x10, 0xe1, 0x58, 0xf5,
-				0x2a, 0xf8, 0x50, 0x18, 0xf2, 0x9c, 0x02, 0x42, 0xb4, 0x10, 0x92, 0xf6, 0xac, 0xae, 0x50, 0x6c,
-				0xac, 0x3f, 0xb9, 0x54, 0xab, 0xa3, 0x1d, 0x20, 0xde, 0x81, 0xe2, 0xec, 0xf2, 0x0b, 0xed, 0x51,
-				0x55, 0xb6, 0xdc, 0x47, 0x87, 0xac, 0x67, 0x55, 0x5c, 0x02, 0xa8, 0x21, 0x57, 0x53, 0x5c, 0x2a,
-				0xaf, 0x70, 0x70, 0xa9, 0x52, 0x5c, 0xea, 0x6f, 0xb5, 0x57, 0xaf, 0xc3, 0x11, 0x46, 0xdb, 0xa1,
-				0x4e, 0x38, 0x54, 0x39
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa9, 0x2a, 0x95, 0x5f,
-				0x4b, 0x1a, 0x18, 0x95, 0x58, 0xdb, 0xac, 0x74, 0x5a, 0x24, 0x0d, 0x1e, 0x29, 0x5f, 0x0e, 0x46,
-				0x96, 0x84, 0x39, 0x23, 0x63, 0xcc, 0x8c, 0x06, 0x49, 0xb2, 0x13, 0x58, 0xf3, 0xe1, 0x5e, 0x16,
-				0xc4, 0xfe, 0x89, 0xac, 0xcd, 0x7b, 0xd7, 0xbe, 0x66, 0x46, 0xba, 0x33, 0x71, 0xbe, 0xd8, 0x5f,
-				0x4d, 0x97, 0xc6, 0x97, 0xe9, 0x09, 0x18, 0xa0, 0x66, 0xe4, 0x74, 0xff, 0x46, 0xf5, 0xab, 0x1e,
-				0x89, 0xdf, 0x2c, 0x47, 0x2d, 0x9b, 0xc0, 0x2d, 0x2e, 0x7b, 0xd2, 0xc4, 0x87, 0xc8, 0x5f, 0x75,
-				0xb9, 0xb8, 0xf1, 0xfa, 0x8a, 0x32, 0x06, 0x40, 0x70, 0x73, 0x4e, 0x34, 0x43, 0x3a, 0x41, 0x4a,
-				0xff, 0xe4, 0x6c, 0x4d, 0x75, 0xa0, 0x0c, 0x2b, 0x9f, 0x22, 0xcc, 0x27, 0x19, 0xc5, 0x93, 0x55,
-				0x3a, 0x81, 0xaf, 0x4f, 0x9c, 0xa7, 0x09, 0x1e, 0xe5, 0x04, 0x22, 0x41, 0xb7, 0x1c, 0x64, 0x1c,
-				0x9a, 0x1f, 0xf1, 0x52, 0x73, 0xb7, 0x38, 0xa2, 0x75, 0xe2, 0x2f, 0x38, 0x71, 0x11, 0x9a, 0x91,
-				0x8f, 0x62, 0x8e, 0xd3, 0xb3, 0x29, 0x78, 0xe4, 0x99, 0xf7, 0xbd, 0x61, 0x92, 0x6f, 0xcc, 0xe9,
-				0xf8, 0x09, 0xd0, 0xb4, 0x2f, 0x9e, 0x86, 0x4d, 0xf3, 0x8a, 0xe0, 0x72, 0x8d, 0x87, 0x44, 0xfd,
-				0x38, 0xf6, 0x9d, 0x58, 0x10, 0xe1, 0x58, 0xf5, 0x2a, 0xf8, 0x50, 0x18, 0xf2, 0x9c, 0x02, 0x42,
-				0xb4, 0x10, 0x92, 0xf6, 0xac, 0xae, 0x50, 0x6c, 0xac, 0x3f, 0xb9, 0x54, 0xab, 0xa3, 0x1d, 0x20,
-				0xde, 0x81, 0xe2, 0xec, 0xf2, 0x0b, 0xed, 0x51, 0x55, 0xb6, 0xdc, 0x47, 0x87, 0xac, 0x67, 0x55,
-				0x5c, 0x02, 0xa8, 0x21, 0x57, 0x53, 0x5c, 0x2a, 0xaf, 0x70, 0x70, 0xa9, 0x52, 0x5c, 0xea, 0x6f,
-				0xb5, 0x57, 0xaf, 0xc3, 0x11, 0x46, 0xdb, 0xa1, 0x4e, 0x38, 0x54, 0x39, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x1d, 0x63, 0x7d, 0xfe, 0xc7, 0xa3, 0xd9, 0x78, 0x7c, 0xae, 0xf1,
-				0x37, 0x67, 0x7f, 0x92, 0xdd, 0xd6, 0x0f, 0x23, 0x02, 0x45, 0x5c, 0xe4, 0x36, 0x4f, 0x3c, 0xb6,
-				0x68, 0xd3, 0x3d, 0xc2, 0x19, 0xb6, 0x88, 0xc5, 0x19, 0x4c, 0x90, 0xf1, 0xe7, 0x18, 0xed, 0xb6,
-				0x6d, 0xe8, 0x03, 0xca, 0x8e, 0x6c, 0x68, 0xdc, 0xdb, 0x35, 0xb6, 0x33, 0xf4, 0xa9, 0x32, 0x00,
-				0xda, 0xc0, 0xf5, 0x58, 0x94, 0x0e, 0xc6, 0x58, 0x3b, 0x9e, 0x75, 0x2c, 0x92, 0x93, 0x0c, 0x57,
-				0x67, 0x22, 0x07, 0xb5, 0xf6, 0x99, 0xa6, 0x48, 0x5b, 0x41, 0xf0, 0x2c, 0xed, 0xbb, 0x3b, 0x74,
-				0x95, 0x96, 0x53, 0x99, 0xd6, 0xff, 0x84, 0xeb, 0xd9, 0xf5, 0x39, 0xc0, 0x4c, 0xf6, 0xad, 0xde,
-				0xdf, 0x67, 0x2e, 0x9a, 0xec, 0x02, 0x10, 0xae, 0x87, 0x64, 0x7a, 0x2a, 0x34, 0x39, 0x01, 0x55,
-				0xd6, 0xcd, 0xaf, 0x99, 0xa9, 0xab, 0x97, 0x7d, 0x0c, 0x1a, 0x32, 0x61, 0x82, 0xcd, 0x60, 0xe0,
-				0x6b, 0x80, 0x55, 0x50, 0x61, 0x4b, 0x87, 0x16, 0x50, 0x7f, 0x7b, 0x37, 0x92, 0xda, 0xe9, 0x4e,
-				0xbe, 0x3a, 0xed, 0x64, 0xae, 0xf6, 0x3c, 0xb9, 0x19, 0x3e, 0x25, 0xc4, 0x91, 0x3a, 0x90, 0xbc,
-				0x8d, 0x2c, 0x12, 0xad, 0xdb, 0xb1, 0x5f, 0x7a, 0x60, 0xe2, 0xd8, 0x13, 0x61, 0x79, 0x45, 0xdf,
-				0xad, 0x4d, 0x4f, 0x3f, 0xf0, 0xd8, 0xfd, 0xd5, 0xc3, 0x29, 0x71, 0x2a, 0xf8, 0x6a, 0xf6, 0x55,
-				0x71, 0x3a, 0xa6, 0xb2, 0xf9, 0x62, 0xd7, 0x45, 0x01, 0x00, 0x39, 0x15, 0xbd, 0x5d, 0x4f, 0x18,
-				0x69, 0x99, 0x67, 0xa9, 0x60, 0xa3, 0x4d, 0x43, 0x68, 0x13, 0x4d, 0xca, 0x52, 0xb0, 0x66, 0x3d,
-				0xf6, 0xd7, 0x6d, 0x13, 0x7d, 0x17, 0xab, 0x74, 0xac, 0x63, 0x2b, 0xa5, 0xdd, 0xce, 0xe4, 0xaa,
-				0xfc, 0x98, 0x3c, 0xa8, 0x0f, 0x02, 0x81, 0x81, 0x00, 0xdb, 0x55, 0xe8, 0xb7, 0x5e, 0x3e, 0xab,
-				0x3a, 0xff, 0x73, 0xdc, 0xb3, 0xc6, 0x79, 0x93, 0x1f, 0xb1, 0xfe, 0x8c, 0xc8, 0x1b, 0x45, 0x5c,
-				0xcb, 0x3c, 0x00, 0x51, 0x00, 0xd5, 0x3b, 0x91, 0x57, 0x0b, 0x14, 0xad, 0x1e, 0x5c, 0x0a, 0x43,
-				0x46, 0x4f, 0x42, 0x92, 0x9a, 0x9c, 0xd0, 0x0d, 0x1e, 0x13, 0x60, 0xed, 0xee, 0x1f, 0x99, 0x6d,
-				0x3b, 0xc1, 0xb9, 0xc9, 0x28, 0xb4, 0x1a, 0x3b, 0xdd, 0x2d, 0x91, 0xa3, 0xea, 0x8c, 0xb5, 0xd6,
-				0xd6, 0x4d, 0x83, 0x48, 0x45, 0xcb, 0xdb, 0xc6, 0xff, 0xef, 0x5c, 0xbd, 0x5b, 0x82, 0xde, 0x70,
-				0x0d, 0xac, 0x35, 0x19, 0xd7, 0xdd, 0xf2, 0x6c, 0xaf, 0x29, 0xb4, 0xf2, 0x8e, 0xe8, 0xc6, 0xf4,
-				0x9a, 0x10, 0x3b, 0x01, 0xd3, 0xa0, 0xde, 0x95, 0x6a, 0xbe, 0xa8, 0x5b, 0xb8, 0x53, 0xea, 0xde,
-				0x8b, 0xd1, 0x8f, 0xe1, 0x57, 0x44, 0x65, 0x6a, 0x3f, 0x02, 0x81, 0x81, 0x00, 0xc5, 0x71, 0xc4,
-				0x83, 0x86, 0xcf, 0x8d, 0x18, 0x24, 0x75, 0xf4, 0x4d, 0x8d, 0xc9, 0x6f, 0x7c, 0x07, 0xa2, 0xa5,
-				0x1b, 0x78, 0xa3, 0xcf, 0x72, 0x75, 0x78, 0x83, 0x21, 0xc7, 0x0f, 0x37, 0x88, 0xb9, 0xe2, 0xe1,
-				0x27, 0x54, 0x90, 0x62, 0x11, 0x45, 0x20, 0x15, 0x6e, 0x01, 0x19, 0x99, 0xa8, 0xd5, 0xae, 0x69,
-				0x7c, 0xff, 0xdd, 0xff, 0x79, 0x98, 0x4d, 0x02, 0xdc, 0x42, 0x99, 0xbe, 0x06, 0x58, 0xf3, 0xc6,
-				0xe3, 0x20, 0x97, 0x21, 0x7f, 0x39, 0xa2, 0xa9, 0xfe, 0xdf, 0xc3, 0x30, 0x6b, 0xb2, 0x4f, 0x87,
-				0x64, 0xea, 0x72, 0xc8, 0x05, 0xe3, 0xa6, 0x32, 0xa5, 0xe3, 0xfb, 0x02, 0xe2, 0xcf, 0x5c, 0x00,
-				0xd3, 0x34, 0x9a, 0xe0, 0x57, 0x4a, 0x4f, 0xde, 0xeb, 0x61, 0x45, 0x3d, 0xd8, 0xf4, 0x21, 0x49,
-				0x35, 0x52, 0x33, 0xbd, 0x29, 0x11, 0x00, 0xd4, 0xde, 0x63, 0x3d, 0x73, 0x87, 0x02, 0x81, 0x80,
-				0x19, 0x7d, 0xfd, 0xa3, 0x3a, 0x47, 0xec, 0x5c, 0xda, 0x0d, 0xdc, 0x4b, 0xe4, 0xb8, 0x82, 0x99,
-				0xff, 0x75, 0x07, 0x65, 0xc6, 0x8d, 0xa4, 0x40, 0x56, 0xc3, 0xee, 0xa6, 0x3b, 0x22, 0x46, 0x3d,
-				0x28, 0xa3, 0x89, 0x8f, 0x6a, 0xc1, 0x22, 0x9a, 0x8c, 0x61, 0xbf, 0x6a, 0x4a, 0xe9, 0x7f, 0x6c,
-				0xcc, 0x71, 0xca, 0x95, 0x8f, 0x84, 0xa4, 0x86, 0x7a, 0x78, 0x9e, 0x61, 0xa5, 0xb5, 0x1a, 0xda,
-				0x15, 0x0e, 0xc5, 0x4f, 0x60, 0x75, 0x4d, 0xf7, 0xf0, 0x60, 0x5e, 0xc9, 0x05, 0xed, 0x90, 0x4e,
-				0x74, 0xc2, 0x81, 0x9b, 0x9e, 0x35, 0x3e, 0x2e, 0xc8, 0xa2, 0x0f, 0x53, 0xe0, 0x8e, 0xe9, 0x84,
-				0xde, 0x43, 0x12, 0xa1, 0xfb, 0x7a, 0x0c, 0x39, 0xcf, 0xc3, 0x1b, 0xee, 0x3d, 0xd7, 0x40, 0xe4,
-				0x7c, 0x2e, 0x53, 0x22, 0xb4, 0x56, 0x2a, 0xf1, 0x73, 0x34, 0xd6, 0xca, 0xee, 0xbf, 0x1e, 0xbf,
-				0x02, 0x81, 0x80, 0x79, 0xc3, 0x0f, 0x4d, 0x8d, 0x75, 0xb1, 0xad, 0x91, 0xce, 0xac, 0x3a, 0xa7,
-				0x95, 0xf2, 0x0a, 0xab, 0x2a, 0xc2, 0x67, 0x8e, 0x9e, 0x76, 0xf0, 0x3f, 0x41, 0x72, 0x9d, 0x02,
-				0x05, 0x80, 0x59, 0xf1, 0x48, 0xd9, 0x51, 0x47, 0xf5, 0x42, 0x85, 0x23, 0xfc, 0x05, 0x3b, 0x31,
-				0xb2, 0x77, 0xf0, 0x86, 0xd6, 0x68, 0x77, 0x8d, 0xd3, 0x7a, 0x19, 0xa2, 0xb2, 0xdb, 0x70, 0xba,
-				0x21, 0xd5, 0xee, 0x54, 0x2d, 0x02, 0x1a, 0x4f, 0x9e, 0xe4, 0x29, 0x71, 0x81, 0xbf, 0x14, 0x4f,
-				0x2a, 0x30, 0x52, 0x3a, 0x44, 0x91, 0x5a, 0xca, 0xba, 0xbe, 0x5f, 0xe3, 0x64, 0x3b, 0x17, 0xd2,
-				0xe0, 0x99, 0x87, 0x06, 0x19, 0xd6, 0xe8, 0x69, 0x28, 0x99, 0xf1, 0x3b, 0x02, 0xc6, 0x96, 0xa2,
-				0x05, 0xf1, 0x7e, 0x3a, 0x0f, 0xcc, 0xf5, 0xf5, 0x1b, 0xb3, 0x2c, 0x00, 0x30, 0x63, 0x16, 0x42,
-				0x5d, 0x43, 0x41, 0x02, 0x81, 0x80, 0x2c, 0x82, 0xb7, 0x40, 0x91, 0xa6, 0xf8, 0xd2, 0xf1, 0x25,
-				0x76, 0x23, 0x8d, 0x33, 0xc8, 0x8e, 0xdf, 0x36, 0xb1, 0x5e, 0x58, 0xfb, 0x91, 0x7d, 0x1a, 0x74,
-				0xb7, 0xb3, 0x8e, 0x8d, 0xce, 0x16, 0xf7, 0xef, 0x45, 0xb5, 0xb2, 0x80, 0xc4, 0x59, 0x64, 0x97,
-				0xf0, 0x09, 0xfa, 0xe6, 0x5a, 0x6d, 0x10, 0x6e, 0x74, 0x7d, 0xa7, 0x39, 0xc5, 0x18, 0x07, 0x59,
-				0xb2, 0x6d, 0xf7, 0x55, 0x36, 0x17, 0x1f, 0x3e, 0x36, 0x74, 0x3b, 0x2e, 0x43, 0x1d, 0x5d, 0x5b,
-				0xa8, 0x04, 0x99, 0x50, 0x1f, 0xf4, 0x06, 0x25, 0x20, 0x49, 0x89, 0x55, 0x94, 0xf7, 0x5f, 0x0e,
-				0x93, 0x22, 0xd4, 0x2b, 0x76, 0x3d, 0xb0, 0xd6, 0xf7, 0x3d, 0x4c, 0x39, 0x8e, 0x4b, 0x60, 0x55,
-				0x17, 0xa2, 0xa3, 0x94, 0xe0, 0x0b, 0x1e, 0x32, 0xbb, 0x8a, 0xf2, 0x34, 0x0f, 0x6a, 0x2e, 0xa0,
-				0x5c, 0x11, 0xae, 0x59, 0x1b, 0xb0
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA256 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xc1, 0x61, 0xce, 0x9c, 0xa6, 0x1c, 0xb8, 0xe5, 0xfd, 0xe6, 0x67, 0x34,
-				0x07, 0x21, 0x8b, 0xfe, 0xe6, 0x84, 0xbc, 0x97, 0x22, 0xaa, 0xcf, 0x90, 0x2e, 0x88, 0x77, 0x66,
-				0xd6, 0xf7, 0x24, 0xc6, 0xa1, 0x93, 0x04, 0x92, 0x56, 0x89, 0x2a, 0xb0, 0x35, 0xda, 0x06, 0x9a,
-				0x76, 0x97, 0xf5, 0xb2, 0x98, 0x80, 0x1f, 0x6e, 0x87, 0x29, 0xff, 0xda, 0x67, 0x27, 0xa7, 0x58,
-				0x09, 0x32, 0x6d, 0xff, 0x37, 0x31, 0xba, 0x92, 0x88, 0xa1, 0x59, 0xfb, 0x69, 0x4f, 0xa2, 0x26,
-				0x8e, 0xa1, 0xa8, 0x46, 0x83, 0xe8, 0x90, 0x53, 0xfc, 0x91, 0x9c, 0xe2, 0x54, 0xd8, 0x23, 0x08,
-				0x29, 0x00, 0x4f, 0x10, 0xc3, 0xff, 0x4b, 0xc9, 0xc4, 0xf9, 0xe5, 0x7d, 0xfb, 0xcd, 0x89, 0x6f,
-				0x13, 0x4b, 0xc2, 0xda, 0xe3, 0x8b, 0xaa, 0x9c, 0xfd, 0x18, 0x8b, 0xc3, 0x5e, 0x32, 0x40, 0xe9,
-				0x25, 0x3b, 0x0f, 0xdf, 0x6f, 0x26, 0x3e, 0xb8, 0xe8, 0xd3, 0x5a, 0x38, 0x27, 0xfc, 0xde, 0x6b,
-				0xbf, 0xb8, 0x5b, 0x5c, 0x8f, 0x38, 0x4f, 0x31, 0x8b, 0x69, 0x76, 0x9d, 0x29, 0x20, 0x17, 0xcc,
-				0x22, 0x1f, 0x99, 0x33, 0x47, 0x0f, 0x6e, 0xf8, 0xd1, 0x47, 0x28, 0xf5, 0x99, 0x28, 0xad, 0x42,
-				0xab, 0xac, 0xfc, 0x29, 0x27, 0x90, 0xc1, 0xfc, 0xb8, 0x5f, 0x47, 0xc2, 0xa0, 0x69, 0x39, 0x32,
-				0x75, 0x5c, 0x0a, 0x4c, 0x98, 0x52, 0xeb, 0xfc, 0x53, 0xaf, 0x16, 0x62, 0x93, 0xcc, 0x63, 0x39,
-				0x5a, 0x2d, 0x1a, 0x3d, 0x60, 0xf4, 0x22, 0x8d, 0x8d, 0x70, 0xc3, 0xab, 0x2c, 0xf2, 0x91, 0xb3,
-				0xe5, 0xc6, 0x80, 0x43, 0x3e, 0xd2, 0x9e, 0xf1, 0x28, 0xce, 0xec, 0x98, 0xbc, 0x99, 0x2f, 0x98,
-				0xbb, 0xf3, 0x29, 0xa9, 0x59, 0x48, 0x18, 0x54, 0xa8, 0x6d, 0x2b, 0xb8, 0xf4, 0x56, 0xb3, 0x79,
-				0x87, 0xa4, 0xd5, 0x2f
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x61, 0xce, 0x9c,
-				0xa6, 0x1c, 0xb8, 0xe5, 0xfd, 0xe6, 0x67, 0x34, 0x07, 0x21, 0x8b, 0xfe, 0xe6, 0x84, 0xbc, 0x97,
-				0x22, 0xaa, 0xcf, 0x90, 0x2e, 0x88, 0x77, 0x66, 0xd6, 0xf7, 0x24, 0xc6, 0xa1, 0x93, 0x04, 0x92,
-				0x56, 0x89, 0x2a, 0xb0, 0x35, 0xda, 0x06, 0x9a, 0x76, 0x97, 0xf5, 0xb2, 0x98, 0x80, 0x1f, 0x6e,
-				0x87, 0x29, 0xff, 0xda, 0x67, 0x27, 0xa7, 0x58, 0x09, 0x32, 0x6d, 0xff, 0x37, 0x31, 0xba, 0x92,
-				0x88, 0xa1, 0x59, 0xfb, 0x69, 0x4f, 0xa2, 0x26, 0x8e, 0xa1, 0xa8, 0x46, 0x83, 0xe8, 0x90, 0x53,
-				0xfc, 0x91, 0x9c, 0xe2, 0x54, 0xd8, 0x23, 0x08, 0x29, 0x00, 0x4f, 0x10, 0xc3, 0xff, 0x4b, 0xc9,
-				0xc4, 0xf9, 0xe5, 0x7d, 0xfb, 0xcd, 0x89, 0x6f, 0x13, 0x4b, 0xc2, 0xda, 0xe3, 0x8b, 0xaa, 0x9c,
-				0xfd, 0x18, 0x8b, 0xc3, 0x5e, 0x32, 0x40, 0xe9, 0x25, 0x3b, 0x0f, 0xdf, 0x6f, 0x26, 0x3e, 0xb8,
-				0xe8, 0xd3, 0x5a, 0x38, 0x27, 0xfc, 0xde, 0x6b, 0xbf, 0xb8, 0x5b, 0x5c, 0x8f, 0x38, 0x4f, 0x31,
-				0x8b, 0x69, 0x76, 0x9d, 0x29, 0x20, 0x17, 0xcc, 0x22, 0x1f, 0x99, 0x33, 0x47, 0x0f, 0x6e, 0xf8,
-				0xd1, 0x47, 0x28, 0xf5, 0x99, 0x28, 0xad, 0x42, 0xab, 0xac, 0xfc, 0x29, 0x27, 0x90, 0xc1, 0xfc,
-				0xb8, 0x5f, 0x47, 0xc2, 0xa0, 0x69, 0x39, 0x32, 0x75, 0x5c, 0x0a, 0x4c, 0x98, 0x52, 0xeb, 0xfc,
-				0x53, 0xaf, 0x16, 0x62, 0x93, 0xcc, 0x63, 0x39, 0x5a, 0x2d, 0x1a, 0x3d, 0x60, 0xf4, 0x22, 0x8d,
-				0x8d, 0x70, 0xc3, 0xab, 0x2c, 0xf2, 0x91, 0xb3, 0xe5, 0xc6, 0x80, 0x43, 0x3e, 0xd2, 0x9e, 0xf1,
-				0x28, 0xce, 0xec, 0x98, 0xbc, 0x99, 0x2f, 0x98, 0xbb, 0xf3, 0x29, 0xa9, 0x59, 0x48, 0x18, 0x54,
-				0xa8, 0x6d, 0x2b, 0xb8, 0xf4, 0x56, 0xb3, 0x79, 0x87, 0xa4, 0xd5, 0x2f, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x4a, 0xc4, 0x60, 0x88, 0x43, 0x57, 0x46, 0x8b, 0xb1, 0xb3, 0x73,
-				0xc2, 0x73, 0x61, 0x5e, 0x89, 0xb2, 0xa1, 0xae, 0x72, 0xb6, 0xb6, 0x18, 0xe3, 0x33, 0x82, 0x92,
-				0xbb, 0xa1, 0xb0, 0x53, 0x39, 0x32, 0xfe, 0x2f, 0x1d, 0xcf, 0x34, 0x60, 0x5b, 0x59, 0xae, 0xce,
-				0xaf, 0xc8, 0xdb, 0x6e, 0xe4, 0xda, 0xbe, 0x6a, 0xa8, 0xa6, 0xbc, 0xaf, 0xcd, 0xc6, 0xe5, 0x57,
-				0x77, 0x9b, 0xb2, 0xb2, 0x41, 0xa3, 0x1a, 0xe8, 0x7a, 0x40, 0x36, 0x36, 0x1e, 0x94, 0xb4, 0x73,
-				0xca, 0x79, 0x89, 0xfa, 0x10, 0x2d, 0x6e, 0xec, 0xe2, 0x73, 0xfb, 0xee, 0x8e, 0xb9, 0x64, 0x09,
-				0x83, 0x5d, 0xaa, 0xdf, 0x66, 0xe9, 0x88, 0x9a, 0xca, 0x4b, 0x8c, 0x9c, 0xd4, 0xad, 0x56, 0xe5,
-				0xe4, 0x9a, 0xae, 0xc7, 0x8b, 0x2e, 0xbf, 0xf0, 0xba, 0x9a, 0xc6, 0x73, 0x3f, 0x19, 0x7b, 0xcf,
-				0x89, 0xf4, 0xd9, 0x95, 0x84, 0x4f, 0x16, 0x86, 0xb1, 0x3f, 0xac, 0x6e, 0x6a, 0xfc, 0x5d, 0x29,
-				0x8d, 0x33, 0xa5, 0x2d, 0x4c, 0x5a, 0xa1, 0x31, 0x81, 0xe9, 0xb6, 0x12, 0x4e, 0x3d, 0x2f, 0xef,
-				0xfb, 0x99, 0x48, 0x64, 0xc5, 0xb6, 0x6e, 0xaf, 0x39, 0x5f, 0x94, 0x03, 0xcd, 0xd3, 0x4b, 0xbf,
-				0x58, 0x6d, 0x17, 0x79, 0x72, 0x93, 0x04, 0xbe, 0xbc, 0x1b, 0x82, 0x2a, 0x11, 0x51, 0xe7, 0x05,
-				0x06, 0x3b, 0xa7, 0xf9, 0xbc, 0x34, 0x75, 0xd7, 0x3f, 0x3a, 0x37, 0x00, 0x68, 0xa9, 0x4c, 0xd0,
-				0xc6, 0x8d, 0x6c, 0xfb, 0x2a, 0x74, 0x00, 0x33, 0xda, 0x1e, 0x14, 0xe9, 0x73, 0xb5, 0x4e, 0x17,
-				0x2e, 0x12, 0x42, 0xf4, 0x9f, 0x01, 0x0b, 0x04, 0xae, 0x53, 0xf0, 0x89, 0xd5, 0x9a, 0x8f, 0x0d,
-				0xfa, 0x0c, 0xfd, 0x48, 0x6a, 0x09, 0xd9, 0xf7, 0x00, 0x1c, 0x57, 0x10, 0x1e, 0x43, 0xcb, 0x93,
-				0xc7, 0x57, 0x78, 0xff, 0xfd, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x73, 0x4f, 0xb1, 0xf1, 0x1b, 0x13,
-				0x7f, 0xd2, 0x62, 0xa3, 0x8e, 0xc3, 0x23, 0xf0, 0xe2, 0xfa, 0x07, 0x49, 0x5f, 0x65, 0xac, 0xdf,
-				0xf4, 0x9f, 0xf4, 0x9e, 0x7a, 0x0e, 0xf8, 0x7e, 0x8f, 0x60, 0xad, 0x02, 0xb6, 0xd0, 0xf3, 0xb8,
-				0x4d, 0xdb, 0x2a, 0x16, 0xc4, 0xb8, 0x43, 0x98, 0x1b, 0x89, 0x47, 0xd9, 0x91, 0x3c, 0x06, 0x67,
-				0xf1, 0xc9, 0xd3, 0x33, 0xb9, 0x82, 0x28, 0x9e, 0xa4, 0x9c, 0xf8, 0xc2, 0x89, 0x9a, 0x05, 0xde,
-				0xfc, 0xc2, 0xbc, 0x60, 0x2c, 0x04, 0x81, 0xe0, 0x26, 0x64, 0xd4, 0x01, 0xac, 0xaa, 0x36, 0x81,
-				0x0e, 0xc1, 0x97, 0xc7, 0xaa, 0xb9, 0x24, 0x8e, 0xc5, 0x2f, 0x3c, 0xcb, 0x8a, 0x80, 0x69, 0x94,
-				0x3b, 0xea, 0xf8, 0x7d, 0x64, 0x96, 0xd8, 0x55, 0x12, 0x95, 0x2c, 0x88, 0x15, 0x2e, 0x19, 0x47,
-				0x4b, 0x2d, 0x00, 0x02, 0x26, 0xa4, 0xa5, 0xd2, 0xdb, 0x02, 0x81, 0x81, 0x00, 0xda, 0x9d, 0xd4,
-				0x90, 0x6c, 0x4f, 0x18, 0x8f, 0x32, 0x43, 0xd7, 0xe6, 0x0f, 0xf8, 0x11, 0xc6, 0x07, 0x86, 0x1e,
-				0xe1, 0x7c, 0xa6, 0x4e, 0x44, 0x08, 0xc6, 0xcb, 0x34, 0xea, 0x0e, 0xdc, 0x62, 0x1b, 0x16, 0xbf,
-				0x91, 0x78, 0x52, 0xa3, 0x56, 0xee, 0x41, 0xba, 0x2e, 0x07, 0xb3, 0x2d, 0xde, 0x85, 0xc6, 0xb8,
-				0x73, 0x8b, 0xae, 0x5b, 0x51, 0x46, 0x86, 0xac, 0xe3, 0xdc, 0x3a, 0xa7, 0xd0, 0x5a, 0x2e, 0x2e,
-				0x39, 0xec, 0xe8, 0x3d, 0x2a, 0x3d, 0xb2, 0x8d, 0x2d, 0xea, 0x5a, 0x30, 0x2d, 0xe0, 0x85, 0xa0,
-				0x6e, 0xe7, 0x68, 0xf6, 0x3f, 0xf2, 0x7b, 0x61, 0xdd, 0x79, 0x39, 0x85, 0xda, 0x72, 0xad, 0x5f,
-				0xc4, 0x2f, 0xdd, 0xb3, 0xac, 0x83, 0x95, 0x7c, 0x7a, 0x95, 0xb6, 0x34, 0x18, 0xa7, 0xba, 0x4d,
-				0x2a, 0xbf, 0x68, 0x16, 0xca, 0x3b, 0xe4, 0x0a, 0x70, 0x9c, 0xe2, 0xf5, 0x3d, 0x02, 0x81, 0x80,
-				0x63, 0x1e, 0x72, 0x0d, 0xc3, 0x29, 0x44, 0xd9, 0xb8, 0x2e, 0xf0, 0xc4, 0x76, 0x69, 0xee, 0xf0,
-				0x8a, 0xdc, 0x51, 0xa3, 0x6e, 0x0f, 0xc3, 0x5f, 0x81, 0xfc, 0x42, 0xb9, 0xce, 0x7f, 0xba, 0x75,
-				0xeb, 0xad, 0x0e, 0xf9, 0x12, 0x70, 0xfb, 0x85, 0x28, 0x9f, 0x3d, 0xa4, 0x11, 0xbb, 0x94, 0x82,
-				0xc9, 0x0e, 0x28, 0x0f, 0x48, 0x24, 0xcd, 0xae, 0xa9, 0xd6, 0xc6, 0x57, 0x36, 0xbf, 0xac, 0xe1,
-				0x04, 0xcc, 0x65, 0xea, 0x70, 0xfe, 0x8c, 0xe2, 0x3a, 0x22, 0xd6, 0x3d, 0xae, 0x23, 0x63, 0x07,
-				0xab, 0x2e, 0x99, 0x25, 0x08, 0xc4, 0x1e, 0xad, 0x64, 0xd3, 0x98, 0xd4, 0x03, 0x82, 0x1a, 0xf3,
-				0xf8, 0x7f, 0x35, 0xe0, 0x83, 0xe0, 0xb2, 0xbf, 0x9f, 0x53, 0xf1, 0x1e, 0xec, 0x5f, 0xf8, 0xac,
-				0xcf, 0x9a, 0xd4, 0x5d, 0xe0, 0xf5, 0xb3, 0x9d, 0x16, 0x2f, 0x60, 0xc1, 0xa5, 0x63, 0xe7, 0xed,
-				0x02, 0x81, 0x80, 0x0d, 0xea, 0xb6, 0x39, 0x6b, 0x6b, 0xad, 0x98, 0x90, 0x0e, 0x99, 0x93, 0xdf,
-				0xb8, 0x5f, 0x09, 0x48, 0x39, 0x55, 0x85, 0xed, 0x35, 0x79, 0x0e, 0x03, 0xb1, 0x04, 0x06, 0x9e,
-				0x4f, 0xcb, 0xdf, 0xc2, 0xf1, 0xb3, 0xc8, 0x42, 0xec, 0x9f, 0xd1, 0x4c, 0xe1, 0x8a, 0x44, 0x9b,
-				0xe0, 0xe0, 0x2e, 0xa6, 0x3d, 0x7c, 0x48, 0x7e, 0xbf, 0xde, 0xb8, 0x51, 0xd1, 0x08, 0xf8, 0x88,
-				0x70, 0x83, 0x76, 0x54, 0x07, 0x54, 0x92, 0x03, 0x6e, 0xd5, 0x55, 0xf7, 0x0f, 0x82, 0xc5, 0x45,
-				0x81, 0xf0, 0x47, 0x3b, 0x5f, 0xc6, 0x52, 0xc9, 0x10, 0x79, 0x7c, 0xa0, 0xa7, 0x12, 0x17, 0xd3,
-				0x3b, 0xc2, 0x35, 0xa1, 0xcf, 0x3f, 0xa5, 0x71, 0x96, 0x9f, 0x75, 0x7f, 0xfa, 0xe8, 0x2d, 0xb5,
-				0x92, 0x1f, 0xc6, 0xe2, 0x06, 0x8e, 0x1b, 0x06, 0x8c, 0x4d, 0xc7, 0x1a, 0x00, 0xee, 0x59, 0x34,
-				0xe3, 0x8d, 0xd1, 0x02, 0x81, 0x80, 0x44, 0x9b, 0x6e, 0xb6, 0x1e, 0x84, 0x3c, 0xab, 0x43, 0x3e,
-				0x20, 0x9a, 0xd2, 0x94, 0x39, 0x38, 0x01, 0x25, 0x67, 0x59, 0x45, 0x2d, 0xcd, 0x7a, 0xcd, 0xea,
-				0x72, 0x2a, 0x32, 0x71, 0x66, 0x82, 0x04, 0x85, 0xc9, 0x06, 0xf0, 0x26, 0xa6, 0x2d, 0x41, 0x49,
-				0x3e, 0xa3, 0x68, 0x98, 0xf1, 0x05, 0x00, 0xb5, 0xa0, 0x35, 0x01, 0x39, 0xee, 0x29, 0x1d, 0x8a,
-				0xea, 0x4e, 0x3b, 0x40, 0x78, 0xe9, 0x97, 0x77, 0x5b, 0xc1, 0x8f, 0xac, 0x2c, 0x45, 0x49, 0x33,
-				0xc4, 0x33, 0xa4, 0x67, 0xbf, 0xe9, 0x6d, 0xb5, 0x1e, 0x36, 0x0f, 0x6a, 0xb4, 0x8c, 0x77, 0xdd,
-				0x5a, 0x74, 0x66, 0xf5, 0xb3, 0x9b, 0x78, 0x03, 0x02, 0xf7, 0x21, 0xbd, 0xc2, 0x74, 0x56, 0x10,
-				0xa2, 0x4f, 0x43, 0xbf, 0xa2, 0xd0, 0xa9, 0xcc, 0xf4, 0xd6, 0xa6, 0x96, 0xae, 0xeb, 0x88, 0x3b,
-				0x53, 0x5d, 0xe1, 0x71, 0x52, 0x0a
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( RSASHA256 );
-
-//===========================================================================================================================
-// MARK: - RSA/SHA-512 DNS Keys
-
-typedef struct
-{
-	DNSKeyRSASHA512Info		ksk;	// Key-Signing Key
-	DNSKeyRSASHA512Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyRSASHA512Set;
-
-static const DNSKeyRSASHA512Set		kDNSKeyRSASHA512Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0x9d, 0x14, 0x59, 0x1b, 0x69, 0x68, 0x51, 0xfa, 0xea, 0xb2, 0xd6, 0x77,
-				0x89, 0x6d, 0xbc, 0xb0, 0x12, 0xd7, 0x88, 0x3b, 0x50, 0x70, 0x6f, 0x89, 0x10, 0x8c, 0x13, 0xeb,
-				0xe1, 0xc3, 0xa2, 0xc9, 0x87, 0xe6, 0x12, 0x00, 0x9a, 0x2c, 0x7e, 0x56, 0xa0, 0xfc, 0xb5, 0xba,
-				0xb9, 0xcb, 0xac, 0xac, 0x81, 0x1e, 0x63, 0x40, 0x09, 0xce, 0xd3, 0xd1, 0x38, 0xbc, 0xe9, 0xe0,
-				0x41, 0xea, 0x86, 0xe9, 0xba, 0x4f, 0xd2, 0x95, 0xc5, 0xa4, 0xad, 0x4a, 0x79, 0xf3, 0x40, 0x57,
-				0xa4, 0xdf, 0xed, 0x7f, 0x6f, 0x2f, 0x88, 0x1b, 0xf5, 0xff, 0x51, 0xa7, 0xa2, 0x2b, 0x5f, 0xbe,
-				0xc6, 0x02, 0x25, 0xcf, 0x3c, 0x81, 0x67, 0x7a, 0x12, 0x3a, 0x0f, 0x23, 0x14, 0xbe, 0x20, 0x17,
-				0x75, 0x1a, 0x99, 0x8c, 0x64, 0x68, 0x95, 0x4e, 0x9d, 0xa0, 0x90, 0xac, 0x48, 0xee, 0xf2, 0x5f,
-				0x22, 0x35, 0x87, 0x58, 0xa4, 0xfa, 0xed, 0x47, 0xb0, 0xb9, 0xbc, 0xef, 0x60, 0x60, 0x4f, 0x55,
-				0x8a, 0xf8, 0xb1, 0x87, 0xa2, 0x82, 0x20, 0xf7, 0x29, 0xdb, 0x82, 0x9d, 0xf6, 0xe5, 0x10, 0x20,
-				0xac, 0xc5, 0x88, 0x61, 0x15, 0xf8, 0xf4, 0x3b, 0x29, 0x17, 0xfc, 0xef, 0x91, 0xe0, 0xee, 0x31,
-				0xdd, 0xd3, 0x44, 0x55, 0x77, 0x7e, 0xef, 0xdd, 0x9c, 0x2a, 0x02, 0xd4, 0x24, 0x98, 0x59, 0x20,
-				0x2d, 0x96, 0x67, 0x1f, 0x13, 0xd9, 0xff, 0x6e, 0xec, 0x27, 0xee, 0xa3, 0x74, 0x19, 0x4a, 0xed,
-				0x3f, 0xed, 0xd6, 0xfc, 0x4c, 0xdb, 0x09, 0x5b, 0xd3, 0xf4, 0x51, 0x22, 0x68, 0xa4, 0x93, 0x7a,
-				0x46, 0x92, 0x4a, 0x75, 0xc1, 0x58, 0x95, 0xf0, 0x46, 0x6e, 0xda, 0x0f, 0x48, 0x2d, 0x0e, 0x0c,
-				0xca, 0xd6, 0x21, 0x67, 0x5d, 0x9e, 0xa7, 0x3f, 0xa0, 0x94, 0x57, 0x64, 0xa6, 0xd9, 0x0d, 0x48,
-				0x55, 0x0f, 0x60, 0x5f
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9d, 0x14, 0x59, 0x1b,
-				0x69, 0x68, 0x51, 0xfa, 0xea, 0xb2, 0xd6, 0x77, 0x89, 0x6d, 0xbc, 0xb0, 0x12, 0xd7, 0x88, 0x3b,
-				0x50, 0x70, 0x6f, 0x89, 0x10, 0x8c, 0x13, 0xeb, 0xe1, 0xc3, 0xa2, 0xc9, 0x87, 0xe6, 0x12, 0x00,
-				0x9a, 0x2c, 0x7e, 0x56, 0xa0, 0xfc, 0xb5, 0xba, 0xb9, 0xcb, 0xac, 0xac, 0x81, 0x1e, 0x63, 0x40,
-				0x09, 0xce, 0xd3, 0xd1, 0x38, 0xbc, 0xe9, 0xe0, 0x41, 0xea, 0x86, 0xe9, 0xba, 0x4f, 0xd2, 0x95,
-				0xc5, 0xa4, 0xad, 0x4a, 0x79, 0xf3, 0x40, 0x57, 0xa4, 0xdf, 0xed, 0x7f, 0x6f, 0x2f, 0x88, 0x1b,
-				0xf5, 0xff, 0x51, 0xa7, 0xa2, 0x2b, 0x5f, 0xbe, 0xc6, 0x02, 0x25, 0xcf, 0x3c, 0x81, 0x67, 0x7a,
-				0x12, 0x3a, 0x0f, 0x23, 0x14, 0xbe, 0x20, 0x17, 0x75, 0x1a, 0x99, 0x8c, 0x64, 0x68, 0x95, 0x4e,
-				0x9d, 0xa0, 0x90, 0xac, 0x48, 0xee, 0xf2, 0x5f, 0x22, 0x35, 0x87, 0x58, 0xa4, 0xfa, 0xed, 0x47,
-				0xb0, 0xb9, 0xbc, 0xef, 0x60, 0x60, 0x4f, 0x55, 0x8a, 0xf8, 0xb1, 0x87, 0xa2, 0x82, 0x20, 0xf7,
-				0x29, 0xdb, 0x82, 0x9d, 0xf6, 0xe5, 0x10, 0x20, 0xac, 0xc5, 0x88, 0x61, 0x15, 0xf8, 0xf4, 0x3b,
-				0x29, 0x17, 0xfc, 0xef, 0x91, 0xe0, 0xee, 0x31, 0xdd, 0xd3, 0x44, 0x55, 0x77, 0x7e, 0xef, 0xdd,
-				0x9c, 0x2a, 0x02, 0xd4, 0x24, 0x98, 0x59, 0x20, 0x2d, 0x96, 0x67, 0x1f, 0x13, 0xd9, 0xff, 0x6e,
-				0xec, 0x27, 0xee, 0xa3, 0x74, 0x19, 0x4a, 0xed, 0x3f, 0xed, 0xd6, 0xfc, 0x4c, 0xdb, 0x09, 0x5b,
-				0xd3, 0xf4, 0x51, 0x22, 0x68, 0xa4, 0x93, 0x7a, 0x46, 0x92, 0x4a, 0x75, 0xc1, 0x58, 0x95, 0xf0,
-				0x46, 0x6e, 0xda, 0x0f, 0x48, 0x2d, 0x0e, 0x0c, 0xca, 0xd6, 0x21, 0x67, 0x5d, 0x9e, 0xa7, 0x3f,
-				0xa0, 0x94, 0x57, 0x64, 0xa6, 0xd9, 0x0d, 0x48, 0x55, 0x0f, 0x60, 0x5f, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x02, 0x96, 0xce, 0x29, 0x31, 0x48, 0xb2, 0xaf, 0x72, 0xfa, 0x00,
-				0x18, 0x4d, 0x31, 0x98, 0x4c, 0x98, 0x71, 0x21, 0xe9, 0x0b, 0xed, 0xb5, 0x9e, 0x42, 0xbe, 0x01,
-				0xaa, 0x7f, 0xaa, 0x5c, 0xbb, 0x6d, 0x34, 0xe7, 0x28, 0x64, 0xb7, 0x7e, 0x95, 0x9a, 0xf4, 0xcf,
-				0x62, 0x04, 0xc0, 0x30, 0xad, 0x89, 0xe4, 0x2e, 0x8e, 0x2b, 0xe2, 0x53, 0x4b, 0x04, 0xa7, 0x48,
-				0x7d, 0x5c, 0xae, 0x1c, 0xb6, 0x47, 0xc0, 0x8d, 0x11, 0x97, 0xcd, 0x0d, 0x84, 0x64, 0x13, 0xf8,
-				0x59, 0x87, 0xb2, 0x66, 0x86, 0xa3, 0x6b, 0xa2, 0x41, 0x95, 0x81, 0x8a, 0xbb, 0x3b, 0x81, 0xba,
-				0x2e, 0x80, 0xcf, 0x3d, 0x24, 0x4d, 0x89, 0xe5, 0x62, 0xf5, 0x7c, 0x2c, 0x64, 0x24, 0xbf, 0x9a,
-				0xd7, 0x5d, 0x79, 0x36, 0x8b, 0x97, 0x69, 0x6d, 0x71, 0xec, 0xba, 0x50, 0x21, 0x0a, 0x67, 0x27,
-				0xa3, 0x8f, 0x91, 0x02, 0xbf, 0xa0, 0xe8, 0x84, 0x1b, 0x6f, 0xfc, 0xf2, 0x38, 0xf8, 0x35, 0x38,
-				0x1e, 0x7b, 0xc4, 0x5e, 0xcc, 0x03, 0xa8, 0xab, 0x6e, 0x2f, 0x99, 0xd3, 0xca, 0x58, 0x6e, 0xd5,
-				0xe9, 0x08, 0xeb, 0x03, 0xc2, 0x59, 0x0d, 0xb7, 0x7f, 0x8a, 0x76, 0x11, 0x3e, 0x92, 0x32, 0xba,
-				0x8a, 0x83, 0x5e, 0x92, 0x31, 0xa0, 0x4f, 0x50, 0x7b, 0xa7, 0x49, 0x84, 0x05, 0x7d, 0x96, 0x06,
-				0xe1, 0x52, 0xf5, 0xce, 0x4f, 0x74, 0x16, 0x64, 0x80, 0x7e, 0x7d, 0x39, 0x90, 0x33, 0x64, 0xd9,
-				0xa5, 0xf2, 0x44, 0x1e, 0x6d, 0x74, 0xd2, 0xbf, 0xc4, 0xcc, 0x59, 0x91, 0x93, 0xcf, 0x17, 0x9a,
-				0x6a, 0x97, 0x5b, 0xda, 0x89, 0xb2, 0x70, 0xe7, 0xcb, 0xc5, 0x64, 0xd7, 0x5d, 0x23, 0x02, 0x56,
-				0x35, 0x54, 0x2f, 0x7b, 0xf2, 0xc8, 0x47, 0xac, 0x61, 0xaf, 0x36, 0x84, 0x92, 0x98, 0x9d, 0x97,
-				0x14, 0xdb, 0xe7, 0x54, 0xf1, 0x02, 0x81, 0x81, 0x00, 0xcb, 0x0c, 0x61, 0xd8, 0xb7, 0xb2, 0xc9,
-				0x18, 0x32, 0xfd, 0x4a, 0x3e, 0xf9, 0x22, 0xbe, 0xa2, 0x9b, 0x9f, 0xf9, 0xa2, 0x63, 0x9a, 0xe1,
-				0x64, 0x53, 0x81, 0x3e, 0x1a, 0x97, 0xf9, 0x6a, 0xf1, 0xc3, 0x59, 0x23, 0xe2, 0x74, 0x09, 0x52,
-				0x16, 0xfe, 0x35, 0xa5, 0x80, 0x26, 0x9e, 0x5d, 0xbc, 0xb4, 0xeb, 0x88, 0x9e, 0xa1, 0x58, 0x6c,
-				0x7f, 0x17, 0x0f, 0x2f, 0xa6, 0x2e, 0xc1, 0x61, 0x33, 0xbf, 0x9b, 0xd0, 0xbf, 0x60, 0x09, 0x7d,
-				0xa4, 0xa1, 0x9b, 0x7a, 0x95, 0x95, 0x47, 0x93, 0x8a, 0xad, 0x5d, 0x3c, 0x49, 0x77, 0x67, 0x3e,
-				0xe8, 0xa3, 0xa4, 0xd0, 0xce, 0x33, 0xa6, 0x55, 0xf3, 0xa7, 0xdf, 0xbe, 0x62, 0x2b, 0xe4, 0x5d,
-				0x7f, 0x49, 0x40, 0xbe, 0xb8, 0xac, 0x77, 0x20, 0x40, 0x19, 0xfc, 0x4a, 0xae, 0xfc, 0x42, 0xe4,
-				0x73, 0xb1, 0xb1, 0xf7, 0x3b, 0x2c, 0x2b, 0xb0, 0xab, 0x02, 0x81, 0x81, 0x00, 0xc6, 0x0b, 0x0e,
-				0xff, 0xd4, 0x3a, 0xb9, 0x59, 0xc9, 0x98, 0xa8, 0xe4, 0x24, 0xfc, 0xc9, 0x5b, 0x5c, 0x3f, 0x6d,
-				0x46, 0xe3, 0xd8, 0xb5, 0xb9, 0x23, 0x3d, 0xdf, 0xa4, 0x4c, 0x66, 0x1a, 0x29, 0xaa, 0x8e, 0xd4,
-				0xa1, 0x57, 0x32, 0x8c, 0x77, 0x2c, 0xd2, 0xf9, 0xb8, 0x44, 0x67, 0xc5, 0xbd, 0x81, 0x6b, 0x08,
-				0x61, 0x1b, 0x9d, 0x59, 0xb0, 0x26, 0x3e, 0x88, 0x29, 0x90, 0x05, 0xc0, 0x94, 0x05, 0xea, 0x4e,
-				0x8c, 0x4a, 0x75, 0xf4, 0xe5, 0xa1, 0xf3, 0x0f, 0x74, 0xb4, 0x6d, 0xf5, 0x8c, 0x8d, 0xcc, 0xde,
-				0x15, 0x8b, 0xc1, 0xa5, 0xac, 0xae, 0x8b, 0xa5, 0xb6, 0xa8, 0xf6, 0x24, 0xcd, 0x63, 0x45, 0x04,
-				0x5e, 0xaf, 0xf6, 0x37, 0x35, 0x89, 0x2f, 0x89, 0x64, 0x16, 0x7d, 0x4e, 0xaa, 0x14, 0x8c, 0xc5,
-				0x41, 0x5f, 0x8b, 0x2a, 0xbc, 0xf5, 0xbd, 0x91, 0x05, 0x57, 0xb7, 0x17, 0x1d, 0x02, 0x81, 0x80,
-				0x11, 0x5c, 0xc9, 0xb1, 0x22, 0x64, 0x23, 0x55, 0xf2, 0x66, 0x3e, 0x47, 0x0c, 0x3e, 0xb0, 0x56,
-				0x6f, 0x40, 0x4a, 0xb4, 0x5c, 0x18, 0x0e, 0x55, 0xe9, 0xde, 0x0f, 0x55, 0x6e, 0xd1, 0x61, 0x17,
-				0xb3, 0x40, 0x98, 0x14, 0xf1, 0x1f, 0x2a, 0xe9, 0xd4, 0x6a, 0xf9, 0xef, 0xef, 0x5d, 0x73, 0x5e,
-				0x83, 0x89, 0xf0, 0x70, 0xc0, 0x13, 0x33, 0x93, 0xda, 0x80, 0xed, 0xee, 0x23, 0xe9, 0x5d, 0x4a,
-				0x73, 0x83, 0xfb, 0x61, 0xa1, 0xf0, 0xad, 0xd1, 0xba, 0x0f, 0xf5, 0x77, 0x7d, 0x00, 0x55, 0xd9,
-				0x71, 0xe1, 0x9b, 0x1a, 0x1d, 0x1f, 0xb2, 0xfd, 0x69, 0xa0, 0xda, 0x4a, 0x07, 0x98, 0x9d, 0x98,
-				0xec, 0x2d, 0xf1, 0xb5, 0xab, 0x53, 0x27, 0xbb, 0x8e, 0xa3, 0xfe, 0xab, 0x03, 0xf4, 0x5b, 0xc9,
-				0x9f, 0x6f, 0x37, 0x63, 0xa7, 0x26, 0x81, 0x2a, 0x73, 0x73, 0x68, 0x54, 0xa2, 0xfe, 0x49, 0x69,
-				0x02, 0x81, 0x80, 0x65, 0x10, 0x17, 0xa3, 0x6e, 0x06, 0x59, 0xb7, 0xfc, 0x2c, 0xaf, 0x63, 0x5d,
-				0x8c, 0xb2, 0xa4, 0xb0, 0xba, 0x9d, 0x65, 0x63, 0xb8, 0x9f, 0x63, 0xcf, 0x1c, 0x30, 0x18, 0x83,
-				0xf4, 0x46, 0xbd, 0xa4, 0x90, 0x26, 0xe9, 0xfe, 0xb9, 0x88, 0xfc, 0xf8, 0x1e, 0xe1, 0xd8, 0xaa,
-				0xef, 0xd9, 0xf5, 0x0f, 0x2a, 0x33, 0xa8, 0x7a, 0x93, 0x1d, 0xc5, 0xca, 0x7e, 0x76, 0xb5, 0xdf,
-				0x0d, 0x50, 0x6d, 0x39, 0x67, 0x8c, 0x96, 0x03, 0x19, 0x96, 0xd3, 0xe8, 0x85, 0x45, 0x09, 0xe5,
-				0x59, 0x87, 0xc9, 0x26, 0x43, 0xb9, 0xc1, 0x7d, 0x04, 0x61, 0x2b, 0x72, 0x17, 0x49, 0x85, 0xa1,
-				0x4b, 0x9b, 0x14, 0x44, 0xe8, 0x5f, 0x86, 0x82, 0x7d, 0x3f, 0x47, 0x4e, 0xae, 0xb7, 0x8a, 0x1f,
-				0xff, 0xea, 0x38, 0xd9, 0x2b, 0xcd, 0x2d, 0xc3, 0x38, 0x1d, 0xa3, 0x38, 0x34, 0x78, 0xe1, 0x25,
-				0x16, 0x05, 0xf1, 0x02, 0x81, 0x80, 0x19, 0xcb, 0xe3, 0x33, 0xd8, 0x26, 0xad, 0x8b, 0x32, 0xfb,
-				0xdb, 0x2d, 0x8b, 0xb7, 0x99, 0xd0, 0xf6, 0xc3, 0xa1, 0xf0, 0x6e, 0x53, 0x7c, 0xbf, 0xdf, 0xd5,
-				0xc4, 0x43, 0x81, 0x09, 0xf5, 0x2a, 0x0b, 0xe9, 0xf4, 0xf3, 0xc1, 0x4e, 0xa4, 0xdc, 0x94, 0x11,
-				0x17, 0xa7, 0x26, 0x43, 0xee, 0xf3, 0xf0, 0xce, 0x24, 0xb8, 0xcb, 0x86, 0x3a, 0x37, 0xb1, 0xc9,
-				0x3e, 0x96, 0x68, 0x00, 0xad, 0xf0, 0x9a, 0xd6, 0xc3, 0x25, 0xa6, 0x3a, 0x0c, 0xe6, 0x61, 0xc5,
-				0x05, 0x80, 0xb6, 0xd6, 0xa7, 0x40, 0xd1, 0xb2, 0xad, 0xb5, 0x35, 0xa4, 0xdd, 0x63, 0x32, 0x5d,
-				0x09, 0x59, 0x9a, 0x80, 0x00, 0xf6, 0x4f, 0xdf, 0x41, 0xa3, 0xc6, 0x3f, 0xe8, 0xe2, 0x67, 0xa1,
-				0x87, 0x56, 0x26, 0x1b, 0xc9, 0x8c, 0xe9, 0x24, 0x4d, 0xa5, 0x29, 0xce, 0x37, 0x36, 0xa8, 0xd2,
-				0x7a, 0x1f, 0x01, 0x10, 0x6c, 0x43
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xc8, 0xc4, 0xc6, 0xc6, 0x72, 0xb0, 0xa6, 0x5e, 0x8a, 0xe2, 0x26, 0x35,
-				0x1a, 0xad, 0x21, 0x9c, 0x0d, 0x6f, 0xe2, 0x91, 0x95, 0xe7, 0x73, 0xf3, 0xc4, 0x43, 0xe2, 0x86,
-				0x4a, 0x96, 0xc6, 0x2c, 0x0b, 0x1f, 0xa4, 0xf1, 0x36, 0xc3, 0xa9, 0xcd, 0x53, 0xf5, 0x8e, 0x78,
-				0x62, 0xad, 0x9e, 0x55, 0x4d, 0x6b, 0xb9, 0xaf, 0xf9, 0x22, 0x88, 0x61, 0xc5, 0xac, 0x57, 0x84,
-				0x6f, 0x85, 0xf8, 0x0e, 0x66, 0xd8, 0x67, 0x75, 0x69, 0x8e, 0x2d, 0xfa, 0x29, 0x2d, 0xe5, 0xde,
-				0x1c, 0xe0, 0x9c, 0xa0, 0xcf, 0xf5, 0xec, 0xe2, 0xaa, 0x5a, 0x19, 0x70, 0x87, 0xd0, 0xbe, 0x1a,
-				0x56, 0x63, 0x74, 0x2a, 0x6f, 0x6f, 0x35, 0xc8, 0x83, 0xe5, 0x8b, 0x44, 0x89, 0x86, 0xa2, 0xbb,
-				0xb1, 0x16, 0x9a, 0x06, 0x35, 0x21, 0x78, 0xd9, 0x07, 0x27, 0x37, 0xbd, 0x24, 0xca, 0xb9, 0xef,
-				0x5b, 0x71, 0xd0, 0xc0, 0x8b, 0xec, 0xe4, 0x8d, 0xeb, 0x32, 0x7c, 0x41, 0x5c, 0xe0, 0xda, 0xb2,
-				0x1c, 0x0f, 0xcd, 0x8b, 0xa7, 0xa8, 0x31, 0x07, 0x4e, 0xd1, 0xe2, 0xd4, 0xae, 0x48, 0x84, 0xa0,
-				0xee, 0x87, 0x25, 0x3c, 0xdb, 0x1f, 0x85, 0x96, 0xd7, 0x1d, 0x4b, 0x51, 0x4c, 0x92, 0xe5, 0x47,
-				0x9b, 0x67, 0x79, 0x62, 0x0d, 0xe2, 0xa7, 0x01, 0xab, 0x72, 0x0c, 0x38, 0xed, 0xab, 0x88, 0x86,
-				0xcf, 0x7e, 0x84, 0xd3, 0x1c, 0x09, 0x26, 0xb3, 0x6b, 0x41, 0x4f, 0x09, 0xef, 0xe5, 0xcc, 0xda,
-				0x9b, 0x09, 0x55, 0xee, 0x3e, 0xe5, 0x89, 0x11, 0x63, 0x1a, 0x2a, 0xe8, 0xfa, 0xf1, 0x44, 0x9b,
-				0x92, 0x46, 0x2d, 0x3f, 0x88, 0x26, 0xc1, 0x44, 0xda, 0x9f, 0x02, 0x09, 0x2d, 0x7d, 0xea, 0xc2,
-				0x63, 0xc5, 0xa7, 0x62, 0x27, 0x42, 0x1a, 0x48, 0xde, 0xf2, 0xa9, 0xf2, 0x80, 0x9b, 0xfc, 0x5b,
-				0x97, 0xef, 0xfb, 0x6f
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, 0xc4, 0xc6, 0xc6,
-				0x72, 0xb0, 0xa6, 0x5e, 0x8a, 0xe2, 0x26, 0x35, 0x1a, 0xad, 0x21, 0x9c, 0x0d, 0x6f, 0xe2, 0x91,
-				0x95, 0xe7, 0x73, 0xf3, 0xc4, 0x43, 0xe2, 0x86, 0x4a, 0x96, 0xc6, 0x2c, 0x0b, 0x1f, 0xa4, 0xf1,
-				0x36, 0xc3, 0xa9, 0xcd, 0x53, 0xf5, 0x8e, 0x78, 0x62, 0xad, 0x9e, 0x55, 0x4d, 0x6b, 0xb9, 0xaf,
-				0xf9, 0x22, 0x88, 0x61, 0xc5, 0xac, 0x57, 0x84, 0x6f, 0x85, 0xf8, 0x0e, 0x66, 0xd8, 0x67, 0x75,
-				0x69, 0x8e, 0x2d, 0xfa, 0x29, 0x2d, 0xe5, 0xde, 0x1c, 0xe0, 0x9c, 0xa0, 0xcf, 0xf5, 0xec, 0xe2,
-				0xaa, 0x5a, 0x19, 0x70, 0x87, 0xd0, 0xbe, 0x1a, 0x56, 0x63, 0x74, 0x2a, 0x6f, 0x6f, 0x35, 0xc8,
-				0x83, 0xe5, 0x8b, 0x44, 0x89, 0x86, 0xa2, 0xbb, 0xb1, 0x16, 0x9a, 0x06, 0x35, 0x21, 0x78, 0xd9,
-				0x07, 0x27, 0x37, 0xbd, 0x24, 0xca, 0xb9, 0xef, 0x5b, 0x71, 0xd0, 0xc0, 0x8b, 0xec, 0xe4, 0x8d,
-				0xeb, 0x32, 0x7c, 0x41, 0x5c, 0xe0, 0xda, 0xb2, 0x1c, 0x0f, 0xcd, 0x8b, 0xa7, 0xa8, 0x31, 0x07,
-				0x4e, 0xd1, 0xe2, 0xd4, 0xae, 0x48, 0x84, 0xa0, 0xee, 0x87, 0x25, 0x3c, 0xdb, 0x1f, 0x85, 0x96,
-				0xd7, 0x1d, 0x4b, 0x51, 0x4c, 0x92, 0xe5, 0x47, 0x9b, 0x67, 0x79, 0x62, 0x0d, 0xe2, 0xa7, 0x01,
-				0xab, 0x72, 0x0c, 0x38, 0xed, 0xab, 0x88, 0x86, 0xcf, 0x7e, 0x84, 0xd3, 0x1c, 0x09, 0x26, 0xb3,
-				0x6b, 0x41, 0x4f, 0x09, 0xef, 0xe5, 0xcc, 0xda, 0x9b, 0x09, 0x55, 0xee, 0x3e, 0xe5, 0x89, 0x11,
-				0x63, 0x1a, 0x2a, 0xe8, 0xfa, 0xf1, 0x44, 0x9b, 0x92, 0x46, 0x2d, 0x3f, 0x88, 0x26, 0xc1, 0x44,
-				0xda, 0x9f, 0x02, 0x09, 0x2d, 0x7d, 0xea, 0xc2, 0x63, 0xc5, 0xa7, 0x62, 0x27, 0x42, 0x1a, 0x48,
-				0xde, 0xf2, 0xa9, 0xf2, 0x80, 0x9b, 0xfc, 0x5b, 0x97, 0xef, 0xfb, 0x6f, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x01, 0x02, 0x32, 0xb9, 0xd7, 0x17, 0x75, 0x7d, 0xf8, 0x4b, 0xc6,
-				0xe1, 0x6d, 0x59, 0x2e, 0x2d, 0x46, 0xf3, 0x56, 0x4e, 0xcf, 0xec, 0xce, 0xd6, 0xd0, 0x7e, 0xa1,
-				0x13, 0x98, 0xc3, 0xba, 0xce, 0xcc, 0xb3, 0xa3, 0xb1, 0xeb, 0xb8, 0xf1, 0x72, 0x77, 0x95, 0xcf,
-				0x62, 0x3f, 0xe8, 0x1f, 0xb6, 0x34, 0x0f, 0x43, 0xd9, 0x5f, 0xf6, 0xdc, 0xe1, 0x66, 0x76, 0x0d,
-				0xe1, 0xd5, 0x12, 0x87, 0x0d, 0xdb, 0x33, 0x68, 0xe8, 0xd8, 0x52, 0xf0, 0x8f, 0xdb, 0x54, 0x1a,
-				0x44, 0x16, 0xe2, 0xd9, 0x50, 0x2f, 0x80, 0x99, 0x68, 0x59, 0xf7, 0x55, 0x2c, 0xa6, 0xa5, 0xc0,
-				0x0b, 0x00, 0x6d, 0xc4, 0x35, 0x76, 0xc4, 0x0c, 0x5b, 0x9e, 0xe2, 0x8a, 0x6c, 0x99, 0xaf, 0x99,
-				0xc3, 0xc0, 0x7c, 0x7e, 0xe1, 0x85, 0xf8, 0x12, 0xb6, 0x2d, 0xbb, 0xfc, 0xcd, 0x65, 0x7b, 0x8d,
-				0xc5, 0x3c, 0xe4, 0x77, 0x50, 0xb1, 0xc0, 0x99, 0x75, 0xca, 0xb9, 0x43, 0x23, 0xf5, 0x2b, 0xfa,
-				0x77, 0x5c, 0x23, 0x2f, 0x50, 0x75, 0x41, 0x2b, 0xd7, 0x35, 0xe2, 0xe4, 0x44, 0x45, 0xf1, 0xc0,
-				0xce, 0x86, 0x53, 0x26, 0x02, 0x43, 0x47, 0x65, 0x15, 0x45, 0xc4, 0x14, 0xcd, 0xb5, 0xdb, 0x33,
-				0x4f, 0x4b, 0xcf, 0xda, 0xf0, 0x7f, 0xe8, 0x0c, 0xae, 0xca, 0x49, 0xf5, 0x26, 0x60, 0x69, 0x17,
-				0xf9, 0x19, 0x5a, 0x7f, 0x92, 0xe8, 0xc6, 0x52, 0x4d, 0x93, 0x24, 0xd6, 0x2e, 0x7a, 0xd4, 0xbc,
-				0x02, 0x14, 0x40, 0x93, 0xa2, 0xa6, 0xe8, 0xfb, 0x74, 0xbc, 0x17, 0x2b, 0x83, 0x9c, 0xdf, 0x2b,
-				0xe0, 0x6c, 0xf6, 0x47, 0x1e, 0x3a, 0x75, 0xb6, 0xc0, 0x07, 0x84, 0x44, 0x32, 0x36, 0xbb, 0x5c,
-				0x3a, 0x4e, 0x55, 0x14, 0x70, 0x8f, 0x08, 0x96, 0x20, 0xc2, 0x37, 0x49, 0xdc, 0x85, 0xdb, 0x26,
-				0x7e, 0x1c, 0x83, 0xcb, 0xcd, 0x02, 0x81, 0x81, 0x00, 0xff, 0x1d, 0x80, 0x38, 0x5f, 0xc6, 0xd8,
-				0xbb, 0xf3, 0xae, 0x35, 0x56, 0x04, 0x01, 0xdf, 0x69, 0xf5, 0x05, 0xbe, 0x5a, 0x0f, 0x19, 0x97,
-				0x84, 0xf8, 0xb2, 0xe5, 0x55, 0xb0, 0xd7, 0x49, 0x28, 0xfa, 0xf0, 0x2a, 0x71, 0xa8, 0x17, 0x14,
-				0x5a, 0xb1, 0x34, 0x40, 0x42, 0xf7, 0x9d, 0x8e, 0x2a, 0x1d, 0x26, 0x64, 0x57, 0xbd, 0xaf, 0xe4,
-				0x13, 0xec, 0xa2, 0xde, 0xd2, 0x68, 0xbd, 0xe9, 0xef, 0x77, 0x64, 0x31, 0xf9, 0xd0, 0xb9, 0x18,
-				0x4a, 0xf2, 0xdd, 0xbe, 0x9d, 0xd6, 0x57, 0xda, 0x1b, 0x66, 0x98, 0xbf, 0x5d, 0xeb, 0x28, 0x5b,
-				0xdf, 0x13, 0x81, 0x96, 0xd7, 0x8a, 0x75, 0xee, 0xaa, 0x45, 0x14, 0x6a, 0x75, 0x86, 0x99, 0x19,
-				0xc7, 0x7e, 0x36, 0xf6, 0xb6, 0x52, 0xe5, 0x2c, 0x2a, 0x1c, 0xe7, 0x93, 0x7a, 0xe5, 0xf1, 0x1a,
-				0xc8, 0x5f, 0x89, 0xf4, 0x9a, 0x68, 0x88, 0x51, 0x03, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x77, 0x06,
-				0x69, 0x41, 0x67, 0xf5, 0xd2, 0xdf, 0x69, 0x4e, 0x16, 0x57, 0xf6, 0x18, 0xb5, 0x75, 0x8c, 0x0e,
-				0xcc, 0xc5, 0x68, 0x4b, 0x21, 0x9d, 0xfa, 0x54, 0x32, 0xcd, 0x09, 0xed, 0x61, 0xf3, 0xe3, 0xe8,
-				0xf8, 0xed, 0x96, 0xdd, 0x86, 0x26, 0x8b, 0x96, 0x9c, 0x24, 0xed, 0x98, 0x50, 0x3e, 0x10, 0x95,
-				0x28, 0x89, 0xc7, 0x42, 0x31, 0x37, 0x75, 0xe5, 0xc3, 0xa5, 0x9b, 0x85, 0x15, 0xe9, 0xed, 0x63,
-				0xf2, 0x0b, 0x52, 0x62, 0xfa, 0x05, 0x8c, 0x36, 0x09, 0xc3, 0xd8, 0xae, 0xbb, 0x53, 0xc0, 0x20,
-				0x84, 0x0d, 0x84, 0xaf, 0xdf, 0x2c, 0xc8, 0x06, 0x33, 0xf8, 0x3b, 0xcc, 0x0b, 0x07, 0x3e, 0x7f,
-				0x3c, 0x4a, 0x6f, 0xb9, 0x47, 0xfc, 0xb0, 0xdc, 0xed, 0x89, 0xe7, 0x1c, 0xc4, 0x48, 0x2f, 0xca,
-				0x5d, 0xa1, 0xe1, 0xda, 0x2a, 0x2a, 0xdc, 0xd5, 0x3e, 0x22, 0x48, 0xc2, 0x25, 0x02, 0x81, 0x80,
-				0x0b, 0xd5, 0x72, 0x7d, 0x2a, 0xf4, 0x2e, 0x59, 0x89, 0x94, 0x2b, 0x25, 0x32, 0x4a, 0x63, 0xf2,
-				0xa6, 0x4a, 0xfd, 0xe9, 0x6f, 0x89, 0xe0, 0x5d, 0x6a, 0xab, 0xe1, 0xb7, 0x77, 0xdc, 0x84, 0xa8,
-				0x41, 0xfb, 0xa1, 0xfc, 0x63, 0xaf, 0xae, 0x62, 0x06, 0x96, 0x45, 0xe4, 0xd5, 0x57, 0x99, 0xa0,
-				0x9a, 0x79, 0x8d, 0x6e, 0x04, 0x7e, 0x84, 0x35, 0xe8, 0x64, 0x25, 0xb1, 0xdc, 0xe9, 0xf2, 0x50,
-				0x09, 0x59, 0xbc, 0x77, 0xba, 0x16, 0xdb, 0xe9, 0x9e, 0x1a, 0x6b, 0x1d, 0x27, 0x34, 0x2c, 0x09,
-				0xd9, 0x58, 0x7c, 0x87, 0xfe, 0xc0, 0x80, 0x82, 0x78, 0x85, 0x2a, 0x5a, 0x15, 0x32, 0x23, 0x40,
-				0x02, 0xb4, 0x4f, 0xbb, 0xe3, 0xe2, 0x76, 0x2f, 0xaa, 0xcb, 0x21, 0xe6, 0x93, 0x31, 0xce, 0x3a,
-				0xa5, 0xdc, 0x98, 0x1a, 0xbb, 0x4f, 0xd3, 0xce, 0x37, 0xa0, 0x4e, 0x98, 0x5b, 0x00, 0xf7, 0xc1,
-				0x02, 0x81, 0x80, 0x7b, 0xc0, 0xaa, 0x66, 0x83, 0x6f, 0xd9, 0xb7, 0xe3, 0xd6, 0x6a, 0xca, 0x1c,
-				0xd4, 0x25, 0xcf, 0x69, 0x5a, 0x54, 0x49, 0x02, 0xc6, 0x12, 0xc8, 0x9e, 0xa3, 0x03, 0x8f, 0x85,
-				0x15, 0xa1, 0x04, 0xb7, 0x6c, 0xfb, 0x51, 0xd5, 0x98, 0x03, 0x91, 0x81, 0x21, 0xe3, 0xad, 0x1c,
-				0x9d, 0xfa, 0x1e, 0xe8, 0x51, 0x05, 0x5e, 0xb6, 0x6b, 0x78, 0xc4, 0x84, 0xbd, 0xde, 0x1a, 0x75,
-				0x22, 0xf7, 0xf8, 0x43, 0x0e, 0xb8, 0x83, 0x18, 0xe3, 0x4d, 0xbb, 0x29, 0x27, 0x3c, 0x96, 0x79,
-				0x00, 0x24, 0x2d, 0x1b, 0xbf, 0xfb, 0xf9, 0x41, 0xd8, 0x8c, 0xb3, 0xf9, 0x6d, 0x11, 0x2a, 0x61,
-				0x44, 0x52, 0x0d, 0x40, 0x30, 0xea, 0xb5, 0x5d, 0x40, 0x0d, 0xbf, 0x23, 0x80, 0x7c, 0xe5, 0x48,
-				0xfd, 0x77, 0x55, 0x36, 0xc6, 0x6c, 0x77, 0x61, 0x96, 0x3b, 0x8e, 0x05, 0x70, 0x4b, 0x68, 0xf4,
-				0x64, 0x5f, 0x25, 0x02, 0x81, 0x80, 0x59, 0x97, 0x37, 0x4d, 0xf5, 0x4d, 0x46, 0xe2, 0xb4, 0x43,
-				0x51, 0xa2, 0x8a, 0x0f, 0x02, 0x12, 0xf0, 0xa2, 0x94, 0x91, 0xdd, 0x65, 0x7f, 0xb0, 0x7d, 0xb5,
-				0x68, 0xf1, 0x80, 0xa6, 0x4c, 0x6a, 0x65, 0x19, 0xcf, 0x4f, 0x90, 0x95, 0x5e, 0x45, 0x06, 0xd6,
-				0xda, 0x07, 0x54, 0xa7, 0x8e, 0x8e, 0x85, 0x4c, 0x2c, 0x68, 0x72, 0x20, 0xf0, 0x5d, 0xad, 0x38,
-				0x5b, 0x91, 0x50, 0x5f, 0x7e, 0x7c, 0x94, 0x2f, 0x92, 0x7b, 0x2f, 0x51, 0x5b, 0x71, 0x11, 0xd7,
-				0x58, 0x13, 0x5c, 0x00, 0xeb, 0xfe, 0x1a, 0xbf, 0x6c, 0xfe, 0x26, 0xb4, 0xac, 0x42, 0x70, 0x52,
-				0xb4, 0xf7, 0x9c, 0x75, 0x0c, 0x38, 0xf5, 0x50, 0x01, 0x45, 0x9f, 0x5d, 0x5f, 0x7d, 0xa1, 0x65,
-				0x52, 0xca, 0xed, 0x30, 0x37, 0x4d, 0x74, 0xda, 0xcf, 0xb1, 0x18, 0xdb, 0x6d, 0x68, 0x75, 0xd3,
-				0xc0, 0x6d, 0x74, 0x6e, 0x58, 0x32
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xd1, 0x2a, 0x16, 0x41, 0xce, 0xe4, 0xc4, 0xe8, 0x7f, 0x68, 0x4c, 0xb5,
-				0xe6, 0x99, 0x5a, 0x5c, 0x07, 0x2d, 0x08, 0x9e, 0x27, 0xf5, 0x4a, 0xdc, 0x77, 0x2d, 0x11, 0xbf,
-				0x4b, 0x88, 0x6e, 0x46, 0x88, 0xb9, 0x0b, 0x42, 0x48, 0xd9, 0xa9, 0x83, 0xb3, 0xef, 0xe5, 0x0e,
-				0xbb, 0x3f, 0x5c, 0xe5, 0x99, 0x87, 0xef, 0xd6, 0xa0, 0x00, 0x60, 0x23, 0xa1, 0xd2, 0xb6, 0x27,
-				0x80, 0xe4, 0x66, 0xe6, 0xea, 0x22, 0xfd, 0xe4, 0x47, 0x3a, 0xda, 0xa9, 0x8e, 0x10, 0x5e, 0x5f,
-				0xdb, 0x1e, 0xa6, 0x42, 0xba, 0x84, 0x10, 0x98, 0x9b, 0xa1, 0xd3, 0x0d, 0xa8, 0xc9, 0xdc, 0xb4,
-				0xc3, 0x93, 0x18, 0x87, 0xd9, 0x77, 0xf4, 0x2e, 0x89, 0x4b, 0xa3, 0x0a, 0x16, 0x63, 0x0d, 0x51,
-				0x1a, 0x86, 0xd7, 0x98, 0x6a, 0x8b, 0x11, 0xf3, 0x38, 0x87, 0xa6, 0x87, 0xc7, 0x76, 0xfe, 0x68,
-				0x2c, 0x53, 0x8b, 0x6d, 0x9c, 0xee, 0xe1, 0xb3, 0xda, 0xff, 0x22, 0xe2, 0x80, 0xe2, 0xae, 0x14,
-				0xf0, 0x5e, 0xd2, 0x03, 0x53, 0x72, 0xf1, 0x50, 0xad, 0x03, 0xb1, 0x29, 0xd9, 0x0c, 0x7a, 0xfc,
-				0x33, 0x76, 0x7e, 0x6a, 0xbf, 0x9d, 0x15, 0x6c, 0x09, 0x27, 0xe9, 0xe3, 0x66, 0x86, 0xe9, 0x42,
-				0x08, 0xd4, 0x8f, 0xfc, 0x52, 0x24, 0xe7, 0x27, 0xb2, 0x1d, 0x59, 0x90, 0x75, 0xf6, 0xfc, 0x54,
-				0x11, 0x6b, 0xb0, 0xad, 0x60, 0xab, 0xfe, 0x9a, 0xea, 0xf4, 0xf5, 0xf6, 0xd0, 0x36, 0x95, 0x9f,
-				0xda, 0x74, 0x9a, 0x59, 0x59, 0xd6, 0x8c, 0x74, 0xd3, 0x9a, 0xca, 0x91, 0x03, 0x36, 0x10, 0xf6,
-				0x3e, 0x5d, 0xf2, 0xab, 0x10, 0xcb, 0xe4, 0x25, 0xdd, 0x39, 0x44, 0x67, 0xf5, 0xaa, 0x72, 0x27,
-				0x30, 0x1b, 0xc3, 0xe7, 0x1e, 0x21, 0x0c, 0x57, 0xc5, 0xe6, 0x2c, 0xe3, 0xf2, 0x4b, 0x43, 0x65,
-				0xa0, 0xa3, 0xb5, 0xb7
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd1, 0x2a, 0x16, 0x41,
-				0xce, 0xe4, 0xc4, 0xe8, 0x7f, 0x68, 0x4c, 0xb5, 0xe6, 0x99, 0x5a, 0x5c, 0x07, 0x2d, 0x08, 0x9e,
-				0x27, 0xf5, 0x4a, 0xdc, 0x77, 0x2d, 0x11, 0xbf, 0x4b, 0x88, 0x6e, 0x46, 0x88, 0xb9, 0x0b, 0x42,
-				0x48, 0xd9, 0xa9, 0x83, 0xb3, 0xef, 0xe5, 0x0e, 0xbb, 0x3f, 0x5c, 0xe5, 0x99, 0x87, 0xef, 0xd6,
-				0xa0, 0x00, 0x60, 0x23, 0xa1, 0xd2, 0xb6, 0x27, 0x80, 0xe4, 0x66, 0xe6, 0xea, 0x22, 0xfd, 0xe4,
-				0x47, 0x3a, 0xda, 0xa9, 0x8e, 0x10, 0x5e, 0x5f, 0xdb, 0x1e, 0xa6, 0x42, 0xba, 0x84, 0x10, 0x98,
-				0x9b, 0xa1, 0xd3, 0x0d, 0xa8, 0xc9, 0xdc, 0xb4, 0xc3, 0x93, 0x18, 0x87, 0xd9, 0x77, 0xf4, 0x2e,
-				0x89, 0x4b, 0xa3, 0x0a, 0x16, 0x63, 0x0d, 0x51, 0x1a, 0x86, 0xd7, 0x98, 0x6a, 0x8b, 0x11, 0xf3,
-				0x38, 0x87, 0xa6, 0x87, 0xc7, 0x76, 0xfe, 0x68, 0x2c, 0x53, 0x8b, 0x6d, 0x9c, 0xee, 0xe1, 0xb3,
-				0xda, 0xff, 0x22, 0xe2, 0x80, 0xe2, 0xae, 0x14, 0xf0, 0x5e, 0xd2, 0x03, 0x53, 0x72, 0xf1, 0x50,
-				0xad, 0x03, 0xb1, 0x29, 0xd9, 0x0c, 0x7a, 0xfc, 0x33, 0x76, 0x7e, 0x6a, 0xbf, 0x9d, 0x15, 0x6c,
-				0x09, 0x27, 0xe9, 0xe3, 0x66, 0x86, 0xe9, 0x42, 0x08, 0xd4, 0x8f, 0xfc, 0x52, 0x24, 0xe7, 0x27,
-				0xb2, 0x1d, 0x59, 0x90, 0x75, 0xf6, 0xfc, 0x54, 0x11, 0x6b, 0xb0, 0xad, 0x60, 0xab, 0xfe, 0x9a,
-				0xea, 0xf4, 0xf5, 0xf6, 0xd0, 0x36, 0x95, 0x9f, 0xda, 0x74, 0x9a, 0x59, 0x59, 0xd6, 0x8c, 0x74,
-				0xd3, 0x9a, 0xca, 0x91, 0x03, 0x36, 0x10, 0xf6, 0x3e, 0x5d, 0xf2, 0xab, 0x10, 0xcb, 0xe4, 0x25,
-				0xdd, 0x39, 0x44, 0x67, 0xf5, 0xaa, 0x72, 0x27, 0x30, 0x1b, 0xc3, 0xe7, 0x1e, 0x21, 0x0c, 0x57,
-				0xc5, 0xe6, 0x2c, 0xe3, 0xf2, 0x4b, 0x43, 0x65, 0xa0, 0xa3, 0xb5, 0xb7, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x19, 0xdc, 0x4e, 0x6d, 0xd5, 0x82, 0xdd, 0xc0, 0xf1, 0xdb, 0xb7,
-				0x3c, 0x4d, 0x90, 0xb6, 0xa6, 0x26, 0x86, 0xfa, 0xb2, 0x9f, 0x35, 0xc9, 0xe0, 0x87, 0x3a, 0xed,
-				0xca, 0x4d, 0x30, 0x46, 0xe8, 0xcb, 0xf2, 0x61, 0x02, 0x26, 0xd8, 0x03, 0xdd, 0x92, 0x40, 0xe8,
-				0xa7, 0xa6, 0x74, 0x0c, 0xec, 0x20, 0x4c, 0x39, 0x2a, 0xe6, 0x93, 0xbf, 0xf9, 0xe2, 0x81, 0xec,
-				0x5e, 0x91, 0xa6, 0x40, 0xfe, 0x1a, 0x2d, 0xb8, 0x5e, 0xb7, 0x30, 0x7f, 0x7a, 0x33, 0x8e, 0x87,
-				0x89, 0xea, 0x21, 0x6d, 0xcf, 0x55, 0xed, 0xdf, 0xd0, 0x16, 0x7c, 0x99, 0x5d, 0x18, 0xcf, 0x83,
-				0x22, 0x60, 0x59, 0xe3, 0xfb, 0x0b, 0xe2, 0xb3, 0xb0, 0x90, 0x98, 0xbc, 0x45, 0x92, 0x2e, 0x03,
-				0x51, 0x51, 0xea, 0x76, 0x66, 0x7e, 0xff, 0x1c, 0x79, 0x8a, 0x0a, 0xe4, 0xdb, 0xe8, 0x72, 0xa8,
-				0x68, 0x15, 0xd9, 0x95, 0xcf, 0xd4, 0x22, 0x22, 0x05, 0x00, 0x36, 0x93, 0x84, 0x12, 0x84, 0x11,
-				0x50, 0xb4, 0x99, 0xf5, 0xad, 0x9d, 0x88, 0x60, 0xf8, 0x9a, 0xef, 0x14, 0xc3, 0x67, 0x32, 0x2a,
-				0x35, 0x0b, 0x98, 0x58, 0xa5, 0x56, 0x73, 0xd9, 0x20, 0x41, 0x63, 0x43, 0x47, 0x1c, 0x73, 0x57,
-				0x61, 0xe6, 0xf6, 0x4f, 0x09, 0xf4, 0xd1, 0xb1, 0x1d, 0xc0, 0x6c, 0x35, 0xd3, 0x5d, 0x68, 0xc2,
-				0x95, 0x23, 0x43, 0x7f, 0x4a, 0x07, 0x14, 0xb5, 0x87, 0x6d, 0x52, 0xaf, 0x83, 0x06, 0x3e, 0x29,
-				0xd9, 0x70, 0x6f, 0x88, 0x5f, 0xd1, 0xf8, 0xe7, 0x6b, 0x74, 0x3f, 0xb6, 0x92, 0xae, 0xcd, 0xff,
-				0x5f, 0x60, 0xea, 0x40, 0x84, 0x44, 0x23, 0x39, 0xcb, 0xbc, 0x25, 0x06, 0x29, 0x85, 0xb5, 0xe2,
-				0xcb, 0x92, 0x2a, 0x1c, 0x88, 0x40, 0x54, 0x2d, 0x47, 0x42, 0x39, 0xcc, 0xba, 0x8e, 0x89, 0x18,
-				0x0b, 0x93, 0x33, 0x8d, 0x49, 0x02, 0x81, 0x81, 0x00, 0xf5, 0xe0, 0xdd, 0xef, 0x8b, 0x24, 0xdc,
-				0xaf, 0x00, 0x1b, 0x39, 0x29, 0xb2, 0x1e, 0x9c, 0x46, 0x8e, 0x5d, 0xe4, 0x5f, 0xd9, 0x40, 0x8e,
-				0x2f, 0xfc, 0x28, 0x7d, 0x54, 0x68, 0x6b, 0x09, 0xd6, 0x28, 0x97, 0x6f, 0xf9, 0xc9, 0x07, 0x97,
-				0x88, 0x09, 0x27, 0x68, 0x84, 0x8f, 0x5d, 0x35, 0xbe, 0x4e, 0x80, 0x9d, 0xc7, 0x38, 0x4d, 0x43,
-				0xf1, 0x34, 0xe5, 0xc7, 0xd3, 0xa0, 0x2e, 0x02, 0x81, 0xf9, 0xbf, 0x59, 0x80, 0x12, 0xe1, 0x5a,
-				0x8a, 0x72, 0x27, 0x36, 0x0e, 0xbc, 0x13, 0xd0, 0xc0, 0x01, 0xc5, 0x3e, 0x7c, 0x91, 0xa9, 0x6a,
-				0xfe, 0x0a, 0x8e, 0x3f, 0x52, 0xdd, 0xca, 0x7e, 0x80, 0xe4, 0x09, 0xc3, 0x5a, 0xec, 0x0a, 0x6e,
-				0xe5, 0xa5, 0x58, 0x45, 0xa2, 0x24, 0x5a, 0xdd, 0x02, 0x42, 0x86, 0xbe, 0x28, 0x34, 0x51, 0x0b,
-				0x20, 0x8f, 0xe7, 0x5a, 0xf2, 0xed, 0x9c, 0xf1, 0x1f, 0x02, 0x81, 0x81, 0x00, 0xd9, 0xc6, 0x51,
-				0x6e, 0x51, 0x08, 0xf3, 0xc4, 0x9e, 0x37, 0x06, 0x7c, 0x00, 0xf4, 0x16, 0x0d, 0x36, 0x35, 0xa7,
-				0xc3, 0x06, 0x3a, 0x44, 0x03, 0x61, 0x11, 0x15, 0x69, 0xa4, 0xc8, 0x5f, 0xbb, 0xb1, 0xdd, 0x9f,
-				0xf7, 0x7c, 0x9b, 0x5e, 0x91, 0x0f, 0xd6, 0x80, 0x53, 0xb5, 0x54, 0x79, 0x0b, 0x0d, 0x71, 0x13,
-				0x31, 0xf3, 0xdd, 0xd1, 0xe8, 0xa3, 0xac, 0x4c, 0xbb, 0x71, 0x8a, 0xc5, 0xe5, 0x50, 0xab, 0x67,
-				0xc5, 0x84, 0xd6, 0xc4, 0x8d, 0x4a, 0x6d, 0xd6, 0x0b, 0xc4, 0x85, 0x4b, 0x83, 0x2f, 0x8d, 0x48,
-				0x4a, 0xe8, 0x3a, 0x0b, 0x7e, 0xda, 0xea, 0x2b, 0xc6, 0x31, 0xf5, 0xd9, 0x8d, 0xe1, 0x59, 0x66,
-				0xd7, 0xc8, 0x1a, 0x4b, 0x27, 0x15, 0xcd, 0x2d, 0xe3, 0xe0, 0x51, 0x13, 0x0c, 0xff, 0x3a, 0x25,
-				0x62, 0x64, 0x80, 0x61, 0xa3, 0xdb, 0x17, 0x06, 0xe8, 0xe5, 0x11, 0x30, 0x69, 0x02, 0x81, 0x80,
-				0x11, 0xad, 0xa1, 0x47, 0x5f, 0xd1, 0xbe, 0xac, 0x36, 0x6d, 0xbe, 0xa6, 0x68, 0xd0, 0x1a, 0x9c,
-				0x58, 0x10, 0x18, 0x23, 0x6c, 0x13, 0x60, 0x25, 0xc3, 0x13, 0x86, 0x2f, 0x53, 0x72, 0x9e, 0xba,
-				0x6f, 0x20, 0xb4, 0x44, 0x59, 0x57, 0xda, 0x65, 0x45, 0x83, 0x37, 0xd8, 0x90, 0x16, 0x3b, 0x8e,
-				0xfb, 0x45, 0xf4, 0x12, 0x26, 0xd2, 0x27, 0x58, 0x68, 0x5d, 0x3d, 0x08, 0xd2, 0x33, 0x7c, 0xaa,
-				0xab, 0xb2, 0x3e, 0x55, 0x1f, 0x06, 0x64, 0xe4, 0x1f, 0x61, 0x02, 0x59, 0xfc, 0xdb, 0xcf, 0xde,
-				0x7e, 0x42, 0x18, 0x44, 0x0c, 0x95, 0x09, 0xc4, 0x4a, 0x2e, 0x00, 0x0f, 0x8d, 0x32, 0xc9, 0xf5,
-				0xaa, 0x6f, 0xa9, 0x44, 0x18, 0x44, 0x87, 0xc4, 0xab, 0x26, 0xb5, 0x9a, 0xfa, 0xd2, 0x2d, 0xa1,
-				0xc3, 0xf6, 0xbc, 0x25, 0x57, 0xdd, 0x9b, 0xd7, 0x33, 0x81, 0x86, 0xe0, 0x80, 0x85, 0x10, 0x31,
-				0x02, 0x81, 0x80, 0x75, 0x06, 0x05, 0xe2, 0x22, 0xf7, 0x8d, 0x8e, 0xbd, 0x7a, 0x52, 0x28, 0xb6,
-				0x96, 0x73, 0x77, 0x1c, 0x07, 0x4f, 0x24, 0x14, 0xa7, 0xa0, 0xbe, 0xb4, 0x1d, 0x6b, 0x05, 0x3f,
-				0x00, 0x51, 0xb9, 0x59, 0xc5, 0xff, 0x5d, 0x0d, 0x7f, 0xac, 0x1c, 0x85, 0x87, 0x3d, 0xa4, 0x3d,
-				0xcf, 0xab, 0xcf, 0xcd, 0xa4, 0x52, 0xad, 0x48, 0x1f, 0x8d, 0xd9, 0xd6, 0x82, 0x13, 0x25, 0xb2,
-				0xc8, 0xe0, 0xb8, 0xee, 0x55, 0x7d, 0x48, 0xfd, 0xae, 0x2f, 0x26, 0xc1, 0xb5, 0x2e, 0x0d, 0x5a,
-				0xc8, 0x4a, 0x20, 0xaf, 0x9f, 0xdb, 0x16, 0x2d, 0x9e, 0x6b, 0x68, 0xfa, 0x98, 0x55, 0x77, 0x86,
-				0x87, 0x57, 0x25, 0xcf, 0xcf, 0xab, 0xdd, 0x0e, 0x71, 0x5a, 0xab, 0x21, 0x23, 0x05, 0xa2, 0xeb,
-				0x7a, 0x85, 0xa3, 0x39, 0x4f, 0x74, 0xa1, 0x5f, 0xe2, 0x41, 0x15, 0xbc, 0xf8, 0xad, 0xc4, 0xde,
-				0xbb, 0x12, 0xe9, 0x02, 0x81, 0x80, 0x69, 0xf6, 0xb7, 0x3f, 0x90, 0x91, 0x22, 0x94, 0x4e, 0x2d,
-				0x75, 0xe7, 0xbe, 0x6f, 0x49, 0x92, 0x12, 0x40, 0xe2, 0xdd, 0x0f, 0x78, 0x98, 0xbb, 0xc6, 0x55,
-				0x77, 0xd8, 0xe3, 0x2c, 0xcf, 0xea, 0x5e, 0xfe, 0xce, 0x20, 0xa6, 0xc2, 0x3a, 0x0a, 0x62, 0x22,
-				0x2b, 0x45, 0x77, 0x9e, 0x16, 0x9a, 0xf6, 0x68, 0x3a, 0x48, 0x51, 0xe6, 0x98, 0xbc, 0xf7, 0xa1,
-				0xc4, 0x86, 0xfe, 0xf5, 0xaf, 0x02, 0xa0, 0xbc, 0x9f, 0x5e, 0xed, 0x88, 0xe0, 0xa3, 0x97, 0xde,
-				0x2e, 0xf1, 0x41, 0xca, 0x9f, 0x59, 0xf2, 0x9b, 0x70, 0x16, 0x3b, 0x2a, 0x10, 0xab, 0x43, 0x74,
-				0x5b, 0x36, 0x8b, 0xc9, 0x7c, 0x70, 0x9d, 0x80, 0xa1, 0x34, 0x0b, 0x29, 0x30, 0x26, 0xb8, 0xb6,
-				0xe2, 0xb8, 0xa1, 0x2c, 0x2e, 0xa5, 0x58, 0x09, 0xf2, 0x7d, 0x99, 0xc2, 0xf6, 0xab, 0x19, 0x2b,
-				0x75, 0x29, 0x51, 0x52, 0x19, 0x78
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0x96, 0x4c, 0x6f, 0xef, 0x79, 0xdf, 0x8b, 0x5e, 0x8e, 0xcf, 0xd1, 0x4a,
-				0x4c, 0xa0, 0x89, 0x6b, 0x59, 0x8e, 0x5d, 0x88, 0x4a, 0x82, 0x48, 0x2d, 0xaa, 0x21, 0xab, 0x69,
-				0x61, 0x19, 0x10, 0x55, 0xc1, 0xe3, 0x40, 0xc7, 0x59, 0xd2, 0xa2, 0xcb, 0x8f, 0x64, 0xdc, 0x1a,
-				0xd7, 0x70, 0xf9, 0x83, 0x06, 0x55, 0x5d, 0xef, 0xc6, 0x3e, 0x3f, 0x2b, 0x56, 0xc3, 0x0b, 0xbd,
-				0x1a, 0x01, 0xda, 0x4f, 0x91, 0x45, 0x21, 0x09, 0x0a, 0x83, 0xdb, 0xb6, 0x8b, 0x14, 0xd3, 0xbd,
-				0x49, 0x9a, 0xb5, 0x20, 0xac, 0x41, 0x65, 0x0b, 0x8e, 0x53, 0x8c, 0x3e, 0xe9, 0xe6, 0xed, 0x48,
-				0xc5, 0x5d, 0x4d, 0x04, 0xc1, 0x24, 0x67, 0xa3, 0xc6, 0x36, 0x69, 0xb5, 0x7d, 0xa9, 0x75, 0x44,
-				0xf1, 0x0f, 0x7c, 0x29, 0xc3, 0x70, 0xb1, 0x05, 0x70, 0x97, 0x24, 0xa5, 0x8d, 0xa9, 0xfe, 0xdc,
-				0x7f, 0x9d, 0xb7, 0x01, 0x5c, 0xf5, 0xee, 0x8e, 0xa5, 0x56, 0xfb, 0xf9, 0x05, 0x10, 0x06, 0xd0,
-				0x5d, 0x0a, 0xb0, 0x14, 0x7d, 0x4e, 0xac, 0x1d, 0xf5, 0x8e, 0xe9, 0x36, 0x90, 0x5d, 0x91, 0xde,
-				0xd5, 0x30, 0x1a, 0x8d, 0x2c, 0x97, 0xec, 0x31, 0x37, 0xb7, 0x22, 0x7a, 0x55, 0x8e, 0xa2, 0x71,
-				0x89, 0x03, 0xcf, 0x10, 0xb3, 0x8d, 0xce, 0xce, 0x2f, 0xfb, 0x43, 0x63, 0x74, 0x27, 0x01, 0x71,
-				0x22, 0x14, 0x99, 0xe5, 0xd2, 0x6d, 0x68, 0x75, 0xa5, 0x7f, 0xb5, 0xfd, 0x44, 0x67, 0x36, 0x7d,
-				0x25, 0xa7, 0x61, 0x76, 0x9d, 0x26, 0xfa, 0x53, 0x5f, 0xf9, 0x76, 0x1b, 0x40, 0x6e, 0x2e, 0x25,
-				0xf4, 0xb1, 0xc3, 0x1c, 0xa0, 0x41, 0x6d, 0x11, 0x05, 0x20, 0xac, 0x68, 0x7e, 0x51, 0x35, 0xa0,
-				0x62, 0x05, 0x17, 0x87, 0xe0, 0xf4, 0xb7, 0xc6, 0xc9, 0x2e, 0xf7, 0xf8, 0x98, 0x1b, 0x74, 0x09,
-				0x2e, 0xe6, 0x9f, 0x59
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x96, 0x4c, 0x6f, 0xef,
-				0x79, 0xdf, 0x8b, 0x5e, 0x8e, 0xcf, 0xd1, 0x4a, 0x4c, 0xa0, 0x89, 0x6b, 0x59, 0x8e, 0x5d, 0x88,
-				0x4a, 0x82, 0x48, 0x2d, 0xaa, 0x21, 0xab, 0x69, 0x61, 0x19, 0x10, 0x55, 0xc1, 0xe3, 0x40, 0xc7,
-				0x59, 0xd2, 0xa2, 0xcb, 0x8f, 0x64, 0xdc, 0x1a, 0xd7, 0x70, 0xf9, 0x83, 0x06, 0x55, 0x5d, 0xef,
-				0xc6, 0x3e, 0x3f, 0x2b, 0x56, 0xc3, 0x0b, 0xbd, 0x1a, 0x01, 0xda, 0x4f, 0x91, 0x45, 0x21, 0x09,
-				0x0a, 0x83, 0xdb, 0xb6, 0x8b, 0x14, 0xd3, 0xbd, 0x49, 0x9a, 0xb5, 0x20, 0xac, 0x41, 0x65, 0x0b,
-				0x8e, 0x53, 0x8c, 0x3e, 0xe9, 0xe6, 0xed, 0x48, 0xc5, 0x5d, 0x4d, 0x04, 0xc1, 0x24, 0x67, 0xa3,
-				0xc6, 0x36, 0x69, 0xb5, 0x7d, 0xa9, 0x75, 0x44, 0xf1, 0x0f, 0x7c, 0x29, 0xc3, 0x70, 0xb1, 0x05,
-				0x70, 0x97, 0x24, 0xa5, 0x8d, 0xa9, 0xfe, 0xdc, 0x7f, 0x9d, 0xb7, 0x01, 0x5c, 0xf5, 0xee, 0x8e,
-				0xa5, 0x56, 0xfb, 0xf9, 0x05, 0x10, 0x06, 0xd0, 0x5d, 0x0a, 0xb0, 0x14, 0x7d, 0x4e, 0xac, 0x1d,
-				0xf5, 0x8e, 0xe9, 0x36, 0x90, 0x5d, 0x91, 0xde, 0xd5, 0x30, 0x1a, 0x8d, 0x2c, 0x97, 0xec, 0x31,
-				0x37, 0xb7, 0x22, 0x7a, 0x55, 0x8e, 0xa2, 0x71, 0x89, 0x03, 0xcf, 0x10, 0xb3, 0x8d, 0xce, 0xce,
-				0x2f, 0xfb, 0x43, 0x63, 0x74, 0x27, 0x01, 0x71, 0x22, 0x14, 0x99, 0xe5, 0xd2, 0x6d, 0x68, 0x75,
-				0xa5, 0x7f, 0xb5, 0xfd, 0x44, 0x67, 0x36, 0x7d, 0x25, 0xa7, 0x61, 0x76, 0x9d, 0x26, 0xfa, 0x53,
-				0x5f, 0xf9, 0x76, 0x1b, 0x40, 0x6e, 0x2e, 0x25, 0xf4, 0xb1, 0xc3, 0x1c, 0xa0, 0x41, 0x6d, 0x11,
-				0x05, 0x20, 0xac, 0x68, 0x7e, 0x51, 0x35, 0xa0, 0x62, 0x05, 0x17, 0x87, 0xe0, 0xf4, 0xb7, 0xc6,
-				0xc9, 0x2e, 0xf7, 0xf8, 0x98, 0x1b, 0x74, 0x09, 0x2e, 0xe6, 0x9f, 0x59, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x08, 0x1a, 0xa5, 0x83, 0x7a, 0x65, 0x13, 0x18, 0xfd, 0x66, 0xd7,
-				0xc0, 0x63, 0x9a, 0xd9, 0x66, 0x0c, 0x2d, 0x68, 0xbe, 0x2f, 0x54, 0x50, 0x8b, 0x83, 0xcb, 0xae,
-				0x78, 0x2f, 0x67, 0xe0, 0x51, 0x5b, 0x73, 0xc3, 0x3b, 0xac, 0x8c, 0x76, 0xc2, 0x36, 0xa0, 0x67,
-				0xdc, 0xdb, 0xa6, 0x88, 0x11, 0xa8, 0x4f, 0x04, 0x92, 0x67, 0xf4, 0x55, 0xc8, 0x22, 0xb4, 0xc0,
-				0x26, 0x89, 0x67, 0x35, 0xac, 0x0a, 0x27, 0x79, 0xd5, 0x48, 0xb7, 0x9c, 0xea, 0x7e, 0x1b, 0xd8,
-				0xa1, 0xf1, 0x7c, 0xd1, 0xcc, 0xe9, 0xf4, 0xd9, 0xbb, 0xb2, 0x88, 0x2f, 0x3c, 0xfa, 0x34, 0x3d,
-				0x31, 0xaa, 0x10, 0xb2, 0x95, 0x31, 0xcb, 0xe2, 0x79, 0xba, 0x77, 0x97, 0x22, 0x15, 0xdd, 0x44,
-				0x09, 0x3c, 0x5d, 0x4b, 0x22, 0xde, 0x5a, 0xae, 0x74, 0xde, 0x62, 0x0b, 0xf4, 0x10, 0x4c, 0x2d,
-				0x05, 0x9b, 0x2c, 0xf8, 0x1f, 0xd9, 0xc6, 0x76, 0x7c, 0x6d, 0xa7, 0x32, 0xa3, 0xa0, 0xe3, 0x5f,
-				0x61, 0xbe, 0x69, 0xc9, 0x17, 0xa1, 0xed, 0xc2, 0x3a, 0x0e, 0x2b, 0xd9, 0x54, 0x60, 0xa0, 0xdc,
-				0x9f, 0x73, 0x40, 0xbe, 0x39, 0xf1, 0x11, 0x68, 0xaa, 0x02, 0x68, 0x7a, 0xdc, 0x53, 0xf2, 0x5f,
-				0x37, 0xbb, 0x79, 0x64, 0x06, 0x33, 0xe8, 0x1a, 0xfe, 0x77, 0xdc, 0x19, 0xdd, 0xe1, 0xdb, 0xe6,
-				0xbb, 0xfc, 0xcc, 0x95, 0x31, 0xbc, 0x44, 0xf9, 0x2c, 0xe8, 0x60, 0x54, 0x66, 0x4c, 0xe2, 0x5a,
-				0xda, 0xec, 0xa0, 0xfe, 0x38, 0x41, 0x13, 0xd2, 0x4a, 0xf4, 0x17, 0xf2, 0xd1, 0x5c, 0xe2, 0x3b,
-				0xbe, 0x23, 0x78, 0xdb, 0xf7, 0x7f, 0x9d, 0x50, 0x41, 0x57, 0x28, 0xa0, 0xbe, 0x00, 0x26, 0x1c,
-				0xeb, 0xf0, 0xa9, 0xc6, 0x5b, 0x58, 0x9a, 0xb6, 0x3f, 0xc7, 0x6f, 0x99, 0xf9, 0x9d, 0xe6, 0x2e,
-				0x48, 0xdf, 0x11, 0x78, 0xe1, 0x02, 0x81, 0x81, 0x00, 0xcb, 0x27, 0x6b, 0x97, 0x81, 0xdb, 0x84,
-				0xf3, 0x33, 0x91, 0xf2, 0x18, 0x23, 0xe5, 0x8b, 0x87, 0x40, 0x47, 0xb0, 0x73, 0x2d, 0xf0, 0x0e,
-				0xa1, 0xbc, 0x46, 0xaf, 0xaa, 0x78, 0x18, 0x23, 0xa1, 0xf7, 0x9e, 0xf9, 0x13, 0x49, 0xd7, 0x39,
-				0x04, 0x9b, 0xed, 0x00, 0xf9, 0xfd, 0x3f, 0x0d, 0x07, 0x4f, 0xfb, 0xc7, 0xab, 0x13, 0x26, 0xd9,
-				0xda, 0x85, 0x93, 0x07, 0x68, 0x73, 0x68, 0xfb, 0x37, 0xc2, 0x5b, 0x7c, 0x02, 0x90, 0xd0, 0x0b,
-				0xac, 0xa2, 0x4d, 0xe6, 0x2b, 0xb8, 0xf3, 0x04, 0xa6, 0x39, 0x80, 0x12, 0x81, 0xdb, 0x0d, 0x94,
-				0x8b, 0x7f, 0xf8, 0x25, 0xd0, 0x5c, 0x17, 0x3d, 0xc3, 0x50, 0x43, 0x7f, 0x2c, 0x6f, 0xe4, 0x4f,
-				0x8d, 0x42, 0x86, 0x9a, 0x78, 0x95, 0xdc, 0x7b, 0xe3, 0x28, 0x6f, 0x70, 0x4e, 0x10, 0x7b, 0x84,
-				0xa8, 0x1d, 0xa6, 0xd5, 0x3b, 0x80, 0x58, 0xa2, 0x91, 0x02, 0x81, 0x81, 0x00, 0xbd, 0x65, 0x3b,
-				0x29, 0xb1, 0xd3, 0x7f, 0xf2, 0x2a, 0x74, 0x3a, 0x20, 0xf0, 0x2c, 0x67, 0xa8, 0xbf, 0x61, 0x6b,
-				0x22, 0xd8, 0x6f, 0x3d, 0x61, 0x04, 0x07, 0xb9, 0x7c, 0x82, 0x50, 0xe3, 0x9d, 0xfa, 0x64, 0xdb,
-				0x53, 0x2b, 0xa6, 0xfc, 0xcc, 0x5d, 0x44, 0xbe, 0xc7, 0xff, 0xe3, 0x4b, 0x18, 0x30, 0xd1, 0xa8,
-				0xc5, 0xec, 0x73, 0x36, 0x3a, 0x39, 0x15, 0xa5, 0x2c, 0x69, 0xbc, 0x0c, 0x0c, 0x39, 0x90, 0xc2,
-				0x6c, 0x1f, 0x56, 0x1f, 0x4d, 0x96, 0x8d, 0x06, 0xb1, 0xc6, 0xd4, 0xca, 0xd6, 0xc7, 0x70, 0x41,
-				0x77, 0x68, 0x21, 0xc4, 0x98, 0xf4, 0xab, 0x16, 0xbd, 0xef, 0xc1, 0x15, 0x73, 0x6c, 0x38, 0xfb,
-				0x15, 0xb0, 0x34, 0x99, 0xa9, 0xff, 0x58, 0xb7, 0xf2, 0xbe, 0x78, 0x1d, 0x38, 0x2a, 0x74, 0x03,
-				0x07, 0xcd, 0xbc, 0x91, 0x17, 0x5d, 0x79, 0x71, 0x52, 0xa0, 0xb6, 0x04, 0x49, 0x02, 0x81, 0x80,
-				0x3f, 0xd2, 0x91, 0x95, 0x96, 0x81, 0x4d, 0x82, 0x4e, 0x28, 0x42, 0xa3, 0x5c, 0xdb, 0xa7, 0x7b,
-				0x05, 0x31, 0xc0, 0x78, 0x5e, 0xed, 0x34, 0xdb, 0x90, 0xd7, 0xb0, 0x26, 0x60, 0xf6, 0x4c, 0x73,
-				0x7c, 0xe4, 0x9f, 0xa1, 0x74, 0xa8, 0x3d, 0xcc, 0x79, 0xe3, 0xfa, 0x53, 0x8f, 0x40, 0xf8, 0xa9,
-				0xdc, 0x71, 0xe0, 0x27, 0x99, 0xab, 0xb1, 0xf3, 0x59, 0xd5, 0x78, 0x15, 0x53, 0x74, 0x9e, 0xbf,
-				0xc4, 0xba, 0x92, 0xfa, 0x07, 0x5e, 0xa4, 0xdc, 0x46, 0x5d, 0x2c, 0xbb, 0x7d, 0xae, 0x33, 0x3e,
-				0xb9, 0x7f, 0xc7, 0xd0, 0xad, 0xed, 0xd5, 0x46, 0x02, 0x1d, 0x06, 0x5c, 0x30, 0x22, 0x49, 0x10,
-				0x0c, 0x2e, 0x38, 0x4c, 0xd0, 0x96, 0x2c, 0x7b, 0xd7, 0x73, 0x8c, 0x21, 0xe8, 0x0a, 0xcd, 0x8c,
-				0xee, 0xce, 0x1b, 0xbd, 0x1a, 0xa6, 0x83, 0x65, 0x81, 0x73, 0x41, 0x38, 0x21, 0x39, 0x37, 0x51,
-				0x02, 0x81, 0x80, 0x6f, 0xf9, 0x98, 0xe8, 0x06, 0xcd, 0xef, 0xd8, 0x62, 0x47, 0x43, 0x52, 0xd4,
-				0x0c, 0xbc, 0xe0, 0xa4, 0xfd, 0xd8, 0xd4, 0xca, 0x37, 0xc2, 0x87, 0x48, 0x55, 0xb4, 0xd1, 0xab,
-				0x4e, 0x5d, 0xb4, 0xba, 0x24, 0xc5, 0x13, 0x40, 0x3c, 0xc3, 0x3b, 0xa4, 0x6d, 0x0f, 0x8a, 0xb9,
-				0x7c, 0x4d, 0x9a, 0xa8, 0xca, 0x5c, 0x49, 0x60, 0x89, 0xa1, 0x66, 0xfc, 0xf7, 0x12, 0x27, 0xd6,
-				0xff, 0xa9, 0xf3, 0xd4, 0x59, 0x04, 0xc9, 0xde, 0x21, 0x11, 0xf2, 0xd2, 0x6e, 0xe0, 0xa5, 0x5c,
-				0xd3, 0xd4, 0x74, 0xf5, 0x87, 0x25, 0xfd, 0x8d, 0xe0, 0x61, 0x16, 0xb9, 0x99, 0x29, 0xa1, 0xf4,
-				0x4d, 0x28, 0xfc, 0x8b, 0xe0, 0x88, 0x7a, 0x83, 0x2a, 0x26, 0x2b, 0xbe, 0xdf, 0x5a, 0x2a, 0x37,
-				0x78, 0x56, 0x76, 0x2d, 0x8b, 0x57, 0x7b, 0x56, 0xa5, 0x04, 0xf7, 0x56, 0x79, 0x85, 0x89, 0x7f,
-				0xa0, 0xfd, 0x99, 0x02, 0x81, 0x80, 0x1b, 0xbd, 0x2b, 0x67, 0xfc, 0x29, 0x48, 0x49, 0xe4, 0x18,
-				0x43, 0x9c, 0x88, 0xbd, 0x70, 0xec, 0xf9, 0x44, 0xff, 0xd6, 0xb5, 0x54, 0x0b, 0xfc, 0x4d, 0x94,
-				0xf9, 0xb1, 0xbd, 0x3e, 0xa3, 0xab, 0x6e, 0x1f, 0xe3, 0x8b, 0xe3, 0x03, 0xe6, 0x31, 0x6c, 0x5a,
-				0x9f, 0x5f, 0xe6, 0x7a, 0x36, 0x0e, 0x4c, 0xbe, 0x12, 0x77, 0xc2, 0xce, 0x2e, 0xa5, 0x93, 0x3f,
-				0x80, 0x97, 0xcb, 0x50, 0x1e, 0x5f, 0xad, 0x28, 0xc2, 0x13, 0x8e, 0xe4, 0x57, 0x5a, 0x4e, 0x59,
-				0x50, 0x92, 0x83, 0x22, 0xf3, 0xa7, 0xbd, 0x31, 0xb8, 0xbb, 0xb8, 0xd3, 0xfb, 0xd0, 0xcc, 0x52,
-				0x31, 0xfc, 0xff, 0xc6, 0x61, 0x57, 0x93, 0xa1, 0x92, 0x04, 0x4f, 0x3f, 0xf1, 0x8e, 0x21, 0x95,
-				0x2e, 0x39, 0x22, 0xaa, 0xfd, 0xb3, 0x06, 0x76, 0x96, 0x20, 0x82, 0x39, 0x66, 0x3b, 0x90, 0x46,
-				0xa4, 0x1f, 0xaa, 0xef, 0x51, 0x26
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xf8, 0xb4, 0xc8, 0x01, 0x83, 0x7c, 0x91, 0xac, 0x5a, 0x73, 0x06, 0xa7,
-				0x15, 0xad, 0x47, 0x18, 0xf2, 0x27, 0xd7, 0x79, 0x01, 0x8f, 0x66, 0xe3, 0xe2, 0x7f, 0x16, 0x60,
-				0xd4, 0xf2, 0x97, 0xd7, 0x3f, 0x9e, 0xd1, 0xf6, 0x81, 0x1f, 0x7e, 0xe1, 0x6e, 0x95, 0xb8, 0x5b,
-				0x22, 0x9e, 0xac, 0x8f, 0x8d, 0x9d, 0x57, 0xf2, 0xb0, 0xd7, 0x81, 0x81, 0x21, 0x0a, 0xe3, 0x6b,
-				0x90, 0xb7, 0xb4, 0x88, 0x9c, 0xa2, 0xec, 0x6c, 0xee, 0xd3, 0xa3, 0xfa, 0x7d, 0x17, 0xa4, 0x11,
-				0x3a, 0x83, 0x49, 0x08, 0x10, 0xbc, 0xc4, 0xee, 0x58, 0x6a, 0x5e, 0x2b, 0x20, 0x7a, 0xc8, 0x9c,
-				0xac, 0x33, 0xe4, 0x27, 0xd4, 0x12, 0x0a, 0xd1, 0x2c, 0x65, 0x40, 0x8f, 0xb5, 0xa8, 0x4b, 0x21,
-				0x9d, 0xd3, 0x88, 0xba, 0x5d, 0x73, 0xa5, 0x9e, 0x42, 0x94, 0x05, 0xf2, 0x76, 0xc9, 0x1f, 0xdc,
-				0x9d, 0x88, 0x79, 0x11, 0x59, 0x64, 0x31, 0xfb, 0xcb, 0x49, 0x05, 0x28, 0x76, 0x37, 0x6a, 0x5b,
-				0x2d, 0x23, 0xc5, 0xc0, 0x6f, 0xb7, 0x5d, 0xbc, 0x19, 0x4b, 0x23, 0xc1, 0x3b, 0xdd, 0xa9, 0xec,
-				0xab, 0xb2, 0xc4, 0x14, 0xa1, 0x79, 0xc5, 0x21, 0x99, 0xc2, 0x01, 0x5b, 0xca, 0x2b, 0xbe, 0x2f,
-				0x56, 0xaa, 0x89, 0xf2, 0x9e, 0x9a, 0x9a, 0xd7, 0x7a, 0x64, 0xe0, 0xf0, 0x0e, 0x9b, 0xb5, 0x02,
-				0xba, 0x3a, 0xab, 0x41, 0x98, 0x8f, 0xfb, 0xbf, 0x2b, 0xb8, 0x85, 0x61, 0x36, 0x2e, 0xcb, 0xf7,
-				0xf1, 0x68, 0x78, 0xbe, 0x9a, 0xdb, 0xab, 0xfb, 0x4f, 0xd4, 0x88, 0xdb, 0x16, 0xdc, 0x0d, 0xfe,
-				0xf7, 0x2a, 0xce, 0x53, 0x7b, 0x63, 0x72, 0x3c, 0x42, 0x35, 0x10, 0x51, 0x92, 0xbf, 0x79, 0x64,
-				0x7c, 0x35, 0xa9, 0x97, 0x56, 0x90, 0x2e, 0x7b, 0xe1, 0x4d, 0x1b, 0x46, 0x3a, 0x5c, 0x91, 0x07,
-				0x0f, 0xd8, 0x22, 0x7d
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf8, 0xb4, 0xc8, 0x01,
-				0x83, 0x7c, 0x91, 0xac, 0x5a, 0x73, 0x06, 0xa7, 0x15, 0xad, 0x47, 0x18, 0xf2, 0x27, 0xd7, 0x79,
-				0x01, 0x8f, 0x66, 0xe3, 0xe2, 0x7f, 0x16, 0x60, 0xd4, 0xf2, 0x97, 0xd7, 0x3f, 0x9e, 0xd1, 0xf6,
-				0x81, 0x1f, 0x7e, 0xe1, 0x6e, 0x95, 0xb8, 0x5b, 0x22, 0x9e, 0xac, 0x8f, 0x8d, 0x9d, 0x57, 0xf2,
-				0xb0, 0xd7, 0x81, 0x81, 0x21, 0x0a, 0xe3, 0x6b, 0x90, 0xb7, 0xb4, 0x88, 0x9c, 0xa2, 0xec, 0x6c,
-				0xee, 0xd3, 0xa3, 0xfa, 0x7d, 0x17, 0xa4, 0x11, 0x3a, 0x83, 0x49, 0x08, 0x10, 0xbc, 0xc4, 0xee,
-				0x58, 0x6a, 0x5e, 0x2b, 0x20, 0x7a, 0xc8, 0x9c, 0xac, 0x33, 0xe4, 0x27, 0xd4, 0x12, 0x0a, 0xd1,
-				0x2c, 0x65, 0x40, 0x8f, 0xb5, 0xa8, 0x4b, 0x21, 0x9d, 0xd3, 0x88, 0xba, 0x5d, 0x73, 0xa5, 0x9e,
-				0x42, 0x94, 0x05, 0xf2, 0x76, 0xc9, 0x1f, 0xdc, 0x9d, 0x88, 0x79, 0x11, 0x59, 0x64, 0x31, 0xfb,
-				0xcb, 0x49, 0x05, 0x28, 0x76, 0x37, 0x6a, 0x5b, 0x2d, 0x23, 0xc5, 0xc0, 0x6f, 0xb7, 0x5d, 0xbc,
-				0x19, 0x4b, 0x23, 0xc1, 0x3b, 0xdd, 0xa9, 0xec, 0xab, 0xb2, 0xc4, 0x14, 0xa1, 0x79, 0xc5, 0x21,
-				0x99, 0xc2, 0x01, 0x5b, 0xca, 0x2b, 0xbe, 0x2f, 0x56, 0xaa, 0x89, 0xf2, 0x9e, 0x9a, 0x9a, 0xd7,
-				0x7a, 0x64, 0xe0, 0xf0, 0x0e, 0x9b, 0xb5, 0x02, 0xba, 0x3a, 0xab, 0x41, 0x98, 0x8f, 0xfb, 0xbf,
-				0x2b, 0xb8, 0x85, 0x61, 0x36, 0x2e, 0xcb, 0xf7, 0xf1, 0x68, 0x78, 0xbe, 0x9a, 0xdb, 0xab, 0xfb,
-				0x4f, 0xd4, 0x88, 0xdb, 0x16, 0xdc, 0x0d, 0xfe, 0xf7, 0x2a, 0xce, 0x53, 0x7b, 0x63, 0x72, 0x3c,
-				0x42, 0x35, 0x10, 0x51, 0x92, 0xbf, 0x79, 0x64, 0x7c, 0x35, 0xa9, 0x97, 0x56, 0x90, 0x2e, 0x7b,
-				0xe1, 0x4d, 0x1b, 0x46, 0x3a, 0x5c, 0x91, 0x07, 0x0f, 0xd8, 0x22, 0x7d, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x05, 0xfd, 0x04, 0x5b, 0xd4, 0xf8, 0xa8, 0xe1, 0x47, 0x84, 0x41,
-				0x82, 0xc0, 0x68, 0xdd, 0xaf, 0x62, 0x15, 0x47, 0x80, 0xe8, 0x62, 0xb5, 0x8d, 0x83, 0x24, 0xa0,
-				0x3b, 0x50, 0xa5, 0x4e, 0xb6, 0xa6, 0x17, 0x82, 0xe2, 0xb6, 0x95, 0x35, 0x8e, 0xe4, 0x04, 0xc2,
-				0xdd, 0x9e, 0xe5, 0xc7, 0x2d, 0xe5, 0xb1, 0x06, 0x2f, 0x17, 0xc6, 0xf8, 0x9d, 0x4d, 0x58, 0x5f,
-				0xc5, 0x75, 0x44, 0x97, 0x1a, 0x3a, 0xfb, 0x49, 0x4a, 0x0e, 0x2e, 0x16, 0x62, 0xaf, 0xa4, 0x64,
-				0x14, 0xee, 0x1d, 0xbf, 0x22, 0x6c, 0x94, 0xbf, 0x01, 0x26, 0x2b, 0xd9, 0x7c, 0x9c, 0x59, 0x98,
-				0x7e, 0xfd, 0x3e, 0x7a, 0x9d, 0xe2, 0xe3, 0x54, 0x53, 0x59, 0x08, 0x4f, 0x17, 0xa6, 0xbe, 0x18,
-				0xa1, 0x04, 0x95, 0xd5, 0x52, 0xf7, 0x71, 0x13, 0x69, 0xce, 0x1c, 0x96, 0x50, 0x12, 0x40, 0x21,
-				0x7e, 0x44, 0x64, 0xc6, 0xd5, 0x71, 0xf4, 0xb9, 0x83, 0x3c, 0x7c, 0x86, 0x94, 0x6d, 0x96, 0xf3,
-				0x52, 0x9e, 0xa6, 0xe4, 0x1c, 0x89, 0x8b, 0x00, 0xb3, 0x6b, 0x39, 0x93, 0xa7, 0xa4, 0x2d, 0x52,
-				0xf7, 0xab, 0x4d, 0xe8, 0x98, 0x83, 0x37, 0xb8, 0xb5, 0xe0, 0x47, 0x10, 0xf9, 0xb4, 0x13, 0x78,
-				0xab, 0xdf, 0x41, 0xe4, 0xfe, 0x67, 0xb9, 0xea, 0x3c, 0x2c, 0x24, 0x5f, 0x10, 0x72, 0xd9, 0x30,
-				0xad, 0x4f, 0x0e, 0x29, 0xf6, 0xc4, 0x8a, 0xaf, 0xf9, 0x3c, 0xb1, 0x18, 0x16, 0xfb, 0xbe, 0xd7,
-				0xc1, 0x7d, 0xb1, 0x20, 0x16, 0xb7, 0x00, 0x67, 0x39, 0x8d, 0xfe, 0xb9, 0x99, 0x25, 0xe9, 0xcc,
-				0x0f, 0xd7, 0x2d, 0xb5, 0xc6, 0xe0, 0x79, 0x11, 0xdb, 0x1f, 0x69, 0xd2, 0x75, 0x41, 0x40, 0x36,
-				0xf1, 0x9d, 0xec, 0x83, 0x14, 0xb0, 0xdd, 0x8c, 0xdb, 0x59, 0xe1, 0xe7, 0x0b, 0x89, 0xb6, 0x0f,
-				0x19, 0x26, 0xd3, 0xff, 0x59, 0x02, 0x81, 0x81, 0x00, 0xfe, 0xa2, 0x13, 0xc6, 0x53, 0x64, 0xaa,
-				0x01, 0x8c, 0xa5, 0x5f, 0xae, 0x27, 0x1c, 0xe9, 0xfd, 0x12, 0x39, 0x55, 0x81, 0x54, 0x6e, 0x60,
-				0x67, 0xd2, 0x8d, 0xa0, 0xf7, 0xcc, 0x67, 0xe1, 0xa8, 0x5f, 0xeb, 0xfb, 0x76, 0x8b, 0xee, 0x9d,
-				0xc7, 0xa2, 0x9a, 0xf8, 0xe7, 0x03, 0xa8, 0x7a, 0x0b, 0xc2, 0xe2, 0x5c, 0xf0, 0x38, 0xfc, 0x50,
-				0x3b, 0x13, 0x31, 0x0d, 0xbe, 0x21, 0x66, 0x74, 0x55, 0x25, 0xd1, 0x56, 0xd9, 0xb5, 0xd5, 0xee,
-				0xdb, 0xa5, 0xb6, 0xf0, 0x95, 0xa0, 0x2e, 0xbc, 0x26, 0x0a, 0xeb, 0x59, 0xab, 0xc2, 0x01, 0x3e,
-				0xf4, 0x38, 0x76, 0x6b, 0x85, 0xad, 0x11, 0x38, 0xa6, 0x6f, 0xc8, 0xf4, 0xb2, 0x95, 0x67, 0xd4,
-				0x93, 0xd2, 0x96, 0xdd, 0xe9, 0xa9, 0x5a, 0xdd, 0x82, 0x7c, 0x89, 0xa4, 0xf0, 0xbe, 0xe9, 0x31,
-				0x62, 0x52, 0x7d, 0x2f, 0x6e, 0x6a, 0x03, 0xd6, 0x3f, 0x02, 0x81, 0x81, 0x00, 0xfa, 0x0a, 0x8f,
-				0x20, 0xb3, 0xf4, 0xbb, 0x09, 0xae, 0xf1, 0x9c, 0x1a, 0xb2, 0x12, 0x17, 0x3b, 0x78, 0xd2, 0x5a,
-				0x3f, 0xf8, 0xf0, 0x69, 0x99, 0xae, 0x97, 0x3b, 0x16, 0x3f, 0x66, 0xcd, 0xe9, 0xda, 0x56, 0x51,
-				0x08, 0xa9, 0xbd, 0x1f, 0x51, 0x25, 0x1a, 0x8b, 0xa2, 0x89, 0x3b, 0x20, 0x66, 0x94, 0x49, 0x48,
-				0x45, 0x9c, 0xd1, 0x7e, 0xba, 0x83, 0x19, 0x9d, 0x74, 0x03, 0x03, 0x6b, 0xa8, 0xe0, 0xd3, 0x53,
-				0x78, 0x02, 0x52, 0xb9, 0x8d, 0x0d, 0xbd, 0x0c, 0x52, 0xd5, 0x2e, 0x6a, 0x88, 0x7c, 0x9d, 0x39,
-				0x02, 0x75, 0x72, 0x04, 0x29, 0xc9, 0x7a, 0x67, 0x7b, 0x08, 0xf4, 0xc3, 0xfa, 0x8d, 0x12, 0x7c,
-				0xdb, 0x8e, 0xcc, 0x47, 0xe5, 0x61, 0xd3, 0x91, 0x1f, 0xd5, 0x6d, 0xf0, 0x8c, 0xe9, 0x3c, 0x71,
-				0x63, 0x1b, 0x0c, 0x7b, 0xaa, 0x07, 0x69, 0x25, 0x5f, 0xe1, 0x04, 0xf0, 0x43, 0x02, 0x81, 0x80,
-				0x2b, 0x9e, 0xe2, 0x5a, 0x58, 0x50, 0xe7, 0x5a, 0xca, 0x98, 0x4d, 0xf2, 0xcc, 0x9a, 0x84, 0x6f,
-				0x29, 0x1f, 0x0f, 0x49, 0xcf, 0x87, 0xf5, 0x15, 0xf4, 0x18, 0xf5, 0x19, 0x5e, 0x37, 0xf1, 0x8d,
-				0x61, 0x99, 0x50, 0x83, 0xb7, 0x67, 0x12, 0x3a, 0x6f, 0xdd, 0xb2, 0x84, 0x08, 0xb9, 0x64, 0xe6,
-				0xfc, 0xe4, 0xc0, 0x5d, 0x1a, 0xb6, 0x06, 0x9c, 0x88, 0x26, 0x20, 0x1f, 0x91, 0x23, 0x37, 0x0c,
-				0x9b, 0x24, 0xe8, 0x86, 0xf5, 0x42, 0x87, 0xdf, 0xb2, 0xdc, 0xcb, 0x0c, 0x26, 0xdb, 0xba, 0xb9,
-				0x9d, 0xa7, 0x41, 0xbe, 0x4d, 0xc6, 0xde, 0xdd, 0x01, 0x8b, 0x2f, 0xd2, 0x3f, 0x9a, 0xb2, 0xa4,
-				0xb8, 0x83, 0xa9, 0x7f, 0xaa, 0x5e, 0x96, 0x29, 0x18, 0xab, 0x65, 0xaa, 0xb0, 0xab, 0x73, 0x44,
-				0xf6, 0x46, 0xb2, 0x2d, 0xd7, 0xd6, 0xa4, 0xf2, 0x1e, 0x05, 0x7a, 0x09, 0xa5, 0x39, 0xb1, 0x0b,
-				0x02, 0x81, 0x80, 0x27, 0x93, 0x66, 0x46, 0x11, 0xd5, 0xa9, 0x89, 0x05, 0xd4, 0x9e, 0x15, 0xa7,
-				0x9b, 0xaf, 0x6b, 0xad, 0x5a, 0xf6, 0x07, 0xec, 0x19, 0xf9, 0x4c, 0xe6, 0xd2, 0x6e, 0xfa, 0xbd,
-				0x7c, 0x43, 0x19, 0x41, 0x82, 0xa9, 0xfe, 0xca, 0x06, 0xf2, 0x1f, 0x00, 0xd5, 0x6b, 0xc6, 0x85,
-				0x1c, 0x03, 0xab, 0xd8, 0xca, 0xa4, 0x92, 0xc8, 0x18, 0x6c, 0x8b, 0x8e, 0xd6, 0x8e, 0x12, 0x5f,
-				0xab, 0xb9, 0xed, 0x97, 0xf0, 0x3a, 0xe4, 0xe2, 0xd1, 0x3f, 0x27, 0x31, 0x46, 0x7b, 0xdd, 0xdc,
-				0x7a, 0x25, 0x48, 0x87, 0x18, 0xc7, 0x7e, 0x39, 0x22, 0x9b, 0xc0, 0x15, 0x70, 0xb7, 0x52, 0x44,
-				0xff, 0xa0, 0xc9, 0x56, 0x6c, 0xd7, 0xb0, 0x54, 0xb0, 0xc6, 0xac, 0x6a, 0xc8, 0x76, 0xce, 0xe8,
-				0x14, 0x27, 0x9f, 0xd6, 0x06, 0xc8, 0x17, 0x9c, 0x9f, 0x64, 0x2f, 0x6c, 0x4e, 0xdb, 0x28, 0x8a,
-				0xd0, 0x22, 0x4b, 0x02, 0x81, 0x80, 0x02, 0x77, 0x7c, 0x61, 0x2b, 0x3b, 0x9a, 0x56, 0x14, 0xdd,
-				0x15, 0x5c, 0x28, 0x62, 0x9d, 0x85, 0x36, 0xba, 0x80, 0x85, 0xc8, 0x58, 0xd2, 0x4a, 0xfd, 0x6e,
-				0x02, 0x86, 0xda, 0x31, 0xfc, 0x55, 0xb8, 0x33, 0x95, 0x74, 0x05, 0xf0, 0xaf, 0x60, 0x56, 0xc3,
-				0xcf, 0xbb, 0x10, 0xa6, 0x18, 0xab, 0xd8, 0xb5, 0xed, 0x7d, 0xce, 0x85, 0xf0, 0xf9, 0xa1, 0x50,
-				0x41, 0xae, 0x00, 0x49, 0xe5, 0x0e, 0xea, 0xda, 0xb7, 0xdc, 0x1a, 0x62, 0x55, 0x77, 0x80, 0x67,
-				0xd6, 0x5e, 0x9c, 0x3a, 0x77, 0xb6, 0xff, 0x8c, 0x40, 0x9a, 0xa5, 0x92, 0x78, 0xd0, 0xd1, 0xd3,
-				0xcb, 0x73, 0x13, 0xca, 0x9e, 0xda, 0x80, 0x25, 0x4a, 0xfc, 0xbb, 0xd4, 0xfe, 0x60, 0x6f, 0x7b,
-				0x4e, 0x1a, 0xb9, 0x9b, 0x73, 0x0f, 0xf6, 0x8d, 0x7d, 0xaa, 0x04, 0xfd, 0x66, 0x48, 0x41, 0x35,
-				0x05, 0x20, 0xe7, 0x10, 0x14, 0x69
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xd7, 0xb0, 0x48, 0x38, 0x46, 0x6b, 0x83, 0xe1, 0x31, 0x0b, 0x44, 0x53,
-				0xbe, 0x08, 0xd1, 0x0d, 0x10, 0x3e, 0x67, 0x9c, 0x6c, 0x5f, 0x42, 0xf1, 0x27, 0x7e, 0xe8, 0x54,
-				0x6f, 0x6e, 0x48, 0x1a, 0x4c, 0x6e, 0x1a, 0xd5, 0xac, 0x4f, 0x42, 0x0a, 0x05, 0x19, 0xab, 0x0d,
-				0xec, 0x24, 0x37, 0xb5, 0x10, 0xdc, 0x3a, 0xa9, 0x4f, 0x28, 0xb4, 0x41, 0x9b, 0xcb, 0xd7, 0xc9,
-				0x42, 0x3f, 0x30, 0x21, 0x27, 0x44, 0x64, 0xf7, 0x7d, 0x6a, 0x13, 0xb3, 0x06, 0x00, 0xed, 0x96,
-				0x5f, 0xa1, 0xc5, 0x6c, 0xca, 0x7a, 0xfc, 0x13, 0x33, 0x17, 0xb3, 0x04, 0x94, 0xba, 0x38, 0x5b,
-				0x01, 0xce, 0x23, 0xc4, 0x43, 0x8e, 0x46, 0x5f, 0x99, 0x1c, 0xa9, 0xbe, 0x10, 0x8e, 0x30, 0x06,
-				0x54, 0x4f, 0xb7, 0x03, 0x66, 0x82, 0x64, 0xa9, 0xf8, 0x7e, 0x71, 0x5a, 0x7f, 0x58, 0x06, 0x8e,
-				0xf8, 0x73, 0xb9, 0x0a, 0xae, 0x47, 0x10, 0x9d, 0x44, 0x4d, 0x72, 0xcb, 0x38, 0x7b, 0x87, 0xb0,
-				0x34, 0xdb, 0x8c, 0x45, 0x66, 0x0a, 0x08, 0x6b, 0x9f, 0x31, 0xb9, 0x41, 0x5b, 0x08, 0x9a, 0xd4,
-				0x48, 0xaa, 0xa8, 0xdd, 0xa2, 0xe0, 0x66, 0xf0, 0xcc, 0x35, 0xaa, 0xc5, 0xb1, 0x8a, 0x04, 0x6b,
-				0xb3, 0xf2, 0x4b, 0xbb, 0x46, 0xad, 0x37, 0x46, 0xac, 0x55, 0xc3, 0xb0, 0xb1, 0x72, 0x2e, 0xb6,
-				0x9d, 0xa3, 0x12, 0x87, 0xd7, 0x44, 0x60, 0x6c, 0x18, 0x58, 0x43, 0x3c, 0xc5, 0x7b, 0x04, 0xf3,
-				0xb3, 0x73, 0x33, 0xd8, 0x4b, 0x90, 0x5f, 0xfd, 0x9c, 0xca, 0xe0, 0x5c, 0x60, 0xb1, 0x46, 0x83,
-				0x7d, 0x42, 0x13, 0xad, 0x27, 0xfd, 0x81, 0xf3, 0x6d, 0xe1, 0x05, 0x51, 0xc6, 0x41, 0xac, 0x8a,
-				0xe4, 0x31, 0xc5, 0x72, 0x56, 0x9f, 0xed, 0x0f, 0xf0, 0xc9, 0x8a, 0xae, 0x61, 0x3d, 0xc3, 0x97,
-				0x2e, 0x96, 0xbc, 0x8b
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd7, 0xb0, 0x48, 0x38,
-				0x46, 0x6b, 0x83, 0xe1, 0x31, 0x0b, 0x44, 0x53, 0xbe, 0x08, 0xd1, 0x0d, 0x10, 0x3e, 0x67, 0x9c,
-				0x6c, 0x5f, 0x42, 0xf1, 0x27, 0x7e, 0xe8, 0x54, 0x6f, 0x6e, 0x48, 0x1a, 0x4c, 0x6e, 0x1a, 0xd5,
-				0xac, 0x4f, 0x42, 0x0a, 0x05, 0x19, 0xab, 0x0d, 0xec, 0x24, 0x37, 0xb5, 0x10, 0xdc, 0x3a, 0xa9,
-				0x4f, 0x28, 0xb4, 0x41, 0x9b, 0xcb, 0xd7, 0xc9, 0x42, 0x3f, 0x30, 0x21, 0x27, 0x44, 0x64, 0xf7,
-				0x7d, 0x6a, 0x13, 0xb3, 0x06, 0x00, 0xed, 0x96, 0x5f, 0xa1, 0xc5, 0x6c, 0xca, 0x7a, 0xfc, 0x13,
-				0x33, 0x17, 0xb3, 0x04, 0x94, 0xba, 0x38, 0x5b, 0x01, 0xce, 0x23, 0xc4, 0x43, 0x8e, 0x46, 0x5f,
-				0x99, 0x1c, 0xa9, 0xbe, 0x10, 0x8e, 0x30, 0x06, 0x54, 0x4f, 0xb7, 0x03, 0x66, 0x82, 0x64, 0xa9,
-				0xf8, 0x7e, 0x71, 0x5a, 0x7f, 0x58, 0x06, 0x8e, 0xf8, 0x73, 0xb9, 0x0a, 0xae, 0x47, 0x10, 0x9d,
-				0x44, 0x4d, 0x72, 0xcb, 0x38, 0x7b, 0x87, 0xb0, 0x34, 0xdb, 0x8c, 0x45, 0x66, 0x0a, 0x08, 0x6b,
-				0x9f, 0x31, 0xb9, 0x41, 0x5b, 0x08, 0x9a, 0xd4, 0x48, 0xaa, 0xa8, 0xdd, 0xa2, 0xe0, 0x66, 0xf0,
-				0xcc, 0x35, 0xaa, 0xc5, 0xb1, 0x8a, 0x04, 0x6b, 0xb3, 0xf2, 0x4b, 0xbb, 0x46, 0xad, 0x37, 0x46,
-				0xac, 0x55, 0xc3, 0xb0, 0xb1, 0x72, 0x2e, 0xb6, 0x9d, 0xa3, 0x12, 0x87, 0xd7, 0x44, 0x60, 0x6c,
-				0x18, 0x58, 0x43, 0x3c, 0xc5, 0x7b, 0x04, 0xf3, 0xb3, 0x73, 0x33, 0xd8, 0x4b, 0x90, 0x5f, 0xfd,
-				0x9c, 0xca, 0xe0, 0x5c, 0x60, 0xb1, 0x46, 0x83, 0x7d, 0x42, 0x13, 0xad, 0x27, 0xfd, 0x81, 0xf3,
-				0x6d, 0xe1, 0x05, 0x51, 0xc6, 0x41, 0xac, 0x8a, 0xe4, 0x31, 0xc5, 0x72, 0x56, 0x9f, 0xed, 0x0f,
-				0xf0, 0xc9, 0x8a, 0xae, 0x61, 0x3d, 0xc3, 0x97, 0x2e, 0x96, 0xbc, 0x8b, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x0c, 0xa9, 0x99, 0x3b, 0xd0, 0x8a, 0x8c, 0x56, 0x02, 0xa2, 0x96,
-				0x32, 0xd2, 0x63, 0xc3, 0x1e, 0x20, 0xb7, 0x81, 0x2e, 0xb2, 0x40, 0x0f, 0x76, 0x87, 0xea, 0x8f,
-				0xea, 0x31, 0x16, 0x88, 0xde, 0x1e, 0x61, 0x92, 0x6a, 0xbb, 0xf0, 0x75, 0x40, 0x90, 0x57, 0x16,
-				0xef, 0x3c, 0xcf, 0x4d, 0x83, 0xf0, 0x46, 0xf5, 0x9c, 0xad, 0xfc, 0x86, 0x44, 0x99, 0xc8, 0x68,
-				0x55, 0x34, 0xf1, 0xef, 0xb9, 0xea, 0x8b, 0xbd, 0xdf, 0xb7, 0xb9, 0xac, 0x09, 0x65, 0x0f, 0x55,
-				0xe3, 0x6f, 0x9e, 0xd8, 0x2f, 0xd0, 0x5d, 0x53, 0x02, 0x2f, 0x8c, 0x33, 0x22, 0xd0, 0x36, 0x74,
-				0x8b, 0x87, 0x3a, 0x1a, 0x68, 0x71, 0xcc, 0xde, 0xfd, 0xca, 0xc7, 0xdf, 0x81, 0x3c, 0x88, 0x94,
-				0x72, 0x32, 0xad, 0xf1, 0x61, 0x1e, 0x3a, 0x06, 0x7d, 0xe2, 0x0c, 0x4e, 0x4c, 0x51, 0x50, 0x92,
-				0x25, 0xff, 0x99, 0x0f, 0xa2, 0x60, 0xbe, 0x02, 0x66, 0x8a, 0x74, 0x54, 0x6e, 0x69, 0x23, 0x6b,
-				0xdd, 0x6c, 0xe4, 0x82, 0x26, 0xa0, 0x5a, 0x05, 0xe3, 0x6a, 0x41, 0x7c, 0xaa, 0xad, 0x6a, 0xb0,
-				0x83, 0x9e, 0x03, 0x3b, 0x1b, 0xdd, 0x80, 0xfb, 0x14, 0x63, 0x52, 0x0c, 0x2a, 0x6c, 0xdd, 0xd0,
-				0xc3, 0xe3, 0x28, 0xf8, 0xd5, 0x66, 0xcc, 0x57, 0xad, 0x4e, 0x0e, 0x6d, 0xad, 0xbf, 0x93, 0x24,
-				0xd0, 0xb8, 0x27, 0xbd, 0x77, 0x39, 0x2d, 0x26, 0xdf, 0xb4, 0xf5, 0xe8, 0xc3, 0xc8, 0x7d, 0xfd,
-				0x15, 0x46, 0x68, 0xcd, 0x91, 0x59, 0xc5, 0xbe, 0x9b, 0x36, 0x5f, 0x2d, 0xd9, 0x87, 0x05, 0xa3,
-				0x3a, 0x10, 0x2e, 0x38, 0x12, 0x51, 0x00, 0x19, 0xad, 0x71, 0x88, 0x7d, 0xa9, 0xc9, 0x27, 0x0e,
-				0x51, 0x6b, 0x6d, 0x0c, 0x4d, 0x16, 0xc1, 0xbf, 0x81, 0x4a, 0xa1, 0x7f, 0x21, 0x27, 0x07, 0x8b,
-				0x3c, 0xb1, 0xd5, 0x20, 0x31, 0x02, 0x81, 0x81, 0x00, 0xfa, 0x9f, 0x55, 0xde, 0x82, 0xb5, 0xe5,
-				0xb8, 0x53, 0x40, 0xa0, 0x7c, 0xf3, 0xd9, 0x6f, 0xe8, 0xe4, 0x9d, 0x19, 0xb4, 0xc6, 0x9f, 0x10,
-				0xaf, 0xa3, 0xed, 0xb2, 0x5b, 0x5b, 0xce, 0x44, 0x0c, 0xc6, 0xda, 0xe3, 0xaa, 0xec, 0x7d, 0xdf,
-				0xac, 0x4d, 0x9f, 0x8e, 0xcd, 0x27, 0x64, 0xc4, 0x5a, 0xdc, 0xc2, 0x86, 0x1f, 0x1b, 0x73, 0xdf,
-				0x4f, 0x41, 0xb5, 0x21, 0xdf, 0x21, 0x57, 0x4b, 0x40, 0x05, 0x66, 0x76, 0x65, 0x54, 0xc7, 0x5f,
-				0x8a, 0xfa, 0x91, 0x00, 0x09, 0xf3, 0x66, 0x46, 0xe4, 0x6f, 0xbd, 0x20, 0xb6, 0x87, 0x27, 0x52,
-				0x7d, 0x31, 0xac, 0xb1, 0xfe, 0xe6, 0x9c, 0x98, 0x3e, 0xbb, 0xd8, 0xea, 0x8e, 0x7a, 0x2f, 0x53,
-				0x9c, 0xcb, 0x72, 0x3d, 0x7d, 0x8f, 0xaa, 0xb6, 0x19, 0x45, 0x74, 0xe1, 0x8a, 0xdf, 0x42, 0x1b,
-				0x0d, 0xd6, 0xae, 0x10, 0xb9, 0xb8, 0xd3, 0xbe, 0x11, 0x02, 0x81, 0x81, 0x00, 0xdc, 0x51, 0x0e,
-				0x4f, 0xd9, 0x63, 0x31, 0xbc, 0x75, 0xa8, 0xc1, 0x48, 0xd3, 0xf5, 0x7f, 0xca, 0x9f, 0xa8, 0x11,
-				0x51, 0x44, 0xa2, 0x90, 0xdf, 0x06, 0x7e, 0x04, 0xe5, 0x7a, 0x65, 0x04, 0xd4, 0x8b, 0x74, 0xb0,
-				0xa8, 0xe3, 0x1d, 0x98, 0x6e, 0xeb, 0xcd, 0x13, 0x21, 0xaa, 0x23, 0x45, 0x25, 0xd1, 0xc3, 0xab,
-				0x7d, 0x37, 0x68, 0x83, 0x75, 0x47, 0xe3, 0xe1, 0xb3, 0xa8, 0x50, 0x0f, 0xdf, 0xe1, 0x47, 0x45,
-				0x8e, 0x9c, 0x11, 0x96, 0xf7, 0x01, 0xc9, 0xf1, 0x88, 0x8a, 0x62, 0x29, 0x1f, 0xf3, 0x2c, 0x59,
-				0x10, 0x42, 0x7d, 0xe9, 0xb6, 0x45, 0xa9, 0xa4, 0x24, 0x04, 0x3f, 0x32, 0xcd, 0xdd, 0x53, 0xd2,
-				0x13, 0xa9, 0xcf, 0x39, 0x30, 0xc8, 0x95, 0xea, 0x2e, 0x0c, 0xcd, 0x9b, 0x66, 0x09, 0xb1, 0x90,
-				0x97, 0x30, 0xd0, 0xbd, 0xff, 0x58, 0x72, 0x34, 0x87, 0x7d, 0x6c, 0xe4, 0xdb, 0x02, 0x81, 0x80,
-				0x32, 0x87, 0x3f, 0x4b, 0xbe, 0x34, 0xa8, 0x1c, 0xf2, 0x83, 0xfc, 0x17, 0x55, 0x1e, 0x88, 0x86,
-				0x7e, 0xd9, 0x01, 0x9e, 0xc5, 0xd0, 0xba, 0x0f, 0x7f, 0x50, 0x63, 0xfe, 0x31, 0x53, 0x33, 0xbb,
-				0x13, 0xb8, 0x7b, 0xe0, 0x31, 0x0f, 0xeb, 0xb1, 0x94, 0x70, 0xcf, 0xdc, 0xa2, 0xcd, 0x99, 0x1c,
-				0xec, 0x97, 0x37, 0x6d, 0x3c, 0x1e, 0xaf, 0x6e, 0x0e, 0x44, 0x53, 0x90, 0xe5, 0xea, 0xf0, 0x9b,
-				0xf6, 0xba, 0xc2, 0xb2, 0x09, 0x56, 0xac, 0xf7, 0x9b, 0x2e, 0xf2, 0xc0, 0x0e, 0xd7, 0x97, 0x01,
-				0x65, 0x59, 0xcf, 0x27, 0x9d, 0xb6, 0x1a, 0xd6, 0x6c, 0xd6, 0x71, 0x88, 0x7f, 0xbc, 0x20, 0xa1,
-				0xbd, 0x43, 0xad, 0x7e, 0x8e, 0x39, 0xce, 0x74, 0xb5, 0x3b, 0xd2, 0x13, 0xe7, 0x8c, 0x36, 0x6c,
-				0x7f, 0xe9, 0x61, 0xb3, 0x9a, 0xf1, 0x7b, 0xfc, 0xdd, 0x44, 0x78, 0xd0, 0xc8, 0xe7, 0xbf, 0xd1,
-				0x02, 0x81, 0x80, 0x37, 0x95, 0x23, 0x7d, 0x35, 0xa4, 0xf6, 0xe9, 0x4a, 0xed, 0xd6, 0x45, 0x9f,
-				0x63, 0xf2, 0x67, 0x96, 0x3b, 0xfa, 0x92, 0x7c, 0x34, 0x5f, 0x44, 0x45, 0x09, 0x0a, 0x07, 0x33,
-				0x07, 0xc5, 0x5e, 0x32, 0x08, 0xb0, 0x81, 0x0b, 0x3b, 0x6e, 0x37, 0x9d, 0xb9, 0xd1, 0x37, 0xcf,
-				0x0a, 0xb2, 0xe9, 0x45, 0xb0, 0x8d, 0xd5, 0x3b, 0x63, 0x5c, 0xb6, 0xfb, 0xfa, 0x1b, 0xf9, 0x0d,
-				0x5f, 0x95, 0x81, 0xaf, 0xfe, 0x21, 0x28, 0x47, 0x6b, 0x90, 0xa0, 0xa4, 0x8c, 0xe4, 0x28, 0xc4,
-				0x70, 0xdb, 0x5b, 0x3a, 0x28, 0x58, 0x17, 0xe8, 0x0e, 0x88, 0x25, 0xfa, 0x11, 0x40, 0x5d, 0xed,
-				0xcc, 0x5b, 0xee, 0xe0, 0x05, 0xc3, 0x9c, 0x3e, 0x5d, 0x0f, 0x5a, 0xa5, 0x60, 0x5d, 0x02, 0x5d,
-				0x2c, 0x8a, 0x26, 0x06, 0x10, 0x0c, 0x20, 0x78, 0xaa, 0x51, 0x24, 0xd8, 0x95, 0x87, 0x77, 0x1f,
-				0x47, 0x97, 0xbd, 0x02, 0x81, 0x80, 0x25, 0x8b, 0x8f, 0xb6, 0x3e, 0x35, 0x5c, 0x56, 0x81, 0x03,
-				0x06, 0x67, 0x8f, 0xc7, 0x7a, 0x54, 0xe0, 0x29, 0x84, 0xf5, 0x0e, 0xd1, 0x96, 0x4b, 0xeb, 0xe2,
-				0x0a, 0x31, 0x8e, 0xea, 0xcf, 0xc9, 0x0d, 0x73, 0x2f, 0x31, 0xfc, 0xbc, 0xd0, 0xec, 0xe2, 0xd2,
-				0x2c, 0x72, 0x48, 0xbb, 0xb7, 0x61, 0x85, 0xe8, 0xf0, 0xac, 0x3e, 0x11, 0x34, 0xb4, 0xc4, 0xaa,
-				0xe8, 0x43, 0x83, 0xeb, 0x12, 0xf5, 0x44, 0x32, 0xb8, 0x82, 0x08, 0x53, 0x5e, 0xec, 0xb8, 0x10,
-				0x63, 0xc5, 0x53, 0xbe, 0x36, 0x3a, 0x28, 0xdf, 0x87, 0x5e, 0x46, 0xa4, 0xe0, 0xbc, 0xd6, 0xa6,
-				0x16, 0x77, 0x6a, 0xf5, 0xd9, 0x0a, 0x79, 0x8f, 0xaa, 0x1a, 0x9f, 0x7f, 0xea, 0x94, 0xd8, 0x6d,
-				0x7a, 0xfd, 0x19, 0x46, 0x27, 0x6f, 0x4b, 0xb8, 0xd9, 0x67, 0xa7, 0xce, 0x51, 0x95, 0x3e, 0xe6,
-				0xce, 0x36, 0x09, 0xfc, 0xd0, 0x71
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xae, 0x09, 0xe7, 0x83, 0x17, 0xc1, 0x72, 0xd7, 0x86, 0x28, 0xe8, 0x40,
-				0xb5, 0x1e, 0x5b, 0xb6, 0xd7, 0x6a, 0xa1, 0xb2, 0xb7, 0xe4, 0xcd, 0x53, 0x40, 0xf5, 0x54, 0x58,
-				0x8a, 0x52, 0xf5, 0xd3, 0x77, 0x16, 0xd0, 0x1d, 0xc1, 0x80, 0x48, 0x79, 0xe6, 0xa4, 0xb8, 0x2b,
-				0xe0, 0x5e, 0xc9, 0x87, 0x2e, 0x5e, 0x02, 0x80, 0xe7, 0x1c, 0xb8, 0x88, 0xc9, 0xff, 0x2c, 0x4a,
-				0x33, 0x10, 0x82, 0x56, 0x3d, 0x1f, 0x61, 0x6d, 0x6d, 0x52, 0x68, 0xaf, 0x39, 0x47, 0x6b, 0xaa,
-				0x1e, 0x0d, 0x95, 0x35, 0x24, 0x48, 0xff, 0x0c, 0x45, 0xd6, 0x2e, 0x06, 0x3a, 0x50, 0xc9, 0x27,
-				0xfb, 0xf7, 0x3a, 0x01, 0xfd, 0xc8, 0x0e, 0xd7, 0x93, 0xe0, 0x7c, 0x63, 0xc1, 0x63, 0x4e, 0xf2,
-				0x23, 0x63, 0x6f, 0x07, 0x74, 0xfd, 0x02, 0xbe, 0x9d, 0x1b, 0xad, 0x14, 0x28, 0x80, 0x15, 0x0a,
-				0x3a, 0x44, 0x5c, 0xa1, 0x29, 0xfc, 0xb0, 0x18, 0x48, 0x2f, 0xa4, 0xcb, 0x56, 0xb5, 0xd1, 0xa3,
-				0x20, 0x3b, 0xe1, 0xd2, 0x2e, 0x07, 0x18, 0x06, 0xa1, 0x1f, 0x37, 0xa3, 0x05, 0xbc, 0x11, 0x66,
-				0x20, 0xa6, 0x9b, 0xd6, 0x6c, 0x89, 0xef, 0x5b, 0x72, 0xfd, 0x44, 0x7c, 0x27, 0x09, 0x65, 0x48,
-				0x1f, 0x9c, 0x79, 0xa1, 0x49, 0x23, 0xbf, 0x93, 0xcb, 0xfb, 0xeb, 0x14, 0x0a, 0x8e, 0xa4, 0xef,
-				0xec, 0xfb, 0xc3, 0x48, 0xf1, 0xf0, 0xc3, 0x10, 0xe3, 0x80, 0x24, 0xca, 0xa6, 0xca, 0xc2, 0x4a,
-				0xee, 0x6e, 0xe7, 0x4e, 0xdc, 0x8c, 0x15, 0xe3, 0xfc, 0xed, 0xa2, 0xc6, 0xa7, 0x4b, 0xe7, 0x79,
-				0xfd, 0x40, 0xc4, 0x60, 0xd2, 0x50, 0x33, 0x73, 0x70, 0x9d, 0x60, 0x8c, 0x28, 0x81, 0x5d, 0x63,
-				0xf5, 0xe7, 0x16, 0xe9, 0xe4, 0x08, 0xa2, 0xa9, 0xa5, 0xc5, 0x08, 0x6c, 0x24, 0xea, 0x22, 0x83,
-				0x29, 0x33, 0x7d, 0xe9
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0x09, 0xe7, 0x83,
-				0x17, 0xc1, 0x72, 0xd7, 0x86, 0x28, 0xe8, 0x40, 0xb5, 0x1e, 0x5b, 0xb6, 0xd7, 0x6a, 0xa1, 0xb2,
-				0xb7, 0xe4, 0xcd, 0x53, 0x40, 0xf5, 0x54, 0x58, 0x8a, 0x52, 0xf5, 0xd3, 0x77, 0x16, 0xd0, 0x1d,
-				0xc1, 0x80, 0x48, 0x79, 0xe6, 0xa4, 0xb8, 0x2b, 0xe0, 0x5e, 0xc9, 0x87, 0x2e, 0x5e, 0x02, 0x80,
-				0xe7, 0x1c, 0xb8, 0x88, 0xc9, 0xff, 0x2c, 0x4a, 0x33, 0x10, 0x82, 0x56, 0x3d, 0x1f, 0x61, 0x6d,
-				0x6d, 0x52, 0x68, 0xaf, 0x39, 0x47, 0x6b, 0xaa, 0x1e, 0x0d, 0x95, 0x35, 0x24, 0x48, 0xff, 0x0c,
-				0x45, 0xd6, 0x2e, 0x06, 0x3a, 0x50, 0xc9, 0x27, 0xfb, 0xf7, 0x3a, 0x01, 0xfd, 0xc8, 0x0e, 0xd7,
-				0x93, 0xe0, 0x7c, 0x63, 0xc1, 0x63, 0x4e, 0xf2, 0x23, 0x63, 0x6f, 0x07, 0x74, 0xfd, 0x02, 0xbe,
-				0x9d, 0x1b, 0xad, 0x14, 0x28, 0x80, 0x15, 0x0a, 0x3a, 0x44, 0x5c, 0xa1, 0x29, 0xfc, 0xb0, 0x18,
-				0x48, 0x2f, 0xa4, 0xcb, 0x56, 0xb5, 0xd1, 0xa3, 0x20, 0x3b, 0xe1, 0xd2, 0x2e, 0x07, 0x18, 0x06,
-				0xa1, 0x1f, 0x37, 0xa3, 0x05, 0xbc, 0x11, 0x66, 0x20, 0xa6, 0x9b, 0xd6, 0x6c, 0x89, 0xef, 0x5b,
-				0x72, 0xfd, 0x44, 0x7c, 0x27, 0x09, 0x65, 0x48, 0x1f, 0x9c, 0x79, 0xa1, 0x49, 0x23, 0xbf, 0x93,
-				0xcb, 0xfb, 0xeb, 0x14, 0x0a, 0x8e, 0xa4, 0xef, 0xec, 0xfb, 0xc3, 0x48, 0xf1, 0xf0, 0xc3, 0x10,
-				0xe3, 0x80, 0x24, 0xca, 0xa6, 0xca, 0xc2, 0x4a, 0xee, 0x6e, 0xe7, 0x4e, 0xdc, 0x8c, 0x15, 0xe3,
-				0xfc, 0xed, 0xa2, 0xc6, 0xa7, 0x4b, 0xe7, 0x79, 0xfd, 0x40, 0xc4, 0x60, 0xd2, 0x50, 0x33, 0x73,
-				0x70, 0x9d, 0x60, 0x8c, 0x28, 0x81, 0x5d, 0x63, 0xf5, 0xe7, 0x16, 0xe9, 0xe4, 0x08, 0xa2, 0xa9,
-				0xa5, 0xc5, 0x08, 0x6c, 0x24, 0xea, 0x22, 0x83, 0x29, 0x33, 0x7d, 0xe9, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x0f, 0x3c, 0xda, 0xc2, 0x45, 0x90, 0x30, 0x67, 0xe2, 0x5d, 0x2e,
-				0x88, 0x8b, 0xd3, 0x0e, 0xa0, 0xa1, 0x97, 0xba, 0x74, 0x95, 0x59, 0x39, 0x08, 0xf3, 0x05, 0x07,
-				0xcf, 0x80, 0xbc, 0xe6, 0xbd, 0x0f, 0x0e, 0x36, 0x46, 0x84, 0xac, 0xa0, 0xab, 0xdb, 0x9f, 0xcc,
-				0x68, 0x3b, 0x0a, 0xd1, 0x86, 0x3e, 0x6f, 0x08, 0xb5, 0x14, 0x87, 0x15, 0x39, 0x14, 0xc6, 0x7c,
-				0xb0, 0x3a, 0x6c, 0x55, 0x9d, 0x0b, 0x58, 0xf6, 0x04, 0xc8, 0xaf, 0x90, 0x6e, 0xd7, 0x0b, 0x03,
-				0xc8, 0x2f, 0x3d, 0x6d, 0x34, 0xeb, 0xea, 0x60, 0x3a, 0x48, 0xdb, 0x09, 0xc8, 0x8d, 0xce, 0x88,
-				0xee, 0x31, 0x47, 0x62, 0x12, 0xce, 0x8f, 0x77, 0x8d, 0x34, 0x6b, 0x51, 0x38, 0xc2, 0xb3, 0xd9,
-				0x33, 0xa6, 0x19, 0x8c, 0x9d, 0x10, 0x87, 0x1e, 0x78, 0x65, 0xf5, 0x08, 0x60, 0x5d, 0x73, 0x69,
-				0x64, 0x2d, 0xd9, 0xd2, 0x6a, 0x3c, 0x87, 0x7e, 0x9b, 0x27, 0x4d, 0x27, 0x8a, 0xab, 0xc5, 0x1f,
-				0xe1, 0x3f, 0x45, 0x58, 0x69, 0xfe, 0x53, 0x86, 0x71, 0xed, 0x4b, 0x59, 0x0b, 0x60, 0x8b, 0x57,
-				0x13, 0xef, 0xcc, 0x42, 0x17, 0x40, 0x19, 0x11, 0x68, 0x98, 0x12, 0x9d, 0x87, 0x79, 0xe7, 0xf6,
-				0x27, 0x91, 0x92, 0x40, 0xdd, 0x23, 0x50, 0x42, 0x88, 0xb1, 0x59, 0x5f, 0x21, 0xc8, 0x51, 0x8f,
-				0xde, 0x6c, 0x0c, 0x6f, 0x7c, 0xa2, 0xf9, 0x69, 0x28, 0xd6, 0xab, 0xa8, 0x7a, 0x29, 0x48, 0x29,
-				0xfd, 0x87, 0x84, 0xff, 0xff, 0x3d, 0xad, 0x58, 0xc3, 0xb7, 0x3f, 0x3b, 0x85, 0x98, 0x57, 0x6d,
-				0x80, 0x61, 0x33, 0x98, 0x4c, 0x33, 0xc0, 0x70, 0x11, 0x9a, 0x89, 0xfe, 0x04, 0xd2, 0x3f, 0x6d,
-				0xa3, 0xd1, 0x50, 0xee, 0x5c, 0xe1, 0xd4, 0x1f, 0x6d, 0xb9, 0xff, 0x30, 0x09, 0xd0, 0x59, 0x02,
-				0x83, 0x60, 0x84, 0xbe, 0x29, 0x02, 0x81, 0x81, 0x00, 0xf6, 0x00, 0xf9, 0x0d, 0x70, 0xb7, 0xeb,
-				0x8d, 0x1d, 0xb8, 0x5d, 0xf1, 0xad, 0x98, 0x91, 0x52, 0xa9, 0x83, 0x2f, 0xc2, 0xf1, 0x5d, 0x36,
-				0xf0, 0x3f, 0x12, 0xb2, 0xfb, 0x2a, 0x8c, 0xd2, 0x55, 0x05, 0xc3, 0xdb, 0x0d, 0xd9, 0x33, 0x25,
-				0x82, 0x20, 0x65, 0x08, 0xe3, 0xe8, 0x85, 0x9c, 0x59, 0x15, 0x8e, 0x54, 0xfa, 0xc7, 0x7d, 0x6f,
-				0x61, 0xeb, 0x19, 0xf9, 0xdc, 0xab, 0x1e, 0x30, 0x60, 0x5f, 0x12, 0x73, 0x33, 0x09, 0xd8, 0xba,
-				0x7e, 0x6f, 0x05, 0x49, 0x8f, 0x5a, 0xd2, 0x7c, 0x4c, 0xd5, 0x71, 0x3f, 0xb0, 0xdc, 0x84, 0xdd,
-				0x39, 0x90, 0x55, 0x5c, 0x20, 0xcf, 0x63, 0xf0, 0xbd, 0xb1, 0xef, 0xec, 0xdc, 0x50, 0x7c, 0xfc,
-				0xbe, 0x7d, 0x84, 0x0b, 0x0d, 0x54, 0xd8, 0x4d, 0x06, 0x88, 0xfc, 0x62, 0xc4, 0x64, 0xba, 0x61,
-				0x49, 0xf0, 0xed, 0xea, 0x63, 0xf0, 0x1b, 0xae, 0x43, 0x02, 0x81, 0x81, 0x00, 0xb5, 0x1c, 0x52,
-				0x8a, 0x71, 0xbb, 0x69, 0x4d, 0x10, 0xc1, 0xaf, 0x03, 0xaa, 0x8e, 0xfb, 0xf0, 0x17, 0xad, 0x2f,
-				0xac, 0x2f, 0xa8, 0x05, 0x92, 0xd9, 0xa2, 0xb1, 0x85, 0xde, 0x9f, 0xe7, 0x82, 0x32, 0x34, 0x08,
-				0x45, 0xae, 0xb4, 0x5d, 0xe1, 0x27, 0xf3, 0x25, 0xe4, 0xa1, 0x03, 0x4d, 0xbd, 0x15, 0xa1, 0x1c,
-				0xbf, 0x36, 0x8c, 0x8f, 0x5d, 0x33, 0x62, 0x19, 0xa1, 0xab, 0xeb, 0xdf, 0x10, 0x14, 0xf6, 0x93,
-				0x94, 0xb0, 0x7f, 0x35, 0xed, 0x8e, 0x4f, 0x46, 0x54, 0xe5, 0x24, 0xb1, 0x7d, 0x17, 0x0c, 0xfc,
-				0x85, 0x65, 0x57, 0x6d, 0x44, 0x1b, 0x1c, 0x79, 0x55, 0x21, 0xe8, 0x2e, 0x64, 0x93, 0x01, 0xf7,
-				0xcc, 0x75, 0x2e, 0x32, 0x10, 0xef, 0x6a, 0xe6, 0x95, 0x22, 0xf1, 0x5b, 0x6e, 0x19, 0x6b, 0x4f,
-				0xf6, 0xad, 0xf3, 0x45, 0xea, 0xf3, 0xe1, 0xad, 0xfa, 0x25, 0x8b, 0xde, 0x63, 0x02, 0x81, 0x80,
-				0x02, 0x60, 0x46, 0x07, 0x8c, 0x34, 0x2a, 0x91, 0x45, 0x5d, 0x37, 0x83, 0x13, 0x13, 0x2b, 0x2c,
-				0x2a, 0x38, 0xfb, 0x28, 0x1d, 0xde, 0xb1, 0x9e, 0x26, 0x6d, 0xce, 0xce, 0xc0, 0x3d, 0x75, 0xf6,
-				0x9e, 0x44, 0xa3, 0x04, 0x02, 0x3a, 0x0d, 0x3d, 0xb1, 0x84, 0x68, 0x4e, 0x93, 0x3b, 0x5f, 0x24,
-				0x39, 0x22, 0x13, 0xce, 0x0c, 0x49, 0x38, 0xdf, 0x30, 0x3f, 0x22, 0xfb, 0xaf, 0xa7, 0x6d, 0xfe,
-				0x30, 0x4c, 0xe4, 0x51, 0xf4, 0xe1, 0x64, 0x03, 0xbe, 0x9c, 0xc5, 0x76, 0x1e, 0x01, 0x74, 0x73,
-				0xe5, 0x87, 0xdf, 0x7e, 0x9c, 0xd2, 0xa7, 0xb4, 0x5b, 0xa1, 0x87, 0x6f, 0x45, 0xb1, 0x88, 0x6c,
-				0xbc, 0xa0, 0x3d, 0xa0, 0x6f, 0x22, 0x95, 0xea, 0x5d, 0x19, 0xfe, 0x65, 0x55, 0x91, 0x75, 0x44,
-				0xff, 0xe3, 0xb8, 0x2c, 0x7f, 0x70, 0x91, 0x69, 0xfe, 0x6a, 0xbd, 0xdd, 0xd3, 0x3e, 0xe1, 0x33,
-				0x02, 0x81, 0x80, 0x3b, 0x7c, 0xa0, 0x07, 0xe5, 0x2f, 0x5f, 0x78, 0xf6, 0xa6, 0x07, 0x6c, 0x36,
-				0xdb, 0x5c, 0x19, 0x12, 0x4d, 0xca, 0x38, 0xce, 0x36, 0x6c, 0x0e, 0x3d, 0xf9, 0xd8, 0x41, 0x56,
-				0x4c, 0x43, 0x68, 0x5a, 0x41, 0x08, 0xee, 0x8a, 0x61, 0xa7, 0xec, 0x4a, 0x88, 0xec, 0xcb, 0x59,
-				0xaf, 0x92, 0x1b, 0x27, 0x3d, 0x92, 0x09, 0xa4, 0x4b, 0x2a, 0xd3, 0xbc, 0x0a, 0xde, 0xcc, 0x61,
-				0x81, 0xc9, 0xf4, 0xa8, 0x4e, 0x0d, 0x4f, 0x6b, 0x61, 0x7d, 0x3f, 0x17, 0xdd, 0x26, 0x06, 0xc0,
-				0x74, 0xfa, 0xef, 0x51, 0x60, 0xec, 0x98, 0x8c, 0x1e, 0xd9, 0x3e, 0xe3, 0x80, 0xc8, 0xc1, 0x93,
-				0xaf, 0x85, 0x7d, 0x77, 0x63, 0xd0, 0x16, 0x91, 0xee, 0xa8, 0x77, 0x33, 0x8c, 0x73, 0x4c, 0x4c,
-				0xfb, 0xe5, 0xc2, 0x16, 0x0b, 0x4f, 0x6a, 0x80, 0xdc, 0x44, 0xfc, 0xd5, 0x3a, 0x2d, 0x40, 0xda,
-				0x90, 0x44, 0x6d, 0x02, 0x81, 0x80, 0x6e, 0x45, 0xc7, 0x6f, 0x93, 0xfb, 0x46, 0x8b, 0x81, 0xa8,
-				0x6b, 0x09, 0x9a, 0xaf, 0x26, 0xe6, 0xcb, 0xfb, 0x6c, 0x5a, 0xc6, 0x4d, 0x29, 0x22, 0x65, 0x47,
-				0xab, 0x0c, 0xee, 0xf3, 0x8b, 0xed, 0xa4, 0x9d, 0x2a, 0x15, 0xcc, 0x6f, 0x1e, 0x19, 0x1b, 0x0e,
-				0xda, 0xd3, 0xcc, 0xb3, 0x0d, 0x4f, 0x5c, 0x4a, 0x73, 0xee, 0xaf, 0x22, 0x83, 0x2b, 0x92, 0x0f,
-				0xfc, 0xf8, 0xa3, 0xac, 0x53, 0xb8, 0x28, 0xfc, 0x96, 0x4e, 0x1d, 0x84, 0xdd, 0xeb, 0x74, 0xac,
-				0x7b, 0xbe, 0x7e, 0x2e, 0xaf, 0x47, 0x16, 0x50, 0x84, 0xdf, 0x05, 0x7b, 0xeb, 0x4a, 0xb6, 0xea,
-				0x27, 0x65, 0x5d, 0xef, 0x01, 0x8c, 0x91, 0x70, 0xc6, 0x33, 0xad, 0xe9, 0x55, 0xf4, 0x0c, 0x00,
-				0xa5, 0xfa, 0xb5, 0x90, 0xde, 0x16, 0x8b, 0x2d, 0x02, 0x56, 0xc0, 0x95, 0xef, 0x68, 0x8e, 0x15,
-				0x9a, 0x49, 0x53, 0x96, 0x2b, 0x17
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_RSASHA512 ),
-			.pubKey =
-			{
-				0x03, 0x01, 0x00, 0x01, 0xdc, 0xac, 0xa7, 0x8f, 0xd9, 0xca, 0xf4, 0x85, 0x3d, 0x3a, 0xa7, 0x54,
-				0x5e, 0xda, 0x67, 0x30, 0x3b, 0x1d, 0xf1, 0x90, 0x1c, 0x84, 0xa3, 0xb6, 0xab, 0xb8, 0x06, 0xc6,
-				0xca, 0x99, 0x5e, 0xa6, 0xb0, 0x8b, 0x75, 0x48, 0x61, 0xce, 0x94, 0xf4, 0x50, 0x88, 0xcb, 0x4d,
-				0xe7, 0xe9, 0x70, 0x91, 0x47, 0x0a, 0x77, 0xdc, 0x38, 0xc2, 0x73, 0x54, 0xd0, 0x33, 0x27, 0x92,
-				0xdd, 0x35, 0xab, 0xe6, 0x32, 0xee, 0x7d, 0x5b, 0x4e, 0x9d, 0x6e, 0xfb, 0x00, 0x7e, 0xe6, 0xd0,
-				0x68, 0x9b, 0xc0, 0x6d, 0x02, 0x4c, 0xc4, 0x20, 0x6f, 0x61, 0x98, 0x24, 0xdb, 0x21, 0x89, 0xb0,
-				0x13, 0xf2, 0x58, 0x98, 0x82, 0x5c, 0x79, 0xcb, 0x0f, 0x56, 0x83, 0xda, 0x50, 0x21, 0x40, 0xd5,
-				0x28, 0xcc, 0x92, 0xbc, 0x09, 0x04, 0xba, 0x9d, 0xa2, 0xcb, 0xed, 0x56, 0x91, 0xfd, 0x1b, 0x4b,
-				0x73, 0x5f, 0x5f, 0xb7, 0x46, 0x25, 0xc3, 0x0c, 0xcb, 0x66, 0xe6, 0x59, 0x0e, 0x0e, 0x39, 0x12,
-				0x23, 0x22, 0x97, 0x3e, 0x34, 0x69, 0x4d, 0x8b, 0xbd, 0x14, 0x9d, 0x08, 0xef, 0xd9, 0x0a, 0x5d,
-				0xf1, 0x96, 0x8b, 0xa0, 0xe6, 0x1c, 0x83, 0x38, 0x21, 0xc9, 0xe6, 0xd0, 0x35, 0xd4, 0x73, 0x92,
-				0xc5, 0x27, 0x98, 0xb3, 0x70, 0x3d, 0x87, 0x93, 0x41, 0xb3, 0xc5, 0xf3, 0x27, 0xd4, 0x29, 0x1e,
-				0xc8, 0xf6, 0xe1, 0xc1, 0xc9, 0x48, 0xb3, 0x7e, 0xa2, 0x53, 0xe2, 0xfe, 0xd8, 0x48, 0xa6, 0x04,
-				0x40, 0x71, 0x99, 0x08, 0x96, 0x43, 0x25, 0x01, 0xc4, 0xdd, 0x6f, 0xe2, 0x86, 0xac, 0x73, 0xc2,
-				0xe3, 0x05, 0x67, 0x21, 0xf7, 0x63, 0x4f, 0x46, 0xf9, 0xd2, 0xf6, 0x80, 0x43, 0x13, 0xe4, 0x05,
-				0x5c, 0x99, 0x2a, 0xf5, 0xde, 0x1d, 0x87, 0x4f, 0xf3, 0x87, 0x00, 0x36, 0x46, 0x21, 0xe8, 0x12,
-				0x6a, 0xda, 0x76, 0x29
-			},
-			.secKey =
-			{
-				0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xdc, 0xac, 0xa7, 0x8f,
-				0xd9, 0xca, 0xf4, 0x85, 0x3d, 0x3a, 0xa7, 0x54, 0x5e, 0xda, 0x67, 0x30, 0x3b, 0x1d, 0xf1, 0x90,
-				0x1c, 0x84, 0xa3, 0xb6, 0xab, 0xb8, 0x06, 0xc6, 0xca, 0x99, 0x5e, 0xa6, 0xb0, 0x8b, 0x75, 0x48,
-				0x61, 0xce, 0x94, 0xf4, 0x50, 0x88, 0xcb, 0x4d, 0xe7, 0xe9, 0x70, 0x91, 0x47, 0x0a, 0x77, 0xdc,
-				0x38, 0xc2, 0x73, 0x54, 0xd0, 0x33, 0x27, 0x92, 0xdd, 0x35, 0xab, 0xe6, 0x32, 0xee, 0x7d, 0x5b,
-				0x4e, 0x9d, 0x6e, 0xfb, 0x00, 0x7e, 0xe6, 0xd0, 0x68, 0x9b, 0xc0, 0x6d, 0x02, 0x4c, 0xc4, 0x20,
-				0x6f, 0x61, 0x98, 0x24, 0xdb, 0x21, 0x89, 0xb0, 0x13, 0xf2, 0x58, 0x98, 0x82, 0x5c, 0x79, 0xcb,
-				0x0f, 0x56, 0x83, 0xda, 0x50, 0x21, 0x40, 0xd5, 0x28, 0xcc, 0x92, 0xbc, 0x09, 0x04, 0xba, 0x9d,
-				0xa2, 0xcb, 0xed, 0x56, 0x91, 0xfd, 0x1b, 0x4b, 0x73, 0x5f, 0x5f, 0xb7, 0x46, 0x25, 0xc3, 0x0c,
-				0xcb, 0x66, 0xe6, 0x59, 0x0e, 0x0e, 0x39, 0x12, 0x23, 0x22, 0x97, 0x3e, 0x34, 0x69, 0x4d, 0x8b,
-				0xbd, 0x14, 0x9d, 0x08, 0xef, 0xd9, 0x0a, 0x5d, 0xf1, 0x96, 0x8b, 0xa0, 0xe6, 0x1c, 0x83, 0x38,
-				0x21, 0xc9, 0xe6, 0xd0, 0x35, 0xd4, 0x73, 0x92, 0xc5, 0x27, 0x98, 0xb3, 0x70, 0x3d, 0x87, 0x93,
-				0x41, 0xb3, 0xc5, 0xf3, 0x27, 0xd4, 0x29, 0x1e, 0xc8, 0xf6, 0xe1, 0xc1, 0xc9, 0x48, 0xb3, 0x7e,
-				0xa2, 0x53, 0xe2, 0xfe, 0xd8, 0x48, 0xa6, 0x04, 0x40, 0x71, 0x99, 0x08, 0x96, 0x43, 0x25, 0x01,
-				0xc4, 0xdd, 0x6f, 0xe2, 0x86, 0xac, 0x73, 0xc2, 0xe3, 0x05, 0x67, 0x21, 0xf7, 0x63, 0x4f, 0x46,
-				0xf9, 0xd2, 0xf6, 0x80, 0x43, 0x13, 0xe4, 0x05, 0x5c, 0x99, 0x2a, 0xf5, 0xde, 0x1d, 0x87, 0x4f,
-				0xf3, 0x87, 0x00, 0x36, 0x46, 0x21, 0xe8, 0x12, 0x6a, 0xda, 0x76, 0x29, 0x02, 0x03, 0x01, 0x00,
-				0x01, 0x02, 0x82, 0x01, 0x00, 0x06, 0x43, 0xda, 0x19, 0x7f, 0xca, 0xce, 0xec, 0xa1, 0xf7, 0x82,
-				0x74, 0xe7, 0x20, 0xfe, 0xfd, 0x3b, 0xee, 0x6e, 0x93, 0x63, 0x75, 0xe2, 0x12, 0x7f, 0x77, 0x50,
-				0xec, 0xef, 0xa7, 0x51, 0x4c, 0x3c, 0xf6, 0xa6, 0xa0, 0xa4, 0x93, 0x39, 0x80, 0x22, 0xb1, 0xb1,
-				0x88, 0xef, 0x90, 0xbd, 0x77, 0x08, 0x6b, 0xec, 0x09, 0x7a, 0xec, 0x8d, 0x5a, 0xee, 0xf2, 0xc6,
-				0xd8, 0xb8, 0xf2, 0x4b, 0x44, 0x34, 0xb5, 0xb7, 0xe6, 0x21, 0xda, 0x1f, 0x22, 0x9d, 0xe9, 0xdc,
-				0x6a, 0x76, 0x0f, 0xd6, 0xf3, 0x99, 0x55, 0x3d, 0xdb, 0xb8, 0x61, 0xce, 0x50, 0x9c, 0x8e, 0x8c,
-				0x12, 0xcd, 0x4c, 0x2b, 0xf6, 0xff, 0x7b, 0x79, 0xe3, 0x39, 0x97, 0x20, 0x94, 0xf0, 0x01, 0xb3,
-				0xae, 0x21, 0x93, 0x86, 0x46, 0x73, 0xa0, 0x98, 0x5e, 0x3d, 0x97, 0x19, 0xd0, 0xc3, 0x82, 0x0a,
-				0xb6, 0x76, 0x8a, 0xf2, 0x84, 0x0b, 0x69, 0x10, 0xf5, 0x7c, 0xa1, 0xb5, 0xf0, 0xcc, 0xca, 0xda,
-				0x66, 0xdd, 0xc1, 0x01, 0x70, 0x2b, 0xc7, 0xb1, 0x28, 0xfc, 0xab, 0xea, 0xf4, 0x8a, 0x3c, 0xc8,
-				0x7d, 0xdf, 0x6d, 0x89, 0x7b, 0x75, 0xad, 0xa0, 0xfc, 0x88, 0x31, 0x43, 0x21, 0xa6, 0x33, 0x13,
-				0x0f, 0x4a, 0xab, 0x71, 0xd5, 0xca, 0x1a, 0xf3, 0xca, 0xe6, 0x45, 0xec, 0xf5, 0xe2, 0xee, 0x56,
-				0xc0, 0x62, 0x66, 0x91, 0x14, 0x95, 0xd7, 0xf1, 0x1d, 0xd0, 0x57, 0x8a, 0xa6, 0xb7, 0xc5, 0x90,
-				0x7d, 0xcb, 0xb5, 0xb2, 0xa0, 0xa8, 0x97, 0xd3, 0x50, 0x20, 0x49, 0x6b, 0xbc, 0x3d, 0x25, 0x02,
-				0x5d, 0x35, 0x61, 0xd2, 0x47, 0xe1, 0x69, 0xf4, 0xe3, 0x50, 0xf5, 0xbe, 0xb2, 0x5c, 0xe7, 0x64,
-				0x62, 0x1f, 0x32, 0xce, 0x0e, 0x26, 0xd0, 0xf9, 0x6e, 0x15, 0x84, 0xc9, 0xba, 0x21, 0x16, 0x02,
-				0x12, 0xf6, 0xef, 0xd4, 0x71, 0x02, 0x81, 0x81, 0x00, 0xef, 0xb8, 0xdc, 0x5b, 0xe0, 0x55, 0x50,
-				0x3a, 0xeb, 0xcb, 0x96, 0x35, 0x0e, 0x97, 0x45, 0x38, 0x3b, 0xdd, 0xf7, 0x9f, 0xeb, 0x1d, 0x0e,
-				0x08, 0x6a, 0xa4, 0x6f, 0xf1, 0x87, 0xec, 0x4c, 0x69, 0xaf, 0x51, 0xdf, 0x08, 0xe7, 0xde, 0x07,
-				0x5b, 0x2c, 0x9c, 0x6f, 0x21, 0xd6, 0x5d, 0x5f, 0x71, 0x8b, 0xc8, 0x9d, 0x1e, 0xdb, 0xcb, 0x4d,
-				0xf3, 0xbc, 0xfe, 0x58, 0x7c, 0x39, 0x12, 0x42, 0x11, 0xa8, 0x30, 0xc2, 0xf6, 0x87, 0x33, 0xd8,
-				0x99, 0xfb, 0x7b, 0x70, 0x30, 0x51, 0x95, 0xea, 0x42, 0x09, 0xd8, 0x2d, 0xdf, 0x68, 0xa4, 0xd9,
-				0xc0, 0xb7, 0x6d, 0x4d, 0x20, 0xd6, 0xff, 0x95, 0x92, 0x03, 0xcf, 0x3a, 0xda, 0x76, 0xcd, 0x30,
-				0x49, 0xf5, 0xb5, 0x38, 0x08, 0x79, 0xc7, 0x09, 0x95, 0xdf, 0x39, 0x10, 0x02, 0xa4, 0x20, 0xd2,
-				0x4e, 0xc8, 0x19, 0x0a, 0xf9, 0x50, 0xff, 0xee, 0x91, 0x02, 0x81, 0x81, 0x00, 0xeb, 0xa8, 0xaf,
-				0x19, 0x20, 0xf9, 0xe0, 0x7b, 0x8e, 0xfc, 0x48, 0xe2, 0x98, 0xc4, 0x53, 0x03, 0x84, 0x0f, 0x72,
-				0x1a, 0x24, 0x4a, 0xd0, 0xff, 0xa2, 0x47, 0x32, 0x9b, 0xe4, 0x49, 0x23, 0xa5, 0x9b, 0x40, 0xce,
-				0x92, 0xeb, 0x2e, 0x32, 0x89, 0xc8, 0x92, 0xbc, 0xff, 0xec, 0x92, 0xbd, 0x95, 0xc2, 0xb6, 0xde,
-				0x78, 0x72, 0xa8, 0xb7, 0x50, 0x6b, 0x8b, 0x33, 0x2b, 0x44, 0xf7, 0x40, 0x9c, 0x60, 0xee, 0x41,
-				0x80, 0x63, 0xb9, 0x0a, 0x22, 0x7c, 0x9f, 0x7e, 0xaa, 0x67, 0xc3, 0xbf, 0x5f, 0xed, 0xd0, 0xb5,
-				0x22, 0x09, 0x74, 0x8d, 0xfe, 0x0d, 0x9b, 0xd9, 0x89, 0x55, 0x4d, 0x2f, 0xef, 0xed, 0x45, 0x94,
-				0x1e, 0xa8, 0x67, 0x5a, 0xb4, 0xde, 0x97, 0xeb, 0xac, 0x0a, 0xae, 0x0c, 0x1f, 0xa3, 0xa7, 0x76,
-				0x9f, 0x8b, 0x18, 0x7a, 0x1a, 0xe8, 0x40, 0x41, 0x5a, 0x1c, 0x22, 0x8a, 0x19, 0x02, 0x81, 0x80,
-				0x2f, 0x7a, 0x79, 0x8a, 0x68, 0xdf, 0xfc, 0xc7, 0xee, 0xb3, 0x9f, 0xc8, 0x5a, 0x5f, 0x73, 0x82,
-				0x33, 0xb9, 0x3e, 0xb6, 0x19, 0xa6, 0xe3, 0x84, 0x9f, 0x3a, 0x7a, 0x41, 0x68, 0x1e, 0x50, 0xf4,
-				0x0d, 0x99, 0x35, 0x87, 0x5a, 0x05, 0x0b, 0x87, 0xef, 0x49, 0xfc, 0x68, 0xc3, 0x40, 0x33, 0x0b,
-				0x16, 0x18, 0x61, 0xa6, 0x1e, 0xfa, 0x21, 0x32, 0x49, 0x18, 0x47, 0x06, 0x33, 0x77, 0x7e, 0x46,
-				0x68, 0xfd, 0x5f, 0x5f, 0xdc, 0x5f, 0x54, 0x63, 0x0a, 0xff, 0xe3, 0xb4, 0x6e, 0x34, 0x36, 0xf5,
-				0x65, 0x65, 0xbf, 0x90, 0x23, 0xf5, 0xa2, 0x7b, 0x1c, 0xd9, 0x35, 0x11, 0x70, 0x03, 0xa6, 0xe8,
-				0x08, 0x81, 0x1e, 0xb2, 0xee, 0x1c, 0xad, 0x97, 0xb8, 0x66, 0x6f, 0xf6, 0x9d, 0xc7, 0xe2, 0x0a,
-				0x20, 0xef, 0xf8, 0x4f, 0xcd, 0x9a, 0x02, 0x8d, 0x3f, 0xec, 0x55, 0xd4, 0x13, 0x4a, 0xdd, 0x41,
-				0x02, 0x81, 0x80, 0x4e, 0xce, 0x4e, 0x1f, 0xbd, 0x23, 0x52, 0xaa, 0x7f, 0x1a, 0x66, 0xd5, 0x3f,
-				0xf9, 0x07, 0x39, 0xb9, 0xc3, 0xe0, 0x88, 0x55, 0x72, 0x9f, 0x89, 0x9d, 0x1e, 0xea, 0x11, 0xaf,
-				0xb9, 0xb5, 0xad, 0xff, 0xc9, 0x20, 0x4b, 0x89, 0x52, 0x1d, 0x9c, 0x6d, 0xf2, 0x84, 0x39, 0xa1,
-				0x47, 0x41, 0x16, 0xff, 0xd2, 0x5f, 0x7b, 0x2f, 0xfc, 0xb3, 0xb0, 0xb5, 0x06, 0x0b, 0xca, 0x80,
-				0x79, 0x9e, 0xa5, 0xac, 0xd4, 0x80, 0x1b, 0x0b, 0x3e, 0x29, 0xe1, 0x76, 0x83, 0x6f, 0xbc, 0x54,
-				0x8e, 0xe5, 0x44, 0x93, 0x26, 0xa4, 0x2c, 0x09, 0xb5, 0x6c, 0x76, 0x74, 0xde, 0x95, 0x54, 0x93,
-				0xae, 0x08, 0x45, 0xd7, 0xb6, 0xd8, 0xdd, 0x97, 0xbb, 0x58, 0x5d, 0xfb, 0xc2, 0x1a, 0x11, 0xa2,
-				0x50, 0xa9, 0xc5, 0x3a, 0xd9, 0x19, 0x96, 0x28, 0xd1, 0xba, 0xa3, 0x9c, 0xdf, 0x3f, 0xfb, 0x7e,
-				0x45, 0x1e, 0xa1, 0x02, 0x81, 0x80, 0x60, 0xfd, 0x65, 0x54, 0x17, 0x04, 0x28, 0x92, 0x73, 0xc8,
-				0xff, 0x3b, 0xb7, 0x8f, 0x91, 0xed, 0x29, 0x0a, 0xcd, 0xdb, 0x7c, 0xbb, 0x4e, 0xe6, 0xf1, 0xe6,
-				0xd3, 0xe3, 0xb4, 0x64, 0x09, 0x4d, 0x25, 0x1e, 0x85, 0x74, 0x8c, 0x95, 0xe8, 0x87, 0x39, 0xa0,
-				0x02, 0x05, 0xf7, 0x31, 0x37, 0xf1, 0x88, 0x58, 0x7e, 0x9d, 0xf6, 0x19, 0x09, 0x8b, 0x5f, 0xee,
-				0xae, 0x48, 0x9b, 0x7b, 0xa6, 0x3e, 0x6d, 0x32, 0x07, 0x20, 0xda, 0x4e, 0x95, 0x7f, 0xb3, 0x28,
-				0xaf, 0x7d, 0x46, 0xc7, 0x25, 0x41, 0x38, 0x9c, 0x8d, 0xe6, 0x1f, 0xe5, 0x98, 0xdd, 0x83, 0x08,
-				0xe0, 0xee, 0x31, 0xea, 0xdd, 0x54, 0x42, 0xa3, 0x5c, 0x35, 0x96, 0x6a, 0x96, 0xc6, 0xb5, 0xae,
-				0xac, 0x79, 0x2b, 0x55, 0xf1, 0x09, 0x3f, 0xb8, 0x97, 0x78, 0x02, 0xd6, 0x8a, 0xc9, 0xd5, 0xd7,
-				0xbe, 0x3f, 0x68, 0xb8, 0x3d, 0xce
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( RSASHA512 );
-
-//===========================================================================================================================
-// MARK: - ECDSA Curve P-256 with SHA-256 DNS Keys
-
-typedef struct
-{
-	DNSKeyECDSAP256SHA256Info		ksk;	// Key-Signing Key
-	DNSKeyECDSAP256SHA256Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyECDSAP256SHA256Set;
-
-static const DNSKeyECDSAP256SHA256Set		kDNSKeyECDSAP256SHA256Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0x29, 0x03, 0x21, 0x45, 0x5c, 0x5e, 0x50, 0x4b, 0x4a, 0x02, 0x08, 0x48, 0xfb, 0xc5, 0x75, 0xf8, 0xff,
-				0x74, 0x03, 0x99, 0xe9, 0x47, 0xcb, 0xa7, 0xf2, 0xd0, 0xe9, 0x96, 0x24, 0x60, 0x16, 0x83, 0x9a, 0x50,
-				0xa2, 0xea, 0x24, 0x43, 0x89, 0x5a, 0x2f, 0x6d, 0x42, 0xca, 0xb1, 0x3a, 0x78, 0xbf, 0xf6, 0xf5, 0xe6,
-				0xb2, 0x42, 0x4b, 0x5b, 0x15, 0x8c, 0x1e, 0x8d, 0xe2, 0x5a, 0x6d, 0xbb, 0x80
-			},
-			.secKey =
-			{
-				0x29, 0x03, 0x21, 0x45, 0x5c, 0x5e, 0x50, 0x4b, 0x4a, 0x02, 0x08, 0x48, 0xfb, 0xc5, 0x75, 0xf8, 0xff,
-				0x74, 0x03, 0x99, 0xe9, 0x47, 0xcb, 0xa7, 0xf2, 0xd0, 0xe9, 0x96, 0x24, 0x60, 0x16, 0x83, 0x9a, 0x50,
-				0xa2, 0xea, 0x24, 0x43, 0x89, 0x5a, 0x2f, 0x6d, 0x42, 0xca, 0xb1, 0x3a, 0x78, 0xbf, 0xf6, 0xf5, 0xe6,
-				0xb2, 0x42, 0x4b, 0x5b, 0x15, 0x8c, 0x1e, 0x8d, 0xe2, 0x5a, 0x6d, 0xbb, 0x80, 0xb0, 0xb7, 0x11, 0xa1,
-				0x52, 0xca, 0xaf, 0x49, 0xe9, 0xb9, 0x89, 0x0f, 0x44, 0x4a, 0xcd, 0xb0, 0x6c, 0xcb, 0xe2, 0x17, 0x45,
-				0xe6, 0x73, 0x22, 0x6b, 0xce, 0x88, 0xf8, 0x55, 0xcc, 0x5a, 0xbf
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0x71, 0x00, 0x24, 0xba, 0xbe, 0x13, 0xb1, 0xdb, 0xa6, 0xb9, 0x77, 0xbd, 0xeb, 0x38, 0x03, 0x33, 0x38,
-				0xab, 0x4b, 0x6b, 0xc2, 0xb2, 0xe4, 0x51, 0xad, 0xa1, 0x1d, 0x1f, 0x83, 0x42, 0xcb, 0x33, 0x0b, 0x8a,
-				0x3d, 0x54, 0x17, 0x43, 0x56, 0x87, 0xcc, 0xc1, 0xf3, 0x2c, 0x04, 0x7f, 0xaa, 0x4c, 0x18, 0x78, 0x86,
-				0x10, 0xcf, 0x53, 0x24, 0xee, 0x5d, 0x74, 0x31, 0xe4, 0x4d, 0xc4, 0x84, 0x6a
-			},
-			.secKey =
-			{
-				0x71, 0x00, 0x24, 0xba, 0xbe, 0x13, 0xb1, 0xdb, 0xa6, 0xb9, 0x77, 0xbd, 0xeb, 0x38, 0x03, 0x33, 0x38,
-				0xab, 0x4b, 0x6b, 0xc2, 0xb2, 0xe4, 0x51, 0xad, 0xa1, 0x1d, 0x1f, 0x83, 0x42, 0xcb, 0x33, 0x0b, 0x8a,
-				0x3d, 0x54, 0x17, 0x43, 0x56, 0x87, 0xcc, 0xc1, 0xf3, 0x2c, 0x04, 0x7f, 0xaa, 0x4c, 0x18, 0x78, 0x86,
-				0x10, 0xcf, 0x53, 0x24, 0xee, 0x5d, 0x74, 0x31, 0xe4, 0x4d, 0xc4, 0x84, 0x6a, 0x46, 0x1e, 0x0b, 0x8e,
-				0xcc, 0x18, 0x3a, 0xad, 0xfb, 0x7e, 0x07, 0xaf, 0xd6, 0x20, 0x99, 0xbb, 0xaa, 0x6b, 0xb0, 0xb8, 0x89,
-				0x3c, 0x6e, 0x3b, 0x9c, 0x73, 0x25, 0x12, 0x06, 0x50, 0x37, 0x3a
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0xaf, 0x44, 0xb4, 0x8a, 0xc1, 0x8f, 0x0b, 0xd1, 0xfb, 0x90, 0x45, 0x0d, 0x08, 0x32, 0x79, 0xa1, 0xe5,
-				0x9b, 0x4a, 0xbd, 0x64, 0xb3, 0xce, 0xbb, 0x6d, 0x5f, 0x74, 0xe7, 0x74, 0x85, 0xf2, 0xe8, 0xda, 0x37,
-				0xbe, 0x58, 0x60, 0x94, 0xed, 0x22, 0xa4, 0xd7, 0x6b, 0xee, 0x7f, 0xd8, 0x1b, 0xcf, 0xc8, 0x26, 0x8f,
-				0x85, 0x31, 0xcc, 0xdd, 0x90, 0x3a, 0x71, 0xe1, 0xd0, 0x1e, 0x65, 0x69, 0x62
-
-			},
-			.secKey =
-			{
-				0xaf, 0x44, 0xb4, 0x8a, 0xc1, 0x8f, 0x0b, 0xd1, 0xfb, 0x90, 0x45, 0x0d, 0x08, 0x32, 0x79, 0xa1, 0xe5,
-				0x9b, 0x4a, 0xbd, 0x64, 0xb3, 0xce, 0xbb, 0x6d, 0x5f, 0x74, 0xe7, 0x74, 0x85, 0xf2, 0xe8, 0xda, 0x37,
-				0xbe, 0x58, 0x60, 0x94, 0xed, 0x22, 0xa4, 0xd7, 0x6b, 0xee, 0x7f, 0xd8, 0x1b, 0xcf, 0xc8, 0x26, 0x8f,
-				0x85, 0x31, 0xcc, 0xdd, 0x90, 0x3a, 0x71, 0xe1, 0xd0, 0x1e, 0x65, 0x69, 0x62, 0x5a, 0x72, 0xe9, 0x12,
-				0xb6, 0x87, 0xf8, 0x22, 0x3c, 0xde, 0x13, 0xa0, 0x2f, 0x81, 0x44, 0x9f, 0x46, 0xaf, 0x41, 0x56, 0x3f,
-				0x69, 0xfb, 0xfd, 0x0b, 0xae, 0x52, 0xa1, 0xd8, 0xae, 0x23, 0xd7
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0xd7, 0x3a, 0x08, 0xe9, 0x14, 0x1b, 0xf7, 0xa7, 0xe5, 0x48, 0xb2, 0xf7, 0x5f, 0x7d, 0xe0, 0xb3, 0x42,
-				0x90, 0xe6, 0x96, 0x41, 0x58, 0x98, 0xfb, 0x89, 0xc7, 0xbb, 0x43, 0xcd, 0x16, 0xc2, 0x41, 0x40, 0xd7,
-				0x3c, 0x28, 0x23, 0x94, 0x45, 0x96, 0xad, 0xa0, 0x9b, 0x67, 0x1d, 0x53, 0xa3, 0x97, 0x84, 0x6a, 0x48,
-				0xcc, 0x58, 0xe9, 0x34, 0x5b, 0x2c, 0xb6, 0xcf, 0x4b, 0xe5, 0xbc, 0xb6, 0x34
-			},
-			.secKey =
-			{
-				0xd7, 0x3a, 0x08, 0xe9, 0x14, 0x1b, 0xf7, 0xa7, 0xe5, 0x48, 0xb2, 0xf7, 0x5f, 0x7d, 0xe0, 0xb3, 0x42,
-				0x90, 0xe6, 0x96, 0x41, 0x58, 0x98, 0xfb, 0x89, 0xc7, 0xbb, 0x43, 0xcd, 0x16, 0xc2, 0x41, 0x40, 0xd7,
-				0x3c, 0x28, 0x23, 0x94, 0x45, 0x96, 0xad, 0xa0, 0x9b, 0x67, 0x1d, 0x53, 0xa3, 0x97, 0x84, 0x6a, 0x48,
-				0xcc, 0x58, 0xe9, 0x34, 0x5b, 0x2c, 0xb6, 0xcf, 0x4b, 0xe5, 0xbc, 0xb6, 0x34, 0xaf, 0x91, 0xcf, 0x9c,
-				0x8a, 0xa5, 0xad, 0x12, 0xa1, 0xbb, 0x04, 0xeb, 0xb8, 0x2e, 0x8a, 0x2c, 0x96, 0xdf, 0x5c, 0xbc, 0xce,
-				0x88, 0xab, 0x52, 0x60, 0xaf, 0x27, 0x4e, 0xd9, 0x9d, 0x39, 0x42
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0x6a, 0xb9, 0x99, 0x0e, 0x9f, 0x7f, 0xad, 0x0c, 0x77, 0x94, 0xb2, 0x40, 0xa7, 0x40, 0x15, 0xf5, 0xe4,
-				0x9b, 0x1e, 0x90, 0x58, 0x25, 0xed, 0x26, 0x2f, 0x35, 0x55, 0x3c, 0x0f, 0x09, 0xd2, 0x58, 0x6f, 0x20,
-				0xa7, 0x77, 0x36, 0x4c, 0xdf, 0x45, 0x25, 0xa4, 0xa8, 0xc4, 0x8a, 0xa0, 0x1c, 0xe1, 0xea, 0x47, 0xb7,
-				0xb6, 0xa2, 0xf4, 0x49, 0x9a, 0xbc, 0x07, 0xe5, 0x32, 0x15, 0xaf, 0x5d, 0x6f
-			},
-			.secKey =
-			{
-				0x6a, 0xb9, 0x99, 0x0e, 0x9f, 0x7f, 0xad, 0x0c, 0x77, 0x94, 0xb2, 0x40, 0xa7, 0x40, 0x15, 0xf5, 0xe4,
-				0x9b, 0x1e, 0x90, 0x58, 0x25, 0xed, 0x26, 0x2f, 0x35, 0x55, 0x3c, 0x0f, 0x09, 0xd2, 0x58, 0x6f, 0x20,
-				0xa7, 0x77, 0x36, 0x4c, 0xdf, 0x45, 0x25, 0xa4, 0xa8, 0xc4, 0x8a, 0xa0, 0x1c, 0xe1, 0xea, 0x47, 0xb7,
-				0xb6, 0xa2, 0xf4, 0x49, 0x9a, 0xbc, 0x07, 0xe5, 0x32, 0x15, 0xaf, 0x5d, 0x6f, 0xa9, 0xa7, 0xf2, 0xe4,
-				0x8a, 0x0b, 0xf9, 0x87, 0x60, 0x96, 0x91, 0x72, 0xdd, 0xeb, 0xb7, 0x65, 0x1a, 0x9e, 0xa4, 0xcc, 0xb4,
-				0x9c, 0xee, 0xc9, 0xe2, 0x73, 0x1c, 0x22, 0x4c, 0x8f, 0xb4, 0xec
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0x89, 0xfc, 0xb4, 0xa2, 0x5f, 0x27, 0xbd, 0x2c, 0xa8, 0xf7, 0xb3, 0xfb, 0xa1, 0x24, 0x25, 0x61, 0x28,
-				0x55, 0xd2, 0x8a, 0xb5, 0x74, 0x24, 0xf4, 0x1b, 0x27, 0x47, 0x23, 0x10, 0x5d, 0x76, 0xd6, 0x40, 0x01,
-				0xf2, 0x91, 0x74, 0xa5, 0x99, 0x5b, 0x9e, 0xc5, 0xd8, 0x82, 0x63, 0x1f, 0xcd, 0x55, 0xa8, 0xcf, 0x01,
-				0x0a, 0xf8, 0x97, 0x0b, 0x41, 0x23, 0xee, 0x6b, 0xc4, 0x3e, 0x8e, 0x81, 0x22
-			},
-			.secKey =
-			{
-				0x89, 0xfc, 0xb4, 0xa2, 0x5f, 0x27, 0xbd, 0x2c, 0xa8, 0xf7, 0xb3, 0xfb, 0xa1, 0x24, 0x25, 0x61, 0x28,
-				0x55, 0xd2, 0x8a, 0xb5, 0x74, 0x24, 0xf4, 0x1b, 0x27, 0x47, 0x23, 0x10, 0x5d, 0x76, 0xd6, 0x40, 0x01,
-				0xf2, 0x91, 0x74, 0xa5, 0x99, 0x5b, 0x9e, 0xc5, 0xd8, 0x82, 0x63, 0x1f, 0xcd, 0x55, 0xa8, 0xcf, 0x01,
-				0x0a, 0xf8, 0x97, 0x0b, 0x41, 0x23, 0xee, 0x6b, 0xc4, 0x3e, 0x8e, 0x81, 0x22, 0x37, 0x9a, 0x95, 0xfe,
-				0xf1, 0x98, 0x28, 0x2b, 0x01, 0xa9, 0x8a, 0x57, 0x19, 0xea, 0x61, 0xf1, 0x57, 0x21, 0x15, 0x72, 0x3a,
-				0x67, 0x41, 0x79, 0x8a, 0x1f, 0x12, 0x3b, 0x48, 0xe6, 0xf1, 0x71
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0xd4, 0x0d, 0x1c, 0xe7, 0xd7, 0x38, 0xda, 0xda, 0x50, 0x3f, 0xd3, 0x4e, 0x41, 0x6e, 0x72, 0xde, 0x8c,
-				0x97, 0x57, 0xdc, 0x7c, 0xed, 0x44, 0x09, 0x9c, 0xa6, 0xef, 0x05, 0x74, 0x6a, 0xb6, 0xb4, 0x16, 0xf4,
-				0x39, 0xc8, 0x6d, 0x3a, 0xe5, 0x26, 0x1c, 0x44, 0x96, 0x96, 0x3f, 0x22, 0x0c, 0xb7, 0xce, 0x57, 0x6f,
-				0x60, 0x8f, 0x90, 0x64, 0x29, 0x97, 0x60, 0x11, 0xfd, 0xf4, 0x8d, 0x38, 0x03
-			},
-			.secKey =
-			{
-				0xd4, 0x0d, 0x1c, 0xe7, 0xd7, 0x38, 0xda, 0xda, 0x50, 0x3f, 0xd3, 0x4e, 0x41, 0x6e, 0x72, 0xde, 0x8c,
-				0x97, 0x57, 0xdc, 0x7c, 0xed, 0x44, 0x09, 0x9c, 0xa6, 0xef, 0x05, 0x74, 0x6a, 0xb6, 0xb4, 0x16, 0xf4,
-				0x39, 0xc8, 0x6d, 0x3a, 0xe5, 0x26, 0x1c, 0x44, 0x96, 0x96, 0x3f, 0x22, 0x0c, 0xb7, 0xce, 0x57, 0x6f,
-				0x60, 0x8f, 0x90, 0x64, 0x29, 0x97, 0x60, 0x11, 0xfd, 0xf4, 0x8d, 0x38, 0x03, 0x0a, 0xc0, 0xef, 0x99,
-				0x50, 0x3c, 0x4b, 0xbb, 0x29, 0xf9, 0xed, 0xac, 0x06, 0xfe, 0x5f, 0x04, 0x92, 0xa8, 0xe2, 0xba, 0x3d,
-				0x82, 0x8b, 0xa6, 0x03, 0xe4, 0xcb, 0xaf, 0xff, 0xf2, 0x3e, 0xbd
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP256SHA256 ),
-			.pubKey =
-			{
-				0x00, 0x84, 0x50, 0x07, 0x60, 0x06, 0x3b, 0xae, 0x68, 0xe1, 0x57, 0x5e, 0x7b, 0xd2, 0xdd, 0x1f, 0x0f,
-				0x10, 0xaa, 0x27, 0xd4, 0x93, 0x94, 0x5e, 0xe8, 0xd8, 0x2d, 0x96, 0xe0, 0x61, 0xd2, 0xfb, 0x97, 0xa9,
-				0x88, 0x0a, 0x6d, 0xca, 0x13, 0x78, 0x95, 0x61, 0x60, 0x09, 0xcd, 0xf1, 0x69, 0xa4, 0xf8, 0xa7, 0xfa,
-				0x84, 0xef, 0xab, 0xe1, 0xc3, 0x3d, 0x48, 0xbb, 0x57, 0x13, 0x3d, 0x47, 0x46
-			},
-			.secKey =
-			{
-				0x00, 0x84, 0x50, 0x07, 0x60, 0x06, 0x3b, 0xae, 0x68, 0xe1, 0x57, 0x5e, 0x7b, 0xd2, 0xdd, 0x1f, 0x0f,
-				0x10, 0xaa, 0x27, 0xd4, 0x93, 0x94, 0x5e, 0xe8, 0xd8, 0x2d, 0x96, 0xe0, 0x61, 0xd2, 0xfb, 0x97, 0xa9,
-				0x88, 0x0a, 0x6d, 0xca, 0x13, 0x78, 0x95, 0x61, 0x60, 0x09, 0xcd, 0xf1, 0x69, 0xa4, 0xf8, 0xa7, 0xfa,
-				0x84, 0xef, 0xab, 0xe1, 0xc3, 0x3d, 0x48, 0xbb, 0x57, 0x13, 0x3d, 0x47, 0x46, 0x1f, 0xc8, 0x60, 0x20,
-				0xcd, 0x95, 0x3a, 0x4a, 0xae, 0xb5, 0xa2, 0xfb, 0x9a, 0x24, 0x66, 0x9d, 0xdc, 0xba, 0xdf, 0x2a, 0x73,
-				0x53, 0xed, 0xdd, 0xe0, 0x30, 0x7c, 0x5f, 0x1f, 0x27, 0x58, 0xf8
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( ECDSAP256SHA256 );
-
-//===========================================================================================================================
-// MARK: - ECDSA Curve P-384 with SHA-384 DNS Keys
-
-typedef struct
-{
-	DNSKeyECDSAP384SHA384Info		ksk;	// Key-Signing Key
-	DNSKeyECDSAP384SHA384Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyECDSAP384SHA384Set;
-
-static const DNSKeyECDSAP384SHA384Set		kDNSKeyECDSAP384SHA384Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0xbe, 0x4a, 0x40, 0xe7, 0xc8, 0x60, 0x51, 0x7f, 0x7c, 0x8a, 0x8f, 0x37, 0x5d, 0xe3, 0xfc, 0x8e, 0x12,
-				0xe0, 0xa1, 0x42, 0x7f, 0x2f, 0x2d, 0xda, 0x27, 0x60, 0x0f, 0xf0, 0xa1, 0x94, 0x47, 0x1c, 0xa4, 0x4e,
-				0x37, 0xef, 0x59, 0x6b, 0x7c, 0x3d, 0x47, 0xaa, 0xef, 0x10, 0x63, 0x6a, 0x4f, 0x17, 0xb5, 0xa0, 0x2b,
-				0xe3, 0xac, 0x90, 0xd6, 0x5e, 0xca, 0xd2, 0x2f, 0x21, 0xe3, 0x5d, 0xae, 0x63
-			},
-			.secKey =
-			{
-				0xbe, 0x4a, 0x40, 0xe7, 0xc8, 0x60, 0x51, 0x7f, 0x7c, 0x8a, 0x8f, 0x37, 0x5d, 0xe3, 0xfc, 0x8e, 0x12,
-				0xe0, 0xa1, 0x42, 0x7f, 0x2f, 0x2d, 0xda, 0x27, 0x60, 0x0f, 0xf0, 0xa1, 0x94, 0x47, 0x1c, 0xa4, 0x4e,
-				0x37, 0xef, 0x59, 0x6b, 0x7c, 0x3d, 0x47, 0xaa, 0xef, 0x10, 0x63, 0x6a, 0x4f, 0x17, 0xb5, 0xa0, 0x2b,
-				0xe3, 0xac, 0x90, 0xd6, 0x5e, 0xca, 0xd2, 0x2f, 0x21, 0xe3, 0x5d, 0xae, 0x63, 0xe7, 0x91, 0x9c, 0x19,
-				0x57, 0x44, 0xe4, 0x97, 0x3d, 0xd2, 0xc4, 0xc1, 0x84, 0x7b, 0x2c, 0x4e, 0xcb, 0xe5, 0x36, 0x56, 0xf5,
-				0x6e, 0x7c, 0x54, 0xd7, 0x49, 0xd7, 0x69, 0x7c, 0x87, 0xd0, 0xce
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0x8f, 0x51, 0x89, 0xe2, 0x28, 0x01, 0xde, 0x07, 0xf6, 0x2f, 0xb3, 0xbd, 0x42, 0xc5, 0xe0, 0x66, 0x8d,
-				0x08, 0x09, 0xdb, 0x06, 0x77, 0x45, 0xdd, 0xa8, 0x1d, 0xe2, 0x68, 0xb6, 0x90, 0xa7, 0x8a, 0x9d, 0x06,
-				0x11, 0x8f, 0x98, 0x05, 0xf1, 0xb0, 0xfa, 0x55, 0xa6, 0x4b, 0xd7, 0x04, 0x63, 0x40, 0xcc, 0x72, 0xe4,
-				0x5b, 0xb9, 0x5b, 0x2c, 0x68, 0xee, 0x3c, 0x7e, 0x3c, 0xac, 0x67, 0xfc, 0x7e
-			},
-			.secKey =
-			{
-				0x8f, 0x51, 0x89, 0xe2, 0x28, 0x01, 0xde, 0x07, 0xf6, 0x2f, 0xb3, 0xbd, 0x42, 0xc5, 0xe0, 0x66, 0x8d,
-				0x08, 0x09, 0xdb, 0x06, 0x77, 0x45, 0xdd, 0xa8, 0x1d, 0xe2, 0x68, 0xb6, 0x90, 0xa7, 0x8a, 0x9d, 0x06,
-				0x11, 0x8f, 0x98, 0x05, 0xf1, 0xb0, 0xfa, 0x55, 0xa6, 0x4b, 0xd7, 0x04, 0x63, 0x40, 0xcc, 0x72, 0xe4,
-				0x5b, 0xb9, 0x5b, 0x2c, 0x68, 0xee, 0x3c, 0x7e, 0x3c, 0xac, 0x67, 0xfc, 0x7e, 0xaf, 0xa8, 0xfd, 0x7f,
-				0x39, 0x1a, 0x72, 0xf6, 0x19, 0x3b, 0xc7, 0x62, 0xcc, 0xf7, 0x16, 0xfd, 0x16, 0x55, 0xc3, 0x57, 0x77,
-				0xca, 0x88, 0x18, 0x48, 0x79, 0x69, 0xa6, 0xc0, 0x2d, 0xa6, 0x7d
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0xf7, 0x8c, 0x7e, 0xca, 0xa6, 0xf7, 0xd7, 0x8c, 0x42, 0x22, 0x53, 0xcf, 0xc2, 0x7e, 0x75, 0xdf, 0xf2,
-				0x64, 0xbd, 0x58, 0x75, 0x82, 0x4f, 0x80, 0xe8, 0xcd, 0x3b, 0xed, 0xc8, 0x09, 0x94, 0x2a, 0x49, 0x5e,
-				0x85, 0x67, 0xeb, 0xaf, 0x2e, 0x04, 0x7f, 0x6b, 0x4c, 0x12, 0x16, 0x52, 0xd3, 0x8f, 0x4c, 0x42, 0x85,
-				0xdd, 0x69, 0x3d, 0x45, 0x74, 0xc3, 0x35, 0xba, 0x3d, 0x6d, 0xb3, 0xea, 0xe9
-			},
-			.secKey =
-			{
-				0xf7, 0x8c, 0x7e, 0xca, 0xa6, 0xf7, 0xd7, 0x8c, 0x42, 0x22, 0x53, 0xcf, 0xc2, 0x7e, 0x75, 0xdf, 0xf2,
-				0x64, 0xbd, 0x58, 0x75, 0x82, 0x4f, 0x80, 0xe8, 0xcd, 0x3b, 0xed, 0xc8, 0x09, 0x94, 0x2a, 0x49, 0x5e,
-				0x85, 0x67, 0xeb, 0xaf, 0x2e, 0x04, 0x7f, 0x6b, 0x4c, 0x12, 0x16, 0x52, 0xd3, 0x8f, 0x4c, 0x42, 0x85,
-				0xdd, 0x69, 0x3d, 0x45, 0x74, 0xc3, 0x35, 0xba, 0x3d, 0x6d, 0xb3, 0xea, 0xe9, 0x44, 0x2a, 0x21, 0xb1,
-				0xad, 0x42, 0x72, 0x2c, 0x0f, 0x92, 0xdb, 0x0b, 0x2c, 0x0e, 0x47, 0x11, 0x8b, 0x0b, 0xaa, 0x58, 0x73,
-				0x06, 0x79, 0xaf, 0xf4, 0x8f, 0x71, 0x0d, 0x7d, 0xbc, 0x95, 0xdf
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0xf1, 0xa1, 0xe6, 0xaf, 0xa8, 0x29, 0x4f, 0x65, 0xc8, 0xb0, 0xb4, 0x32, 0x59, 0x79, 0x40, 0x57, 0xc6,
-				0x7a, 0x10, 0xc0, 0x09, 0x44, 0xfc, 0xe4, 0x32, 0xaf, 0xa2, 0x70, 0x39, 0x39, 0x59, 0x83, 0x12, 0x14,
-				0x6a, 0x0b, 0x83, 0x8b, 0xa9, 0x23, 0x29, 0xa4, 0x5e, 0x98, 0x4f, 0x84, 0xbd, 0xfa, 0x69, 0xd2, 0xb8,
-				0xa1, 0x44, 0x56, 0xfe, 0xdc, 0x81, 0xa1, 0xe7, 0xeb, 0x15, 0x9b, 0xda, 0x99
-			},
-			.secKey =
-			{
-				0xf1, 0xa1, 0xe6, 0xaf, 0xa8, 0x29, 0x4f, 0x65, 0xc8, 0xb0, 0xb4, 0x32, 0x59, 0x79, 0x40, 0x57, 0xc6,
-				0x7a, 0x10, 0xc0, 0x09, 0x44, 0xfc, 0xe4, 0x32, 0xaf, 0xa2, 0x70, 0x39, 0x39, 0x59, 0x83, 0x12, 0x14,
-				0x6a, 0x0b, 0x83, 0x8b, 0xa9, 0x23, 0x29, 0xa4, 0x5e, 0x98, 0x4f, 0x84, 0xbd, 0xfa, 0x69, 0xd2, 0xb8,
-				0xa1, 0x44, 0x56, 0xfe, 0xdc, 0x81, 0xa1, 0xe7, 0xeb, 0x15, 0x9b, 0xda, 0x99, 0x12, 0xf6, 0x33, 0x34,
-				0x17, 0x32, 0xf2, 0x6d, 0x12, 0x25, 0x73, 0x91, 0x57, 0xdf, 0x6a, 0xf6, 0xba, 0x64, 0x73, 0x09, 0xda,
-				0xea, 0x02, 0x3f, 0x5e, 0x96, 0xa0, 0x0d, 0x2e, 0x72, 0xc8, 0xd8
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0x0e, 0x67, 0xd0, 0x3e, 0x50, 0x85, 0x75, 0x90, 0x68, 0x55, 0x02, 0x4d, 0xd8, 0x23, 0x74, 0x55, 0xf6,
-				0xb6, 0x95, 0xa3, 0x9e, 0x02, 0x2e, 0xbd, 0x61, 0xd8, 0x7e, 0xa2, 0xed, 0xe9, 0xcc, 0x40, 0xc1, 0xf6,
-				0xa4, 0xb5, 0x9e, 0x14, 0xcf, 0x92, 0xf2, 0xe0, 0x8a, 0xe6, 0x21, 0xa0, 0x48, 0xb7, 0xff, 0x04, 0xeb,
-				0x53, 0x6d, 0xb6, 0x52, 0xd0, 0x0e, 0x7d, 0x52, 0x5a, 0x1a, 0x72, 0xa8, 0xab
-			},
-			.secKey =
-			{
-				0x0e, 0x67, 0xd0, 0x3e, 0x50, 0x85, 0x75, 0x90, 0x68, 0x55, 0x02, 0x4d, 0xd8, 0x23, 0x74, 0x55, 0xf6,
-				0xb6, 0x95, 0xa3, 0x9e, 0x02, 0x2e, 0xbd, 0x61, 0xd8, 0x7e, 0xa2, 0xed, 0xe9, 0xcc, 0x40, 0xc1, 0xf6,
-				0xa4, 0xb5, 0x9e, 0x14, 0xcf, 0x92, 0xf2, 0xe0, 0x8a, 0xe6, 0x21, 0xa0, 0x48, 0xb7, 0xff, 0x04, 0xeb,
-				0x53, 0x6d, 0xb6, 0x52, 0xd0, 0x0e, 0x7d, 0x52, 0x5a, 0x1a, 0x72, 0xa8, 0xab, 0x59, 0x0e, 0x96, 0x19,
-				0x2c, 0x32, 0x81, 0xce, 0x2f, 0x0a, 0x67, 0xa0, 0xb7, 0xa7, 0x98, 0xd2, 0xfc, 0x5f, 0xc5, 0x1a, 0x7b,
-				0xc9, 0x94, 0x72, 0xe4, 0xcc, 0xf7, 0xc3, 0x7d, 0x01, 0xef, 0xf5
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0xfa, 0xc6, 0x7e, 0xa5, 0x0f, 0xd0, 0xda, 0x3e, 0xbd, 0x89, 0x96, 0x9b, 0x8f, 0xbf, 0x11, 0x6d, 0x68,
-				0xaf, 0x2d, 0x6b, 0x90, 0x62, 0x31, 0x74, 0xcf, 0x60, 0xbb, 0xab, 0x28, 0x00, 0xbc, 0x5c, 0x54, 0xb4,
-				0x2a, 0xe1, 0x25, 0xfd, 0x72, 0x27, 0x80, 0x79, 0xc3, 0x05, 0xd7, 0xb7, 0xb1, 0x43, 0x17, 0x12, 0x58,
-				0x9e, 0xb0, 0x4e, 0x69, 0x1d, 0x8a, 0x18, 0x96, 0x15, 0x75, 0x18, 0xbd, 0xa6
-			},
-			.secKey =
-			{
-				0xfa, 0xc6, 0x7e, 0xa5, 0x0f, 0xd0, 0xda, 0x3e, 0xbd, 0x89, 0x96, 0x9b, 0x8f, 0xbf, 0x11, 0x6d, 0x68,
-				0xaf, 0x2d, 0x6b, 0x90, 0x62, 0x31, 0x74, 0xcf, 0x60, 0xbb, 0xab, 0x28, 0x00, 0xbc, 0x5c, 0x54, 0xb4,
-				0x2a, 0xe1, 0x25, 0xfd, 0x72, 0x27, 0x80, 0x79, 0xc3, 0x05, 0xd7, 0xb7, 0xb1, 0x43, 0x17, 0x12, 0x58,
-				0x9e, 0xb0, 0x4e, 0x69, 0x1d, 0x8a, 0x18, 0x96, 0x15, 0x75, 0x18, 0xbd, 0xa6, 0x64, 0x67, 0xa5, 0xb1,
-				0x41, 0x8c, 0x4e, 0xfb, 0xaf, 0xf5, 0xd8, 0xfc, 0xbc, 0x6a, 0xc3, 0x2a, 0x05, 0xd8, 0x1a, 0x70, 0xe4,
-				0xd0, 0xa4, 0x4c, 0xc5, 0x26, 0xd2, 0x0c, 0x8b, 0x37, 0xa9, 0xb8
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0xec, 0xa5, 0x90, 0x20, 0xea, 0x1d, 0xa8, 0xbd, 0x8c, 0x83, 0xd8, 0x79, 0x2a, 0xd2, 0x1c, 0x91, 0xd5,
-				0x6a, 0x40, 0xa6, 0x91, 0x55, 0x8e, 0xc6, 0xaf, 0x48, 0xd0, 0xa6, 0x6a, 0x2d, 0xec, 0x11, 0x65, 0x05,
-				0x2b, 0x71, 0x4a, 0x2d, 0xc7, 0xd9, 0x00, 0x40, 0x8f, 0x34, 0x72, 0x13, 0x1d, 0xc5, 0x2b, 0xff, 0x3e,
-				0xc1, 0xff, 0x0a, 0xbf, 0x06, 0x37, 0x01, 0x32, 0xcd, 0x6e, 0x3d, 0x31, 0x11
-			},
-			.secKey =
-			{
-				0xec, 0xa5, 0x90, 0x20, 0xea, 0x1d, 0xa8, 0xbd, 0x8c, 0x83, 0xd8, 0x79, 0x2a, 0xd2, 0x1c, 0x91, 0xd5,
-				0x6a, 0x40, 0xa6, 0x91, 0x55, 0x8e, 0xc6, 0xaf, 0x48, 0xd0, 0xa6, 0x6a, 0x2d, 0xec, 0x11, 0x65, 0x05,
-				0x2b, 0x71, 0x4a, 0x2d, 0xc7, 0xd9, 0x00, 0x40, 0x8f, 0x34, 0x72, 0x13, 0x1d, 0xc5, 0x2b, 0xff, 0x3e,
-				0xc1, 0xff, 0x0a, 0xbf, 0x06, 0x37, 0x01, 0x32, 0xcd, 0x6e, 0x3d, 0x31, 0x11, 0x8a, 0x2d, 0xde, 0x0c,
-				0xcb, 0xaf, 0xe9, 0x33, 0xc3, 0x3b, 0xcc, 0x30, 0x24, 0xdc, 0xb3, 0xcd, 0xe8, 0xb4, 0x48, 0xef, 0x65,
-				0xb8, 0x1e, 0xa0, 0x3d, 0x04, 0xf6, 0x75, 0xa2, 0xc2, 0xce, 0x06
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_ECDSAP384SHA384 ),
-			.pubKey =
-			{
-				0x26, 0x82, 0x99, 0xe2, 0x51, 0x15, 0x28, 0x73, 0x5e, 0x3f, 0x41, 0x5b, 0xc9, 0x8e, 0xad, 0x55, 0x93,
-				0x68, 0x6d, 0x36, 0xf8, 0xe1, 0x6b, 0xd9, 0xd4, 0x83, 0x57, 0xdd, 0x37, 0x78, 0xfd, 0xb4, 0xf6, 0xc2,
-				0x0d, 0xe8, 0xf8, 0x9f, 0xbf, 0x79, 0xe5, 0x4e, 0xa7, 0x75, 0x33, 0x0d, 0xc4, 0x5b, 0x0a, 0xeb, 0x3e,
-				0xd7, 0x70, 0x0f, 0x77, 0x86, 0x75, 0xd8, 0x37, 0xe9, 0x06, 0x5e, 0xa6, 0x9c
-			},
-			.secKey =
-			{
-				0x26, 0x82, 0x99, 0xe2, 0x51, 0x15, 0x28, 0x73, 0x5e, 0x3f, 0x41, 0x5b, 0xc9, 0x8e, 0xad, 0x55, 0x93,
-				0x68, 0x6d, 0x36, 0xf8, 0xe1, 0x6b, 0xd9, 0xd4, 0x83, 0x57, 0xdd, 0x37, 0x78, 0xfd, 0xb4, 0xf6, 0xc2,
-				0x0d, 0xe8, 0xf8, 0x9f, 0xbf, 0x79, 0xe5, 0x4e, 0xa7, 0x75, 0x33, 0x0d, 0xc4, 0x5b, 0x0a, 0xeb, 0x3e,
-				0xd7, 0x70, 0x0f, 0x77, 0x86, 0x75, 0xd8, 0x37, 0xe9, 0x06, 0x5e, 0xa6, 0x9c, 0xcb, 0x7b, 0xa7, 0xdb,
-				0x80, 0x63, 0x4e, 0xb8, 0x8b, 0x96, 0xd5, 0x5c, 0x36, 0xc7, 0xd5, 0xde, 0x25, 0xa7, 0xf6, 0xf5, 0x52,
-				0xcc, 0x09, 0x6b, 0x55, 0xde, 0xbf, 0x63, 0xa2, 0x1c, 0x4f, 0xce
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( ECDSAP384SHA384 );
-
-//===========================================================================================================================
-// MARK: - Ed25519 DNS Keys
-
-typedef struct
-{
-	DNSKeyEd25519Info		ksk;	// Key-Signing Key
-	DNSKeyEd25519Info		zsk;	// Zone-Signing Key
-	
-}	DNSKeyEd25519Set;
-
-static const DNSKeyEd25519Set		kDNSKeyEd25519Sets[] =
-{
-	// DNSSEC Zone 0
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0xCD, 0x87, 0xB7, 0x2E, 0x13, 0xC4, 0x97, 0x6E, 0x94, 0x78, 0x0A, 0xE9, 0x2E, 0x2B, 0x68, 0x98,
-				0x70, 0xCB, 0x42, 0xF5, 0x79, 0x41, 0x9A, 0x00, 0xB2, 0x21, 0x84, 0xB6, 0xA7, 0x81, 0x48, 0x55
-			},
-			.secKey =
-			{
-				0x68, 0x41, 0xF5, 0x9D, 0x2F, 0xA7, 0x45, 0xC7, 0xFA, 0xFE, 0x2F, 0xD5, 0xD9, 0xD9, 0x18, 0xB8,
-				0x3C, 0x47, 0xFD, 0xAE, 0xC4, 0x3A, 0x06, 0x93, 0x9C, 0x90, 0xAA, 0x31, 0xFE, 0x84, 0xC5, 0x88
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0xDF, 0x14, 0xB0, 0x25, 0x78, 0xFD, 0xC2, 0x57, 0x2A, 0xC0, 0xDB, 0x4F, 0x88, 0xD7, 0x13, 0xE2,
-				0x5C, 0x1E, 0x28, 0xE6, 0xBC, 0xA6, 0x14, 0x50, 0x39, 0x51, 0xC0, 0x0A, 0x1F, 0x1D, 0x30, 0x64
-			},
-			.secKey =
-			{
-				0x37, 0x9B, 0x7B, 0x5A, 0x88, 0x55, 0xA8, 0xB9, 0xBE, 0x63, 0x89, 0x16, 0xF8, 0x8E, 0x1D, 0x34,
-				0x22, 0x09, 0xF1, 0xED, 0xC4, 0x2B, 0xBA, 0xD5, 0xEE, 0x2C, 0xA5, 0x47, 0x34, 0x6C, 0x28, 0xFB
-			}
-		}
-	},
-	// DNSSEC Zone 1
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0x67, 0x2E, 0xCD, 0xEE, 0xD5, 0x6D, 0xEE, 0xB5, 0xE4, 0x08, 0x3A, 0x24, 0xFF, 0x36, 0xBF, 0xC9,
-				0x6A, 0x86, 0x0D, 0xFD, 0x50, 0xE8, 0x23, 0xB3, 0x0F, 0x78, 0x5C, 0x4E, 0xF4, 0x5D, 0x16, 0x2C
-			},
-			.secKey =
-			{
-				0xB9, 0x6E, 0xD4, 0x87, 0x7F, 0x83, 0x6F, 0xA6, 0x69, 0x03, 0x5C, 0x40, 0xF4, 0x27, 0x80, 0x6F,
-				0xBD, 0x2E, 0x98, 0xA8, 0xBE, 0xE7, 0x31, 0xF2, 0x43, 0xAD, 0xDF, 0x81, 0x1A, 0x3C, 0xCA, 0x9C
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0xAC, 0xB3, 0x9C, 0x79, 0x18, 0xC6, 0x74, 0x8F, 0x6B, 0x1F, 0x6A, 0xF5, 0xB0, 0x0B, 0x67, 0xDB,
-				0x30, 0xF1, 0x2D, 0xD7, 0xB5, 0xD6, 0x1F, 0xA8, 0xAC, 0x6C, 0xBB, 0x7A, 0x23, 0x88, 0x58, 0xF1
-			},
-			.secKey =
-			{
-				0xBB, 0xDA, 0x61, 0x6F, 0x93, 0x0D, 0xB7, 0x55, 0x6D, 0x10, 0xFA, 0x65, 0x05, 0xB5, 0xEA, 0xFC,
-				0xA9, 0x11, 0x1F, 0x2C, 0xD6, 0xD7, 0xB4, 0x1D, 0xC8, 0x56, 0xA8, 0xEE, 0x7D, 0xE9, 0x32, 0x22
-			}
-		}
-	},
-	// DNSSEC Zone 2
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0xA9, 0xC7, 0x9D, 0x56, 0xDA, 0x01, 0x35, 0xA1, 0xFD, 0x24, 0x17, 0x4A, 0x37, 0xDA, 0x6F, 0x6A,
-				0x00, 0x5A, 0xAD, 0x14, 0x7D, 0x7A, 0x8E, 0xD6, 0xC6, 0x2F, 0xA5, 0xCB, 0x90, 0x92, 0x23, 0xC4
-			},
-			.secKey =
-			{
-				0x49, 0x55, 0x36, 0x5F, 0x87, 0x5B, 0xC1, 0x70, 0x02, 0x4B, 0xB7, 0xE7, 0xB7, 0xD0, 0x30, 0x7A,
-				0x14, 0xB4, 0x4D, 0xC6, 0x91, 0x4A, 0x64, 0x33, 0x5F, 0xA5, 0x6E, 0x45, 0x18, 0xDE, 0x9B, 0x9C
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0x40, 0x84, 0x91, 0xFF, 0x79, 0x2A, 0x2A, 0x00, 0x9B, 0x81, 0x47, 0xF3, 0xB5, 0xFD, 0xCF, 0x45,
-				0xDD, 0x40, 0xCD, 0xDC, 0x7E, 0xC3, 0xEA, 0x52, 0x1F, 0x92, 0x47, 0x8F, 0x3B, 0xFC, 0x2B, 0x1E
-			},
-			.secKey =
-			{
-				0x31, 0xEE, 0x63, 0x02, 0x4D, 0x0F, 0x67, 0x19, 0x8E, 0xE0, 0x81, 0xE3, 0x19, 0xCA, 0x0E, 0x44,
-				0xBF, 0x47, 0x26, 0x1C, 0x2E, 0x45, 0x98, 0xAC, 0x97, 0x45, 0x57, 0x59, 0x17, 0x45, 0xB4, 0xA5
-			}
-		}
-	},
-	// DNSSEC Zone 3
-	{
-		.ksk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitKSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0x6A, 0xBE, 0x53, 0x33, 0xA7, 0x21, 0xF5, 0xE9, 0x09, 0xC6, 0x63, 0xBB, 0x16, 0x19, 0xD6, 0x5D,
-				0x7C, 0xA6, 0x90, 0x7B, 0xD6, 0x30, 0xDB, 0x81, 0xFD, 0x95, 0xF0, 0xDB, 0xCF, 0x6B, 0xB1, 0xDA
-			},
-			.secKey =
-			{
-				0x3C, 0xE0, 0x72, 0x1F, 0x4F, 0x3E, 0xA1, 0xBA, 0x12, 0xF3, 0x6E, 0x8E, 0xAE, 0x67, 0x9F, 0x45,
-				0x20, 0x69, 0xA6, 0xC3, 0x6E, 0xEC, 0xA8, 0xC0, 0x84, 0x31, 0xA8, 0x12, 0x0A, 0xEC, 0xED, 0x3B
-			}
-		},
-		.zsk =
-		{
-			.fixedFields = _DNSKeyInfoFixedFieldsInitZSK( kDNSSECAlgorithm_Ed25519 ),
-			.pubKey =
-			{
-				0x4A, 0xE1, 0x8C, 0xED, 0x15, 0x60, 0x8C, 0x0A, 0x97, 0xD9, 0x77, 0xF2, 0x93, 0x1B, 0xDA, 0x40,
-				0xAB, 0xE7, 0x9E, 0x0C, 0xE7, 0xF4, 0xA6, 0x68, 0x08, 0x3E, 0x9B, 0xC9, 0x2A, 0x0C, 0x7A, 0xDA
-			},
-			.secKey =
-			{
-				0x6B, 0x1E, 0x83, 0xC8, 0xFB, 0xF5, 0xF8, 0x98, 0x92, 0x85, 0x7E, 0x5F, 0x07, 0xF8, 0xB5, 0xB1,
-				0x9D, 0x9C, 0x58, 0x76, 0xCB, 0x20, 0x2E, 0x81, 0xB4, 0x4B, 0x4D, 0xFF, 0xF2, 0x3B, 0xCD, 0x50
-			}
-		}
-	}
-};
-
-_DNSKeySetsCompileTimeChecks( Ed25519 );
-
-//===========================================================================================================================
-// MARK: - Public Functions -
-
-#define _GetDNSKeyInfoCase( ALG_NAME )																		\
-	case kDNSSECAlgorithm_ ## ALG_NAME:																		\
-		if( inIndex < countof( kDNSKey ## ALG_NAME ## Sets ) )												\
-		{																									\
-			const DNSKey ## ALG_NAME ## Set * const			_set = &kDNSKey ## ALG_NAME ## Sets[ inIndex ];	\
-			const DNSKey ## ALG_NAME ## Info * const		_keyInfo = inGetZSK ? &_set->zsk : &_set->ksk;	\
-																											\
-			return( (DNSKeyInfoRef) _keyInfo );																\
-		}																									\
-		break
-
-DNSKeyInfoRef	GetDNSKeyInfoEx( const uint32_t inAlgorithm, const uint32_t inIndex, const Boolean inGetZSK )
-{
-	switch( inAlgorithm )
-	{
-		_GetDNSKeyInfoCase( RSASHA1 );
-		_GetDNSKeyInfoCase( RSASHA256 );
-		_GetDNSKeyInfoCase( RSASHA512 );
-		_GetDNSKeyInfoCase( ECDSAP256SHA256 );
-		_GetDNSKeyInfoCase( ECDSAP384SHA384 );
-		_GetDNSKeyInfoCase( Ed25519 );
-		default: break;
-	}
-	return( NULL );
-}
-
-//===========================================================================================================================
-
-uint8_t	DNSKeyInfoGetAlgorithm( const DNSKeyInfoRef me )
-{
-	return( dns_fixed_fields_dnskey_get_algorithm( &me->fixedFields ) );
-}
-
-//===========================================================================================================================
-
-const uint8_t *	DNSKeyInfoGetRDataPtr( const DNSKeyInfoRef me )
-{
-	return( (const uint8_t *) &me->fixedFields );
-}
-
-//===========================================================================================================================
-
-#define _DNSKeyInfoGetRDataLenCase( ALG_NAME ) \
-	case kDNSSECAlgorithm_ ## ALG_NAME: return( endof_field( DNSKey ## ALG_NAME ## Info, pubKey ) )
-
-uint16_t	DNSKeyInfoGetRDataLen( const DNSKeyInfoRef me )
-{
-	switch( DNSKeyInfoGetAlgorithm( me ) )
-	{
-		_DNSKeyInfoGetRDataLenCase( RSASHA1 );
-		_DNSKeyInfoGetRDataLenCase( RSASHA256 );
-		_DNSKeyInfoGetRDataLenCase( RSASHA512 );
-		_DNSKeyInfoGetRDataLenCase( ECDSAP256SHA256 );
-		_DNSKeyInfoGetRDataLenCase( ECDSAP384SHA384 );
-		_DNSKeyInfoGetRDataLenCase( Ed25519 );
-		default: return( 0 );
-	}
-}
-
-//===========================================================================================================================
-
-#define _DNSKeyInfoGetPubKeyPtrCase( ALG_NAME ) \
-	case kDNSSECAlgorithm_ ## ALG_NAME: return( me->ALG_NAME.pubKey )
-
-const uint8_t *	DNSKeyInfoGetPubKeyPtr( const DNSKeyInfoRef me )
-{
-	switch( DNSKeyInfoGetAlgorithm( me ) )
-	{
-		_DNSKeyInfoGetPubKeyPtrCase( RSASHA1 );
-		_DNSKeyInfoGetPubKeyPtrCase( RSASHA256 );
-		_DNSKeyInfoGetPubKeyPtrCase( RSASHA512 );
-		_DNSKeyInfoGetPubKeyPtrCase( ECDSAP256SHA256 );
-		_DNSKeyInfoGetPubKeyPtrCase( ECDSAP384SHA384 );
-		_DNSKeyInfoGetPubKeyPtrCase( Ed25519 );
-		default: return( NULL );
-	}
-}
-
-//===========================================================================================================================
-
-#define _DNSKeyInfoGetPubKeyLenCase( ALG_NAME ) \
-	case kDNSSECAlgorithm_ ## ALG_NAME: return( sizeof_field( DNSKey ## ALG_NAME ## Info, pubKey ) )
-
-size_t	DNSKeyInfoGetPubKeyLen( const DNSKeyInfoRef me )
-{
-	switch( DNSKeyInfoGetAlgorithm( me ) )
-	{
-		_DNSKeyInfoGetPubKeyLenCase( RSASHA1 );
-		_DNSKeyInfoGetPubKeyLenCase( RSASHA256 );
-		_DNSKeyInfoGetPubKeyLenCase( RSASHA512 );
-		_DNSKeyInfoGetPubKeyLenCase( ECDSAP256SHA256 );
-		_DNSKeyInfoGetPubKeyLenCase( ECDSAP384SHA384 );
-		_DNSKeyInfoGetPubKeyLenCase( Ed25519 );
-		default: return( 0 );
-	}
-}
-
-//===========================================================================================================================
-
-uint16_t	DNSKeyInfoGetKeyTag( const DNSKeyInfoRef inKeyInfo )
-{
-	return( DNSComputeDNSKeyTag( DNSKeyInfoGetRDataPtr( inKeyInfo ), DNSKeyInfoGetRDataLen( inKeyInfo ) ) );
-}
-
-//===========================================================================================================================
-
-#define SHA256_OUTPUT_SIZE		32
-#define SHA384_OUTPUT_SIZE		48
-
-Boolean
-	DNSKeyInfoSign(
-		DNSKeyInfoRef   dnsKey,
-		const uint8_t *	dataToSign,
-		const size_t	dataLen,
-		uint8_t			outSignature[ STATIC_PARAM kDNSServerSignatureLengthMax ],
-		size_t * const	outSignatureLen )
-{
-	Boolean isSigned = false;
-	CFErrorRef cfError = NULL;
-	uint8_t dnsKeyAlgorithm = DNSKeyInfoGetAlgorithm( dnsKey );
-
-	if( dataLen > LONG_MAX )
-	{
-		return isSigned;
-	}
-
-	switch( dnsKeyAlgorithm )
-	{
-		case kDNSSECAlgorithm_RSASHA1:
-		case kDNSSECAlgorithm_RSASHA256:
-		case kDNSSECAlgorithm_RSASHA512:
-		{
-			const void *		secKeyRefOpts[]		= { kSecAttrKeyType, kSecAttrKeyClass };
-			const void *		seckeyRefVals[]		= { kSecAttrKeyTypeRSA, kSecAttrKeyClassPrivate };
-			SecKeyAlgorithm		algorithm;
-			const uint8_t *		secKeyBytes			= NULL;
-			CFIndex				secKeyBytesLength;
-			CFDictionaryRef		secKeyDic			= NULL;
-			CFDataRef			secKeyDataRef		= NULL;
-			SecKeyRef			secKeyRef			= NULL;
-			CFDataRef			cfDataToSign		= NULL;
-			CFDataRef			sigDataRef			= NULL;
-
-			secKeyDic = CFDictionaryCreate(kCFAllocatorDefault, secKeyRefOpts, seckeyRefVals, countof( secKeyRefOpts ),
-				&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-			require_quiet( secKeyDic, rsa_sign_exit );
-
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA1 )
-			{
-				secKeyBytes = dnsKey->RSASHA1.secKey;
-				secKeyBytesLength = kRSASHA1_SecretKeyBytes;
-				algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;
-			}
-			else if( dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA256 )
-			{
-				secKeyBytes = dnsKey->RSASHA256.secKey;
-				secKeyBytesLength = kRSASHA256_SecretKeyBytes;
-				algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256;
-			}
-			else // dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA512
-			{
-				secKeyBytes = dnsKey->RSASHA512.secKey;
-				secKeyBytesLength = kRSASHA512_SecretKeyBytes;
-				algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512;
-			}
-
-			secKeyDataRef = CFDataCreate( kCFAllocatorDefault, secKeyBytes, secKeyBytesLength);
-			require_quiet( secKeyDataRef, rsa_sign_exit );
-			secKeyRef = SecKeyCreateWithData( secKeyDataRef, secKeyDic, &cfError );
-			require_quiet( secKeyRef, rsa_sign_exit );
-
-			cfDataToSign = CFDataCreate( kCFAllocatorDefault, dataToSign, ( signed long )dataLen );
-			require_quiet( cfDataToSign, rsa_sign_exit );
-
-			sigDataRef = SecKeyCreateSignature( secKeyRef, algorithm, cfDataToSign, &cfError );
-			require_quiet( sigDataRef != NULL, rsa_sign_exit );
-
-			memcpy( outSignature, CFDataGetBytePtr( sigDataRef ), (size_t) CFDataGetLength( sigDataRef ) );
-			if( outSignatureLen != NULL ) *outSignatureLen = (size_t)CFDataGetLength( sigDataRef );
-
-			isSigned = true;
-		rsa_sign_exit:
-			if( secKeyDic != NULL )		CFRelease(secKeyDic);
-			if( secKeyDataRef != NULL )	CFRelease(secKeyDataRef);
-			if( secKeyRef != NULL )		CFRelease(secKeyRef);
-			if( cfDataToSign != NULL )	CFRelease(cfDataToSign);
-			if( sigDataRef != NULL )	CFRelease(sigDataRef);
-			break;
-		}
-		case kDNSSECAlgorithm_ECDSAP256SHA256:
-		case kDNSSECAlgorithm_ECDSAP384SHA384:
-		{
-			// prepare kSecAttrKey dictionary to create the SecKeyRef
-			const void *		secKeyRefOpts[]		= { kSecAttrKeyType, kSecAttrKeyClass };
-			const void *		seckeyRefVals[]		= { kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClassPrivate };
-			uint8_t				secKeyDataWithPrefix[ 1 + MAX( kECDSAP256SHA256_SecretKeyBytes, kECDSAP384SHA384_SecretKeyBytes ) ]; // 04|data
-			CFDictionaryRef		secKeyDic			= NULL;
-			CFDataRef			secKeyDataRef		= NULL;
-			SecKeyRef			secKeyRef			= NULL;
-			uint8_t				digest[ MAX( SHA256_OUTPUT_SIZE, SHA384_OUTPUT_SIZE ) ];
-			uint8_t				digestLen			= (dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP256SHA256) ? SHA256_OUTPUT_SIZE : SHA384_OUTPUT_SIZE;
-			CFDataRef			digestToSignRef		= NULL;
-			CFDataRef			sigDataRef			= NULL;
-
-			// construct private key
-			secKeyDataWithPrefix[0] = 4;
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP256SHA256 )
-			{
-				memcpy( secKeyDataWithPrefix + 1, dnsKey->ECDSAP256SHA256.secKey, sizeof( dnsKey->ECDSAP256SHA256.secKey ) );
-			}
-			else // dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP384SHA384
-			{
-				memcpy( secKeyDataWithPrefix + 1, dnsKey->ECDSAP384SHA384.secKey, sizeof( dnsKey->ECDSAP384SHA384.secKey ) );
-			}
-
-			// create kSecAttrKey dictionary
-			secKeyDic = CFDictionaryCreate( kCFAllocatorDefault, secKeyRefOpts, seckeyRefVals,
-				countof( secKeyRefOpts ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-			require_quiet( secKeyDic != NULL, ecdsa_sign_exit );
-
-			// create private key
-			secKeyDataRef = CFDataCreate( kCFAllocatorDefault, secKeyDataWithPrefix, sizeof( secKeyDataWithPrefix ) );
-			require_quiet(secKeyDataRef != NULL, ecdsa_sign_exit);
-			secKeyRef = SecKeyCreateWithData( secKeyDataRef, secKeyDic, &cfError );
-			require_quiet(secKeyRef != NULL, ecdsa_sign_exit );
-
-			// calculate digest for the data and create CFDataRef
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP256SHA256 )
-			{
-				CC_SHA256( dataToSign, (uint32_t)dataLen, digest );
-			}
-			else // dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP384SHA384
-			{
-				CC_SHA384( dataToSign, (uint32_t)dataLen, digest );
-			}
-			digestToSignRef = CFDataCreate( kCFAllocatorDefault, digest, digestLen );
-			require_quiet( digestToSignRef != NULL, ecdsa_sign_exit);
-
-			// Sign the data
-			sigDataRef = SecKeyCreateSignature( secKeyRef, kSecKeyAlgorithmECDSASignatureRFC4754, digestToSignRef, &cfError );
-			require_quiet( sigDataRef != NULL, ecdsa_sign_exit );
-
-			// copy the result
-			memcpy( outSignature, CFDataGetBytePtr( sigDataRef ), (size_t) CFDataGetLength( sigDataRef ) );
-			if( outSignatureLen != NULL ) *outSignatureLen = (size_t)CFDataGetLength( sigDataRef );
-
-			isSigned = true;
-		ecdsa_sign_exit:
-			if( sigDataRef != NULL )			CFRelease( sigDataRef );
-			if( digestToSignRef != NULL )		CFRelease( digestToSignRef );
-			if( secKeyRef != NULL )				CFRelease( secKeyRef );
-			if( secKeyDataRef != NULL )			CFRelease( secKeyDataRef );
-			if( secKeyDic != NULL )				CFRelease( secKeyDic );
-			break;
-		}
-		case kDNSSECAlgorithm_Ed25519:
-		{
-			const DNSKeyEd25519Info *key = &dnsKey->Ed25519;
-			Ed25519_sign( outSignature, dataToSign, dataLen, key->pubKey, key->secKey );
-			isSigned = true;
-			if( outSignatureLen != NULL ) *outSignatureLen = kEd25519_SignatureBytes;
-			break;
-		}
-		default:
-			isSigned = false;
-			break;
-	}
-
-	return isSigned;
-}
-
-//===========================================================================================================================
-
-static void
-	_ParseRSAPublicKey(
-		const uint8_t *		inPublicKey,
-		uint16_t			inKeyLength,
-		const uint8_t **	outModulus,
-		long *				outModulusLength,
-		const uint8_t **	outExponent,
-		long *				outExponentLength );
-
-Boolean
-	DNSKeyInfoVerify(
-		DNSKeyInfoRef	inKeyInfo,
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inSignaturePtr,
-		size_t			inSignatureLen )
-{
-	CFErrorRef		cfError				= NULL;
-	SecKeyRef		pubKeyRef			= NULL;
-	const uint8_t *	dataToSign			= NULL;
-	size_t			dataToSignLength	= 0;
-	CFDataRef		dataToSignRef		= NULL;
-	CFDataRef		sigDataRef			= NULL;
-	Boolean			isValid				= false;
-	uint8_t			dnsKeyAlgorithm;
-	SecKeyAlgorithm	verifyAlgorithm;
-
-	dnsKeyAlgorithm = DNSKeyInfoGetAlgorithm( inKeyInfo );
-	switch( dnsKeyAlgorithm )
-	{
-		case kDNSSECAlgorithm_RSASHA1:
-		case kDNSSECAlgorithm_RSASHA256:
-		case kDNSSECAlgorithm_RSASHA512:
-		{
-			const uint8_t *	keyBytes;
-			uint16_t		keyLength;
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA1 )
-			{
-				verifyAlgorithm	= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;
-				keyBytes		= inKeyInfo->RSASHA1.pubKey;
-				keyLength		= kRSASHA1_PublicKeyBytes;
-			}
-			else if( dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA256 )
-			{
-				verifyAlgorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256;
-				keyBytes		= inKeyInfo->RSASHA256.pubKey;
-				keyLength		= kRSASHA256_PublicKeyBytes;
-			}
-			else // dnsKeyAlgorithm == kDNSSECAlgorithm_RSASHA512
-			{
-				verifyAlgorithm	= kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512;
-				keyBytes		= inKeyInfo->RSASHA512.pubKey;
-				keyLength		= kRSASHA512_PublicKeyBytes;
-			}
-			SecRSAPublicKeyParams rsaKeyParams;
-			_ParseRSAPublicKey( keyBytes, keyLength, ( const uint8_t ** )&rsaKeyParams.modulus,
-				&rsaKeyParams.modulusLength, ( const uint8_t ** )&rsaKeyParams.exponent, &rsaKeyParams.exponentLength );
-			pubKeyRef = SecKeyCreateRSAPublicKey( kCFAllocatorDefault, ( const uint8_t * )&rsaKeyParams,
-				sizeof( rsaKeyParams ), kSecKeyEncodingRSAPublicParams );
-
-			dataToSign			= inMsgPtr;
-			dataToSignLength	= inMsgLen;
-
-			break;
-		}
-		case kDNSSECAlgorithm_ECDSAP256SHA256:
-		case kDNSSECAlgorithm_ECDSAP384SHA384:
-		{
-			const void *		pubKeyRefOpts[]		= { kSecAttrKeyType, kSecAttrKeyClass };
-			const void *		pubKeyRefVals[]		= { kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClassPublic };
-			uint8_t				pubKeyDataWithPrefix[ 1 + MAX( kECDSAP256SHA256_PublicKeyBytes , kECDSAP384SHA384_PublicKeyBytes ) ]; // 04|data
-			CFDictionaryRef		pubKeyDic			= NULL;
-			CFDataRef			pubKeyDataRef		= NULL;
-			uint8_t				digest[ MAX( SHA256_OUTPUT_SIZE , SHA384_OUTPUT_SIZE ) ];
-
-			pubKeyDataWithPrefix[ 0 ] = 4;
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP256SHA256 )
-			{
-				memcpy( pubKeyDataWithPrefix + 1, inKeyInfo->ECDSAP256SHA256.pubKey, sizeof( inKeyInfo->ECDSAP256SHA256.pubKey ) );
-			}
-			else
-			{
-				memcpy( pubKeyDataWithPrefix + 1, inKeyInfo->ECDSAP384SHA384.pubKey, sizeof( inKeyInfo->ECDSAP384SHA384.pubKey ) );
-			}
-			verifyAlgorithm = kSecKeyAlgorithmECDSASignatureRFC4754;
-
-			pubKeyDic = CFDictionaryCreate( kCFAllocatorDefault, pubKeyRefOpts, pubKeyRefVals,
-				sizeof( pubKeyRefOpts ) / sizeof( void * ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-			require_quiet( pubKeyDic != NULL, ecdsa_exit );
-
-			pubKeyDataRef = CFDataCreate( kCFAllocatorDefault, pubKeyDataWithPrefix, sizeof( pubKeyDataWithPrefix ) );
-			require_quiet( pubKeyDataRef != NULL, ecdsa_exit );
-			pubKeyRef = SecKeyCreateWithData( pubKeyDataRef, pubKeyDic, &cfError );
-			require_action_quiet( pubKeyRef != NULL, ecdsa_exit, FPrintF( stderr, "%@", CFErrorCopyDescription( cfError ) ) );
-
-			if( dnsKeyAlgorithm == kDNSSECAlgorithm_ECDSAP256SHA256 )
-			{
-				CC_SHA256( inMsgPtr, (uint32_t)inMsgLen, digest );
-				dataToSignLength = SHA256_OUTPUT_SIZE;
-			}
-			else
-			{
-				CC_SHA384( inMsgPtr, (uint32_t)inMsgLen, digest );
-				dataToSignLength = SHA384_OUTPUT_SIZE;
-			}
-			dataToSign = digest;
-
-		ecdsa_exit:
-			if( pubKeyDataRef != NULL )	CFRelease( pubKeyDataRef );
-			if( pubKeyDic != NULL )		CFRelease( pubKeyDic );
-			break;
-		}
-		case kDNSSECAlgorithm_Ed25519:
-		{
-			require_action_quiet( inSignatureLen == kEd25519_SignatureBytes, exit, isValid = false );
-			isValid = ( Ed25519_verify( inMsgPtr, inMsgLen, inSignaturePtr, inKeyInfo->Ed25519.pubKey ) == 0 );
-			goto exit;
-		}
-		default:
-			isValid = false;
-			goto exit;
-	}
-
-	require_quiet( pubKeyRef != NULL, exit );
-
-	dataToSignRef = CFDataCreate( kCFAllocatorDefault, dataToSign, ( signed long )dataToSignLength );
-	require_quiet( dataToSignRef != NULL, exit);
-
-	sigDataRef = CFDataCreate( kCFAllocatorDefault, inSignaturePtr, (signed long)inSignatureLen );
-	require_quiet( sigDataRef != NULL, exit );
-
-	isValid = SecKeyVerifySignature( pubKeyRef, verifyAlgorithm, dataToSignRef, sigDataRef, &cfError);
-
-exit:
-	if( pubKeyRef != NULL )		CFRelease( pubKeyRef );
-	if( dataToSignRef != NULL )	CFRelease( dataToSignRef );
-	if( sigDataRef != NULL )	CFRelease( sigDataRef );
-	return isValid;
-}
-
-//===========================================================================================================================
-
-static void
-	_ParseRSAPublicKey(
-	const uint8_t * const	publicKey,
-	const uint16_t			keyLength,
-	const uint8_t ** const	outModulus,
-	long * const			outModulusLength,
-	const uint8_t ** const	outExponent,
-	long * const			outExponentLength )
-{
-	uint8_t exponentLengthFieldLength;
-	if( publicKey[0] != 0 )
-	{
-		*outExponentLength = publicKey[0];
-		exponentLengthFieldLength = 1;
-	}
-	else
-	{
-		*outExponentLength = (long)(((uint32_t)publicKey[1] << 8) | (uint32_t)publicKey[2]);
-		exponentLengthFieldLength = 3;
-	}
-
-	*outExponent		= publicKey + exponentLengthFieldLength;
-	*outModulusLength	= keyLength - ( *outExponentLength + exponentLengthFieldLength );
-	*outModulus			= publicKey + exponentLengthFieldLength + *outExponentLength;
-}
-
-//===========================================================================================================================
-// Note: The descriptions come from
-// <https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1>.
-
-const char *	DNSKeyInfoGetAlgorithmDescription( const DNSKeyInfoRef me )
-{
-	switch( DNSKeyInfoGetAlgorithm( me ) )
-	{
-		case kDNSSECAlgorithm_RSASHA1:			return( "RSA/SHA-1" );
-		case kDNSSECAlgorithm_RSASHA256:		return( "RSA/SHA-256" );
-		case kDNSSECAlgorithm_RSASHA512:		return( "RSA/SHA-512" );
-		case kDNSSECAlgorithm_ECDSAP256SHA256:	return( "ECDSA Curve P-256 with SHA-256" );
-		case kDNSSECAlgorithm_ECDSAP384SHA384:	return( "ECDSA Curve P-384 with SHA-384" );
-		case kDNSSECAlgorithm_Ed25519:			return( "Ed25519" );
-		default:								return( "<UNKNOWN ALGORITHM>" );
-	}
-}
diff --git a/Clients/dnssdutil/DNSServerDNSSEC.h b/Clients/dnssdutil/DNSServerDNSSEC.h
deleted file mode 100644
index a2c310c..0000000
--- a/Clients/dnssdutil/DNSServerDNSSEC.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-	Copyright (c) 2020 Apple Inc. All rights reserved.
-*/
-
-#ifndef	__DNSServerDNSSEC_h
-#define	__DNSServerDNSSEC_h
-
-#include <CoreUtils/CoreUtils.h>
-
-CU_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief	Zone Label Argument Limits
-*/
-
-#define kZoneLabelIndexArgMin		1
-#define kZoneLabelIndexArgMax		3
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief	Reference to a DNSKeyInfo object.
-*/
-typedef const union DNSKeyInfo *		DNSKeyInfoRef;
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets a constant DNSKeyInfo object, which represents a DNSSEC DNS key.
-	
-	@param		inAlgorithm		The desired DNSKeyInfo object's DNSSEC algorithm number.
-	@param		inIndex			The desired DNSKeyInfo object's index number.
-	@param		inGetZSK		If true, gets a zone-signing key. Otherwise a key-signing key.
-	
-	@result		A reference to the DNSKeyInfo object if it exists, otherwise, NULL.
-*/
-DNSKeyInfoRef _Nullable	GetDNSKeyInfoEx( uint32_t inAlgorithm, uint32_t inIndex, Boolean inGetZSK );
-#define GetDNSKeyInfoKSK( ALGORITHM, INDEX )		GetDNSKeyInfoEx( ALGORITHM, INDEX, false )
-#define GetDNSKeyInfoZSK( ALGORITHM, INDEX )		GetDNSKeyInfoEx( ALGORITHM, INDEX, true )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets a DNSKeyInfo object's DNSSEC algorithm number.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The DNSSEC algorithm number.
-	
-	@discussion	See <https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1>.
-*/
-uint8_t	DNSKeyInfoGetAlgorithm( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets a pointer to a DNSKeyInfo object's DNSKEY record data.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The DNSKEY record data in wire format. See <https://tools.ietf.org/html/rfc4034#section-2.1>.
-	
-	@discussion	Use DNSKeyInfoGetRDataLen() to get the record data's length.
-*/
-const uint8_t *	DNSKeyInfoGetRDataPtr( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets the length of a DNSKeyInfo object's DNSKEY record data.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The length of the record data.
-*/
-uint16_t	DNSKeyInfoGetRDataLen( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets a pointer to a DNSKeyInfo object's public key.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		A pointer to the public key.
-	
-	@discussion	Use DNSKeyInfoGetPubKeyLen() to get the public key's length.
-*/
-const uint8_t *	_Nullable DNSKeyInfoGetPubKeyPtr( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets the length of a DNSKeyInfo object's public key.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The length of the public key.
-*/
-size_t	DNSKeyInfoGetPubKeyLen( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets the DNSSEC key tag of DNSKeyInfo objects' DNSKEY record data.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The DNSSEC key tag.
-*/
-uint16_t	DNSKeyInfoGetKeyTag( DNSKeyInfoRef inKeyInfo );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	kDNSServerSignatureLengthMax
-	
-	@discussion	The maximum length of a DNSSEC signature for DNSSEC algorithms currently implemented by the test DNS server.
-*/
-#define kDNSServerSignatureLengthMax		256
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Signs a message using a DNSKeyInfo object's secret key.
-	
-	@param		inKeyInfo			The DNSKeyInfo object.
-	@param		inMsgPtr			Pointer to the message to sign.
-	@param		inMsgLen			Length, in bytes, of the message to sign.
-	@param		outSignature		Buffer to which to write the signature.
-	@param		outSignatureLen		Pointer of variable to get set to the signature's length.
-	
-	@result		Returns true if the message was able to be signed, otherwise, returns false.
-*/
-Boolean
-	DNSKeyInfoSign(
-		DNSKeyInfoRef	inKeyInfo,
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		uint8_t			outSignature[ STATIC_PARAM kDNSServerSignatureLengthMax ],
-		size_t *		outSignatureLen );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Verifies a signature using a DNSKeyInfo object's public key.
-	
-	@param		inKeyInfo			The DNSKeyInfo object.
-	@param		inMsgPtr			Pointer to the message that was signed.
-	@param		inMsgLen			Length, in bytes, of the message that was signed.
-	@param		inSignaturePtr		Pointer to the supposed signature.
-	@param		inSignatureLen		Length, in bytes, of the supposed signature.
-	
-	@result		Returns true if the signature was verified, otherwise, returns false.
-*/
-Boolean
-	DNSKeyInfoVerify(
-		DNSKeyInfoRef	inKeyInfo,
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inSignaturePtr,
-		size_t			inSignatureLen );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@brief		Gets a short description of a DNSKeyInfo object's DNSSEC algorithm.
-	
-	@param		inKeyInfo		The DNSKeyInfo object.
-	
-	@result		The description as a UTF-8 C string.
-*/
-const char *	DNSKeyInfoGetAlgorithmDescription( DNSKeyInfoRef inKeyInfo );
-
-__END_DECLS
-
-CU_ASSUME_NONNULL_END
-
-#endif	// __DNSServerDNSSEC_h
diff --git a/Clients/dnssdutil/TestUtils.h b/Clients/dnssdutil/TestUtils.h
deleted file mode 100644
index 81fbb10..0000000
--- a/Clients/dnssdutil/TestUtils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-//  TestUtils.h
-//  mDNSResponder
-//
-//  Copyright (c) 2019 Apple Inc. All rights reserved.
-//
-
-#ifndef    __TestUtils_h
-#define    __TestUtils_h
-
-#include <TargetConditionals.h>
-#include <MacTypes.h>
-#include <mach/mach.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DNSSDUTIL_XCTEST "DNSSDUTIL_XCTEST"
-
-bool run_xctest_named(const char *classname);
-bool audit_token_for_pid(pid_t pid, const audit_token_t *token);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __TestUtils_h
diff --git a/Clients/dnssdutil/TestUtils.m b/Clients/dnssdutil/TestUtils.m
index e728c3d..f0cd43d 100644
--- a/Clients/dnssdutil/TestUtils.m
+++ b/Clients/dnssdutil/TestUtils.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2019-2022 Apple 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.
@@ -28,7 +28,7 @@
 //===========================================================================================================================
 //    XCTest Utils
 //===========================================================================================================================
-static bool _load_xctest_framework()
+static bool _load_xctest_framework(void)
 {
     bool loaded = (NSClassFromString(@"XCTestSuite") != nil);
     static void *s_xctest_handle;
diff --git a/Clients/dnssdutil/dnssdutil.c b/Clients/dnssdutil/dnssdutil.c
deleted file mode 100644
index 1999456..0000000
--- a/Clients/dnssdutil/dnssdutil.c
+++ /dev/null
@@ -1,36370 +0,0 @@
-/*
- * Copyright (c) 2016-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "DNSServerDNSSEC.h"
-
-#include <CoreUtils/CoreUtils.h>
-#include <dns_sd.h>
-#include <dns_sd_private.h>
-#include <mdns/DNSMessage.h>
-#include <mdns/dns_relay.h>
-#include <mdns/pf.h>
-#include <mdns/security.h>
-#include <mdns/signed_result.h>
-#include <mdns/system.h>
-#include <mrc/private.h>
-#include <os/feature_private.h>
-#include <pcap.h>
-#include <Security/SecCertificateRequest.h>
-#include <Security/SecTrustSettings.h>
-
-#include CF_RUNTIME_HEADER
-
-#if( TARGET_OS_DARWIN )
-	#include <CFNetwork/CFHost.h>
-	#include <CoreFoundation/CoreFoundation.h>
-	#include <SystemConfiguration/SCPrivate.h>
-	#include <dnsinfo.h>
-	#include <netdb.h>
-	#include <netinet6/in6_var.h>
-	#include <netinet6/nd6.h>
-	#include <spawn.h>
-	#include <xpc/xpc.h>
-#endif
-
-#if( TARGET_OS_POSIX )
-	#include <sys/resource.h>
-	#include <spawn.h>
-#endif
-
-#if( !defined( DNSSDUTIL_INCLUDE_DNSCRYPT ) )
-	#define DNSSDUTIL_INCLUDE_DNSCRYPT		0
-#endif
-
-#if( DNSSDUTIL_INCLUDE_DNSCRYPT )
-	#include "tweetnacl.h"	// TweetNaCl from <https://tweetnacl.cr.yp.to/software.html>.
-#endif
-
-#if( !defined( MDNSRESPONDER_PROJECT ) )
-	#define MDNSRESPONDER_PROJECT		0
-#endif
-
-#if( MDNSRESPONDER_PROJECT )
-	#include <CoreFoundation/CFXPCBridge.h>
-	#include <dns_services.h>
-	#include "dnssd_private.h"
-	#include <mdns/private.h>
-	#include <mdns/tcpinfo.h>
-	#include "TestUtils.h"
-	// Set ENABLE_DNSSDUTIL_DNSSEC_TEST to 1 to enable DNSSEC test functionality.
-	#define ENABLE_DNSSDUTIL_DNSSEC_TEST 1
-#endif
-
-//===========================================================================================================================
-//	Versioning
-//===========================================================================================================================
-
-#define kDNSSDUtilNumVersion	NumVersionBuild( 2, 0, 0, kVersionStageBeta, 0 )
-
-#if( !MDNSRESPONDER_PROJECT && !defined( DNSSDUTIL_SOURCE_VERSION ) )
-	#define DNSSDUTIL_SOURCE_VERSION	"0.0.0"
-#endif
-
-#define kDNSSDUtilIdentifier		"com.apple.dnssdutil"
-
-//===========================================================================================================================
-//	DNS-SD
-//===========================================================================================================================
-
-// DNS-SD API flag descriptors
-
-#define kDNSServiceFlagsDescriptors		\
-	"\x00" "AutoTrigger\0"				\
-	"\x01" "Add\0"						\
-	"\x02" "Default\0"					\
-	"\x03" "NoAutoRename\0"				\
-	"\x04" "Shared\0"					\
-	"\x05" "Unique\0"					\
-	"\x06" "BrowseDomains\0"			\
-	"\x07" "RegistrationDomains\0"		\
-	"\x08" "LongLivedQuery\0"			\
-	"\x09" "AllowRemoteQuery\0"			\
-	"\x0A" "ForceMulticast\0"			\
-	"\x0B" "KnownUnique\0"				\
-	"\x0C" "ReturnIntermediates\0"		\
-	"\x0D" "DenyConstrained\0"			\
-	"\x0E" "ShareConnection\0"			\
-	"\x0F" "SuppressUnusable\0"			\
-	"\x10" "Timeout\0"					\
-	"\x11" "IncludeP2P\0"				\
-	"\x12" "WakeOnResolve\0"			\
-	"\x13" "BackgroundTrafficClass\0"	\
-	"\x14" "IncludeAWDL\0"				\
-	"\x15" "EnableDNSSEC\0"				\
-	"\x16" "UnicastResponse\0"			\
-	"\x17" "ValidateOptional\0"			\
-	"\x18" "WakeOnlyService\0"			\
-	"\x19" "ThresholdOne\0"				\
-	"\x1A" "ThresholdFinder\0"			\
-	"\x1B" "DenyCellular\0"				\
-	"\x1C" "ServiceIndex\0"				\
-	"\x1D" "DenyExpensive\0"			\
-	"\x1E" "PathEvaluationDone\0"		\
-	"\x1F" "AllowExpiredAnswers\0"		\
-	"\x00"
-
-#define DNSServiceFlagsToAddRmvStr( FLAGS )		( ( (FLAGS) & kDNSServiceFlagsAdd ) ? "Add" : "Rmv" )
-
-#define kDNSServiceProtocolDescriptors	\
-	"\x00" "IPv4\0"						\
-	"\x01" "IPv6\0"						\
-	"\x04" "UDP\0"						\
-	"\x05" "TCP\0"						\
-	"\x00"
-
-#define kBadDNSServiceRef		( (DNSServiceRef)(intptr_t) -1 )
-
-//===========================================================================================================================
-//	DNS
-//===========================================================================================================================
-
-#define kDNSPort_Do53		 53 // See <https://tools.ietf.org/html/rfc1035#section-4.2>.
-#define kDNSPort_DoT		853 // See <https://tools.ietf.org/html/rfc7858#section-3.1>.
-#define kDNSPort_DoH		443 // See <https://tools.ietf.org/html/rfc8484#section-8.1>.
-
-#define kDNSMaxUDPMessageSize		512
-#define kDNSMaxTCPMessageSize		UINT16_MAX
-#define kDNSRecordDataLengthMax		UINT16_MAX
-
-//===========================================================================================================================
-//	mDNS
-//===========================================================================================================================
-
-#define kMDNSPort		5353
-
-#define kDefaultMDNSMessageID		0
-#define kDefaultMDNSQueryFlags		0
-
-// Recommended Resource Record TTL values. See <https://tools.ietf.org/html/rfc6762#section-10>.
-
-#define kMDNSRecordTTL_Host			120		// TTL for resource records related to a host name, e.g., A, AAAA, SRV, etc.
-#define kMDNSRecordTTL_Other		4500	// TTL for other resource records.
-
-// Maximum mDNS Message Size. See <https://tools.ietf.org/html/rfc6762#section-17>.
-
-#define kMDNSMessageSizeMax		8952	// 9000 B (Ethernet jumbo frame max size) - 40 B (IPv6 header) - 8 B (UDP header)
-
-#define kLocalStr			"\x05" "local"
-#define kLocalLabel			( (const uint8_t *) kLocalStr )
-#define kLocalName			( (const uint8_t *) kLocalStr )
-#define kLocalNameLen		sizeof( kLocalStr )
-
-//===========================================================================================================================
-//	Test Address Blocks
-//===========================================================================================================================
-
-// IPv4 address block 203.0.113.0/24 (TEST-NET-3) is reserved for documentation. See <https://tools.ietf.org/html/rfc5737>.
-
-#define kDNSServerBaseAddrV4		UINT32_C( 0xCB007100 )	// 203.0.113.0/24
-
-#define kDNSServerReverseIPv4DomainStr		"113.0.203.in-addr.arpa."
-#define kDNSServerReverseIPv4DomainName \
-	( (const uint8_t *) "\x3" "113" "\x1" "0" "\x3" "203" "\x7" "in-addr" "\x4" "arpa" )
-
-// IPv6 address block 2001:db8::/32 is reserved for documentation. See <https://tools.ietf.org/html/rfc3849>.
-
-static const uint8_t		kDNSServerBaseAddrV6[] =
-{
-	0x20, 0x01, 0x0D, 0xB8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	// 2001:db8:1::/96
-};
-check_compile_time( sizeof( kDNSServerBaseAddrV6 ) == 16 );
-
-#define kDNSServerReverseIPv6DomainStr		"0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."
-#define kDNSServerReverseIPv6DomainName												\
-	( (const uint8_t *) "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0"	\
-	"\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0"	\
-	"\x1" "0" "\x1" "0" "\x1" "0" "\x1" "0" "\x1" "1" "\x1" "0" "\x1" "0" "\x1" "0"	\
-	"\x1" "8" "\x1" "b" "\x1" "d" "\x1" "0" "\x1" "1" "\x1" "0" "\x1" "0" "\x1" "2"	\
-	"\x3" "ip6" "\x4" "arpa" )
-
-static const uint8_t		kMDNSReplierBaseAddrV6[] =
-{
-	0x20, 0x01, 0x0D, 0xB8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	// 2001:db8:2::/96
-};
-check_compile_time( sizeof( kMDNSReplierBaseAddrV6 ) == 16 );
-
-static const uint8_t		kMDNSReplierLinkLocalBaseAddrV6[] =
-{
-	0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	// fe80::/96
-};
-check_compile_time( sizeof( kMDNSReplierLinkLocalBaseAddrV6 ) == 16 );
-
-// Bad IPv4 and IPv6 Address Blocks
-// Used by the DNS server when it needs to respond with intentionally "bad" A/AAAA record data, i.e., IP addresses neither
-// in 203.0.113.0/24 nor 2001:db8:1::/120.
-
-#define kDNSServerBadBaseAddrV4		UINT32_C( 0x00000000 )	// 0.0.0.0/24
-
-static const uint8_t		kDNSServerBadBaseAddrV6[] =
-{
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00	// ::ffff:0:0/120
-};
-check_compile_time( sizeof( kDNSServerBadBaseAddrV6 ) == 16 );
-
-#if( TARGET_OS_DARWIN )
-// IPv6 Unique Local Address for assigning extra randomly-generated IPv6 addresses to the loopback interface.
-// 40-bit Global ID: 0xEDF03555E4 (randomly-generated)
-// 16-bit Subnet ID: 0
-// See <https://tools.ietf.org/html/rfc4193#section-3.1>.
-
-static const uint8_t		kExtraLoopbackIPv6Prefix[] =
-{
-	0xFD, 0xED, 0xF0, 0x35, 0x55, 0xE4, 0x00, 0x00	// fded:f035:55e4::/64
-};
-
-#define kExtraLoopbackIPv6PrefixBitLen		64
-check_compile_time( ( sizeof( kExtraLoopbackIPv6Prefix ) * 8 ) == kExtraLoopbackIPv6PrefixBitLen );
-#endif
-
-//===========================================================================================================================
-//	DNS Server Domains
-//===========================================================================================================================
-
-#define kDNSServerDomain_Default		( (const uint8_t *) "\x01" "d" "\x04" "test" )
-#define kDNSServerDomain_DNSSEC			( (const uint8_t *) "\x06" "dnssec" "\x04" "test" )
-
-//===========================================================================================================================
-//	Misc.
-//===========================================================================================================================
-
-#define kLowerAlphaNumericCharSet			"abcdefghijklmnopqrstuvwxyz0123456789"
-#define kLowerAlphaNumericCharSetSize		sizeof_string( kLowerAlphaNumericCharSet )
-
-#if( !defined( kWhiteSpaceCharSet ) )
-	#define kWhiteSpaceCharSet		"\t\n\v\f\r "
-#endif
-
-#define _RandomStringExact( CHAR_SET, CHAR_SET_SIZE, CHAR_COUNT, OUT_STRING ) \
-	RandomString( CHAR_SET, CHAR_SET_SIZE, CHAR_COUNT, CHAR_COUNT, OUT_STRING )
-
-#define kNoSuchRecordStr			"No Such Record"
-#define kNoSuchRecordAStr			"No Such Record (A)"
-#define kNoSuchRecordAAAAStr		"No Such Record (AAAA)"
-#define kNoSuchNameStr				"No Such Name"
-
-#define kRootLabel		( (const uint8_t *) "" )
-
-#if !defined( nw_forget )
-	#define nw_forget( X )		ForgetCustom( X, nw_release )
-#endif
-
-//===========================================================================================================================
-//	Gerneral Command Options
-//===========================================================================================================================
-
-// Command option macros
-
-#define Command( NAME, CALLBACK, SUB_OPTIONS, SHORT_HELP, IS_NOTCOMMON )											\
-	CLI_COMMAND_EX( NAME, CALLBACK, SUB_OPTIONS, (IS_NOTCOMMON) ? kCLIOptionFlags_NotCommon : kCLIOptionFlags_None,	\
-		(SHORT_HELP), NULL )
-
-#define kRequiredOptionSuffix		" [REQUIRED]"
-
-#define MultiStringOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, VAL_COUNT_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, LONG_HELP )	\
-	CLI_OPTION_MULTI_STRING_EX( SHORT_CHAR, LONG_NAME, VAL_PTR, VAL_COUNT_PTR, ARG_HELP,									\
-		(IS_REQUIRED) ? SHORT_HELP kRequiredOptionSuffix : SHORT_HELP,														\
-		(IS_REQUIRED) ? kCLIOptionFlags_Required : kCLIOptionFlags_None, LONG_HELP )
-
-#define MultiStringOption( SHORT_CHAR, LONG_NAME, VAL_PTR, VAL_COUNT_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED ) \
-		MultiStringOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, VAL_COUNT_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, NULL )
-
-#define IntegerOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, LONG_HELP )	\
-	CLI_OPTION_INTEGER_EX( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP,									\
-		(IS_REQUIRED) ? SHORT_HELP kRequiredOptionSuffix : SHORT_HELP,									\
-		(IS_REQUIRED) ? kCLIOptionFlags_Required : kCLIOptionFlags_None, LONG_HELP )
-
-#define IntegerOption( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED )	\
-	IntegerOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, NULL )
-
-#define DoubleOption( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED )	\
-	CLI_OPTION_DOUBLE_EX( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP,							\
-		(IS_REQUIRED) ? SHORT_HELP kRequiredOptionSuffix : SHORT_HELP,						\
-		(IS_REQUIRED) ? kCLIOptionFlags_Required : kCLIOptionFlags_None, NULL )
-
-#define BooleanOption( SHORT_CHAR, LONG_NAME, VAL_PTR, SHORT_HELP ) \
-	CLI_OPTION_BOOLEAN( (SHORT_CHAR), (LONG_NAME), (VAL_PTR), (SHORT_HELP), NULL )
-
-#define StringOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, LONG_HELP )	\
-	CLI_OPTION_STRING_EX( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP,										\
-		(IS_REQUIRED) ? SHORT_HELP kRequiredOptionSuffix : SHORT_HELP,									\
-		(IS_REQUIRED) ? kCLIOptionFlags_Required : kCLIOptionFlags_None, LONG_HELP )
-
-#define StringOption( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED ) \
-	StringOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED, NULL )
-
-#define CFStringOption( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP, SHORT_HELP, IS_REQUIRED )	\
-	CLI_OPTION_CFSTRING_EX( SHORT_CHAR, LONG_NAME, VAL_PTR, ARG_HELP,						\
-		(IS_REQUIRED) ? SHORT_HELP kRequiredOptionSuffix : SHORT_HELP,						\
-		(IS_REQUIRED) ? kCLIOptionFlags_Required : kCLIOptionFlags_None, NULL )
-
-// DNS-SD API flag options
-
-static int		gDNSSDFlags						= 0;
-static int		gDNSSDFlag_AllowExpiredAnswers	= false;
-static int		gDNSSDFlag_BrowseDomains		= false;
-static int		gDNSSDFlag_DenyCellular			= false;
-static int		gDNSSDFlag_DenyConstrained		= false;
-static int		gDNSSDFlag_DenyExpensive		= false;
-static int		gDNSSDFlag_ForceMulticast		= false;
-static int		gDNSSDFlag_IncludeAWDL			= false;
-static int		gDNSSDFlag_KnownUnique			= false;
-static int		gDNSSDFlag_NoAutoRename			= false;
-static int		gDNSSDFlag_PathEvaluationDone	= false;
-static int		gDNSSDFlag_RegistrationDomains	= false;
-static int		gDNSSDFlag_ReturnIntermediates	= false;
-static int		gDNSSDFlag_Shared				= false;
-static int		gDNSSDFlag_SuppressUnusable		= false;
-static int		gDNSSDFlag_Timeout				= false;
-static int		gDNSSDFlag_UnicastResponse		= false;
-static int		gDNSSDFlag_Unique				= false;
-static int		gDNSSDFlag_WakeOnResolve		= false;
-static int		gDNSSDFlag_EnableDNSSEC			= false;
-
-#define DNSSDFlagsOption()								\
-	IntegerOption( 'f', "flags", &gDNSSDFlags, "flags",	\
-		"DNSServiceFlags as an integer. This value is bitwise ORed with other single flag options.", false )
-
-#define DNSSDFlagOption( SHORT_CHAR, FLAG_NAME ) \
-	BooleanOption( SHORT_CHAR, # FLAG_NAME, &gDNSSDFlag_ ## FLAG_NAME, "Use kDNSServiceFlags" # FLAG_NAME "." )
-
-#define DNSSDFlagsOption_AllowExpiredAnswers()		DNSSDFlagOption( 'X', AllowExpiredAnswers )
-#define DNSSDFlagsOption_DenyCellular()				DNSSDFlagOption( 'C', DenyCellular )
-#define DNSSDFlagsOption_DenyConstrained()			DNSSDFlagOption( 'R', DenyConstrained)
-#define DNSSDFlagsOption_DenyExpensive()			DNSSDFlagOption( 'E', DenyExpensive )
-#define DNSSDFlagsOption_EnableDNSSEC()				DNSSDFlagOption( 'D', EnableDNSSEC )
-#define DNSSDFlagsOption_ForceMulticast()			DNSSDFlagOption( 'M', ForceMulticast )
-#define DNSSDFlagsOption_IncludeAWDL()				DNSSDFlagOption( 'A', IncludeAWDL )
-#define DNSSDFlagsOption_KnownUnique()				DNSSDFlagOption( 'K', KnownUnique )
-#define DNSSDFlagsOption_NoAutoRename()				DNSSDFlagOption( 'N', NoAutoRename )
-#define DNSSDFlagsOption_PathEvalDone()				DNSSDFlagOption( 'P', PathEvaluationDone )
-#define DNSSDFlagsOption_ReturnIntermediates()		DNSSDFlagOption( 'I', ReturnIntermediates )
-#define DNSSDFlagsOption_Shared()					DNSSDFlagOption( 'S', Shared )
-#define DNSSDFlagsOption_SuppressUnusable()			DNSSDFlagOption( 'S', SuppressUnusable )
-#define DNSSDFlagsOption_Timeout()					DNSSDFlagOption( 'T', Timeout )
-#define DNSSDFlagsOption_UnicastResponse()			DNSSDFlagOption( 'U', UnicastResponse )
-#define DNSSDFlagsOption_Unique()					DNSSDFlagOption( 'U', Unique )
-#define DNSSDFlagsOption_WakeOnResolve()			DNSSDFlagOption( 'W', WakeOnResolve )
-
-// Interface option
-
-static const char *		gInterface = NULL;
-
-#define InterfaceOption()										\
-	StringOption( 'i', "interface", &gInterface, "interface",	\
-		"Network interface by name or index. Use index -1 for local-only.", false )
-
-// Connection options
-
-#define kConnectionArg_Normal			""
-#define kConnectionArgPrefix_PID		"pid:"
-#define kConnectionArgPrefix_UUID		"uuid:"
-
-static const char *		gConnectionOpt = kConnectionArg_Normal;
-
-#define ConnectionOptions()																						\
-	{ kCLIOptionType_String, 0, "connection", &gConnectionOpt, NULL, (intptr_t) kConnectionArg_Normal, "type",	\
-		kCLIOptionFlags_OptionalArgument, NULL, NULL, NULL, NULL,												\
-		"Specifies the type of main connection to use. See " kConnectionSection_Name " below.", NULL }
-
-#define kConnectionSection_Name		"Connection Option"
-#define kConnectionSection_Text																							\
-	"The default behavior is to create a main connection with DNSServiceCreateConnection() and perform operations on\n"	\
-	"the main connection using the kDNSServiceFlagsShareConnection flag. This behavior can be explicitly invoked by\n"	\
-	"specifying the connection option without an argument, i.e.,\n"														\
-	"\n"																												\
-	"    --connection\n"																								\
-	"\n"																												\
-	"To instead use a delegate connection created with DNSServiceCreateDelegateConnection(), use\n"						\
-	"\n"																												\
-	"    --connection=pid:<PID>\n"																						\
-	"\n"																												\
-	"to specify the delegator by PID, or use\n"																			\
-	"\n"																												\
-	"    --connection=uuid:<UUID>\n"																					\
-	"\n"																												\
-	"to specify the delegator by UUID.\n"																				\
-	"\n"																												\
-	"To not use a main connection at all, but instead perform operations on their own implicit connections, use\n"		\
-	"\n"																												\
-	"    --no-connection\n"
-
-#define ConnectionSection()		CLI_SECTION( kConnectionSection_Name, kConnectionSection_Text )
-
-// Help text for record data options
-
-#define kRDataArgPrefix_Domain			"domain:"
-#define kRDataArgPrefix_File			"file:"
-#define kRDataArgPrefix_HexString		"hex:"
-#define kRDataArgPrefix_IPv4			"ipv4:"
-#define kRDataArgPrefix_IPv6			"ipv6:"
-#define kRDataArgPrefix_SRV				"srv:"
-#define kRDataArgPrefix_String			"string:"
-#define kRDataArgPrefix_TXT				"txt:"
-
-#define kRecordDataSection_Name		"Record Data Arguments"
-#define kRecordDataSection_Text																							\
-	"A record data argument is specified in one of the following formats:\n"											\
-	"\n"																												\
-	"Format                       Syntax                                   Example\n"									\
-	"Domain name                  domain:<domain name>                     domain:demo._test._tcp.local\n"				\
-	"File containing record data  file:<file path>                         file:/path/to/binary-rdata-file\n"			\
-	"Hexadecimal string           hex:<hex string>                         hex:c0000201 or hex:'C0 00 02 01'\n"		    \
-	"IPv4 address                 ipv4:<IPv4 address>                      ipv4:192.0.2.1\n"							\
-	"IPv6 address                 ipv6:<IPv6 address>                      ipv6:2001:db8::1\n"							\
-	"SRV record                   srv:<priority>,<weight>,<port>,<target>  srv:0,0,64206,example.local\n"				\
-	"String                       string:<string>                          string:'\\x09color=red'\n"					\
-	"TXT record strings           txt:<comma-delimited strings>            txt:'vers=1.0,lang=en\\,es\\,fr,passreq'\n"	\
-	"\n"																												\
-	"Note: The string format converts each \\xHH escape sequence into the octet represented by the HH hex digit pair.\n"
-
-#define RecordDataSection()		CLI_SECTION( kRecordDataSection_Name, kRecordDataSection_Text )
-
-// Fallback DNS service option
-
-#if( MDNSRESPONDER_PROJECT )
-static const char *		gFallbackDNSService = NULL;
-
-#define kFallbackDNSServiceArgPrefix_DoH		"doh:"
-#define kFallbackDNSServiceArgPrefix_DoT		"dot:"
-
-#define FallbackDNSServiceGroup()		CLI_OPTION_GROUP( "Default Fallback DNS Service" )
-#define FallbackDNSServiceOption()																						\
-	StringOptionEx( 0, "fallback", &gFallbackDNSService, "DNS service", "Default fallback DNS service to set.", false,	\
-		"\n"																											\
-		"When this option is used, an nw_resolver_config is created for the specified DoH or DoT service.\n"			\
-		"DNSServiceSetResolverDefaults() is then used to set the DNS service described by nw_resolver_config as the\n"	\
-		"default fallback DNS service for the dnssdutil process.\n"														\
-		"\n"																											\
-		"To specify a DNS over HTTPS (DoH) service, use\n"																\
-		"\n"																											\
-		"    --fallback=doh:<URL>\n"																					\
-		"\n"																											\
-		"Example: --fallback=doh:https://dns.example.com/dns-query\n"													\
-		"\n"																											\
-		"To specify a DNS over TLS (DoT) service, use\n"																\
-		"\n"																											\
-		"    --fallback=dot:<hostname>\n"																				\
-		"\n"																											\
-		"Example: --fallback=dot:dns.example.com\n"																		\
-	)
-#endif
-
-//===========================================================================================================================
-//	Output Formatting
-//===========================================================================================================================
-
-#define kOutputFormatStr_JSON		"json"
-#define kOutputFormatStr_XML		"xml"
-#define kOutputFormatStr_Binary		"binary"
-
-typedef enum
-{
-	kOutputFormatType_Invalid	= 0,
-	kOutputFormatType_JSON		= 1,
-	kOutputFormatType_XML		= 2,
-	kOutputFormatType_Binary	= 3
-	
-}	OutputFormatType;
-
-#define FormatOption( SHORT_CHAR, LONG_NAME, VAL_PTR, SHORT_HELP, IS_REQUIRED )			\
-	StringOptionEx( SHORT_CHAR, LONG_NAME, VAL_PTR, "format", SHORT_HELP, IS_REQUIRED,	\
-		"\n"																			\
-		"Use '" kOutputFormatStr_JSON   "' for JavaScript Object Notation (JSON).\n"	\
-		"Use '" kOutputFormatStr_XML    "' for property list XML version 1.0.\n"		\
-		"Use '" kOutputFormatStr_Binary "' for property list binary version 1.0.\n"		\
-		"\n"																			\
-	)
-
-//===========================================================================================================================
-//	Browse Command Options
-//===========================================================================================================================
-
-static char **			gBrowse_ServiceTypes		= NULL;
-static size_t			gBrowse_ServiceTypesCount	= 0;
-static const char *		gBrowse_Domain				= NULL;
-static int				gBrowse_DoResolve			= false;
-static int				gBrowse_QueryTXT			= false;
-static int				gBrowse_TimeLimitSecs		= 0;
-static int 				gBrowse_ValidateResults		= false;
-static int 				gBrowse_ResolveDelayMs		= 0;
-
-static CLIOption		kBrowseOpts[] =
-{
-	InterfaceOption(),
-	MultiStringOption(	't', "type",	&gBrowse_ServiceTypes, &gBrowse_ServiceTypesCount, "service type", "Service type(s), e.g., \"_ssh._tcp\".", true ),
-	StringOption(		'd', "domain",	&gBrowse_Domain, "domain", "Domain in which to browse for the service type(s).", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	BooleanOption(  0 , "resolve",      &gBrowse_DoResolve,       "Resolve service instances." ),
-	BooleanOption(  0 , "queryTXT",     &gBrowse_QueryTXT,        "Query TXT records of service instances." ),
-	IntegerOption( 'l', "timeLimit",    &gBrowse_TimeLimitSecs,   "seconds", "Specifies the max duration of the browse operation. Use '0' for no time limit.", false ),
-	BooleanOption( 'v', "validate",     &gBrowse_ValidateResults, "Validate results." ),
-	IntegerOption(  0 , "resolveDelay", &gBrowse_ResolveDelayMs,  "ms", "The amount of time to wait before a resolve or TXT query in milliseconds. (default: 0)", false ),
-	
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	GetAddrInfo Command Options
-//===========================================================================================================================
-
-static const char *		gGetAddrInfo_Name			= NULL;
-static int				gGetAddrInfo_ProtocolIPv4	= false;
-static int				gGetAddrInfo_ProtocolIPv6	= false;
-static int				gGetAddrInfo_OneShot		= false;
-static int				gGetAddrInfo_TimeLimitSecs	= 0;
-
-static CLIOption		kGetAddrInfoOpts[] =
-{
-	InterfaceOption(),
-	StringOption(  'n', "name", &gGetAddrInfo_Name,			"domain name", "Domain name to resolve.", true ),
-	BooleanOption(  0 , "ipv4", &gGetAddrInfo_ProtocolIPv4,	"Use kDNSServiceProtocol_IPv4." ),
-	BooleanOption(  0 , "ipv6", &gGetAddrInfo_ProtocolIPv6,	"Use kDNSServiceProtocol_IPv6." ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_AllowExpiredAnswers(),
-	DNSSDFlagsOption_DenyCellular(),
-	DNSSDFlagsOption_DenyConstrained(),
-	DNSSDFlagsOption_DenyExpensive(),
-	DNSSDFlagsOption_EnableDNSSEC(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_PathEvalDone(),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_SuppressUnusable(),
-	DNSSDFlagsOption_Timeout(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	BooleanOption( 'o', "oneshot",		&gGetAddrInfo_OneShot,			"Finish after first set of results." ),
-	IntegerOption( 'l', "timeLimit",	&gGetAddrInfo_TimeLimitSecs,	"seconds", "Maximum duration of the GetAddrInfo operation. Use '0' for no time limit.", false ),
-	
-#if( MDNSRESPONDER_PROJECT )
-	FallbackDNSServiceGroup(),
-	FallbackDNSServiceOption(),
-#endif
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	QueryRecord Command Options
-//===========================================================================================================================
-
-static const char *		gQueryRecord_Name			= NULL;
-static const char *		gQueryRecord_Type			= NULL;
-static int				gQueryRecord_AAAAFallback	= false;
-static int				gQueryRecord_UseFailover	= false;
-static int				gQueryRecord_OneShot		= false;
-static int				gQueryRecord_TimeLimitSecs	= 0;
-static int				gQueryRecord_RawRData		= false;
-
-static CLIOption		kQueryRecordOpts[] =
-{
-	InterfaceOption(),
-	StringOption( 'n', "name", &gQueryRecord_Name, "domain name", "Full domain name of record to query.", true ),
-	StringOption( 't', "type", &gQueryRecord_Type, "record type", "Record type by name (e.g., TXT, SRV, etc.) or number.", true ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_AllowExpiredAnswers(),
-	DNSSDFlagsOption_DenyCellular(),
-	DNSSDFlagsOption_DenyConstrained(),
-	DNSSDFlagsOption_DenyExpensive(),
-	DNSSDFlagsOption_EnableDNSSEC(),
-	DNSSDFlagsOption_ForceMulticast(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_PathEvalDone(),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_SuppressUnusable(),
-	DNSSDFlagsOption_Timeout(),
-	DNSSDFlagsOption_UnicastResponse(),
-	
-	CLI_OPTION_GROUP( "Attributes" ),
-	BooleanOption( 0, "aaaaFallback",	&gQueryRecord_AAAAFallback,		"If a AAAA record doesn't exist, try querying for an A record of the same name and type." ),
-	BooleanOption( 0, "useFailover",	&gQueryRecord_UseFailover,		"Use DNS service failover if necessary and applicable." ),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	BooleanOption( 'o', "oneshot",		&gQueryRecord_OneShot,			"Finish after first set of results." ),
-	IntegerOption( 'l', "timeLimit",	&gQueryRecord_TimeLimitSecs,	"seconds", "Maximum duration of the query record operation. Use '0' for no time limit.", false ),
-	BooleanOption(  0 , "raw",			&gQueryRecord_RawRData,			"Show record data as a hexdump." ),
-	
-#if( MDNSRESPONDER_PROJECT )
-	FallbackDNSServiceGroup(),
-	FallbackDNSServiceOption(),
-#endif	
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Register Command Options
-//===========================================================================================================================
-
-static const char *			gRegister_Name			= NULL;
-static const char *			gRegister_Type			= NULL;
-static const char *			gRegister_Domain		= NULL;
-static int					gRegister_Port			= 0;
-static const char *			gRegister_TXT			= NULL;
-static int					gRegister_LifetimeMs	= -1;
-static const char *			gRegister_TimeOfReceipt	= NULL;
-
-static const char **		gAddRecord_Types		= NULL;
-static size_t				gAddRecord_TypesCount	= 0;
-static const char **		gAddRecord_Data			= NULL;
-static size_t				gAddRecord_DataCount	= 0;
-static const char **		gAddRecord_TTLs			= NULL;
-static size_t				gAddRecord_TTLsCount	= 0;
-
-static const char **		gUpdateRecord_Datas			= NULL;
-static size_t				gUpdateRecord_DataCount		= 0;
-static const char **		gUpdateRecord_DelaysMs		= NULL;
-static size_t				gUpdateRecord_DelayCount	= 0;
-static const char **		gUpdateRecord_TTLs			= NULL;
-static size_t				gUpdateRecord_TTLCount		= 0;
-
-static CLIOption		kRegisterOpts[] =
-{
-	InterfaceOption(),
-	StringOption(  'n', "name",		&gRegister_Name,	"service name",	"Name of service.", false ),
-	StringOption(  't', "type",		&gRegister_Type,	"service type",	"Service type, e.g., \"_ssh._tcp\".", true ),
-	StringOption(  'd', "domain",	&gRegister_Domain,	"domain",		"Domain in which to advertise the service.", false ),
-	IntegerOption( 'p', "port",		&gRegister_Port,	"port number",	"Service's port number.", true ),
-	StringOption(   0 , "txt",		&gRegister_TXT,		"record data",	"The TXT record data. See " kRecordDataSection_Name " below.", false ),
-	
-	CLI_OPTION_GROUP( "Attributes" ),
-	StringOption( 0, "timestamp", &gRegister_TimeOfReceipt, "Unix time", "Time since epoch in seconds to indicate when the service registration request is received, should be used with flag kDNSServiceFlagsNoAutoRename", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_KnownUnique(),
-	DNSSDFlagsOption_NoAutoRename(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	IntegerOption( 'l', "lifetime", &gRegister_LifetimeMs, "ms", "Lifetime of the service registration in milliseconds.", false ),
-	
-	CLI_OPTION_GROUP( "Options for adding extra record(s) to the registered service with DNSServiceAddRecord()\n" ),
-	MultiStringOption(   0, "addType", &gAddRecord_Types, &gAddRecord_TypesCount, "record type", "Type of additional record by name (e.g., TXT, SRV, etc.) or number.", false ),
-	MultiStringOptionEx( 0, "addData", &gAddRecord_Data,  &gAddRecord_DataCount,  "record data", "Additional record's data. See " kRecordDataSection_Name " below.", false, NULL ),
-	MultiStringOption(   0, "addTTL",  &gAddRecord_TTLs,  &gAddRecord_TTLsCount,  "seconds",     "Time-to-live of additional record in seconds. Use '0' for the system default.", false ),
-	
-	CLI_OPTION_GROUP( "Options for updating the service's primary TXT record with DNSServiceUpdateRecord()\n" ),
-	MultiStringOption( 0, "updateData",  &gUpdateRecord_Datas,    &gUpdateRecord_DataCount,  "record data", "Record data for the record update. See " kRecordDataSection_Name " below.", false ),
-	MultiStringOption( 0, "updateDelay", &gUpdateRecord_DelaysMs, &gUpdateRecord_DelayCount, "ms", "Number of milliseconds after registration to wait before the update.", false ),
-	MultiStringOption( 0, "updateTTL",   &gUpdateRecord_TTLs,     &gUpdateRecord_TTLCount,   "seconds", "Time-to-live of the updated record. Use '0' for the system default.", false ),
-	
-	CLI_SECTION( "Rules for multiple extra records",
-		"1. The --addType, --addData, and --addTTL options can be specified more than once to add multiple extra records.\n"
-		"2. The i-th --addType, --addData, and --addTTL options are used for the i-th extra record.\n"
-		"3. The number of --addType options must equal the number of --addData options.\n"
-		"4. The number of --addTTL options must equal the number of --addType options or not be specified at all, in\n"
-		"   which case a TTL of 0 is used for all extra records.\n"
-	),
-	CLI_SECTION( "Rules for multiple primary TXT record updates",
-		"1. The --updateData, --updateDelay, and --updateTTL options can be specified more than once to specify multiple\n"
-		"   primary TXT record updates.\n"
-		"2. The i-th --updateData, --updateDelay, and --updateTTL options are used for the i-th update.\n"
-		"3. The number of --updateData options must equal the number of --updateDelay options.\n"
-		"4. The number of --updateTTL options must equal the number of --updateData options or not be specified at all,\n"
-		"   in which case a TTL of 0 is used for all updates.\n"
-	),
-	RecordDataSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	RegisterRecord Command Options
-//===========================================================================================================================
-
-static const char *		gRegisterRecord_Name			= NULL;
-static const char *		gRegisterRecord_Type			= NULL;
-static const char *		gRegisterRecord_Data			= NULL;
-static int				gRegisterRecord_TTL				= 0;
-static int				gRegisterRecord_LifetimeMs		= -1;
-static const char *		gRegisterRecord_UpdateData		= NULL;
-static int				gRegisterRecord_UpdateDelayMs	= 0;
-static int				gRegisterRecord_UpdateTTL		= 0;
-static const char *		gRegisterRecord_TimeOfReceipt	= NULL;
-
-static CLIOption		kRegisterRecordOpts[] =
-{
-	InterfaceOption(),
-	StringOption( 'n', "name",	&gRegisterRecord_Name,	"record name",	"Fully qualified domain name of record.", true ),
-	StringOption( 't', "type",	&gRegisterRecord_Type,	"record type",	"Record type by name (e.g., TXT, PTR, A) or number.", true ),
-	StringOption( 'd', "data",	&gRegisterRecord_Data,	"record data",	"The record data. See " kRecordDataSection_Name " below.", false ),
-	IntegerOption( 0 , "ttl",	&gRegisterRecord_TTL,	"seconds",		"Time-to-live in seconds. Use '0' for default.", false ),
-	
-	CLI_OPTION_GROUP( "Attributes" ),
-	StringOption( 0, "timestamp", &gRegisterRecord_TimeOfReceipt, "Unix time", "Time since epoch in seconds to indicate when the record registration request is received.", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_ForceMulticast(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_KnownUnique(),
-	DNSSDFlagsOption_Shared(),
-	DNSSDFlagsOption_Unique(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	IntegerOption( 'l', "lifetime", &gRegisterRecord_LifetimeMs, "ms", "Lifetime of the service registration in milliseconds.", false ),
-	
-	CLI_OPTION_GROUP( "Options for updating the registered record with DNSServiceUpdateRecord()\n" ),
-	StringOption(  0 , "updateData",	&gRegisterRecord_UpdateData,	"record data",	"Record data for the record update.", false ),
-	IntegerOption( 0 , "updateDelay",	&gRegisterRecord_UpdateDelayMs,	"ms",			"Number of milliseconds after registration to wait before record update.", false ),
-	IntegerOption( 0 , "updateTTL",		&gRegisterRecord_UpdateTTL,		"seconds",		"Time-to-live of the updated record.", false ),
-	
-	RecordDataSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Resolve Command Options
-//===========================================================================================================================
-
-static char *		gResolve_Name			= NULL;
-static char *		gResolve_Type			= NULL;
-static char *		gResolve_Domain			= NULL;
-static int			gResolve_TimeLimitSecs	= 0;
-
-static CLIOption		kResolveOpts[] =
-{
-	InterfaceOption(),
-	StringOption( 'n', "name",		&gResolve_Name,		"service name", "Name of the service instance to resolve.", true ),
-	StringOption( 't', "type",		&gResolve_Type,		"service type", "Type of the service instance to resolve.", true ),
-	StringOption( 'd', "domain",	&gResolve_Domain,	"domain", "Domain of the service instance to resolve.", true ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_ForceMulticast(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_WakeOnResolve(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	IntegerOption( 'l', "timeLimit", &gResolve_TimeLimitSecs, "seconds", "Maximum duration of the resolve operation. Use '0' for no time limit.", false ),
-	
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Reconfirm Command Options
-//===========================================================================================================================
-
-static const char *		gReconfirmRecord_Name	= NULL;
-static const char *		gReconfirmRecord_Type	= NULL;
-static const char *		gReconfirmRecord_Class	= NULL;
-static const char *		gReconfirmRecord_Data	= NULL;
-
-static CLIOption		kReconfirmOpts[] =
-{
-	InterfaceOption(),
-	StringOption( 'n', "name",	&gReconfirmRecord_Name,		"record name",	"Full name of the record to reconfirm.", true ),
-	StringOption( 't', "type",	&gReconfirmRecord_Type,		"record type",	"Type of the record to reconfirm.", true ),
-	StringOption( 'c', "class",	&gReconfirmRecord_Class,	"record class",	"Class of the record to reconfirm. Default class is IN.", false ),
-	StringOption( 'd', "data",	&gReconfirmRecord_Data,		"record data",	"The record data. See " kRecordDataSection_Name " below.", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	
-	RecordDataSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	getaddrinfo-POSIX Command Options
-//===========================================================================================================================
-
-static const char *		gGAIPOSIX_HostName			= NULL;
-static const char *		gGAIPOSIX_ServName			= NULL;
-static const char *		gGAIPOSIX_Family			= NULL;
-static int				gGAIPOSIXFlag_AddrConfig	= false;
-static int				gGAIPOSIXFlag_All			= false;
-static int				gGAIPOSIXFlag_CanonName		= false;
-static int				gGAIPOSIXFlag_NumericHost	= false;
-static int				gGAIPOSIXFlag_NumericServ	= false;
-static int				gGAIPOSIXFlag_Passive		= false;
-static int				gGAIPOSIXFlag_V4Mapped		= false;
-#if( defined( AI_V4MAPPED_CFG ) )
-static int				gGAIPOSIXFlag_V4MappedCFG	= false;
-#endif
-#if( defined( AI_DEFAULT ) )
-static int				gGAIPOSIXFlag_Default		= false;
-#endif
-#if( defined( AI_UNUSABLE ) )
-static int				gGAIPOSIXFlag_Unusable		= false;
-#endif
-
-static CLIOption		kGetAddrInfoPOSIXOpts[] =
-{
-	StringOption(	'n', "hostname",			&gGAIPOSIX_HostName,		"hostname", "Domain name to resolve or an IPv4 or IPv6 address.", true ),
-	StringOption(	's', "servname",			&gGAIPOSIX_ServName,		"servname", "Port number in decimal or service name from services(5).", false ),
-	
-	CLI_OPTION_GROUP( "Hints" ),
-	StringOptionEx(	'f', "family",				&gGAIPOSIX_Family,			"address family", "Address family to use for hints ai_family field.", false,
-		"\n"
-		"Possible address family values are 'inet' for AF_INET, 'inet6' for AF_INET6, or 'unspec' for AF_UNSPEC. If no\n"
-		"address family is specified, then AF_UNSPEC is used.\n"
-		"\n" ),
-	BooleanOption(   0 , "flag-addrconfig",		&gGAIPOSIXFlag_AddrConfig,	"In hints ai_flags field, set AI_ADDRCONFIG." ),
-	BooleanOption(   0 , "flag-all",			&gGAIPOSIXFlag_All,			"In hints ai_flags field, set AI_ALL." ),
-	BooleanOption(   0 , "flag-canonname",		&gGAIPOSIXFlag_CanonName,	"In hints ai_flags field, set AI_CANONNAME." ),
-	BooleanOption(   0 , "flag-numerichost",	&gGAIPOSIXFlag_NumericHost,	"In hints ai_flags field, set AI_NUMERICHOST." ),
-	BooleanOption(   0 , "flag-numericserv",	&gGAIPOSIXFlag_NumericServ,	"In hints ai_flags field, set AI_NUMERICSERV." ),
-	BooleanOption(   0 , "flag-passive",		&gGAIPOSIXFlag_Passive,		"In hints ai_flags field, set AI_PASSIVE." ),
-	BooleanOption(   0 , "flag-v4mapped",		&gGAIPOSIXFlag_V4Mapped,	"In hints ai_flags field, set AI_V4MAPPED." ),
-#if( defined( AI_V4MAPPED_CFG ) )
-	BooleanOption(   0 , "flag-v4mappedcfg",	&gGAIPOSIXFlag_V4MappedCFG,	"In hints ai_flags field, set AI_V4MAPPED_CFG." ),
-#endif
-#if( defined( AI_DEFAULT ) )
-	BooleanOption(   0 , "flag-default",		&gGAIPOSIXFlag_Default,		"In hints ai_flags field, set AI_DEFAULT." ),
-#endif
-#if( defined( AI_UNUSABLE ) )
-	BooleanOption(   0 , "flag-unusable",		&gGAIPOSIXFlag_Unusable,	"In hints ai_flags field, set AI_UNUSABLE." ),
-#endif
-	
-#if( MDNSRESPONDER_PROJECT )
-	FallbackDNSServiceGroup(),
-	FallbackDNSServiceOption(),
-#endif
-	CLI_SECTION( "Notes", "See getaddrinfo(3) man page for more details.\n" ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	ReverseLookup Command Options
-//===========================================================================================================================
-
-static const char *		gReverseLookup_IPAddr			= NULL;
-static int				gReverseLookup_OneShot			= false;
-static int				gReverseLookup_TimeLimitSecs	= 0;
-
-static CLIOption		kReverseLookupOpts[] =
-{
-	InterfaceOption(),
-	StringOption( 'a', "address", &gReverseLookup_IPAddr, "IP address", "IPv4 or IPv6 address for which to perform a reverse IP lookup.", true ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_ForceMulticast(),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_SuppressUnusable(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	BooleanOption( 'o', "oneshot",		&gReverseLookup_OneShot,		"Finish after first set of results." ),
-	IntegerOption( 'l', "timeLimit",	&gReverseLookup_TimeLimitSecs,	"seconds", "Specifies the max duration of the query record operation. Use '0' for no time limit.", false ),
-	
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	PortMapping Command Options
-//===========================================================================================================================
-
-static int		gPortMapping_ProtocolTCP	= false;
-static int		gPortMapping_ProtocolUDP	= false;
-static int		gPortMapping_InternalPort	= 0;
-static int		gPortMapping_ExternalPort	= 0;
-static int		gPortMapping_TTL			= 0;
-
-static CLIOption		kPortMappingOpts[] =
-{
-	InterfaceOption(),
-	BooleanOption( 0, "tcp",			&gPortMapping_ProtocolTCP,	"Use kDNSServiceProtocol_TCP." ),
-	BooleanOption( 0, "udp",			&gPortMapping_ProtocolUDP,	"Use kDNSServiceProtocol_UDP." ),
-	IntegerOption( 0, "internalPort",	&gPortMapping_InternalPort,	"port number", "Internal port.", false ),
-	IntegerOption( 0, "externalPort",	&gPortMapping_ExternalPort,	"port number", "Requested external port. Use '0' for any external port.", false ),
-	IntegerOption( 0, "ttl",			&gPortMapping_TTL,			"seconds", "Requested TTL (renewal period) in seconds. Use '0' for a default value.", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	
-	ConnectionSection(),
-	CLI_OPTION_END()
-};
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	RegisterKA Command Options
-//===========================================================================================================================
-
-static const char *		gRegisterKA_LocalAddress	= NULL;
-static const char *		gRegisterKA_RemoteAddress	= NULL;
-static int				gRegisterKA_Timeout			= 0;
-
-static CLIOption		kRegisterKA_Opts[] =
-{
-	DNSSDFlagsOption(),
-	StringOption(  'l', "local",   &gRegisterKA_LocalAddress,  "IP addr+port", "TCP connection's local IPv4 or IPv6 address and port pair.", true ),
-	StringOption(  'r', "remote",  &gRegisterKA_RemoteAddress, "IP addr+port", "TCP connection's remote IPv4 or IPv6 address and port pair.", true ),
-	IntegerOption( 't', "timeout", &gRegisterKA_Timeout,       "timeout", "Keepalive record's timeout value, i.e., its 't=' value.", false ),
-	CLI_OPTION_END()
-};
-
-static void	RegisterKACmd( void );
-#endif
-
-//===========================================================================================================================
-//	BrowseAll Command Options
-//===========================================================================================================================
-
-static const char *		gBrowseAll_Domain				= NULL;
-static const char **	gBrowseAll_ServiceTypes			= NULL;
-static size_t			gBrowseAll_ServiceTypesCount	= 0;
-static int				gBrowseAll_BrowseTimeSecs		= 5;
-static int				gBrowseAll_ConnectTimeout		= 0;
-static int 				gBrowseAll_UseNewGAI		 	= false;
-static int 				gBrowseAll_ValidateResults		= false;
-
-static CLIOption		kBrowseAllOpts[] =
-{
-	InterfaceOption(),
-	StringOption(      'd', "domain",    &gBrowseAll_Domain,          "domain", "Domain in which to browse for the service.", false ),
-	MultiStringOption( 't', "type",      &gBrowseAll_ServiceTypes, &gBrowseAll_ServiceTypesCount, "service type", "Service type(s), e.g., \"_ssh._tcp\". All services are browsed for if none is specified.", false ),
-	BooleanOption(      0 , "useNewGAI", &gBrowseAll_UseNewGAI,       "Use dnssd_getaddrinfo_* instead of DNSServiceGetAddrInfo()." ),
-	BooleanOption(     'v', "validate",  &gBrowseAll_ValidateResults, "Validate results." ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption_IncludeAWDL(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	IntegerOption( 'b', "browseTime",     &gBrowseAll_BrowseTimeSecs, "seconds", "Amount of time to spend browsing in seconds. (default: 5)", false ),
-	IntegerOption( 'c', "connectTimeout", &gBrowseAll_ConnectTimeout, "seconds", "Timeout for connection attempts. If <= 0, no connections are attempted. (default: 0)", false ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	GetNameInfo Command Options
-//===========================================================================================================================
-
-static void	GetNameInfoCmd( void );
-
-static char *		gGetNameInfo_IPAddress			= NULL;
-static int			gGetNameInfoFlag_DGram			= false;
-static int			gGetNameInfoFlag_NameReqd		= false;
-static int			gGetNameInfoFlag_NoFQDN			= false;
-static int			gGetNameInfoFlag_NumericHost	= false;
-static int			gGetNameInfoFlag_NumericScope	= false;
-static int			gGetNameInfoFlag_NumericServ	= false;
-
-static CLIOption		kGetNameInfoOpts[] =
-{
-	StringOption( 'a', "address",           &gGetNameInfo_IPAddress,        "IP address", "IPv4 or IPv6 address to use in sockaddr structure.", true ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	BooleanOption( 0 , "flag-dgram",        &gGetNameInfoFlag_DGram,        "Use NI_DGRAM flag." ),
-	BooleanOption( 0 , "flag-namereqd",     &gGetNameInfoFlag_NameReqd,     "Use NI_NAMEREQD flag." ),
-	BooleanOption( 0 , "flag-nofqdn",       &gGetNameInfoFlag_NoFQDN,       "Use NI_NOFQDN flag." ),
-	BooleanOption( 0 , "flag-numerichost",  &gGetNameInfoFlag_NumericHost,  "Use NI_NUMERICHOST flag." ),
-	BooleanOption( 0 , "flag-numericscope", &gGetNameInfoFlag_NumericScope, "Use NI_NUMERICSCOPE flag." ),
-	BooleanOption( 0 , "flag-numericserv",  &gGetNameInfoFlag_NumericServ,  "Use NI_NUMERICSERV flag." ),
-	
-	CLI_SECTION( "Notes", "See getnameinfo(3) man page for more details.\n" ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	GetAddrInfoStress Command Options
-//===========================================================================================================================
-
-static int		gGAIStress_TestDurationSecs	= 0;
-static int		gGAIStress_ConnectionCount	= 0;
-static int		gGAIStress_DurationMinMs	= 0;
-static int		gGAIStress_DurationMaxMs	= 0;
-static int		gGAIStress_RequestCountMax	= 0;
-
-static CLIOption		kGetAddrInfoStressOpts[] =
-{
-	InterfaceOption(),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_SuppressUnusable(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	IntegerOption( 0, "testDuration",			&gGAIStress_TestDurationSecs,	"seconds",	"Stress test duration in seconds. Use '0' for forever.", false ),
-	IntegerOption( 0, "connectionCount",		&gGAIStress_ConnectionCount,	"integer",	"Number of simultaneous DNS-SD connections.", true ),
-	IntegerOption( 0, "requestDurationMin",		&gGAIStress_DurationMinMs,		"ms",		"Minimum duration of DNSServiceGetAddrInfo() request in milliseconds.", true ),
-	IntegerOption( 0, "requestDurationMax",		&gGAIStress_DurationMaxMs,		"ms",		"Maximum duration of DNSServiceGetAddrInfo() request in milliseconds.", true ),
-	IntegerOption( 0, "consecutiveRequestMax",	&gGAIStress_RequestCountMax,	"integer",	"Maximum number of requests on a connection before restarting it.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	DNSQuery Command Options
-//===========================================================================================================================
-
-static char *		gDNSQuery_Name				= NULL;
-static char *		gDNSQuery_Type				= "A";
-static char *		gDNSQuery_Server			= NULL;
-static int			gDNSQuery_TimeLimitSecs		= 5;
-static int			gDNSQuery_UseTCP			= false;
-static int			gDNSQuery_Flags				= kDNSHeaderFlag_RecursionDesired;
-static int			gDNSQuery_DNSSEC			= false;
-static int			gDNSQuery_CheckingDisabled	= false;
-static int			gDNSQuery_RawRData			= false;
-static int			gDNSQuery_Verbose			= false;
-
-#if( TARGET_OS_DARWIN )
-	#define kDNSQueryServerOptionIsRequired		false
-#else
-	#define kDNSQueryServerOptionIsRequired		true
-#endif
-
-static CLIOption		kDNSQueryOpts[] =
-{
-	StringOption(  'n', "name",             &gDNSQuery_Name,             "name", "Question name (QNAME) to put in DNS query message.", true ),
-	StringOption(  't', "type",             &gDNSQuery_Type,             "type", "Question type (QTYPE) to put in DNS query message. (default: A)", false ),
-	StringOption(  's', "server",           &gDNSQuery_Server,           "IP address", "DNS server's IPv4 or IPv6 address.", kDNSQueryServerOptionIsRequired ),
-	IntegerOption( 'l', "timeLimit",        &gDNSQuery_TimeLimitSecs,    "seconds", "Specifies query time limit. Use '-1' for no limit and '0' to exit immediately after sending.", false ),
-	BooleanOption(  0 , "tcp",              &gDNSQuery_UseTCP,           "Send the DNS query via TCP instead of UDP." ),
-	IntegerOption( 'f', "flags",            &gDNSQuery_Flags,            "flags", "16-bit value for DNS header flags/codes field. (default: 0x0100 [Recursion Desired])", false ),
-	BooleanOption(  0 , "dnssec",           &gDNSQuery_DNSSEC,           "Set the AD bit and include OPT record with DO extended flag bit set." ),
-	BooleanOption(  0 , "checkingDisabled", &gDNSQuery_CheckingDisabled, "Set the Checking Disabled (CD) bit." ),
-	BooleanOption(  0 , "raw",              &gDNSQuery_RawRData,         "Present record data as a hexdump." ),
-	BooleanOption( 'v', "verbose",          &gDNSQuery_Verbose,          "Prints the DNS message to be sent to the server." ),
-	CLI_OPTION_END()
-};
-
-#if( DNSSDUTIL_INCLUDE_DNSCRYPT )
-//===========================================================================================================================
-//	DNSCrypt Command Options
-//===========================================================================================================================
-
-static char *		gDNSCrypt_ProviderName	= NULL;
-static char *		gDNSCrypt_ProviderKey	= NULL;
-static char *		gDNSCrypt_Name			= NULL;
-static char *		gDNSCrypt_Type			= NULL;
-static char *		gDNSCrypt_Server		= NULL;
-static int			gDNSCrypt_TimeLimitSecs	= 5;
-static int			gDNSCrypt_RawRData		= false;
-static int			gDNSCrypt_Verbose		= false;
-
-static CLIOption		kDNSCryptOpts[] =
-{
-	StringOption(  'p', "providerName",	&gDNSCrypt_ProviderName,	"name", "The DNSCrypt provider name.", true ),
-	StringOption(  'k', "providerKey",	&gDNSCrypt_ProviderKey,		"hex string", "The DNSCrypt provider's public signing key.", true ),
-	StringOption(  'n', "name",			&gDNSCrypt_Name,			"name",	"Question name (QNAME) to put in DNS query message.", true ),
-	StringOption(  't', "type",			&gDNSCrypt_Type,			"type",	"Question type (QTYPE) to put in DNS query message.", true ),
-	StringOption(  's', "server",		&gDNSCrypt_Server,			"IP address", "DNS server's IPv4 or IPv6 address.", true ),
-	IntegerOption( 'l', "timeLimit",	&gDNSCrypt_TimeLimitSecs,	"seconds", "Specifies query time limit. Use '-1' for no time limit and '0' to exit immediately after sending.", false ),
-	BooleanOption(  0 , "raw",			&gDNSCrypt_RawRData,		"Present record data as a hexdump." ),
-	BooleanOption( 'v', "verbose",		&gDNSCrypt_Verbose,			"Prints the DNS message to be sent to the server." ),
-	CLI_OPTION_END()
-};
-#endif
-
-//===========================================================================================================================
-//	MDNSQuery Command Options
-//===========================================================================================================================
-
-static char *		gMDNSQuery_Name			= NULL;
-static char *		gMDNSQuery_Type			= NULL;
-static int			gMDNSQuery_SourcePort	= 0;
-static int			gMDNSQuery_IsQU			= false;
-static int			gMDNSQuery_RawRData		= false;
-static int			gMDNSQuery_UseIPv4		= false;
-static int			gMDNSQuery_UseIPv6		= false;
-static int			gMDNSQuery_AllResponses	= false;
-static int			gMDNSQuery_ReceiveSecs	= 1;
-
-static CLIOption		kMDNSQueryOpts[] =
-{
-	StringOption(  'i', "interface",	&gInterface,				"name or index", "Network interface by name or index.", true ),
-	StringOption(  'n', "name",			&gMDNSQuery_Name,			"name", "Question name (QNAME) to put in mDNS message.", true ),
-	StringOption(  't', "type",			&gMDNSQuery_Type,			"type", "Question type (QTYPE) to put in mDNS message.", true ),
-	IntegerOption( 'p', "sourcePort",	&gMDNSQuery_SourcePort,		"port number", "UDP source port to use when sending mDNS messages. Default is 5353 for QM questions.", false ),
-	BooleanOption( 'u', "QU",			&gMDNSQuery_IsQU,			"Set the unicast-response bit, i.e., send a QU question." ),
-	BooleanOption(  0 , "raw",			&gMDNSQuery_RawRData,		"Present record data as a hexdump." ),
-	BooleanOption(  0 , "ipv4",			&gMDNSQuery_UseIPv4,		"Use IPv4." ),
-	BooleanOption(  0 , "ipv6",			&gMDNSQuery_UseIPv6,		"Use IPv6." ),
-	BooleanOption( 'a', "allResponses",	&gMDNSQuery_AllResponses,	"Print all received mDNS messages, not just those containing answers." ),
-	IntegerOption( 'r', "receiveTime",	&gMDNSQuery_ReceiveSecs,	"seconds", "Amount of time to spend receiving messages after the query is sent. The default is one second. Use -1 for unlimited time.", false ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	MDNSCollider Command Options
-//===========================================================================================================================
-
-#define kMDNSColliderProgramSection_Intro																				\
-	"Programs dictate when the collider sends out unsolicited response messages for its record and how the collider\n"	\
-	"ought to react to probe queries that match its record's name, if at all.\n"										\
-	"\n"																												\
-	"For example, suppose that the goal is to cause a specific unique record in the verified state to be renamed.\n"	\
-	"The collider should be invoked such that its record's name is equal to that of the record being targeted. Also,\n"	\
-	"the record's type and data should be such that no record with that name, type, and data combination currently\n"	\
-	"exists. If the mDNS responder that owns the record follows sections 8.1 and 9 of RFC 6762, then the goal can be\n"	\
-	"accomplished with the following program:\n"																		\
-	"\n"																												\
-	"    probes 3r; send; wait 5000\n"																					\
-	"\n"																												\
-	"The first command, 'probes 3r', tells the collider to respond to the next three probe queries that match its\n"	\
-	"record's name. The second command, makes the collider send an unsolicited response message that contains its\n"	\
-	"record in the answer section. The third command makes the collider wait for five seconds before exiting, which\n"	\
-	"is more than enough time for the collider to respond to probe queries.\n"											\
-	"\n"																												\
-	"The send command will cause the targeted record to go into the probing state per section 9 since the collider's\n"	\
-	"record conflicts with target record. Per the probes command, the subsequent probe query sent during the probing\n"	\
-	"state will be answered by the collider, which will cause the record to be renamed per section 8.1.\n"
-
-#define kMDNSColliderProgramSection_Probes																				\
-	"The probes command defines how the collider ought to react to probe queries that match its record's name.\n"		\
-	"\n"																												\
-	"Usage: probes [<action-string>]\n"																					\
-	"\n"																												\
-	"The syntax for an action-string is\n"																				\
-	"\n"																												\
-	"    <action-string> ::= <action> | <action-string> \"-\" <action>\n"												\
-	"    <action>        ::= [<repeat-count>] <action-code>\n"															\
-	"    <repeat-count>  ::= \"1\" | \"2\" | ... | \"10\"\n"															\
-	"    <action-code>   ::= \"n\" | \"r\" | \"u\" | \"m\" | \"p\"\n"													\
-	"\n"																												\
-	"An expanded action-string is defined as\n"																			\
-	"\n"																												\
-	"    <expanded-action-string> ::= <action-code> | <expanded-action-string> \"-\" <action-code>\n"					\
-	"\n"																												\
-	"The action-string argument is converted into an expanded-action-string by expanding each action with a\n"			\
-	"repeat-count into an expanded-action-string consisting of exactly <repeat-count> <action-code>s. For example,\n"	\
-	"2n-r expands to n-n-r. Action-strings that expand to expanded-action-strings with more than 10 action-codes\n"		\
-	"are not allowed.\n"																								\
-	"\n"																												\
-	"When the probes command is executed, it does two things. Firstly, it resets to zero the collider's count of\n"		\
-	"probe queries that match its record's name. Secondly, it defines how the collider ought to react to such probe\n"	\
-	"queries based on the action-string argument. Specifically, the nth action-code in the expanded version of the\n"	\
-	"action-string argument defines how the collider ought to react to the nth received probe query:\n"					\
-	"\n"																												\
-	"    Code  Action\n"																								\
-	"    ----  ------\n"																								\
-	"    n     Do nothing.\n"																							\
-	"    r     Respond to the probe query.\n"																			\
-	"    u     Respond to the probe query via unicast.\n"																\
-	"    m     Respond to the probe query via multicast.\n"																\
-	"    p     Multicast own probe query. (Useful for causing simultaneous probe scenarios.)\n"							\
-	"\n"																												\
-	"Note: If no action is defined for a received probe query, then the collider does nothing, i.e., it doesn't send\n"	\
-	"a response nor does it multicast its own probe query.\n"
-
-#define kMDNSColliderProgramSection_Send																				\
-	"The send command multicasts an unsolicited mDNS response containing the collider's record in the answer\n"			\
-	"section, which can be used to force unique records with the same record name into the probing state.\n"			\
-	"\n"																												\
-	"Usage: send\n"
-
-#define kMDNSColliderProgramSection_Wait																				\
-	"The wait command pauses program execution for the interval of time specified by its argument.\n"					\
-	"\n"																												\
-	"Usage: wait <milliseconds>\n"
-
-#define kMDNSColliderProgramSection_Loop																				\
-	"The loop command starts a counting loop. The done statement marks the end of the loop body. The loop command's\n"	\
-	"argument specifies the number of loop iterations. Note: Loop nesting is supported up to a depth of 16.\n"			\
-	"\n"																												\
-	"Usage: loop <non-zero count>; ... ; done\n"																		\
-	"\n"																												\
-	"For example, the following program sends three unsolicited responses at an approximate rate of one per second:\n"	\
-	"\n"																												\
-	"    loop 3; wait 1000; send; done"
-
-#define ConnectionSection()		CLI_SECTION( kConnectionSection_Name, kConnectionSection_Text )
-
-static const char *		gMDNSCollider_Name			= NULL;
-static const char *		gMDNSCollider_Type			= NULL;
-static const char *		gMDNSCollider_RecordData	= NULL;
-static int				gMDNSCollider_UseIPv4		= false;
-static int				gMDNSCollider_UseIPv6		= false;
-static const char *		gMDNSCollider_Program		= NULL;
-
-static CLIOption		kMDNSColliderOpts[] =
-{
-	StringOption(  'i', "interface", &gInterface,               "name or index", "Network interface by name or index.", true ),
-	StringOption(  'n', "name",      &gMDNSCollider_Name,       "name", "Collider's record name.", true ),
-	StringOption(  't', "type",      &gMDNSCollider_Type,       "type", "Collider's record type.", true ),
-	StringOption(  'd', "data",      &gMDNSCollider_RecordData, "record data", "Collider's record data. See " kRecordDataSection_Name " below.", true ),
-	StringOption(  'p', "program",   &gMDNSCollider_Program,    "program", "Program to execute. See Program section below.", true ),
-	BooleanOption(  0 , "ipv4",      &gMDNSCollider_UseIPv4,    "Use IPv4." ),
-	BooleanOption(  0 , "ipv6",      &gMDNSCollider_UseIPv6,    "Use IPv6." ),
-	
-	RecordDataSection(),
-	CLI_SECTION( "Program",					kMDNSColliderProgramSection_Intro ),
-	CLI_SECTION( "Program Command: probes",	kMDNSColliderProgramSection_Probes ),
-	CLI_SECTION( "Program Command: send",	kMDNSColliderProgramSection_Send ),
-	CLI_SECTION( "Program Command: wait",	kMDNSColliderProgramSection_Wait ),
-	CLI_SECTION( "Program Command: loop",	kMDNSColliderProgramSection_Loop ),
-	CLI_OPTION_END()
-};
-
-static void	MDNSColliderCmd( void );
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	PIDToUUID Command Options
-//===========================================================================================================================
-
-static int		gPIDToUUID_PID = 0;
-
-static CLIOption		kPIDToUUIDOpts[] =
-{
-	IntegerOption( 'p', "pid", &gPIDToUUID_PID, "PID", "Process ID.", true ),
-	CLI_OPTION_END()
-};
-#endif
-
-//===========================================================================================================================
-//	DNSServer Command Options
-//===========================================================================================================================
-
-static const char		kDNSServerInfoText_Intro[] =
-	"The DNS server answers certain queries in the d.test. domain. Responses are dynamically generated based on the\n"
-	"presence of special labels in the query's QNAME. There are currently nine types of special labels that can be\n"
-	"used to generate specific responses: Alias labels, Alias-TTL labels, Count labels, Tag labels, TTL labels, the\n"
-	"IPv4 label, the IPv6 label, Index labels, and SRV labels.\n"
-	"\n"
-	"Note: Sub-strings representing integers in domain name labels are in decimal notation and without leading zeros.\n";
-
-static const char		kDNSServerInfoText_NameExistence[] =
-	"A name is considered to exist if it's an Address name or an SRV name.\n"
-	"\n"
-	"An Address name is defined as a name that ends with d.test., and the other labels, if any, and in no particular\n"
-	"order, unless otherwise noted, consist of\n"
-	"\n"
-	"    1. at most one Alias or Alias-TTL label as the first label;\n"
-	"    2. at most one Count label;\n"
-	"    3. zero or more Tag labels;\n"
-	"    4. at most one TTL label; and\n"
-	"    5. at most one IPv4 or IPv6 label.\n"
-	"    6. at most one Index label.\n"
-	"\n"
-	"An SRV name is defined as a name with the following form:\n"
-	"\n"
-	" _<service>._<proto>[.<parent domain>][.<SRV label 1>[.<target 1>][.<SRV label 2>[.<target 2>][...]]].d.test.\n"
-	"\n"
-	"See \"SRV Names\" for details.\n";
-
-static const char		kDNSServerInfoText_ResourceRecords[] =
-	"Currently, the server only supports CNAME, A, AAAA, and SRV records.\n"
-	"\n"
-	"Address names that begin with an Alias or Alias-TTL label are aliases of canonical names, i.e., they're the\n"
-	"names of CNAME records. See \"Alias Labels\" and \"Alias-TTL Labels\" for details.\n"
-	"\n"
-	"A canonical Address name can exclusively be the name of one or more A records, can exclusively be the name or\n"
-	"one or more AAAA records, or can be the name of both A and AAAA records. Address names that contain an IPv4\n"
-	"label have at least one A record, but no AAAA records. Address names that contain an IPv6 label, have at least\n"
-	"one AAAA record, but no A records. All other Address names have at least one A record and at least one AAAA\n"
-	"record. See \"Count Labels\" for how the number of address records for a given Address name is determined.\n"
-	"\n"
-	"A records contain IPv4 addresses in the 203.0.113.0/24 block, while AAAA records contain IPv6 addresses in the\n"
-	"2001:db8:1::/120 block. Both of these address blocks are reserved for documentation. See\n"
-	"<https://tools.ietf.org/html/rfc5737> and <https://tools.ietf.org/html/rfc3849>.\n"
-	"\n"
-	"SRV names are names of SRV records.\n"
-	"\n"
-	"Unless otherwise specified, all resource records will use a default TTL. The default TTL can be set with the\n"
-	"--defaultTTL option. See \"Alias-TTL Labels\" and \"TTL Labels\" for details on how to query for CNAME, A, and\n"
-	"AAAA records with specific TTL values.\n";
-
-static const char		kDNSServerInfoText_AliasLabel[] =
-	"Alias labels are of the form \"alias\" or \"alias-N\", where N is an integer in [2, 2^31 - 1].\n"
-	"\n"
-	"If QNAME is an Address name and its first label is Alias label \"alias-N\", then the response will contain\n"
-	"exactly N CNAME records:\n"
-	"\n"
-	"    1. For each i in [3, N], the response will contain a CNAME record whose name is identical to QNAME, except\n"
-	"       that the first label is \"alias-i\" instead, and whose RDATA is the name of the other CNAME record whose\n"
-	"       name has \"alias-(i - 1)\" as its first label.\n"
-	"\n"
-	"    2. The response will contain a CNAME record whose name is identical to QNAME, except that the first label\n"
-	"       is \"alias-2\" instead, and whose RDATA is the name identical to QNAME, except that the first label is\n"
-	"       \"alias\" instead.\n"
-	"\n"
-	"    3. The response will contain a CNAME record whose name is identical to QNAME, except that the first label\n"
-	"       is \"alias\" instead, and whose RDATA is the name identical to QNAME minus its first label.\n"
-	"\n"
-	"If QNAME is an Address name and its first label is Alias label \"alias\", then the response will contain a\n"
-	"single CNAME record. The CNAME record's name will be equal to QNAME and its RDATA will be the name identical to\n"
-	"QNAME minus its first label.\n"
-	"\n"
-	"Example. A response to a query with a QNAME of alias-3.count-5.d.test will contain the following CNAME\n"
-	"records:\n"
-	"\n"
-	"    alias-4.count-5.d.test.                        60    IN CNAME alias-3.count-5.d.test.\n"
-	"    alias-3.count-5.d.test.                        60    IN CNAME alias-2.count-5.d.test.\n"
-	"    alias-2.count-5.d.test.                        60    IN CNAME alias.count-5.d.test.\n"
-	"    alias.count-5.d.test.                          60    IN CNAME count-5.d.test.\n";
-
-static const char		kDNSServerInfoText_AliasTTLLabel[] =
-	"Alias-TTL labels are of the form \"alias-ttl-T_1[-T_2[...-T_N]]\", where each T_i is an integer in\n"
-	"[0, 2^31 - 1] and N is a positive integer bounded by the size of the maximum legal label length (63 octets).\n"
-	"\n"
-	"If QNAME is an Address name and its first label is Alias-TTL label \"alias-ttl-T_1...-T_N\", then the response\n"
-	"will contain exactly N CNAME records:\n"
-	"\n"
-	"    1. For each i in [1, N - 1], the response will contain a CNAME record whose name is identical to QNAME,\n"
-	"       except that the first label is \"alias-ttl-T_i...-T_N\" instead, whose TTL value is T_i, and whose RDATA\n"
-	"       is the name of the other CNAME record whose name has \"alias-ttl-T_(i+1)...-T_N\" as its first label.\n"
-	"\n"
-	"    2. The response will contain a CNAME record whose name is identical to QNAME, except that the first label\n"
-	"       is \"alias-ttl-T_N\", whose TTL is T_N, and whose RDATA is identical to QNAME stripped of its first\n"
-	"       label.\n"
-	"\n"
-	"Example. A response to a query with a QNAME of alias-ttl-20-40-80.count-5.d.test will contain the following\n"
-	"CNAME records:\n"
-	"\n"
-	"    alias-ttl-20-40-80.count-5.d.test.             20    IN CNAME alias-ttl-40-80.count-5.d.test.\n"
-	"    alias-ttl-40-80.count-5.d.test.                40    IN CNAME alias-ttl-80.count-5.d.test.\n"
-	"    alias-ttl-80.count-5.d.test.                   80    IN CNAME count-5.d.test.\n";
-
-static const char		kDNSServerInfoText_CountLabel[] =
-	"Count labels are of the form \"count-N_1\" or \"count-N_1-N_2\", where N_1 is an integer in [0, 255] and N_2 is\n"
-	"an integer in [N_1, 255].\n"
-	"\n"
-	"If QNAME is an Address name, contains Count label \"count-N\", and has the type of address records specified by\n"
-	"QTYPE, then the response will contain exactly N address records:\n"
-	"\n"
-	"    1. For i in [1, N], the response will contain an address record of type QTYPE whose name is equal to QNAME\n"
-	"       and whose RDATA is an address equal to a constant base address + i.\n"
-	"\n"
-	"    2. The address records will be ordered by the address contained in RDATA in ascending order.\n"
-	"\n"
-	"Example. A response to an A record query with a QNAME of alias.count-3.d.test will contain the following A\n"
-	"records:\n"
-	"\n"
-	"    count-3.d.test.                                60    IN A     203.0.113.1\n"
-	"    count-3.d.test.                                60    IN A     203.0.113.2\n"
-	"    count-3.d.test.                                60    IN A     203.0.113.3\n"
-	"\n"
-	"If QNAME is an Address name, contains Count label \"count-N_1-N_2\", and has the type of address records\n"
-	"specified by QTYPE, then the response will contain exactly N_1 address records:\n"
-	"\n"
-	"    1. Each of the address records will be of type QTYPE, have name equal to QNAME, and have as its RDATA a\n"
-	"       unique address equal to a constant base address + i, where i is a randomly chosen integer in [1, N_2].\n"
-	"\n"
-	"    2. The order of the address records will be random.\n"
-	"\n"
-	"Example. A response to a AAAA record query with a QNAME of count-3-100.ttl-20.d.test could contain the\n"
-	"following AAAA records:\n"
-	"\n"
-	"    count-3-100.ttl-20.d.test.                     20    IN AAAA  2001:db8:1::c\n"
-	"    count-3-100.ttl-20.d.test.                     20    IN AAAA  2001:db8:1::3a\n"
-	"    count-3-100.ttl-20.d.test.                     20    IN AAAA  2001:db8:1::4f\n"
-	"\n"
-	"If QNAME is an Address name, but doesn't have the type of address records specified by QTYPE, then the response\n"
-	"will contain no address records, regardless of whether it contains a Count label.\n"
-	"\n"
-	"Address names that don't have a Count label are treated as though they contain a count label equal to\n"
-	"count-1\".\n";
-
-static const char		kDNSServerInfoText_TagLabel[] =
-	"Tag labels are labels prefixed with \"tag-\" and contain zero or more arbitrary octets after the prefix.\n"
-	"\n"
-	"This type of label exists to allow testers to \"uniquify\" domain names. Tag labels can also serve as padding\n"
-	"to increase the sizes of domain names.\n";
-
-static const char		kDNSServerInfoText_TTLLabel[] =
-	"TTL labels are of the form \"ttl-T\", where T is an integer in [0, 2^31 - 1].\n"
-	"\n"
-	"If QNAME is an Address name and contains TTL label \"ttl-T\", then all non-CNAME records contained in the\n"
-	"response will have a TTL value equal to T.\n";
-
-static const char		kDNSServerInfoText_IPv4Label[] =
-	"The IPv4 label is \"ipv4\". See \"Resource Records\" for the affect of this label.\n";
-
-static const char		kDNSServerInfoText_IPv6Label[] =
-	"The IPv6 label is \"ipv6\". See \"Resource Records\" for the affect of this label.\n";
-
-static const char		kDNSServerInfoText_IndexLabel[] =
-	"Index labels are of the form \"index-N\", where N is an integer in [1, 2^31 - 1].\n"
-	"\n"
-	"When the server runs in loopback-only mode, each of the server's addresses is assigned a sequential index value\n"
-	"starting from 1. For example, if the server is running in loopback-only mode and listening exclusively on IPv6\n"
-	"with two extra IPv6 addresses, then address ::1 would be assigned index 1, the first extra IPv6 address would be\n"
-	"assigned index 2, and the second extra IPv6 address would be assigned index 3.\n"
-	"\n"
-	"If QNAME is an Address name and has an index label, then the query will be ignored unless the query was received\n"
-	"on an address whose index value equals that of the index label. This is useful for simulating unresponsive servers.\n";
-
-static const char		kDNSServerInfoText_SRVNames[] =
-	"SRV labels are of the form \"srv-R-W-P\", where R, W, and P are integers in [0, 2^16 - 1].\n"
-	"\n"
-	"After the first two labels, i.e., the service and protocol labels, the sequence of labels, which may be empty,\n"
-	"leading up to the the first SRV label, if one exists, or the d.test. labels will be used as a parent domain for\n"
-	"the target hostname of each of the SRV name's SRV records.\n"
-	"\n"
-	"If QNAME is an SRV name and QTYPE is SRV, then for each SRV label, the response will contain an SRV record with\n"
-	"priority R, weight W, port P, and target hostname <target>[.<parent domain>]., where <target> is the sequence\n"
-	"of labels, which may be empty, that follows the SRV label leading up to either the next SRV label or the\n"
-	"d.test. labels, whichever comes first.\n"
-	"\n"
-	"Example. A response to an SRV record query with a QNAME of\n"
-	"_http._tcp.example.com.srv-0-0-80.www.srv-1-0-8080.www.d.test. will contain the following SRV records:\n"
-	"\n"
-	"_http._tcp.example.com.srv-0-0-80.www.srv-1-0-8080.www.d.test.     60    IN SRV   0 0 80 www.example.com.\n"
-	"_http._tcp.example.com.srv-0-0-80.www.srv-1-0-8080.www.d.test.     60    IN SRV   1 0 8080 www.example.com.\n";
-
-static const char		kDNSServerInfoText_BadUDPMode[] =
-	"The purpose of Bad UDP mode is to test mDNSResponder's TCP fallback mechanism by which mDNSResponder reissues a\n"
-	"UDP query as a TCP query if the UDP response contains the expected QNAME, QTYPE, and QCLASS, but a message ID\n"
-	"that's not equal to the query's message ID.\n"
-	"\n"
-	"This mode is identical to the normal mode except that all responses sent via UDP have a message ID equal to the\n"
-	"query's message ID plus one. Also, in this mode, to aid in debugging, A records in responses sent via UDP have\n"
-	"IPv4 addresses in the 0.0.0.0/24 block instead of the 203.0.113.0/24 block, i.e., 0.0.0.0 is used as the IPv4\n"
-	"base address, and AAAA records in responses sent via UDP have IPv6 addresses in the ::ffff:0:0/120 block\n"
-	"instead of the 2001:db8:1::/120 block, i.e., ::ffff:0:0 is used as the IPv6 base address.\n";
-
-typedef enum
-{
-	kDNSProtocol_Do53	= 0,
-	kDNSProtocol_DoT	= 1,
-	kDNSProtocol_DoH	= 2
-	
-}	DNSProtocol;
-
-#define kDNSProtocolStr_Do53		"Do53"
-#define kDNSProtocolStr_DoT			"DoT"
-#define kDNSProtocolStr_DoH			"DoH"
-
-static int				gDNSServer_LoopbackOnly			= false;
-static int				gDNSServer_Foreground			= false;
-static int				gDNSServer_ResponseDelayMs		= 0;
-static int				gDNSServer_DefaultTTL			= 60;
-static int				gDNSServer_Port					= -1;
-static const char *		gDNSServer_DomainOverride		= NULL;
-static char **			gDNSServer_IgnoredQTypes		= NULL;
-static size_t			gDNSServer_IgnoredQTypesCount	= 0;
-static int				gDNSServer_ListenOnV4			= false;
-static int				gDNSServer_ListenOnV6			= false;
-static int				gDNSServer_BadUDPMode			= false;
-static const char *		gDNSServer_FollowPID			= NULL;
-static int				gDNSServer_ExtraV6Count			= 0;
-static const char *		gDNSServer_Protocol				= kDNSProtocolStr_Do53;
-
-static CLIOption		kDNSServerOpts[] =
-{
-	BooleanOption(     'l', "loopback",      &gDNSServer_LoopbackOnly,    "Bind only to the loopback interface." ),
-	BooleanOption(     'f', "foreground",    &gDNSServer_Foreground,      "Direct log output to stdout instead of system logging." ),
-	IntegerOption(     'd', "responseDelay", &gDNSServer_ResponseDelayMs, "ms", "The amount of additional delay in milliseconds to apply to responses. (default: 0)", false ),
-	IntegerOption(      0 , "defaultTTL",    &gDNSServer_DefaultTTL,      "seconds", "Resource record TTL value to use when unspecified. (default: 60)", false ),
-	IntegerOption(     'p', "port",          &gDNSServer_Port,            "port number", "UDP/TCP port number to use. Use 0 for any port. (default: 53)", false ),
-	StringOption(       0 , "domain",        &gDNSServer_DomainOverride,  "domain", "Use to override 'd.test.' as the server's domain.", false ),
-	MultiStringOption( 'i', "ignoreQType",	 &gDNSServer_IgnoredQTypes, &gDNSServer_IgnoredQTypesCount, "qtype", "A QTYPE to ignore. This option can be specified more than once.", false ),
-	BooleanOption(      0 , "ipv4",          &gDNSServer_ListenOnV4,      "Listen on IPv4. Will listen on both IPv4 and IPv6 if neither --ipv4 nor --ipv6 is used." ),
-	BooleanOption(      0 , "ipv6",          &gDNSServer_ListenOnV6,      "Listen on IPv6. Will listen on both IPv4 and IPv6 if neither --ipv4 nor --ipv6 is used." ),
-#if( TARGET_OS_DARWIN )
-	StringOption(       0 , "follow",        &gDNSServer_FollowPID,       "pid", "Exit when the process, usually the parent process, specified by PID exits.", false ),
-#endif
-	BooleanOption(      0 , "badUDPMode",    &gDNSServer_BadUDPMode,      "Run in Bad UDP mode to trigger mDNSResponder's TCP fallback mechanism." ),
-	StringOptionEx(    'P', "protocol",      &gDNSServer_Protocol,        "protocol", "The DNS protocol to use. (default: Do53)", false,
-		"\n"
-		"Use '" kDNSProtocolStr_Do53 "' for DNS over UDP and TCP (Do53).\n"
-		"Use '" kDNSProtocolStr_DoT  "' for DNS over TLS (DoT).\n"
-		"Use '" kDNSProtocolStr_DoH  "' for DNS over HTTPS (DoH).\n"
- 	),
-#if( TARGET_OS_DARWIN )
-	CLI_OPTION_GROUP( "Loopback-Only Mode Options" ),
-	IntegerOptionEx( 0 , "extraIPv6",     &gDNSServer_ExtraV6Count,    "count", "The number of extra IPv6 addresses to listen on. (default: 0)", false,
-		"\n"
-		"This option will add extra IPv6 addresses from the fded:f035:55e4::/64 address block to the loopback interface.\n"
-		"The server will then bind to those addresses in addition to the standard loopback IP addresses, i.e., 127.0.0.1.\n"
-		"and/or ::1, depending on the specified IP protocol options.\n"
-		"\n"
-		"This option is useful for setting up a DNS configuration with multiple server addresses, e.g., one for the\n"
-		"primary server, one for the secondary server, etc. The Index label can then be used to simulate unresponsive\n"
-		"servers.\n"
-		"\n"
-		"Note: This option is ignored unless the server is in loopback only mode and listening on IPv6.\n"
-		"Note: This option currently requires root privileges.\n"
-	),
-#endif
-	CLI_SECTION( "Intro",				kDNSServerInfoText_Intro ),
-	CLI_SECTION( "Name Existence",		kDNSServerInfoText_NameExistence ),
-	CLI_SECTION( "Resource Records",	kDNSServerInfoText_ResourceRecords ),
-	CLI_SECTION( "Alias Labels",		kDNSServerInfoText_AliasLabel ),
-	CLI_SECTION( "Alias-TTL Labels",	kDNSServerInfoText_AliasTTLLabel ),
-	CLI_SECTION( "Count Labels",		kDNSServerInfoText_CountLabel ),
-	CLI_SECTION( "Tag Labels",			kDNSServerInfoText_TagLabel ),
-	CLI_SECTION( "TTL Labels",			kDNSServerInfoText_TTLLabel ),
-	CLI_SECTION( "IPv4 Label",			kDNSServerInfoText_IPv4Label ),
-	CLI_SECTION( "IPv6 Label",			kDNSServerInfoText_IPv6Label ),
-	CLI_SECTION( "Index Labels",		kDNSServerInfoText_IndexLabel ),
-	CLI_SECTION( "SRV Names",			kDNSServerInfoText_SRVNames ),
-	CLI_SECTION( "Bad UDP Mode",		kDNSServerInfoText_BadUDPMode ),
-	CLI_OPTION_END()
-};
-
-static void	DNSServerCommand( void );
-
-//===========================================================================================================================
-//	MDNSReplier Command Options
-//===========================================================================================================================
-
-#define kMDNSReplierPortBase		50000
-
-static const char		kMDNSReplierInfoText_Intro[] =
-	"The mDNS replier answers mDNS queries for its authoritative records. These records are of class IN and of types\n"
-	"PTR, SRV, TXT, A, and AAAA as described below.\n"
-	"\n"
-	"Note: Sub-strings representing integers in domain name labels are in decimal notation and without leading zeros.\n";
-
-static const char		kMDNSReplierInfoText_Parameters[] =
-	"There are five parameters that control the replier's set of authoritative records.\n"
-	"\n"
-	"    1. <hostname> is the base name used for service instance names and the names of A and AAAA records. This\n"
-	"       parameter is specified with the --hostname option.\n"
-	"    2. <tag> is an arbitrary string used to uniquify service types. This parameter is specified with the --tag\n"
-	"       option.\n"
-	"    3. N_max in an integer in [1, 65535] and limits service types to those that have no more than N_max\n"
-	"       instances. It also limits the number of hostnames to N_max, i.e., <hostname>.local.,\n"
-	"       <hostname>-1.local., ..., <hostname>-N_max.local. This parameter is specified with the\n"
-	"       --maxInstanceCount option.\n"
-	"    4. N_a is an integer in [1, 255] and the number of A records per hostname. This parameter is specified\n"
-	"       with the --countA option.\n"
-	"    5. N_aaaa is an integer in [1, 255] and the number of AAAA records per hostname. This parameter is\n"
-	"       specified with the --countAAAA option.\n";
-
-static const char		kMDNSReplierInfoText_PTR[] =
-	"The replier's authoritative PTR records have names of the form _t-<tag>-<L>-<N>._tcp.local., where L is an\n"
-	"integer in [1, 65535], and N is an integer in [1, N_max].\n"
-	"\n"
-	"For a given L and N, the replier has exactly N authoritative PTR records:\n"
-	"\n"
-	"    1. The first PTR record is defined as\n"
-	"\n"
-	"        NAME:  _t-<tag>-<L>-<N>._tcp.local.\n"
-	"        TYPE:  PTR\n"
-	"        CLASS: IN\n"
-	"        TTL:   4500\n"
-	"        RDATA: <hostname>._t-<tag>-<L>-<N>._tcp.local.\n"
-	"\n"
-	"    2. For each i in [2, N], there is one PTR record defined as\n"
-	"\n"
-	"        NAME:  _t-<tag>-<L>-<N>._tcp.local.\n"
-	"        TYPE:  PTR\n"
-	"        CLASS: IN\n"
-	"        TTL:   4500\n"
-	"        RDATA: \"<hostname> (<i>)._t-<tag>-<L>-<N>._tcp.local.\"\n";
-
-static const char		kMDNSReplierInfoText_SRV[] =
-	"The replier's authoritative SRV records have names of the form <instance name>._t-<tag>-<L>-<N>._tcp.local.,\n"
-	"where L is an integer in [1, 65535], N is an integer in [1, N_max], and <instance name> is <hostname> or\n"
-	"\"<hostname> (<i>)\", where i is in [2, N].\n"
-	"\n"
-	"For a given L and N, the replier has exactly N authoritative SRV records:\n"
-	"\n"
-	"    1. The first SRV record is defined as\n"
-	"\n"
-	"        NAME:  <hostname>._t-<tag>-<L>-<N>._tcp.local.\n"
-	"        TYPE:  SRV\n"
-	"        CLASS: IN\n"
-	"        TTL:   120\n"
-	"        RDATA:\n"
-	"            Priority: 0\n"
-	"            Weight:   0\n"
-	"            Port:     (50000 + L) mod 2^16\n"
-	"            Target:   <hostname>.local.\n"
-	"\n"
-	"    2. For each i in [2, N], there is one SRV record defined as:\n"
-	"\n"
-	"        NAME:  \"<hostname> (<i>)._t-<tag>-<L>-<N>._tcp.local.\"\n"
-	"        TYPE:  SRV\n"
-	"        CLASS: IN\n"
-	"        TTL:   120\n"
-	"        RDATA:\n"
-	"            Priority: 0\n"
-	"            Weight:   0\n"
-	"            Port:     (50000 + L) mod 2^16\n"
-	"            Target:   <hostname>-<i>.local.\n";
-
-static const char		kMDNSReplierInfoText_TXT[] =
-	"The replier's authoritative TXT records have names of the form <instance name>._t-<tag>-<L>-<N>._tcp.local.,\n"
-	"where L is an integer in [1, 65535], N is an integer in [1, N_max], and <instance name> is <hostname> or\n"
-	"\"<hostname> (<i>)\", where i is in [2, N].\n"
-	"\n"
-	"For a given L and N, the replier has exactly N authoritative TXT records:\n"
-	"\n"
-	"    1. The first TXT record is defined as\n"
-	"\n"
-	"        NAME:     <hostname>._t-<tag>-<L>-<N>._tcp.local.\n"
-	"        TYPE:     TXT\n"
-	"        CLASS:    IN\n"
-	"        TTL:      4500\n"
-	"        RDLENGTH: L\n"
-	"        RDATA:    <one or more strings with an aggregate length of L octets>\n"
-	"\n"
-	"    2. For each i in [2, N], there is one TXT record:\n"
-	"\n"
-	"        NAME:     \"<hostname> (<i>)._t-<tag>-<L>-<N>._tcp.local.\"\n"
-	"        TYPE:     TXT\n"
-	"        CLASS:    IN\n"
-	"        TTL:      4500\n"
-	"        RDLENGTH: L\n"
-	"        RDATA:    <one or more strings with an aggregate length of L octets>\n"
-	"\n"
-	"The RDATA of each TXT record is exactly L octets and consists of a repeating series of the 15-byte string\n"
-	"\"hash=0x<32-bit FNV-1 hash of the record name as an 8-character hexadecimal string>\". The last instance of\n"
-	"the string may be truncated to satisfy the TXT record data's size requirement.\n";
-
-static const char		kMDNSReplierInfoText_A[] =
-	"The replier has exactly N_max ✕ N_a authoritative A records:\n"
-	"\n"
-	"    For each i in [1, N_max], for each j in [1, N_a], an A record is defined as\n"
-	"\n"
-	"        NAME:     \"<hostname>.local.\" if i = 1, otherwise \"<hostname>-<i>.local.\"\n"
-	"        TYPE:     A\n"
-	"        CLASS:    IN\n"
-	"        TTL:      120\n"
-	"        RDLENGTH: 4\n"
-	"        RDATA:    0.<⌊i / 256⌋>.<i mod 256>.<j>\n";
-
-static const char		kMDNSReplierInfoText_AAAA[] =
-	"The replier has exactly N_max ✕ N_aaaa authoritative AAAA records:\n"
-	"\n"
-	"    1. For each j in [1, N_aaaa], a AAAA record is defined as\n"
-	"\n"
-	"        NAME:     <hostname>.local.\n"
-	"        TYPE:     AAAA\n"
-	"        CLASS:    IN\n"
-	"        TTL:      120\n"
-	"        RDLENGTH: 16\n"
-	"        RDATA:    fe80::1:<j>\n"
-	"\n"
-	"    2. For each i in [2, N_max], for each j in [1, N_aaaa], a AAAA record is defined as\n"
-	"\n"
-	"        NAME:     <hostname>-<i>.local.\n"
-	"        TYPE:     AAAA\n"
-	"        CLASS:    IN\n"
-	"        TTL:      120\n"
-	"        RDLENGTH: 16\n"
-	"        RDATA:    2001:db8:2::<i>:<j>\n";
-
-static const char		kMDNSReplierInfoText_Responses[] =
-	"When generating answers for a query message, any two records pertaining to the same hostname will be grouped\n"
-	"together in the same response message, and any two records pertaining to different hostnames will be in\n"
-	"separate response messages.\n";
-
-static const char *		gMDNSReplier_Hostname				= NULL;
-static const char *		gMDNSReplier_ServiceTypeTag			= NULL;
-static int				gMDNSReplier_MaxInstanceCount		= 1000;
-static int				gMDNSReplier_NoAdditionals			= false;
-static int				gMDNSReplier_RecordCountA			= 1;
-static int				gMDNSReplier_RecordCountAAAA		= 1;
-static double			gMDNSReplier_UnicastDropRate		= 0.0;
-static double			gMDNSReplier_MulticastDropRate		= 0.0;
-static int				gMDNSReplier_MaxDropCount			= 0;
-static int				gMDNSReplier_UseIPv4				= false;
-static int				gMDNSReplier_UseIPv6				= false;
-static int				gMDNSReplier_Foreground				= false;
-#if( TARGET_OS_POSIX )
-static const char *		gMDNSReplier_FollowPID				= NULL;
-#endif
-
-static CLIOption		kMDNSReplierOpts[] =
-{
-	StringOption(  'i', "interface",        &gInterface,                     "name or index", "Network interface by name or index.", true ),
-	StringOption(  'n', "hostname",         &gMDNSReplier_Hostname,          "string", "Base name to use for hostnames and service instance names.", true ),
-	StringOption(  't', "tag",              &gMDNSReplier_ServiceTypeTag,    "string", "Tag to use for service types, e.g., _t-<tag>-<TXT size>-<count>._tcp.", true ),
-	IntegerOption( 'c', "maxInstanceCount", &gMDNSReplier_MaxInstanceCount,  "count", "Maximum number of service instances. (default: 1000)", false ),
-	BooleanOption(  0 , "noAdditionals",    &gMDNSReplier_NoAdditionals,     "When answering queries, don't include any additional records." ),
-	IntegerOption(  0 , "countA",           &gMDNSReplier_RecordCountA,      "count", "Number of A records per hostname. (default: 1)", false ),
-	IntegerOption(  0 , "countAAAA",        &gMDNSReplier_RecordCountAAAA,   "count", "Number of AAAA records per hostname. (default: 1)", false ),
-	DoubleOption(   0 , "udrop",            &gMDNSReplier_UnicastDropRate,   "probability", "Probability of dropping a unicast response. (default: 0.0)", false ),
-	DoubleOption(   0 , "mdrop",            &gMDNSReplier_MulticastDropRate, "probability", "Probability of dropping a multicast query or response. (default: 0.0)", false ),
-	IntegerOption(  0 , "maxDropCount",     &gMDNSReplier_MaxDropCount,      "count", "If > 0, drop probabilities are limted to first <count> responses from each instance. (default: 0)", false ),
-	BooleanOption(  0 , "ipv4",             &gMDNSReplier_UseIPv4,           "Use IPv4." ),
-	BooleanOption(  0 , "ipv6",             &gMDNSReplier_UseIPv6,           "Use IPv6." ),
-	BooleanOption( 'f', "foreground",       &gMDNSReplier_Foreground,        "Direct log output to stdout instead of system logging." ),
-#if( TARGET_OS_POSIX )
-	StringOption(   0 , "follow",           &gMDNSReplier_FollowPID,         "pid", "Exit when the process, usually the parent process, specified by PID exits.", false ),
-#endif
-	
-	CLI_SECTION( "Intro",							kMDNSReplierInfoText_Intro ),
-	CLI_SECTION( "Authoritative Record Parameters",	kMDNSReplierInfoText_Parameters ),
-	CLI_SECTION( "Authoritative PTR Records",		kMDNSReplierInfoText_PTR ),
-	CLI_SECTION( "Authoritative SRV Records",		kMDNSReplierInfoText_SRV ),
-	CLI_SECTION( "Authoritative TXT Records",		kMDNSReplierInfoText_TXT ),
-	CLI_SECTION( "Authoritative A Records",			kMDNSReplierInfoText_A ),
-	CLI_SECTION( "Authoritative AAAA Records",		kMDNSReplierInfoText_AAAA ),
-	CLI_SECTION( "Responses",						kMDNSReplierInfoText_Responses ),
-	CLI_OPTION_END()
-};
-
-static void	MDNSReplierCmd( void );
-
-//===========================================================================================================================
-//	Test Command Options
-//===========================================================================================================================
-
-#define kTestExitStatusSection_Name		"Exit Status"
-#define kTestExitStatusSection_Text																						\
-	"This test command can exit with one of three status codes:\n"														\
-	"\n"																												\
-	"0 - The test ran to completion and passed.\n"																		\
-	"1 - A fatal error prevented the test from completing.\n"															\
-	"2 - The test ran to completion, but it or a subtest failed. See test output for details.\n"						\
-	"\n"																												\
-	"Note: The pass/fail status applies to the correctness or results. It does not necessarily imply anything about\n"	\
-	"performance.\n"
-
-#define TestExitStatusSection()		CLI_SECTION( kTestExitStatusSection_Name, kTestExitStatusSection_Text )
-
-#define kGAIPerfTestSuiteName_Basic			"basic"
-#define kGAIPerfTestSuiteName_Advanced		"advanced"
-
-static const char *		gGAIPerf_TestSuite				= NULL;
-static int				gGAIPerf_CallDelayMs			= 10;
-static int				gGAIPerf_ServerDelayMs			= 10;
-static int				gGAIPerf_SkipPathEvalulation	= false;
-static int				gGAIPerf_BadUDPMode				= false;
-static int				gGAIPerf_IterationCount			= 100;
-static int				gGAIPerf_IterationTimeLimitMs	= 100;
-static const char *		gGAIPerf_OutputFilePath			= NULL;
-static const char *		gGAIPerf_OutputFormat			= kOutputFormatStr_JSON;
-static int				gGAIPerf_OutputAppendNewline	= false;
-static const char *		gGAIPerf_Protocol				= kDNSProtocolStr_Do53;
-
-static void	GAIPerfCmd( void );
-
-#define kGAIPerfSectionText_TestSuiteBasic																					\
-	"This test suite consists of the following three test cases:\n"															\
-	"\n"																													\
-	"Test Case #1: Resolve a domain name with\n"																			\
-	"\n"																													\
-	"    2 CNAME records, 4 A records, and 4 AAAA records\n"																\
-	"\n"																													\
-	"to its IPv4 and IPv6 addresses. Each iteration resolves a unique instance of such a domain name, which requires\n"		\
-	"server queries.\n"																										\
-	"\n"																													\
-	"Test Case #2: Resolve a domain name with\n"																			\
-	"\n"																													\
-	"    2 CNAME records, 4 A records, and 4 AAAA records\n"																\
-	"\n"																													\
-	"to its IPv4 and IPv6 addresses. A preliminary iteration resolves a unique instance of such a domain name, which\n"		\
-	"requires server queries. Each subsequent iteration resolves the same domain name as the preliminary iteration,\n"		\
-	"which should ideally require no additional server queries, i.e., the results should come from the cache.\n"			\
-	"\n"																													\
-	"Unlike the preceding test case, this test case is concerned with DNSServiceGetAddrInfo() performance when the\n"		\
-	"records of the domain name being resolved are already in the cache. Therefore, the time required to resolve the\n"		\
-	"domain name in the preliminary iteration isn't counted in the performance stats.\n"									\
-	"\n"																													\
-	"Test Case #3: Each iteration resolves localhost to its IPv4 and IPv6 addresses.\n"
-
-#define kGAIPerfSectionText_TestSuiteAdvanced																				\
-	"This test suite consists of 33 test cases. Test cases 1 through 32 can be described in the following way\n"			\
-	"\n"																													\
-	"Test Case #N (where N is in [1, 32] and odd): Resolve a domain name with\n"											\
-	"\n"																													\
-	"    N_c CNAME records, N_a A records, and N_a AAAA records\n"															\
-	"\n"																													\
-	"to its IPv4 and IPv6 addresses. Each iteration resolves a unique instance of such a domain name, which requires\n"		\
-	"server queries.\n"																										\
-	"\n"																													\
-	"Test Case #N (where N is in [1, 32] and even): Resolve a domain name with\n"											\
-	"\n"																													\
-	"    N_c CNAME records, N_a A records, and N_a AAAA records\n"															\
-	"\n"																													\
-	"to its IPv4 and IPv6 addresses. A preliminary iteration resolves a unique instance of such a domain name, which\n"		\
-	"requires server queries. Each subsequent iteration resolves the same domain name as the preliminary iteration,\n"		\
-	"which should ideally require no additional server queries, i.e., the results should come from the cache.\n"			\
-	"\n"																													\
-	"Unlike the preceding test case, this test case is concerned with DNSServiceGetAddrInfo() performance when the\n"		\
-	"records of the domain name being resolved are already in the cache. Therefore, the time required to resolve the\n"		\
-	"domain name in the preliminary iteration isn't counted in the performance stats.\n"									\
-	"\n"																													\
-	"N_c and N_a take on the following values, depending on the value of N:\n"												\
-	"\n"																													\
-	"    N_c is 0 if N is in [1, 8].\n"																						\
-	"    N_c is 1 if N is in [9, 16].\n"																					\
-	"    N_c is 2 if N is in [17, 24].\n"																					\
-	"    N_c is 4 if N is in [25, 32].\n"																					\
-	"\n"																													\
-	"    N_a is 1 if N mod 8 is 1 or 2.\n"																					\
-	"    N_a is 2 if N mod 8 is 3 or 4.\n"																					\
-	"    N_a is 4 if N mod 8 is 5 or 6.\n"																					\
-	"    N_a is 8 if N mod 8 is 7 or 0.\n"																					\
-	"\n"																													\
-	"Finally,\n"																											\
-	"\n"																													\
-	"Test Case #33: Each iteration resolves localhost to its IPv4 and IPv6 addresses.\n"
-
-static CLIOption		kGAIPerfOpts[] =
-{
-	StringOptionEx( 's', "suite",         &gGAIPerf_TestSuite,            "name", "Name of the predefined test suite to run.", true,
-		"\n"
-		"There are currently two predefined test suites, '" kGAIPerfTestSuiteName_Basic "' and '" kGAIPerfTestSuiteName_Advanced "', which are described below.\n"
-		"\n"
-	),
-	StringOption(   'o', "output",        &gGAIPerf_OutputFilePath,       "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	FormatOption(   'f', "format",        &gGAIPerf_OutputFormat,         "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	BooleanOption(  'n', "appendNewline", &gGAIPerf_OutputAppendNewline,  "If the output format is JSON, output a trailing newline character." ),
-	IntegerOption(  'i', "iterations",    &gGAIPerf_IterationCount,       "count", "The number of iterations per test case. (default: 100)", false ),
-	IntegerOption(  'l', "timeLimit",     &gGAIPerf_IterationTimeLimitMs, "ms", "Time limit for each DNSServiceGetAddrInfo() operation in milliseconds. (default: 100)", false ),
-	IntegerOption(   0 , "callDelay",     &gGAIPerf_CallDelayMs,          "ms", "Time to wait before calling DNSServiceGetAddrInfo() in milliseconds. (default: 10)", false ),
-	BooleanOption(   0 , "skipPathEval",  &gGAIPerf_SkipPathEvalulation,  "Use kDNSServiceFlagsPathEvaluationDone when calling DNSServiceGetAddrInfo()." ),
-	
-	CLI_OPTION_GROUP( "DNS Server Options" ),
-	IntegerOption(   0 , "responseDelay", &gGAIPerf_ServerDelayMs,        "ms", "Additional delay in milliseconds to have the server apply to responses. (default: 10)", false ),
-	BooleanOption(   0 , "badUDPMode",    &gGAIPerf_BadUDPMode,           "Run server in Bad UDP mode to trigger mDNSResponder's TCP fallback mechanism." ),
-	StringOptionEx( 'P', "protocol",      &gGAIPerf_Protocol,             "protocol", "The DNS protocol to use. (default: Do53)", false,
-		"\n"
-		"Use '" kDNSProtocolStr_Do53 "' for DNS over UDP and TCP (Do53).\n"
-		"Use '" kDNSProtocolStr_DoT  "' for DNS over TLS (DoT).\n"
-		"Use '" kDNSProtocolStr_DoH  "' for DNS over HTTPS (DoH).\n"
- 	),
-	CLI_SECTION( "Test Suite \"Basic\"",	kGAIPerfSectionText_TestSuiteBasic ),
-	CLI_SECTION( "Test Suite \"Advanced\"",	kGAIPerfSectionText_TestSuiteAdvanced ),
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	MDNSDiscoveryTestCmd( void );
-
-static int				gMDNSDiscoveryTest_InstanceCount		= 100;
-static int				gMDNSDiscoveryTest_TXTSize				= 100;
-static int				gMDNSDiscoveryTest_BrowseTimeSecs		= 2;
-static int				gMDNSDiscoveryTest_FlushCache			= false;
-static char *			gMDNSDiscoveryTest_Interface			= NULL;
-static int				gMDNSDiscoveryTest_NoAdditionals		= false;
-static int				gMDNSDiscoveryTest_RecordCountA			= 1;
-static int				gMDNSDiscoveryTest_RecordCountAAAA		= 1;
-static double			gMDNSDiscoveryTest_UnicastDropRate		= 0.0;
-static double			gMDNSDiscoveryTest_MulticastDropRate	= 0.0;
-static int				gMDNSDiscoveryTest_MaxDropCount			= 0;
-static int				gMDNSDiscoveryTest_UseIPv4				= false;
-static int				gMDNSDiscoveryTest_UseIPv6				= false;
-static int				gMDNSDiscoveryTest_UseNewGAI			= false;
-static const char *		gMDNSDiscoveryTest_OutputFormat			= kOutputFormatStr_JSON;
-static int				gMDNSDiscoveryTest_OutputAppendNewline	= false;
-static const char *		gMDNSDiscoveryTest_OutputFilePath		= NULL;
-
-static CLIOption		kMDNSDiscoveryTestOpts[] =
-{
-	IntegerOption( 'c', "instanceCount",  &gMDNSDiscoveryTest_InstanceCount,       "count", "Number of service instances to discover. (default: 100)", false ),
-	IntegerOption( 's', "txtSize",        &gMDNSDiscoveryTest_TXTSize,             "bytes", "Desired size of each service instance's TXT record data. (default: 100)", false ),
-	IntegerOption( 'b', "browseTime",     &gMDNSDiscoveryTest_BrowseTimeSecs,      "seconds", "Amount of time to spend browsing in seconds. (default: 2)", false ),
-	BooleanOption(  0 , "flushCache",     &gMDNSDiscoveryTest_FlushCache,          "Flush mDNSResponder's record cache before browsing. Requires root privileges." ),
-	
-	CLI_OPTION_GROUP( "mDNS Replier Parameters" ),
-	StringOption(  'i', "interface",      &gMDNSDiscoveryTest_Interface,           "name or index", "Network interface. If unspecified, any available mDNS-capable interface will be used.", false ),
-	BooleanOption(  0 , "noAdditionals",  &gMDNSDiscoveryTest_NoAdditionals,       "When answering queries, don't include any additional records." ),
-	IntegerOption(  0 , "countA",         &gMDNSDiscoveryTest_RecordCountA,        "count", "Number of A records per hostname. (default: 1)", false ),
-	IntegerOption(  0 , "countAAAA",      &gMDNSDiscoveryTest_RecordCountAAAA,     "count", "Number of AAAA records per hostname. (default: 1)", false ),
-	DoubleOption(   0 , "udrop",          &gMDNSDiscoveryTest_UnicastDropRate,     "probability", "Probability of dropping a unicast response. (default: 0.0)", false ),
-	DoubleOption(   0 , "mdrop",          &gMDNSDiscoveryTest_MulticastDropRate,   "probability", "Probability of dropping a multicast query or response. (default: 0.0)", false ),
-	IntegerOption(  0 , "maxDropCount",   &gMDNSDiscoveryTest_MaxDropCount,        "count", "If > 0, drop probabilities are limted to first <count> responses from each instance. (default: 0)", false ),
-	BooleanOption(  0 , "ipv4",           &gMDNSDiscoveryTest_UseIPv4,             "Use IPv4." ),
-	BooleanOption(  0 , "ipv6",           &gMDNSDiscoveryTest_UseIPv6,             "Use IPv6." ),
-	BooleanOption(  0 , "useNewGAI",      &gMDNSDiscoveryTest_UseNewGAI,           "Use dnssd_getaddrinfo_* instead of DNSServiceGetAddrInfo()." ),
-	
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption(   'f', "format",        &gMDNSDiscoveryTest_OutputFormat,        "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption(   'o', "output",        &gMDNSDiscoveryTest_OutputFilePath,      "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	DotLocalTestCmd( void );
-
-static const char *		gDotLocalTest_Interface			= NULL;
-static const char *		gDotLocalTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gDotLocalTest_OutputFilePath	= NULL;
-
-#define kDotLocalTestSubtestDesc_GAIMDNSOnly	"GAI for a dotlocal name that has only MDNS A and AAAA records."
-#define kDotLocalTestSubtestDesc_GAIDNSOnly		"GAI for a dotlocal name that has only DNS A and AAAA records."
-#define kDotLocalTestSubtestDesc_GAIBoth		"GAI for a dotlocal name that has both mDNS and DNS A and AAAA records."
-#define kDotLocalTestSubtestDesc_GAINeither		"GAI for a dotlocal name that has no A or AAAA records."
-#define kDotLocalTestSubtestDesc_GAINoSuchRecord \
-	"GAI for a dotlocal name that has no A or AAAA records, but is a subdomain name of a search domain."
-#define kDotLocalTestSubtestDesc_QuerySRV		"SRV query for a dotlocal name that has only a DNS SRV record."
-
-#define kDotLocalTestSectionText_Description																				\
-	"The goal of the dotlocal test is to verify that mDNSResponder properly handles queries for domain names in the\n"		\
-	"local domain when a local SOA record exists. As part of the test setup, a test DNS server and an mdnsreplier are\n"	\
-	"spawned, and a dummy local SOA record is registered with DNSServiceRegisterRecord(). The server is invoked such\n"		\
-	"that its domain is a second-level subdomain of the local domain, i.e., <some label>.local, while the mdnsreplier is\n"	\
-	"invoked such that its base hostname is equal to the server's domain, e.g., if the server's domain is test.local.,\n"	\
-	"then the mdnsreplier's base hostname is test.local.\n"																	\
-	"\n"																													\
-	"The dotlocal test consists of six subtests that perform either a DNSServiceGetAddrInfo (GAI) operation for a\n"		\
-	"hostname in the local domain or a DNSServiceQueryRecord operation to query for an SRV record in the local domain:\n"	\
-	"\n"																													\
-	"1. " kDotLocalTestSubtestDesc_GAIMDNSOnly		"\n"																	\
-	"2. " kDotLocalTestSubtestDesc_GAIDNSOnly		"\n"																	\
-	"3. " kDotLocalTestSubtestDesc_GAIBoth			"\n"																	\
-	"4. " kDotLocalTestSubtestDesc_GAINeither		"\n"																	\
-	"5. " kDotLocalTestSubtestDesc_GAINoSuchRecord	"\n"																	\
-	"6. " kDotLocalTestSubtestDesc_QuerySRV			"\n"																	\
-	"\n"																													\
-	"Each subtest runs for five seconds.\n"
-
-static CLIOption		kDotLocalTestOpts[] =
-{
-	StringOption(  'i', "interface",     &gDotLocalTest_Interface,           "name or index", "mdnsreplier's network interface. If not set, any mDNS-capable interface will be used.", false ),
-	
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption(  'f', "format",        &gDotLocalTest_OutputFormat,        "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption(  'o', "output",        &gDotLocalTest_OutputFilePath,      "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	CLI_SECTION( "Description", kDotLocalTestSectionText_Description ),
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	ProbeConflictTestCmd( void );
-
-static const char *		gProbeConflictTest_Interface		= NULL;
-static int				gProbeConflictTest_UseComputerName	= false;
-static int				gProbeConflictTest_UseIPv4			= false;
-static int				gProbeConflictTest_UseIPv6			= false;
-static int				gProbeConflictTest_RegisterOnAny	= false;
-static int				gProbeConflictTest_ExtraWaitMs		= 0;
-static const char *		gProbeConflictTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gProbeConflictTest_OutputFilePath	= NULL;
-
-static CLIOption		kProbeConflictTestOpts[] =
-{
-	StringOption(    'i', "interface",       &gProbeConflictTest_Interface,       "name or index", "mdnsreplier's network interface. If not set, any mDNS-capable interface will be used.", false ),
-	BooleanOption(   'c', "useComputerName", &gProbeConflictTest_UseComputerName, "Use the device's \"computer name\" for the test service's name." ),
-	BooleanOption(    0 , "ipv4",            &gProbeConflictTest_UseIPv4,         "Use IPv4 instead of IPv6. (Default behavior.)" ),
-	BooleanOption(    0 , "ipv6",            &gProbeConflictTest_UseIPv6,         "Use IPv6 instead of IPv4." ),
-	BooleanOption(   'r', "registerOnAny",   &gProbeConflictTest_RegisterOnAny,   "Register test service on kDNSServiceInterfaceIndexAny instead of specific interface." ),
-	IntegerOptionEx(  0 , "extraWait",       &gProbeConflictTest_ExtraWaitMs,     "ms", "Extra time in milliseconds to wait after a probe conflict. (default: 0)", false,
-		"\n"
-		"After each probe conflict, there is a minimum amount of time that the test will wait to allow for probing and\n"
-		"renames to take place. The minimum wait time was chosen for relatively tranquil environments.\n"
-		"\n"
-		"If the test environment is such that mDNSResponder is expected to be busier than usual, then use this option to\n"
-		"allow extra time for renames, which may be delayed by events outside of mDNSResponder's control, such as network\n"
-		"changes.\n"
-	),
-	
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gProbeConflictTest_OutputFormat,   "Specifies the test report output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gProbeConflictTest_OutputFilePath, "path", "Path of the file to write test report to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	RegistrationTestCmd( void );
-
-static int				gRegistrationTest_BATSEnvironment	= false;
-static const char *		gRegistrationTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gRegistrationTest_OutputFilePath	= NULL;
-
-static CLIOption		kRegistrationTestOpts[] =
-{
-	CLI_OPTION_BOOLEAN( 0, "bats", &gRegistrationTest_BATSEnvironment, "Informs the test that it's running in a BATS environment.",
-		"\n"
-		"This option allows the test to take special measures while running in a BATS environment. Currently, this option\n"
-		"only has an effect on watchOS. Because it has been observed that the Wi-Fi interface sometimes goes down during\n"
-		"watchOS BATS testing, for watchOS, when a service is registered using kDNSServiceInterfaceIndexAny,\n"
-		"\n"
-		"    1. missing browse and query \"add\" results for Wi-Fi interfaces aren't enough for a subtest to fail; and\n"
-		"    2. unexpected browse and query results for Wi-Fi interfaces are ignored.\n"
-	),
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gRegistrationTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gRegistrationTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-#if( MDNSRESPONDER_PROJECT )
-static void	FallbackTestCmd( void );
-
-static int				gFallbackTest_UseRefused		= false;
-static const char *		gFallbackTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gFallbackTest_OutputFilePath	= NULL;
-
-static CLIOption		kFallbackTestOpts[] =
-{
-	BooleanOption( 0 , "useRefused", &gFallbackTest_UseRefused,     "Have the server use the Refused RCODE in responses when a query is not allowed to be answered." ),
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format",     &gFallbackTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output",     &gFallbackTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void ExpensiveConstrainedTestCmd( void );
-
-static const char *     gExpensiveConstrainedTest_Interface                 = NULL;
-static const char *     gExpensiveConstrainedTest_Name                      = NULL;
-static Boolean          gExpensiveConstrainedTest_DenyExpensive             = false;
-static Boolean          gExpensiveConstrainedTest_DenyConstrained           = false;
-static Boolean          gExpensiveConstrainedTest_StartFromExpensive        = false;
-static int              gExpensiveConstrainedTest_ProtocolIPv4              = false;
-static int              gExpensiveConstrainedTest_ProtocolIPv6              = false;
-static const char *     gExpensiveConstrainedTest_OutputFormat              = kOutputFormatStr_JSON;
-static const char *     gExpensiveConstrainedTest_OutputFilePath            = NULL;
-
-static CLIOption        kExpensiveConstrainedTestOpts[] =
-{
-    CLI_OPTION_GROUP( "Results" ),
-    FormatOption( 'f', "format", &gExpensiveConstrainedTest_OutputFormat,              "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-    StringOption( 'o', "output", &gExpensiveConstrainedTest_OutputFilePath, "path",    "Path of the file to write test results to instead of standard output (stdout).", false ),
-
-    TestExitStatusSection(),
-    CLI_OPTION_END()
-};
-
-static void	DNSProxyTestCmd( void );
-
-static const char *		gDNSProxyTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gDNSProxyTest_OutputFilePath	= NULL;
-static int				gDNSProxyTest_UseLegacyDNSProxy	= false;
-
-static CLIOption		kDNSProxyTestOpts[] =
-{
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption(  'f', "format", &gDNSProxyTest_OutputFormat,      "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption(  'o', "output", &gDNSProxyTest_OutputFilePath,    "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	BooleanOption( 'l', "legacy", &gDNSProxyTest_UseLegacyDNSProxy, "Use the legacy DNS proxy client SPI, i.e., DNSXEnableProxy() and DNSXEnableProxy64()." ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	RCodeTestCmd( void );
-
-static const char *		gRCodeTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gRCodeTest_OutputFilePath	= NULL;
-
-static CLIOption		kRCodeTestOpts[] =
-{
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gRCodeTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gRCodeTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	DNSQueryTestCmd( void );
-
-static const char *		gDNSQueryTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gDNSQueryTest_OutputFilePath	= NULL;
-
-static CLIOption		kDNSQueryTestOpts[] =
-{
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gDNSQueryTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gDNSQueryTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void	FastRecoveryTestCmd( void );
-
-static const char *		gFastRecoveryTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gFastRecoveryTest_OutputFilePath	= NULL;
-
-static CLIOption		kFastRecoveryTestOpts[] =
-{
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gFastRecoveryTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gFastRecoveryTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static void XCTestCmd( void );
-
-static const char *     gXCTest_Classname        = NULL;
-
-static CLIOption        kXCTestOpts[] =
-{
-    StringOption(      'c', "class", &gXCTest_Classname, "classname", "The classname of the XCTest to run (from /AppleInternal/XCTests/com.apple.mDNSResponder/Tests.xctest)", true ),
-    CLI_OPTION_END()
-};
-
-static void MultiConnectTestCmd( void );
-
-static int    			gMultiConnectTest_ConnectionCount = 4; // default to 4
-
-static CLIOption        kMultiConnectTestOpts[] =
-{
-	IntegerOption( 0, "connections", &gMultiConnectTest_ConnectionCount,	"count", "Number of simultanious connections. (default: 4)", false ),
-    CLI_OPTION_END()
-};
-#endif	// MDNSRESPONDER_PROJECT
-
-#if( TARGET_OS_DARWIN )
-static void	KeepAliveTestCmd( void );
-
-static const char *		gKeepAliveTest_OutputFormat		= kOutputFormatStr_JSON;
-static const char *		gKeepAliveTest_OutputFilePath	= NULL;
-
-static CLIOption		kKeepAliveTestOpts[] =
-{
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format", &gKeepAliveTest_OutputFormat,   "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output", &gKeepAliveTest_OutputFilePath, "path", "Path of the file to write test results to instead of standard output (stdout).", false ),
-	
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-#endif	// TARGET_OS_DARWIN
-
-static void DNSSECTestCmd( void );
-
-static const char * gDNSSECTest_TestCaseName	= NULL;
-#if ( ENABLE_DNSSDUTIL_DNSSEC_TEST == 1 )
-static const char * gDNSSECTest_OutputFormat	= kOutputFormatStr_JSON;
-static const char * gDNSSECTest_OutputFilePath	= NULL;
-#endif
-
-static CLIOption	kDNSSECTestOpts[] =
-{
-	StringOption( 'n', "testCaseName", &gDNSSECTest_TestCaseName,                  "Specifies the DNSSEC test that the user intends to run", "test name", true ),
-
-	CLI_OPTION_GROUP( "Results" ),
-	FormatOption( 'f', "format",       &gExpensiveConstrainedTest_OutputFormat,    "Specifies the test results output format. (default: " kOutputFormatStr_JSON ")", false ),
-	StringOption( 'o', "output",       &gExpensiveConstrainedTest_OutputFilePath,  "path",    "Path of the file to write test results to instead of standard output (stdout).", false ),
-
-	TestExitStatusSection(),
-	CLI_OPTION_END()
-};
-
-static CLIOption		kTestOpts[] =
-{
-	Command( "gaiperf",        GAIPerfCmd,           kGAIPerfOpts,            "Runs DNSServiceGetAddrInfo() performance tests.", false ),
-	Command( "mdnsdiscovery",  MDNSDiscoveryTestCmd, kMDNSDiscoveryTestOpts,  "Tests mDNS service discovery for correctness.", false ),
-	Command( "dotlocal",       DotLocalTestCmd,      kDotLocalTestOpts,       "Tests DNS and mDNS queries for domain names in the local domain.", false ),
-	Command( "probeconflicts", ProbeConflictTestCmd, kProbeConflictTestOpts,  "Tests various probing conflict scenarios.", false ),
-	Command( "registration",   RegistrationTestCmd,  kRegistrationTestOpts,   "Tests service registrations.", false ),
-#if( MDNSRESPONDER_PROJECT )
-	Command( "fallback",       FallbackTestCmd,      kFallbackTestOpts,       "Tests DNS server fallback.", false ),
-    Command( "expensive_constrained_updates", ExpensiveConstrainedTestCmd, kExpensiveConstrainedTestOpts, "Tests if the mDNSResponder can handle expensive and constrained property change correctly", false),
-	Command( "dnsproxy",       DNSProxyTestCmd,      kDNSProxyTestOpts,       "Tests mDNSResponder's DNS proxy.", false ),
-	Command( "rcodes",         RCodeTestCmd,         kRCodeTestOpts,          "Tests handling of all DNS RCODEs.", false ),
-	Command( "dnsquery",       DNSQueryTestCmd,      kDNSQueryTestOpts,       "Tests mDNSResponder's DNS queries.", false ),
-	Command( "fastrecovery",   FastRecoveryTestCmd,  kFastRecoveryTestOpts,   "Tests mDNSResponder's fast querier recovery.", false ),
-    Command( "xctest",         XCTestCmd,            kXCTestOpts,			  "Run a XCTest from /AppleInternal/XCTests/com.apple.mDNSResponder/Tests.xctest.", true ),
-	Command( "multiconnect",   MultiConnectTestCmd,	 kMultiConnectTestOpts,	  "Tests multiple simultanious connections.", false ),
-#endif
-#if( TARGET_OS_DARWIN )
-	Command( "keepalive",      KeepAliveTestCmd,     kKeepAliveTestOpts,      "Tests keepalive record registrations.", false ),
-#endif
-	Command( "dnssec",         DNSSECTestCmd,        kDNSSECTestOpts,         "Tests mDNSResponder's DNSSEC validation", false),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	SSDP Command Options
-//===========================================================================================================================
-
-static int				gSSDPDiscover_MX			= 1;
-static const char *		gSSDPDiscover_ST			= "ssdp:all";
-static int				gSSDPDiscover_ReceiveSecs	= 1;
-static int				gSSDPDiscover_UseIPv4		= false;
-static int				gSSDPDiscover_UseIPv6		= false;
-static int				gSSDPDiscover_Verbose		= false;
-
-static CLIOption		kSSDPDiscoverOpts[] =
-{
-	StringOption(  'i', "interface",	&gInterface,				"name or index", "Network interface by name or index.", true ),
-	IntegerOption( 'm', "mx",			&gSSDPDiscover_MX,			"seconds", "MX value in search request, i.e., max response delay in seconds. (Default: 1 second)", false ),
-	StringOption(  's', "st",			&gSSDPDiscover_ST,			"string", "ST value in search request, i.e., the search target. (Default: \"ssdp:all\")", false ),
-	IntegerOption( 'r', "receiveTime",	&gSSDPDiscover_ReceiveSecs,	"seconds", "Amount of time to spend receiving responses. -1 means unlimited. (Default: 1 second)", false ),
-	BooleanOption(  0 , "ipv4",			&gSSDPDiscover_UseIPv4,		"Use IPv4, i.e., multicast to 239.255.255.250:1900." ),
-	BooleanOption(  0 , "ipv6",			&gSSDPDiscover_UseIPv6,		"Use IPv6, i.e., multicast to [ff02::c]:1900" ),
-	BooleanOption( 'v', "verbose",		&gSSDPDiscover_Verbose,		"Prints the search request(s) that were sent." ),
-	CLI_OPTION_END()
-};
-
-static void	SSDPDiscoverCmd( void );
-
-static CLIOption		kSSDPOpts[] =
-{
-	Command( "discover", SSDPDiscoverCmd, kSSDPDiscoverOpts, "Crafts and multicasts an SSDP search message.", false ),
-	CLI_OPTION_END()
-};
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	res_query Command Options
-//===========================================================================================================================
-
-static void	ResQueryCmd( void );
-
-static const char *		gResQuery_Name			= NULL;
-static const char *		gResQuery_Type			= NULL;
-static const char *		gResQuery_Class			= NULL;
-static int				gResQuery_UseLibInfo	= false;
-
-static CLIOption		kResQueryOpts[] =
-{
-	StringOption( 'n', "name",		&gResQuery_Name,		"domain name",	"Full domain name of record to query.", true ),
-	StringOption( 't', "type",		&gResQuery_Type,		"record type",	"Record type by name (e.g., TXT, SRV, etc.) or number.", true ),
-	StringOption( 'c', "class",		&gResQuery_Class,		"record class",	"Record class by name or number. Default class is IN.", false ),
-	BooleanOption( 0 , "libinfo",	&gResQuery_UseLibInfo,	"Use res_query from libinfo instead of libresolv." ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	dns_query Command Options
-//===========================================================================================================================
-
-static void ResolvDNSQueryCmd( void );
-
-static const char *		gResolvDNSQuery_Name	= NULL;
-static const char *		gResolvDNSQuery_Type	= NULL;
-static const char *		gResolvDNSQuery_Class	= NULL;
-static const char *		gResolvDNSQuery_Path	= NULL;
-
-static CLIOption		kResolvDNSQueryOpts[] =
-{
-	StringOption( 'n', "name",	&gResolvDNSQuery_Name,	"domain name",	"Full domain name of record to query.", true ),
-	StringOption( 't', "type",	&gResolvDNSQuery_Type,	"record type",	"Record type by name (e.g., TXT, SRV, etc.) or number.", true ),
-	StringOption( 'c', "class",	&gResolvDNSQuery_Class,	"record class",	"Record class by name or number. Default class is IN.", false ),
-	StringOption( 'p', "path",	&gResolvDNSQuery_Path,	"file path",	"The path argument to pass to dns_open() before calling dns_query(). Default value is NULL.", false ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	CFHost Command Options
-//===========================================================================================================================
-
-static void	CFHostCmd( void );
-
-static const char *		gCFHost_Name		= NULL;
-static int				gCFHost_WaitSecs	= 0;
-
-static CLIOption		kCFHostOpts[] =
-{
-	StringOption(  'n', "name", &gCFHost_Name,     "hostname", "Hostname to resolve.", true ),
-	IntegerOption( 'w', "wait", &gCFHost_WaitSecs, "seconds",  "Time in seconds to wait before a normal exit. (default: 0)", false ),
-	CLI_OPTION_END()
-};
-
-static CLIOption		kLegacyOpts[] =
-{
-	Command( "res_query", ResQueryCmd,       kResQueryOpts,       "Uses res_query() from either libresolv or libinfo to query for a record.", true ),
-	Command( "dns_query", ResolvDNSQueryCmd, kResolvDNSQueryOpts, "Uses dns_query() from libresolv to query for a record.", true ),
-	Command( "cfhost",    CFHostCmd,         kCFHostOpts,         "Uses CFHost to resolve a hostname.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	DNSConfigAdd Command Options
-//===========================================================================================================================
-
-static void	DNSConfigAddCmd( void );
-
-static CFStringRef		gDNSConfigAdd_ID			= NULL;
-static char **			gDNSConfigAdd_IPAddrArray	= NULL;
-static size_t			gDNSConfigAdd_IPAddrCount	= 0;
-static char **			gDNSConfigAdd_DomainArray	= NULL;
-static size_t			gDNSConfigAdd_DomainCount	= 0;
-static const char *		gDNSConfigAdd_Interface		= NULL;
-static int				gDNSConfigAdd_SearchOrder	= -1;
-
-static CLIOption		kDNSConfigAddOpts[] =
-{
-	CFStringOption(     0 , "id",          &gDNSConfigAdd_ID,                                      "ID", "Arbitrary ID to use for resolver entry.", true ),
-	MultiStringOption( 'a', "address",     &gDNSConfigAdd_IPAddrArray, &gDNSConfigAdd_IPAddrCount, "IP address", "DNS server IP address(es). Can be specified more than once.", true ),
-	MultiStringOption( 'd', "domain",      &gDNSConfigAdd_DomainArray, &gDNSConfigAdd_DomainCount, "domain", "Specific domain(s) for the resolver entry. Can be specified more than once.", false ),
-	StringOption(      'i', "interface",   &gDNSConfigAdd_Interface,                               "interface name", "Specific interface for the resolver entry.", false ),
-	IntegerOption(     'o', "searchOrder", &gDNSConfigAdd_SearchOrder,                             "integer", "Resolver entry's search order. Will only be set for values >= 0. (default: -1)", false ),
-	
-	CLI_SECTION( "Notes", "Run 'scutil -d -v --dns' to see the current DNS configuration. See scutil(8) man page for more details.\n" ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	DNSConfigRemove Command Options
-//===========================================================================================================================
-
-static void	DNSConfigRemoveCmd( void );
-
-static CFStringRef		gDNSConfigRemove_ID = NULL;
-
-static CLIOption		kDNSConfigRemoveOpts[] =
-{
-	CFStringOption( 0, "id", &gDNSConfigRemove_ID, "ID", "ID of resolver entry to remove.", true ),
-	
-	CLI_SECTION( "Notes", "Run 'scutil -d -v --dns' to see the current DNS configuration. See scutil(8) man page for more details.\n" ),
-	CLI_OPTION_END()
-};
-
-static CLIOption		kDNSConfigOpts[] =
-{
-	Command( "add",    DNSConfigAddCmd,    kDNSConfigAddOpts,    "Add a supplemental resolver entry to the system's DNS configuration.", true ),
-	Command( "remove", DNSConfigRemoveCmd, kDNSConfigRemoveOpts, "Remove a supplemental resolver entry from the system's DNS configuration.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	XPCSend
-//===========================================================================================================================
-
-static void	XPCSendCommand( void );
-
-static const char *		gXPCSend_ServiceName		= NULL;
-static const char *		gXPCSend_MessageStr			= NULL;
-static int				gXPCSend_NoReply			= false;
-static int				gXPCSend_CancelDelaySecs	= 0;
-
-static const char		kXPCSendMessageSection_Name[] = "Message Argument";
-static const char		kXPCSendMessageSection_Text[] =
-	"XPC messages are described as a string using the following syntax.\n"
-	"\n"
-	"With the exception of the top-most XPC message dictionary, dictionaries begin with a '{' and end with a '}'.\n"
-	"Key-value pairs are of the form <key>=<value>, where <key> is a string and <value> is a value of any of the\n"
-	"currently supported XPC types.\n"
-	"\n"
-	"Arrays begin with a '[' and end with a ']'.\n"
-	"\n"
-	"The following non-container XPC types are supported:\n"
-	"\n"
-	"Type                              Syntax                      Example\n"
-	"bool                              bool:<string>               bool:true (or yes/y/on/1), bool:false (or no/n/off/0)\n"
-	"data                              data:<hex string>           data:C0000201\n"
-	"int64  (signed 64-bit integer)    int:<integer>               int:10, int:-1\n"
-	"string                            string:<string>             string:example, string:escaped\\ white\\ space\n"
-	"uint64 (unsigned 64-bit integer)  uint:<non-neg. integer>     uint:1024 or uint:0x400\n"
-	"UUID                              uuid:<UUID>                 uuid:dab10183-84b5-4859-9de6-4bee287cfea3\n"
-	"\n"
-	"For convenience, the following type prefix abbreviations are accepted:\n"
-	"\n"
-	"    bool:   ↔ b:\n"
-	"    data:   ↔ d:\n"
-	"    int:    ↔ i:\n"
-	"    string: ↔ s:\n"
-	"    uint:   ↔ u:\n"
-	"\n"
-	"Here are some message string examples:\n"
-	"\n"
-	"    1. 'cmd=s:add make=s:Apple model=s:Macintosh aliases=[s:Mac s:Macintosh\\ 128K]'\n"
-	"    2. 'cmd=s:search features={portable=b:yes solar=b:no} priceMin=u:100 priceMax=u:200'\n";
-
-static CLIOption		kXPCSendOpts[] =
-{
-	StringOption(  's', "service", &gXPCSend_ServiceName,     "service name", "XPC service name.", true ),
-	StringOption(  'm', "message", &gXPCSend_MessageStr,      "message",      "XPC message as a string.", false ),
-	BooleanOption( 'n', "noReply", &gXPCSend_NoReply,         "No reply is expected." ),
-	IntegerOption( 'd', "delay",   &gXPCSend_CancelDelaySecs, "seconds",      "Time to delay the XPC connection's cancellation in seconds. (default: 0)", false ),
-	
-	CLI_SECTION( kXPCSendMessageSection_Name, kXPCSendMessageSection_Text ),
-	CLI_OPTION_END()
-};
-#endif	// TARGET_OS_DARWIN
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	InterfaceMonitor Command Options
-//===========================================================================================================================
-
-static void InterfaceMonitorCmd( void );
-
-static CLIOption		kInterfaceMonitorOpts[] =
-{
-	StringOption( 'i', "interface", &gInterface, "name or index", "Network interface by name or index.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Querier Command Options
-//===========================================================================================================================
-
-#define kMDNSResolverTypeStr_Normal		"normal"
-#define kMDNSResolverTypeStr_TCPOnly	"tcp"
-#define kMDNSResolverTypeStr_TLS		"tls"
-#define kMDNSResolverTypeStr_HTTPS		"https"
-
-static const char *		gQuerier_Name				= NULL;
-static const char *		gQuerier_Type				= "A";
-static const char *		gQuerier_Class				= "IN";
-static const char *		gQuerier_Delegator			= NULL;
-static int				gQuerier_DNSSECOK			= false;
-static int				gQuerier_CheckingDisabled	= false;
-static const char *		gQuerier_ResolverType		= NULL;
-static char **			gQuerier_ServerAddrs		= NULL;
-static size_t			gQuerier_ServerAddrCount	= 0;
-static const char *		gQuerier_ProviderName		= NULL;
-static const char *		gQuerier_ConnectionHostname	= NULL;
-static const char *		gQuerier_URLPath			= NULL;
-static const char *		gQuerier_ODoHConfig			= NULL;
-static const char *		gQuerier_IdentityReference	= NULL;
-static int				gQuerier_NoConnectionReuse	= false;
-static int				gQuerier_SquashCNAMEs		= false;
-static char **			gQuerier_Domains			= NULL;
-static size_t			gQuerier_DomainCount		= 0;
-static const char *		gQuerier_StartLeewayMs		= NULL;
-
-static CLIOption		kQuerierOpts[] =
-{
-	StringOption( 'i', "interface",        &gInterface,                "name or index", "If specified, network traffic is scoped to this interface.", false ),
-	StringOption( 'n', "name",             &gQuerier_Name,             "name", "Question name (QNAME).", true ),
-	StringOption( 't', "type",             &gQuerier_Type,             "type", "Question type (QTYPE). (default: A)", false ),
-	StringOption( 'c', "class",            &gQuerier_Class,            "class", "Question class (QCLASS). (default: IN)", false ),
-	StringOption(  0 , "delegator",        &gQuerier_Delegator,        "PID|UUID", "Delegator's PID or UUID.", false ),
-	BooleanOption( 0 , "dnssec",           &gQuerier_DNSSECOK,         "Have queries include an OPT record with the DNSSEC OK (DO) bit set." ),
-	BooleanOption( 0 , "checkingDisabled", &gQuerier_CheckingDisabled, "Set the Checking Disabled (CD) bit in queries." ),
-	StringOption(  0 , "startLeeway",      &gQuerier_StartLeewayMs,    "ms", "Start time leeway in milliseconds. Negative values mean infinite leeway.", false ),
-	
-	CLI_OPTION_GROUP( "DNS Service Options" ),
-	StringOptionEx( 'r', "resolverType", &gQuerier_ResolverType, "resolver type", "Specifies the type of resolver to use.", false,
-		"\n"
-		"Use '" kMDNSResolverTypeStr_Normal  "' for DNS over UDP and TCP (Do53).\n"
-		"Use '" kMDNSResolverTypeStr_TCPOnly "' for DNS over TCP.\n"
-		"Use '" kMDNSResolverTypeStr_TLS     "' for DNS over TLS (DoT).\n"
-		"Use '" kMDNSResolverTypeStr_HTTPS   "' for DNS over HTTPS (DoH or ODoH).\n"
-		"\n"
-		"If no resolver type is specified, an mdns_dns_service_manager will be used to determine which DNS service to use.\n"
-		"How the mdns_dns_service_manager's services are populated depends on whether the server and domain options are\n"
-		"specified. If either the server or domain, or both, options are specified, then an mdns_dns_service_definition\n"
-		"will be used to define a Do53 DNS service using the interface, server, and domain options. If neither the server\n"
-		"nor the domain options are specified, then the mdns_dns_service_manager will be populated with the system's DNS\n"
-		"configuration. In both of these cases, the other resolver-specific options will be ignored.\n"
-		"\n"
-	),
-	MultiStringOptionEx( 's', "server", &gQuerier_ServerAddrs, &gQuerier_ServerAddrCount, "IP address", "Server's IPv4 or IPv6 address with optionally-specified port.", false,
-		"\n"
-		"Use this option one or more times to specify a DNS service's server(s) by IP address.\n"
-		"\n"
-		"If no server IP addresses are specified for DNS over TLS/HTTPS resolvers, then connections to the DNS service\n"
-		"will use the specified provider name as the DNS service's hostname.\n"
-		"\n"
-	),
-	
-	MultiStringOptionEx( 'd', "domain", &gQuerier_Domains, &gQuerier_DomainCount, "domain name", "DNS service's domains.", false,
-		"\n"
-		"Use this option one or more times to specify a DNS service's domains. This option is ignored if a resolver type\n"
-		"is specified.\n"
-		"\n"
-	),
-	StringOption( 'p', "providerName",       &gQuerier_ProviderName,       "domain name", "Provider's domain name for DNS over TLS/HTTPS.", false ),
-	StringOption(  0 , "connectionHostname", &gQuerier_ConnectionHostname, "hostname",    "Overrides hostname used for transport layer connection for DNS over TLS/HTTPS.", false ),
-	StringOption( 'q', "urlPath",            &gQuerier_URLPath,            "path", "URL path for DNS over HTTPS.", false ),
-	StringOption( 'o', "odohConfig",         &gQuerier_ODoHConfig,         "odoh config", "Config for Oblivious DNS over HTTPS.", false ),
-	StringOption(  0 , "identityReference",  &gQuerier_IdentityReference,  "hex string", "Persistent keychain reference for a client certificate.", false ),
-	BooleanOption( 0 , "noConnectionReuse",  &gQuerier_NoConnectionReuse,  "Disable connection reuse." ),
-	BooleanOption( 0 , "squashCNAMEs",       &gQuerier_SquashCNAMEs,       "Squash CNAME chains in responses." ),
-	CLI_OPTION_END()
-};
-
-static void QuerierCommand( void );
-
-//===========================================================================================================================
-//	DNSProxy Command Options
-//===========================================================================================================================
-
-static void DNSProxyCmd( void );
-
-static char **			gDNSProxy_InputInterfaces		= NULL;
-static size_t			gDNSProxy_InputInterfaceCount	= 0;
-static const char *		gDNSProxy_OutputInterface		= NULL;
-static const char *		gDNSProxy_DNS64IPv6Prefix		= NULL;
-static int				gDNSProxy_ForceAAAASynthesis	= false;
-
-static CLIOption		kDNSProxyOpts[] =
-{
-	MultiStringOption( 'i', "inputInterface",  &gDNSProxy_InputInterfaces, &gDNSProxy_InputInterfaceCount, "name or index", "Interface to accept queries on. Can be specified more than once.", true ),
-	StringOption(      'o', "outputInterface", &gDNSProxy_OutputInterface,    "name or index", "Interface to forward queries over. Use '0' for primary interface. (default: 0)", false ),
-	StringOption(      'p', "dns64Prefix",     &gDNSProxy_DNS64IPv6Prefix,    "IPv6 prefix", "IPv6 prefix to use for DNS64 AAAA record synthesis.", false ),
-	BooleanOption(     'f', "forceAAAASynth",  &gDNSProxy_ForceAAAASynthesis, "Force AAAA synthesis for DNS64." ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	GetAddrInfoNew Command Options
-//===========================================================================================================================
-
-static const char *		gGAINew_Hostname				= NULL;
-static const char *		gGAINew_DelegatorID				= NULL;
-static const char *		gGAINew_ServiceScheme			= NULL;
-static const char *		gGAINew_AccountID				= NULL;
-static int				gGAINew_ProtocolIPv4			= false;
-static int				gGAINew_ProtocolIPv6			= false;
-static int				gGAINew_WantAuthTags			= false;
-static int				gGAINew_ShowTracker				= false;
-static int				gGAINew_UseFailover				= false;
-static int				gGAINew_ProhibitEncryptedDNS	= false;
-static int				gGAINew_OneShot					= false;
-static int				gGAINew_TimeLimitSecs			= 0;
-static const char *		gGAINew_QoS						= NULL;
-static const char *		gGAINew_ResolverUUID			= NULL;
-
-#define kQoSTypeStr_Unspecified			"unspecified"
-#define kQoSTypeStr_Background			"background"
-#define kQoSTypeStr_Utility				"utility"
-#define kQoSTypeStr_Default				"default"
-#define kQoSTypeStr_UserInitiated		"userInitiated"
-#define kQoSTypeStr_UserInteractive		"userInteractive"
-
-#define kQoSArgShortName		"QoS class"
-
-static CLIOption		kGetAddrInfoNewOpts[] =
-{
-	InterfaceOption(),
-	StringOption(  'n', "name",                 &gGAINew_Hostname,             "domain name", "Hostname to resolve.", true ),
-	StringOption(  'd', "delegate",             &gGAINew_DelegatorID,          "PID|UUID", "Delegator's PID or UUID. If PID p < 0, the audit token of PID |p| will be used.", false ),
-	StringOption(   0,  "accountID",            &gGAINew_AccountID,            "account ID", "Account ID string.", false ),
-	StringOption(   0,  "serviceScheme",        &gGAINew_ServiceScheme,        "scheme", "Service scheme such as '_443._https'.", false ),
-	BooleanOption(  0 , "ipv4",                 &gGAINew_ProtocolIPv4,         "Use kDNSServiceProtocol_IPv4." ),
-	BooleanOption(  0 , "ipv6",                 &gGAINew_ProtocolIPv6,         "Use kDNSServiceProtocol_IPv6." ),
-	BooleanOption( 'a', "wantAuthTags",         &gGAINew_WantAuthTags,         "Want authentication tags." ),
-	BooleanOption( 't', "showTracker",          &gGAINew_ShowTracker,          "Display tracker hostnames." ),
-	BooleanOption(  0,  "useFailover",          &gGAINew_UseFailover,          "Use DNS service failover if necessary and applicable." ),
-	BooleanOption(  0,  "prohibitEncryptedDNS", &gGAINew_ProhibitEncryptedDNS, "Prohibit use of encrypted DNS protocols such as DoT, DoH, ODoH, etc." ),
-	StringOption(   0,  "resolverUUID",         &gGAINew_ResolverUUID,         "UUID", "UUID of libnetwork DNS resolver configuration to use.", false ),
-	
-	CLI_OPTION_GROUP( "Flags" ),
-	DNSSDFlagsOption(),
-	DNSSDFlagsOption_AllowExpiredAnswers(),
-	DNSSDFlagsOption_DenyCellular(),
-	DNSSDFlagsOption_DenyConstrained(),
-	DNSSDFlagsOption_DenyExpensive(),
-	DNSSDFlagsOption_IncludeAWDL(),
-	DNSSDFlagsOption_PathEvalDone(),
-	DNSSDFlagsOption_ReturnIntermediates(),
-	DNSSDFlagsOption_SuppressUnusable(),
-	DNSSDFlagsOption_Timeout(),
-	
-	CLI_OPTION_GROUP( "Operation" ),
-	ConnectionOptions(),
-	BooleanOption(  'o', "oneshot",   &gGAINew_OneShot,       "Finish after first set of results." ),
-	IntegerOption(  'l', "timeLimit", &gGAINew_TimeLimitSecs, "seconds", "Time limit for dnssd_getaddrinfo operation. Use '0' for no limit. (default: 0)", false ),
-	StringOptionEx( 'q', "qos",       &gGAINew_QoS,           kQoSArgShortName, "Specifies the QoS of the queue used for the dnssd_getaddrinfo object.", false,
-		"\n"
-		"Use '" kQoSTypeStr_Unspecified     "' for QOS_CLASS_UNSPECIFIED.\n"
-		"Use '" kQoSTypeStr_Background      "' for QOS_CLASS_BACKGROUND.\n"
-		"Use '" kQoSTypeStr_Utility         "' for QOS_CLASS_UTILITY.\n"
-		"Use '" kQoSTypeStr_Default         "' for QOS_CLASS_DEFAULT.\n"
-		"Use '" kQoSTypeStr_UserInitiated   "' for QOS_CLASS_USER_INITIATED.\n"
-		"Use '" kQoSTypeStr_UserInteractive "' for QOS_CLASS_USER_INTERACTIVE.\n"
-		"\n"
-	),
-	CLI_OPTION_END()
-};
-
-static void	GetAddrInfoNewCommand( void );
-
-//===========================================================================================================================
-//	TCPInfo Command Options
-//===========================================================================================================================
-
-static const char *		gTCPInfo_LocalAddrStr	= NULL;
-static const char *		gTCPInfo_RemoteAddrStr	= NULL;
-
-static CLIOption		kTCPInfoOpts[] =
-{
-	StringOption( 'l', "local",  &gTCPInfo_LocalAddrStr,  "IP address+port", "TCP connection's local IPv4 or IPv6 address and port number.", true ),
-	StringOption( 'r', "remote", &gTCPInfo_RemoteAddrStr, "IP address+port", "TCP connection's remote IPv4 or IPv6 address and port number.", true ),
-	CLI_OPTION_END()
-};
-
-static void	TCPInfoCommand( void );
-
-#endif	// MDNSRESPONDER_PROJECT
-
-//===========================================================================================================================
-//	PF
-//===========================================================================================================================
-
-static const char *		gThreadPFNAT64_IPv6Prefix	= NULL;
-static const char *		gThreadPFNAT64_IPv4Address	= NULL;
-
-static CLIOption		kThreadPFNAT64Opts[] =
-{
-	StringOption( 'p', "prefix",  &gThreadPFNAT64_IPv6Prefix,  "IPv6 prefix", "NAT64's IPv6 prefix.", true ),
-	StringOption( 'a', "address", &gThreadPFNAT64_IPv4Address, "IPv4 address", "NAT64's IPv4 address.", true ),
-	CLI_OPTION_END()
-};
-
-static void	ThreadPFNAT64Command( void );
-static void	ThreadPFDeleteCommand( void );
-
-static CLIOption		kPFOpts[] =
-{
-	Command( "nat64",  ThreadPFNAT64Command,  kThreadPFNAT64Opts, "Set Thread border router NAT64 PF rules.", true ),
-	Command( "delete", ThreadPFDeleteCommand, NULL,               "Delete Thread border router PF rules.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	IPv4 Forwarding
-//===========================================================================================================================
-
-static void	IPv4FwdEnableCommand( void );
-static void	IPv4FwdDisableCommand( void );
-
-static CLIOption		kIPv4FwdOpts[] =
-{
-	Command( "enable",  IPv4FwdEnableCommand,  NULL, "Enable IPv4 forwarding between network interfaces.", true ),
-	Command( "disable", IPv4FwdDisableCommand, NULL, "Disable IPv4 forwarding between network interfaces.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	IPv6 Forwarding
-//===========================================================================================================================
-
-static void	IPv6FwdEnableCommand( void );
-static void	IPv6FwdDisableCommand( void );
-
-static CLIOption		kIPv6FwdOpts[] =
-{
-	Command( "enable",  IPv6FwdEnableCommand,  NULL, "Enable IPv6 forwarding between network interfaces.", true ),
-	Command( "disable", IPv6FwdDisableCommand, NULL, "Disable IPv6 forwarding between network interfaces.", true ),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Print
-//===========================================================================================================================
-
-static void	PrintCommand( void );
-
-static CLIOption		kPrintOpts[] =
-{
-	CLI_OPTIONAL_ARGUMENT( "file", "Path to the file containing the DNS message.",
-		"\n"
-		"If this argument isn't specified or the argument is '-' (a single hyphen), then the DNS message is read from\n"
-		"standard input.\n"
-	),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Command Table
-//===========================================================================================================================
-
-static OSStatus	VersionOptionCallback( CLIOption *inOption, const char *inArg, int inUnset );
-
-static void	BrowseCmd( void );
-static void	GetAddrInfoCmd( void );
-static void	QueryRecordCmd( void );
-static void	RegisterCmd( void );
-static void	RegisterRecordCmd( void );
-static void	ResolveCmd( void );
-static void	ReconfirmCmd( void );
-static void	GetAddrInfoPOSIXCmd( void );
-static void	ReverseLookupCmd( void );
-static void	PortMappingCmd( void );
-static void	BrowseAllCmd( void );
-static void	GetAddrInfoStressCmd( void );
-static void	DNSQueryCmd( void );
-#if( DNSSDUTIL_INCLUDE_DNSCRYPT )
-static void	DNSCryptCmd( void );
-#endif
-static void	MDNSQueryCmd( void );
-#if( TARGET_OS_DARWIN )
-static void	PIDToUUIDCmd( void );
-#endif
-static void	DNSProxyStateCmd( void );
-static void	DaemonVersionCmd( void );
-
-static CLIOption		kGlobalOpts[] =
-{
-	CLI_OPTION_CALLBACK_EX( 'V', "version", VersionOptionCallback, NULL, NULL,
-		kCLIOptionFlags_NoArgument | kCLIOptionFlags_GlobalOnly, "Displays the version of this tool.", NULL ),
-	CLI_OPTION_HELP(),
-	
-	// Common commands.
-	
-	Command( "browse",				BrowseCmd,				kBrowseOpts,			"Uses DNSServiceBrowse() to browse for one or more service types.", false ),
-	Command( "getAddrInfo",			GetAddrInfoCmd,			kGetAddrInfoOpts,		"Uses DNSServiceGetAddrInfo() to resolve a hostname to IP addresses.", false ),
-	Command( "queryRecord",			QueryRecordCmd,			kQueryRecordOpts,		"Uses DNSServiceQueryRecord() to query for an arbitrary DNS record.", false ),
-	Command( "register",			RegisterCmd,			kRegisterOpts,			"Uses DNSServiceRegister() to register a service.", false ),
-	Command( "registerRecord",		RegisterRecordCmd,		kRegisterRecordOpts,	"Uses DNSServiceRegisterRecord() to register a record.", false ),
-	Command( "resolve",				ResolveCmd,				kResolveOpts,			"Uses DNSServiceResolve() to resolve a service.", false ),
-	Command( "reconfirm",			ReconfirmCmd,			kReconfirmOpts,			"Uses DNSServiceReconfirmRecord() to reconfirm a record.", false ),
-	Command( "getaddrinfo-posix",	GetAddrInfoPOSIXCmd,	kGetAddrInfoPOSIXOpts,	"Uses getaddrinfo() to resolve a hostname to IP addresses.", false ),
-	Command( "reverseLookup",		ReverseLookupCmd,		kReverseLookupOpts,		"Uses DNSServiceQueryRecord() to perform a reverse IP address lookup.", false ),
-	Command( "portMapping",			PortMappingCmd,			kPortMappingOpts,		"Uses DNSServiceNATPortMappingCreate() to create a port mapping.", false ),
-#if( TARGET_OS_DARWIN )
-	Command( "registerKA",			RegisterKACmd,			kRegisterKA_Opts,		"Uses DNSServiceSleepKeepalive_sockaddr() to register a keep alive record.", false ),
-#endif
-	Command( "browseAll",			BrowseAllCmd,			kBrowseAllOpts,			"Browse and resolve all (or specific) services and, optionally, attempt connections.", false ),
-	
-	// Uncommon commands.
-	
-	Command( "getnameinfo",			GetNameInfoCmd,			kGetNameInfoOpts,		"Calls getnameinfo() and prints results.", true ),
-	Command( "getAddrInfoStress",	GetAddrInfoStressCmd,	kGetAddrInfoStressOpts,	"Runs DNSServiceGetAddrInfo() stress testing.", true ),
-	Command( "DNSQuery",			DNSQueryCmd,			kDNSQueryOpts,			"Crafts and sends a DNS query.", true ),
-#if( DNSSDUTIL_INCLUDE_DNSCRYPT )
-	Command( "DNSCrypt",			DNSCryptCmd,			kDNSCryptOpts,			"Crafts and sends a DNSCrypt query.", true ),
-#endif
-	Command( "mdnsquery",			MDNSQueryCmd,			kMDNSQueryOpts,			"Crafts and sends an mDNS query over the specified interface.", true ),
-	Command( "mdnscollider",		MDNSColliderCmd,		kMDNSColliderOpts,		"Creates record name collision scenarios.", true ),
-#if( TARGET_OS_DARWIN )
-	Command( "pid2uuid",			PIDToUUIDCmd,			kPIDToUUIDOpts,			"Prints the UUID of a process.", true ),
-#endif
-	Command( "server",				DNSServerCommand,		kDNSServerOpts,			"DNS server for testing.", true ),
-	Command( "mdnsreplier",			MDNSReplierCmd,			kMDNSReplierOpts,		"Responds to mDNS queries for a set of authoritative resource records.", true ),
-	Command( "test",				NULL,					kTestOpts,				"Commands for testing DNS-SD.", true ),
-	Command( "ssdp",				NULL,					kSSDPOpts,				"Simple Service Discovery Protocol (SSDP).", true ),
-#if( TARGET_OS_DARWIN )
-	Command( "legacy",				NULL,					kLegacyOpts,			"Legacy DNS API.", true ),
-	Command( "dnsconfig",			NULL,					kDNSConfigOpts,			"Add/remove a supplemental resolver entry to/from the system's DNS configuration.", true ),
-	Command( "xpcsend",				XPCSendCommand,			kXPCSendOpts,			"Sends a message to an XPC service.", true ),
-#endif
-#if( MDNSRESPONDER_PROJECT )
-	Command( "interfaceMonitor",	InterfaceMonitorCmd,	kInterfaceMonitorOpts,	"Instantiates an mdns_interface_monitor.", true ),
-	Command( "querier",				QuerierCommand,			kQuerierOpts,			"Sends a DNS query using mdns_querier.", true ),
-	Command( "dnsproxy",			DNSProxyCmd,			kDNSProxyOpts,			"Enables mDNSResponder's DNS proxy.", true ),
-	Command( "dnsproxy-state",		DNSProxyStateCmd,		NULL,					"Gets mDNSResponder's DNS proxy state dump.", true ),
-	Command( "getaddrinfo-new",		GetAddrInfoNewCommand,	kGetAddrInfoNewOpts,	"Uses dnssd_getaddrinfo to resolve a hostname to IP addresses.", false ),
-	Command( "tcpinfo",				TCPInfoCommand,			kTCPInfoOpts,			"Uses mdns_tcpinfo_* to get TCP info.", true ),
-#endif
-	Command( "pf",					NULL,					kPFOpts,				"Packet filter commands.", true ),
-	Command( "ipv4fwd",				NULL,					kIPv4FwdOpts,			"IPv4 forwarding commands.", true ),
-	Command( "ipv6fwd",				NULL,					kIPv6FwdOpts,			"IPv6 forwarding commands.", true ),
-	Command( "print",				PrintCommand,			kPrintOpts,				"Reads a DNS message in wire format and writes it to stdout in a human-readable form.", true ),
-	Command( "daemonVersion",		DaemonVersionCmd,		NULL,					"Prints the version of the DNS-SD daemon.", true ),
-	
-	CLI_COMMAND_HELP(),
-	CLI_OPTION_END()
-};
-
-//===========================================================================================================================
-//	Helper Prototypes
-//===========================================================================================================================
-
-#define kExitReason_OneShotDone				"one-shot done"
-#define kExitReason_ReceivedResponse		"received response"
-#define kExitReason_SIGINT					"interrupt signal"
-#define kExitReason_Timeout					"timeout"
-#define kExitReason_TimeLimit				"time limit"
-
-static void	Exit( void *inContext ) ATTRIBUTE_NORETURN;
-
-static DNSServiceFlags	GetDNSSDFlagsFromOpts( void );
-
-typedef enum
-{
-	kConnectionType_None			= 0,
-	kConnectionType_Normal			= 1,
-	kConnectionType_DelegatePID		= 2,
-	kConnectionType_DelegateUUID	= 3
-	
-}	ConnectionType;
-
-typedef struct
-{
-	ConnectionType		type;
-	union
-	{
-		int32_t			pid;
-		uint8_t			uuid[ 16 ];
-		
-	}	delegate;
-	
-}	ConnectionDesc;
-
-static OSStatus
-	CreateConnectionFromArgString(
-		const char *			inString,
-		dispatch_queue_t		inQueue,
-		DNSServiceRef *			outSDRef,
-		ConnectionDesc *		outDesc );
-static OSStatus			InterfaceIndexFromArgString( const char *inString, uint32_t *outIndex );
-static OSStatus			RecordDataFromArgString( const char *inString, uint8_t **outDataPtr, size_t *outDataLen );
-static OSStatus			RecordTypeFromArgString( const char *inString, uint16_t *outValue );
-static OSStatus			RecordClassFromArgString( const char *inString, uint16_t *outValue );
-static OSStatus			SockAddrFromArgString( const char *inString, const char *inArgName, sockaddr_ip *outSA );
-
-#define kInterfaceNameBufLen		( Max( IF_NAMESIZE, 16 ) + 1 )
-
-static char *			InterfaceIndexToName( uint32_t inIfIndex, char inNameBuf[ kInterfaceNameBufLen ] );
-static const char *		RecordTypeToString( int inValue );
-#if( MDNSRESPONDER_PROJECT )
-static const char *		RecordClassToString( int inValue );
-#endif
-
-static OSStatus
-	WriteDNSQueryMessage(
-		uint8_t			inMsg[ kDNSQueryMessageMaxLen ],
-		uint16_t		inMsgID,
-		uint16_t		inFlags,
-		const char *	inQName,
-		uint16_t		inQType,
-		uint16_t		inQClass,
-		size_t *		outMsgLen );
-
-// Dispatch helpers
-
-typedef void ( *DispatchHandler )( void *inContext );
-
-static OSStatus
-	DispatchSignalSourceCreate(
-		int					inSignal,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		void *				inContext,
-		dispatch_source_t *	outSource );
-static OSStatus
-	DispatchSocketSourceCreate(
-		SocketRef				inSock,
-		dispatch_source_type_t	inType,
-		dispatch_queue_t		inQueue,
-		DispatchHandler			inEventHandler,
-		DispatchHandler			inCancelHandler,
-		void *					inContext,
-		dispatch_source_t *		outSource );
-
-#define DispatchReadSourceCreate( SOCK, QUEUE, EVENT_HANDLER, CANCEL_HANDLER, CONTEXT, OUT_SOURCE ) \
-	DispatchSocketSourceCreate( SOCK, DISPATCH_SOURCE_TYPE_READ, QUEUE, EVENT_HANDLER, CANCEL_HANDLER, CONTEXT, OUT_SOURCE )
-
-#define DispatchWriteSourceCreate( SOCK, QUEUE, EVENT_HANDLER, CANCEL_HANDLER, CONTEXT, OUT_SOURCE ) \
-	DispatchSocketSourceCreate( SOCK, DISPATCH_SOURCE_TYPE_WRITE, QUEUE, EVENT_HANDLER, CANCEL_HANDLER, CONTEXT, OUT_SOURCE )
-
-static OSStatus
-	DispatchTimerCreate(
-		dispatch_time_t		inStart,
-		uint64_t			inIntervalNs,
-		uint64_t			inLeewayNs,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		DispatchHandler		inCancelHandler,
-		void *				inContext,
-		dispatch_source_t *	outTimer );
-
-#define DispatchTimerOneShotCreate( IN_START, IN_LEEWAY, IN_QUEUE, IN_EVENT_HANDLER, IN_CONTEXT, OUT_TIMER )	\
-	DispatchTimerCreate( IN_START, DISPATCH_TIME_FOREVER, IN_LEEWAY, IN_QUEUE, IN_EVENT_HANDLER, NULL, IN_CONTEXT, OUT_TIMER )
-
-#if( TARGET_OS_DARWIN )
-static OSStatus
-	DispatchProcessMonitorCreate(
-		pid_t				inPID,
-		unsigned long		inFlags,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		DispatchHandler		inCancelHandler,
-		void *				inContext,
-		dispatch_source_t *	outMonitor );
-#endif
-
-static const char *	ServiceTypeDescription( const char *inName );
-
-typedef void ( *SocketContextFinalizer_f )( void *inUserCtx );
-
-typedef struct
-{
-	SocketRef						sock;			// Socket.
-	int32_t							refCount;		// Reference count.
-	void *							userContext;	// User's context.
-	SocketContextFinalizer_f		userFinalizer;	// User's finalizer.
-	
-}	SocketContext;
-
-static SocketContext *	SocketContextCreate( SocketRef inSock, void *inUserContext, OSStatus *outError );
-static SocketContext *
-	SocketContextCreateEx(
-		SocketRef					inSock,
-		void *						inUserContext,
-		SocketContextFinalizer_f	inUserFinalizer,
-		OSStatus *					outError );
-static SocketContext *	SocketContextRetain( SocketContext *inContext );
-static void				SocketContextRelease( SocketContext *inContext );
-static void				SocketContextCancelHandler( void *inContext );
-static void				SocketContextFinalizerCF( void *inUserCtx );
-
-#define ForgetSocketContext( X )	ForgetCustom( X, SocketContextRelease )
-
-static OSStatus		StringToInt32( const char *inString, int32_t *outValue );
-static OSStatus		StringToUInt32( const char *inString, uint32_t *outValue );
-#if( TARGET_OS_DARWIN )
-static int64_t		_StringToInt64( const char *inString, OSStatus *outError );
-static uint64_t		_StringToUInt64( const char *inString, OSStatus *outError );
-static pid_t		_StringToPID( const char *inString, OSStatus *outError );
-static OSStatus
-	_ParseEscapedString(
-		const char *	inSrc,
-		const char *	inEnd,
-		const char *	inDelimiters,
-		char *			inBufPtr,
-		size_t			inBufLen,
-		size_t *		outCopiedLen,
-		size_t *		outActualLen,
-		const char **	outPtr );
-static OSStatus
-	_ParseEscapedStringWithCopy(
-		const char *	inSrc,
-		const char *	inEnd,
-		const char *	inDelimiters,
-		char *			inBufPtr,
-		size_t			inBufLen,
-		const char **	outString,
-		char **			outMemory,
-		const char **	outPtr );
-#endif
-static OSStatus		StringToARecordData( const char *inString, uint8_t **outPtr, size_t *outLen );
-static OSStatus		StringToAAAARecordData( const char *inString, uint8_t **outPtr, size_t *outLen );
-static OSStatus		StringToDomainName( const char *inString, uint8_t **outPtr, size_t *outLen );
-#if( TARGET_OS_DARWIN )
-static OSStatus		GetDefaultDNSServer( sockaddr_ip *outAddr );
-#endif
-static OSStatus
-	_ServerSocketOpenEx2( 
-		int				inFamily, 
-		int				inType, 
-		int				inProtocol, 
-		const void *	inAddr, 
-		int				inPort, 
-		int *			outPort, 
-		int				inRcvBufSize, 
-		Boolean			inNoPortReuse,
-		SocketRef *		outSock );
-
-static const struct sockaddr *	GetMDNSMulticastAddrV4( void );
-static const struct sockaddr *	GetMDNSMulticastAddrV6( void );
-
-static OSStatus
-	CreateMulticastSocket(
-		const struct sockaddr *	inAddr,
-		int						inPort,
-		const char *			inIfName,
-		uint32_t				inIfIndex,
-		Boolean					inJoin,
-		int *					outPort,
-		SocketRef *				outSock );
-
-static OSStatus	DecimalTextToUInt32( const char *inSrc, const char *inEnd, uint32_t *outValue, const char **outPtr );
-static OSStatus	CheckIntegerArgument( int inArgValue, const char *inArgName, int inMin, int inMax );
-static OSStatus	CheckDoubleArgument( double inArgValue, const char *inArgName, double inMin, double inMax );
-static OSStatus	CheckRootUser( void );
-#if( TARGET_OS_POSIX )
-static OSStatus
-	_SpawnCommand(
-		pid_t *			outPID,
-		const char *	inStdOutRedirect,
-		const char *	inStdErrRedirect,
-		const char *	inFormat,
-		... );
-#endif
-static OSStatus	OutputFormatFromArgString( const char *inArgString, OutputFormatType *outFormat );
-static OSStatus	OutputPropertyList( CFPropertyListRef inPList, OutputFormatType inType, const char *inOutputFilePath );
-static OSStatus	CreateSRVRecordDataFromString( const char *inString, uint8_t **outPtr, size_t *outLen );
-static OSStatus	CreateTXTRecordDataFromString( const char *inString, int inDelimiter, uint8_t **outPtr, size_t *outLen );
-static OSStatus
-	CreateNSECRecordData(
-		const uint8_t *	inNextDomainName,
-		uint8_t **		outPtr,
-		size_t *		outLen,
-		unsigned int	inTypeCount,
-		... );
-static OSStatus
-	AppendSOARecord(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass,
-		uint32_t		inTTL,
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		size_t *		outLen );
-static OSStatus
-	CreateSOARecordData(
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		uint8_t **		outPtr,
-		size_t *		outLen );
-static OSStatus
-	_DataBuffer_AppendDNSQuestion(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass );
-static OSStatus
-	_DataBuffer_AppendDNSRecord(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass,
-		uint32_t		inTTL,
-		const uint8_t *	inRDataPtr,
-		size_t			inRDataLen );
-static char *	_NanoTime64ToTimestamp( NanoTime64 inTime, char *inBuf, size_t inMaxLen );
-
-typedef struct MDNSInterfaceItem		MDNSInterfaceItem;
-struct MDNSInterfaceItem
-{
-	MDNSInterfaceItem *		next;
-	char *					ifName;
-	uint32_t				ifIndex;
-	Boolean					hasIPv4;
-	Boolean					hasIPv6;
-	Boolean					isAWDL;
-	Boolean					isWiFi;
-};
-
-typedef enum
-{
-	kMDNSInterfaceSubset_All		= 0,	// All mDNS-capable interfaces.
-	kMDNSInterfaceSubset_AWDL		= 1,	// All mDNS-capable AWDL interfaces.
-	kMDNSInterfaceSubset_NonAWDL	= 2		// All mDNS-capable non-AWDL iterfaces.
-	
-}	MDNSInterfaceSubset;
-
-static OSStatus	_MDNSInterfaceListCreate( MDNSInterfaceSubset inSubset, size_t inItemSize, MDNSInterfaceItem **outList );
-static void		_MDNSInterfaceListFree( MDNSInterfaceItem *inList );
-#define _MDNSInterfaceListForget( X )		ForgetCustom( X, _MDNSInterfaceListFree )
-static OSStatus _MDNSInterfaceGetAny( MDNSInterfaceSubset inSubset, char inNameBuf[ IF_NAMESIZE + 1 ], uint32_t *outIndex );
-
-static OSStatus	_SetComputerName( CFStringRef inComputerName, CFStringEncoding inEncoding );
-static OSStatus	_SetComputerNameWithUTF8CString( const char *inComputerName );
-static OSStatus	_SetLocalHostName( CFStringRef inLocalHostName );
-static OSStatus	_SetLocalHostNameWithUTF8CString( const char *inLocalHostName );
-#if( TARGET_OS_DARWIN )
-static OSStatus	_InterfaceIPv6AddressAdd( const char *inIfName, uint8_t inAddr[ STATIC_PARAM 16 ], int inMaskBitLen );
-static OSStatus	_InterfaceIPv6AddressRemove( const char *inIfName, const uint8_t inAddr[ STATIC_PARAM 16 ] );
-#endif
-static int64_t	_TicksDiff( uint64_t inT1, uint64_t inT2 );
-static void		_SockAddrInitIPv4( struct sockaddr_in *inSA, uint32_t inIPv4, uint16_t inPort );
-static void
-	_SockAddrInitIPv6(
-		struct sockaddr_in6 *	inSA,
-		const uint8_t			inIPv6[ STATIC_PARAM 16 ],
-		uint32_t				inScope,
-		uint16_t				inPort );
-
-#define kIP6ArpaDomainStr					"ip6.arpa."
-#define kReverseIPv6DomainNameBufLen		( ( 4 * 16 ) + sizeof_string( kIP6ArpaDomainStr ) + 1 )
-
-static void
-	_WriteReverseIPv6DomainNameString(
-		const uint8_t	inIPv6Addr[ STATIC_PARAM 16 ],
-		char			outBuffer[ STATIC_PARAM kReverseIPv6DomainNameBufLen ] );
-
-#define kInAddrArpaDomainStr				"in-addr.arpa."
-#define kReverseIPv4DomainNameBufLen		( ( 4 * 4 ) + sizeof_string( kInAddrArpaDomainStr ) + 1 )
-
-static void
-	_WriteReverseIPv4DomainNameString(
-		uint32_t	inIPv4Addr,
-		char		outBuffer[ STATIC_PARAM kReverseIPv4DomainNameBufLen ] );
-
-#if( MDNSRESPONDER_PROJECT )
-static OSStatus	_SetDefaultFallbackDNSService( const char *inFallbackDNSServiceStr );
-#endif
-
-static OSStatus
-	_StringToIPv4Address(
-		const char *			inStr,
-		StringToIPAddressFlags	inFlags,
-		uint32_t *				outIP,
-		int *					outPort,
-		uint32_t *				outSubnet,
-		uint32_t *				outRouter,
-		const char **			outStr );
-static OSStatus
-	_StringToIPv6Address(
-		const char *			inStr,
-		StringToIPAddressFlags	inFlags,
-		uint8_t					outIPv6[ 16 ],
-		uint32_t *				outScope,
-		int *					outPort,
-		int *					outPrefix,
-		const char **			outStr );
-static Boolean
-	_ParseQuotedEscapedString(
-		const char *	inSrc,
-		const char *	inEnd,
-		const char *	inDelimiters,
-		char *			inBuf,
-		size_t			inMaxLen,
-		size_t *		outCopiedLen,
-		size_t *		outTotalLen,
-		const char **	outSrc );
-static void *	_memdup( const void *inPtr, size_t inLen );
-static int		_memicmp( const void *inP1, const void *inP2, size_t inLen );
-static uint32_t	_FNV1( const void *inData, size_t inSize );
-static OSStatus	_UInt32FromArgString( const char *inArgStr, const char *inArgName, uint32_t *outValue );
-static char *	_UnixTimeToDateAndTimeString( int64_t inTimeSecs, char *inBufPtr, size_t inBufLen );
-static char *	_DNSSDSourceVersionToCString( uint32_t inVersion, char *inBufPtr, size_t inBufLen );
-static Boolean	_StdOutIsTTY( void );
-#if( TARGET_OS_IOS )
-static Boolean	_StdErrIsTTY( void );
-#endif
-static void		_PrintValidatedToStdOut( const char *inPrefix, Boolean inValidated, const char *inSuffix );
-
-static Boolean		_DNSProtocolIsSecure( DNSProtocol inProtocol );
-static const char *	_DNSProtocolToString( DNSProtocol inProtocol );
-
-#define Unused( X )		(void)(X)
-
-//===========================================================================================================================
-//	MDNSCollider
-//===========================================================================================================================
-
-typedef struct MDNSColliderPrivate *		MDNSColliderRef;
-
-typedef uint32_t		MDNSColliderProtocols;
-#define kMDNSColliderProtocol_None		0
-#define kMDNSColliderProtocol_IPv4		( 1 << 0 )
-#define kMDNSColliderProtocol_IPv6		( 1 << 1 )
-
-typedef void ( *MDNSColliderStopHandler_f )( void *inContext, OSStatus inError );
-
-static OSStatus	MDNSColliderCreate( dispatch_queue_t inQueue, MDNSColliderRef *outCollider );
-static OSStatus	MDNSColliderStart( MDNSColliderRef inCollider );
-static void		MDNSColliderStop( MDNSColliderRef inCollider );
-static void		MDNSColliderSetProtocols( MDNSColliderRef inCollider, MDNSColliderProtocols inProtocols );
-static void		MDNSColliderSetInterfaceIndex( MDNSColliderRef inCollider, uint32_t inInterfaceIndex );
-static OSStatus	MDNSColliderSetProgram( MDNSColliderRef inCollider, const char *inProgramStr );
-static void
-	MDNSColliderSetStopHandler(
-		MDNSColliderRef				inCollider,
-		MDNSColliderStopHandler_f	inStopHandler,
-		void *						inStopContext );
-static OSStatus
-	MDNSColliderSetRecord(
-		MDNSColliderRef	inCollider,
-		const uint8_t *	inName,
-		uint16_t		inType,
-		const void *	inRDataPtr,
-		size_t			inRDataLen );
-static CFTypeID	MDNSColliderGetTypeID( void );
-
-//===========================================================================================================================
-//	ServiceBrowser
-//===========================================================================================================================
-
-typedef struct ServiceBrowserPrivate *		ServiceBrowserRef;
-typedef struct ServiceBrowserResults		ServiceBrowserResults;
-typedef struct SBRDomain					SBRDomain;
-typedef struct SBRServiceType				SBRServiceType;
-typedef struct SBRServiceInstance			SBRServiceInstance;
-typedef struct SBRIPAddress					SBRIPAddress;
-
-typedef void ( *ServiceBrowserCallback_f )( ServiceBrowserResults *inResults, OSStatus inError, void *inContext );
-
-struct ServiceBrowserResults
-{
-	SBRDomain *		domainList;	// List of domains in which services were found.
-};
-
-struct SBRDomain
-{
-	SBRDomain *				next;		// Next domain in list.
-	char *					name;		// Name of domain represented by this object.
-	SBRServiceType *		typeList;	// List of service types in this domain.
-};
-
-struct SBRServiceType
-{
-	SBRServiceType *			next;			// Next service type in list.
-	char *						name;			// Name of service type represented by this object.
-	SBRServiceInstance *		instanceList;	// List of service instances of this service type.
-};
-
-struct SBRServiceInstance
-{
-	SBRServiceInstance *		next;			// Next service instance in list.
-	char *						name;			// Name of service instance represented by this object.
-	char *						hostname;		// Target from service instance's SRV record.
-	uint32_t					ifIndex;		// Index of interface over which this service instance was discovered.
-	uint16_t					port;			// Port from service instance's SRV record.
-	uint8_t *					txtPtr;			// Service instance's TXT record data.
-	size_t						txtLen;			// Service instance's TXT record data length.
-	SBRIPAddress *				ipaddrList;		// List of IP addresses that the hostname resolved to.
-	uint64_t					discoverTimeUs;	// Time it took to discover this service instance in microseconds.
-	uint64_t					resolveTimeUs;	// Time it took to resolve this service instance in microseconds.
-};
-
-struct SBRIPAddress
-{
-	SBRIPAddress *		next;			// Next IP address in list.
-	sockaddr_ip			sip;			// IPv4 or IPv6 address.
-	uint64_t			resolveTimeUs;	// Time it took to resolve this IP address in microseconds.
-	Boolean				validated;		// True if IP address is validated.
-};
-
-static CFTypeID	ServiceBrowserGetTypeID( void );
-static OSStatus
-	ServiceBrowserCreate(
-		dispatch_queue_t	inQueue,
-		uint32_t			inInterfaceIndex,
-		const char *		inDomain,
-		unsigned int		inBrowseTimeSecs,
-		Boolean				inIncludeAWDL,
-		ServiceBrowserRef *	outBrowser );
-static void		ServiceBrowserSetUseNewGAI( ServiceBrowserRef inBrowser, Boolean inUseNewGAI );
-static void		ServiceBrowserSetValidateResults( ServiceBrowserRef inBrowser, Boolean inValidateResults );
-static void		ServiceBrowserStart( ServiceBrowserRef inBrowser );
-static OSStatus	ServiceBrowserAddServiceType( ServiceBrowserRef inBrowser, const char *inServiceType );
-static void
-	ServiceBrowserSetCallback(
-		ServiceBrowserRef			inBrowser,
-		ServiceBrowserCallback_f	inCallback,
-		void *						inContext );
-static void		ServiceBrowserResultsRetain( ServiceBrowserResults *inResults );
-static void		ServiceBrowserResultsRelease( ServiceBrowserResults *inResults );
-
-#define ForgetServiceBrowserResults( X )		ForgetCustom( X, ServiceBrowserResultsRelease )
-
-//===========================================================================================================================
-//	DNSServer
-//===========================================================================================================================
-
-typedef struct DNSServerPrivate *		DNSServerRef;
-
-typedef void ( *DNSServerStartHandler_f )( uint16_t inActualPort, void *inCtx );
-typedef void ( *DNSServerStopHandler_f )( OSStatus inError, void *inCtx );
-
-static CFTypeID	DNSServerGetTypeID( void );
-static OSStatus
-	_DNSServerCreate(
-		dispatch_queue_t		inQueue,
-		DNSServerStartHandler_f	inStartHandler,
-		DNSServerStopHandler_f	inStopHandler,
-		void *					inUserContext,
-		unsigned int			inResponseDelayMs,
-		uint32_t				inDefaultTTL,
-		const sockaddr_ip *		inServerArray,
-		size_t					inServerCount,
-		const char *			inDomain,
-		Boolean					inBadUDPMode,
-		DNSServerRef *			outServer );
-static OSStatus	_DNSServerSetIgnoredQType( DNSServerRef inServer, int inQType );
-static void		_DNSServerSetPort( DNSServerRef inServer, uint16_t inPort );
-static void		_DNSServerStart( DNSServerRef inServer );
-static void		_DNSServerStop( DNSServerRef inServer );
-
-//===========================================================================================================================
-//	main
-//===========================================================================================================================
-
-#define _PRINTF_EXTENSION_HANDLER_DECLARE( NAME )	\
-	static int										\
-		_PrintFExtensionHandler_ ## NAME (			\
-			PrintFContext *	inContext,				\
-			PrintFFormat *	inFormat,				\
-			PrintFVAList *	inArgs,					\
-			void *			inUserContext )
-
-_PRINTF_EXTENSION_HANDLER_DECLARE( Timestamp );
-_PRINTF_EXTENSION_HANDLER_DECLARE( DNSMessage );
-_PRINTF_EXTENSION_HANDLER_DECLARE( RawDNSMessage );
-_PRINTF_EXTENSION_HANDLER_DECLARE( CallbackFlags );
-_PRINTF_EXTENSION_HANDLER_DECLARE( DNSRecordData );
-_PRINTF_EXTENSION_HANDLER_DECLARE( DomainName );
-
-#ifdef FUZZING
-#define main main_dnssdutil
-#endif
-
-int	main( int argc, const char **argv )
-{
-	OSStatus		err;
-	
-	// Route DebugServices logging output to stderr.
-	
-	dlog_control( "DebugServices:output=file;stderr" );
-	
-	PrintFRegisterExtension( "du:time",		_PrintFExtensionHandler_Timestamp,		NULL );
-	PrintFRegisterExtension( "du:dnsmsg",	_PrintFExtensionHandler_DNSMessage,		NULL );
-	PrintFRegisterExtension( "du:rdnsmsg",	_PrintFExtensionHandler_RawDNSMessage,	NULL );
-	PrintFRegisterExtension( "du:cbflags",	_PrintFExtensionHandler_CallbackFlags,	NULL );
-	PrintFRegisterExtension( "du:rdata",	_PrintFExtensionHandler_DNSRecordData,	NULL );
-	PrintFRegisterExtension( "du:dname",	_PrintFExtensionHandler_DomainName,		NULL );
-	CLIInit( argc, argv );
-	err = CLIParse( kGlobalOpts, kCLIFlags_None );
-	if( err ) gExitCode = 1;
-	
-	return( gExitCode );
-}
-
-//===========================================================================================================================
-//	VersionOptionCallback
-//===========================================================================================================================
-
-static OSStatus	VersionOptionCallback( CLIOption *inOption, const char *inArg, int inUnset )
-{
-	const char *		srcVers;
-#if( MDNSRESPONDER_PROJECT )
-	char				srcStr[ 16 ];
-#endif
-	
-	Unused( inOption );
-	Unused( inArg );
-	Unused( inUnset );
-	
-#if( MDNSRESPONDER_PROJECT )
-	srcVers = _DNSSDSourceVersionToCString( _DNS_SD_H, srcStr, sizeof( srcStr ) );
-#else
-	srcVers = DNSSDUTIL_SOURCE_VERSION;
-#endif
-	FPrintF( stdout, "%s version %v (%s)\n", gProgramName, kDNSSDUtilNumVersion, srcVers );
-	
-	return( kEndingErr );
-}
-
-//===========================================================================================================================
-//	BrowseCmd
-//===========================================================================================================================
-
-typedef struct BrowseResolveOp		BrowseResolveOp;
-
-struct BrowseResolveOp
-{
-	BrowseResolveOp *		next;			// Next resolve operation in list.
-	DNSServiceRef			sdRef;			// sdRef of the DNSServiceResolve or DNSServiceQueryRecord operation.
-	char *					fullName;		// Full name of the service to resolve.
-	uint32_t				interfaceIndex;	// Interface index of the DNSServiceResolve or DNSServiceQueryRecord operation.
-};
-
-typedef struct
-{
-	DNSServiceRef			mainRef;			// Main sdRef for shared connection.
-	DNSServiceRef *			opRefs;				// Array of sdRefs for individual Browse operarions.
-	size_t					opRefsCount;		// Count of array of sdRefs for non-shared connections.
-	const char *			domain;				// Domain for DNSServiceBrowse operation(s).
-	DNSServiceFlags			flags;				// Flags for DNSServiceBrowse operation(s).
-	char **					serviceTypes;		// Array of service types to browse for.
-	size_t					serviceTypesCount;	// Count of array of service types to browse for.
-	int						timeLimitSecs;		// Time limit of DNSServiceBrowse operation in seconds.
-	BrowseResolveOp *		resolveList;		// List of resolve and/or TXT record query operations.
-	uint32_t				ifIndex;			// Interface index of DNSServiceBrowse operation(s).
-	useconds_t				resolveDelayUs;		// Amount of time to wait before a resolve or TXT query in microseconds.
-	Boolean					printedHeader;		// True if results header has been printed.
-	Boolean					doResolve;			// True if service instances are to be resolved.
-	Boolean					doResolveTXTOnly;	// True if TXT records of service instances are to be queried.
-	Boolean					validateResults;	// True if signed results are requested and validated.
-	
-}	BrowseContext;
-
-#define _DNSServiceAttrForget( X )		ForgetCustom( X, DNSServiceAttributeDeallocate )
-
-static void		BrowsePrintPrologue( const BrowseContext *inContext );
-static void		BrowseContextFree( BrowseContext *inContext );
-static OSStatus	BrowseResolveOpCreate( const char *inFullName, uint32_t inInterfaceIndex, BrowseResolveOp **outOp );
-static void		BrowseResolveOpFree( BrowseResolveOp *inOp );
-static void DNSSD_API
-	BrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inRegType,
-		const char *		inDomain,
-		void *				inContext );
-static void DNSSD_API
-	BrowseResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext );
-static void DNSSD_API
-	BrowseQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-ulog_define_ex( kDNSSDUtilIdentifier, Browse, kLogLevelTrace, kLogFlags_None, "Browse", NULL );
-#define bc_ulog( LEVEL, ... )		ulog( &log_category_from_name( Browse ), (LEVEL), __VA_ARGS__ )
-
-static void	BrowseCmd( void )
-{
-	OSStatus				err;
-	size_t					i;
-	BrowseContext *			context			= NULL;
-	dispatch_source_t		signalSource	= NULL;
-	int						useMainConnection;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (BrowseContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->opRefs = (DNSServiceRef *) calloc( gBrowse_ServiceTypesCount, sizeof( DNSServiceRef ) );
-	require_action( context->opRefs, exit, err = kNoMemoryErr );
-	context->opRefsCount = gBrowse_ServiceTypesCount;
-	
-	// Check command parameters.
-	
-	if( gBrowse_TimeLimitSecs < 0 )
-	{
-		FPrintF( stderr, "Invalid time limit: %d seconds.\n", gBrowse_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Set remaining parameters.
-	
-	context->serviceTypes		= gBrowse_ServiceTypes;
-	context->serviceTypesCount	= gBrowse_ServiceTypesCount;
-	context->domain				= gBrowse_Domain;
-	context->doResolve			= gBrowse_DoResolve			? true : false;
-	context->timeLimitSecs		= gBrowse_TimeLimitSecs;
-	context->doResolveTXTOnly	= gBrowse_QueryTXT			? true : false;
-	context->validateResults	= gBrowse_ValidateResults	? true : false;
-	
-	if( gBrowse_ResolveDelayMs > 0 )
-	{
-		const int		maxDelayMs = ( (useconds_t) -1 ) / kMicrosecondsPerMillisecond;
-		
-		err = CheckIntegerArgument( gBrowse_ResolveDelayMs, "resolveDelay", INT_MIN, maxDelayMs );
-		require_noerr_quiet( err, exit );
-		
-		context->resolveDelayUs = (useconds_t)( gBrowse_ResolveDelayMs * kMicrosecondsPerMillisecond );
-	}
-#if( TARGET_OS_IOS )
-	// Check for potential issues.
-	
-	if( context->validateResults && context->doResolve && os_feature_enabled( mDNSResponder, revoke_media_sessions ) )
-	{
-		FPrintF( stderr,
-			"%s"
-			"Warning: --validate and --resolve are not compatible when media revocation is enabled.\n"
-			"         Use 'ffctl mDNSResponder/revoke_media_sessions=off' to disable.\n"
-			"%s",
-			_StdErrIsTTY() ? kANSIRed : "", _StdErrIsTTY() ? kANSINormal : "" );
-	}
-#endif
-	// Print prologue.
-	
-	BrowsePrintPrologue( context );
-	
-	// Start operation(s).
-	
-	for( i = 0; i < context->serviceTypesCount; ++i )
-	{
-		DNSServiceRef		sdRef;
-		
-		sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-		if( context->validateResults )
-		{
-			if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-			{
-				err = DNSServiceBrowseEx( &sdRef, context->flags, context->ifIndex, context->serviceTypes[ i ],
-					context->domain, &kDNSServiceAttrValidationRequired, BrowseCallback, context );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				FPrintF( stderr, "DNSServiceBrowseEx is not available on this OS." );
-				err = kUnsupportedErr;
-				goto exit;
-			}
-		}
-		else
-		{
-			err = DNSServiceBrowse( &sdRef, context->flags, context->ifIndex, context->serviceTypes[ i ],
-				context->domain, BrowseCallback, context );
-			require_noerr( err, exit );
-		}
-		context->opRefs[ i ] = sdRef;
-		if( !useMainConnection )
-		{
-			err = DNSServiceSetDispatchQueue( context->opRefs[ i ], dispatch_get_main_queue() );
-			require_noerr( err, exit );
-		}
-	}
-	
-	// Set time limit.
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(),
-			kExitReason_TimeLimit, Exit );
-	}
-	dispatch_main();
-	
-exit:
-	dispatch_source_forget( &signalSource );
-	if( context ) BrowseContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	BrowsePrintPrologue
-//===========================================================================================================================
-
-static void	BrowsePrintPrologue( const BrowseContext *inContext )
-{
-	const int						timeLimitSecs	= inContext->timeLimitSecs;
-	const char * const *			ptr				= (const char **) inContext->serviceTypes;
-	const char * const * const		end				= (const char **) inContext->serviceTypes + inContext->serviceTypesCount;
-	char							ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:         %#{flags}\n",	inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:     %d (%s)\n",	(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Service types: %s",			*ptr++ );
-	while( ptr < end ) FPrintF( stdout, ", %s",		*ptr++ );
-	FPrintF( stdout, "\n" );
-	FPrintF( stdout, "Domain:        %s\n",	inContext->domain ? inContext->domain : "<NULL> (default domains)" );
-	FPrintF( stdout, "Time limit:    " );
-	if( timeLimitSecs > 0 )	FPrintF( stdout, "%d second%?c\n", timeLimitSecs, timeLimitSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time:    %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	BrowseContextFree
-//===========================================================================================================================
-
-static void	BrowseContextFree( BrowseContext *inContext )
-{
-	size_t		i;
-	
-	for( i = 0; i < inContext->opRefsCount; ++i )
-	{
-		DNSServiceForget( &inContext->opRefs[ i ] );
-	}
-	if( inContext->serviceTypes )
-	{
-		StringArray_Free( inContext->serviceTypes, inContext->serviceTypesCount );
-		inContext->serviceTypes			= NULL;
-		inContext->serviceTypesCount	= 0;
-	}
-	DNSServiceForget( &inContext->mainRef );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	BrowseResolveOpCreate
-//===========================================================================================================================
-
-static OSStatus	BrowseResolveOpCreate( const char *inFullName, uint32_t inInterfaceIndex, BrowseResolveOp **outOp )
-{
-	OSStatus				err;
-	BrowseResolveOp *		resolveOp;
-	
-	resolveOp = (BrowseResolveOp *) calloc( 1, sizeof( *resolveOp ) );
-	require_action( resolveOp, exit, err = kNoMemoryErr );
-	
-	resolveOp->fullName = strdup( inFullName );
-	require_action( resolveOp->fullName, exit, err = kNoMemoryErr );
-	
-	resolveOp->interfaceIndex = inInterfaceIndex;
-	
-	*outOp = resolveOp;
-	resolveOp = NULL;
-	err = kNoErr;
-	
-exit:
-	if( resolveOp ) BrowseResolveOpFree( resolveOp );
-	return( err );
-}
-
-//===========================================================================================================================
-//	BrowseResolveOpFree
-//===========================================================================================================================
-
-static void	BrowseResolveOpFree( BrowseResolveOp *inOp )
-{
-	DNSServiceForget( &inOp->sdRef );
-	ForgetMem( &inOp->fullName );
-	free( inOp );
-}
-
-//===========================================================================================================================
-//	BrowseCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	BrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inRegType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	BrowseContext * const			context = (BrowseContext *) inContext;
-	OSStatus						err;
-	BrowseResolveOp *				newOp			= NULL;
-	BrowseResolveOp **				p;
-	mdns_signed_browse_result_t		signedResult	= NULL;
-	DNSServiceAttributeRef			attr			= NULL;
-	struct timeval					now;
-	Boolean 						browseOnly, resultValidated;
-	char							fullName[ kDNSServiceMaxDomainName ];
-	
-	gettimeofday( &now, NULL );
-	
-	err = inError;
-	require_noerr( err, exit );
-	
-	if( !context->printedHeader )
-	{
-		FPrintF( stdout, "%-26s  %-17s IF %-20s %-20s Instance Name\n", "Timestamp", "Flags", "Domain", "Service Type" );
-		context->printedHeader = true;
-	}
-	browseOnly		= !context->doResolve && !context->doResolveTXTOnly;
-	resultValidated	= false;
-	if( context->validateResults )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			const uint8_t *		dataPtr;
-			size_t				dataLen;
-			
-			dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-			bc_ulog( kLogLevelTrace, "Got %zu bytes of validation data for TXT query result\n", dataLen );
-			if( dataPtr )
-			{
-				if( browseOnly )
-				{
-					signedResult = mdns_signed_browse_result_create_from_data( dataPtr, dataLen, &err );
-					if( signedResult )
-					{
-						uint8_t		instanceName[ kDomainNameLengthMax ];
-						
-						err = DNSServiceConstructFullName( fullName, inName, inRegType, inDomain );
-						require_noerr( err, exit );
-						
-						err = DomainNameFromString( instanceName, fullName, NULL );
-						require_noerr( err, exit );
-						
-						if( mdns_signed_browse_result_contains( signedResult, instanceName, inInterfaceIndex ) )
-						{
-							resultValidated = true;
-						}
-						else
-						{
-							bc_ulog( kLogLevelError, "Signed browse result doesn't contain instance %s interface %d\n",
-								fullName, inInterfaceIndex );
-						}
-						mdns_forget( &signedResult );
-					}
-					else
-					{
-						bc_ulog( kLogLevelError, "mdns_signed_browse_result_create_from_data() failed: %#m\n", err );
-					}
-				}
-				else
-				{
-					attr = DNSServiceAttributeCreate();
-					require( attr, exit );
-					
-					err = DNSServiceAttrSetValidationData( attr, dataPtr, dataLen );
-					require_noerr( err, exit );
-				}
-			}
-		}
-		else
-		{
-			bc_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS\n" );
-		}
-	}
-	FPrintF( stdout, "%{du:time}  %{du:cbflags} %2d %-20s %-20s %s",
-		&now, inFlags, (int32_t) inInterfaceIndex, inDomain, inRegType, inName );
-	if( browseOnly && context->validateResults ) _PrintValidatedToStdOut( " (", resultValidated, ")" );
-	FPrintF( stdout, "\n" );
-	if( browseOnly ) goto exit;
-	
-	err = DNSServiceConstructFullName( fullName, inName, inRegType, inDomain );
-	require_noerr( err, exit );
-	
-	if( inFlags & kDNSServiceFlagsAdd )
-	{
-		DNSServiceRef		sdRef;
-		DNSServiceFlags		flags;
-		
-		err = BrowseResolveOpCreate( fullName, inInterfaceIndex, &newOp );
-		require_noerr( err, exit );
-		
-		if( context->mainRef )
-		{
-			sdRef = context->mainRef;
-			flags = kDNSServiceFlagsShareConnection;
-		}
-		else
-		{
-			flags = 0;
-		}
-		if( context->resolveDelayUs > 0 ) usleep( context->resolveDelayUs );
-		if( context->doResolve )
-		{
-			if( attr )
-			{
-				if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-				{
-					err = DNSServiceResolveEx( &sdRef, flags, inInterfaceIndex, inName, inRegType, inDomain, attr,
-						BrowseResolveCallback, context );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					bc_ulog( kLogLevelError, "DNSServiceResolveEx is not available on this OS\n" );
-					err = kUnsupportedErr;
-					goto exit;
-				}
-			}
-			else
-			{
-				err = DNSServiceResolve( &sdRef, flags, inInterfaceIndex, inName, inRegType, inDomain,
-					BrowseResolveCallback, context );
-				require_noerr( err, exit );
-			}
-		}
-		else
-		{
-			if( attr )
-			{
-				if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-				{
-					err = DNSServiceQueryRecordWithAttribute( &sdRef, flags, inInterfaceIndex, fullName,
-						kDNSServiceType_TXT, kDNSServiceClass_IN, attr, BrowseQueryRecordCallback, context );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					bc_ulog( kLogLevelError, "DNSServiceQueryRecordWithAttribute is not available on this OS\n" );
-					err = kUnsupportedErr;
-					goto exit;
-				}
-			}
-			else
-			{
-				err = DNSServiceQueryRecord( &sdRef, flags, inInterfaceIndex, fullName, kDNSServiceType_TXT,
-					kDNSServiceClass_IN, BrowseQueryRecordCallback, context );
-				require_noerr( err, exit );
-			}
-		}
-		
-		newOp->sdRef = sdRef;
-		if( !context->mainRef )
-		{
-			err = DNSServiceSetDispatchQueue( newOp->sdRef, dispatch_get_main_queue() );
-			require_noerr( err, exit );
-		}
-		for( p = &context->resolveList; *p; p = &( *p )->next ) {}
-		*p = newOp;
-		newOp = NULL;
-	}
-	else
-	{
-		BrowseResolveOp *		resolveOp;
-		
-		for( p = &context->resolveList; ( resolveOp = *p ) != NULL; p = &resolveOp->next )
-		{
-			if( ( resolveOp->interfaceIndex == inInterfaceIndex ) && ( strcasecmp( resolveOp->fullName, fullName ) == 0 ) )
-			{
-				break;
-			}
-		}
-		if( resolveOp )
-		{
-			*p = resolveOp->next;
-			BrowseResolveOpFree( resolveOp );
-		}
-	}
-	
-exit:
-	mdns_forget( &signedResult );
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-	if( newOp ) BrowseResolveOpFree( newOp );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	BrowseQueryRecordCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	BrowseQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus				err;
-	BrowseContext * const	context = (BrowseContext *) inContext;
-	struct timeval			now;
-	Boolean					txtValidated = false;
-	
-	Unused( inClass );
-	Unused( inTTL );
-	
-	gettimeofday( &now, NULL );
-	
-	err = inError;
-	require_noerr( err, exit );
-	require_action( inType == kDNSServiceType_TXT, exit, err = kTypeErr );
-	
-	if( context->validateResults )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			const uint8_t *		dataPtr;
-			size_t				dataLen;
-			
-			dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-			bc_ulog( kLogLevelTrace, "Got %zu bytes of validation data for TXT query result\n", dataLen );
-			if( dataPtr )
-			{
-				mdns_signed_browse_result_t		signedResult;
-				
-				signedResult = mdns_signed_browse_result_create_from_data( dataPtr, dataLen, &err );
-				if( signedResult )
-				{
-					if( mdns_signed_browse_result_covers_txt_rdata( signedResult, inRDataPtr, inRDataLen ) )
-					{
-						txtValidated = true;
-					}
-					else
-					{
-						bc_ulog( kLogLevelError, "Signed resolve result doesn't cover TXT record data\n" );
-					}
-					mdns_forget( &signedResult );
-				}
-				else
-				{
-					bc_ulog( kLogLevelError, "mdns_signed_resolve_result_create_from_data() failed: %#m\n", err );
-				}
-			}
-		}
-		else
-		{
-			bc_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS\n" );
-		}
-	}
-	FPrintF( stdout, "%{du:time}  %s %s TXT on interface %d\n    TXT: %#{txt}",
-		&now, DNSServiceFlagsToAddRmvStr( inFlags ), inFullName, (int32_t) inInterfaceIndex, inRDataPtr,
-		(size_t) inRDataLen );
-	if( context->validateResults ) _PrintValidatedToStdOut( " (", txtValidated, ")" );
-	FPrintF( stdout, "\n" );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	BrowseResolveCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	BrowseResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext )
-{
-	BrowseContext * const	context = (BrowseContext *) inContext;
-	struct timeval			now;
-	char					errorStr[ 64 ];
-	Boolean					txtValidated = false;
-	
-	Unused( inFlags );
-	
-	gettimeofday( &now, NULL );
-	
-	if( inError ) SNPrintF( errorStr, sizeof( errorStr ), " error %#m", inError );
-	
-	if( context->validateResults )
-	{
-		OSStatus	err;
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			const uint8_t *		dataPtr;
-			size_t				dataLen;
-			
-			dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-			bc_ulog( kLogLevelTrace, "Got %zu bytes of validation data for resolve result\n", dataLen );
-			if( dataPtr )
-			{
-				mdns_signed_resolve_result_t		signedResult;
-				
-				signedResult = mdns_signed_resolve_result_create_from_data( dataPtr, dataLen, &err );
-				if( signedResult )
-				{
-					if( mdns_signed_resolve_result_covers_txt_rdata( signedResult, inTXTPtr, inTXTLen ) )
-					{
-						txtValidated = true;
-					}
-					else
-					{
-						bc_ulog( kLogLevelError, "Signed resolve result doesn't cover TXT record data\n" );
-					}
-					mdns_forget( &signedResult );
-				}
-				else
-				{
-					bc_ulog( kLogLevelError, "mdns_signed_resolve_result_create_from_data() failed: %#m\n", err );
-				}
-			}
-		}
-		else
-		{
-			bc_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS\n" );
-		}
-	}
-	
-	FPrintF( stdout, "%{du:time}  %s can be reached at %s:%u (interface %d)%?s\n",
-		&now, inFullName, inHostname, ntohs( inPort ), (int32_t) inInterfaceIndex, inError, errorStr );
-	if( inTXTLen == 1 )
-	{
-		FPrintF( stdout, " TXT record: %#H", inTXTPtr, (int) inTXTLen, INT_MAX );
-	}
-	else
-	{
-		FPrintF( stdout, " TXT record: %#{txt}", inTXTPtr, (size_t) inTXTLen );
-	}
-	if( context->validateResults ) _PrintValidatedToStdOut( " (", txtValidated, ")" );
-	FPrintF( stdout, "\n" );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef			mainRef;		// Main sdRef for shared connection.
-	DNSServiceRef			opRef;			// sdRef for the DNSServiceGetAddrInfo operation.
-	const char *			name;			// Hostname to resolve.
-	DNSServiceFlags			flags;			// Flags argument for DNSServiceGetAddrInfo().
-	DNSServiceProtocol		protocols;		// Protocols argument for DNSServiceGetAddrInfo().
-	uint32_t				ifIndex;		// Interface index argument for DNSServiceGetAddrInfo().
-	int						timeLimitSecs;	// Time limit for the DNSServiceGetAddrInfo() operation in seconds.
-	Boolean					printedHeader;	// True if the results header has been printed.
-	Boolean					oneShotMode;	// True if command is done after the first set of results (one-shot mode).
-	Boolean					needIPv4;		// True if in one-shot mode and an IPv4 result is needed.
-	Boolean					needIPv6;		// True if in one-shot mode and an IPv6 result is needed.
-	
-}	GetAddrInfoContext;
-
-static void	GetAddrInfoPrintPrologue( const GetAddrInfoContext *inContext );
-static void	GetAddrInfoContextFree( GetAddrInfoContext *inContext );
-static void DNSSD_API
-	GetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-static void	GetAddrInfoCmd( void )
-{
-	OSStatus					err;
-	DNSServiceRef				sdRef;
-	GetAddrInfoContext *		context			= NULL;
-	dispatch_source_t			signalSource	= NULL;
-	int							useMainConnection;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Check command parameters.
-	
-	if( gGetAddrInfo_TimeLimitSecs < 0 )
-	{
-		FPrintF( stderr, "Invalid time limit: %d s.\n", gGetAddrInfo_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-#if( MDNSRESPONDER_PROJECT )
-	if( gFallbackDNSService )
-	{
-		err = _SetDefaultFallbackDNSService( gFallbackDNSService );
-		require_noerr_quiet( err, exit );
-	}
-#endif
-	// Create context.
-	
-	context = (GetAddrInfoContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Set remaining parameters.
-	
-	context->name			= gGetAddrInfo_Name;
-	context->timeLimitSecs	= gGetAddrInfo_TimeLimitSecs;
-	if( gGetAddrInfo_ProtocolIPv4 ) context->protocols |= kDNSServiceProtocol_IPv4;
-	if( gGetAddrInfo_ProtocolIPv6 ) context->protocols |= kDNSServiceProtocol_IPv6;
-	if( gGetAddrInfo_OneShot )
-	{
-		context->oneShotMode	= true;
-		context->needIPv4		= ( gGetAddrInfo_ProtocolIPv4 || !gGetAddrInfo_ProtocolIPv6 ) ? true : false;
-		context->needIPv6		= ( gGetAddrInfo_ProtocolIPv6 || !gGetAddrInfo_ProtocolIPv4 ) ? true : false;
-	}
-	
-	// Print prologue.
-	
-	GetAddrInfoPrintPrologue( context );
-	
-	// Start operation.
-	
-	sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-	err = DNSServiceGetAddrInfo( &sdRef, context->flags, context->ifIndex, context->protocols, context->name,
-		GetAddrInfoCallback, context );
-	require_noerr( err, exit );
-	
-	context->opRef = sdRef;
-	if( !useMainConnection )
-	{
-		err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-	}
-	
-	// Set time limit.
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(),
-			kExitReason_TimeLimit, Exit );
-	}
-	dispatch_main();
-	
-exit:
-	dispatch_source_forget( &signalSource );
-	if( context ) GetAddrInfoContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoPrintPrologue
-//===========================================================================================================================
-
-static void	GetAddrInfoPrintPrologue( const GetAddrInfoContext *inContext )
-{
-	const int		timeLimitSecs = inContext->timeLimitSecs;
-	char			ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:      %#{flags}\n",		inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:  %d (%s)\n",		(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Protocols:  %#{flags}\n",		inContext->protocols, kDNSServiceProtocolDescriptors );
-	FPrintF( stdout, "Name:       %s\n",			inContext->name );
-	FPrintF( stdout, "Mode:       %s\n",			inContext->oneShotMode ? "one-shot" : "continuous" );
-	FPrintF( stdout, "Time limit: " );
-	if( timeLimitSecs > 0 )	FPrintF( stdout, "%d second%?c\n", timeLimitSecs, timeLimitSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoContextFree
-//===========================================================================================================================
-
-static void	GetAddrInfoContextFree( GetAddrInfoContext *inContext )
-{
-	DNSServiceForget( &inContext->opRef );
-	DNSServiceForget( &inContext->mainRef );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	GetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	GetAddrInfoContext * const		context = (GetAddrInfoContext *) inContext;
-	struct timeval					now;
-	OSStatus						err;
-	const char *					addrStr;
-	char							addrStrBuf[ kSockAddrStringMaxSize ];
-	
-	Unused( inSDRef );
-	
-	gettimeofday( &now, NULL );
-	
-	switch( inError )
-	{
-		case kDNSServiceErr_NoError:
-		case kDNSServiceErr_NoSuchRecord:
-			err = kNoErr;
-			break;
-		
-		case kDNSServiceErr_Timeout:
-			Exit( kExitReason_Timeout );
-		
-		default:
-			err = inError;
-			goto exit;
-	}
-	
-	if( ( inSockAddr->sa_family != AF_INET ) && ( inSockAddr->sa_family != AF_INET6 ) )
-	{
-		dlogassert( "Unexpected address family: %d", inSockAddr->sa_family );
-		err = kTypeErr;
-		goto exit;
-	}
-	
-	if( !inError )
-	{
-		err = SockAddrToString( inSockAddr, kSockAddrStringFlagsNone, addrStrBuf );
-		require_noerr( err, exit );
-		addrStr = addrStrBuf;
-	}
-	else
-	{
-		addrStr = ( inSockAddr->sa_family == AF_INET ) ? kNoSuchRecordAStr : kNoSuchRecordAAAAStr;
-	}
-	
-	if( !context->printedHeader )
-	{
-		FPrintF( stdout, "%-26s  %-17s IF %-30s %-34s %6s\n", "Timestamp", "Flags", "Hostname", "Address", "TTL" );
-		context->printedHeader = true;
-	}
-	FPrintF( stdout, "%{du:time}  %{du:cbflags} %2d %-30s %-34s %6u\n",
-		&now, inFlags, (int32_t) inInterfaceIndex, inHostname, addrStr, inTTL );
-	
-	if( context->oneShotMode )
-	{
-		if( inFlags & kDNSServiceFlagsAdd )
-		{
-			if( inSockAddr->sa_family == AF_INET )	context->needIPv4 = false;
-			else									context->needIPv6 = false;
-		}
-		if( !( inFlags & kDNSServiceFlagsMoreComing ) && !context->needIPv4 && !context->needIPv6 )
-		{
-			Exit( kExitReason_OneShotDone );
-		}
-	}
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	QueryRecordCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef		mainRef;			// Main sdRef for shared connection.
-	DNSServiceRef		opRef;				// sdRef for the DNSServiceQueryRecord operation.
-	const char *		recordName;			// Resource record name argument for DNSServiceQueryRecord().
-	DNSServiceFlags		flags;				// Flags argument for DNSServiceQueryRecord().
-	uint32_t			ifIndex;			// Interface index argument for DNSServiceQueryRecord().
-	int					timeLimitSecs;		// Time limit for the DNSServiceQueryRecord() operation in seconds.
-	uint16_t			recordType;			// Resource record type argument for DNSServiceQueryRecord().
-	Boolean				useAAAAFallback;	// True if query for AAAA should fallback to A if AAAA doesn't exist.
-	Boolean				useFailover;		// True if DNS service failover should be used if necessary and applicable.
-	Boolean				printedHeader;		// True if the results header was printed.
-	Boolean				oneShotMode;		// True if command is done after the first set of results (one-shot mode).
-	Boolean				gotRecord;			// True if in one-shot mode and received at least one record of the desired type.
-	Boolean				printRawRData;		// True if RDATA results are not to be formatted when printed.
-	
-}	QueryRecordContext;
-
-static void	QueryRecordPrintPrologue( const QueryRecordContext *inContext );
-static void	QueryRecordContextFree( QueryRecordContext *inContext );
-static void DNSSD_API
-	QueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-static void	QueryRecordCmd( void )
-{
-	OSStatus					err;
-	DNSServiceRef				sdRef;
-	DNSServiceAttributeRef		attr			= NULL;
-	QueryRecordContext *		context			= NULL;
-	dispatch_source_t			signalSource	= NULL;
-	int							useMainConnection;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (QueryRecordContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Check command parameters.
-	
-	if( gQueryRecord_TimeLimitSecs < 0 )
-	{
-		FPrintF( stderr, "Invalid time limit: %d seconds.\n", gQueryRecord_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-#if( MDNSRESPONDER_PROJECT )
-	if( gFallbackDNSService )
-	{
-		err = _SetDefaultFallbackDNSService( gFallbackDNSService );
-		require_noerr_quiet( err, exit );
-	}
-#endif
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Get record type.
-	
-	err = RecordTypeFromArgString( gQueryRecord_Type, &context->recordType );
-	require_noerr( err, exit );
-	
-	// Set remaining parameters.
-	
-	context->recordName			= gQueryRecord_Name;
-	context->timeLimitSecs		= gQueryRecord_TimeLimitSecs;
-	context->useAAAAFallback	= gQueryRecord_AAAAFallback ? true : false;
-	context->useFailover		= gQueryRecord_UseFailover  ? true : false;
-	context->oneShotMode		= gQueryRecord_OneShot      ? true : false;
-	context->printRawRData		= gQueryRecord_RawRData     ? true : false;
-	
-	// Print prologue.
-	
-	QueryRecordPrintPrologue( context );
-	
-	// Start operation.
-	
-	if( context->useAAAAFallback || context->useFailover )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			attr = DNSServiceAttributeCreate();
-			require_action( attr, exit, err = kNoResourcesErr );
-			if( context->useAAAAFallback )
-			{
-				err = DNSServiceAttributeSetAAAAPolicy( attr, kDNSServiceAAAAPolicyFallback );
-				require_noerr( err, exit );
-			}
-			if( context->useFailover )
-			{
-				err = DNSServiceAttrSetFailoverPolicy( attr, kDNSServiceFailoverPolicyAllow );
-				require_noerr( err, exit );
-			}
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceAttributeCreate is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-	if( attr )
-	{
-
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			err = DNSServiceQueryRecordWithAttribute( &sdRef, context->flags, context->ifIndex, context->recordName,
-				context->recordType, kDNSServiceClass_IN, attr, QueryRecordCallback, context );
-			require_noerr( err, exit );
-			_DNSServiceAttrForget( &attr );
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceQueryRecordWithAttribute is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = DNSServiceQueryRecord( &sdRef, context->flags, context->ifIndex, context->recordName, context->recordType,
-			kDNSServiceClass_IN, QueryRecordCallback, context );
-		require_noerr( err, exit );
-	}
-	
-	context->opRef = sdRef;
-	if( !useMainConnection )
-	{
-		err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-	}
-	
-	// Set time limit.
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(), kExitReason_TimeLimit,
-			Exit );
-	}
-	dispatch_main();
-	
-exit:
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-	dispatch_source_forget( &signalSource );
-	if( context ) QueryRecordContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	QueryRecordContextFree
-//===========================================================================================================================
-
-static void	QueryRecordContextFree( QueryRecordContext *inContext )
-{
-	DNSServiceForget( &inContext->opRef );
-	DNSServiceForget( &inContext->mainRef );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	QueryRecordPrintPrologue
-//===========================================================================================================================
-
-static void	QueryRecordPrintPrologue( const QueryRecordContext *inContext )
-{
-	const int		timeLimitSecs = inContext->timeLimitSecs;
-	char			ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:          %#{flags}\n",	inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:      %d (%s)\n",	(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Name:           %s\n",		inContext->recordName );
-	FPrintF( stdout, "Type:           %s (%u)\n",	RecordTypeToString( inContext->recordType ), inContext->recordType );
-	FPrintF( stdout, "AAAA Fallback:  %s\n",		YesNoStr( inContext->useAAAAFallback ) );
-	FPrintF( stdout, "Mode:           %s\n",		inContext->oneShotMode ? "one-shot" : "continuous" );
-	FPrintF( stdout, "Time limit:     " );
-	if( timeLimitSecs > 0 )	FPrintF( stdout, "%d second%?c\n", timeLimitSecs, timeLimitSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time:     %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-	
-}
-
-//===========================================================================================================================
-//	QueryRecordCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	QueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	QueryRecordContext * const		context		= (QueryRecordContext *) inContext;
-	struct timeval					now;
-	OSStatus						err;
-	char *							rdataStrMem	= NULL;
-	const char *					rdataStr;
-	
-	Unused( inSDRef );
-	
-	gettimeofday( &now, NULL );
-	
-	switch( inError )
-	{
-		case kDNSServiceErr_NoError:
-			if( !context->printRawRData ) DNSRecordDataToString( inRDataPtr, inRDataLen, inType, &rdataStrMem );
-			if( !rdataStrMem )
-			{
-				ASPrintF( &rdataStrMem, "%#H", inRDataPtr, (int) inRDataLen, INT_MAX );
-				require_action( rdataStrMem, exit, err = kNoMemoryErr );
-			}
-			rdataStr = rdataStrMem;
-			break;
-		
-		case kDNSServiceErr_NoSuchRecord:
-			rdataStr = kNoSuchRecordStr;
-			break;
-		
-		case kDNSServiceErr_NoSuchName:
-			rdataStr = kNoSuchNameStr;
-			break;
-		
-		case kDNSServiceErr_Timeout:
-			Exit( kExitReason_Timeout );
-		
-		default:
-			err = inError;
-			goto exit;
-	}
-	if( !context->printedHeader )
-	{
-		FPrintF( stdout, "%-26s  %-17s IF %-32s %-5s %-5s %6s RData\n",
-			"Timestamp", "Flags", "Name", "Type", "Class", "TTL" );
-		context->printedHeader = true;
-	}
-	FPrintF( stdout, "%{du:time}  %{du:cbflags} %2d %-32s %-5s %?-5s%?5u %6u %s\n",
-		&now, inFlags, (int32_t) inInterfaceIndex, inFullName, RecordTypeToString( inType ),
-		( inClass == kDNSServiceClass_IN ), "IN", ( inClass != kDNSServiceClass_IN ), inClass, inTTL, rdataStr );
-	
-	if( context->oneShotMode )
-	{
-		if( ( inFlags & kDNSServiceFlagsAdd ) &&
-			( ( context->recordType == kDNSServiceType_ANY ) || ( context->recordType == inType ) ) )
-		{
-			context->gotRecord = true;
-		}
-		if( !( inFlags & kDNSServiceFlagsMoreComing ) && context->gotRecord ) Exit( kExitReason_OneShotDone );
-	}
-	err = kNoErr;
-	
-exit:
-	ForgetMem( &rdataStrMem );
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	RegisterCmd
-//===========================================================================================================================
-
-typedef struct RecordUpdate		RecordUpdate;
-struct RecordUpdate
-{
-	RecordUpdate *		next;		// Next record update in list.
-	uint8_t *			dataPtr;	// Record data.
-	size_t				dataLen;	// Record data length.
-	uint32_t			ttl;		// Record TTL value.
-	uint32_t			delayMs;	// Update delay in milliseconds.
-};
-
-typedef struct
-{
-	DNSRecordRef		recordRef;	// Reference returned by DNSServiceAddRecord().
-	uint8_t *			dataPtr;	// Record data.
-	size_t				dataLen;	// Record data length.
-	uint32_t			ttl;		// Record TTL value.
-	uint16_t			type;		// Record type.
-	
-}	ExtraRecord;
-
-typedef struct
-{
-	DNSServiceRef			opRef;				// sdRef for DNSServiceRegister operation.
-	const char *			name;				// Service name argument for DNSServiceRegister().
-	const char *			type;				// Service type argument for DNSServiceRegister().
-	const char *			domain;				// Domain in which advertise the service.
-	uint8_t *				txtPtr;				// Service TXT record data. (malloc'd)
-	size_t					txtLen;				// Service TXT record data len.
-	ExtraRecord *			extraRecords;		// Array of extra records to add to registered service.
-	size_t					extraRecordsCount;	// Number of extra records.
-	RecordUpdate *			txtUpdates;			// List of TXT record updates. (malloc'd)
-	dispatch_source_t		updateTimer;		// Timer for the next delayed TXT record update.
-	dispatch_source_t		lifetimeTimer;		// Timer for the registration's lifetime.
-	DNSServiceFlags			flags;				// Flags argument for DNSServiceRegister().
-	uint32_t				ifIndex;			// Interface index argument for DNSServiceRegister().
-	int						lifetimeMs;			// Lifetime of the record registration in milliseconds.
-	uint32_t				timestamp;			// Timestamp in seconds since epoch time to indicate when the service is registered.
-	uint16_t				port;				// Service instance's port number.
-	Boolean					setTimestamp;		// True if the timestamp attribute needs to be set.
-	Boolean					printedHeader;		// True if results header was printed.
-	Boolean					didRegister;		// True if service was registered.
-}	RegisterContext;
-
-static void	RegisterPrintPrologue( const RegisterContext *inContext );
-static void	RegisterContextFree( RegisterContext *inContext );
-static void DNSSD_API
-	RegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain,
-		void *				inContext );
-static OSStatus	_RegisterHandleTXTRecordUpdates( RegisterContext *inContext );
-static void		_RegisterUpdateTimerHandler( void *inContext );
-static void		_RecordUpdateFree( RecordUpdate *inUpdate );
-#define _RecordUpdateForget( X )		ForgetCustom( X, _RecordUpdateFree )
-
-static void	RegisterCmd( void )
-{
-	OSStatus					err;
-	RegisterContext *			context			= NULL;
-	dispatch_source_t			signalSource	= NULL;
-	DNSServiceAttributeRef		attr			= NULL;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (RegisterContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Check command parameters.
-	
-	err = CheckIntegerArgument( gRegister_Port, "port", 0, UINT16_MAX );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( ( gAddRecord_TypesCount == gAddRecord_DataCount ) &&
-		( ( gAddRecord_TTLsCount == 0 ) || ( gAddRecord_TTLsCount == gAddRecord_TypesCount ) ), exit,
-		FPrintF( stderr, "There are missing additional record parameters.\n" ); err = kParamErr );
-	require_action_quiet( ( gUpdateRecord_DataCount == gUpdateRecord_DelayCount ) &&
-		( ( gUpdateRecord_TTLCount == 0 ) || ( gUpdateRecord_TTLCount == gUpdateRecord_DataCount ) ), exit,
-		FPrintF( stderr, "There are missing update record parameters.\n" ); err = kParamErr );
-
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Get TXT record data.
-	
-	if( gRegister_TXT )
-	{
-		err = RecordDataFromArgString( gRegister_TXT, &context->txtPtr, &context->txtLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// Set remaining parameters.
-	
-	context->name		= gRegister_Name;
-	context->type		= gRegister_Type;
-	context->domain		= gRegister_Domain;
-	context->port		= (uint16_t) gRegister_Port;
-	context->lifetimeMs	= gRegister_LifetimeMs;
-	if ( gRegister_TimeOfReceipt )
-	{
-		err = _UInt32FromArgString( gRegister_TimeOfReceipt, "timestamp", &context->timestamp );
-		require_noerr_quiet( err, exit );
-
-		context->setTimestamp = true;
-	}
-	
-	if( gAddRecord_TypesCount > 0 )
-	{
-		size_t		i;
-		
-		context->extraRecords = (ExtraRecord *) calloc( gAddRecord_TypesCount, sizeof( *context->extraRecords ) );
-		require_action( context->extraRecords, exit, err = kNoMemoryErr );
-		context->extraRecordsCount = gAddRecord_TypesCount;
-		
-		for( i = 0; i < gAddRecord_TypesCount; ++i )
-		{
-			ExtraRecord * const		extraRecord = &context->extraRecords[ i ];
-			
-			err = RecordTypeFromArgString( gAddRecord_Types[ i ], &extraRecord->type );
-			require_noerr( err, exit );
-			
-			err = RecordDataFromArgString( gAddRecord_Data[ i ], &extraRecord->dataPtr, &extraRecord->dataLen );
-			require_noerr_quiet( err, exit );
-			
-			if( gAddRecord_TTLsCount > 0 )
-			{
-				err = StringToUInt32( gAddRecord_TTLs[ i ], &extraRecord->ttl );
-				require_noerr_action_quiet( err, exit,
-					FPrintF( stderr, "Invalid TTL value: '%s'\n", gAddRecord_TTLs[ i ] ); err = kParamErr );
-			}
-			else
-			{
-				extraRecord->ttl = 0;
-			}
-		}
-	}
-	
-	if( gUpdateRecord_DataCount > 0 )
-	{
-		size_t				i;
-		RecordUpdate **		ptr = &context->txtUpdates;
-		
-		for( i = 0; i < gUpdateRecord_DataCount; ++i )
-		{
-			RecordUpdate *		update;
-			
-			update = (RecordUpdate *) calloc( 1, sizeof( *update ) );
-			require_action( update, exit, err = kNoMemoryErr );
-			*ptr = update;
-			ptr = &update->next;
-			
-			err = RecordDataFromArgString( gUpdateRecord_Datas[ i ], &update->dataPtr, &update->dataLen );
-			require_noerr_quiet( err, exit );
-			
-			err = StringToUInt32( gUpdateRecord_DelaysMs[ i ], &update->delayMs );
-			require_noerr_action_quiet( err, exit,
-				FPrintF( stderr, "Invalid delay value: '%s'\n", gUpdateRecord_DelaysMs[ i ] ); err = kParamErr );
-			
-			if( gUpdateRecord_TTLCount > 0 )
-			{
-				err = StringToUInt32( gUpdateRecord_TTLs[ i ], &update->ttl );
-				require_noerr_action_quiet( err, exit,
-					FPrintF( stderr, "Invalid TTL value: '%s'\n", gUpdateRecord_TTLs[ i ] ); err = kParamErr );
-			}
-			else
-			{
-				update->ttl = 0;
-			}
-		}
-	}
-	
-	// Print prologue.
-	
-	RegisterPrintPrologue( context );
-	
-	// Start operation.
-	
-	if( context->setTimestamp )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			attr = DNSServiceAttributeCreate();
-			require_action( attr, exit, err = kNoResourcesErr );
-			
-			err = DNSServiceAttributeSetTimestamp( attr, context->timestamp );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceAttributeCreate is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	if( attr )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			err = DNSServiceRegisterWithAttribute( &context->opRef, context->flags, context->ifIndex, context->name,
-				context->type, context->domain, NULL, htons( context->port ), (uint16_t) context->txtLen, context->txtPtr,
-				attr, RegisterCallback, context );
-			require_noerr( err, exit );
-			_DNSServiceAttrForget( &attr );
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceRegisterWithAttribute is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = DNSServiceRegister( &context->opRef, context->flags, context->ifIndex, context->name, context->type,
-			context->domain, NULL, htons( context->port ), (uint16_t) context->txtLen, context->txtPtr,
-			RegisterCallback, context );
-		ForgetMem( &context->txtPtr );
-		require_noerr( err, exit );
-	}
-	err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-	require_noerr( err, exit );
-	
-	dispatch_main();
-	
-exit:
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-	dispatch_source_forget( &signalSource );
-	if( context ) RegisterContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	RegisterPrintPrologue
-//===========================================================================================================================
-
-static void	RegisterPrintPrologue( const RegisterContext *inContext )
-{
-	char					ifName[ kInterfaceNameBufLen ];
-	const char * const		defaultTTLStr = " (system will use a default value.)";
-	Boolean					printedRecords;
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:      %#{flags}\n",	inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:  %d (%s)\n",	(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Name:       %s\n",		inContext->name ? inContext->name : "<NULL>" );
-	FPrintF( stdout, "Type:       %s\n",		inContext->type );
-	FPrintF( stdout, "Domain:     %s\n",		inContext->domain ? inContext->domain : "<NULL> (default domains)" );
-	FPrintF( stdout, "Port:       %u\n",		inContext->port );
-	FPrintF( stdout, "TXT data:   %#{txt}\n",	inContext->txtPtr, inContext->txtLen );
-	if( inContext->setTimestamp )
-	{
-		const char *		dateTimeStr;
-		char				dateTimeBuf[ 32 ];
-		
-		FPrintF( stdout, "Timestamp:  %u", inContext->timestamp );
-		dateTimeStr = _UnixTimeToDateAndTimeString( inContext->timestamp, dateTimeBuf, sizeof( dateTimeBuf ) );
-		if( dateTimeStr ) FPrintF( stdout, " (%s)", dateTimeStr );
-		FPrintF( stdout, "\n" );
-	}
-	if( inContext->lifetimeMs < 0 )	FPrintF( stdout, "Lifetime:   ∞ ms\n" );
-	else							FPrintF( stdout, "Lifetime:   %d ms\n", inContext->lifetimeMs );
-	
-	printedRecords = false;
-	if( inContext->extraRecordsCount > 0 )
-	{
-		size_t		i;
-		
-		for( i = 0; i < inContext->extraRecordsCount; ++i )
-		{
-			const ExtraRecord *		record = &inContext->extraRecords[ i ];
-			
-			FPrintF( stdout, "\nExtra record #%zu:\n",		i + 1 );
-			FPrintF( stdout, "    Type:  %s (%u)\n",		RecordTypeToString( record->type ), record->type );
-			FPrintF( stdout, "    RData: %{du:rdata}\n",	record->type, record->dataPtr, (unsigned int) record->dataLen );
-			FPrintF( stdout, "    TTL:   %u%?s\n",			record->ttl, record->ttl == 0, defaultTTLStr );
-		}
-		printedRecords = true;
-	}
-	if( inContext->txtUpdates )
-	{
-		const RecordUpdate *		update;
-		size_t						count = 0;
-		
-		for( update = inContext->txtUpdates; update; update = update->next )
-		{
-			++count;
-			FPrintF( stdout, "\nTXT record update #%zu:\n",	count );
-			FPrintF( stdout, "    Delay:    %u ms\n",		( update->delayMs > 0 ) ? update->delayMs : 0 );
-			FPrintF( stdout, "    TXT data: %#{txt}\n",		update->dataPtr, update->dataLen );
-			FPrintF( stdout, "    TTL:      %u%?s\n",		update->ttl, update->ttl == 0, defaultTTLStr );
-		}
-		printedRecords = true;
-	}
-	FPrintF( stdout, "%sStart time: %{du:time}\n", printedRecords ? "\n" : "", NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	RegisterContextFree
-//===========================================================================================================================
-
-static void	RegisterContextFree( RegisterContext *inContext )
-{
-	ExtraRecord *					record;
-	const ExtraRecord * const		end = inContext->extraRecords + inContext->extraRecordsCount;
-	
-	DNSServiceForget( &inContext->opRef );
-	ForgetMem( &inContext->txtPtr );
-	for( record = inContext->extraRecords; record < end; ++record )
-	{
-		check( !record->recordRef );
-		ForgetMem( &record->dataPtr );
-	}
-	ForgetMem( &inContext->extraRecords );
-	while( inContext->txtUpdates )
-	{
-		RecordUpdate *		update = inContext->txtUpdates;
-		
-		inContext->txtUpdates = update->next;
-		_RecordUpdateForget( &update );
-	}
-	dispatch_source_forget( &inContext->updateTimer );
-	dispatch_source_forget( &inContext->lifetimeTimer );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	RegisterCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	RegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	RegisterContext * const		context = (RegisterContext *) inContext;
-	OSStatus					err;
-	struct timeval				now;
-	
-	Unused( inSDRef );
-	
-	gettimeofday( &now, NULL );
-	
-	if( !context->printedHeader )
-	{
-		FPrintF( stdout, "%-26s  %-17s Service\n", "Timestamp", "Flags" );
-		context->printedHeader = true;
-	}
-	FPrintF( stdout, "%{du:time}  %{du:cbflags} %s.%s%s %?#m\n", &now, inFlags, inName, inType, inDomain, inError, inError );
-	
-	require_noerr_action_quiet( inError, exit, err = inError );
-	
-	if( !context->didRegister && ( inFlags & kDNSServiceFlagsAdd ) )
-	{
-		context->didRegister = true;
-		if( context->extraRecordsCount > 0 )
-		{
-			ExtraRecord *					record;
-			const ExtraRecord * const		end = context->extraRecords + context->extraRecordsCount;
-			
-			for( record = context->extraRecords; record < end; ++record )
-			{
-				err = DNSServiceAddRecord( context->opRef, &record->recordRef, 0, record->type,
-					(uint16_t) record->dataLen, record->dataPtr, record->ttl );
-				require_noerr( err, exit );
-			}
-		}
-		if( context->lifetimeMs == 0 )
-		{
-			Exit( kExitReason_TimeLimit );
-		}
-		else if( context->lifetimeMs > 0 )
-		{
-			check( !context->lifetimeTimer );
-			err = DispatchTimerOneShotCreate( dispatch_time_milliseconds( context->lifetimeMs ), 0,
-				dispatch_get_main_queue(), Exit, kExitReason_TimeLimit, &context->lifetimeTimer );
-			require_noerr( err, exit );
-			dispatch_activate( context->lifetimeTimer );
-		}
-		err = _RegisterHandleTXTRecordUpdates( context );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_RegisterHandleTXTRecordUpdates
-//===========================================================================================================================
-
-static OSStatus	_RegisterHandleTXTRecordUpdates( RegisterContext *inContext )
-{
-	OSStatus		err;
-	
-	while( inContext->txtUpdates )
-	{
-		RecordUpdate *		update = inContext->txtUpdates;
-		
-		if( update->delayMs > 0 )
-		{
-			check( !inContext->updateTimer );
-			err = DispatchTimerOneShotCreate( dispatch_time_milliseconds( update->delayMs ), 0, dispatch_get_main_queue(),
-				_RegisterUpdateTimerHandler, inContext, &inContext->updateTimer );
-			require_noerr( err, exit );
-			dispatch_activate( inContext->updateTimer );
-			break;
-		}
-		err = DNSServiceUpdateRecord( inContext->opRef, NULL, 0, (uint16_t) update->dataLen, update->dataPtr, update->ttl );
-		require_noerr( err, exit );
-		inContext->txtUpdates = update->next;
-		_RecordUpdateForget( &update );
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_RegisterUpdateTimerHandler
-//===========================================================================================================================
-
-static void	_RegisterUpdateTimerHandler( void *inContext )
-{
-	OSStatus					err;
-	RegisterContext * const		context	= (RegisterContext *) inContext;
-	RecordUpdate * const		update	= context->txtUpdates;
-	
-	dispatch_source_forget( &context->updateTimer );
-	if( update ) update->delayMs = 0;
-	err = _RegisterHandleTXTRecordUpdates( context );
-	require_noerr( err, exit );
-	
-exit:
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_RecordUpdateFree
-//===========================================================================================================================
-
-static void	_RecordUpdateFree( RecordUpdate *inUpdate )
-{
-	inUpdate->next = NULL;
-	ForgetMem( &inUpdate->dataPtr );
-	free( inUpdate );
-}
-
-//===========================================================================================================================
-//	RegisterRecordCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef		conRef;			// sdRef to be initialized by DNSServiceCreateConnection().
-	DNSRecordRef		recordRef;		// Registered record reference.
-	const char *		recordName;		// Name of resource record.
-	uint8_t *			dataPtr;		// Pointer to resource record data.
-	size_t				dataLen;		// Length of resource record data.
-	uint32_t			ttl;			// TTL value of resource record in seconds.
-	uint32_t			ifIndex;		// Interface index argument for DNSServiceRegisterRecord().
-	DNSServiceFlags		flags;			// Flags argument for DNSServiceRegisterRecord().
-	int					lifetimeMs;		// Lifetime of the record registration in milliseconds.
-	uint16_t			recordType;		// Resource record type.
-	uint8_t *			updateDataPtr;	// Pointer to data for record update. (malloc'd)
-	size_t				updateDataLen;	// Length of data for record update.
-	uint32_t			updateTTL;		// TTL for updated record.
-	int					updateDelayMs;	// Post-registration record update delay in milliseconds.
-	uint32_t			timestamp;		// Timestamp in seconds since epoch time to indicate when the record is registered.
-	Boolean				setTimestamp;	// True if the timestamp attribute needs to be set.
-	Boolean				didRegister;	// True if the record was registered.
-
-	
-}	RegisterRecordContext;
-
-static void	RegisterRecordPrintPrologue( const RegisterRecordContext *inContext );
-static void	RegisterRecordContextFree( RegisterRecordContext *inContext );
-static void DNSSD_API
-	RegisterRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSRecordRef		inRecordRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		void *				inContext );
-static void	RegisterRecordUpdate( void *inContext );
-
-static void	RegisterRecordCmd( void )
-{
-	OSStatus					err;
-	RegisterRecordContext *		context			= NULL;
-	dispatch_source_t			signalSource	= NULL;
-	DNSServiceAttributeRef		attr			= NULL;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-
-	// Create context.
-	
-	context = (RegisterRecordContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Create connection.
-	
-	err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->conRef, NULL );
-	require_noerr_quiet( err, exit );
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	
-	// Get interface.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Get record type.
-	
-	err = RecordTypeFromArgString( gRegisterRecord_Type, &context->recordType );
-	require_noerr( err, exit );
-	
-	// Get record data.
-	
-	if( gRegisterRecord_Data )
-	{
-		err = RecordDataFromArgString( gRegisterRecord_Data, &context->dataPtr, &context->dataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// Set remaining parameters.
-	
-	context->recordName	= gRegisterRecord_Name;
-	context->ttl		= (uint32_t) gRegisterRecord_TTL;
-	context->lifetimeMs	= gRegisterRecord_LifetimeMs;
-	if( gRegisterRecord_TimeOfReceipt )
-	{
-		err = _UInt32FromArgString( gRegisterRecord_TimeOfReceipt, "timestamp", &context->timestamp );
-		require_noerr_quiet( err, exit );
-
-		context->setTimestamp = true;
-	}
-
-	// Get update data.
-	
-	if( gRegisterRecord_UpdateData )
-	{
-		err = RecordDataFromArgString( gRegisterRecord_UpdateData, &context->updateDataPtr, &context->updateDataLen );
-		require_noerr_quiet( err, exit );
-		
-		context->updateTTL		= (uint32_t) gRegisterRecord_UpdateTTL;
-		context->updateDelayMs	= gRegisterRecord_UpdateDelayMs;
-	}
-	
-	// Print prologue.
-	
-	RegisterRecordPrintPrologue( context );
-	
-	// Start operation.
-	
-	// Only call DNSServiceAttributeSetTimestamp when the option is set.
-	if( context->setTimestamp )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			attr = DNSServiceAttributeCreate();
-			require_action( attr, exit, err = kNoResourcesErr );
-			
-			err = DNSServiceAttributeSetTimestamp( attr, context->timestamp );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceAttributeCreate is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	if( attr )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			err = DNSServiceRegisterRecordWithAttribute( context->conRef, &context->recordRef, context->flags,
-				context->ifIndex, context->recordName, context->recordType, kDNSServiceClass_IN,
-				(uint16_t) context->dataLen, context->dataPtr, context->ttl, attr, RegisterRecordCallback, context );
-			require_noerr( err, exit );
-			_DNSServiceAttrForget( &attr );
-		}
-		else
-		{
-			FPrintF( stderr, "error: DNSServiceRegisterRecordWithAttribute is not available on this OS.\n" );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = DNSServiceRegisterRecord( context->conRef, &context->recordRef, context->flags, context->ifIndex,
-			context->recordName, context->recordType, kDNSServiceClass_IN, (uint16_t) context->dataLen, context->dataPtr,
-			context->ttl, RegisterRecordCallback, context );
-		if( err )
-		{
-			FPrintF( stderr, "DNSServiceRegisterRecord() returned %#m\n", err );
-			goto exit;
-		}
-	}
-
-	dispatch_main();
-	
-exit:
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-	dispatch_source_forget( &signalSource );
-	if( context ) RegisterRecordContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	RegisterRecordPrintPrologue
-//===========================================================================================================================
-
-static void	RegisterRecordPrintPrologue( const RegisterRecordContext *inContext )
-{
-	int			infinite;
-	char		ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:       %#{flags}\n",	inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:   %d (%s)\n",		(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Name:        %s\n",			inContext->recordName );
-	FPrintF( stdout, "Type:        %s (%u)\n",		RecordTypeToString( inContext->recordType ), inContext->recordType );
-	FPrintF( stdout, "TTL:         %u\n",			inContext->ttl );
-	FPrintF( stdout, "Data:        %#H\n",			inContext->dataPtr, (int) inContext->dataLen, INT_MAX );
-	if( inContext->setTimestamp )
-	{
-		const char *		dateTimeStr;
-		char				dateTimeBuf[ 32 ];
-		
-		FPrintF( stdout, "Timestamp:   %u", inContext->timestamp );
-		dateTimeStr = _UnixTimeToDateAndTimeString( inContext->timestamp, dateTimeBuf, sizeof( dateTimeBuf ) );
-		if( dateTimeStr ) FPrintF( stdout, " (%s)", dateTimeStr );
-		FPrintF( stdout, "\n" );
-	}
-	infinite = ( inContext->lifetimeMs < 0 ) ? true : false;
-	FPrintF( stdout, "Lifetime:    %?s%?d ms\n",	infinite, "∞", !infinite, inContext->lifetimeMs );
-	if( inContext->updateDataPtr )
-	{
-		FPrintF( stdout, "\nUpdate record:\n" );
-		FPrintF( stdout, "    Delay:    %d ms\n",	( inContext->updateDelayMs >= 0 ) ? inContext->updateDelayMs : 0 );
-		FPrintF( stdout, "    TTL:      %u%?s\n",
-			inContext->updateTTL, inContext->updateTTL == 0, " (system will use a default value.)" );
-		FPrintF( stdout, "    RData:    %#H\n",		inContext->updateDataPtr, (int) inContext->updateDataLen, INT_MAX );
-	}
-	FPrintF( stdout, "Start time:  %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	RegisterRecordContextFree
-//===========================================================================================================================
-
-static void	RegisterRecordContextFree( RegisterRecordContext *inContext )
-{
-	DNSServiceForget( &inContext->conRef );
-	ForgetMem( &inContext->dataPtr );
-	ForgetMem( &inContext->updateDataPtr );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	RegisterRecordCallback
-//===========================================================================================================================
-
-static void
-	RegisterRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSRecordRef		inRecordRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		void *				inContext )
-{
-	RegisterRecordContext *		context = (RegisterRecordContext *) inContext;
-	struct timeval				now;
-	
-	Unused( inSDRef );
-	Unused( inRecordRef );
-	Unused( inFlags );
-	Unused( context );
-	
-	gettimeofday( &now, NULL );
-	FPrintF( stdout, "%{du:time} Record registration result (error %#m)\n", &now, inError );
-	
-	if( !context->didRegister && !inError )
-	{
-		context->didRegister = true;
-		if( context->updateDataPtr )
-		{
-			if( context->updateDelayMs > 0 )
-			{
-				dispatch_after_f( dispatch_time_milliseconds( context->updateDelayMs ), dispatch_get_main_queue(),
-					context, RegisterRecordUpdate );
-			}
-			else
-			{
-				RegisterRecordUpdate( context );
-			}
-		}
-		if( context->lifetimeMs == 0 )
-		{
-			Exit( kExitReason_TimeLimit );
-		}
-		else if( context->lifetimeMs > 0 )
-		{
-			dispatch_after_f( dispatch_time_milliseconds( context->lifetimeMs ), dispatch_get_main_queue(),
-				kExitReason_TimeLimit, Exit );
-		}
-	}
-}
-
-//===========================================================================================================================
-//	RegisterRecordUpdate
-//===========================================================================================================================
-
-static void	RegisterRecordUpdate( void *inContext )
-{
-	OSStatus							err;
-	RegisterRecordContext * const		context = (RegisterRecordContext *) inContext;
-	
-	err = DNSServiceUpdateRecord( context->conRef, context->recordRef, 0, (uint16_t) context->updateDataLen,
-		context->updateDataPtr, context->updateTTL );
-	require_noerr( err, exit );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	ResolveCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef		mainRef;		// Main sdRef for shared connections.
-	DNSServiceRef		opRef;			// sdRef for the DNSServiceResolve operation.
-	DNSServiceFlags		flags;			// Flags argument for DNSServiceResolve().
-	const char *		name;			// Service name argument for DNSServiceResolve().
-	const char *		type;			// Service type argument for DNSServiceResolve().
-	const char *		domain;			// Domain argument for DNSServiceResolve().
-	uint32_t			ifIndex;		// Interface index argument for DNSServiceResolve().
-	int					timeLimitSecs;	// Time limit for the DNSServiceResolve operation in seconds.
-	
-}	ResolveContext;
-
-static void	ResolvePrintPrologue( const ResolveContext *inContext );
-static void	ResolveContextFree( ResolveContext *inContext );
-static void DNSSD_API
-	ResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext );
-
-static void	ResolveCmd( void )
-{
-	OSStatus				err;
-	DNSServiceRef			sdRef;
-	ResolveContext *		context			= NULL;
-	dispatch_source_t		signalSource	= NULL;
-	int						useMainConnection;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (ResolveContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Check command parameters.
-	
-	if( gResolve_TimeLimitSecs < 0 )
-	{
-		FPrintF( stderr, "Invalid time limit: %d seconds.\n", gResolve_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Set remaining parameters.
-	
-	context->name			= gResolve_Name;
-	context->type			= gResolve_Type;
-	context->domain			= gResolve_Domain;
-	context->timeLimitSecs	= gResolve_TimeLimitSecs;
-	
-	// Print prologue.
-	
-	ResolvePrintPrologue( context );
-	
-	// Start operation.
-	
-	sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-	err = DNSServiceResolve( &sdRef, context->flags, context->ifIndex, context->name, context->type, context->domain,
-		ResolveCallback, NULL );
-	require_noerr( err, exit );
-	
-	context->opRef = sdRef;
-	if( !useMainConnection )
-	{
-		err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-	}
-	
-	// Set time limit.
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(),
-			kExitReason_TimeLimit, Exit );
-	}
-	dispatch_main();
-	
-exit:
-	dispatch_source_forget( &signalSource );
-	if( context ) ResolveContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	ReconfirmCmd
-//===========================================================================================================================
-
-static void	ReconfirmCmd( void )
-{
-	OSStatus			err;
-	uint8_t *			rdataPtr = NULL;
-	size_t				rdataLen = 0;
-	DNSServiceFlags		flags;
-	uint32_t			ifIndex;
-	uint16_t			type, class;
-	char				ifName[ kInterfaceNameBufLen ];
-	
-	// Get flags.
-	
-	flags = GetDNSSDFlagsFromOpts();
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Get record type.
-	
-	err = RecordTypeFromArgString( gReconfirmRecord_Type, &type );
-	require_noerr( err, exit );
-	
-	// Get record data.
-	
-	if( gReconfirmRecord_Data )
-	{
-		err = RecordDataFromArgString( gReconfirmRecord_Data, &rdataPtr, &rdataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// Get record class.
-	
-	if( gReconfirmRecord_Class )
-	{
-		err = RecordClassFromArgString( gReconfirmRecord_Class, &class );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		class = kDNSServiceClass_IN;
-	}
-	
-	// Print prologue.
-	
-	FPrintF( stdout, "Flags:     %#{flags}\n",	flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface: %d (%s)\n",	(int32_t) ifIndex, InterfaceIndexToName( ifIndex, ifName ) );
-	FPrintF( stdout, "Name:      %s\n",			gReconfirmRecord_Name );
-	FPrintF( stdout, "Type:      %s (%u)\n",	RecordTypeToString( type ), type );
-	FPrintF( stdout, "Class:     %s (%u)\n",	( class == kDNSServiceClass_IN ) ? "IN" : "???", class );
-	FPrintF( stdout, "Data:      %#H\n",		rdataPtr, (int) rdataLen, INT_MAX );
-	FPrintF( stdout, "---\n" );
-	
-	err = DNSServiceReconfirmRecord( flags, ifIndex, gReconfirmRecord_Name, type, class, (uint16_t) rdataLen, rdataPtr );
-	FPrintF( stdout, "Error:     %#m\n", err );
-	
-exit:
-	FreeNullSafe( rdataPtr );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	ResolvePrintPrologue
-//===========================================================================================================================
-
-static void	ResolvePrintPrologue( const ResolveContext *inContext )
-{
-	const int		timeLimitSecs = inContext->timeLimitSecs;
-	char			ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:      %#{flags}\n",		inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:  %d (%s)\n",		(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Name:       %s\n",			inContext->name );
-	FPrintF( stdout, "Type:       %s\n",			inContext->type );
-	FPrintF( stdout, "Domain:     %s\n",			inContext->domain );
-	FPrintF( stdout, "Time limit: " );
-	if( timeLimitSecs > 0 )	FPrintF( stdout, "%d second%?c\n", timeLimitSecs, timeLimitSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	ResolveContextFree
-//===========================================================================================================================
-
-static void	ResolveContextFree( ResolveContext *inContext )
-{
-	DNSServiceForget( &inContext->opRef );
-	DNSServiceForget( &inContext->mainRef );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	ResolveCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	ResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext )
-{
-	struct timeval		now;
-	char				errorStr[ 64 ];
-	
-	Unused( inSDRef );
-	Unused( inFlags );
-	Unused( inContext );
-	
-	gettimeofday( &now, NULL );
-	
-	if( inError ) SNPrintF( errorStr, sizeof( errorStr ), " error %#m", inError );
-	
-	FPrintF( stdout, "%{du:time}: %s can be reached at %s:%u (interface %d)%?s\n",
-		&now, inFullName, inHostname, ntohs( inPort ), (int32_t) inInterfaceIndex, inError, errorStr );
-	if( inTXTLen == 1 )
-	{
-		FPrintF( stdout, " TXT record: %#H\n", inTXTPtr, (int) inTXTLen, INT_MAX );
-	}
-	else
-	{
-		FPrintF( stdout, " TXT record: %#{txt}\n", inTXTPtr, (size_t) inTXTLen );
-	}
-}
-
-//===========================================================================================================================
-//	GetAddrInfoPOSIXCmd
-//===========================================================================================================================
-
-#define AddressFamilyStr( X ) (				\
-	( (X) == AF_INET )		? "inet"	:	\
-	( (X) == AF_INET6 )		? "inet6"	:	\
-	( (X) == AF_UNSPEC )	? "unspec"	:	\
-							  "???" )
-
-typedef struct
-{
-    unsigned int		flag;
-    const char *        str;
-
-}   FlagStringPair;
-
-#define CaseFlagStringify( X )		{ (X), # X }
-
-const FlagStringPair		kGAIPOSIXFlagStringPairs[] =
-{
-#if( defined( AI_UNUSABLE ) )
-	CaseFlagStringify( AI_UNUSABLE ),
-#endif
-	CaseFlagStringify( AI_NUMERICSERV ),
-	CaseFlagStringify( AI_V4MAPPED ),
-	CaseFlagStringify( AI_ADDRCONFIG ),
-#if( defined( AI_V4MAPPED_CFG ) )
-	CaseFlagStringify( AI_V4MAPPED_CFG ),
-#endif
-	CaseFlagStringify( AI_ALL ),
-	CaseFlagStringify( AI_NUMERICHOST ),
-	CaseFlagStringify( AI_CANONNAME ),
-	CaseFlagStringify( AI_PASSIVE ),
-	{ 0, NULL }
-};
-
-static void	GetAddrInfoPOSIXCmd( void )
-{
-	OSStatus					err;
-	struct addrinfo				hints;
-	struct timeval				now;
-	const struct addrinfo *		addrInfo;
-	struct addrinfo *			addrInfoList = NULL;
-	const FlagStringPair *		pair;
-	
-	memset( &hints, 0, sizeof( hints ) );
-	hints.ai_socktype = SOCK_STREAM;
-	
-	// Set hints address family.
-	
-	if( !gGAIPOSIX_Family )										hints.ai_family = AF_UNSPEC;
-	else if( strcasecmp( gGAIPOSIX_Family, "inet" ) == 0 )		hints.ai_family = AF_INET;
-	else if( strcasecmp( gGAIPOSIX_Family, "inet6" ) == 0 )		hints.ai_family = AF_INET6;
-	else if( strcasecmp( gGAIPOSIX_Family, "unspec" ) == 0 )	hints.ai_family = AF_UNSPEC;
-	else
-	{
-		FPrintF( stderr, "Invalid address family: %s.\n", gGAIPOSIX_Family );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Set hints flags.
-	
-	if( gGAIPOSIXFlag_AddrConfig )	hints.ai_flags |= AI_ADDRCONFIG;
-	if( gGAIPOSIXFlag_All )			hints.ai_flags |= AI_ALL;
-	if( gGAIPOSIXFlag_CanonName )	hints.ai_flags |= AI_CANONNAME;
-	if( gGAIPOSIXFlag_NumericHost )	hints.ai_flags |= AI_NUMERICHOST;
-	if( gGAIPOSIXFlag_NumericServ )	hints.ai_flags |= AI_NUMERICSERV;
-	if( gGAIPOSIXFlag_Passive )		hints.ai_flags |= AI_PASSIVE;
-	if( gGAIPOSIXFlag_V4Mapped )	hints.ai_flags |= AI_V4MAPPED;
-#if( defined( AI_V4MAPPED_CFG ) )
-	if( gGAIPOSIXFlag_V4MappedCFG )	hints.ai_flags |= AI_V4MAPPED_CFG;
-#endif
-#if( defined( AI_DEFAULT ) )
-	if( gGAIPOSIXFlag_Default )		hints.ai_flags |= AI_DEFAULT;
-#endif
-#if( defined( AI_UNUSABLE ) )
-	if( gGAIPOSIXFlag_Unusable )	hints.ai_flags |= AI_UNUSABLE;
-#endif
-	
-#if( MDNSRESPONDER_PROJECT )
-	if( gFallbackDNSService )
-	{
-		err = _SetDefaultFallbackDNSService( gFallbackDNSService );
-		require_noerr_quiet( err, exit );
-	}
-#endif
-	// Print prologue.
-	
-	FPrintF( stdout, "Hostname:       %s\n",	gGAIPOSIX_HostName );
-	FPrintF( stdout, "Servname:       %s\n",	gGAIPOSIX_ServName );
-	FPrintF( stdout, "Address family: %s\n",	AddressFamilyStr( hints.ai_family ) );
-	FPrintF( stdout, "Flags:          0x%X < ",	hints.ai_flags );
-	for( pair = kGAIPOSIXFlagStringPairs; pair->str != NULL; ++pair )
-	{
-		if( ( (unsigned int) hints.ai_flags ) & pair->flag ) FPrintF( stdout, "%s ", pair->str );
-	}
-	FPrintF( stdout, ">\n" );
-	FPrintF( stdout, "Start time:     %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-	
-	// Call getaddrinfo().
-	
-	err = getaddrinfo( gGAIPOSIX_HostName, gGAIPOSIX_ServName, &hints, &addrInfoList );
-	gettimeofday( &now, NULL );
-	if( err )
-	{
-		FPrintF( stderr, "Error %d: %s.\n", err, gai_strerror( err ) );
-	}
-	else
-	{
-		int		addrCount = 0;
-		
-		for( addrInfo = addrInfoList; addrInfo; addrInfo = addrInfo->ai_next ) { ++addrCount; }
-		
-		FPrintF( stdout, "Addresses (%d total):\n", addrCount );
-		for( addrInfo = addrInfoList; addrInfo; addrInfo = addrInfo->ai_next )
-		{
-			FPrintF( stdout, "%##a\n", addrInfo->ai_addr );
-		}
-	}
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:       %{du:time}\n", &now );
-	
-exit:
-	if( addrInfoList ) freeaddrinfo( addrInfoList );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	ReverseLookupCmd
-//===========================================================================================================================
-
-static void	ReverseLookupCmd( void )
-{
-	OSStatus					err;
-	QueryRecordContext *		context			= NULL;
-	DNSServiceRef				sdRef;
-	dispatch_source_t			signalSource	= NULL;
-	uint32_t					ipv4Addr;
-	uint8_t						ipv6Addr[ 16 ];
-	char						recordName[ kReverseIPv6DomainNameBufLen ];
-	int							useMainConnection;
-	const char *				endPtr;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (QueryRecordContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Check command parameters.
-	
-	if( gReverseLookup_TimeLimitSecs < 0 )
-	{
-		FPrintF( stderr, "Invalid time limit: %d s.\n", gReverseLookup_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Create reverse lookup record name.
-	
-	err = _StringToIPv4Address( gReverseLookup_IPAddr, kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoPrefix,
-		&ipv4Addr, NULL, NULL, NULL, &endPtr );
-	if( err || ( *endPtr != '\0' ) )
-	{
-		err = _StringToIPv6Address( gReverseLookup_IPAddr,
-			kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoPrefix | kStringToIPAddressFlagsNoScope,
-			ipv6Addr, NULL, NULL, NULL, &endPtr );
-		if( err || ( *endPtr != '\0' ) )
-		{
-			FPrintF( stderr, "Invalid IP address: \"%s\".\n", gReverseLookup_IPAddr );
-			err = kParamErr;
-			goto exit;
-		}
-		_WriteReverseIPv6DomainNameString( ipv6Addr, recordName );
-	}
-	else
-	{
-		_WriteReverseIPv4DomainNameString( ipv4Addr, recordName );
-	}
-	
-	// Set remaining parameters.
-	
-	context->recordName		= recordName;
-	context->recordType		= kDNSServiceType_PTR;
-	context->timeLimitSecs	= gReverseLookup_TimeLimitSecs;
-	context->oneShotMode	= gReverseLookup_OneShot ? true : false;
-	
-	// Print prologue.
-	
-	QueryRecordPrintPrologue( context );
-	
-	// Start operation.
-	
-	sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-	err = DNSServiceQueryRecord( &sdRef, context->flags, context->ifIndex, context->recordName, context->recordType,
-		kDNSServiceClass_IN, QueryRecordCallback, context );
-	require_noerr( err, exit );
-	
-	context->opRef = sdRef;
-	if( !useMainConnection )
-	{
-		err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-	}
-	
-	// Set time limit.
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(),
-			kExitReason_TimeLimit, Exit );
-	}
-	dispatch_main();
-	
-exit:
-	dispatch_source_forget( &signalSource );
-	if( context ) QueryRecordContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	PortMappingCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef			mainRef;		// Main sdRef for shared connection.
-	DNSServiceRef			opRef;			// sdRef for the DNSServiceNATPortMappingCreate operation.
-	DNSServiceFlags			flags;			// Flags for DNSServiceNATPortMappingCreate operation.
-	uint32_t				ifIndex;		// Interface index argument for DNSServiceNATPortMappingCreate operation.
-	DNSServiceProtocol		protocols;		// Protocols argument for DNSServiceNATPortMappingCreate operation.
-	uint32_t				ttl;			// TTL argument for DNSServiceNATPortMappingCreate operation.
-	uint16_t				internalPort;	// Internal port argument for DNSServiceNATPortMappingCreate operation.
-	uint16_t				externalPort;	// External port argument for DNSServiceNATPortMappingCreate operation.
-	Boolean					printedHeader;	// True if results header was printed.
-	
-}	PortMappingContext;
-
-static void	PortMappingPrintPrologue( const PortMappingContext *inContext );
-static void	PortMappingContextFree( PortMappingContext *inContext );
-static void DNSSD_API
-	PortMappingCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		uint32_t			inExternalIPv4Address,
-		DNSServiceProtocol	inProtocol,
-		uint16_t			inInternalPort,
-		uint16_t			inExternalPort,
-		uint32_t			inTTL,
-		void *				inContext );
-
-static void	PortMappingCmd( void )
-{
-	OSStatus					err;
-	PortMappingContext *		context			= NULL;
-	DNSServiceRef				sdRef;
-	dispatch_source_t			signalSource	= NULL;
-	int							useMainConnection;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Create context.
-	
-	context = (PortMappingContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	// Check command parameters.
-	
-	if( ( gPortMapping_InternalPort < 0 ) || ( gPortMapping_InternalPort > UINT16_MAX ) )
-	{
-		FPrintF( stderr, "Internal port number %d is out-of-range.\n", gPortMapping_InternalPort );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	if( ( gPortMapping_ExternalPort < 0 ) || ( gPortMapping_ExternalPort > UINT16_MAX ) )
-	{
-		FPrintF( stderr, "External port number %d is out-of-range.\n", gPortMapping_ExternalPort );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create main connection.
-	
-	if( gConnectionOpt )
-	{
-		err = CreateConnectionFromArgString( gConnectionOpt, dispatch_get_main_queue(), &context->mainRef, NULL );
-		require_noerr_quiet( err, exit );
-		useMainConnection = true;
-	}
-	else
-	{
-		useMainConnection = false;
-	}
-	
-	// Get flags.
-	
-	context->flags = GetDNSSDFlagsFromOpts();
-	if( useMainConnection ) context->flags |= kDNSServiceFlagsShareConnection;
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	// Set remaining parameters.
-	
-	if( gPortMapping_ProtocolTCP ) context->protocols |= kDNSServiceProtocol_TCP;
-	if( gPortMapping_ProtocolUDP ) context->protocols |= kDNSServiceProtocol_UDP;
-	context->ttl			= (uint32_t) gPortMapping_TTL;
-	context->internalPort	= (uint16_t) gPortMapping_InternalPort;
-	context->externalPort	= (uint16_t) gPortMapping_ExternalPort;
-	
-	// Print prologue.
-	
-	PortMappingPrintPrologue( context );
-	
-	// Start operation.
-	
-	sdRef = useMainConnection ? context->mainRef : kBadDNSServiceRef;
-	err = DNSServiceNATPortMappingCreate( &sdRef, context->flags, context->ifIndex, context->protocols,
-		htons( context->internalPort ), htons( context->externalPort ), context->ttl, PortMappingCallback, context );
-	require_noerr( err, exit );
-	
-	context->opRef = sdRef;
-	if( !useMainConnection )
-	{
-		err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-	}
-	
-	dispatch_main();
-	
-exit:
-	dispatch_source_forget( &signalSource );
-	if( context ) PortMappingContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	PortMappingPrintPrologue
-//===========================================================================================================================
-
-static void	PortMappingPrintPrologue( const PortMappingContext *inContext )
-{
-	char		ifName[ kInterfaceNameBufLen ];
-	
-	InterfaceIndexToName( inContext->ifIndex, ifName );
-	
-	FPrintF( stdout, "Flags:         %#{flags}\n",		inContext->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:     %d (%s)\n",		(int32_t) inContext->ifIndex, ifName );
-	FPrintF( stdout, "Protocols:     %#{flags}\n",		inContext->protocols, kDNSServiceProtocolDescriptors );
-	FPrintF( stdout, "Internal Port: %u\n",				inContext->internalPort );
-	FPrintF( stdout, "External Port: %u\n",				inContext->externalPort );
-	FPrintF( stdout, "TTL:           %u%?s\n",			inContext->ttl, !inContext->ttl,
-		" (system will use a default value.)" );
-	FPrintF( stdout, "Start time:    %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-}
-
-//===========================================================================================================================
-//	PortMappingContextFree
-//===========================================================================================================================
-
-static void	PortMappingContextFree( PortMappingContext *inContext )
-{
-	DNSServiceForget( &inContext->opRef );
-	DNSServiceForget( &inContext->mainRef );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	PortMappingCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	PortMappingCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		uint32_t			inExternalIPv4Address,
-		DNSServiceProtocol	inProtocol,
-		uint16_t			inInternalPort,
-		uint16_t			inExternalPort,
-		uint32_t			inTTL,
-		void *				inContext )
-{
-	PortMappingContext * const		context = (PortMappingContext *) inContext;
-	struct timeval					now;
-	char							errorStr[ 128 ];
-	
-	Unused( inSDRef );
-	Unused( inFlags );
-	
-	gettimeofday( &now, NULL );
-	
-	if( inError ) SNPrintF( errorStr, sizeof( errorStr ), " (error: %#m)", inError );
-	if( !context->printedHeader )
-	{
-		FPrintF( stdout, "%-26s  IF %7s %15s %7s %6s Protocol\n", "Timestamp", "IntPort", "ExtAddr", "ExtPort", "TTL" );
-		context->printedHeader = true;
-	}
-	FPrintF( stdout, "%{du:time}  %2u %7u %15.4a %7u %6u %#{flags}%?s\n",
-		&now, inInterfaceIndex, ntohs( inInternalPort), &inExternalIPv4Address, ntohs( inExternalPort ), inTTL,
-		inProtocol, kDNSServiceProtocolDescriptors, inError, errorStr );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	RegisterKACmd
-//===========================================================================================================================
-
-typedef struct
-{
-	dispatch_queue_t			queue;			// Serial queue for command's events.
-	dispatch_semaphore_t		doneSem;		// Semaphore to signal when underlying command operation is done.
-	sockaddr_ip					local;			// Connection's local IP address and port.
-	sockaddr_ip					remote;			// Connection's remote IP address and port.
-	DNSServiceFlags				flags;			// Flags to pass to DNSServiceSleepKeepalive_sockaddr().
-	unsigned int				timeout;		// Timeout to pass to DNSServiceSleepKeepalive_sockaddr().
-	DNSServiceRef				keepalive;		// DNSServiceSleepKeepalive_sockaddr operation.
-	dispatch_source_t			sourceSigInt;	// Dispatch source for SIGINT.
-	dispatch_source_t			sourceSigTerm;	// Dispatch source for SIGTERM.
-	OSStatus					error;			// Command's error.
-	
-}	RegisterKACmdContext;
-
-static void	_RegisterKACmdFree( RegisterKACmdContext *inCmd );
-static void	_RegisterKACmdStart( void *inContext );
-
-static void	RegisterKACmd( void )
-{
-	OSStatus					err;
-	RegisterKACmdContext *		cmd = NULL;
-	
-	cmd = (RegisterKACmdContext *) calloc( 1, sizeof( *cmd ) );
-	require_action( cmd, exit, err = kNoMemoryErr );
-	
-	err = SockAddrFromArgString( gRegisterKA_LocalAddress, "local IP address", &cmd->local );
-	require_noerr_quiet( err, exit );
-	
-	err = SockAddrFromArgString( gRegisterKA_RemoteAddress, "remote IP address", &cmd->remote );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gRegisterKA_Timeout, "timeout", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	cmd->flags		= GetDNSSDFlagsFromOpts();
-	cmd->timeout	= (unsigned int) gRegisterKA_Timeout;
-	
-	// Start command.
-	
-	cmd->queue = dispatch_queue_create( "com.apple.dnssdutil.registerka-command", DISPATCH_QUEUE_SERIAL );
-	require_action( cmd->queue, exit, err = kNoResourcesErr );
-	
-	cmd->doneSem = dispatch_semaphore_create( 0 );
-	require_action( cmd->doneSem, exit, err = kNoResourcesErr );
-	
-	dispatch_async_f( cmd->queue, cmd, _RegisterKACmdStart );
-    dispatch_semaphore_wait( cmd->doneSem, DISPATCH_TIME_FOREVER );
-	if( cmd->error ) err = cmd->error;
-	
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:   %{du:time}\n", NULL );
-	
-exit:
-	if( cmd ) _RegisterKACmdFree( cmd );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-
-static void	_RegisterKACmdFree( RegisterKACmdContext *inCmd )
-{
-	check( !inCmd->keepalive );
-	check( !inCmd->sourceSigInt );
-	check( !inCmd->sourceSigTerm );
-	dispatch_forget( &inCmd->queue );
-	dispatch_forget( &inCmd->doneSem );
-	free( inCmd );
-}
-
-//===========================================================================================================================
-
-static void				_RegisterKACmdStop( RegisterKACmdContext *inCmd, OSStatus inError );
-static void				_RegisterKACmdSignalHandler( void *inContext );
-static void DNSSD_API	_RegisterKACmdKeepaliveCallback( DNSServiceRef inSDRef, DNSServiceErrorType inError, void *inCtx );
-
-static void	_RegisterKACmdStart( void *inContext )
-{
-	OSStatus							err;
-	RegisterKACmdContext * const		cmd = (RegisterKACmdContext *) inContext;
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, cmd->queue, _RegisterKACmdSignalHandler, cmd, &cmd->sourceSigInt );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigInt );
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, cmd->queue, _RegisterKACmdSignalHandler, cmd, &cmd->sourceSigTerm );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigTerm );
-	
-	FPrintF( stdout, "Flags:      %#{flags}\n",		cmd->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Local:      %##a\n",			&cmd->local.sa );
-	FPrintF( stdout, "Remote:     %##a\n",			&cmd->remote.sa );
-	FPrintF( stdout, "Timeout:    %u\n",			cmd->timeout );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	err = DNSServiceSleepKeepalive_sockaddr( &cmd->keepalive, cmd->flags, &cmd->local.sa, &cmd->remote.sa, cmd->timeout,
-		_RegisterKACmdKeepaliveCallback, cmd );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( cmd->keepalive, cmd->queue );
-	require_noerr( err, exit );
-	
-exit:
-	if( err ) _RegisterKACmdStop( cmd, err );
-}
-
-//===========================================================================================================================
-
-static void	_RegisterKACmdStop( RegisterKACmdContext *inCmd, OSStatus inError )
-{
-	if( !inCmd->error ) inCmd->error = inError;
-	DNSServiceForget( &inCmd->keepalive );
-	dispatch_source_forget( &inCmd->sourceSigInt );
-	dispatch_source_forget( &inCmd->sourceSigTerm );
-	dispatch_semaphore_signal( inCmd->doneSem );
-}
-
-//===========================================================================================================================
-
-static void	_RegisterKACmdSignalHandler( void *inContext )
-{
-	RegisterKACmdContext * const		cmd = (RegisterKACmdContext *) inContext;
-	
-	_RegisterKACmdStop( cmd, kNoErr );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API	_RegisterKACmdKeepaliveCallback( DNSServiceRef inSDRef, DNSServiceErrorType inError, void *inCtx )
-{
-	RegisterKACmdContext * const		cmd = (RegisterKACmdContext *) inCtx;
-	
-	Unused( inSDRef );
-	
-	FPrintF( stdout, "%{du:time} Record registration result: %#m\n", NULL, inError );
-	if( !cmd->error ) cmd->error = inError;
-}
-#endif	// TARGET_OS_DARWIN
-
-//===========================================================================================================================
-//	BrowseAllCmd
-//===========================================================================================================================
-
-typedef struct BrowseAllConnection		BrowseAllConnection;
-
-typedef struct
-{
-	ServiceBrowserRef			browser;				// Service browser.
-	ServiceBrowserResults *		results;				// Results from the service browser.
-	BrowseAllConnection *		connectionList;			// List of connections.
-	dispatch_source_t			connectionTimer;		// Timer for connection timeout.
-	int							connectionPendingCount;	// Number of pending connections.
-	int							connectionTimeoutSecs;	// Timeout value for connections in seconds.
-	Boolean						validateResults;		// Validate results.
-	
-}	BrowseAllContext;
-
-struct BrowseAllConnection
-{
-	BrowseAllConnection *		next;				// Next connection object in list.
-	sockaddr_ip					sip;				// IPv4 or IPv6 address to connect to.
-	uint16_t					port;				// TCP port to connect to.
-	AsyncConnectionRef			asyncCnx;			// AsyncConnection object to handle the actual connection.
-	OSStatus					status;				// Status of connection. NoErr means connection succeeded.
-	CFTimeInterval				connectTimeSecs;	// Time it took to connect in seconds.
-	int32_t						refCount;			// This object's reference count.
-	BrowseAllContext *			context;			// Back pointer to parent context.
-};
-
-static void	_BrowseAllContextFree( BrowseAllContext *inContext );
-static void	_BrowseAllServiceBrowserCallback( ServiceBrowserResults *inResults, OSStatus inError, void *inContext );
-static OSStatus
-	_BrowseAllConnectionCreate(
-		const struct sockaddr *	inSockAddr,
-		uint16_t				inPort,
-		BrowseAllContext *		inContext,
-		BrowseAllConnection **	outConnection );
-static void _BrowseAllConnectionRetain( BrowseAllConnection *inConnection );
-static void	_BrowseAllConnectionRelease( BrowseAllConnection *inConnection );
-static void	_BrowseAllConnectionProgress( int inPhase, const void *inDetails, void *inArg );
-static void	_BrowseAllConnectionHandler( SocketRef inSock, OSStatus inError, void *inArg );
-static void	_BrowseAllExit( void *inContext );
-
-static Boolean	_IsServiceTypeTCP( const char *inServiceType );
-
-static void	BrowseAllCmd( void )
-{
-	OSStatus				err;
-	BrowseAllContext *		context = NULL;
-	size_t					i;
-	uint32_t				ifIndex;
-	char					ifName[ kInterfaceNameBufLen ];
-	
-	// Check parameters.
-	
-	if( gBrowseAll_BrowseTimeSecs <= 0 )
-	{
-		FPrintF( stdout, "Invalid browse time: %d seconds.\n", gBrowseAll_BrowseTimeSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	context = (BrowseAllContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->connectionTimeoutSecs	= gBrowseAll_ConnectTimeout;
-	context->validateResults		= gBrowseAll_ValidateResults ? true : false;
-#if( TARGET_OS_POSIX )
-	// Increase the open file descriptor limit for connection sockets.
-	
-	if( context->connectionTimeoutSecs > 0 )
-	{
-		struct rlimit		fdLimits;
-		
-		err = getrlimit( RLIMIT_NOFILE, &fdLimits );
-		err = map_global_noerr_errno( err );
-		require_noerr( err, exit );
-		
-		if( fdLimits.rlim_cur < 4096 )
-		{
-			fdLimits.rlim_cur = 4096;
-			err = setrlimit( RLIMIT_NOFILE, &fdLimits );
-			err = map_global_noerr_errno( err );
-			require_noerr( err, exit );
-		}
-	}
-#endif
-	
-	// Get interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &ifIndex );
-	require_noerr_quiet( err, exit );
-	
-#if( TARGET_OS_IOS )
-	// Check for potential issues.
-	
-	if( context->validateResults && os_feature_enabled( mDNSResponder, revoke_media_sessions ) )
-	{
-		FPrintF( stderr,
-			"%s"
-			"Warning: --validate may not work as expected when media revocation is enabled.\n"
-			"         Use 'ffctl mDNSResponder/revoke_media_sessions=off' to disable.\n"
-			"%s",
-			_StdErrIsTTY() ? kANSIRed : "", _StdErrIsTTY() ? kANSINormal : "" );
-	}
-#endif
-	// Print prologue.
-	
-	FPrintF( stdout, "Interface:        %d (%s)\n", (int32_t) ifIndex, InterfaceIndexToName( ifIndex, ifName ) );
-	FPrintF( stdout, "Service types:    ");
-	if( gBrowseAll_ServiceTypesCount > 0 )
-	{
-		FPrintF( stdout, "%s", gBrowseAll_ServiceTypes[ 0 ] );
-		for( i = 1; i < gBrowseAll_ServiceTypesCount; ++i )
-		{
-			FPrintF( stdout, ", %s", gBrowseAll_ServiceTypes[ i ] );
-		}
-		FPrintF( stdout, "\n" );
-	}
-	else
-	{
-		FPrintF( stdout, "all services\n" );
-	}
-	FPrintF( stdout, "Domain:           %s\n", gBrowseAll_Domain ? gBrowseAll_Domain : "default domains" );
-	FPrintF( stdout, "Browse time:      %d second%?c\n", gBrowseAll_BrowseTimeSecs, gBrowseAll_BrowseTimeSecs != 1, 's' );
-	FPrintF( stdout, "Connect timeout:  %d second%?c\n",
-		context->connectionTimeoutSecs, context->connectionTimeoutSecs != 1, 's' );
-	FPrintF( stdout, "IncludeAWDL:      %s\n", YesNoStr( gDNSSDFlag_IncludeAWDL ) );
-	FPrintF( stdout, "New GAI:          %s\n", YesNoStr( gBrowseAll_UseNewGAI ) );
-	FPrintF( stdout, "Validate results: %s\n", YesNoStr( context->validateResults ) );
-	FPrintF( stdout, "Start time:       %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-	err = ServiceBrowserCreate( dispatch_get_main_queue(), ifIndex, gBrowseAll_Domain,
-		(unsigned int) gBrowseAll_BrowseTimeSecs, gDNSSDFlag_IncludeAWDL ? true : false,
-		&context->browser );
-	require_noerr( err, exit );
-	
-	ServiceBrowserSetUseNewGAI( context->browser, gBrowseAll_UseNewGAI ? true : false );
-	ServiceBrowserSetValidateResults( context->browser, context->validateResults );
-	
-	for( i = 0; i < gBrowseAll_ServiceTypesCount; ++i )
-	{
-		err = ServiceBrowserAddServiceType( context->browser, gBrowseAll_ServiceTypes[ i ] );
-		require_noerr( err, exit );
-	}
-	ServiceBrowserSetCallback( context->browser, _BrowseAllServiceBrowserCallback, context );
-	ServiceBrowserStart( context->browser );
-	dispatch_main();
-	
-exit:
-	if( context ) _BrowseAllContextFree( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_BrowseAllContextFree
-//===========================================================================================================================
-
-static void	_BrowseAllContextFree( BrowseAllContext *inContext )
-{
-	check( !inContext->browser );
-	check( !inContext->connectionTimer );
-	check( !inContext->connectionList );
-	ForgetServiceBrowserResults( &inContext->results );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	_BrowseAllServiceBrowserCallback
-//===========================================================================================================================
-
-#define kDiscardProtocolPort		9
-
-static void	_BrowseAllServiceBrowserCallback( ServiceBrowserResults *inResults, OSStatus inError, void *inContext )
-{
-	OSStatus						err;
-	BrowseAllContext * const		context = (BrowseAllContext *) inContext;
-	SBRDomain *						domain;
-	SBRServiceType *				type;
-	SBRServiceInstance *			instance;
-	SBRIPAddress *					ipaddr;
-	
-	Unused( inError );
-	
-	require_action( inResults, exit, err = kUnexpectedErr );
-	
-	check( !context->results );
-	context->results = inResults;
-	ServiceBrowserResultsRetain( context->results );
-	
-	check( context->connectionPendingCount == 0 );
-	if( context->connectionTimeoutSecs > 0 )
-	{
-		BrowseAllConnection *			connection;
-		BrowseAllConnection **			connectionPtr = &context->connectionList;
-		char							destination[ kSockAddrStringMaxSize ];
-		
-		for( domain = context->results->domainList; domain; domain = domain->next )
-		{
-			for( type = domain->typeList; type; type = type->next )
-			{
-				if( !_IsServiceTypeTCP( type->name ) ) continue;
-				for( instance = type->instanceList; instance; instance = instance->next )
-				{
-					if( instance->port == kDiscardProtocolPort ) continue;
-					for( ipaddr = instance->ipaddrList; ipaddr; ipaddr = ipaddr->next )
-					{
-						err = _BrowseAllConnectionCreate( &ipaddr->sip.sa, instance->port, context, &connection );
-						require_noerr( err, exit );
-						
-						*connectionPtr = connection;
-						 connectionPtr = &connection->next;
-						
-						err = SockAddrToString( &ipaddr->sip, kSockAddrStringFlagsNoPort, destination );
-						check_noerr( err );
-						if( !err )
-						{
-							err = AsyncConnection_Connect( &connection->asyncCnx, destination, -instance->port,
-								kAsyncConnectionFlag_P2P, kAsyncConnectionNoTimeout,
-								kSocketBufferSize_DontSet, kSocketBufferSize_DontSet,
-								_BrowseAllConnectionProgress, connection, _BrowseAllConnectionHandler, connection,
-								dispatch_get_main_queue() );
-							check_noerr( err );
-						}
-						if( !err )
-						{
-							_BrowseAllConnectionRetain( connection );
-							connection->status = kInProgressErr;
-							++context->connectionPendingCount;
-						}
-						else
-						{
-							connection->status = err;
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	if( context->connectionPendingCount > 0 )
-	{
-		check( !context->connectionTimer );
-		err = DispatchTimerCreate( dispatch_time_seconds( context->connectionTimeoutSecs ), DISPATCH_TIME_FOREVER,
-			100 * kNanosecondsPerMillisecond, NULL, _BrowseAllExit, NULL, context, &context->connectionTimer );
-		require_noerr( err, exit );
-		dispatch_resume( context->connectionTimer );
-	}
-	else
-	{
-		dispatch_async_f( dispatch_get_main_queue(), context, _BrowseAllExit );
-	}
-	err = kNoErr;
-	
-exit:
-	ForgetCF( &context->browser );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_BrowseAllConnectionCreate
-//===========================================================================================================================
-
-static OSStatus
-	_BrowseAllConnectionCreate(
-		const struct sockaddr *	inSockAddr,
-		uint16_t				inPort,
-		BrowseAllContext *		inContext,
-		BrowseAllConnection **	outConnection )
-{
-	OSStatus					err;
-	BrowseAllConnection *		obj;
-	
-	obj = (BrowseAllConnection *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	SockAddrCopy( inSockAddr, &obj->sip );
-	obj->port		= inPort;
-	obj->context	= inContext;
-	
-	*outConnection = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_BrowseAllConnectionRetain
-//===========================================================================================================================
-
-static void _BrowseAllConnectionRetain( BrowseAllConnection *inConnection )
-{
-	++inConnection->refCount;
-}
-
-//===========================================================================================================================
-//	_BrowseAllConnectionRelease
-//===========================================================================================================================
-
-static void	_BrowseAllConnectionRelease( BrowseAllConnection *inConnection )
-{
-	if( --inConnection->refCount == 0 ) free( inConnection );
-}
-
-//===========================================================================================================================
-//	_BrowseAllConnectionProgress
-//===========================================================================================================================
-
-static void	_BrowseAllConnectionProgress( int inPhase, const void *inDetails, void *inArg )
-{
-	BrowseAllConnection * const		connection = (BrowseAllConnection *) inArg;
-	
-	if( inPhase == kAsyncConnectionPhase_Connected )
-	{
-		const AsyncConnectedInfo * const		info = (AsyncConnectedInfo *) inDetails;
-		
-		connection->connectTimeSecs = info->connectSecs;
-	}
-}
-
-//===========================================================================================================================
-//	_BrowseAllConnectionHandler
-//===========================================================================================================================
-
-static void	_BrowseAllConnectionHandler( SocketRef inSock, OSStatus inError, void *inArg )
-{
-	BrowseAllConnection * const		connection	= (BrowseAllConnection *) inArg;
-	BrowseAllContext * const		context		= connection->context;
-	
-	connection->status = inError;
-	ForgetSocket( &inSock );
-	if( context )
-	{
-		check( context->connectionPendingCount > 0 );
-		if( ( --context->connectionPendingCount == 0 ) && context->connectionTimer )
-		{
-			dispatch_source_forget( &context->connectionTimer );
-			dispatch_async_f( dispatch_get_main_queue(), context, _BrowseAllExit );
-		}
-	}
-	_BrowseAllConnectionRelease( connection );
-}
-
-//===========================================================================================================================
-//	_BrowseAllExit
-//===========================================================================================================================
-
-#define Indent( X )		( (X) * 4 ), ""
-
-static void	_BrowseAllExit( void *inContext )
-{
-	BrowseAllContext * const		context		= (BrowseAllContext *) inContext;
-	SBRDomain *						domain;
-	SBRServiceType *				type;
-	SBRServiceInstance *			instance;
-	SBRIPAddress *					ipaddr;
-	char							textBuf[ 512 ];
-	
-	dispatch_source_forget( &context->connectionTimer );
-	
-	for( domain = context->results->domainList; domain; domain = domain->next )
-	{
-		FPrintF( stdout, "%s\n\n", domain->name );
-		
-		for( type = domain->typeList; type; type = type->next )
-		{
-			const char *		description;
-			const Boolean		serviceTypeIsTCP = _IsServiceTypeTCP( type->name );
-			
-			description = ServiceTypeDescription( type->name );
-			if( description )	FPrintF( stdout, "%*s" "%s (%s)\n\n",	Indent( 1 ), description, type->name );
-			else				FPrintF( stdout, "%*s" "%s\n\n",		Indent( 1 ), type->name );
-			
-			for( instance = type->instanceList; instance; instance = instance->next )
-			{
-				char *				dst = textBuf;
-				char * const		lim = &textBuf[ countof( textBuf ) ];
-				char				ifname[ IF_NAMESIZE + 1 ];
-				
-				SNPrintF_Add( &dst, lim, "%s via ", instance->name );
-				if( instance->ifIndex == 0 )
-				{
-					SNPrintF_Add( &dst, lim, "the Internet" );
-				}
-				else if( if_indextoname( instance->ifIndex, ifname ) )
-				{
-					NetTransportType		netType;
-					
-					SocketGetInterfaceInfo( kInvalidSocketRef, ifname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &netType );
-					SNPrintF_Add( &dst, lim, "%s (%s)",
-						( netType == kNetTransportType_Ethernet ) ? "Ethernet" : NetTransportTypeToString( netType ),
-						ifname );
-				}
-				else
-				{
-					SNPrintF_Add( &dst, lim, "interface index %u", instance->ifIndex );
-				}
-				FPrintF( stdout, "%*s" "%-55s %4llu.%03llu ms\n\n",
-					Indent( 2 ), textBuf, instance->discoverTimeUs / 1000, instance->discoverTimeUs % 1000 );
-				
-				if( instance->hostname )
-				{
-					SNPrintF( textBuf, sizeof( textBuf ), "%s:%u", instance->hostname, instance->port );
-					FPrintF( stdout, "%*s" "%-51s %4llu.%03llu ms\n",
-						Indent( 3 ), textBuf, instance->resolveTimeUs / 1000, instance->resolveTimeUs % 1000 );
-				}
-				else
-				{
-					FPrintF( stdout, "%*s" "%s:%u\n", Indent( 3 ), instance->hostname, instance->port );
-				}
-				
-				for( ipaddr = instance->ipaddrList; ipaddr; ipaddr = ipaddr->next )
-				{
-					BrowseAllConnection *		conn;
-					BrowseAllConnection **		connPtr;
-					const char * const			colorEnd = _StdOutIsTTY() ? kANSINormal : "";
-					
-					FPrintF( stdout, "%*s" "%-##47a %4llu.%03llu ms",
-						Indent( 4 ), &ipaddr->sip.sa, ipaddr->resolveTimeUs / 1000, ipaddr->resolveTimeUs % 1000 );
-					
-					conn = NULL;
-					if( serviceTypeIsTCP && ( instance->port != kDiscardProtocolPort ) )
-					{
-						for( connPtr = &context->connectionList; ( conn = *connPtr ) != NULL; connPtr = &conn->next )
-						{
-							if( ( conn->port == instance->port ) &&
-								( SockAddrCompareAddr( &conn->sip, &ipaddr->sip ) == 0 ) ) break;
-						}
-						if( conn )
-						{
-							if( conn->status == kInProgressErr ) conn->status = kTimeoutErr;
-							*connPtr = conn->next;
-							conn->context = NULL;
-							AsyncConnection_Forget( &conn->asyncCnx );
-						}
-					}
-					FPrintF( stdout, " (");
-					if( context->validateResults ) _PrintValidatedToStdOut( "", ipaddr->validated , ", " );
-					if( conn )
-					{
-						if( conn->status == kNoErr )
-						{
-							FPrintF( stdout, "%sconnected%s in %.3f ms",
-								_StdOutIsTTY() ? kANSIGreen : "", colorEnd, conn->connectTimeSecs * 1000 );
-						}
-						else
-						{
-							FPrintF( stdout, "%scould not connect%s: %m",
-								_StdOutIsTTY() ? kANSIRed : "", colorEnd, conn->status );
-						}
-						_BrowseAllConnectionRelease( conn );
-					}
-					else
-					{
-						FPrintF( stdout, "no connection attempted" );
-					}
-					FPrintF( stdout, ")\n" );
-				}
-				
-				FPrintF( stdout, "\n" );
-				if( instance->txtLen == 0 ) continue;
-				
-				FPrintF( stdout, "%*s" "TXT record (%zu byte%?c):\n",
-					Indent( 3 ), instance->txtLen, instance->txtLen != 1, 's' );
-				if( instance->txtLen > 1 )
-				{
-					FPrintF( stdout, "%3{txt}", instance->txtPtr, instance->txtLen );
-				}
-				else
-				{
-					FPrintF( stdout, "%*s" "%#H\n", Indent( 3 ), instance->txtPtr, (int) instance->txtLen, INT_MAX );
-				}
-				FPrintF( stdout, "\n" );
-			}
-			FPrintF( stdout, "\n" );
-		}
-	}
-	
-	_BrowseAllContextFree( context );
-	Exit( NULL );
-}
-
-//===========================================================================================================================
-//	_IsServiceTypeTCP
-//===========================================================================================================================
-
-static Boolean	_IsServiceTypeTCP( const char *inServiceType )
-{
-	OSStatus			err;
-	const uint8_t *		secondLabel;
-	uint8_t				name[ kDomainNameLengthMax ];
-	
-	err = DomainNameFromString( name, inServiceType, NULL );
-	if( !err )
-	{
-		secondLabel = DomainNameGetNextLabel( name );
-		if( secondLabel && DomainNameEqual( secondLabel, (const uint8_t *) "\x04" "_tcp" ) ) return( true );
-	}
-	return( false );
-}
-
-//===========================================================================================================================
-//	GetNameInfoCmd
-//===========================================================================================================================
-
-const FlagStringPair		kGetNameInfoFlagStringPairs[] =
-{
-	CaseFlagStringify( NI_NUMERICSCOPE ),
-	CaseFlagStringify( NI_DGRAM ),
-	CaseFlagStringify( NI_NUMERICSERV ),
-	CaseFlagStringify( NI_NAMEREQD ),
-	CaseFlagStringify( NI_NUMERICHOST ),
-	CaseFlagStringify( NI_NOFQDN ),
-	{ 0, NULL }
-};
-
-static void	GetNameInfoCmd( void )
-{
-	OSStatus					err;
-	sockaddr_ip					sip;
-	size_t						sockAddrLen;
-	unsigned int				flags;
-	const FlagStringPair *		pair;
-	struct timeval				now;
-	char						host[ NI_MAXHOST ];
-	char						serv[ NI_MAXSERV ];
-	
-	err = StringToSockAddr( gGetNameInfo_IPAddress, &sip, sizeof( sip ), &sockAddrLen );
-	check_noerr( err );
-	if( err )
-	{
-		FPrintF( stderr, "Failed to convert \"%s\" to a sockaddr.\n", gGetNameInfo_IPAddress );
-		goto exit;
-	}
-	
-	flags = 0;
-	if( gGetNameInfoFlag_DGram )		flags |= NI_DGRAM;
-	if( gGetNameInfoFlag_NameReqd )		flags |= NI_NAMEREQD;
-	if( gGetNameInfoFlag_NoFQDN )		flags |= NI_NOFQDN;
-	if( gGetNameInfoFlag_NumericHost )	flags |= NI_NUMERICHOST;
-	if( gGetNameInfoFlag_NumericScope )	flags |= NI_NUMERICSCOPE;
-	if( gGetNameInfoFlag_NumericServ )	flags |= NI_NUMERICSERV;
-	
-	// Print prologue.
-	
-	FPrintF( stdout, "SockAddr:   %##a\n",	&sip.sa );
-	FPrintF( stdout, "Flags:      0x%X < ",	flags );
-	for( pair = kGetNameInfoFlagStringPairs; pair->str != NULL; ++pair )
-	{
-		if( flags & pair->flag ) FPrintF( stdout, "%s ", pair->str );
-	}
-	FPrintF( stdout, ">\n" );
-	FPrintF( stdout, "Start time: %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-	
-	// Call getnameinfo().
-	
-	err = getnameinfo( &sip.sa, (socklen_t) sockAddrLen, host, (socklen_t) sizeof( host ), serv, (socklen_t) sizeof( serv ),
-		(int) flags );
-	gettimeofday( &now, NULL );
-	if( err )
-	{
-		FPrintF( stderr, "Error %d: %s.\n", err, gai_strerror( err ) );
-	}
-	else
-	{
-		FPrintF( stdout, "host: %s\n", host );
-		FPrintF( stdout, "serv: %s\n", serv );
-	}
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:   %{du:time}\n", &now );
-	
-exit:
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-//	GetAddrInfoStressCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef			mainRef;
-	DNSServiceRef			sdRef;
-	DNSServiceFlags			flags;
-	unsigned int			interfaceIndex;
-	unsigned int			connectionNumber;
-	unsigned int			requestCount;
-	unsigned int			requestCountMax;
-	unsigned int			requestCountLimit;
-	unsigned int			durationMinMs;
-	unsigned int			durationMaxMs;
-	
-}	GAIStressContext;
-
-static void	GetAddrInfoStressEvent( void *inContext );
-static void	DNSSD_API
-	GetAddrInfoStressCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-static void	GetAddrInfoStressCmd( void )
-{
-	OSStatus				err;
-	GAIStressContext *		context = NULL;
-	int						i;
-	DNSServiceFlags			flags;
-	uint32_t				ifIndex;
-	char					ifName[ kInterfaceNameBufLen ];
-	
-	if( gGAIStress_TestDurationSecs < 0 )
-	{
-		FPrintF( stdout, "Invalid test duration: %d s.\n", gGAIStress_TestDurationSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	if( gGAIStress_ConnectionCount <= 0 )
-	{
-		FPrintF( stdout, "Invalid simultaneous connection count: %d.\n", gGAIStress_ConnectionCount );
-		err = kParamErr;
-		goto exit;
-	}
-	if( gGAIStress_DurationMinMs <= 0 )
-	{
-		FPrintF( stdout, "Invalid minimum DNSServiceGetAddrInfo() duration: %d ms.\n", gGAIStress_DurationMinMs );
-		err = kParamErr;
-		goto exit;
-	}
-	if( gGAIStress_DurationMaxMs <= 0 )
-	{
-		FPrintF( stdout, "Invalid maximum DNSServiceGetAddrInfo() duration: %d ms.\n", gGAIStress_DurationMaxMs );
-		err = kParamErr;
-		goto exit;
-	}
-	if( gGAIStress_DurationMinMs > gGAIStress_DurationMaxMs )
-	{
-		FPrintF( stdout, "Invalid minimum and maximum DNSServiceGetAddrInfo() durations: %d ms and %d ms.\n",
-			gGAIStress_DurationMinMs, gGAIStress_DurationMaxMs );
-		err = kParamErr;
-		goto exit;
-	}
-	if( gGAIStress_RequestCountMax <= 0 )
-	{
-		FPrintF( stdout, "Invalid maximum request count: %d.\n", gGAIStress_RequestCountMax );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Set flags.
-	
-	flags = GetDNSSDFlagsFromOpts();
-	
-	// Set interface index.
-	
-	err = InterfaceIndexFromArgString( gInterface, &ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	for( i = 0; i < gGAIStress_ConnectionCount; ++i )
-	{
-		context = (GAIStressContext *) calloc( 1, sizeof( *context ) );
-		require_action( context, exit, err = kNoMemoryErr );
-		
-		context->flags				= flags;
-		context->interfaceIndex		= ifIndex;
-		context->connectionNumber	= (unsigned int)( i + 1 );
-		context->requestCountMax	= (unsigned int) gGAIStress_RequestCountMax;
-		context->durationMinMs		= (unsigned int) gGAIStress_DurationMinMs;
-		context->durationMaxMs		= (unsigned int) gGAIStress_DurationMaxMs;
-		
-		dispatch_async_f( dispatch_get_main_queue(), context, GetAddrInfoStressEvent );
-		context = NULL;
-	}
-	
-	if( gGAIStress_TestDurationSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( gGAIStress_TestDurationSecs ), dispatch_get_main_queue(), NULL, Exit );
-	}
-	
-	FPrintF( stdout, "Flags:                %#{flags}\n",	flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:            %d (%s)\n",		(int32_t) ifIndex, InterfaceIndexToName( ifIndex, ifName ) );
-	FPrintF( stdout, "Test duration:        " );
-	if( gGAIStress_TestDurationSecs == 0 )
-	{
-		FPrintF( stdout, "∞\n" );
-	}
-	else
-	{
-		FPrintF( stdout, "%d s\n", gGAIStress_TestDurationSecs );
-	}
-	FPrintF( stdout, "Connection count:     %d\n",			gGAIStress_ConnectionCount );
-	FPrintF( stdout, "Request duration min: %d ms\n",		gGAIStress_DurationMinMs );
-	FPrintF( stdout, "Request duration max: %d ms\n",		gGAIStress_DurationMaxMs );
-	FPrintF( stdout, "Request count max:    %d\n",			gGAIStress_RequestCountMax );
-	FPrintF( stdout, "Start time:           %{du:time}\n",	NULL);
-	FPrintF( stdout, "---\n" );
-	
-	dispatch_main();
-	
-exit:
-	FreeNullSafe( context );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoStressEvent
-//===========================================================================================================================
-
-#define kStressRandStrLen		5
-
-#define kLowercaseAlphaCharSet		"abcdefghijklmnopqrstuvwxyz"
-
-static void	GetAddrInfoStressEvent( void *inContext )
-{
-	GAIStressContext * const		context = (GAIStressContext *) inContext;
-	OSStatus						err;
-	DNSServiceRef					sdRef;
-	unsigned int					nextMs;
-	char							randomStr[ kStressRandStrLen + 1 ];
-	char							hostname[ kStressRandStrLen + 4 + 1 ];
-	Boolean							isConnectionNew	= false;
-	static Boolean					printedHeader	= false;
-	
-	if( !context->mainRef || ( context->requestCount >= context->requestCountLimit ) )
-	{
-		DNSServiceForget( &context->mainRef );
-		context->sdRef				= NULL;
-		context->requestCount		= 0;
-		context->requestCountLimit	= RandomRange( 1, context->requestCountMax );
-		
-		err = DNSServiceCreateConnection( &context->mainRef );
-		require_noerr( err, exit );
-		
-		err = DNSServiceSetDispatchQueue( context->mainRef, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-		
-		isConnectionNew = true;
-	}
-	
-	RandomString( kLowercaseAlphaCharSet, sizeof_string( kLowercaseAlphaCharSet ), 2, kStressRandStrLen, randomStr );
-	SNPrintF( hostname, sizeof( hostname ), "%s.com", randomStr );
-	
-	nextMs = RandomRange( context->durationMinMs, context->durationMaxMs );
-	
-	if( !printedHeader )
-	{
-		FPrintF( stdout, "%-26s Conn  Hostname Dur (ms)\n", "Timestamp" );
-		printedHeader = true;
-	}
-	FPrintF( stdout, "%{du:time} %3u%c %9s %8u\n",
-		NULL, context->connectionNumber, isConnectionNew ? '*': ' ', hostname, nextMs );
-	
-	DNSServiceForget( &context->sdRef );
-	sdRef = context->mainRef;
-	err = DNSServiceGetAddrInfo( &sdRef, context->flags | kDNSServiceFlagsShareConnection, context->interfaceIndex,
-		kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6, hostname, GetAddrInfoStressCallback, NULL );
-	require_noerr( err, exit );
-	context->sdRef = sdRef;
-	
-	context->requestCount++;
-	
-	dispatch_after_f( dispatch_time_milliseconds( nextMs ), dispatch_get_main_queue(), context, GetAddrInfoStressEvent );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	GetAddrInfoStressCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	GetAddrInfoStressCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	Unused( inSDRef );
-	Unused( inFlags );
-	Unused( inInterfaceIndex );
-	Unused( inError );
-	Unused( inHostname );
-	Unused( inSockAddr );
-	Unused( inTTL );
-	Unused( inContext );
-}
-
-//===========================================================================================================================
-//	DNSQueryCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	sockaddr_ip				serverAddr;
-	uint64_t				sendTicks;
-	uint8_t *				msgPtr;
-	size_t					msgLen;
-	size_t					msgOffset;
-	const char *			name;
-	dispatch_source_t		readSource;
-	SocketRef				sock;
-	int						timeLimitSecs;
-	uint16_t				queryID;
-	uint16_t				type;
-	Boolean					haveTCPLen;
-	Boolean					useTCP;
-	Boolean					printRawRData;	// True if RDATA results are not to be formatted.
-	uint8_t					msgBuf[ 512 ];
-	
-}	DNSQueryContext;
-
-static void	DNSQueryPrintPrologue( const DNSQueryContext *inContext );
-static void	DNSQueryReadHandler( void *inContext );
-static void	DNSQueryCancelHandler( void *inContext );
-
-static void	DNSQueryCmd( void )
-{
-	OSStatus				err;
-	DNSQueryContext *		context = NULL;
-	uint8_t *				msgPtr;
-	size_t					msgLen, sendLen;
-	
-	// Check command parameters.
-	
-	if( gDNSQuery_TimeLimitSecs < -1 )
-	{
-		FPrintF( stdout, "Invalid time limit: %d seconds.\n", gDNSQuery_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	if( ( gDNSQuery_Flags < INT16_MIN ) || ( gDNSQuery_Flags > UINT16_MAX ) )
-	{
-		FPrintF( stdout, "DNS flags-and-codes value is out of the unsigned 16-bit range: 0x%08X.\n", gDNSQuery_Flags );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create context.
-	
-	context = (DNSQueryContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->name			= gDNSQuery_Name;
-	context->sock			= kInvalidSocketRef;
-	context->timeLimitSecs	= gDNSQuery_TimeLimitSecs;
-	context->queryID		= (uint16_t) Random32();
-	context->useTCP			= gDNSQuery_UseTCP	 ? true : false;
-	context->printRawRData	= gDNSQuery_RawRData ? true : false;
-	
-#if( TARGET_OS_DARWIN )
-	if( gDNSQuery_Server )
-#endif
-	{
-		err = StringToSockAddr( gDNSQuery_Server, &context->serverAddr, sizeof( context->serverAddr ), NULL );
-		require_noerr( err, exit );
-	}
-#if( TARGET_OS_DARWIN )
-	else
-	{
-		err = GetDefaultDNSServer( &context->serverAddr );
-		require_noerr( err, exit );
-	}
-#endif
-	if( SockAddrGetPort( &context->serverAddr ) == 0 ) SockAddrSetPort( &context->serverAddr, kDNSPort_Do53 );
-	
-	err = RecordTypeFromArgString( gDNSQuery_Type, &context->type );
-	require_noerr( err, exit );
-	
-	// Write query message.
-	
-	check_compile_time_code( sizeof( context->msgBuf ) >= ( 2 + kDNSQueryMessageMaxLen + sizeof( dns_fixed_fields_opt ) ) );
-	
-	msgPtr = context->useTCP ? &context->msgBuf[ 2 ] : context->msgBuf;
-	err = WriteDNSQueryMessage( msgPtr, context->queryID, (uint16_t) gDNSQuery_Flags, context->name, context->type,
-		kDNSServiceClass_IN, &msgLen );
-	require_noerr( err, exit );
-	check( msgLen <= UINT16_MAX );
-	
-	if( gDNSQuery_DNSSEC )
-	{
-		DNSHeader * const					hdr = (DNSHeader *) msgPtr;
-		dns_fixed_fields_opt * const		opt = (dns_fixed_fields_opt *) &msgPtr[ msgLen ];
-		unsigned int						flags;
-		
-		memset( opt, 0, sizeof( *opt ) );
-		dns_fixed_fields_opt_set_type( opt, kDNSServiceType_OPT );
-		dns_fixed_fields_opt_set_udp_payload_size( opt, 512 );
-		dns_fixed_fields_opt_set_extended_flags( opt, kDNSExtendedFlag_DNSSECOK );
-		
-		flags = DNSHeaderGetFlags( hdr ) | kDNSHeaderFlag_AuthenticData;
-		DNSHeaderSetFlags( hdr, flags );
-		DNSHeaderSetAdditionalCount( hdr, 1 );
-		msgLen += sizeof( dns_fixed_fields_opt );
-	}
-	if( gDNSQuery_CheckingDisabled )
-	{
-		DNSHeader * const		hdr = (DNSHeader *) msgPtr;
-		unsigned int			flags;
-		
-		flags = DNSHeaderGetFlags( hdr ) | kDNSHeaderFlag_CheckingDisabled;
-		DNSHeaderSetFlags( hdr, flags );
-	}
-	if( context->useTCP )
-	{
-		WriteBig16Typed( context->msgBuf, (uint16_t) msgLen );
-		sendLen = 2 + msgLen;
-	}
-	else
-	{
-		sendLen = msgLen;
-	}
-	
-	DNSQueryPrintPrologue( context );
-	
-	if( gDNSQuery_Verbose )
-	{
-		FPrintF( stdout, "DNS message to send:\n\n%{du:dnsmsg}\n", msgPtr, msgLen );
-		FPrintF( stdout, "---\n" );
-	}
-	
-	if( context->useTCP )
-	{
-		// Create TCP socket.
-		
-		context->sock = socket( context->serverAddr.sa.sa_family, SOCK_STREAM, IPPROTO_TCP );
-		err = map_socket_creation_errno( context->sock );
-		require_noerr( err, exit );
-		
-		err = SocketConnect( context->sock, &context->serverAddr, 5 );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		// Create UDP socket.
-		
-		err = UDPClientSocketOpen( AF_UNSPEC, &context->serverAddr, 0, -1, NULL, &context->sock );
-		require_noerr( err, exit );
-	}
-	
-	context->sendTicks = UpTicks();
-	err = SocketWriteAll( context->sock, context->msgBuf, sendLen, 5 );
-	require_noerr( err, exit );
-	
-	if( context->timeLimitSecs == 0 ) goto exit;
-	
-	err = DispatchReadSourceCreate( context->sock, NULL, DNSQueryReadHandler, DNSQueryCancelHandler, context,
-		&context->readSource );
-	require_noerr( err, exit );
-	dispatch_resume( context->readSource );
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(), kExitReason_Timeout,
-			Exit );
-	}
-	dispatch_main();
-	
-exit:
-	if( context )
-	{
-		dispatch_source_forget( &context->readSource );
-		ForgetSocket( &context->sock );
-		free( context );
-	}
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	DNSQueryPrintPrologue
-//===========================================================================================================================
-
-static void	DNSQueryPrintPrologue( const DNSQueryContext *inContext )
-{
-	const int		timeLimitSecs = inContext->timeLimitSecs;
-	
-	FPrintF( stdout, "Name:        %s\n",		inContext->name );
-	FPrintF( stdout, "Type:        %s (%u)\n",	RecordTypeToString( inContext->type ), inContext->type );
-	FPrintF( stdout, "Server:      %##a\n",		&inContext->serverAddr );
-	FPrintF( stdout, "Transport:   %s\n",		inContext->useTCP ? "TCP" : "UDP" );
-	FPrintF( stdout, "Time limit:  " );
-	if( timeLimitSecs >= 0 )	FPrintF( stdout, "%d second%?c\n", timeLimitSecs, timeLimitSecs != 1, 's' );
-	else						FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time:  %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-}
-
-//===========================================================================================================================
-//	DNSQueryReadHandler
-//===========================================================================================================================
-
-static void	DNSQueryReadHandler( void *inContext )
-{
-	OSStatus					err;
-	struct timeval				now;
-	const uint64_t				nowTicks	= UpTicks();
-	DNSQueryContext * const		context		= (DNSQueryContext *) inContext;
-	
-	gettimeofday( &now, NULL );
-	
-	if( context->useTCP )
-	{
-		if( !context->haveTCPLen )
-		{
-			err = SocketReadData( context->sock, &context->msgBuf, 2, &context->msgOffset );
-			if( err == EWOULDBLOCK ) { err = kNoErr; goto exit; }
-			require_noerr( err, exit );
-			
-			context->msgOffset	= 0;
-			context->msgLen		= ReadBig16( context->msgBuf );
-			context->haveTCPLen	= true;
-			if( context->msgLen <= sizeof( context->msgBuf ) )
-			{
-				context->msgPtr = context->msgBuf;
-			}
-			else
-			{
-				context->msgPtr = (uint8_t *) malloc( context->msgLen );
-				require_action( context->msgPtr, exit, err = kNoMemoryErr );
-			}
-		}
-		
-		err = SocketReadData( context->sock, context->msgPtr, context->msgLen, &context->msgOffset );
-		if( err == EWOULDBLOCK ) { err = kNoErr; goto exit; }
-		require_noerr( err, exit );
-		context->msgOffset	= 0;
-		context->haveTCPLen	= false;
-	}
-	else
-	{
-		sockaddr_ip		fromAddr;
-		
-		context->msgPtr = context->msgBuf;
-		err = SocketRecvFrom( context->sock, context->msgPtr, sizeof( context->msgBuf ), &context->msgLen, &fromAddr,
-			sizeof( fromAddr ), NULL, NULL, NULL, NULL );
-		require_noerr( err, exit );
-		
-		check( SockAddrCompareAddr( &fromAddr, &context->serverAddr ) == 0 );
-	}
-	
-	FPrintF( stdout, "Receive time: %{du:time}\n",	&now );
-	FPrintF( stdout, "Source:       %##a\n",		&context->serverAddr );
-	FPrintF( stdout, "Message size: %zu\n",			context->msgLen );
-	FPrintF( stdout, "RTT:          %llu ms\n\n",	UpTicksToMilliseconds( nowTicks - context->sendTicks ) );
-	if( context->printRawRData )	FPrintF( stdout, "%{du:rdnsmsg}\n", context->msgPtr, context->msgLen );
-	else							FPrintF( stdout, "%{du:dnsmsg}\n",  context->msgPtr, context->msgLen );
-	
-	if( ( context->msgLen >= kDNSHeaderLength ) && ( DNSHeaderGetID( (DNSHeader *) context->msgPtr ) == context->queryID ) )
-	{
-		Exit( kExitReason_ReceivedResponse );
-	}
-	
-exit:
-	if( err ) dispatch_source_forget( &context->readSource );
-}
-
-//===========================================================================================================================
-//	DNSQueryCancelHandler
-//===========================================================================================================================
-
-static void	DNSQueryCancelHandler( void *inContext )
-{
-	DNSQueryContext * const		context = (DNSQueryContext *) inContext;
-	
-	check( !context->readSource );
-	ForgetSocket( &context->sock );
-	if( context->msgPtr != context->msgBuf ) ForgetMem( &context->msgPtr );
-	free( context );
-	dispatch_async_f( dispatch_get_main_queue(), NULL, Exit );
-}
-
-#if( DNSSDUTIL_INCLUDE_DNSCRYPT )
-//===========================================================================================================================
-//	DNSCryptCmd
-//===========================================================================================================================
-
-#define kDNSCryptPort		443
-
-#define kDNSCryptMinPadLength				8
-#define kDNSCryptMaxPadLength				256
-#define kDNSCryptBlockSize					64
-#define kDNSCryptCertMinimumLength			124
-#define kDNSCryptClientMagicLength			8
-#define kDNSCryptResolverMagicLength		8
-#define kDNSCryptHalfNonceLength			12
-#define kDNSCryptCertMagicLength			4
-
-check_compile_time( ( kDNSCryptHalfNonceLength * 2 ) == crypto_box_NONCEBYTES );
-
-static const uint8_t		kDNSCryptCertMagic[ kDNSCryptCertMagicLength ] = { 'D', 'N', 'S', 'C' };
-static const uint8_t		kDNSCryptResolverMagic[ kDNSCryptResolverMagicLength ] =
-{
-	0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38
-};
-
-typedef struct
-{
-	uint8_t		certMagic[ kDNSCryptCertMagicLength ];
-	uint8_t		esVersion[ 2 ];
-	uint8_t		minorVersion[ 2 ];
-	uint8_t		signature[ crypto_sign_BYTES ];
-	uint8_t		publicKey[ crypto_box_PUBLICKEYBYTES ];
-	uint8_t		clientMagic[ kDNSCryptClientMagicLength ];
-	uint8_t		serial[ 4 ];
-	uint8_t		startTime[ 4 ];
-	uint8_t		endTime[ 4 ];
-	uint8_t		extensions[ 1 ];	// Variably-sized extension data.
-	
-}	DNSCryptCert;
-
-check_compile_time( offsetof( DNSCryptCert, extensions ) == kDNSCryptCertMinimumLength );
-
-typedef struct
-{
-	uint8_t		clientMagic[ kDNSCryptClientMagicLength ];
-	uint8_t		clientPublicKey[ crypto_box_PUBLICKEYBYTES ];
-	uint8_t		clientNonce[ kDNSCryptHalfNonceLength ];
-	uint8_t		poly1305MAC[ 16 ];
-	
-}	DNSCryptQueryHeader;
-
-check_compile_time( sizeof( DNSCryptQueryHeader ) == 68 );
-check_compile_time( sizeof( DNSCryptQueryHeader ) >= crypto_box_ZEROBYTES );
-check_compile_time( ( sizeof( DNSCryptQueryHeader ) - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES ) ==
-	offsetof( DNSCryptQueryHeader, poly1305MAC ) );
-
-typedef struct
-{
-	uint8_t		resolverMagic[ kDNSCryptResolverMagicLength ];
-	uint8_t		clientNonce[ kDNSCryptHalfNonceLength ];
-	uint8_t		resolverNonce[ kDNSCryptHalfNonceLength ];
-	uint8_t		poly1305MAC[ 16 ];
-	
-}	DNSCryptResponseHeader;
-
-check_compile_time( sizeof( DNSCryptResponseHeader ) == 48 );
-check_compile_time( offsetof( DNSCryptResponseHeader, poly1305MAC ) >= crypto_box_BOXZEROBYTES );
-check_compile_time( ( offsetof( DNSCryptResponseHeader, poly1305MAC ) - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES ) ==
-	sizeof( DNSCryptResponseHeader ) );
-
-typedef struct
-{
-	sockaddr_ip				serverAddr;
-	uint64_t				sendTicks;
-	const char *			providerName;
-	const char *			qname;
-	const uint8_t *			certPtr;
-	size_t					certLen;
-	dispatch_source_t		readSource;
-	size_t					msgLen;
-	int						timeLimitSecs;
-	uint16_t				queryID;
-	uint16_t				qtype;
-	Boolean					printRawRData;
-	uint8_t					serverPublicSignKey[ crypto_sign_PUBLICKEYBYTES ];
-	uint8_t					serverPublicKey[ crypto_box_PUBLICKEYBYTES ];
-	uint8_t					clientPublicKey[ crypto_box_PUBLICKEYBYTES ];
-	uint8_t					clientSecretKey[ crypto_box_SECRETKEYBYTES ];
-	uint8_t					clientMagic[ kDNSCryptClientMagicLength ];
-	uint8_t					clientNonce[ kDNSCryptHalfNonceLength ];
-	uint8_t					nmKey[ crypto_box_BEFORENMBYTES ];
-	uint8_t					msgBuf[ 512 ];
-	
-}	DNSCryptContext;
-
-static void		DNSCryptReceiveCertHandler( void *inContext );
-static void		DNSCryptReceiveResponseHandler( void *inContext );
-static void		DNSCryptProceed( void *inContext );
-static OSStatus	DNSCryptProcessCert( DNSCryptContext *inContext );
-static OSStatus	DNSCryptBuildQuery( DNSCryptContext *inContext );
-static OSStatus	DNSCryptSendQuery( DNSCryptContext *inContext );
-static void		DNSCryptPrintCertificate( const DNSCryptCert *inCert, size_t inLen );
-
-static void	DNSCryptCmd( void )
-{
-	OSStatus				err;
-	DNSCryptContext *		context		= NULL;
-	size_t					writtenBytes;
-	size_t					totalBytes;
-	SocketContext *			sockCtx;
-	SocketRef				sock		= kInvalidSocketRef;
-	const char *			ptr;
-	
-	// Check command parameters.
-	
-	if( gDNSCrypt_TimeLimitSecs < -1 )
-	{
-		FPrintF( stdout, "Invalid time limit: %d seconds.\n", gDNSCrypt_TimeLimitSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create context.
-	
-	context = (DNSCryptContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->providerName	= gDNSCrypt_ProviderName;
-	context->qname			= gDNSCrypt_Name;
-	context->timeLimitSecs	= gDNSCrypt_TimeLimitSecs;
-	context->printRawRData	= gDNSCrypt_RawRData ? true : false;
-	
-	err = crypto_box_keypair( context->clientPublicKey, context->clientSecretKey );
-	require_noerr( err, exit );
-	
-	err = HexToData( gDNSCrypt_ProviderKey, kSizeCString, kHexToData_DefaultFlags,
-		context->serverPublicSignKey, sizeof( context->serverPublicSignKey ), &writtenBytes, &totalBytes, &ptr );
-	if( err || ( *ptr != '\0' ) )
-	{
-		FPrintF( stderr, "Failed to parse public signing key hex string (%s).\n", gDNSCrypt_ProviderKey );
-		goto exit;
-	}
-	else if( totalBytes != sizeof( context->serverPublicSignKey ) )
-	{
-		FPrintF( stderr, "Public signing key contains incorrect number of hex bytes (%zu != %zu)\n",
-			totalBytes, sizeof( context->serverPublicSignKey ) );
-		err = kSizeErr;
-		goto exit;
-	}
-	check( writtenBytes == totalBytes );
-	
-	err = StringToSockAddr( gDNSCrypt_Server, &context->serverAddr, sizeof( context->serverAddr ), NULL );
-	require_noerr( err, exit );
-	if( SockAddrGetPort( &context->serverAddr ) == 0 ) SockAddrSetPort( &context->serverAddr, kDNSCryptPort );
-	
-	err = RecordTypeFromArgString( gDNSCrypt_Type, &context->qtype );
-	require_noerr( err, exit );
-	
-	// Write query message.
-	
-	context->queryID = (uint16_t) Random32();
-	err = WriteDNSQueryMessage( context->msgBuf, context->queryID, kDNSHeaderFlag_RecursionDesired, context->providerName,
-		kDNSServiceType_TXT, kDNSServiceClass_IN, &context->msgLen );
-	require_noerr( err, exit );
-	
-	// Create UDP socket.
-	
-	err = UDPClientSocketOpen( AF_UNSPEC, &context->serverAddr, 0, -1, NULL, &sock );
-	require_noerr( err, exit );
-	
-	// Send DNS query.
-	
-	context->sendTicks = UpTicks();
-	err = SocketWriteAll( sock, context->msgBuf, context->msgLen, 5 );
-	require_noerr( err, exit );
-	
-	sockCtx = SocketContextCreate( sock, context, &err );
-	require_noerr( err, exit );
-	sock = kInvalidSocketRef;
-	
-	err = DispatchReadSourceCreate( sockCtx->sock, NULL, DNSCryptReceiveCertHandler, SocketContextCancelHandler, sockCtx,
-		&context->readSource );
-	if( err ) ForgetSocketContext( &sockCtx );
-	require_noerr( err, exit );
-	
-	dispatch_resume( context->readSource );
-	
-	if( context->timeLimitSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->timeLimitSecs ), dispatch_get_main_queue(), kExitReason_Timeout,
-			Exit );
-	}
-	dispatch_main();
-	
-exit:
-	if( context ) free( context );
-	ForgetSocket( &sock );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	DNSCryptReceiveCertHandler
-//===========================================================================================================================
-
-static void	DNSCryptReceiveCertHandler( void *inContext )
-{
-	OSStatus					err;
-	struct timeval				now;
-	const uint64_t				nowTicks	= UpTicks();
-	SocketContext * const		sockCtx		= (SocketContext *) inContext;
-	DNSCryptContext * const		context		= (DNSCryptContext *) sockCtx->userContext;
-	const DNSHeader *			hdr;
-	sockaddr_ip					fromAddr;
-	const uint8_t *				ptr;
-	const uint8_t *				txtPtr;
-	size_t						txtLen;
-	unsigned int				answerCount, i;
-	uint8_t						targetName[ kDomainNameLengthMax ];
-	
-	gettimeofday( &now, NULL );
-	
-	dispatch_source_forget( &context->readSource );
-	
-	err = SocketRecvFrom( sockCtx->sock, context->msgBuf, sizeof( context->msgBuf ), &context->msgLen,
-		&fromAddr, sizeof( fromAddr ), NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	check( SockAddrCompareAddr( &fromAddr, &context->serverAddr ) == 0 );
-	
-	FPrintF( stdout, "Receive time: %{du:time}\n",	&now );
-	FPrintF( stdout, "Source:       %##a\n",		&context->serverAddr );
-	FPrintF( stdout, "Message size: %zu\n",			context->msgLen );
-	FPrintF( stdout, "RTT:          %llu ms\n\n",	UpTicksToMilliseconds( nowTicks - context->sendTicks ) );
-	if( context->printRawRData )	FPrintF( stdout, "%{du:rdnsmsg}\n", context->msgBuf, context->msgLen );
-	else							FPrintF( stdout, "%{du:dnsmsg}\n",  context->msgBuf, context->msgLen );
-	
-	require_action_quiet( context->msgLen >= kDNSHeaderLength, exit, err = kSizeErr );
-	
-	hdr = (DNSHeader *) context->msgBuf;
-	require_action_quiet( DNSHeaderGetID( hdr ) == context->queryID, exit, err = kMismatchErr );
-	
-	err = DNSMessageGetAnswerSection( context->msgBuf, context->msgLen, &ptr );
-	require_noerr( err, exit );
-	
-	err = DomainNameFromString( targetName, context->providerName, NULL );
-	require_noerr( err, exit );
-	
-	answerCount = DNSHeaderGetAnswerCount( hdr );
-	for( i = 0; i < answerCount; ++i )
-	{
-		uint16_t		type;
-		uint16_t		class;
-		uint8_t			name[ kDomainNameLengthMax ];
-		
-		err = DNSMessageExtractRecord( context->msgBuf, context->msgLen, ptr, name, &type, &class, NULL, &txtPtr, &txtLen,
-			&ptr );
-		require_noerr( err, exit );
-		
-		if( ( type == kDNSServiceType_TXT ) && ( class == kDNSServiceClass_IN ) && DomainNameEqual( name, targetName ) )
-		{
-			break;
-		}
-	}
-	
-	if( txtLen < ( 1 + kDNSCryptCertMinimumLength ) )
-	{
-		FPrintF( stderr, "TXT record length is too short (%u < %u)\n", txtLen, kDNSCryptCertMinimumLength + 1 );
-		err = kSizeErr;
-		goto exit;
-	}
-	if( txtPtr[ 0 ] < kDNSCryptCertMinimumLength )
-	{
-		FPrintF( stderr, "TXT record value length is too short (%u < %u)\n", txtPtr[ 0 ], kDNSCryptCertMinimumLength );
-		err = kSizeErr;
-		goto exit;
-	}
-	
-	context->certLen = txtPtr[ 0 ];
-	context->certPtr = &txtPtr[ 1 ];
-	
-	dispatch_async_f( dispatch_get_main_queue(), context, DNSCryptProceed );
-	
-exit:
-	if( err ) Exit( NULL );
-}
-
-//===========================================================================================================================
-//	DNSCryptReceiveResponseHandler
-//===========================================================================================================================
-
-static void	DNSCryptReceiveResponseHandler( void *inContext )
-{
-	OSStatus						err;
-	struct timeval					now;
-	const uint64_t					nowTicks	= UpTicks();
-	SocketContext * const			sockCtx		= (SocketContext *) inContext;
-	DNSCryptContext * const			context		= (DNSCryptContext *) sockCtx->userContext;
-	sockaddr_ip						fromAddr;
-	DNSCryptResponseHeader *		hdr;
-	const uint8_t *					end;
-	uint8_t *						ciphertext;
-	uint8_t *						plaintext;
-	const uint8_t *					response;
-	uint8_t							nonce[ crypto_box_NONCEBYTES ];
-	
-	gettimeofday( &now, NULL );
-	
-	dispatch_source_forget( &context->readSource );
-	
-	err = SocketRecvFrom( sockCtx->sock, context->msgBuf, sizeof( context->msgBuf ), &context->msgLen,
-		&fromAddr, sizeof( fromAddr ), NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	check( SockAddrCompareAddr( &fromAddr, &context->serverAddr ) == 0 );
-	
-	FPrintF( stdout, "Receive time: %{du:time}\n",	&now );
-	FPrintF( stdout, "Source:       %##a\n",		&context->serverAddr );
-	FPrintF( stdout, "Message size: %zu\n",			context->msgLen );
-	FPrintF( stdout, "RTT:          %llu ms\n\n",	UpTicksToMilliseconds( nowTicks - context->sendTicks ) );
-	
-	if( context->msgLen < sizeof( DNSCryptResponseHeader ) )
-	{
-		FPrintF( stderr, "DNSCrypt response is too short.\n" );
-		err = kSizeErr;
-		goto exit;
-	}
-	
-	hdr = (DNSCryptResponseHeader *) context->msgBuf;
-	
-	if( memcmp( hdr->resolverMagic, kDNSCryptResolverMagic, kDNSCryptResolverMagicLength ) != 0 )
-	{
-		FPrintF( stderr, "DNSCrypt response resolver magic %#H != %#H\n",
-			hdr->resolverMagic,		kDNSCryptResolverMagicLength, INT_MAX,
-			kDNSCryptResolverMagic, kDNSCryptResolverMagicLength, INT_MAX );
-		err = kValueErr;
-		goto exit;
-	}
-	
-	if( memcmp( hdr->clientNonce, context->clientNonce, kDNSCryptHalfNonceLength ) != 0 )
-	{
-		FPrintF( stderr, "DNSCrypt response client nonce mismatch.\n" );
-		err = kValueErr;
-		goto exit;
-	}
-	
-	memcpy( nonce, hdr->clientNonce, crypto_box_NONCEBYTES );
-	
-	ciphertext = hdr->poly1305MAC - crypto_box_BOXZEROBYTES;
-	memset( ciphertext, 0, crypto_box_BOXZEROBYTES );
-	
-	plaintext = (uint8_t *)( hdr + 1 ) - crypto_box_ZEROBYTES;
-	check( plaintext == ciphertext );
-	
-	end = context->msgBuf + context->msgLen;
-	
-	err = crypto_box_open_afternm( plaintext, ciphertext, (size_t)( end - ciphertext ), nonce, context->nmKey );
-	require_noerr( err, exit );
-	
-	response = plaintext + crypto_box_ZEROBYTES;
-	if( context->printRawRData )	FPrintF( stdout, "%{du:rdnsmsg}\n", response, (size_t)( end - response ) );
-	else							FPrintF( stdout, "%{du:dnsmsg}\n",  response, (size_t)( end - response ) );
-	Exit( kExitReason_ReceivedResponse );
-	
-exit:
-	if( err ) Exit( NULL );
-}
-
-//===========================================================================================================================
-//	DNSCryptProceed
-//===========================================================================================================================
-
-static void	DNSCryptProceed( void *inContext )
-{
-	OSStatus					err;
-	DNSCryptContext * const		context = (DNSCryptContext *) inContext;
-	
-	err = DNSCryptProcessCert( context );
-	require_noerr_quiet( err, exit );
-	
-	err = DNSCryptBuildQuery( context );
-	require_noerr_quiet( err, exit );
-	
-	err = DNSCryptSendQuery( context );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	if( err ) Exit( NULL );
-}
-
-//===========================================================================================================================
-//	DNSCryptProcessCert
-//===========================================================================================================================
-
-static OSStatus	DNSCryptProcessCert( DNSCryptContext *inContext )
-{
-	OSStatus						err;
-	const DNSCryptCert * const		cert	= (DNSCryptCert *) inContext->certPtr;
-	const uint8_t * const			certEnd	= inContext->certPtr + inContext->certLen;
-	struct timeval					now;
-	time_t							startTimeSecs, endTimeSecs;
-	size_t							signedLen;
-	uint8_t *						tempBuf;
-	unsigned long long				tempLen;
-	
-	DNSCryptPrintCertificate( cert, inContext->certLen );
-	
-	if( memcmp( cert->certMagic, kDNSCryptCertMagic, kDNSCryptCertMagicLength ) != 0 )
-	{
-		FPrintF( stderr, "DNSCrypt certificate magic %#H != %#H\n",
-			cert->certMagic,	kDNSCryptCertMagicLength, INT_MAX,
-			kDNSCryptCertMagic, kDNSCryptCertMagicLength, INT_MAX );
-		err = kValueErr;
-		goto exit;
-	}
-	
-	startTimeSecs	= (time_t) ReadBig32( cert->startTime );
-	endTimeSecs		= (time_t) ReadBig32( cert->endTime );
-	
-	gettimeofday( &now, NULL );
-	if( now.tv_sec < startTimeSecs )
-	{
-		FPrintF( stderr, "DNSCrypt certificate start time is in the future.\n" );
-		err = kDateErr;
-		goto exit;
-	}
-	if( now.tv_sec >= endTimeSecs )
-	{
-		FPrintF( stderr, "DNSCrypt certificate has expired.\n" );
-		err = kDateErr;
-		goto exit;
-	}
-	
-	signedLen = (size_t)( certEnd - cert->signature );
-	tempBuf = (uint8_t *) malloc( signedLen );
-	require_action( tempBuf, exit, err = kNoMemoryErr );
-	err = crypto_sign_open( tempBuf, &tempLen, cert->signature, signedLen, inContext->serverPublicSignKey );
-	free( tempBuf );
-	if( err )
-	{
-		FPrintF( stderr, "DNSCrypt certificate failed verification.\n" );
-		err = kAuthenticationErr;
-		goto exit;
-	}
-	
-	memcpy( inContext->serverPublicKey,	cert->publicKey,	crypto_box_PUBLICKEYBYTES );
-	memcpy( inContext->clientMagic,		cert->clientMagic,	kDNSCryptClientMagicLength );
-	
-	err = crypto_box_beforenm( inContext->nmKey, inContext->serverPublicKey, inContext->clientSecretKey );
-	require_noerr( err, exit );
-	
-	inContext->certPtr	= NULL;
-	inContext->certLen	= 0;
-	inContext->msgLen	= 0;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DNSCryptBuildQuery
-//===========================================================================================================================
-
-static OSStatus	DNSCryptPadQuery( uint8_t *inMsgPtr, size_t inMsgLen, size_t inMaxLen, size_t *outPaddedLen );
-
-static OSStatus	DNSCryptBuildQuery( DNSCryptContext *inContext )
-{
-	OSStatus						err;
-	DNSCryptQueryHeader * const		hdr			= (DNSCryptQueryHeader *) inContext->msgBuf;
-	uint8_t * const					queryPtr	= (uint8_t *)( hdr + 1 );
-	size_t							queryLen;
-	size_t							paddedQueryLen;
-	const uint8_t * const			msgLimit	= inContext->msgBuf + sizeof( inContext->msgBuf );
-	const uint8_t *					padLimit;
-	uint8_t							nonce[ crypto_box_NONCEBYTES ];
-	
-	check_compile_time_code( sizeof( inContext->msgBuf ) >= ( sizeof( DNSCryptQueryHeader ) + kDNSQueryMessageMaxLen ) );
-	
-	inContext->queryID = (uint16_t) Random32();
-	err = WriteDNSQueryMessage( queryPtr, inContext->queryID, kDNSHeaderFlag_RecursionDesired, inContext->qname,
-		inContext->qtype, kDNSServiceClass_IN, &queryLen );
-	require_noerr( err, exit );
-	
-	padLimit = &queryPtr[ queryLen + kDNSCryptMaxPadLength ];
-	if( padLimit > msgLimit ) padLimit = msgLimit;
-	
-	err = DNSCryptPadQuery( queryPtr, queryLen, (size_t)( padLimit - queryPtr ), &paddedQueryLen );
-	require_noerr( err, exit );
-	
-	memset( queryPtr - crypto_box_ZEROBYTES, 0, crypto_box_ZEROBYTES );
-	RandomBytes( inContext->clientNonce, kDNSCryptHalfNonceLength );
-	memcpy( nonce, inContext->clientNonce, kDNSCryptHalfNonceLength );
-	memset( &nonce[ kDNSCryptHalfNonceLength ], 0, kDNSCryptHalfNonceLength );
-	
-	err = crypto_box_afternm( queryPtr - crypto_box_ZEROBYTES, queryPtr - crypto_box_ZEROBYTES,
-		paddedQueryLen + crypto_box_ZEROBYTES, nonce, inContext->nmKey );
-	require_noerr( err, exit );
-	
-	memcpy( hdr->clientMagic,		inContext->clientMagic,		kDNSCryptClientMagicLength );
-	memcpy( hdr->clientPublicKey,	inContext->clientPublicKey,	crypto_box_PUBLICKEYBYTES );
-	memcpy( hdr->clientNonce,		nonce,						kDNSCryptHalfNonceLength );
-	
-	inContext->msgLen = (size_t)( &queryPtr[ paddedQueryLen ] - inContext->msgBuf );
-	
-exit:
-	return( err );
-}
-
-static OSStatus	DNSCryptPadQuery( uint8_t *inMsgPtr, size_t inMsgLen, size_t inMaxLen, size_t *outPaddedLen )
-{
-	OSStatus		err;
-	size_t			paddedLen;
-	
-	require_action_quiet( ( inMsgLen + kDNSCryptMinPadLength ) <= inMaxLen, exit, err = kSizeErr );
-	
-	paddedLen = inMsgLen + kDNSCryptMinPadLength +
-		arc4random_uniform( (uint32_t)( inMaxLen - ( inMsgLen + kDNSCryptMinPadLength ) + 1 ) );
-	paddedLen += ( kDNSCryptBlockSize - ( paddedLen % kDNSCryptBlockSize ) );
-	if( paddedLen > inMaxLen ) paddedLen = inMaxLen;
-	
-	inMsgPtr[ inMsgLen ] = 0x80;
-	memset( &inMsgPtr[ inMsgLen + 1 ], 0, paddedLen - ( inMsgLen + 1 ) );
-	
-	if( outPaddedLen ) *outPaddedLen = paddedLen;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DNSCryptSendQuery
-//===========================================================================================================================
-
-static OSStatus	DNSCryptSendQuery( DNSCryptContext *inContext )
-{
-	OSStatus			err;
-	SocketContext *		sockCtx;
-	SocketRef			sock = kInvalidSocketRef;
-	
-	check( inContext->msgLen > 0 );
-	check( !inContext->readSource );
-	
-	err = UDPClientSocketOpen( AF_UNSPEC, &inContext->serverAddr, 0, -1, NULL, &sock );
-	require_noerr( err, exit );
-	
-	inContext->sendTicks = UpTicks();
-	err = SocketWriteAll( sock, inContext->msgBuf, inContext->msgLen, 5 );
-	require_noerr( err, exit );
-	
-	sockCtx = SocketContextCreate( sock, inContext, &err );
-	require_noerr( err, exit );
-	sock = kInvalidSocketRef;
-	
-	err = DispatchReadSourceCreate( sockCtx->sock, NULL, DNSCryptReceiveResponseHandler, SocketContextCancelHandler, sockCtx,
-		&inContext->readSource );
-	if( err ) ForgetSocketContext( &sockCtx );
-	require_noerr( err, exit );
-	
-	dispatch_resume( inContext->readSource );
-	
-exit:
-	ForgetSocket( &sock );
-	return( err );
-}
-
-//===========================================================================================================================
-//	DNSCryptPrintCertificate
-//===========================================================================================================================
-
-#define kCertTimeStrBufLen		32
-
-static char *	CertTimeStr( time_t inTime, char inBuffer[ kCertTimeStrBufLen ] );
-
-static void	DNSCryptPrintCertificate( const DNSCryptCert *inCert, size_t inLen )
-{
-	time_t		startTime, endTime;
-	int			extLen;
-	char		timeBuf[ kCertTimeStrBufLen ];
-	
-	check( inLen >= kDNSCryptCertMinimumLength );
-	
-	startTime	= (time_t) ReadBig32( inCert->startTime );
-	endTime		= (time_t) ReadBig32( inCert->endTime );
-	
-	FPrintF( stdout, "DNSCrypt certificate (%zu bytes):\n", inLen );
-	FPrintF( stdout, "Cert Magic:    %#H\n", inCert->certMagic, kDNSCryptCertMagicLength, INT_MAX );
-	FPrintF( stdout, "ES Version:    %u\n",	ReadBig16( inCert->esVersion ) );
-	FPrintF( stdout, "Minor Version: %u\n",	ReadBig16( inCert->minorVersion ) );
-	FPrintF( stdout, "Signature:     %H\n",	inCert->signature, crypto_sign_BYTES / 2, INT_MAX );
-	FPrintF( stdout, "               %H\n",	&inCert->signature[ crypto_sign_BYTES / 2 ], crypto_sign_BYTES / 2, INT_MAX );
-	FPrintF( stdout, "Public Key:    %H\n", inCert->publicKey, sizeof( inCert->publicKey ), INT_MAX );
-	FPrintF( stdout, "Client Magic:  %H\n", inCert->clientMagic, kDNSCryptClientMagicLength, INT_MAX );
-	FPrintF( stdout, "Serial:        %u\n",	ReadBig32( inCert->serial ) );
-	FPrintF( stdout, "Start Time:    %u (%s)\n", (uint32_t) startTime, CertTimeStr( startTime, timeBuf ) );
-	FPrintF( stdout, "End Time:      %u (%s)\n", (uint32_t) endTime, CertTimeStr( endTime, timeBuf ) );
-	
-	if( inLen > kDNSCryptCertMinimumLength )
-	{
-		extLen = (int)( inLen - kDNSCryptCertMinimumLength );
-		FPrintF( stdout, "Extensions:    %.1H\n", inCert->extensions, extLen, extLen );
-	}
-	FPrintF( stdout, "\n" );
-}
-
-static char *	CertTimeStr( time_t inTime, char inBuffer[ kCertTimeStrBufLen ] )
-{
-	struct tm *		tm;
-	
-	tm = localtime( &inTime );
-	if( !tm )
-	{
-		dlogassert( "localtime() returned a NULL pointer.\n" );
-		*inBuffer = '\0';
-	}
-	else
-	{
-		strftime( inBuffer, kCertTimeStrBufLen, "%a %b %d %H:%M:%S %Z %Y", tm );
-	}
-	
-	return( inBuffer );
-}
-
-#endif	// DNSSDUTIL_INCLUDE_DNSCRYPT
-
-//===========================================================================================================================
-//	MDNSQueryCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	const char *			qnameStr;							// Name (QNAME) of the record being queried as a C string.
-	dispatch_source_t		readSourceV4;						// Read dispatch source for IPv4 socket.
-	dispatch_source_t		readSourceV6;						// Read dispatch source for IPv6 socket.
-	int						localPort;							// The port number to which the sockets are bound.
-	int						receiveSecs;						// After send, the amount of time to spend receiving.
-	uint32_t				ifIndex;							// Index of the interface over which to send the query.
-	uint16_t				qtype;								// The type (QTYPE) of the record being queried.
-	Boolean					isQU;								// True if the query is QU, i.e., requests unicast responses.
-	Boolean					allResponses;						// True if all mDNS messages received should be printed.
-	Boolean					printRawRData;						// True if RDATA should be printed as hexdumps.
-	Boolean					useIPv4;							// True if the query should be sent via IPv4 multicast.
-	Boolean					useIPv6;							// True if the query should be sent via IPv6 multicast.
-	char					ifName[ IF_NAMESIZE + 1 ];			// Name of the interface over which to send the query.
-	uint8_t					qname[ kDomainNameLengthMax ];		// Buffer to hold the QNAME in DNS label format.
-	uint8_t					msgBuf[ kMDNSMessageSizeMax ];		// mDNS message buffer.
-	
-}	MDNSQueryContext;
-
-static void	MDNSQueryPrintPrologue( const MDNSQueryContext *inContext );
-static void	MDNSQueryReadHandler( void *inContext );
-
-static void	MDNSQueryCmd( void )
-{
-	OSStatus				err;
-	MDNSQueryContext *		context;
-	SocketRef				sockV4 = kInvalidSocketRef;
-	SocketRef				sockV6 = kInvalidSocketRef;
-	ssize_t					n;
-	const char *			ifname;
-	size_t					msgLen;
-	unsigned int			sendCount;
-	
-	// Check command parameters.
-	
-	if( gMDNSQuery_ReceiveSecs < -1 )
-	{
-		FPrintF( stdout, "Invalid receive time value: %d seconds.\n", gMDNSQuery_ReceiveSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	context = (MDNSQueryContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->qnameStr		= gMDNSQuery_Name;
-	context->receiveSecs	= gMDNSQuery_ReceiveSecs;
-	context->isQU			= gMDNSQuery_IsQU		  ? true : false;
-	context->allResponses	= gMDNSQuery_AllResponses ? true : false;
-	context->printRawRData	= gMDNSQuery_RawRData	  ? true : false;
-	context->useIPv4		= ( gMDNSQuery_UseIPv4 || !gMDNSQuery_UseIPv6 ) ? true : false;
-	context->useIPv6		= ( gMDNSQuery_UseIPv6 || !gMDNSQuery_UseIPv4 ) ? true : false;
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	ifname = if_indextoname( context->ifIndex, context->ifName );
-	require_action( ifname, exit, err = kNameErr );
-	
-	err = RecordTypeFromArgString( gMDNSQuery_Type, &context->qtype );
-	require_noerr( err, exit );
-	
-	// Set up IPv4 socket.
-	
-	if( context->useIPv4 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV4(),
-			gMDNSQuery_SourcePort ? gMDNSQuery_SourcePort : ( context->isQU ? context->localPort : kMDNSPort ),
-			ifname, context->ifIndex, !context->isQU, &context->localPort, &sockV4 );
-		require_noerr( err, exit );
-	}
-	
-	// Set up IPv6 socket.
-	
-	if( context->useIPv6 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV6(),
-			gMDNSQuery_SourcePort ? gMDNSQuery_SourcePort : ( context->isQU ? context->localPort : kMDNSPort ),
-			ifname, context->ifIndex, !context->isQU, &context->localPort, &sockV6 );
-		require_noerr( err, exit );
-	}
-	
-	// Craft mDNS query message.
-	
-	check_compile_time_code( sizeof( context->msgBuf ) >= kDNSQueryMessageMaxLen );
-	err = WriteDNSQueryMessage( context->msgBuf, kDefaultMDNSMessageID, kDefaultMDNSQueryFlags, context->qnameStr,
-		context->qtype, context->isQU ? ( kDNSServiceClass_IN | kMDNSClassUnicastResponseBit ) : kDNSServiceClass_IN,
-		&msgLen );
-	require_noerr( err, exit );
-	
-	// Print prologue.
-	
-	MDNSQueryPrintPrologue( context );
-	
-	// Send mDNS query message.
-	
-	sendCount = 0;
-	if( IsValidSocket( sockV4 ) )
-	{
-		const struct sockaddr * const		mcastAddr4 = GetMDNSMulticastAddrV4();
-		
-		n = sendto( sockV4, context->msgBuf, msgLen, 0, mcastAddr4, SockAddrGetSize( mcastAddr4 ) );
-		err = map_socket_value_errno( sockV4, n == (ssize_t) msgLen, n );
-		if( err )
-		{
-			FPrintF( stderr, "*** Failed to send query on IPv4 socket with error %#m\n", err );
-			ForgetSocket( &sockV4 );
-		}
-		else
-		{
-			++sendCount;
-		}
-	}
-	if( IsValidSocket( sockV6 ) )
-	{
-		const struct sockaddr * const		mcastAddr6 = GetMDNSMulticastAddrV6();
-		
-		n = sendto( sockV6, context->msgBuf, msgLen, 0, mcastAddr6, SockAddrGetSize( mcastAddr6 ) );
-		err = map_socket_value_errno( sockV6, n == (ssize_t) msgLen, n );
-		if( err )
-		{
-			FPrintF( stderr, "*** Failed to send query on IPv6 socket with error %#m\n", err );
-			ForgetSocket( &sockV6 );
-		}
-		else
-		{
-			++sendCount;
-		}
-	}
-	require_action_quiet( sendCount > 0, exit, err = kUnexpectedErr );
-	
-	// If there's no wait period after the send, then exit.
-	
-	if( context->receiveSecs == 0 ) goto exit;
-	
-	// Create dispatch read sources for socket(s).
-	
-	if( IsValidSocket( sockV4 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV4, context, &err );
-		require_noerr( err, exit );
-		sockV4 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, MDNSQueryReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV4 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV4 );
-	}
-	
-	if( IsValidSocket( sockV6 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV6, context, &err );
-		require_noerr( err, exit );
-		sockV6 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, MDNSQueryReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV6 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV6 );
-	}
-	
-	if( context->receiveSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->receiveSecs ), dispatch_get_main_queue(), kExitReason_Timeout,
-			Exit );
-	}
-	dispatch_main();
-	
-exit:
-	ForgetSocket( &sockV4 );
-	ForgetSocket( &sockV6 );
-	exit( 1 );
-}
-
-//===========================================================================================================================
-//	MDNSColliderCmd
-//===========================================================================================================================
-
-static void	_MDNSColliderCmdStopHandler( void *inContext, OSStatus inError );
-
-static void	MDNSColliderCmd( void )
-{
-	OSStatus					err;
-	MDNSColliderRef				collider = NULL;
-	uint8_t *					rdataPtr = NULL;
-	size_t						rdataLen = 0;
-	const char *				ifname;
-	uint32_t					ifIndex;
-	MDNSColliderProtocols		protocols;
-	uint16_t					type;
-	char						ifName[ IF_NAMESIZE + 1 ];
-	uint8_t						name[ kDomainNameLengthMax ];
-	
-	err = InterfaceIndexFromArgString( gInterface, &ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	ifname = if_indextoname( ifIndex, ifName );
-	if( !ifname )
-	{
-		FPrintF( stderr, "error: Invalid interface name or index: %s\n", gInterface );
-		err = kNameErr;
-		goto exit;
-	}
-	
-	err = DomainNameFromString( name, gMDNSCollider_Name, NULL );
-	if( err )
-	{
-		FPrintF( stderr, "error: Invalid record name: %s\n", gMDNSCollider_Name );
-		goto exit;
-	}
-	
-	err = RecordTypeFromArgString( gMDNSCollider_Type, &type );
-	require_noerr_quiet( err, exit );
-	
-	if( gMDNSCollider_RecordData )
-	{
-		err = RecordDataFromArgString( gMDNSCollider_RecordData, &rdataPtr, &rdataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	err = MDNSColliderCreate( dispatch_get_main_queue(), &collider );
-	require_noerr( err, exit );
-	
-	err = MDNSColliderSetProgram( collider, gMDNSCollider_Program );
-	if( err )
-	{
-		FPrintF( stderr, "error: Failed to set program string: '%s'\n", gMDNSCollider_Program );
-		goto exit;
-	}
-	
-	err = MDNSColliderSetRecord( collider, name, type, rdataPtr, rdataLen );
-	require_noerr( err, exit );
-	ForgetMem( &rdataPtr );
-	
-	protocols = kMDNSColliderProtocol_None;
-	if( gMDNSCollider_UseIPv4 || !gMDNSCollider_UseIPv6 ) protocols |= kMDNSColliderProtocol_IPv4;
-	if( gMDNSCollider_UseIPv6 || !gMDNSCollider_UseIPv4 ) protocols |= kMDNSColliderProtocol_IPv6;
-	MDNSColliderSetProtocols( collider, protocols );
-	MDNSColliderSetInterfaceIndex( collider, ifIndex );
-	MDNSColliderSetStopHandler( collider, _MDNSColliderCmdStopHandler, collider );
-	
-	err = MDNSColliderStart( collider );
-	require_noerr( err, exit );
-	
-	dispatch_main();
-	
-exit:
-	FreeNullSafe( rdataPtr );
-	CFReleaseNullSafe( collider );
-	if( err ) exit( 1 );
-}
-
-static void	_MDNSColliderCmdStopHandler( void *inContext, OSStatus inError )
-{
-	MDNSColliderRef const		collider = (MDNSColliderRef) inContext;
-	
-	CFRelease( collider );
-	exit( inError ? 1 : 0 );
-}
-
-//===========================================================================================================================
-//	MDNSQueryPrintPrologue
-//===========================================================================================================================
-
-static void	MDNSQueryPrintPrologue( const MDNSQueryContext *inContext )
-{
-	const int		receiveSecs = inContext->receiveSecs;
-	
-	FPrintF( stdout, "Interface:        %d (%s)\n",		(int32_t) inContext->ifIndex, inContext->ifName );
-	FPrintF( stdout, "Name:             %s\n",			inContext->qnameStr );
-	FPrintF( stdout, "Type:             %s (%u)\n",		RecordTypeToString( inContext->qtype ), inContext->qtype );
-	FPrintF( stdout, "Class:            IN (%s)\n",		inContext->isQU ? "QU" : "QM" );
-	FPrintF( stdout, "Local port:       %d\n",			inContext->localPort );
-	FPrintF( stdout, "IP protocols:     %?s%?s%?s\n",
-		inContext->useIPv4, "IPv4", ( inContext->useIPv4 && inContext->useIPv6 ), ", ", inContext->useIPv6, "IPv6" );
-	FPrintF( stdout, "Receive duration: " );
-	if( receiveSecs >= 0 )	FPrintF( stdout, "%d second%?c\n", receiveSecs, receiveSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time:       %{du:time}\n",	NULL );
-}
-
-//===========================================================================================================================
-//	MDNSQueryReadHandler
-//===========================================================================================================================
-
-static void	MDNSQueryReadHandler( void *inContext )
-{
-	OSStatus						err;
-	struct timeval					now;
-	SocketContext * const			sockCtx = (SocketContext *) inContext;
-	MDNSQueryContext * const		context = (MDNSQueryContext *) sockCtx->userContext;
-	size_t							msgLen;
-	sockaddr_ip						fromAddr;
-	Boolean							foundAnswer	= false;
-	
-	gettimeofday( &now, NULL );
-	
-	err = SocketRecvFrom( sockCtx->sock, context->msgBuf, sizeof( context->msgBuf ), &msgLen, &fromAddr,
-		sizeof( fromAddr ), NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	
-	if( !context->allResponses && ( msgLen >= kDNSHeaderLength ) )
-	{
-		const uint8_t *				ptr;
-		const DNSHeader * const		hdr = (DNSHeader *) context->msgBuf;
-		unsigned int				rrCount, i;
-		uint16_t					type, class;
-		uint8_t						name[ kDomainNameLengthMax ];
-		
-		err = DNSMessageGetAnswerSection( context->msgBuf, msgLen, &ptr );
-		require_noerr( err, exit );
-		
-		if( context->qname[ 0 ] == 0 )
-		{
-			err = DomainNameAppendString( context->qname, context->qnameStr, NULL );
-			require_noerr( err, exit );
-		}
-		
-		rrCount = DNSHeaderGetAnswerCount( hdr ) + DNSHeaderGetAuthorityCount( hdr ) + DNSHeaderGetAdditionalCount( hdr );
-		for( i = 0; i < rrCount; ++i )
-		{
-			err = DNSMessageExtractRecord( context->msgBuf, msgLen, ptr, name, &type, &class, NULL, NULL, NULL, &ptr );
-			require_noerr( err, exit );
-			
-			if( ( ( context->qtype == kDNSServiceType_ANY ) || ( type == context->qtype ) ) &&
-				DomainNameEqual( name, context->qname ) )
-			{
-				foundAnswer = true;
-				break;
-			}
-		}
-	}
-	if( context->allResponses || foundAnswer )
-	{
-		FPrintF( stdout, "---\n" );
-		FPrintF( stdout, "Receive time: %{du:time}\n",	&now );
-		FPrintF( stdout, "Source:       %##a\n",		&fromAddr );
-		FPrintF( stdout, "Message size: %zu\n\n",		msgLen );
-		if( context->printRawRData )	FPrintF( stdout, "%#{du:rdnsmsg}\n", context->msgBuf, msgLen );
-		else							FPrintF( stdout, "%#{du:dnsmsg}\n",  context->msgBuf, msgLen );
-	}
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	PIDToUUIDCmd
-//===========================================================================================================================
-
-static void	PIDToUUIDCmd( void )
-{
-	OSStatus		err;
-	uuid_t			uuid;
-	
-	err = mdns_system_pid_to_uuid( gPIDToUUID_PID, uuid );
-	require_noerr_quiet( err, exit );
-	
-	FPrintF( stdout, "%#U\n", uuid );
-	
-exit:
-	gExitCode = err ? 1 : 0;
-}
-#endif
-
-//===========================================================================================================================
-//	DNSServerCommand
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServerRef				server;				// Reference to the DNS server.
-	dispatch_queue_t			queue;				// Serial queue for server.
-	sockaddr_ip *				addrArray;			// Server's addresses.
-	size_t						addrCount;			// Count of server's addresses.
-	dispatch_source_t			sourceSigInt;		// Dispatch source for SIGINT.
-	dispatch_source_t			sourceSigTerm;		// Dispatch source for SIGTERM.
-	const char *				domainOverride;		// If non-NULL, server is to use this domain instead of "d.test.".
-	dispatch_group_t			group;				// Dispatch group to signal when command is done.
-	dispatch_source_t			processMonitor;		// Process monitor source for process being followed, if any.
-	nw_resolver_config_t		secureDNSConfig;	// Resolver configuration for DNS over TLS (DoT).
-	mdns_network_policy_t		domainPolicy;		// Networking policy for matching domains to DoT service.
-	SecIdentityRef				secIdentity;		// Security identity associated with a self-signed certificate for DoT.
-	nw_listener_t				tlsListener;		// TLS listener.
-	DNSProtocol					protocol;			// DNS protocol to use, e.g., Do53, DoT, or DoH.
-	pid_t						followPID;			// PID of process being followed, if any. If it exits, we exit.
-	int32_t						refCount;			// Object's reference count.
-	OSStatus					error;				// Error encounted while running server.
-	uint16_t					portRequested;		// The port that was requested by the user.
-	uint16_t					portActual;			// DNS server's actual port number.
-	Boolean						loopbackOnly;		// True if the server should be bound to the loopback interface.
-	Boolean						addedResolver;		// True if a resolver entry was added to the system DNS settings.
-	Boolean						stopped;			// True if the command has stopped.
-	
-}	DNSServerCmd;
-
-static DNSServerCmd *	_DNSServerCmdCreate( OSStatus *outError );
-static void				_DNSServerCmdRetain( DNSServerCmd *inCmd );
-static void				_DNSServerCmdRelease( DNSServerCmd *inCmd );
-static void				_DNSServerCmdStart( void *inCtx );
-static void				_DNSServerCmdStop( DNSServerCmd *inCmd, OSStatus inError );
-static OSStatus			_DNSServerCmdAddExtraLoopbackAddrs( sockaddr_ip *inAddrArray, size_t inAddrCount );
-static void				_DNSServerCmdServerStartHandler( uint16_t inActualPort, void *inCtx );
-static void				_DNSServerCmdServerStopHandler( OSStatus inError, void *inCtx );
-static void				_DNSServerCmdSIGINTHandler( void *inCtx );
-static void				_DNSServerCmdSIGTERMHandler( void *inCtx );
-static void				_DNSServerCmdShutdown( DNSServerCmd *inCtx, int inSignal );
-static void				_DNSServerCmdFollowedProcessHandler( void *inCtx );
-static OSStatus			_DNSServerCmdModifySystemSettings( DNSServerCmd *inCmd );
-static OSStatus			_DNSServerCmdUndoSystemSettings( DNSServerCmd *inCmd );
-static SecIdentityRef	_DNSServerCmdCreateSecIdentity( OSStatus *outError );
-static OSStatus			_DNSServerCmdSetUpCertificate( SecIdentityRef inIdentity );
-static OSStatus			_DNSServerCmdCleanUpCertificates( void );
-static nw_listener_t
-	_DNSServerCmdCreateTLSListener(
-		sec_identity_t	inIdentity,
-		uint16_t		inPort,
-		Boolean			inUseHTTPS,
-		OSStatus *		outError );
-static OSStatus			_DNSServerCmdHandleNewTLSConnection( DNSServerCmd *inCmd, nw_connection_t inConnection );
-
-ulog_define_ex( kDNSSDUtilIdentifier, DNSServer, kLogLevelInfo, kLogFlags_None, "DNSServer", NULL );
-#define ds_ulog( LEVEL, ... )		ulog( &log_category_from_name( DNSServer ), (LEVEL), __VA_ARGS__ )
-
-static void	DNSServerCommand( void )
-{
-	OSStatus			err;
-	DNSServerCmd *		cmd = NULL;
-	sockaddr_ip *		sip;
-	size_t				addrCount, extraLoopbackV6Count;
-	uint16_t			port;
-	Boolean				listenOnV4, listenOnV6;
-	
-	// Check command arguments.
-	
-	if( gDNSServer_Foreground ) LogControl( "DNSServer:output=file;stdout,DNSServer:flags=time;prefix" );
-	err = CheckIntegerArgument( gDNSServer_ResponseDelayMs, "response delay (ms)", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gDNSServer_DefaultTTL, "default TTL", 0, INT32_MAX );
-	require_noerr_quiet( err, exit );
-	
-	cmd = _DNSServerCmdCreate( &err );
-	require_noerr( err, exit );
-	
-	cmd->followPID		= -1;
-	cmd->domainOverride	= gDNSServer_DomainOverride;
-	cmd->protocol = (DNSProtocol) CLIArgToValue( "protocol", gDNSServer_Protocol, &err,
-		kDNSProtocolStr_Do53,	(int) kDNSProtocol_Do53,
-		kDNSProtocolStr_DoT,	(int) kDNSProtocol_DoT,
-		kDNSProtocolStr_DoH,	(int) kDNSProtocol_DoH,
-		NULL );
-	require_noerr_quiet( err, exit );
-	
-	if( gDNSServer_Port == -1 )
-	{
-		switch( cmd->protocol )
-		{
-			case kDNSProtocol_Do53:	port = kDNSPort_Do53;	break;
-			case kDNSProtocol_DoT:	port = kDNSPort_DoT;	break;
-			case kDNSProtocol_DoH:	port = kDNSPort_DoH;	break;
-		}
-	}
-	else
-	{
-		err = CheckIntegerArgument( gDNSServer_Port, "port number", 0, UINT16_MAX );
-		require_noerr_quiet( err, exit );
-		
-		port = (uint16_t) gDNSServer_Port;
-	}
-	cmd->portRequested = port;
-	listenOnV4 = gDNSServer_ListenOnV4 || !gDNSServer_ListenOnV6;
-	listenOnV6 = gDNSServer_ListenOnV6 || !gDNSServer_ListenOnV4;
-	if( gDNSServer_LoopbackOnly || ( cmd->protocol == kDNSProtocol_DoT ) || ( cmd->protocol == kDNSProtocol_DoH ) )
-	{
-		cmd->loopbackOnly = true;
-	}
-	if( cmd->loopbackOnly && listenOnV6 )
-	{
-		err = CheckIntegerArgument( gDNSServer_ExtraV6Count, "extra IPv6", 0, 100 );
-		require_noerr_quiet( err, exit );
-		extraLoopbackV6Count = (size_t) gDNSServer_ExtraV6Count;
-		if( extraLoopbackV6Count > 0 )
-		{
-			err = CheckRootUser();
-			require_noerr_quiet( err, exit );
-		}
-	}
-	else
-	{
-		extraLoopbackV6Count = 0;
-	}
-	if( gDNSServer_FollowPID )
-	{
-		cmd->followPID = _StringToPID( gDNSServer_FollowPID, &err );
-		if( err || ( cmd->followPID < 0 ) )
-		{
-			FPrintF( stderr, "error: Invalid follow PID: %s\n", gDNSServer_FollowPID );
-			err = kParamErr;
-			goto exit;
-		}
-	}
-	// Set up IP addresses.
-	
-	if( listenOnV4 ) ++cmd->addrCount;
-	if( listenOnV6 ) ++cmd->addrCount;
-	cmd->addrCount += extraLoopbackV6Count;
-	check( cmd->addrCount > 0 );
-	cmd->addrArray = (sockaddr_ip *) calloc( cmd->addrCount, sizeof( *cmd->addrArray ) );
-	require_action( cmd->addrArray, exit, err = kNoMemoryErr );
-	
-	addrCount = 0;
-	if( listenOnV4 )
-	{
-		sip = &cmd->addrArray[ addrCount++ ];
-		_SockAddrInitIPv4( &sip->v4, cmd->loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY, 0 );
-	}
-	if( listenOnV6 )
-	{
-		const struct in6_addr * const		addr = cmd->loopbackOnly ? &in6addr_loopback : &in6addr_any;
-		
-		sip = &cmd->addrArray[ addrCount++ ];
-		_SockAddrInitIPv6( &sip->v6, addr->s6_addr, 0, 0 );
-	}
-	if( extraLoopbackV6Count > 0 )
-	{
-		err = _DNSServerCmdAddExtraLoopbackAddrs( &cmd->addrArray[ addrCount ], extraLoopbackV6Count );
-		require_noerr( err, exit );
-		addrCount += extraLoopbackV6Count;
-	}
-	check( addrCount == cmd->addrCount );
-	
-	// Start command.
-	
-	cmd->queue = dispatch_queue_create( "com.apple.dnssdutil.server-command", DISPATCH_QUEUE_SERIAL );
-	require_action( cmd->queue, exit, err = kNoResourcesErr );
-	
-	dispatch_group_enter( cmd->group ); // Enter for the duration of _DNSServerCmdStart().
-	dispatch_async_f( cmd->queue, cmd, _DNSServerCmdStart );
-    dispatch_group_wait( cmd->group, DISPATCH_TIME_FOREVER );
-	
-exit:
-	if( err ) FPrintF( stderr, "Failed to start DNS server: %#m\n", err );
-	if( cmd ) _DNSServerCmdRelease( cmd );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-
-static DNSServerCmd *	_DNSServerCmdCreate( OSStatus * const outError )
-{
-	OSStatus			err;
-	DNSServerCmd *		obj;
-	DNSServerCmd *		cmd = NULL;
-	
-	obj = (DNSServerCmd *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	obj->group		= dispatch_group_create();
-	require_action( obj->group, exit, err = kNoResourcesErr );
-	
-	cmd = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _DNSServerCmdRelease( obj );
-	if( outError ) *outError = err;
-	return( cmd );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdRetain( DNSServerCmd * const inCmd )
-{
-	atomic_add_32( &inCmd->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdRelease( DNSServerCmd * const inCmd )
-{
-	if( atomic_add_and_fetch_32( &inCmd->refCount, -1 ) == 0 )
-	{
-		size_t		i;
-		
-		check( !inCmd->server );
-		check( !inCmd->sourceSigInt );
-		check( !inCmd->sourceSigTerm );
-		check( !inCmd->processMonitor );
-		check( !inCmd->secureDNSConfig );
-		check( !inCmd->domainPolicy );
-		check( !inCmd->tlsListener );
-		for( i = 0; i < inCmd->addrCount; ++i )
-		{
-			OSStatus								err;
-			const struct sockaddr_in6 * const		sin6 = &inCmd->addrArray[ i ].v6;
-			int										cmp;
-			
-			if( sin6->sin6_family != AF_INET6 ) continue;
-			cmp = memcmp( sin6->sin6_addr.s6_addr, kExtraLoopbackIPv6Prefix, sizeof( kExtraLoopbackIPv6Prefix ) );
-			if( cmp != 0 ) continue;
-			err = _InterfaceIPv6AddressRemove( "lo0", sin6->sin6_addr.s6_addr );
-			check_noerr( err );
-		}
-		dispatch_forget( &inCmd->queue );
-		dispatch_forget( &inCmd->group );
-		ForgetMem( &inCmd->addrArray );
-		CFForget( &inCmd->secIdentity );
-		free( inCmd );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdStart( void *inCtx )
-{
-	OSStatus					err;
-	DNSServerCmd * const		cmd = (DNSServerCmd *) inCtx;
-	size_t						i;
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, cmd->queue, _DNSServerCmdSIGINTHandler, cmd, &cmd->sourceSigInt );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigInt );
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, cmd->queue, _DNSServerCmdSIGTERMHandler, cmd, &cmd->sourceSigTerm );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigTerm );
-	
-	if( cmd->followPID >= 0 )
-	{
-		err = DispatchProcessMonitorCreate( cmd->followPID, DISPATCH_PROC_EXIT, cmd->queue,
-			_DNSServerCmdFollowedProcessHandler, NULL, cmd, &cmd->processMonitor );
-		require_noerr( err, exit );
-		dispatch_resume( cmd->processMonitor );
-	}
-	
-	err = _DNSServerCreate( cmd->queue, _DNSServerCmdServerStartHandler, _DNSServerCmdServerStopHandler, cmd,
-		(unsigned int) gDNSServer_ResponseDelayMs, (uint32_t) gDNSServer_DefaultTTL, cmd->addrArray, cmd->addrCount,
-		cmd->domainOverride, gDNSServer_BadUDPMode ? true : false, &cmd->server );
-	require_noerr( err, exit );
-	
-	_DNSServerCmdRetain( cmd );
-	dispatch_group_enter( cmd->group ); // Enter for the DNS server's lifetime.
-	_DNSServerSetPort( cmd->server, _DNSProtocolIsSecure( cmd->protocol ) ? 0 : cmd->portRequested );
-	for( i = 0; i < gDNSServer_IgnoredQTypesCount; ++i )
-	{
-		uint16_t		qtype;
-		
-		err = RecordTypeFromArgString( gDNSServer_IgnoredQTypes[ i ], &qtype );
-		require_noerr( err, exit );
-		
-		err = _DNSServerSetIgnoredQType( cmd->server, qtype );
-		require_noerr( err, exit );
-	}
-	_DNSServerStart( cmd->server );
-	
-exit:
-	if( err ) _DNSServerCmdStop( cmd, err );
-	dispatch_group_leave( cmd->group ); // Leave for _DNSServerCmdStart().
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdStop( DNSServerCmd *inCmd, OSStatus inError )
-{
-	if( !inCmd->stopped )
-	{
-		inCmd->stopped = true;
-		if( !inCmd->error ) inCmd->error = inError;
-		if( inCmd->server )
-		{
-			_DNSServerStop( inCmd->server );
-			CFForget( &inCmd->server );
-		}
-		dispatch_source_forget( &inCmd->sourceSigInt );
-		dispatch_source_forget( &inCmd->sourceSigTerm );
-		dispatch_source_forget( &inCmd->processMonitor );
-	}
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerCmdAddExtraLoopbackAddrs( sockaddr_ip *inAddrArray, size_t inAddrCount )
-{
-	OSStatus		err;
-	uint8_t			addrV6[ 16 ];
-	size_t			i;
-	
-	check_compile_time_code( sizeof( kExtraLoopbackIPv6Prefix ) == 8 );
-	memcpy( addrV6, kExtraLoopbackIPv6Prefix, 8 );	// 64-bit prefix
-	RandomBytes( &addrV6[ 8 ], 4 );					// 32-bit random
-	WriteBig32Typed( &addrV6[ 12 ], 2 );			// 16-bit base offset starting at 2
-	for( i = 0; i < inAddrCount; ++i )
-	{
-		struct sockaddr_in6 * const		sin6 = &inAddrArray[ i ].v6;
-		
-		err = _InterfaceIPv6AddressAdd( "lo0", addrV6, kExtraLoopbackIPv6PrefixBitLen );
-		require_noerr( err, exit );
-		
-		_SockAddrInitIPv6( sin6, addrV6, 0, 0 );
-		BigEndianIntegerIncrement( addrV6, sizeof( addrV6 ) );
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void
-_DNSServerCmdServerStartHandler( const uint16_t inActualPort, void * const inCtx )
-{
-	OSStatus					err;
-	DNSServerCmd * const		cmd			= (DNSServerCmd *) inCtx;
-	sec_identity_t				secIdentity	= NULL;
-	
-	cmd->portActual = inActualPort;
-	if( cmd->loopbackOnly )
-	{
-		err = _DNSServerCmdModifySystemSettings( cmd );
-		require_noerr_action( err, exit, ds_ulog( kLogLevelError,
-			"Failed to modify system settings: %#m\n", err ) );
-		
-		if( _DNSProtocolIsSecure( cmd->protocol ) )
-		{
-			Boolean		useHTTPS;
-			
-			err = _DNSServerCmdCleanUpCertificates();
-			require_noerr( err, exit );
-			
-			check( !cmd->secIdentity );
-			cmd->secIdentity = _DNSServerCmdCreateSecIdentity( &err );
-			require_noerr( err, exit );
-			
-			err = _DNSServerCmdSetUpCertificate( cmd->secIdentity );
-			require_noerr( err, exit );
-			
-			secIdentity = sec_identity_create( cmd->secIdentity );
-			require_action( secIdentity, exit, err = kNoResourcesErr );
-			
-			useHTTPS = ( cmd->protocol == kDNSProtocol_DoH );
-			cmd->tlsListener = _DNSServerCmdCreateTLSListener( secIdentity, cmd->portRequested, useHTTPS, &err );
-			require_noerr( err, exit );
-			
-			_DNSServerCmdRetain( cmd );
-			dispatch_group_enter( cmd->group ); // Enter for the TLS listener's lifetime.
-			nw_listener_set_state_changed_handler( cmd->tlsListener,
-			^( const nw_listener_state_t inState, const nw_error_t inError )
-			{
-				if( cmd->tlsListener )
-				{
-					switch( inState )
-					{
-						case nw_listener_state_ready:
-							ds_ulog( kLogLevelInfo, "Listening for TLS connections on port %d\n",
-								nw_listener_get_port( cmd->tlsListener ) );
-							break;
-						
-						case nw_listener_state_failed:
-						{
-							OSStatus		listenerErr;
-							
-							ds_ulog( kLogLevelError, "TLS listener failed: %@\n", inError );
-							listenerErr = nw_error_get_error_code( inError );
-							if( !listenerErr ) listenerErr = kUnknownErr;
-							_DNSServerCmdStop( cmd, listenerErr );
-							break;
-						}
-						case nw_listener_state_invalid:
-						case nw_listener_state_waiting:
-						case nw_listener_state_cancelled:
-							break;
-					}
-				}
-				if( inState == nw_listener_state_cancelled )
-				{
-					dispatch_group_leave( cmd->group ); // Leave for the TLS listener.
-					_DNSServerCmdRelease( cmd );
-				}
-			} );
-			nw_listener_set_new_connection_handler( cmd->tlsListener,
-			^( const nw_connection_t inConnection )
-			{
-				OSStatus		connectionErr;
-				
-				connectionErr = _DNSServerCmdHandleNewTLSConnection( cmd, inConnection );
-				if( connectionErr ) _DNSServerCmdStop( cmd, connectionErr );
-			} );
-			nw_listener_set_queue( cmd->tlsListener, cmd->queue );
-			nw_listener_start( cmd->tlsListener );
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	if( secIdentity ) sec_release( secIdentity );
-	if( err ) _DNSServerCmdStop( cmd, err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdServerStopHandler( OSStatus inError, void *inCtx )
-{
-	OSStatus					err;
-	DNSServerCmd * const		cmd = (DNSServerCmd *) inCtx;
-	
-	if( inError )
-	{
-		ds_ulog( kLogLevelError, "The server stopped unexpectedly with error: %#m.\n", inError );
-		if( !cmd->error ) cmd->error = inError;
-	}
-	err = _DNSServerCmdUndoSystemSettings( cmd );
-	if( err )
-	{
-		ds_ulog( kLogLevelError, "Failed to undo system settings: %#m\n", err );
-		if( !cmd->error ) cmd->error = err;
-	}
-	if( _DNSProtocolIsSecure( cmd->protocol ) )
-	{
-		err = _DNSServerCmdCleanUpCertificates();
-		if( !cmd->error ) cmd->error = err;
-	}
-	if( cmd->tlsListener )
-	{
-		nw_listener_cancel( cmd->tlsListener );
-		nw_forget( &cmd->tlsListener );
-	}
-	_DNSServerCmdStop( cmd, cmd->error );
-	dispatch_group_leave( cmd->group ); // Leave for the DNS server.
-	_DNSServerCmdRelease( cmd );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdSIGINTHandler( void *inCtx )
-{
-	_DNSServerCmdShutdown( (DNSServerCmd *) inCtx, SIGINT );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdSIGTERMHandler( void *inCtx )
-{
-	_DNSServerCmdShutdown( (DNSServerCmd *) inCtx, SIGTERM );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdShutdown( DNSServerCmd *inCmd, int inSignal )
-{
-	dispatch_source_forget( &inCmd->sourceSigInt );
-	dispatch_source_forget( &inCmd->sourceSigTerm );
-	dispatch_source_forget( &inCmd->processMonitor );
-	if( inSignal == 0 )
-	{
-		ds_ulog( kLogLevelNotice, "Exiting: followed process (%lld) exited\n", (int64_t) inCmd->followPID );
-	}
-	else
-	{
-		const char *		sigName;
-		
-		switch( inSignal )
-		{
-			case SIGINT:	sigName = "SIGINT";		break;
-			case SIGTERM:	sigName = "SIGTERM";	break;
-			default:		sigName = "???";		break;
-		}
-		ds_ulog( kLogLevelNotice, "Exiting: received signal %d (%s)\n", inSignal, sigName );
-	}
-	_DNSServerCmdStop( inCmd, kNoErr );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerCmdFollowedProcessHandler( void *inCtx )
-{
-	DNSServerCmd * const		cmd = (DNSServerCmd *) inCtx;
-	
-	if( dispatch_source_get_data( cmd->processMonitor ) & DISPATCH_PROC_EXIT ) _DNSServerCmdShutdown( cmd, 0 );
-}
-//===========================================================================================================================
-
-#define kDNSServerHostname				"dns.apple.test"
-#define kDNSServerDoHURLPath			"/dns-query"
-#define kDNSServerDoHURLTemplate		"https://" kDNSServerHostname kDNSServerDoHURLPath
-#define kDNSServerServiceID				CFSTR( "com.apple.dnssdutil.server" )
-
-static OSStatus	_DNSServerCmdModifySystemSettings( DNSServerCmd * const inCmd )
-{
-	OSStatus					err;
-	mdns_dns_configurator_t		configurator	= NULL;
-	nw_resolver_config_t		secureDNSConfig	= NULL;
-	nw_endpoint_t				endpoint		= NULL;
-	const char *				primaryDomainStr;
-	CFArrayRef					domains			= NULL;
-	size_t						i;
-	char						dnssecDomainStr[ kDNSServiceMaxDomainName ];
-	
-	require_action_quiet( inCmd->addrCount > 0, exit, err = kCountErr );
-	
-	err = DomainNameToString( kDNSServerDomain_DNSSEC, NULL, dnssecDomainStr, NULL );
-	require_noerr( err, exit );
-	
-	primaryDomainStr = inCmd->domainOverride ? inCmd->domainOverride : "d.test.";
-	switch( inCmd->protocol )
-	{
-		case kDNSProtocol_DoT:
-		case kDNSProtocol_DoH:
-		{
-			bool					ok;
-			const char * const		domainStrings[] =
-			{
-				primaryDomainStr,
-				dnssecDomainStr,
-				kDNSServerReverseIPv4DomainStr,
-				kDNSServerReverseIPv6DomainStr
-			};
-			
-			// Try to clean up a stale Do53 resolver entry for a previous server from the system's DNS configuration in case
-			// one happens to still be present. Such an entry may interfere with the system settings for the DoT server if
-			// they're for the same domain, i.e., queries may be incorrectly sent to the Do53 server which no longer exists.
-			
-			mdns_dns_configurator_deregister_configuration( kDNSServerServiceID, CFSTR( kDNSSDUtilIdentifier ) );
-			if( inCmd->protocol == kDNSProtocol_DoT )
-			{
-				endpoint = nw_endpoint_create_host_with_numeric_port( kDNSServerHostname, 0 );
-				require_action( endpoint, exit, err = kUnknownErr );
-				
-				secureDNSConfig = nw_resolver_config_create_tls( endpoint );
-				nw_forget( &endpoint );
-				require_action( secureDNSConfig, exit, err = kUnknownErr );
-			}
-			else
-			{
-				endpoint = nw_endpoint_create_url( kDNSServerDoHURLTemplate );
-				require_action( endpoint, exit, err = kUnknownErr );
-				
-				secureDNSConfig = nw_resolver_config_create_https( endpoint );
-				nw_forget( &endpoint );
-				require_action( secureDNSConfig, exit, err = kUnknownErr );
-			}
-			domains = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-			require_action( domains, exit, err = kNoResourcesErr );
-			
-			for( i = 0; i < countof( domainStrings ); ++i )
-			{
-				const char * const		domainStr = domainStrings[ i ];
-				size_t					len;
-				char *					domainStrDup;
-				
-				len = strlen( domainStr );
-				if( len <= 0 ) continue;
-				
-				// NECP doesn't properly handle trailing root dots at the end of FQDNs, so remove them if present.
-				
-				if( domainStr[ len - 1 ] == '.' ) --len;
-				domainStrDup = NULL;
-				ASPrintF( &domainStrDup, "%.*s", (int) len, domainStr );
-				require_action( domainStrDup, exit, err = kNoMemoryErr );
-				
-				nw_resolver_config_add_match_domain( secureDNSConfig, domainStrDup );
-				err = CFPropertyListAppendFormatted( NULL, domains, "%s", domainStrDup );
-				ForgetMem( &domainStrDup );
-				require_noerr( err, exit );
-			}
-			for( i = 0; i < inCmd->addrCount; ++i )
-			{
-				const sockaddr_ip * const		sip = &inCmd->addrArray[ i ];
-				
-				endpoint = nw_endpoint_create_address( &sip->sa );
-				require( endpoint, exit );
-				
-				nw_resolver_config_add_server_address( secureDNSConfig, endpoint );
-				nw_forget( &endpoint );
-			}
-			nw_resolver_config_set_interface_name( secureDNSConfig, "lo0" );
-			ok = nw_resolver_config_publish( secureDNSConfig );
-			require_action( ok, exit, err = kUnknownErr );
-			
-			if( domains )
-			{
-				uuid_t		resolverConfigID;
-				
-				uuid_clear( resolverConfigID );
-				nw_resolver_config_get_identifier( secureDNSConfig, resolverConfigID );
-				check( !inCmd->domainPolicy );
-				inCmd->domainPolicy = mdns_system_add_net_agent_match_domains( resolverConfigID, domains );
-			}
-			inCmd->secureDNSConfig = secureDNSConfig;
-			secureDNSConfig = NULL;
-			break;
-		}
-		case kDNSProtocol_Do53:
-		{
-			configurator = mdns_dns_configurator_create_with_cfstring_id( kDNSServerServiceID, &err );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_add_domain( configurator, primaryDomainStr, 0 );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_add_domain( configurator, dnssecDomainStr, 0 );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_add_domain( configurator, kDNSServerReverseIPv4DomainStr, 0 );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_add_domain( configurator, kDNSServerReverseIPv6DomainStr, 0 );
-			require_noerr( err, exit );
-			
-			for( i = 0; i < inCmd->addrCount; ++i )
-			{
-				const sockaddr_ip * const		sip = &inCmd->addrArray[ i ];
-				char							addrStr[ kSockAddrStringMaxSize ];
-				
-				err = SockAddrToString( &sip->sa, kSockAddrStringFlagsNoPort, addrStr );
-				require_noerr( err, exit );
-				
-				err = mdns_dns_configurator_add_server_address_string( configurator, addrStr );
-				require_noerr( err, exit );
-			}
-			err = mdns_dns_configurator_set_port( configurator, inCmd->portActual );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_set_interface( configurator, "lo0" );
-			require_noerr( err, exit );
-			
-			err = mdns_dns_configurator_register( configurator, CFSTR( kDNSSDUtilIdentifier ) );
-			require_noerr( err, exit );
-			
-			inCmd->addedResolver = true;
-			break;
-		}
-		default:
-			err = kInternalErr;
-			goto exit;
-	}
-	
-exit:
-	mdns_forget( &configurator );
-	nw_forget( &secureDNSConfig );
-	nw_forget( &endpoint );
-	CFForget( &domains );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerCmdUndoSystemSettings( DNSServerCmd * const inCmd )
-{
-	OSStatus		err;
-	
-	if( inCmd->secureDNSConfig )
-	{
-		nw_resolver_config_unpublish( inCmd->secureDNSConfig );
-		nw_forget( &inCmd->secureDNSConfig );
-	}
-	if( inCmd->domainPolicy )
-	{
-		mdns_system_remove_network_policy( inCmd->domainPolicy );
-		inCmd->domainPolicy = NULL;
-	}
-	if( inCmd->addedResolver )
-	{
-		err = mdns_dns_configurator_deregister_configuration( kDNSServerServiceID, CFSTR( kDNSSDUtilIdentifier ) );
-		require_noerr( err, exit );
-		
-		inCmd->addedResolver = false;
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static SecIdentityRef	_DNSServerCmdCreateSecIdentity( OSStatus * const outError )
-{
-	SecIdentityRef		identity	= NULL;
-	CFArrayRef			certSubject	= NULL;
-	CFDictionaryRef		csrParams	= NULL;
-	
-	OSStatus err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &certSubject,
-		"["
-			"[[%O%O]]"	// kSecOidCommonName
-			"[[%O%O]]"	// kSecOidOrganizationalUnit
-			"[[%O%O]]"	// kSecOidOrganization
-		"]",
-		kSecOidCommonName,			CFSTR( kDNSServerHostname ),
-		kSecOidOrganizationalUnit,	CFSTR( "Networking" ),
-		kSecOidOrganization,		CFSTR( "Apple Inc." ) );
-	require_noerr( err, exit );
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &csrParams,
-		"{"
-			"%kO="			// kSecSubjectAltName
-			"{"
-				"%kO=%O"	// kSecSubjectAltNameDNSName
-			"}"
-			"%kO=%lli"		// kSecCertificateLifetime
-		"}",
-		kSecSubjectAltName,
-		kSecSubjectAltNameDNSName,	CFSTR( kDNSServerHostname ),
-		kSecCertificateLifetime,	(int64_t)( 24 * kSecondsPerHour ) );
-	require_noerr( err, exit );
-	
-	identity = mdns_security_create_self_signed_certificate( certSubject, csrParams, kSecAttrKeyTypeECSECPrimeRandom, 256,
-		&err );
-	require_noerr( err, exit );
-	
-exit:
-	CFForget( &certSubject );
-	CFForget( &csrParams );
-	if( outError ) *outError = err;
-	return( identity );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerCmdSetUpCertificate( const SecIdentityRef inIdentity )
-{
-	SecCertificateRef		cert			= NULL;
-	SecPolicyRef			policySSL		= NULL;
-	CFDictionaryRef			trustSettings	= NULL;
-	
-	OSStatus err = SecIdentityCopyCertificate( inIdentity, &cert );
-	require_noerr( err, exit );
-	
-	err = KeychainAddFormatted( NULL,
-		"{"
-			"%kO=%O"	// kSecClass
-			"%kO=%O"	// kSecValueRef
-		"}",
-		kSecClass,		kSecClassCertificate,
-		kSecValueRef,	cert );
-	require_noerr( err, exit );
-	
-	policySSL = SecPolicyCreateSSL( true, NULL );
-	require_action( policySSL, exit, err = kNoResourcesErr );
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &trustSettings,
-		"{"
-			"%kO=%O"	// kSecTrustSettingsPolicy
-			"%kO=%lli"	// kSecTrustSettingsResult
-		"}",
-		kSecTrustSettingsPolicy, policySSL,
-		kSecTrustSettingsResult, (int64_t) kSecTrustSettingsResultTrustRoot );
-	require_noerr( err, exit );
-	
-	err = mdns_security_set_per_user_certificate_trust_settings( cert, trustSettings );
-	require_noerr( err, exit );
-	
-exit:
-	CFForget( &cert );
-	CFForget( &policySSL );
-	CFForget( &trustSettings );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerCmdCleanUpCertificates( void )
-{
-	OSStatus					err;
-	CFMutableDictionaryRef		certQuery = NULL;
-	CFTypeRef					certResults = NULL;
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &certQuery,
-		"{"
-			"%kO=%O"	// kSecClass
-			"%kO=%O"	// kSecAttrLabel
-			"%kO=%O"	// kSecMatchLimit
-			"%kO=%O"	// kSecReturnAttributes
-			"%kO=%O"	// kSecReturnRef
-		"}",
-		kSecClass,				kSecClassCertificate,
-		kSecAttrLabel,			CFSTR( kDNSServerHostname ),
-		kSecMatchLimit,			kSecMatchLimitAll,
-		kSecReturnAttributes,	kCFBooleanTrue,
-		kSecReturnRef,			kCFBooleanTrue );
-	require_noerr( err, exit );
-	
-	err = SecItemCopyMatching( certQuery, &certResults );
-	if( err == errSecItemNotFound )
-	{
-		err = kNoErr;
-		goto exit;
-	}
-	require_noerr( err, exit );
-	
-	if( certResults )
-	{
-		const CFArrayApplierBlock applierBlock =
-		^( const void * const inValue )
-		{
-			const CFDictionaryRef item = CFGetCFDictionary( inValue, NULL );
-			require_return( item );
-			
-			const SecCertificateRef itemCert = (SecCertificateRef) CFDictionaryGetValue( item, kSecValueRef );
-			require_return( itemCert );
-			
-			OSStatus localErr = mdns_security_remove_per_user_certificate_trust_settings( itemCert );
-			require_noerr_fatal( localErr,
-				"mdns_security_remove_per_user_certificate_trust_settings() failed: %#m", localErr );
-		};
-		const CFArrayRef certResultsArray = CFGetCFArray( certResults, NULL );
-		if( certResultsArray )
-		{
-			CFArrayApplyBlock( certResultsArray, CFRangeMake( 0, CFArrayGetCount( certResultsArray ) ), applierBlock );
-		}
-		else
-		{
-			applierBlock( certResults );
-		}
-		err = KeychainDeleteFormatted(
-			"{"
-				"%kO=%O"	// kSecClass
-				"%kO=%O"	// kSecAttrLabel
-			"}",
-			kSecClass,		kSecClassCertificate,
-			kSecAttrLabel,	CFSTR( kDNSServerHostname ) );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	CFForget( &certQuery );
-	CFForget( &certResults );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static nw_listener_t
-	_DNSServerCmdCreateTLSListener(
-		const sec_identity_t	inIdentity,
-		const uint16_t			inPort,
-		const Boolean			inUseHTTPS,
-		OSStatus * const		outError )
-{
-	OSStatus					err;
-	nw_parameters_t				params		= NULL;
-	nw_protocol_options_t		options		= NULL;
-	nw_protocol_stack_t			stack		= NULL;
-	nw_interface_t				interface	= NULL;
-	nw_listener_t				listener	= NULL;
-	__block bool				tlsWasConfigured;
-	char						portStr[ 16 ];
-	
-	tlsWasConfigured = false;
-	const nw_parameters_configure_protocol_block_t configureTLS =
-	^( const nw_protocol_options_t inOptions )
-	{
-		sec_protocol_options_t		tlsOptions;
-		
-		tlsOptions = nw_tls_copy_sec_protocol_options( inOptions );
-		require_return( tlsOptions );
-		
-		sec_protocol_options_set_local_identity( tlsOptions, inIdentity );
-		sec_protocol_options_append_tls_ciphersuite_group( tlsOptions, tls_ciphersuite_group_default );
-		sec_release( tlsOptions );
-		tlsWasConfigured = true;
-	};
-	params = nw_parameters_create_secure_tcp( configureTLS, NW_PARAMETERS_DEFAULT_CONFIGURATION );
-	require_action( params, exit, err = kNoResourcesErr );
-	require_action( tlsWasConfigured, exit, err = kSecurityErr );
-	
-	if( inUseHTTPS )
-	{
-		nw_parameters_set_attach_protocol_listener( params, true );
-		options = nw_http_create_options();
-		require_action( options, exit, err = kNoResourcesErr );
-		
-		nw_http_options_add_version( options, nw_http_version_2 );
-		stack = nw_parameters_copy_default_protocol_stack( params );
-		require_action( stack, exit, err = kNoResourcesErr );
-		
-		nw_protocol_stack_prepend_application_protocol( stack, options );
-	}
-	interface = nw_interface_create_with_name( "lo0" );
-	require_action( interface, exit, err = kNoResourcesErr );
-	
-	nw_parameters_require_interface( params, interface );
-	nw_parameters_set_server_mode( params, true );
-	nw_parameters_set_reuse_local_address( params, true );
-	SNPrintF( portStr, sizeof( portStr ), "%u", inPort );
-	listener = nw_listener_create_with_port( portStr, params );
-	require_action( listener, exit, err = kNoResourcesErr );
-	
-	err = kNoErr;
-	
-exit:
-	nw_forget( &params );
-	nw_forget( &options );
-	nw_forget( &stack );
-	nw_forget( &interface );
-	if( outError ) *outError = err;
-	return( listener );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerCmdHandleNewTLSConnection( DNSServerCmd * const inCmd, const nw_connection_t inConnection )
-{
-	OSStatus					err;
-	nw_connection_t				clientConnection;
-	nw_parameters_t				params;
-	nw_endpoint_t				localEndpoint	= NULL;
-	const struct sockaddr *		localAddr;
-	sockaddr_ip					serverAddr;
-	mdns_dns_relay_t			relay			= NULL;
-	
-	clientConnection = inConnection;
-	params = nw_connection_copy_parameters( clientConnection );
-	require_action( params, exit, err = kNoResourcesErr );
-	
-	localEndpoint = nw_parameters_copy_local_endpoint( params );
-	require_action( localEndpoint, exit, err = kNoResourcesErr );
-	
-	localAddr = nw_endpoint_get_address( localEndpoint );
-	require_action( localAddr, exit, err = kUnexpectedErr );
-	
-	memset( &serverAddr, 0, sizeof( serverAddr ) );
-	switch( localAddr->sa_family )
-	{
-		case AF_INET:
-		{
-			const struct sockaddr_in * const		sin = (const struct sockaddr_in *) localAddr;
-			
-			_SockAddrInitIPv4( &serverAddr.v4, ntohl( sin->sin_addr.s_addr ), inCmd->portActual );
-			break;
-		}
-		case AF_INET6:
-		{
-			const struct sockaddr_in6 * const		sin6 = (const struct sockaddr_in6 *) localAddr;
-			
-			_SockAddrInitIPv6( &serverAddr.v6, sin6->sin6_addr.s6_addr, sin6->sin6_scope_id, inCmd->portActual );
-			break;
-		}
-		default:
-			err = kAddressErr;
-			goto exit;
-	}
-	if( inCmd->protocol == kDNSProtocol_DoH )
-	{
-		mdns_doh_relay_t		relayDoH;
-		
-		relayDoH = mdns_doh_relay_create( NULL );
-		require_action( relayDoH, exit, err = kNoResourcesErr );
-		
-		relay = mdns_dns_relay_upcast( relayDoH );
-		err = mdns_doh_relay_set_request_uri_path( relayDoH, kDNSServerDoHURLPath );
-		require_noerr( err, exit );
-		
-		err = mdns_doh_relay_set_host_and_port( relayDoH, kDNSServerHostname, inCmd->portRequested );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		mdns_dot_relay_t		relayDoT;
-		
-		relayDoT = mdns_dot_relay_create( NULL );
-		require_action( relayDoT, exit, err = kNoResourcesErr );
-		
-		relay = mdns_dns_relay_upcast( relayDoT );
-	}
-	mdns_dns_relay_set_client_connection( relay, clientConnection );
-	clientConnection = NULL;
-	mdns_dns_relay_set_server_address( relay, &serverAddr );
-	mdns_dns_relay_activate( relay );
-	err = kNoErr;
-	
-exit:
-	nw_forget( &params );
-	nw_forget( &localEndpoint );
-	mdns_forget( &relay );
-	if( clientConnection ) nw_connection_cancel( clientConnection );
-	return( err );
-}
-
-//===========================================================================================================================
-
-typedef struct DNSServerConnectionPrivate *		DNSServerConnectionRef;
-
-typedef struct DNSServerDelayedResponse		DNSServerDelayedResponse;
-struct DNSServerDelayedResponse
-{
-	DNSServerDelayedResponse *		next;		// Next delayed response in list.
-	sockaddr_ip						client;		// Destination address.
-	uint64_t						dueTicks;	// Time, in ticks, when send is due.
-	uint8_t *						msgPtr;		// Response message pointer.
-	size_t							msgLen;		// Response message length.
-	size_t							index;		// Address index.
-	SocketRef						sock;		// Socket to use for send.
-};
-
-struct DNSServerPrivate
-{
-	CFRuntimeBase					base;				// CF object base.
-	uint8_t *						domain;				// Parent domain of server's resource records. (malloc'd)
-	dispatch_queue_t				queue;				// Queue for DNS server's events.
-	sockaddr_ip *					addrArray;			// Array of addresses to listen on.
-	size_t							addrCount;			// Number of addresses to listen on.
-	dispatch_source_t *				readSourceArrayUDP;	// Array of read sources for UDP sockets.
-	dispatch_source_t *				readSourceArrayTCP;	// Array of read sources for TCP listening sockets.
-	DNSServerConnectionRef			connectionList;		// List of TCP connections.
-	dispatch_source_t				connectionTimer;	// Timer for idle connections.
-	DNSServerStartHandler_f			startHandler;		// User's activation handler.
-	DNSServerStopHandler_f			stopHandler;		// User's invalidation handler.
-    void *							userContext;		// User's handler context.
-	DNSServerDelayedResponse *		responseList;		// List of delayed UDP responses.
-	dispatch_source_t				responseTimer;		// Timer for when to send next delayed response.
-	int *							ignoredQTypes;		// Array of QTYPEs to ignore.
-	size_t							ignoredQTypeCount;	// Number of QTYPEs to ignore.
-	unsigned int					responseDelayMs;	// Response delay in milliseconds.
-	uint32_t						defaultTTL;			// Default TTL for resource records.
-	uint32_t						serial;				// Serial number for SOA record.
-	OSStatus						stopErr;			// The error, if any, that caused the server to stop.
-	uint16_t						portRequested;		// The port that was requested by the user.
-	Boolean							started;			// True if the server was started.
-	Boolean							stopped;			// True if the server was stopped.
-	Boolean							badUDPMode;			// True if the server runs in Bad UDP mode.
-	Boolean							suspended;			// True if the server is suspended (intentionally not responding).
-};
-
-static void	_DNSServerUDPReadHandler( void *inContext );
-static OSStatus
-	_DNSServerScheduleDelayedResponse(
-		DNSServerRef			inServer,
-		SocketRef				inSock,
-		const struct sockaddr *	inDestAddr,
-		uint8_t *				inMsgPtr,
-		size_t					inMsgLen,
-		size_t					inIndex );
-static void	_DNSServerDelayedResponseFree( DNSServerDelayedResponse *inResponse );
-static void	_DNSServerDelayedResponseListFree( DNSServerDelayedResponse *inList );
-static void	_DNSServerTCPAcceptHandler( void *inContext );
-static void	_DNSServerConnectionTimerHandler( void *inContext );
-static void	_DNSServerResetConnectionTimerMs( DNSServerRef me, uint64_t inTimeoutMs );
-static OSStatus
-	_DNSServerAnswerQuery(
-		DNSServerRef	inServer,
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		size_t			inIndex,
-		Boolean			inForTCP,
-		uint8_t **		outResponsePtr,
-		size_t *		outResponseLen );
-
-#define _DNSServerAnswerQueryForUDP( SERVER, QUERY_PTR, QUERY_LEN, INDEX, RESPONSE_PTR, RESPONSE_LEN ) \
-	_DNSServerAnswerQuery( SERVER, QUERY_PTR, QUERY_LEN, INDEX, false, RESPONSE_PTR, RESPONSE_LEN )
-
-#define _DNSServerAnswerQueryForTCP( SERVER, QUERY_PTR, QUERY_LEN, INDEX, RESPONSE_PTR, RESPONSE_LEN ) \
-	_DNSServerAnswerQuery( SERVER, QUERY_PTR, QUERY_LEN, INDEX, true, RESPONSE_PTR, RESPONSE_LEN )
-
-CF_CLASS_DEFINE( DNSServer );
-
-struct DNSServerConnectionPrivate
-{
-	CFRuntimeBase				base;				// CF object base.
-	DNSServerConnectionRef		next;				// Next connection in list.
-	DNSServerRef				server;				// Back pointer to server object.
-	sockaddr_ip					local;				// TCP connection's local address.
-	sockaddr_ip					remote;				// TCP connection's remote address.
-	size_t						index;				// Sever address index.
-	uint64_t					expirationTicks;	// Expiration time in ticks. Renewed upon receiving a complete query.
-	dispatch_source_t			readSource;			// Dispatch read source for TCP connection.
-	dispatch_source_t			writeSource;		// Dispatch write source for TCP connection.
-	size_t						offset;				// Offset into receive buffer.
-	void *						msgPtr;				// Pointer to dynamically allocated message buffer.
-	size_t						msgLen;				// Length of message buffer.
-	iovec_t						iov[ 2 ];			// IO vector for writing response message.
-	iovec_t *					iovPtr;				// Vector pointer for SocketWriteData().
-	int							iovCount;			// Vector count for SocketWriteData().
-	Boolean						readSuspended;		// True if the read source is currently suspended.
-	Boolean						writeSuspended;		// True if the write source is currently suspended.
-	Boolean						haveLen;			// True if currently receiving message instead of message length.
-	uint8_t						lenBuf[ 2 ];		// Buffer for two-octet message length field.
-};
-
-static CFTypeID	DNSServerConnectionGetTypeID( void );
-static OSStatus
-	_DNSServerConnectionCreate(
-		DNSServerRef				inServer,
-		const struct sockaddr *		inLocal,
-		const struct sockaddr *		inRemote,
-		size_t						inIndex,
-		DNSServerConnectionRef *	outCnx );
-static OSStatus	_DNSServerConnectionStart( DNSServerConnectionRef inCnx, SocketRef inSock );
-static void		_DNSServerConnectionStop( DNSServerConnectionRef inCnx, Boolean inRemoveFromList );
-static void		_DNSServerConnectionReadHandler( void *inContext );
-static void		_DNSServerConnectionWriteHandler( void *inContext );
-static void		_DNSServerConnectionRenewExpiration( DNSServerConnectionRef inCnx );
-
-CF_CLASS_DEFINE( DNSServerConnection );
-
-static OSStatus
-	_DNSServerCreate(
-		dispatch_queue_t		inQueue,
-		DNSServerStartHandler_f	inStartHandler,
-		DNSServerStopHandler_f	inStopHandler,
-		void *					inUserContext,
-		unsigned int			inResponseDelayMs,
-		uint32_t				inDefaultTTL,
-		const sockaddr_ip *		inAddrArray,
-		size_t					inAddrCount,
-		const char *			inDomain,
-		Boolean					inBadUDPMode,
-		DNSServerRef *			outServer )
-{
-	OSStatus			err;
-	DNSServerRef		obj = NULL;
-	
-	require_action_quiet( inDefaultTTL <= INT32_MAX, exit, err = kRangeErr );
-	
-	CF_OBJECT_CREATE( DNSServer, obj, err, exit );
-	
-	ReplaceDispatchQueue( &obj->queue, inQueue );
-	obj->startHandler		= inStartHandler;
-	obj->stopHandler		= inStopHandler;
-	obj->userContext		= inUserContext;
-	obj->responseDelayMs	= inResponseDelayMs;
-	obj->defaultTTL			= inDefaultTTL;
-	obj->badUDPMode			= inBadUDPMode;
-	obj->addrCount			= inAddrCount;
-	
-	obj->addrArray = (sockaddr_ip *) _memdup( inAddrArray, obj->addrCount * sizeof( *obj->addrArray ) );
-	require_action( obj->addrArray, exit, err = kNoMemoryErr );
-	
-	obj->readSourceArrayUDP = (dispatch_source_t *) calloc( obj->addrCount, sizeof( *obj->readSourceArrayUDP ) );
-	require_action( obj->readSourceArrayUDP, exit, err = kNoMemoryErr );
-	
-	obj->readSourceArrayTCP = (dispatch_source_t *) calloc( obj->addrCount, sizeof( *obj->readSourceArrayTCP ) );
-	require_action( obj->readSourceArrayTCP, exit, err = kNoMemoryErr );
-	
-	if( inDomain )
-	{
-		err = StringToDomainName( inDomain, &obj->domain, NULL );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		err = DomainNameDup( kDNSServerDomain_Default, &obj->domain, NULL );
-		require_noerr_quiet( err, exit );
-	}
-	*outServer = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	CFReleaseNullSafe( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerFinalize( CFTypeRef inObj )
-{
-	DNSServerRef const		me = (DNSServerRef) inObj;
-	size_t					i;
-	
-	check( !me->responseTimer );
-	check( !me->connectionList );
-	check( !me->connectionTimer );
-	ForgetMem( &me->addrArray );
-	if( me->readSourceArrayUDP )
-	{
-		for( i = 0; i < me->addrCount; ++i ) check( !me->readSourceArrayUDP[ i ] );
-		ForgetMem( &me->readSourceArrayUDP );
-	}
-	if( me->readSourceArrayTCP )
-	{
-		for( i = 0; i < me->addrCount; ++i ) check( !me->readSourceArrayTCP[ i ] );
-		ForgetMem( &me->readSourceArrayTCP );
-	}
-	ForgetMem( &me->domain );
-	dispatch_forget( &me->queue );
-	ForgetMem( &me->ignoredQTypes );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerSetIgnoredQType( DNSServerRef me, int inQType )
-{
-	size_t		newCount;
-	int *		mem;
-	
-	newCount = me->ignoredQTypeCount + 1;
-	require_return_value( newCount <= SIZE_MAX / sizeof( int ), kSizeErr );
-	
-	mem = realloc( me->ignoredQTypes, newCount * sizeof( int ) );
-	require_return_value( mem, kNoMemoryErr );
-	
-	me->ignoredQTypes = mem;
-	me->ignoredQTypes[ me->ignoredQTypeCount++ ] = inQType;
-	return( kNoErr );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerSetPort( const DNSServerRef me, const uint16_t inPort )
-{
-	me->portRequested = inPort;
-}
-
-//===========================================================================================================================
-
-static void		_DNSServerStartOnQueue( void *inContext );
-static void		_DNSServerStartInternal( DNSServerRef inServer );
-static OSStatus	_DNSServerSetUpSockets( DNSServerRef inServer, uint16_t *outActualPort );
-static void		_DNSServerStopInternal( void *inContext, OSStatus inError );
-static SocketContext *
-	_DNSServerSocketContextCreate(
-		SocketRef		inSock,
-		DNSServerRef	inServer,
-		size_t			inIndex,
-		OSStatus *		outError );
-
-static void	_DNSServerStart( DNSServerRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _DNSServerStartOnQueue );
-}
-
-static void	_DNSServerStartOnQueue( void *inContext )
-{
-	const DNSServerRef		me = (DNSServerRef) inContext;
-	
-	_DNSServerStartInternal( me );
-	CFRelease( me );
-}
-
-static void _DNSServerStartInternal( DNSServerRef me )
-{
-	OSStatus				err;
-	struct timeval			now;
-	SocketRef				sock	= kInvalidSocketRef;
-	SocketContext *			sockCtx	= NULL;
-	int						year, month, day;
-	uint16_t				actualPort;
-	
-	require_action_quiet( !me->started && !me->stopped, exit, err = kNoErr );
-	me->started = true;
-	CFRetain( me );
-	
-	err = _DNSServerSetUpSockets( me, &actualPort );
-	require_noerr( err, exit );
-	
-	if( me->startHandler ) me->startHandler( actualPort, me->userContext );
-	
-	// Create the serial number for the server's SOA record in the YYYMMDDnn convention recommended by
-	// <https://tools.ietf.org/html/rfc1912#section-2.2> using the current time.
-	
-	gettimeofday( &now, NULL );
-	SecondsToYMD_HMS( ( INT64_C_safe( kDaysToUnixEpoch ) * kSecondsPerDay ) + now.tv_sec, &year, &month, &day,
-		NULL, NULL, NULL );
-	me->serial = (uint32_t)( ( year * 1000000 ) + ( month * 10000 ) + ( day * 100 ) + 1 );
-	err = kNoErr;
-	
-exit:
-	ForgetSocket( &sock );
-	if( sockCtx ) SocketContextRelease( sockCtx );
-	if( err ) _DNSServerStopInternal( me, err );
-}
-
-typedef struct
-{
-	SocketRef		sockUDP;
-	SocketRef		sockTCP;
-	
-}	_DNSServerSocketPair;
-
-#define kDNSServerMaxBindTryCount	10
-
-static OSStatus	_DNSServerSetUpSockets( const DNSServerRef me,  uint16_t * const outActualPort )
-{
-	OSStatus					err;
-	SocketContext *				sockCtx			= NULL;
-	_DNSServerSocketPair *		sockPairs		= NULL;
-	_DNSServerSocketPair *		sockPairsHeap	= NULL;
-	_DNSServerSocketPair		sockPairsStack[ 16 ];
-	size_t						i;
-	const size_t				addrCount		= me->addrCount; // Don't use me->addrCount to avoid false analyzer warning.
-	int							portActual		= 0;
-	int							tryCount, tryCountMax;
-	
-	require_action_quiet( addrCount > 0, exit, err = kNoErr );
-	
-	if( me->addrCount > countof( sockPairsStack ) )
-	{
-		sockPairsHeap = (_DNSServerSocketPair *) calloc( me->addrCount, sizeof( *sockPairsHeap ) );
-		require_action( sockPairsHeap, exit, err = kNoMemoryErr );
-		sockPairs = sockPairsHeap;
-	}
-	else
-	{
-		sockPairs = sockPairsStack;
-	}
-	for( i = 0; i < addrCount; ++i )
-	{
-		sockPairs[ i ].sockUDP = kInvalidSocketRef;
-		sockPairs[ i ].sockTCP = kInvalidSocketRef;
-	}
-	// Create server sockets.
-	
-	err = kNoErr;
-	tryCountMax = ( me->portRequested == 0 ) ? kDNSServerMaxBindTryCount : 1;
-	for( tryCount = 0; tryCount < tryCountMax; ++tryCount )
-	{
-		int		portDefault = 0;
-		
-		portActual = 0;
-		for( i = 0; i < addrCount; ++i )
-		{
-			sockaddr_ip * const					sip		= &me->addrArray[ i ];
-			_DNSServerSocketPair * const		pair	= &sockPairs[ i ];
-			const void *						address;
-			SocketRef							sock;
-			int									port;
-			sockaddr_ip							tmpSA;
-			
-			switch( sip->sa.sa_family )
-			{
-				case AF_INET:	address = &sip->v4.sin_addr.s_addr;  break;
-				case AF_INET6:	address = sip->v6.sin6_addr.s6_addr; break;
-				default:
-					ds_ulog( kLogLevelError, "Unhandled address family %d", sip->sa.sa_family );
-					err = kTypeErr;
-					goto exit;
-			}
-			// Create UDP socket.
-			// If the user's requested port 0, then the user wants any available ephemeral port. The actual port number
-			// that was used will be stored in portActual and used for the remaining addresses that don't specify a
-			// non-zero port.
-			
-			port = ( me->portRequested == 0 ) ? portDefault : me->portRequested;
-			err = _ServerSocketOpenEx2( sip->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP, address, port, &portActual,
-				kSocketBufferSize_DontSet, true, &sock );
-			if( err == EADDRINUSE )
-			{
-				SockAddrCopy( sip, &tmpSA );
-				SockAddrSetPort( &tmpSA, port );
-				ds_ulog( kLogLevelError, "IP address %##a is already in use for UDP\n", &tmpSA );
-				break;
-			}
-			require_noerr( err, exit );
-			check( ( me->portRequested == 0 ) || ( portActual == me->portRequested ) );
-			
-			ForgetSocket( &pair->sockUDP );
-			pair->sockUDP = sock;
-			sock = kInvalidSocketRef;
-			if( portDefault == 0 ) portDefault = portActual;
-			
-			// Create TCP socket.
-			
-			err = _ServerSocketOpenEx2( sip->sa.sa_family, SOCK_STREAM, IPPROTO_TCP, address, portActual, NULL,
-				kSocketBufferSize_DontSet, false, &sock );
-			if( err == EADDRINUSE )
-			{
-				SockAddrCopy( sip, &tmpSA );
-				SockAddrSetPort( &tmpSA, portActual );
-				ds_ulog( kLogLevelError, "IP address %##a is already in use for TCP\n", &tmpSA );
-				break;
-			}
-			require_noerr( err, exit );
-			
-			ForgetSocket( &pair->sockTCP );
-			pair->sockTCP = sock;
-			sock = kInvalidSocketRef;
-			
-			SockAddrSetPort( sip, portActual );
-		}
-		if( !err ) break;
-	}
-	require_noerr( err, exit );
-	
-	// Create read sources for server sockets.
-	
-	for( i = 0; i < addrCount; ++i )
-	{
-		const sockaddr_ip * const			sip					= &me->addrArray[ i ];
-		dispatch_source_t * const			readSourceUDPPtr	= &me->readSourceArrayUDP[ i ];
-		dispatch_source_t * const			readSourceTCPPtr	= &me->readSourceArrayTCP[ i ];
-		_DNSServerSocketPair * const		pair				= &sockPairs[ i ];
-		
-		// Create read source for UDP socket.
-		
-		check( IsValidSocket( pair->sockUDP ) );
-		sockCtx = _DNSServerSocketContextCreate( pair->sockUDP, me, i, &err );
-		require_noerr( err, exit );
-		pair->sockUDP = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, me->queue, _DNSServerUDPReadHandler, SocketContextCancelHandler,
-			sockCtx, readSourceUDPPtr );
-		require_noerr( err, exit );
-		dispatch_resume( *readSourceUDPPtr );
-		sockCtx = NULL;
-		
-		// Create read source for TCP socket.
-		
-		check( IsValidSocket( pair->sockTCP ) );
-		sockCtx = _DNSServerSocketContextCreate( pair->sockTCP, me, i, &err );
-		require_noerr( err, exit );
-		pair->sockTCP = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, me->queue, _DNSServerTCPAcceptHandler, SocketContextCancelHandler,
-			sockCtx, readSourceTCPPtr );
-		require_noerr( err, exit );
-		dispatch_resume( *readSourceTCPPtr );
-		sockCtx = NULL;
-		
-		ds_ulog( kLogLevelInfo, "Server is listening on %##a\n", sip );
-	}
-	
-exit:
-	if( sockPairs )
-	{
-		for( i = 0; i < addrCount; ++i )
-		{
-			ForgetSocket( &sockPairs[ i ].sockUDP );
-			ForgetSocket( &sockPairs[ i ].sockTCP );
-		}
-	}
-	FreeNullSafe( sockPairsHeap );
-	if( sockCtx ) SocketContextRelease( sockCtx );
-	if( outActualPort ) *outActualPort = (uint16_t) portActual;
-	return( err );
-}
-
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServerRef	server;
-	size_t			index;
-	
-}	DNSServerContext;
-
-static void	_DNSServerContextFree( DNSServerContext *inCtx );
-static void	_DNSServerSocketContextFinalizer( void *inCtx );
-
-static SocketContext *
-	_DNSServerSocketContextCreate(
-		SocketRef		inSock,
-		DNSServerRef	inServer,
-		size_t			inIndex,
-		OSStatus *		outError )
-{
-	OSStatus				err;
-	SocketContext *			sockCtx = NULL;
-	DNSServerContext *		ctx;
-	
-	ctx = (DNSServerContext *) calloc( 1, sizeof( *ctx ) );
-	require_action( ctx, exit, err = kNoMemoryErr );
-	
-	ctx->index	= inIndex;
-	ctx->server	= inServer;
-	CFRetain( ctx->server );
-	
-	sockCtx = SocketContextCreateEx( inSock, ctx, _DNSServerSocketContextFinalizer, &err );
-	require_noerr( err, exit );
-	ctx	= NULL;
-	
-exit:
-	if( outError ) *outError = err;
-	if( ctx ) _DNSServerContextFree( ctx );
-	return( sockCtx );
-}
-
-static void	_DNSServerSocketContextFinalizer( void *inCtx )
-{
-	_DNSServerContextFree( (DNSServerContext *) inCtx );
-}
-
-static void	_DNSServerContextFree( DNSServerContext *inCtx )
-{
-	ForgetCF( &inCtx->server );
-	free( inCtx );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerStopOnQueue( void *inContext );
-static void	_DNSServerStop2( void *inContext );
-
-static void	_DNSServerStop( DNSServerRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _DNSServerStopOnQueue );
-}
-
-static void	_DNSServerStopOnQueue( void *inContext )
-{
-	DNSServerRef const		me = (DNSServerRef) inContext;
-	
-	_DNSServerStopInternal( me, kNoErr );
-	CFRelease( me );
-}
-
-static void	_DNSServerStopInternal( void *inContext, OSStatus inError )
-{
-	DNSServerRef const			me = (DNSServerRef) inContext;
-	DNSServerConnectionRef		cnx;
-	size_t						i;
-	
-	require_quiet( !me->stopped, exit );
-	me->stopped = true;
-	
-	me->stopErr = inError;
-	if( me->responseList )
-	{
-		_DNSServerDelayedResponseListFree( me->responseList );
-		me->responseList = NULL;
-	}
-	dispatch_source_forget( &me->responseTimer );
-	for( i = 0; i < me->addrCount; ++i )
-	{
-		dispatch_source_forget( &me->readSourceArrayUDP[ i ] );
-		dispatch_source_forget( &me->readSourceArrayTCP[ i ] );
-	}
-	while( ( cnx = me->connectionList ) != NULL )
-	{
-		me->connectionList = cnx->next;
-		_DNSServerConnectionStop( cnx, false );
-		cnx->next = NULL;
-		CFRelease( cnx );
-	}
-	dispatch_source_forget( &me->connectionTimer );
-	
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _DNSServerStop2 );
-	if( me->started ) CFRelease( me );
-	
-exit:
-	return;
-}
-
-static void	_DNSServerStop2( void *inContext )
-{
-	DNSServerRef const		me = (DNSServerRef) inContext;
-	
-	if( me->stopHandler ) me->stopHandler( me->stopErr, me->userContext );
-	CFRelease( me );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerUDPReadHandler( void *inContext )
-{
-	OSStatus							err;
-	SocketContext * const				sockCtx	= (SocketContext *) inContext;
-	const DNSServerContext * const		ctx		= (DNSServerContext *) sockCtx->userContext;
-	const DNSServerRef					me		= ctx->server;
-	ssize_t								n;
-	sockaddr_ip							client;
-	socklen_t							clientLen;
-	uint8_t *							respPtr	= NULL;	// malloc'd
-	size_t								respLen;
-	uint8_t								msg[ 512 ];
-	
-	// Receive message.
-	
-	clientLen = (socklen_t) sizeof( client );
-	n = recvfrom( sockCtx->sock, (char *) msg, sizeof( msg ), 0, &client.sa, &clientLen );
-	err = map_socket_value_errno( sockCtx->sock, n >= 0, n );
-	require_noerr( err, exit );
-	
-	if( n < kDNSHeaderLength )
-	{
-		ds_ulog( kLogLevelInfo, "UDP: Received %zd bytes from %##a to %##a: Message is too small (< %d bytes)\n",
-			n, &client, &me->addrArray[ ctx->index ], kDNSHeaderLength );
-		goto exit;
-	}
-	ds_ulog( kLogLevelInfo, "UDP: Received %zd bytes from %##a to %##a -- %.1{du:dnsmsg}\n",
-		n, &client, &me->addrArray[ ctx->index ], msg, (size_t) n );
-	
-	// Create response.
-	
-	err = _DNSServerAnswerQueryForUDP( me, msg, (size_t) n, ctx->index + 1, &respPtr, &respLen );
-	if( err == kSkipErr ) ds_ulog( kLogLevelInfo, "UDP: Ignoring query\n" );
-	require_noerr_quiet( err, exit );
-	
-	if( me->responseDelayMs > 0 )	// Defer response.
-	{
-		err = _DNSServerScheduleDelayedResponse( me, sockCtx->sock, &client.sa, respPtr, respLen, ctx->index );
-		require_noerr( err, exit );
-		respPtr = NULL;
-	}
-	else							// Send response.
-	{
-		ds_ulog( kLogLevelInfo, "UDP: Sending %zu byte response from %##a to %##a -- %.1{du:dnsmsg}\n",
-			respLen, &me->addrArray[ ctx->index ], &client, respPtr, respLen );
-		
-		n = sendto( sockCtx->sock, (char *) respPtr, respLen, 0, &client.sa, clientLen );
-		err = map_socket_value_errno( sockCtx->sock, n == (ssize_t) respLen, n );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	FreeNullSafe( respPtr );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerSendDelayedResponses( void *inContext );
-
-static OSStatus
-	_DNSServerScheduleDelayedResponse(
-		DNSServerRef			me,
-		SocketRef				inSock,
-		const struct sockaddr *	inDestAddr,
-		uint8_t *				inMsgPtr,
-		size_t					inMsgLen,
-		size_t					inIndex )
-{
-	OSStatus						err;
-	DNSServerDelayedResponse *		resp;
-	DNSServerDelayedResponse *		newResp;
-	DNSServerDelayedResponse **		ptr;
-	uint64_t						dueTicks;
-	
-	dueTicks = UpTicks() + MillisecondsToUpTicks( me->responseDelayMs );
-	newResp = (DNSServerDelayedResponse *) calloc( 1, sizeof( *newResp ) );
-	require_action( newResp, exit, err = kNoMemoryErr );
-	
-	newResp->dueTicks	= dueTicks;
-	newResp->msgPtr		= inMsgPtr;
-	newResp->msgLen		= inMsgLen;
-	newResp->index		= inIndex;
-	newResp->sock		= inSock;
-	SockAddrCopy( inDestAddr, &newResp->client );
-	
-	if( !me->responseList || ( _TicksDiff( dueTicks, me->responseList->dueTicks ) < 0 ) )
-	{
-		dispatch_source_forget( &me->responseTimer );
-		err = DispatchTimerOneShotCreate( dispatch_time_milliseconds( me->responseDelayMs ), 0, me->queue,
-			_DNSServerSendDelayedResponses, me, &me->responseTimer );
-		require_noerr( err, exit );
-		dispatch_resume( me->responseTimer );
-	}
-	for( ptr = &me->responseList; ( resp = *ptr ) != NULL; ptr = &resp->next )
-	{
-		if( _TicksDiff( newResp->dueTicks, resp->dueTicks ) < 0 ) break;
-	}
-	newResp->next = resp;
-	*ptr = newResp;
-	newResp = NULL;
-	err = kNoErr;
-	
-exit:
-	if( newResp ) _DNSServerDelayedResponseFree( newResp );
-	return( err );
-}
-
-static void	_DNSServerSendDelayedResponses( void *inContext )
-{
-	OSStatus						err;
-	const DNSServerRef				me = (DNSServerRef) inContext;
-	DNSServerDelayedResponse *		resp;
-	DNSServerDelayedResponse *		freeList;
-	int64_t							deltaTicks;
-	
-	dispatch_source_forget( &me->responseTimer );
-	
-	deltaTicks = -1;
-	freeList = NULL;
-	while( ( resp = me->responseList ) != NULL )
-	{
-		ssize_t			n;
-		uint64_t		nowTicks = UpTicks();
-		
-		deltaTicks = _TicksDiff( resp->dueTicks, nowTicks );
-		if( deltaTicks > 0 ) break;
-		me->responseList = resp->next;
-		
-		ds_ulog( kLogLevelInfo, "UDP: Sending %zu byte delayed response from %##a to %##a -- %.1{du:dnsmsg}\n",
-			resp->msgLen, &me->addrArray[ resp->index ], &resp->client, resp->msgPtr, resp->msgLen );
-		
-		n = sendto( resp->sock, (char *) resp->msgPtr, resp->msgLen, 0, &resp->client.sa, SockAddrGetSize( &resp->client ) );
-		err = map_socket_value_errno( resp->sock, n == (ssize_t) resp->msgLen, n );
-		check_noerr( err );
-		
-		resp->next = freeList;
-		freeList = resp;
-	}
-	if( deltaTicks > 0 )
-	{
-		uint64_t		deltaNs;
-		
-		deltaNs = UpTicksToNanoseconds( (uint64_t) deltaTicks );
-		if( deltaNs > INT64_MAX ) deltaNs = INT64_MAX;
-		
-		err = DispatchTimerOneShotCreate( dispatch_time( DISPATCH_TIME_NOW, (int64_t) deltaNs ), 0, me->queue,
-			_DNSServerSendDelayedResponses, me, &me->responseTimer );
-		require_noerr( err, exit );
-		dispatch_resume( me->responseTimer );
-	}
-	
-exit:
-	if( freeList ) _DNSServerDelayedResponseListFree( freeList );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerDelayedResponseFree( DNSServerDelayedResponse *inResp )
-{
-	ForgetMem( &inResp->msgPtr );
-	inResp->sock = kInvalidSocketRef;
-	free( inResp );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerDelayedResponseListFree( DNSServerDelayedResponse *inList )
-{
-	DNSServerDelayedResponse *		resp;
-	
-	while( ( resp = inList ) != NULL )
-	{
-		inList = resp->next;
-		_DNSServerDelayedResponseFree( resp );
-	}
-}
-
-//===========================================================================================================================
-
-#define kDNSServerConnectionExpirationTimeSecs		5
-#define kDNSServerConnectionExpirationTimeMs		( kDNSServerConnectionExpirationTimeSecs * kMillisecondsPerSecond )
-
-static void	_DNSServerTCPAcceptHandler( void *inContext )
-{
-	OSStatus							err;
-	SocketContext * const				sockCtx	= (SocketContext *) inContext;
-	const DNSServerContext * const		ctx		= (DNSServerContext *) sockCtx->userContext;
-	const DNSServerRef 					me		= ctx->server;
-	DNSServerConnectionRef				cnx		= NULL;
-	sockaddr_ip							remote, local;
-	socklen_t							len;
-	SocketRef							sock;
-	
-	len = (socklen_t) sizeof( remote );
-	sock = accept( sockCtx->sock, &remote.sa, &len );
-	err = map_socket_creation_errno( sock );
-	require_noerr( err, exit );
-	
-	len = (socklen_t) sizeof( local );
-	err = getsockname( sock, &local.sa, &len );
-	if( unlikely( err ) ) SockAddrCopy( &me->addrArray[ ctx->index ], &local );
-	
-	err = _DNSServerConnectionCreate( me, &local.sa, &remote.sa, ctx->index, &cnx );
-	require_noerr_quiet( err, exit );
-	
-	err = _DNSServerConnectionStart( cnx, sock );
-	require_noerr( err, exit );
-	sock = kInvalidSocketRef;
-	
-	if( !me->connectionList ) _DNSServerResetConnectionTimerMs( me, kDNSServerConnectionExpirationTimeMs );
-	cnx->next = me->connectionList;
-	me->connectionList = cnx;
-	cnx = NULL;
-	
-exit:
-	ForgetSocket( &sock );
-	if( cnx )
-	{
-		_DNSServerConnectionStop( cnx, true );
-		CFRelease( cnx );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionTimerHandler( void *inContext )
-{
-	const DNSServerRef				me			= (DNSServerRef) inContext;
-	DNSServerConnectionRef			cnx;
-	DNSServerConnectionRef *		ptr;
-	uint64_t						nowTicks;
-	int64_t							delta, deltaMin;
-	
-	nowTicks = UpTicks();
-	deltaMin = INT64_MAX;
-	ptr = &me->connectionList;
-	while( ( cnx = *ptr ) != NULL )
-	{
-		delta = _TicksDiff( cnx->expirationTicks, nowTicks );
-		if( delta <= 0 )
-		{
-			ds_ulog( kLogLevelInfo, "Timing out TCP connection: %##a <-> %##a\n", &cnx->local, &cnx->remote );
-			*ptr = cnx->next;
-			cnx->next = NULL;
-			_DNSServerConnectionStop( cnx, false );
-			CFRelease( cnx );
-		}
-		else
-		{
-			if( delta < deltaMin ) deltaMin = delta;
-			ptr = &cnx->next;
-		}
-	}
-	if( me->connectionList )
-	{
-		const uint64_t		timeMs = UpTicksToMilliseconds( (uint64_t) deltaMin );
-		
-		check( timeMs <= kDNSServerConnectionExpirationTimeMs );
-		_DNSServerResetConnectionTimerMs( me, timeMs + 1 );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerResetConnectionTimerMs( DNSServerRef me, uint64_t inTimeoutMs )
-{
-	OSStatus		err;
-	
-	dispatch_source_forget( &me->connectionTimer );
-	if( inTimeoutMs == 0 ) inTimeoutMs = 1;
-	err = DispatchTimerOneShotCreate( dispatch_time_milliseconds( inTimeoutMs ),
-		UINT64_C( 10 ) * kNanosecondsPerMillisecond, me->queue, _DNSServerConnectionTimerHandler, me, &me->connectionTimer );
-	if( likely( !err ) )	dispatch_resume( me->connectionTimer );
-	else					ds_ulog( kLogLevelError, "Failed to create connection timer: %#m\n", err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSServerInitializeResponseMessage(
-		DataBuffer *	inDB,
-		uint16_t		inID,
-		uint16_t		inFlags,
-		const uint8_t *	inQName,
-		uint16_t		inQType,
-		uint16_t		inQClass );
-static OSStatus
-	_DNSServerAnswerQueryDynamically(
-		DNSServerRef	inServer,
-		const uint8_t *	inQName,
-		int				inQType,
-		int				inQClass,
-		size_t          inIndex,
-		size_t			inTruncateLen,
-		Boolean			inDNSSEC,
-		Boolean			inUseBadAddrs,
-		DataBuffer *	inDB );
-
-static OSStatus
-	_DNSServerAnswerQuery(
-		DNSServerRef			me,
-		const uint8_t * const	inMsgPtr,
-		const size_t			inMsgLen,
-		const size_t			inIndex,
-		const Boolean			inForTCP,
-		uint8_t ** const		outResponsePtr,
-		size_t * const			outResponseLen )
-{
-	OSStatus				err;
-	DataBuffer				db;
-	const uint8_t *			qptr;
-	const DNSHeader *		hdr;
-	const uint8_t *			qOptPtr;
-	size_t					qOptLen, truncateLen;
-	unsigned int			qflags, rcode;
-	uint16_t				msgID, qtype, qclass, rflags;
-	uint8_t					qname[ kDomainNameLengthMax ];
-	uint8_t					dbBuf[ 512 ];
-	Boolean					dnssecOK, usePadding, useBadAddrs;
-	
-	DataBuffer_Init( &db, dbBuf, sizeof( dbBuf ), kDNSMaxTCPMessageSize );
-	
-	require_action_quiet( inMsgLen >= kDNSHeaderLength, exit, err = kUnderrunErr );
-	
-	hdr		= (const DNSHeader *) inMsgPtr;
-	qflags	= DNSHeaderGetFlags( hdr );
-	
-	// Minimal checking of the query message's header.
-	
-	require_action_quiet( !( qflags & kDNSHeaderFlag_Response ), exit, err = kRequestErr );
-	require_action_quiet( DNSFlagsGetOpCode( qflags ) == kDNSOpCode_Query, exit, err = kRequestErr );
-	require_action_quiet( DNSHeaderGetQuestionCount( hdr ) == 1, exit, err = kRequestErr );
-	
-	qptr = (const uint8_t *) &hdr[ 1 ];
-	err = DNSMessageExtractQuestion( inMsgPtr, inMsgLen, qptr, qname, &qtype, &qclass, NULL );
-	require_noerr( err, exit );
-	
-	// Check if this query should be ignored because of its QTYPE.
-	
-	if( qclass == kDNSClassType_IN )
-	{
-		size_t		i;
-		
-		for( i = 0; i < me->ignoredQTypeCount; ++i )
-		{
-			if( qtype == me->ignoredQTypes[ i ] )
-			{
-				err = kSkipErr;
-				goto exit;
-			}
-		}
-	}
-	// Set up response flags.
-	
-	rflags = kDNSHeaderFlag_Response;
-	if( qflags & kDNSHeaderFlag_RecursionDesired ) rflags |= kDNSHeaderFlag_RecursionDesired;
-	DNSFlagsSetOpCode( rflags, kDNSOpCode_Query );
-	
-	// Get OPT record, if any.
-	
-	dnssecOK	= false;
-	usePadding	= false;
-	err = DNSMessageGetOptRecord( inMsgPtr, inMsgLen, &qOptPtr, &qOptLen );
-	require_noerr_action_quiet( err, done, rcode = kDNSRCode_FormErr );
-	
-	// Create a tentative response message.
-	
-	msgID = DNSHeaderGetID( hdr );
-	if( me->badUDPMode && !inForTCP ) ++msgID;
-	err = _DNSServerInitializeResponseMessage( &db, msgID, rflags, qname, qtype, qclass );
-	require_noerr_action( err, done, rcode = kDNSRCode_ServFail );
-	
-	// Complete the response message.
-	
-	if( qOptPtr )
-	{
-		const dns_fixed_fields_opt * const		opt = (const dns_fixed_fields_opt *) qOptPtr;
-		unsigned int							version;
-		
-		version = dns_fixed_fields_opt_get_version( opt );
-		require_action_quiet( version == 0, done, rcode = kDNSRCode_BADVERS );
-		
-		if( dns_fixed_fields_opt_get_extended_flags( opt ) & kDNSExtendedFlag_DNSSECOK ) dnssecOK = true;
-		
-		// If the query includes EDNS(0) padding, then so must the response according to
-		// <https://datatracker.ietf.org/doc/html/rfc8467#section-4.1>.
-		
-		if( inForTCP )
-		{
-			const uint8_t *				ptr;
-			const uint8_t * const		optEnd = &qOptPtr[ qOptLen ];
-			
-			ptr = (const uint8_t *) &opt[ 1 ];
-			while( ptr < optEnd )
-			{
-				const dns_fixed_fields_option *		optionFields;
-				unsigned int						optionCode, optionLen;
-				
-				require_action_quiet( (size_t)( optEnd - ptr ) >= sizeof( *optionFields ), done, rcode = kDNSRCode_FormErr );
-				
-				optionFields	= (const dns_fixed_fields_option *) ptr;
-				optionCode		= dns_fixed_fields_option_get_code( optionFields );
-				optionLen		= dns_fixed_fields_option_get_length( optionFields );
-				
-				ptr = (const uint8_t *) &optionFields[ 1 ];
-				require_action_quiet( (size_t)( optEnd - ptr ) >= optionLen, done, rcode = kDNSRCode_FormErr );
-				
-				ptr += optionLen;
-				if( optionCode == kDNSEDNS0OptionCode_Padding )
-				{
-					usePadding = true;
-					break;
-				}
-			}
-			truncateLen = 0;
-		}
-		else
-		{
-			// For UDP, the response's length limit for truncation should account for the inclusion of an OPT record.
-			
-			check_compile_time_code( sizeof( *opt ) < kDNSMaxUDPMessageSize );
-			truncateLen	= kDNSMaxUDPMessageSize - sizeof( *opt );
-		}
-	}
-	else
-	{
-		truncateLen = inForTCP ? 0 : kDNSMaxUDPMessageSize;
-	}
-	useBadAddrs = me->badUDPMode && !inForTCP;
-	err = _DNSServerAnswerQueryDynamically( me, qname, qtype, qclass, inIndex, truncateLen, dnssecOK, useBadAddrs, &db );
-	if( err == kSkipErr ) goto exit;
-	require_noerr_action( err, done, rcode = kDNSRCode_ServFail );
-	
-	rcode = kDNSRCode_NoError;
-	
-done:
-	// Create an error response if necessary.
-	
-	if( rcode != kDNSRCode_NoError )
-	{
-		const unsigned int		rcode4BitMax  =   15; // 2^4  - 1
-		const unsigned int		rcode12BitMax = 4095; // 2^12 - 1
-		
-		// One of the following must be true.
-		// 1. The RCODE value must completely fit in the response header's 4-bit RCODE field.
-		// 2. The response will include an OPT record and the RCODE value can be represented as an unsigned 12-bit
-		//    integer (upper eight bits go in the OPT record's EXTENDED-RCODE field).
-		
-		require_fatal( ( rcode <= rcode4BitMax ) || ( ( rcode <= rcode12BitMax ) && qOptPtr ),
-			"Invalid RCODE value %u for response with%s OPT record", rcode, qOptPtr ? "" : "out" );
-		
-		DNSFlagsSetRCode( rflags, rcode & 0x0FU );
-		err = _DNSServerInitializeResponseMessage( &db, DNSHeaderGetID( hdr ), rflags, qname, qtype, qclass );
-		require_noerr( err, exit );
-	}
-	
-	// Include an OPT record in the response if the query included one.
-	// See <https://datatracker.ietf.org/doc/html/rfc6891#section-6.1.1>.
-	
-	if( qOptPtr )
-	{
-		DNSHeader *					rhdr;
-		uint16_t					additionalCount;
-		dns_fixed_fields_opt		optFields;
-		size_t						rOptOffset;
-		
-		memset( &optFields, 0, sizeof( optFields ) );
-		dns_fixed_fields_opt_set_type( &optFields, kDNSRecordType_OPT );
-		dns_fixed_fields_opt_set_udp_payload_size( &optFields, kDNSMaxUDPMessageSize );
-		dns_fixed_fields_opt_set_extended_rcode( &optFields, ( rcode >> 4 ) & 0xFFU );
-		if( dnssecOK ) dns_fixed_fields_opt_set_extended_flags( &optFields, kDNSExtendedFlag_DNSSECOK );
-		
-		rOptOffset = DataBuffer_GetLen( &db );
-		err = DataBuffer_Append( &db, &optFields, sizeof( optFields ) );
-		require_noerr( err, exit );
-		
-		// Pad responses using the block-length padding strategy using a 468-octet block length as recommended by
-		// <https://datatracker.ietf.org/doc/html/rfc8467#section-4.1>.
-		
-		if( usePadding )
-		{
-			dns_fixed_fields_opt *		rOptPtr;
-			dns_fixed_fields_option		padOption;
-			size_t						curLen, newLen, rdLen;
-			uint16_t					padLen;
-			
-			curLen = DataBuffer_GetLen( &db );
-			newLen = RoundUp( curLen + sizeof( padOption ), 468 );
-			require_action( newLen > curLen, exit, err = kSizeErr );
-			
-			rdLen = newLen - curLen;
-			require_action( rdLen <= UINT16_MAX, exit, err = kSizeErr );
-			
-			memset( &padOption, 0, sizeof( padOption ) );
-			dns_fixed_fields_option_set_code( &padOption, kDNSEDNS0OptionCode_Padding );
-			padLen = (uint16_t)( rdLen - sizeof( padOption ) );
-			dns_fixed_fields_option_set_length( &padOption, padLen );
-			err = DataBuffer_Append( &db, &padOption, sizeof( padOption ) );
-			require_noerr( err, exit );
-			
-			if( padLen > 0 )
-			{
-				err = DataBuffer_AppendF( &db, "%{fill}", 0, padLen );
-				require_noerr( err, exit );
-			}
-			check( DataBuffer_GetLen( &db ) == newLen );
-			rOptPtr = (dns_fixed_fields_opt *)( DataBuffer_GetPtr( &db ) + rOptOffset );
-			dns_fixed_fields_opt_set_rdlen( rOptPtr, (uint16_t) rdLen );
-		}
-		check( DataBuffer_GetLen( &db ) >= sizeof( *rhdr ) );
-		rhdr = (DNSHeader *) DataBuffer_GetPtr( &db );
-		additionalCount = DNSHeaderGetAdditionalCount( rhdr ) + 1;
-		DNSHeaderSetAdditionalCount( rhdr, additionalCount );
-	}
-	err = DataBuffer_Detach( &db, outResponsePtr, outResponseLen );
-	require_noerr( err, exit );
-	
-exit:
-	DataBuffer_Free( &db );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSServerInitializeResponseMessage(
-		DataBuffer *	inDB,
-		uint16_t		inID,
-		uint16_t		inFlags,
-		const uint8_t *	inQName,
-		uint16_t		inQType,
-		uint16_t		inQClass )
-{
-	OSStatus		err;
-	DNSHeader		header;
-	
-	DataBuffer_Reset( inDB );
-	
-	memset( &header, 0, sizeof( header ) );
-	DNSHeaderSetID( &header, inID );
-	DNSHeaderSetFlags( &header, inFlags );
-	DNSHeaderSetQuestionCount( &header, 1 );
-	
-	err = DataBuffer_Append( inDB, &header, sizeof( header ) );
-	require_noerr( err, exit );
-	
-	err = _DataBuffer_AppendDNSQuestion( inDB, inQName, DomainNameLength( inQName ), inQType, inQClass );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-// DNS Server QNAME Labels
-
-#define kLabel_IPv4					"ipv4"
-#define kLabel_IPv6					"ipv6"
-#define kLabelPrefix_Alias			"alias"
-#define kLabelPrefix_AliasTTL		"alias-ttl"
-#define kLabelPrefix_Count			"count-"
-#define kLabelPrefix_Index			"index-"
-#define kLabelPrefix_RCode			"rcode-"
-#define kLabelPrefix_SRV			"srv-"
-#define kLabelPrefix_Tag			"tag-"
-#define kLabelPrefix_TTL			"ttl-"
-
-// Experimental Labels
-
-#define kLabel_CommandSuspend		"command-suspend"	// Causes the DNS server to suspend query responses.
-#define kLabel_CommandResume		"command-resume"	// Causes the DNS server to resume query responses.
-#define kLabelPrefix_Offset			"offset-"			// Specifies an address offset for A and AAAA record addresses.
-#define kLabelPrefix_PDelay			"pdelay-"			// Specifies a simulated processing delay in milliseconds.
-#define kLabelPrefix_Zone			"z-"				// format: z-<algorithm mnemonic exclude '-'>-<zone index>
-
-typedef struct
-{
-	uint16_t			priority;	// Priority from SRV label.
-	uint16_t			weight;		// Weight from SRV label.
-	uint16_t			port;		// Port number from SRV label.
-	uint16_t			targetLen;	// Total length of the target hostname labels that follow an SRV label.
-	const uint8_t *		targetPtr;	// Pointer to the target hostname embedded in a domain name.
-	
-}	ParsedSRV;
-
-typedef uint32_t		DNSNameFlags;
-#define kDNSNameFlag_HasA			( 1U << 0 )
-#define kDNSNameFlag_HasAAAA		( 1U << 1 )
-#define kDNSNameFlag_HasSOA			( 1U << 2 )
-#define kDNSNameFlag_HasSRV			( 1U << 3 )
-#define kDNSNameFlag_HasPTRv4		( 1U << 4 )
-#define kDNSNameFlag_HasPTRv6		( 1U << 5 )
-#define kDNSNameFlag_HasRRSIG		( 1U << 6 )
-#define kDNSNameFlag_HasDNSKEY		( 1U << 7 )
-#define kDNSNameFlag_HasDS			( 1U << 8 )
-
-#define kAliasTTLCountMax		( ( kDomainLabelLengthMax - sizeof_string( kLabelPrefix_AliasTTL ) ) / 2 )
-#define kParsedSRVCountMax		( kDomainNameLengthMax / ( 1 + sizeof_string( kLabelPrefix_SRV ) + 5 ) )
-
-typedef enum
-{
-	kDNSServerAction_None		= 0,
-	kDNSServerAction_Suspend	= 1,
-	kDNSServerAction_Resume		= 2
-	
-}	DNSServerAction;
-
-static Boolean
-	_DNSServerParseHostName(
-		DNSServerRef		inServer,
-		const uint8_t *		inQName,
-		uint32_t *			outAliasCount,
-		uint32_t			outAliasTTLs[ kAliasTTLCountMax ],
-		uint32_t *			outAliasTTLCount,
-		uint32_t *			outCount,
-		uint32_t *			outRandCount,
-		uint32_t *			outIndex,
-		int *				outRCode,
-		uint32_t *			outTTL,
-		uint32_t *			outOffset,
-		uint32_t *			outProcDelayMs,
-		DNSNameFlags *		outFlags,
-		const uint8_t **	outZone,
-		const uint8_t **	outZoneParent,
-		DNSKeyInfoRef *		outZSK,
-		DNSKeyInfoRef *		outKSK,
-		DNSKeyInfoRef *		outParentZSK,
-		DNSServerAction *	outAction );
-static Boolean
-	_DNSServerParseSRVName(
-		DNSServerRef		inServer,
-		const uint8_t *		inName,
-		const uint8_t **	outDomainPtr,
-		size_t *			outDomainLen,
-		ParsedSRV			outSRVArray[ kParsedSRVCountMax ],
-		size_t *			outSRVCount );
-static Boolean	_DNSServerParseReverseIPv4Name( DNSServerRef me, const uint8_t *inQName, unsigned int *outHostID );
-static Boolean	_DNSServerParseReverseIPv6Name( DNSServerRef me, const uint8_t *inQName, unsigned int *outHostID );
-#if( DEBUG )
-static void
-	_DNSServerSigCheck(
-		const uint8_t *		inOwner,
-		int					inTypeCovered,
-		const void *		inMsgPtr,
-		size_t				inMsgLen,
-		const uint8_t *		inSignaturePtr,
-		const size_t		inSignatureLen,
-		DNSKeyInfoRef		inKeyInfo );
-#endif
-
-typedef enum
-{
-	kQueryStatus_Null			= 0,
-	kQueryStatus_OK				= 1,
-	kQueryStatus_Truncated		= 2,
-	kQueryStatus_NotImplemented	= 3,
-	kQueryStatus_Refused		= 4
-	
-}	QueryStatus;
-
-static OSStatus
-	_DNSServerAnswerQueryDynamically(
-		DNSServerRef			me,
-		const uint8_t * const	inQName,
-		const int				inQType,
-		const int				inQClass,
-		const size_t			inIndex,
-		const size_t			inTruncateLen,
-		const Boolean			inDNSSEC,
-		const Boolean			inUseBadAddrs,
-		DataBuffer * const		inDB )
-{
-	OSStatus			err;
-	uint32_t			aliasCount		= 0;
-	uint32_t			aliasTTLs[ kAliasTTLCountMax ];
-	uint32_t			aliasTTLCount	= 0;
-	uint32_t			addrCount		= 0;
-	uint32_t			randCount		= 0;
-	uint32_t			index			= 0;
-	int					rcodeOverride	= -1;
-	uint32_t			ttl				= 0;
-	uint32_t			offset			= 0;
-	uint32_t			procDelayMs		= 0;
-	DNSNameFlags		nameFlags		= 0;
-	const uint8_t *		zone			= NULL;
-	const uint8_t *		zoneParent		= NULL;
-	DNSKeyInfoRef		zsk				= NULL;
-	DNSKeyInfoRef		ksk				= NULL;
-	DNSKeyInfoRef		zskParent		= NULL;
-	DNSServerAction		action			= kDNSServerAction_None;
-	const uint8_t *		srvDomainPtr	= NULL;
-	size_t				srvDomainLen	= 0;
-	ParsedSRV			srvArray[ kParsedSRVCountMax ];
-	size_t				srvCount		= 0;
-	unsigned int		hostID			= 0;
-	struct timeval		now;
-	DNSHeader *			hdr;
-	unsigned int		flags;
-	int					rcode;
-	QueryStatus			status;
-	unsigned int		answerCount		= 0;
-	unsigned int		additionalCount	= 0;
-	Boolean				nameExists		= false;
-	uint8_t *			qnameLower		= NULL;
-	size_t				qnameLowerLen;
-	const uint8_t *		ownerLower;
-	size_t				ownerLowerLen;
-	DataBuffer *		sigMsg			= NULL;
-	DataBuffer			sigDB;
-	uint8_t				sigBuf[ 256 ];
-	uint8_t				nameCPtr[ 2 ];
-	uint64_t			startTicks;
-	Boolean				wasSuspended;
-	
-	startTicks = UpTicks();
-	require_action_quiet( inQClass == kDNSServiceClass_IN, done, status = kQueryStatus_NotImplemented );
-	
-	wasSuspended = me->suspended;
-	nameExists = _DNSServerParseHostName( me, inQName, &aliasCount, aliasTTLs, &aliasTTLCount, &addrCount, &randCount,
-		&index, &rcodeOverride, &ttl, &offset, &procDelayMs, &nameFlags, &zone, &zoneParent, &zsk, &ksk, &zskParent,
-		&action );
-	if( nameExists )
-	{
-		check( !( ( aliasCount > 0 ) && ( aliasTTLCount > 0 ) ) );
-		check( ( randCount == 0 ) || ( ( randCount >= addrCount ) && ( randCount <= 255 ) ) );
-		check( rcodeOverride <= 15 );
-		check( !( nameFlags & kDNSNameFlag_HasRRSIG ) || ( zsk && ksk && zskParent ) );
-		
-		switch( action )
-		{
-			case kDNSServerAction_Suspend:
-				me->suspended = true;
-				break;
-			
-			case kDNSServerAction_Resume:
-				me->suspended = false;
-				break;
-			
-			case kDNSServerAction_None:
-				break;
-		}
-		if( aliasTTLCount > 0 ) aliasCount = (uint32_t) aliasTTLCount;
-		if( index != 0 )
-		{
-			if( index == inIndex )
-			{
-				rcodeOverride = -1;
-			}
-			else if( rcodeOverride < 0 )
-			{
-				err = kSkipErr;
-				goto exit;
-			}
-			else
-			{
-				addrCount = 0;
-			}
-		}
-	}
-	
-	// If the server is in suspended mode, but didn't transition into suspended mode just now, then skip this query.
-	
-	if( me->suspended && wasSuspended )
-	{
-		err = kSkipErr;
-		goto exit;
-	}
-	
-	if( !nameExists )
-	{
-		if( ( nameExists = _DNSServerParseSRVName( me, inQName, &srvDomainPtr, &srvDomainLen, srvArray, &srvCount ) ) )
-		{
-			nameFlags = kDNSNameFlag_HasSRV;
-		}
-		else if( ( nameExists = _DNSServerParseReverseIPv4Name( me, inQName, &hostID ) ) )
-		{
-			check( ( hostID >= 1 ) && ( hostID <= 255 ) );
-			
-			nameFlags = kDNSNameFlag_HasPTRv4;
-		}
-		else if( ( nameExists = _DNSServerParseReverseIPv6Name( me, inQName, &hostID ) ) )
-		{
-			check( ( hostID >= 1 ) && ( hostID <= 255 ) );
-			
-			nameFlags = kDNSNameFlag_HasPTRv6;
-		}
-	}
-	require_action_quiet( nameExists, done, status = kQueryStatus_OK );
-	
-	err = DomainNameDupLower( inQName, &qnameLower, &qnameLowerLen );
-	require_noerr( err, exit );
-	
-	gettimeofday( &now, NULL );
-	if( aliasCount > 0 )
-	{
-		size_t						nameOffset, rdataLabelLen;
-		const uint8_t *				parentLower;
-		size_t						parentLowerLen = 0;
-		uint32_t					i;
-		dns_fixed_fields_record		recFields;
-		uint8_t						rdataLabel[ 1 + kDomainLabelLengthMax ];
-		uint8_t						parentCPtr[ 2 ];
-		Boolean						needSig;
-		
-		// If aliasCount is non-zero, then the first label of QNAME is either "alias" or "alias-<N>". parentCPtr is a
-		// name compression pointer to the second label of QNAME, i.e., the parent domain name of QNAME. It's used for
-		// the RDATA of CNAME records whose canonical name ends with the superdomain name. It may also be used to
-		// construct CNAME record names when the offset to the previous CNAME's RDATA doesn't fit in a compression
-		// pointer.
-		
-		DNSMessageWriteLabelPointer( parentCPtr, kDNSHeaderLength + ( 1 + inQName[ 0 ] ) );
-		
-		rdataLabel[ 0 ]	= 0;
-		rdataLabelLen	= 1;
-		nameOffset		= kDNSHeaderLength; // The name of the first CNAME record is equal to QNAME.
-		
-		needSig = ( inDNSSEC && ( nameFlags & kDNSNameFlag_HasRRSIG ) ) ? true : false;
-		if( needSig )
-		{
-			parentLower		= DomainNameGetNextLabel( qnameLower );
-			parentLowerLen	= DomainNameLength( parentLower );
-		}
-		for( i = aliasCount; i >= 1; --i )
-		{
-			size_t				nameLabelLen, nameLen, rdataLen, recordLen;
-			uint32_t			aliasTTL;
-			uint8_t				nameLabel[ 1 + kDomainLabelLengthMax ];
-			Boolean				useNamePtr;
-			const Boolean		useAliasTTLs = ( aliasTTLCount > 0 ) ? true : false;
-			
-			memcpy( nameLabel, rdataLabel, rdataLabelLen );
-			nameLabelLen = rdataLabelLen;
-			if( nameOffset <= kDNSCompressionOffsetMax )
-			{
-				DNSMessageWriteLabelPointer( nameCPtr, nameOffset );
-				nameLen		= sizeof( nameCPtr );
-				useNamePtr	= true;
-			}
-			else
-			{
-				nameLen		= nameLabelLen + sizeof( parentCPtr );
-				useNamePtr	= false;
-			}
-			
-			if( i > 1 )
-			{
-				// There's at least one alias/CNAME left.
-				
-				uint8_t *			dst = &rdataLabel[ 1 ];
-				const uint8_t *		lim = &rdataLabel[ countof( rdataLabel ) ];
-				size_t				maxLen;
-				int					n;
-				
-				maxLen = (size_t)( lim - dst );
-				if( useAliasTTLs )
-				{
-					uint32_t		j;
-					
-					n = MemPrintF( dst, maxLen, "%s", kLabelPrefix_AliasTTL );
-					require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print AliasTTL label" );
-					dst += n;
-					
-					for( j = aliasCount - ( i - 1 ); j < aliasCount; ++j )
-					{
-						maxLen = (size_t)( lim - dst );
-						n = MemPrintF( dst, maxLen, "-%u", aliasTTLs[ j ] );
-						require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print AliasTTL label" );
-						dst += n;
-					}
-				}
-				else if( i == 2 )
-				{
-					n = MemPrintF( dst, maxLen, "%s", kLabelPrefix_Alias );
-					require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print Alias label" );
-					dst += n;
-				}
-				else
-				{
-					n = MemPrintF( dst, maxLen, "%s-%u", kLabelPrefix_Alias, i - 1 );
-					require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print Alias label" );
-					dst += n;
-				}
-				rdataLabel[ 0 ]	= (uint8_t)( dst - &rdataLabel[ 1 ] );
-				rdataLabelLen	= 1 + rdataLabel[ 0 ];
-				rdataLen		= rdataLabelLen + sizeof( parentCPtr );
-			}
-			else
-			{
-				// This is the final CNAME.
-				
-				rdataLen = sizeof( parentCPtr );
-			}
-			
-			if( inTruncateLen > 0 )
-			{
-				recordLen = nameLen + sizeof( recFields ) + rdataLen;
-				if( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen )
-				{
-					status = kQueryStatus_Truncated;
-					goto done;
-				}
-			}
-			// Append CNAME record's NAME to response.
-			
-			if( useNamePtr )
-			{
-				err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				err = DataBuffer_Append( inDB, nameLabel, nameLabelLen );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( inDB, parentCPtr, sizeof( parentCPtr ) );
-				require_noerr( err, exit );
-			}
-			// Append CNAME record's TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			aliasTTL = useAliasTTLs ? aliasTTLs[ aliasCount - i ] : me->defaultTTL;
-			dns_fixed_fields_record_init( &recFields, kDNSServiceType_CNAME, kDNSServiceClass_IN, aliasTTL,
-				(uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Save offset of CNAME record's RDATA, which may be used for the name of the next CNAME record.
-			
-			nameOffset = DataBuffer_GetLen( inDB );
-			
-			// Append CNAME record's RDATA to response.
-			
-			if( i > 1 )
-			{
-				// There's at least one CNAME left.
-				
-				err = DataBuffer_Append( inDB, rdataLabel, rdataLabelLen );
-				require_noerr( err, exit );
-			}
-			err = DataBuffer_Append( inDB, parentCPtr, sizeof( parentCPtr ) );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			
-			if( needSig )
-			{
-				dns_fixed_fields_rrsig		sigFields;
-				const size_t				signerLen = DomainNameLength( zone );
-				uint32_t					inceptionSecs;
-				uint8_t						signature[ kDNSServerSignatureLengthMax ];
-				size_t						signatureLen;
-				int							labelCount;
-				Boolean						didSign;
-				
-				// Initialize signing buffer.
-				
-				check( !sigMsg );
-				sigMsg = &sigDB;
-				DataBuffer_Init( sigMsg, sigBuf, sizeof( sigBuf ), SIZE_MAX );
-				
-				// Append RRSIG record RDATA fixed fields to signing buffer.
-				
-				memset( &sigFields, 0, sizeof( sigFields ) );
-				dns_fixed_fields_rrsig_set_type_covered( &sigFields, kDNSServiceType_CNAME );
-				dns_fixed_fields_rrsig_set_algorithm( &sigFields, DNSKeyInfoGetAlgorithm( zsk ) );
-				labelCount = DomainNameLabelCount( inQName );
-				check( labelCount >= 0 );
-				dns_fixed_fields_rrsig_set_labels( &sigFields, (uint8_t) labelCount );
-				dns_fixed_fields_rrsig_set_original_ttl( &sigFields, aliasTTL );
-				inceptionSecs = (uint32_t) now.tv_sec;
-				dns_fixed_fields_rrsig_set_signature_expiration( &sigFields, inceptionSecs + kSecondsPerDay );
-				dns_fixed_fields_rrsig_set_signature_inception( &sigFields, inceptionSecs );
-				dns_fixed_fields_rrsig_set_key_tag( &sigFields, DNSKeyInfoGetKeyTag( zsk ) );
-				
-				err = DataBuffer_Append( sigMsg, &sigFields, sizeof( sigFields ) );
-				require_noerr( err, exit );
-				
-				// Append RRSIG record RDATA signer to signing buffer.
-				
-				err = DataBuffer_Append( sigMsg, zone, signerLen );
-				require_noerr( err, exit );
-				
-				// Append expanded CNAME record owner to signing buffer.
-				
-				if( i == aliasCount )
-				{
-					err = DataBuffer_Append( sigMsg, qnameLower, qnameLowerLen );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					err = DataBuffer_Append( sigMsg, nameLabel, nameLabelLen );
-					require_noerr( err, exit );
-					
-					err = DataBuffer_Append( sigMsg, parentLower, parentLowerLen );
-					require_noerr( err, exit );
-				}
-				// Append CNAME record fixed fields to signing buffer.
-				
-				err = DataBuffer_Append( sigMsg, &recFields, sizeof( recFields ) );
-				require_noerr( err, exit );
-				
-				// Append expanded CNAME record RDATA to signing buffer.
-				
-				if( i > 1 )
-				{
-					// There's at least one CNAME left.
-					
-					err = DataBuffer_Append( sigMsg, rdataLabel, rdataLabelLen );
-					require_noerr( err, exit );
-				}
-				err = DataBuffer_Append( sigMsg, parentLower, parentLowerLen );
-				require_noerr( err, exit );
-				
-				// Compute signature with ZSK.
-				
-				memset( signature, 0, sizeof( signature ) );
-				didSign = DNSKeyInfoSign( zsk, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ),
-					signature, &signatureLen );
-				require_quiet( didSign, exit );
-				
-				#if( DEBUG )
-				{
-					const uint8_t *		tmpPtr;
-					uint8_t				tmpBuf[ kDomainNameLengthMax ];
-					
-					if( i == aliasCount )
-					{
-						tmpPtr = inQName;
-					}
-					else
-					{
-						memcpy( tmpBuf, nameLabel, nameLabelLen );
-						memcpy( &tmpBuf[ nameLabelLen ], parentLower, parentLowerLen );
-						tmpPtr = tmpBuf;
-					}
-					_DNSServerSigCheck( tmpPtr, kDNSServiceType_CNAME, DataBuffer_GetPtr( sigMsg ),
-						DataBuffer_GetLen( sigMsg ), signature, signatureLen, zsk );
-				}
-				#endif
-				rdataLen	= sizeof( sigFields ) + signerLen + signatureLen;
-				recordLen	= nameLen + sizeof( recFields ) + rdataLen;
-				if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-				{
-					status = kQueryStatus_Truncated;
-					goto done;
-				}
-				// Append RRSIG record NAME to response.
-				
-				if( useNamePtr )
-				{
-					err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					err = DataBuffer_Append( inDB, nameLabel, nameLabelLen );
-					require_noerr( err, exit );
-					
-					err = DataBuffer_Append( inDB, parentCPtr, sizeof( parentCPtr ) );
-					require_noerr( err, exit );
-				}
-				// Append RRSIG record TYPE, CLASS, TTL, and RDLENGTH to response.
-				
-				dns_fixed_fields_record_init( &recFields, kDNSServiceType_RRSIG, kDNSServiceClass_IN, aliasTTL,
-					(uint16_t) rdataLen );
-				err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-				require_noerr( err, exit );
-				
-				// Append RRSIG record RDATA fixed fields and signer to response.
-				
-				err = DataBuffer_Append( inDB, &sigFields, sizeof( sigFields ) );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( inDB, zone, signerLen );
-				require_noerr( err, exit );
-				
-				// Append RRSIG record RDATA signature to response.
-				
-				err = DataBuffer_Append( inDB, signature, signatureLen );
-				require_noerr( err, exit );
-				
-				++answerCount;
-				DataBuffer_Free( sigMsg );
-				sigMsg = NULL;
-			}
-		}
-		check_compile_time_code( sizeof( nameCPtr ) == sizeof( parentCPtr ) );
-		memcpy( nameCPtr, parentCPtr, sizeof( nameCPtr ) );
-		
-		ownerLower		= DomainNameGetNextLabel( qnameLower );
-		ownerLowerLen	= DomainNameLength( ownerLower );
-	}
-	else
-	{
-		// There are no aliases, so initialize the name compression pointer to point to QNAME.
-		
-		DNSMessageWriteLabelPointer( nameCPtr, kDNSHeaderLength );
-		
-		ownerLower		= qnameLower;
-		ownerLowerLen	= qnameLowerLen;
-	}
-	
-	if( ( inQType == kDNSServiceType_A ) || ( inQType == kDNSServiceType_AAAA ) )
-	{
-		dns_fixed_fields_record		recFields;
-		dns_fixed_fields_rrsig		sigFields;
-		uint8_t *					idPtr;					// Pointer to the host identifier portion of an IP address.
-		size_t						recordLen;				// Length of the entire record.
-		size_t						rdataLen;				// Length of record's RDATA.
-		size_t						signerLen = 0;
-		unsigned int				i;						// For-loop counter.
-		uint8_t						rdata[ 16 ];			// A buffer that's big enough for either A or AAAA RDATA.
-		uint8_t						randIntegers[ 255 ];	// Array for random integers in [1, 255].
-		Boolean						needSig, nameIsV6Only;
-		
-		if( inQType == kDNSServiceType_A )
-		{
-			uint32_t		baseAddr;
-			
-			require_action_quiet( nameFlags & kDNSNameFlag_HasA, done, status = kQueryStatus_OK );
-			
-			rdataLen = 4;
-			baseAddr = inUseBadAddrs ? kDNSServerBadBaseAddrV4 : kDNSServerBaseAddrV4;
-			WriteBig32Typed( rdata, baseAddr );
-			idPtr = &rdata[ 3 ]; // The last octet is the host identifier since the IPv4 address block is /24.
-		}
-		else
-		{
-			const uint8_t		( *baseAddr )[ 16 ];
-			
-			require_action_quiet( nameFlags & kDNSNameFlag_HasAAAA, done, status = kQueryStatus_OK );
-			
-			rdataLen = 16;
-			baseAddr = inUseBadAddrs ? &kDNSServerBadBaseAddrV6 : &kDNSServerBaseAddrV6;
-			memcpy( rdata, baseAddr, rdataLen );
-			idPtr = &rdata[ 14 ]; // The last two octets are the host identifier since we allow up to 511 IPv6 addresses.
-		}
-		
-		if( randCount > 0 )
-		{
-			// Populate the array with all integers between 1 and <randCount>, inclusive.
-			
-			for( i = 0; i < randCount; ++i ) randIntegers[ i ] = (uint8_t)( i + 1 );
-			
-			// Prevent dubious static analyzer warning.
-			// Note: _DNSServerParseHostName() already enforces randCount >= addrCount. Also, this require_fatal() check
-			// needs to be placed right before the next for-loop. Any earlier, and the static analyzer warning will persist
-			// for some reason.
-			
-			require_fatal( addrCount <= randCount, "Invalid Count label values: addrCount %u > randCount %u",
-				addrCount, randCount );
-			
-			// Create a contiguous subarray starting at index 0 that contains <addrCount> randomly chosen integers between
-			// 1 and <randCount>, inclusive.
-			// Loop invariant 1: Array elements with indexes in [0, i - 1] have been randomly chosen.
-			// Loop invariant 2: Array elements with indexes in [i, randCount - 1] are candidates for being chosen.
-			
-			for( i = 0; i < addrCount; ++i )
-			{
-				uint8_t			tmp;
-				uint32_t		j;
-				
-				j = RandomRange( i, randCount - 1 );
-				if( i != j )
-				{
-					tmp = randIntegers[ i ];
-					randIntegers[ i ] = randIntegers[ j ];
-					randIntegers[ j ] = tmp;
-				}
-			}
-		}
-		needSig = ( inDNSSEC && ( nameFlags & kDNSNameFlag_HasRRSIG ) ) ? true : false;
-		if( needSig )
-		{
-			uint32_t		inceptionSecs;
-			int				labelCount;
-			
-			// Initialize signing buffer.
-			
-			check( !sigMsg );
-			sigMsg = &sigDB;
-			DataBuffer_Init( sigMsg, sigBuf, sizeof( sigBuf ), SIZE_MAX );
-			
-			// Append RRSIG record RDATA fixed fields to signing buffer.
-			
-			memset( &sigFields, 0, sizeof( sigFields ) );
-			dns_fixed_fields_rrsig_set_type_covered( &sigFields, (uint16_t) inQType );
-			dns_fixed_fields_rrsig_set_algorithm( &sigFields, DNSKeyInfoGetAlgorithm( zsk ) );
-			labelCount = DomainNameLabelCount( ownerLower );
-			check( labelCount >= 0 );
-			dns_fixed_fields_rrsig_set_labels( &sigFields, (uint8_t) labelCount );
-			dns_fixed_fields_rrsig_set_original_ttl( &sigFields, ttl );
-			inceptionSecs = (uint32_t) now.tv_sec;
-			dns_fixed_fields_rrsig_set_signature_expiration( &sigFields, inceptionSecs + kSecondsPerDay );
-			dns_fixed_fields_rrsig_set_signature_inception( &sigFields, inceptionSecs );
-			dns_fixed_fields_rrsig_set_key_tag( &sigFields, DNSKeyInfoGetKeyTag( zsk ) );
-			
-			err = DataBuffer_Append( sigMsg, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signer to signing buffer.
-			
-			signerLen = DomainNameLength( zone );
-			err = DataBuffer_Append( sigMsg, zone, signerLen );
-			require_noerr( err, exit );
-		}
-		recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-		dns_fixed_fields_record_init( &recFields, (uint16_t) inQType, kDNSServiceClass_IN, ttl, (uint16_t) rdataLen );
-		
-		nameIsV6Only = ( ( nameFlags & ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA ) ) == kDNSNameFlag_HasAAAA );
-		for( i = 0; i < addrCount; ++i )
-		{
-			uint32_t				addrHostID;
-			const unsigned int		modulus = nameIsV6Only ? 512 : 256; // IPv6-only names can have up to 511 addresses.
-			
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append A/AAAA record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append A/AAAA record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append A/AAAA record RDATA to response.
-			
-			addrHostID = ( randCount > 0 ) ? randIntegers[ i ] : ( i + 1 );
-			addrHostID = ( addrHostID + offset ) % modulus;
-			if( inQType == kDNSServiceType_A )
-			{
-				*idPtr = (uint8_t) addrHostID;
-			}
-			else
-			{
-				WriteBig16Typed( idPtr, (uint16_t) addrHostID );
-			}
-			err = DataBuffer_Append( inDB, rdata, rdataLen );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			if( needSig )
-			{
-				// Append A/AAAA record to signing buffer.
-				
-				err = DataBuffer_Append( sigMsg, ownerLower, ownerLowerLen );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( sigMsg, &recFields, sizeof( recFields ) );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( sigMsg, rdata, rdataLen );
-				require_noerr( err, exit );
-			}
-		}
-		if( needSig )
-		{
-			uint8_t		signature[ kDNSServerSignatureLengthMax ];
-			size_t		signatureLen;
-			Boolean		didSign;
-			
-			// Compute signature with ZSK.
-			
-			memset( signature, 0, sizeof( signature ) );
-			didSign = DNSKeyInfoSign( zsk, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ),
-				signature, &signatureLen );
-			require_quiet( didSign, exit );
-			
-		#if( DEBUG )
-			_DNSServerSigCheck( ownerLower, inQType, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ), signature,
-				signatureLen, zsk );
-		#endif
-			rdataLen	= sizeof( sigFields ) + signerLen + signatureLen;
-			recordLen	= sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append RRSIG record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			dns_fixed_fields_record_init( &recFields, kDNSServiceType_RRSIG, kDNSServiceClass_IN, ttl, (uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA fixed fields and signer to response.
-			
-			err = DataBuffer_Append( inDB, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( inDB, zone, signerLen );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signature to response.
-			
-			err = DataBuffer_Append( inDB, signature, signatureLen );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			DataBuffer_Free( sigMsg );
-			sigMsg = NULL;
-		}
-	}
-	else if( inQType == kDNSServiceType_SRV )
-	{
-		dns_fixed_fields_record		recFields;
-		size_t						i;
-		
-		require_action_quiet( nameFlags & kDNSNameFlag_HasSRV, done, status = kQueryStatus_OK );
-		
-		dns_fixed_fields_record_init( &recFields, kDNSServiceType_SRV, kDNSServiceClass_IN, me->defaultTTL, 0 );
-		for( i = 0; i < srvCount; ++i )
-		{
-			dns_fixed_fields_srv		srvFields;
-			size_t						rdataLen;
-			size_t						recordLen;
-			const ParsedSRV * const		srv = &srvArray[ i ];
-			
-			rdataLen  = sizeof( srvFields ) + srvDomainLen + srv->targetLen + 1;
-			recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			dns_fixed_fields_record_set_rdlength( &recFields, (uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append SRV RDATA priority, weight, and port to response.
-			
-			dns_fixed_fields_srv_init( &srvFields, srv->priority, srv->weight, srv->port );
-			err = DataBuffer_Append( inDB, &srvFields, sizeof( srvFields ) );
-			require_noerr( err, exit );
-			
-			// Append SRV RDATA target non-root labels to response.
-			
-			if( srv->targetLen > 0 )
-			{
-				err = DataBuffer_Append( inDB, srv->targetPtr, srv->targetLen );
-				require_noerr( err, exit );
-			}
-			
-			if( srvDomainLen > 0 )
-			{
-				err = DataBuffer_Append( inDB, srvDomainPtr, srvDomainLen );
-				require_noerr( err, exit );
-			}
-			
-			// Append SRV RDATA target root label to response.
-			
-			err = DataBuffer_Append( inDB, "", 1 );
-			require_noerr( err, exit );
-			
-			++answerCount;
-		}
-	}
-	else if( inQType == kDNSServiceType_SOA )
-	{
-		size_t		nameLen, recordLen;
-		
-		require_action_quiet( nameFlags & kDNSNameFlag_HasSOA, done, status = kQueryStatus_OK );
-		
-		nameLen	= DomainNameLength( me->domain );
-		if( inTruncateLen > 0 )
-		{
-			err = AppendSOARecord( NULL, me->domain, nameLen, 0, 0, 0, kRootLabel, kRootLabel, 0, 0, 0, 0, 0, &recordLen );
-			require_noerr( err, exit );
-			
-			if( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-		}
-		err = AppendSOARecord( inDB, me->domain, nameLen, kDNSServiceType_SOA, kDNSServiceClass_IN, me->defaultTTL,
-			kRootLabel, kRootLabel, me->serial, 1 * kSecondsPerDay, 2 * kSecondsPerHour, 1000 * kSecondsPerHour,
-			me->defaultTTL, NULL );
-		require_noerr( err, exit );
-		
-		++answerCount;
-	}
-	else if( inQType == kDNSServiceType_PTR )
-	{
-		dns_fixed_fields_record		recFields;
-		size_t						domainLen, rdataLen, recordLen;
-		uint8_t						label[ 1 + kDomainLabelLengthMax ];
-		uint8_t *					dst = &label[ 1 ];
-		const uint8_t *				lim = &label[ countof( label ) ];
-		
-		if( nameFlags & kDNSNameFlag_HasPTRv4 )
-		{
-			size_t				maxLen;
-			int					n;
-			const uint32_t		ipv4Addr = kDNSServerBaseAddrV4 + hostID;
-			
-			maxLen = (size_t)( lim - dst );
-			n = MemPrintF( dst, maxLen, "ipv4-%u-%u-%u-%u",
-				( ipv4Addr >> 24 ) & 0xFFU,
-				( ipv4Addr >> 16 ) & 0xFFU,
-				( ipv4Addr >>  8 ) & 0xFFU,
-				  ipv4Addr         & 0xFFU );
-			require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print reverse IPv4 hostname label" );
-			dst += n;
-		}
-		else if( nameFlags & kDNSNameFlag_HasPTRv6 )
-		{
-			size_t		maxLen;
-			int			n, i;
-			uint8_t		ipv6Addr[ 16 ];
-			
-			maxLen = (size_t)( lim - dst );
-			n = MemPrintF( dst, maxLen, "ipv6" );
-			require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print reverse IPv6 hostname label" );
-			dst += n;
-			
-			memcpy( ipv6Addr, kDNSServerBaseAddrV6, 16 );
-			ipv6Addr[ 15 ] = (uint8_t) hostID;
-			for( i = 0; i < 8; ++i )
-			{
-				maxLen = (size_t)( lim - dst );
-				n = MemPrintF( dst, maxLen, "-%04x", ReadBig16( &ipv6Addr[ i * 2 ] ) );
-				require_fatal( ( n > 0 ) && ( ( (size_t) n ) <= maxLen ), "Failed to print reverse IPv6 hostname label" );
-				dst += n;
-			}
-		}
-		else
-		{
-			status = kQueryStatus_OK;
-			goto done;
-		}
-		label[ 0 ] = (uint8_t)( dst - &label[ 1 ] );
-		
-		domainLen	= DomainNameLength( me->domain );
-		rdataLen	= 1 + label[ 0 ] + domainLen;
-		recordLen	= sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-		if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-		{
-			status = kQueryStatus_Truncated;
-			goto done;
-		}
-		
-		// Append PTR record NAME to response.
-		
-		err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-		require_noerr( err, exit );
-		
-		// Append PTR record TYPE, CLASS, TTL, and RDLENGTH to response.
-		
-		dns_fixed_fields_record_init( &recFields, kDNSServiceType_PTR, kDNSServiceClass_IN, me->defaultTTL,
-			(uint16_t) rdataLen );
-		err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-		require_noerr( err, exit );
-		
-		// Append PTR record RDATA to response.
-		
-		err = DataBuffer_Append( inDB, label, 1 + label[ 0 ] );
-		require_noerr( err, exit );
-		
-		err = DataBuffer_Append( inDB, me->domain, domainLen );
-		require_noerr( err, exit );
-		
-		++answerCount;
-	}
-	else if( inQType == kDNSServiceType_DNSKEY )
-	{
-		size_t						recordLen;
-		size_t						signerLen = 0;
-		dns_fixed_fields_record		recFields;
-		dns_fixed_fields_rrsig		sigFields;
-		Boolean						needSig;
-		
-		require_action_quiet( nameFlags & kDNSNameFlag_HasDNSKEY, done, status = kQueryStatus_OK );
-		
-		recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + DNSKeyInfoGetRDataLen( zsk );
-		if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-		{
-			status = kQueryStatus_Truncated;
-			goto done;
-		}
-		// Append ZSK DNSKEY record NAME to response.
-		
-		err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-		require_noerr( err, exit );
-		
-		// Append ZSK DNSKEY record TYPE, CLASS, TTL, and RDLENGTH to response.
-		
-		dns_fixed_fields_record_init( &recFields, kDNSServiceType_DNSKEY, kDNSServiceClass_IN, ttl,
-			DNSKeyInfoGetRDataLen( zsk ) );
-		err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-		require_noerr( err, exit );
-		
-		// Append ZSK DNSKEY record RDATA to response.
-		
-		err = DataBuffer_Append( inDB, DNSKeyInfoGetRDataPtr( zsk ), DNSKeyInfoGetRDataLen( zsk ) );
-		require_noerr( err, exit );
-		
-		++answerCount;
-		
-		needSig = ( inDNSSEC && ( nameFlags & kDNSNameFlag_HasRRSIG ) ) ? true : false;
-		if( needSig )
-		{
-			uint32_t		inceptionSecs;
-			int				labelCount;
-			
-			// Initialize signing buffer.
-			
-			check( !sigMsg );
-			sigMsg = &sigDB;
-			DataBuffer_Init( sigMsg, sigBuf, sizeof( sigBuf ), SIZE_MAX );
-			
-			// Append RRSIG record RDATA fixed fields to signing buffer.
-			
-			memset( &sigFields, 0, sizeof( sigFields ) );
-			dns_fixed_fields_rrsig_set_type_covered( &sigFields, kDNSServiceType_DNSKEY );
-			dns_fixed_fields_rrsig_set_algorithm( &sigFields, DNSKeyInfoGetAlgorithm( ksk ) );
-			labelCount = DomainNameLabelCount( ownerLower );
-			check( labelCount >= 0 );
-			dns_fixed_fields_rrsig_set_labels( &sigFields, (uint8_t) labelCount );
-			dns_fixed_fields_rrsig_set_original_ttl( &sigFields, ttl );
-			inceptionSecs = (uint32_t) now.tv_sec;
-			dns_fixed_fields_rrsig_set_signature_expiration( &sigFields, inceptionSecs + kSecondsPerDay );
-			dns_fixed_fields_rrsig_set_signature_inception( &sigFields, inceptionSecs );
-			dns_fixed_fields_rrsig_set_key_tag( &sigFields, DNSKeyInfoGetKeyTag( ksk ) );
-			
-			err = DataBuffer_Append( sigMsg, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signer to signing buffer.
-			
-			signerLen = DomainNameLength( zone );
-			err = DataBuffer_Append( sigMsg, zone, signerLen );
-			require_noerr( err, exit );
-			
-			// Append ZSK DNSKEY record to signing buffer.
-			
-			err = DataBuffer_Append( sigMsg, ownerLower, ownerLowerLen );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( sigMsg, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( sigMsg, DNSKeyInfoGetRDataPtr( zsk ), DNSKeyInfoGetRDataLen( zsk ) );
-			require_noerr( err, exit );
-		}
-		recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + DNSKeyInfoGetRDataLen( ksk );
-		if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-		{
-			status = kQueryStatus_Truncated;
-			goto done;
-		}
-		// Append KSK DNSKEY record NAME to response.
-		
-		err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-		require_noerr( err, exit );
-		
-		// Append KSK DNSKEY record TYPE, CLASS, TTL, and RDLENGTH to response.
-		
-		err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-		require_noerr( err, exit );
-		
-		// Append KSK DNSKEY record RDATA to response.
-		
-		err = DataBuffer_Append( inDB, DNSKeyInfoGetRDataPtr( ksk ), DNSKeyInfoGetRDataLen( ksk ) );
-		require_noerr( err, exit );
-		
-		++answerCount;
-		if( needSig )
-		{
-			size_t		rdataLen;
-			uint8_t		signature[ kDNSServerSignatureLengthMax ];
-			size_t		signatureLen;
-			Boolean		didSign;
-			
-			// Append KSK DNSKEY record to signing buffer.
-			
-			err = DataBuffer_Append( sigMsg, ownerLower, ownerLowerLen );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( sigMsg, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( sigMsg, DNSKeyInfoGetRDataPtr( ksk ), DNSKeyInfoGetRDataLen( ksk ) );
-			require_noerr( err, exit );
-			
-			// Compute signature with KSK.
-			
-			memset( signature, 0, sizeof( signature ) );
-			didSign = DNSKeyInfoSign( ksk, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ),
-				signature, &signatureLen );
-			require_quiet( didSign, exit );
-			
-		#if( DEBUG )
-			_DNSServerSigCheck( ownerLower, inQType, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ), signature,
-				signatureLen, ksk );
-		#endif
-			rdataLen	= sizeof( sigFields ) + signerLen + signatureLen;
-			recordLen	= sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append RRSIG record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			dns_fixed_fields_record_init( &recFields, kDNSServiceType_RRSIG, kDNSServiceClass_IN, ttl, (uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA fixed fields and signer to response.
-			
-			err = DataBuffer_Append( inDB, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( inDB, zone, signerLen );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signature to response.
-			
-			err = DataBuffer_Append( inDB, signature, signatureLen );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			DataBuffer_Free( sigMsg );
-			sigMsg = NULL;
-		}
-	}
-	else if( inQType == kDNSServiceType_DS )
-	{
-		SHA256_CTX					ctx;
-		size_t						rdataLen, i, recordLen;
-		size_t						signerLen = 0;
-		dns_ds_sha256 *				dsPtr;
-		dns_ds_sha256 *				dsPtrs[ 2 ];
-		int							cmp;
-		dns_ds_sha256				dsZSK, dsKSK;
-		dns_fixed_fields_rrsig		sigFields;
-		dns_fixed_fields_record		recFields;
-		Boolean						needSig;
-		
-		check_compile_time_code( sizeof( dsPtr->digest ) == SHA256_DIGEST_LENGTH );
-		
-		require_action_quiet( nameFlags & kDNSNameFlag_HasDS, done, status = kQueryStatus_OK );
-		
-		// Set up ZSK DS RDATA.
-		
-		dsPtr = &dsZSK;
-		memset( dsPtr, 0, sizeof( *dsPtr ) );
-		dns_ds_sha256_set_key_tag( dsPtr, DNSKeyInfoGetKeyTag( zsk ) );
-		dns_ds_sha256_set_algorithm( dsPtr, DNSKeyInfoGetAlgorithm( zsk ) );
-		dns_ds_sha256_set_digest_type( dsPtr, kDSDigestType_SHA256 );
-		
-		SHA256_Init( &ctx );
-		SHA256_Update( &ctx, ownerLower, ownerLowerLen );
-		SHA256_Update( &ctx, DNSKeyInfoGetRDataPtr( zsk ), DNSKeyInfoGetRDataLen( zsk ) );
-		SHA256_Final( dsPtr->digest, &ctx );
-		
-		// Set up KSK DS RDATA.
-		
-		dsPtr = &dsKSK;
-		memset( dsPtr, 0, sizeof( *dsPtr ) );
-		dns_ds_sha256_set_key_tag( dsPtr, DNSKeyInfoGetKeyTag( ksk ) );
-		dns_ds_sha256_set_algorithm( dsPtr, DNSKeyInfoGetAlgorithm( ksk ) );
-		dns_ds_sha256_set_digest_type( dsPtr, kDSDigestType_SHA256 );
-		
-		SHA256_Init( &ctx );
-		SHA256_Update( &ctx, ownerLower, ownerLowerLen );
-		SHA256_Update( &ctx, DNSKeyInfoGetRDataPtr( ksk ), DNSKeyInfoGetRDataLen( ksk ) );
-		SHA256_Final( dsPtr->digest, &ctx );
-		
-		// Order the DS RDATAs
-		
-		cmp = memcmp( &dsZSK, &dsKSK, sizeof( dns_ds_sha256 ) );
-		if( cmp <= 0 )
-		{
-			dsPtrs[ 0 ] = &dsZSK;
-			dsPtrs[ 1 ] = ( cmp == 0 ) ? NULL : &dsKSK;
-		}
-		else
-		{
-			dsPtrs[ 0 ] = &dsKSK;
-			dsPtrs[ 1 ] = &dsZSK;
-		}
-		needSig = ( inDNSSEC && ( nameFlags & kDNSNameFlag_HasRRSIG ) ) ? true : false;
-		if( needSig )
-		{
-			uint32_t		inceptionSecs;
-			int				labelCount;
-			
-			// Initialize signing buffer.
-			
-			check( !sigMsg );
-			sigMsg = &sigDB;
-			DataBuffer_Init( sigMsg, sigBuf, sizeof( sigBuf ), SIZE_MAX );
-			
-			// Append RRSIG record RDATA fixed fields to signing buffer.
-			
-			memset( &sigFields, 0, sizeof( sigFields ) );
-			dns_fixed_fields_rrsig_set_type_covered( &sigFields, kDNSServiceType_DS );
-			dns_fixed_fields_rrsig_set_algorithm( &sigFields, DNSKeyInfoGetAlgorithm( zskParent ) );
-			labelCount = DomainNameLabelCount( ownerLower );
-			check( labelCount >= 0 );
-			dns_fixed_fields_rrsig_set_labels( &sigFields, (uint8_t) labelCount );
-			dns_fixed_fields_rrsig_set_original_ttl( &sigFields, ttl );
-			inceptionSecs = (uint32_t) now.tv_sec;
-			dns_fixed_fields_rrsig_set_signature_expiration( &sigFields, inceptionSecs + kSecondsPerDay );
-			dns_fixed_fields_rrsig_set_signature_inception( &sigFields, inceptionSecs );
-			dns_fixed_fields_rrsig_set_key_tag( &sigFields, DNSKeyInfoGetKeyTag( zskParent ) );
-			
-			err = DataBuffer_Append( sigMsg, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signer to signing buffer.
-			
-			signerLen = DomainNameLength( zoneParent );
-			err = DataBuffer_Append( sigMsg, zoneParent, signerLen );
-			require_noerr( err, exit );
-		}
-		rdataLen = sizeof( dns_ds_sha256 );
-		dns_fixed_fields_record_init( &recFields, kDNSServiceType_DS, kDNSServiceClass_IN, ttl, (uint16_t) rdataLen );
-		for( i = 0; i < countof( dsPtrs ); ++i )
-		{
-			dsPtr = dsPtrs[ i ];
-			if( !dsPtr ) continue;
-			
-			recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append DS record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append DS record TYPE, CLASS, TTL, and RDLENGTH to response.
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append DS record RDATA to response.
-			
-			err = DataBuffer_Append( inDB, dsPtr, sizeof( *dsPtr ) );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			if( needSig )
-			{
-				// Append DS record to signing buffer.
-				
-				err = DataBuffer_Append( sigMsg, ownerLower, ownerLowerLen );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( sigMsg, &recFields, sizeof( recFields ) );
-				require_noerr( err, exit );
-				
-				err = DataBuffer_Append( sigMsg, dsPtr, sizeof( *dsPtr ) );
-				require_noerr( err, exit );
-			}
-		}
-		if( needSig )
-		{
-			uint8_t		signature[ kDNSServerSignatureLengthMax ];
-			size_t		signatureLen;
-			Boolean		didSign;
-			
-			// Compute signature with parent ZSK.
-			
-			memset( signature, 0, sizeof( signature ) );
-			didSign = DNSKeyInfoSign( zskParent, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ),
-				signature, &signatureLen );
-			require_quiet( didSign, exit );
-			
-		#if( DEBUG )
-			_DNSServerSigCheck( ownerLower, inQType, DataBuffer_GetPtr( sigMsg ), DataBuffer_GetLen( sigMsg ), signature,
-				signatureLen, zskParent );
-		#endif
-			rdataLen	= sizeof( sigFields ) + signerLen + signatureLen;
-			recordLen	= sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-			if( ( inTruncateLen > 0 ) && ( ( DataBuffer_GetLen( inDB ) + recordLen ) > inTruncateLen ) )
-			{
-				status = kQueryStatus_Truncated;
-				goto done;
-			}
-			// Append RRSIG record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			dns_fixed_fields_record_init( &recFields, kDNSServiceType_RRSIG, kDNSServiceClass_IN, ttl, (uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA fixed fields and signer to response.
-			
-			err = DataBuffer_Append( inDB, &sigFields, sizeof( sigFields ) );
-			require_noerr( err, exit );
-			
-			err = DataBuffer_Append( inDB, zoneParent, signerLen );
-			require_noerr( err, exit );
-			
-			// Append RRSIG record RDATA signature to response.
-			
-			err = DataBuffer_Append( inDB, signature, signatureLen );
-			require_noerr( err, exit );
-			
-			++answerCount;
-			
-			DataBuffer_Free( sigMsg );
-			sigMsg = NULL;
-		}
-	}
-	status = kQueryStatus_OK;
-	
-done:
-	hdr = (DNSHeader *) DataBuffer_GetPtr( inDB );
-	flags = DNSHeaderGetFlags( hdr );
-	switch( status )
-	{
-		case kQueryStatus_OK:
-		case kQueryStatus_Truncated:
-			flags |= kDNSHeaderFlag_AuthAnswer;
-			if( status == kQueryStatus_Truncated ) flags |= kDNSHeaderFlag_Truncation;
-			rcode = nameExists ? kDNSRCode_NoError : kDNSRCode_NXDomain;
-			break;
-		
-		case kQueryStatus_NotImplemented:
-			rcode = kDNSRCode_NotImp;
-			break;
-		
-		case kQueryStatus_Refused:
-			rcode = kDNSRCode_Refused;
-			break;
-		
-		case kQueryStatus_Null:
-		default:
-			err = kInternalErr;
-			goto exit;
-	}
-	if( rcodeOverride >= 0 )
-	{
-		dns_fixed_fields_record		recFields;
-		const char *				rcodeStr;
-		size_t						maxLen, txtStrLen, rdataLen, recordLen;
-		int							n;
-		uint8_t						rdataBuf[ 1 + 255 ]; // Enough space for one TXT record string.
-		
-		// Create the RDATA for an informational TXT record that contains the original rcode to put in the Additional
-		// section.
-		
-		maxLen = sizeof( rdataBuf ) - 1;
-		rcodeStr = DNSRCodeToString( rcode );
-		if( rcodeStr )	n = MemPrintF( &rdataBuf[ 1 ], maxLen, "original-rcode=%s", rcodeStr );
-		else			n = MemPrintF( &rdataBuf[ 1 ], maxLen, "original-rcode=%d", rcode );
-		txtStrLen = ( n > 0 ) ? Min( (size_t) n, maxLen ) : 0;
-		rdataBuf[ 0 ] = (uint8_t) txtStrLen;
-		rdataLen = 1 + txtStrLen;
-		
-		// The TXT record isn't strictly necessary, so only include it if it fits.
-		
-		recordLen = sizeof( nameCPtr ) + sizeof( recFields ) + rdataLen;
-		maxLen = ( inTruncateLen > 0 ) ? inTruncateLen : kDNSMaxTCPMessageSize;
-		if( ( DataBuffer_GetLen( inDB ) < maxLen ) && ( ( maxLen - DataBuffer_GetLen( inDB ) ) >= recordLen ) )
-		{
-			// Append TXT record NAME to response.
-			
-			err = DataBuffer_Append( inDB, nameCPtr, sizeof( nameCPtr ) );
-			require_noerr( err, exit );
-			
-			// Append TXT record TYPE, CLASS, TTL, and RDLENGTH to response.
-			
-			dns_fixed_fields_record_init( &recFields, kDNSRecordType_TXT, kDNSClassType_IN, 0, (uint16_t) rdataLen );
-			err = DataBuffer_Append( inDB, &recFields, sizeof( recFields ) );
-			require_noerr( err, exit );
-			
-			// Append TXT record RDATA to response.
-			
-			err = DataBuffer_Append( inDB, rdataBuf, rdataLen );
-			require_noerr( err, exit );
-			
-			++additionalCount;
-		}
-		rcode = rcodeOverride;
-	}
-	DNSFlagsSetRCode( flags, rcode );
-	DNSHeaderSetFlags( hdr, flags );
-	DNSHeaderSetAnswerCount( hdr, answerCount );
-	DNSHeaderSetAdditionalCount( hdr, additionalCount );
-	if( procDelayMs > 0 )
-	{
-		const uint64_t		delayTicks		= MillisecondsToUpTicks( procDelayMs );
-		const uint64_t		elapsedTicks	= UpTicks() - startTicks;
-		
-		if( delayTicks > elapsedTicks ) SleepForUpTicks( delayTicks - elapsedTicks );
-	}
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( qnameLower );
-	if( sigMsg ) DataBuffer_Free( sigMsg );
-	return( err );
-}
-
-static Boolean
-	_DNSServerNameIsDNSSECZone(
-		const uint8_t *		inName,
-		const uint8_t **	outZoneParent,
-		DNSKeyInfoRef *		outZSK,
-		DNSKeyInfoRef *		outKSK,
-		DNSKeyInfoRef *		outParentZSK );
-
-static Boolean
-	_DNSServerParseHostName(
-		DNSServerRef		me,
-		const uint8_t *		inQName,
-		uint32_t *			outAliasCount,
-		uint32_t			outAliasTTLs[ kAliasTTLCountMax ],
-		uint32_t *			outAliasTTLCount,
-		uint32_t *			outCount,
-		uint32_t *			outRandCount,
-		uint32_t *			outIndex,
-		int *				outRCode,
-		uint32_t *			outTTL,
-		uint32_t *			outOffset,
-		uint32_t *			outProcDelayMs,
-		DNSNameFlags *		outFlags,
-		const uint8_t **	outZone,
-		const uint8_t **	outZoneParent,
-		DNSKeyInfoRef *		outZSK,
-		DNSKeyInfoRef *		outKSK,
-		DNSKeyInfoRef *		outParentZSK,
-		DNSServerAction *	outAction )
-{
-	OSStatus			err;
-	const uint8_t *		label;
-	size_t				labelLen;
-    const uint8_t *		labelNext;
-	uint32_t			aliasTTLCount	= 0;	// Count of TTL args from Alias-TTL label.
-	uint32_t			aliasCount		= 0;	// Arg from Alias label. Valid values are in [2, 2^31 - 1].
-	int32_t				count			= -1;	// First arg from Count label. Valid values are in [0, 255].
-	uint32_t			randCount		= 0;	// Second arg from Count label. Valid values are in [count, 255].
-	uint32_t			index			= 0;	// Arg from Index label. Valid values are in [1, 2^32 - 1].
-	int					rcode			= -1;	// Arg from RCode label. Valid values are in [0, 15].
-	int32_t				ttl				= -1;	// Arg from TTL label. Valid values are in [0, 2^31 - 1].
-	int32_t				offset			= -1;	// Arg from Offset label. Valid values are in [0, 2^31 - 1].
-	int32_t				procDelayMs		= -1;	// Arg from PDelay label. Valid values are in [0, 2000]. Units are in ms.
-	DNSNameFlags		flags			= 0;
-	int32_t				maxCount;
-	const uint8_t *		zone			= NULL;
-	const uint8_t *		zoneParent		= NULL;
-	DNSKeyInfoRef		zsk				= NULL;
-	DNSKeyInfoRef		ksk				= NULL;
-	DNSKeyInfoRef		parentZSK		= NULL;
-	DNSServerAction		action			= kDNSServerAction_None;
-	Boolean				isAlias			= false;
-	
-	for( label = inQName; ( labelLen = *label ) != 0; label = labelNext )
-	{
-		const uint8_t *		labelData;
-		uint32_t			arg;
-
-		if( labelLen > kDomainLabelLengthMax ) break;
-		labelData = &label[ 1 ];
-		labelNext = &labelData[ labelLen ];
-
-		if( label == inQName )
-		{
-			// Check if the first label is a valid alias TTL sequence label.
-			// Note: Since "alias" is a prefix of "alias-ttl", check for "alias-ttl" first.
-
-			if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_AliasTTL ) == 0 )
-			{
-				const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_AliasTTL ) ];
-				const char * const		end = (const char *) labelNext;
-
-				while( ptr < end )
-				{
-					if( *ptr++ != '-' ) break;
-					err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-					if( err || ( arg > INT32_MAX ) ) break; // TTL must be in [0, 2^31 - 1].
-					if( outAliasTTLs ) outAliasTTLs[ aliasTTLCount ] = arg;
-					++aliasTTLCount;
-				}
-				if( ( aliasTTLCount == 0 ) || ( ptr != end ) ) break;
-				isAlias = true;
-				continue;
-			}
-
-			// Check if the first label is a valid alias label.
-
-			if( ( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Alias ) == 0 ) )
-			{
-				const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_Alias ) ];
-				const char * const		end = (const char *) labelNext;
-
-				if( ptr < end )
-				{
-					if( *ptr++ != '-' ) break;
-					err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-					if( err || ( arg < 2 ) || ( arg > INT32_MAX ) ) break; // Alias count must be in [2, 2^31 - 1].
-					aliasCount = arg;
-					if( ptr != end ) break;
-				}
-				else
-				{
-					aliasCount = 1;
-				}
-				isAlias = true;
-				continue;
-			}
-		}
-
-		// Check if this label is a valid count label.
-
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Count ) == 0  )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_Count ) ];
-			const char * const		end = (const char *) labelNext;
-
-			if( count >= 0 ) break; // Count cannot be specified more than once.
-
-			err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-			if( err || ( arg > INT32_MAX ) ) break; // The actual upper bound for Count will be verified below.
-			count = (int32_t) arg;
-
-			if( ptr < end )
-			{
-				if( *ptr++ != '-' ) break;
-				err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-				if( err || ( arg < ( (uint32_t) count ) ) || ( arg > 255 ) ) break; // Rand count must be in [count, 255].
-				randCount = arg;
-				if( ptr != end ) break;
-			}
-			continue;
-		}
-		
-		// Check if this label is a valid Index label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Index ) == 0  )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_Index ) ];
-			const char * const		end = (const char *) labelNext;
-			
-			if( index > 0 ) break; // Index cannot be specified more than once.
-			
-			err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-			if( err || ( arg < 1 ) || ( arg > UINT32_MAX ) ) break; // Index must be in [1, 2^32 - 1].
-			index = arg;
-			if( ptr != end ) break;
-			continue;
-		}
-		
-		// Check if this label is a valid IPv4 label.
-		
-		if( strnicmpx( labelData, labelLen, kLabel_IPv4 ) == 0 )
-		{
-			// Valid names have at most one IPv4 or IPv6 label.
-			
-			if( flags & ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA ) ) break;
-			flags |= kDNSNameFlag_HasA;
-			continue;
-		}
-		
-		// Check if this label is a valid IPv6 label.
-		
-		if( strnicmpx( labelData, labelLen, kLabel_IPv6 ) == 0 )
-		{
-			// Valid names have at most one IPv4 or IPv6 label.
-			
-			if( flags & ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA ) ) break;
-			flags |= kDNSNameFlag_HasAAAA;
-			continue;
-		}
-		
-		// Check if this label is a valid tag label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Tag ) == 0  )
-		{
-			continue;
-		}
-		
-		// Check if this label is a valid RCode label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_RCode ) == 0  )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_RCode ) ];
-			const char * const		end = (const char *) labelNext;
-			const char *			src;
-			char *					dst;
-			const char *			lim;
-			char					argStr[ kDomainLabelLengthMax + 1 ];
-			
-			if( rcode >= 0 ) break; // RCode cannot be specified more than once.
-			
-			// First check if the RCode label's argument is an RCODE mnemonic, e.g., ServFail, Refused, etc.
-			// The argument part of a label consists of all of the characters up to the start of the next label.
-			// In order to treat the argument as a C string, the argument must not contain any NUL characters.
-			// For example, a malformed label such as "rcode-refused\x00garbage" has the argument "refused\x00garbage",
-			// but as a C string, the NUL character makes it "refused".
-			
-			src = ptr;
-			dst = argStr;
-			lim = &argStr[ countof( argStr ) - 1 ];
-			while( ( src < end ) && ( *src != '\0' ) && ( dst < lim ) ) *dst++ = *src++;
-			if( src == end )
-			{
-				*dst = '\0';
-				rcode = DNSRCodeFromString( argStr );
-			}
-			
-			// If we don't have a valid rcode yet, try to parse the argument as a decimal integer.
-			
-			if( rcode < 0 )
-			{
-				err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-				if( err || ( arg > 15 ) ) break; // RCode must be in [0, 15].
-				rcode = (int) arg;
-				if( ptr != end ) break;
-			}
-			continue;
-		}
-		
-		// Check if this label is a valid TTL label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_TTL ) == 0  )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_TTL ) ];
-			const char * const		end = (const char *) labelNext;
-			
-			if( ttl >= 0 ) break; // TTL cannot be specified more than once.
-			
-			err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-			if( err || ( arg > INT32_MAX ) ) break; // TTL must be in [0, 2^31 - 1].
-			ttl = (int32_t) arg;
-			if( ptr != end ) break;
-			continue;
-		}
-		
-		// Check if this label is a valid Offset label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Offset ) == 0 )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_Offset ) ];
-			const char * const		end = (const char *) labelNext;
-			
-			if( offset >= 0 ) break; // Offset cannot be specified more than once.
-			
-			err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-			if( err ) break;
-			offset = (int32_t) arg;
-			if( ptr != end ) break;
-			continue;
-		}
-		
-		// Check if this label is a valid PDelay label.
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_PDelay ) == 0 )
-		{
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_PDelay ) ];
-			const char * const		end = (const char *) labelNext;
-			
-			if( procDelayMs >= 0 ) break; // PDelay cannot be specified more than once.
-			
-			err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-			if( err || ( arg > 2000 ) ) break; // PDelay must be in [0, 2000].
-			procDelayMs = (int32_t) arg;
-			if( ptr != end ) break;
-			continue;
-		}
-		
-		// Check if this label is a valid CommandSuspend label.
-		
-		if( strnicmpx( labelData, labelLen, kLabel_CommandSuspend ) == 0 )
-		{
-			if( action != kDNSServerAction_None ) break; // A command cannot be specified more than once.
-			action = kDNSServerAction_Suspend;
-			continue;
-		}
-		
-		// Check if this label is a valid CommandResume label.
-		
-		if( strnicmpx( labelData, labelLen, kLabel_CommandResume ) == 0 )
-		{
-			if( action != kDNSServerAction_None ) break; // A command cannot be specified more than once.
-			action = kDNSServerAction_Resume;
-			continue;
-		}
-		
-		// If this and the remaining labels are equal to "d.test.", then the name exists.
-		// Otherwise, this label is invalid. In both cases, there are no more labels to check.
-		
-		if( _DNSServerNameIsDNSSECZone( label, &zoneParent, &zsk, &ksk, &parentZSK ) )
-		{
-			zone = label;
-			flags |= kDNSNameFlag_HasRRSIG;
-			if( ( label == inQName ) || ( isAlias && ( label == DomainNameGetNextLabel( inQName ) ) ) )
-			{
-				flags |= kDNSNameFlag_HasSOA;
-				flags |= kDNSNameFlag_HasDNSKEY;
-				flags |= kDNSNameFlag_HasDS;
-			}
-		}
-		else if( DomainNameEqual( label, me->domain ) )
-		{
-			zone = label;
-			if( ( label == inQName ) || ( isAlias && ( label == DomainNameGetNextLabel( inQName ) ) ) )
-			{
-				flags |= kDNSNameFlag_HasSOA;
-			}
-		}
-		break;
-	}
-	require_quiet( zone, exit );
-	
-	// If a Count value of 0 was specified, then the hostname has no A or AAAA records.
-	// Otherwise, if the hostname has no IPv4 or IPv6 labels, then it has both A and AAAA records.
-	
-	if( count == 0 )
-	{
-		flags &= ~( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA );
-	}
-	else if( !( flags & ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA ) ) )
-	{
-		flags |= ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA );
-	}
-	
-	// Allow IPv6-only hostnames to have a maximum address count of up to 511 instead of the normal 255.
-	
-	maxCount = ( ( flags & ( kDNSNameFlag_HasA | kDNSNameFlag_HasAAAA ) ) == kDNSNameFlag_HasAAAA ) ? 511 : 255;
-	require_action_quiet( count <= maxCount, exit, zone = NULL );
-	
-	if( outAliasCount )		*outAliasCount		= aliasCount;
-	if( outAliasTTLCount )	*outAliasTTLCount	= aliasTTLCount;
-	if( outCount )			*outCount			= ( count       >= 0 ) ? ( (uint32_t) count )       : 1;
-	if( outRandCount )		*outRandCount		= randCount;
-	if( outIndex )			*outIndex			= index;
-	if( outRCode )			*outRCode			= rcode;
-	if( outTTL )			*outTTL				= ( ttl         >= 0 ) ? ( (uint32_t) ttl )         : me->defaultTTL;
-	if( outOffset )			*outOffset			= ( offset      >= 0 ) ? ( (uint32_t) offset )      : 0;
-	if( outProcDelayMs )	*outProcDelayMs		= ( procDelayMs >= 0 ) ? ( (uint32_t) procDelayMs ) : 0;
-	if( outFlags )			*outFlags			= flags;
-	if( outZone )			*outZone			= zone;
-	if( outZoneParent )		*outZoneParent		= zoneParent;
-	if( outZSK )			*outZSK				= zsk;
-	if( outKSK )			*outKSK				= ksk;
-	if( outParentZSK )		*outParentZSK		= parentZSK;
-	if( outAction )			*outAction			= action;
-	
-exit:
-	return( zone ? true : false );
-}
-
-//===========================================================================================================================
-
-static Boolean
-	_DNSServerParseSRVName(
-		DNSServerRef		me,
-		const uint8_t *		inName,
-		const uint8_t **	outDomainPtr,
-		size_t *			outDomainLen,
-		ParsedSRV			outSRVArray[ kParsedSRVCountMax ],
-		size_t *			outSRVCount )
-{
-	OSStatus			err;
-	const uint8_t *		label;
-	const uint8_t *		domainPtr;
-	size_t				domainLen;
-	size_t				srvCount;
-	uint32_t			arg;
-	int					isNameValid = false;
-	
-	label = inName;
-	
-	// Ensure that first label, i.e, the service label, begins with a '_' character.
-	
-	require_quiet( ( label[ 0 ] > 0 ) && ( label[ 1 ] == '_' ), exit );
-	label = DomainNameGetNextLabel( label );
-	
-	// Ensure that the second label, i.e., the proto label, begins with a '_' character (usually _tcp or _udp).
-	
-	require_quiet( ( label[ 0 ] > 0 ) && ( label[ 1 ] == '_' ), exit );
-	label = DomainNameGetNextLabel( label );
-	
-	// Parse the domain name, if any.
-	
-	domainPtr = label;
-	while( *label )
-	{
-		if( DomainNameEqual( label, me->domain ) ||
-			( strnicmp_prefix( &label[ 1 ], label[ 0 ], kLabelPrefix_SRV ) == 0 ) ) break;
-		label = DomainNameGetNextLabel( label );
-	}
-	require_quiet( *label, exit );
-	
-	domainLen = (size_t)( label - domainPtr );
-	
-	// Parse SRV labels, if any.
-	
-	srvCount = 0;
-	while( strnicmp_prefix( &label[ 1 ], label[ 0 ], kLabelPrefix_SRV ) == 0 )
-	{
-		const uint8_t * const	nextLabel	= DomainNameGetNextLabel( label );
-		const char *			ptr			= (const char *) &label[ 1 + sizeof_string( kLabelPrefix_SRV ) ];
-		const char * const		end			= (const char *) nextLabel;
-		const uint8_t *			target;
-		unsigned int			priority, weight, port;
-		
-		err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-		require_quiet( !err && ( arg <= UINT16_MAX ), exit );
-		priority = (unsigned int) arg;
-		
-		require_quiet( ( ptr < end ) && ( *ptr == '-' ), exit );
-		++ptr;
-		
-		err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-		require_quiet( !err && ( arg <= UINT16_MAX ), exit );
-		weight = (unsigned int) arg;
-		
-		require_quiet( ( ptr < end ) && ( *ptr == '-' ), exit );
-		++ptr;
-		
-		err = DecimalTextToUInt32( ptr, end, &arg, &ptr );
-		require_quiet( !err && ( arg <= UINT16_MAX ), exit );
-		port = (unsigned int) arg;
-		
-		require_quiet( ptr == end, exit );
-		
-		target = nextLabel;
-		for( label = nextLabel; *label; label = DomainNameGetNextLabel( label ) )
-		{
-			if( DomainNameEqual( label, me->domain ) ||
-				( strnicmp_prefix( &label[ 1 ], label[ 0 ], kLabelPrefix_SRV ) == 0 ) ) break;
-		}
-		require_quiet( *label, exit );
-		
-		if( outSRVArray )
-		{
-			outSRVArray[ srvCount ].priority	= (uint16_t) priority;
-			outSRVArray[ srvCount ].weight		= (uint16_t) weight;
-			outSRVArray[ srvCount ].port		= (uint16_t) port;
-			outSRVArray[ srvCount ].targetPtr	= target;
-			outSRVArray[ srvCount ].targetLen	= (uint16_t)( label - target );
-		}
-		++srvCount;
-	}
-	require_quiet( DomainNameEqual( label, me->domain ), exit );
-	isNameValid = true;
-	
-	if( outDomainPtr )	*outDomainPtr	= domainPtr;
-	if( outDomainLen )	*outDomainLen	= domainLen;
-	if( outSRVCount )	*outSRVCount	= srvCount;
-	
-exit:
-	return( isNameValid ? true : false );
-}
-
-//===========================================================================================================================
-
-static Boolean	_DNSServerParseReverseIPv4Name( DNSServerRef me, const uint8_t *inQName, unsigned int *outHostID )
-{
-	OSStatus			err;
-	const uint8_t *		label;
-	size_t				labelLen;
-	const uint8_t *		labelData;
-    const uint8_t *		labelNext;
-	const uint8_t *		ptr;
-	uint32_t			hostID;
-	int					isNameValid = false;
-	
-	Unused( me );
-	
-	label		= inQName;
-	labelLen	= *label;
-	require_quiet( labelLen > 0, exit );
-	
-	labelData = &label[ 1 ];
-	labelNext = &labelData[ labelLen ];
-	err = DecimalTextToUInt32( (const char *) labelData, (const char *) labelNext, &hostID, (const char **) &ptr );
-	require_noerr_quiet( err, exit );
-	require_quiet( ( hostID >= 1 ) && ( hostID <= 255 ), exit );
-	require_quiet( ptr == labelNext, exit );
-	
-	require_quiet( DomainNameEqual( labelNext, kDNSServerReverseIPv4DomainName ), exit );
-	isNameValid = true;
-	
-	if( outHostID ) *outHostID = (unsigned int) hostID;
-	
-exit:
-	return( isNameValid ? true : false );
-}
-
-//===========================================================================================================================
-
-static Boolean	_DNSServerParseReverseIPv6Name( DNSServerRef me, const uint8_t *inQName, unsigned int *outHostID )
-{
-	const uint8_t *		label;
-	unsigned int		hostID;
-	int					i;
-	int					isNameValid = false;
-	
-	Unused( me );
-	
-	hostID	= 0;
-	label	= inQName;
-	for( i = 0; i < 2; ++i )
-	{
-		unsigned int		labelLen, c;
-		
-		labelLen = label[ 0 ];
-		require_quiet( labelLen == 1, exit );
-		
-		c = label[ 1 ];
-		require_quiet( isxdigit_safe( c ), exit );
-		
-		hostID = hostID | ( HexCharToValue( c ) << ( 4 * i ) );
-		label = &label[ 1 + labelLen ];
-	}
-	require_quiet( ( hostID >= 1 ) && ( hostID <= 255 ), exit );
-	require_quiet( DomainNameEqual( label, kDNSServerReverseIPv6DomainName ), exit );
-	isNameValid = true;
-	
-	if( outHostID ) *outHostID = hostID;
-	
-exit:
-	return( isNameValid ? true : false );
-}
-
-#if( DEBUG )
-//===========================================================================================================================
-
-static void
-	_DNSServerSigCheck(
-		const uint8_t *	inOwner,
-		int				inTypeCovered,
-		const void *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inSignaturePtr,
-		const size_t	inSignatureLen,
-		DNSKeyInfoRef	inKeyInfo )
-{
-	if( !DNSKeyInfoVerify( inKeyInfo, inMsgPtr, inMsgLen, inSignaturePtr, inSignatureLen ) )
-	{
-		const char *		typeStr;
-		char				typeBuf[ 16 ];
-		
-		typeStr = DNSRecordTypeValueToString( inTypeCovered );
-		if( !typeStr )
-		{
-			SNPrintF( typeBuf, sizeof( typeBuf ), "TYPE%d", inTypeCovered );
-			typeStr = typeBuf;
-		}
-		ds_ulog( kLogLevelError,
-			"Signature for %{du:dname} %s is invalid! -- algorithm: %s (%d), public key: '%H'\n",
-			inOwner, typeStr, DNSKeyInfoGetAlgorithmDescription( inKeyInfo ), DNSKeyInfoGetAlgorithm( inKeyInfo ),
-			DNSKeyInfoGetPubKeyPtr( inKeyInfo ), DNSKeyInfoGetPubKeyLen( inKeyInfo ), SIZE_MAX );
-	}
-}
-#endif
-
-//===========================================================================================================================
-
-#define kDNSServerDefaultDNSSECAlgorithm		14	// TODO: Think about adding an option for the default algorithm.
-
-static Boolean
-	_DNSServerNameIsDNSSECZone(
-		const uint8_t *		inName,
-		const uint8_t **	outZoneParent,
-		DNSKeyInfoRef *		outZSK,
-		DNSKeyInfoRef *		outKSK,
-		DNSKeyInfoRef *		outParentZSK )
-{
-	const uint8_t *		label;
-	size_t				labelLen;
-	const uint8_t *		labelNext;
-	const uint8_t *		zoneParent			= NULL;
-	DNSKeyInfoRef		zsk;
-	DNSKeyInfoRef		ksk;
-	DNSKeyInfoRef		parentZSK;
-	uint32_t			zoneAlgorithm		= 0;
-	uint32_t			zoneIndex			= 0;
-	uint32_t			zoneParentAlgorithm	= 0;
-	uint32_t			zoneParentIndex		= 0;
-	Boolean				parsedAllLabels		= false;
-	Boolean				nameIsValid			= false;
-	
-	for( label = inName; ( labelLen = *label ) != 0; label = labelNext )
-	{
-		const uint8_t *		labelData;
-		
-		if( labelLen > kDomainLabelLengthMax ) break;
-		labelData = &label[ 1 ];
-		labelNext = &labelData[ labelLen ];
-		
-		if( strnicmp_prefix( labelData, labelLen, kLabelPrefix_Zone ) == 0  )
-		{
-			OSStatus				err;
-			const char *			ptr = (const char *) &labelData[ sizeof_string( kLabelPrefix_Zone ) ];
-			const char * const		end = (const char *) labelNext;
-			uint32_t				algorithm;
-			uint32_t				index;
-			
-			err = DecimalTextToUInt32( ptr, end, &algorithm, &ptr );
-			if( err ) break;
-			if( ( ptr >= end ) || ( *ptr++ != '-' ) ) break;
-			
-			err = DecimalTextToUInt32( ptr, end, &index, &ptr );
-			if( err || ( index < kZoneLabelIndexArgMin ) || ( index > kZoneLabelIndexArgMax ) ) break;
-			if( ptr != end ) break;
-			if( zoneIndex == 0 )
-			{
-				zoneAlgorithm	= algorithm;
-				zoneIndex		= index;
-			}
-			else if( zoneParentIndex == 0 )
-			{
-				zoneParentAlgorithm	= algorithm;
-				zoneParent			= label;
-				zoneParentIndex		= index;
-			}
-			continue;
-		}
-		if( DomainNameEqual( label, kDNSServerDomain_DNSSEC ) )
-		{
-			if( !zoneParent ) zoneParent = label;
-			parsedAllLabels = true;
-		}
-		break;
-	}
-	require_quiet( parsedAllLabels, exit );
-	
-	if( zoneAlgorithm == 0 ) zoneAlgorithm = kDNSServerDefaultDNSSECAlgorithm;
-	zsk = GetDNSKeyInfoZSK( zoneAlgorithm, zoneIndex );
-	require_quiet( zsk, exit );
-	
-	ksk = GetDNSKeyInfoKSK( zoneAlgorithm, zoneIndex );
-	require_quiet( ksk, exit );
-	
-	if( zoneParentAlgorithm == 0 ) zoneParentAlgorithm = kDNSServerDefaultDNSSECAlgorithm;
-	parentZSK = GetDNSKeyInfoZSK( zoneParentAlgorithm, zoneParentIndex );
-	require_quiet( parentZSK, exit );
-	
-	if( outZoneParent )	*outZoneParent	= zoneParent;
-	if( outZSK )		*outZSK			= zsk;
-	if( outKSK )		*outKSK			= ksk;
-	if( outParentZSK )	*outParentZSK	= parentZSK;
-	nameIsValid = true;
-	
-exit:
-	return( nameIsValid );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSServerConnectionCreate(
-		DNSServerRef				inServer,
-		const struct sockaddr *		inLocal,
-		const struct sockaddr *		inRemote,
-		size_t						inIndex,
-		DNSServerConnectionRef *	outCnx )
-{
-	OSStatus					err;
-	DNSServerConnectionRef		obj;
-	
-	CF_OBJECT_CREATE( DNSServerConnection, obj, err, exit );
-	
-	obj->index	= inIndex;
-	obj->server	= inServer;
-	CFRetain( obj->server );
-	SockAddrCopy( inLocal, &obj->local );
-	SockAddrCopy( inRemote, &obj->remote );
-	
-	*outCnx = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionFinalize( CFTypeRef inObj )
-{
-	const DNSServerConnectionRef		me = (DNSServerConnectionRef) inObj;
-	
-	check( !me->readSource );
-	check( !me->writeSource );
-	ForgetCF( &me->server );
-	ForgetMem( &me->msgPtr );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSServerConnectionStart( DNSServerConnectionRef me, SocketRef inSock )
-{
-	OSStatus			err;
-	SocketContext *		sockCtx = NULL;
-	
-	err = SocketMakeNonBlocking( inSock );
-	require_noerr( err, exit );
-	
-#if( defined( SO_NOSIGPIPE ) )
-	setsockopt( inSock, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, (socklen_t) sizeof( int ) );
-#endif
-	me->readSource = dispatch_source_create( DISPATCH_SOURCE_TYPE_READ, (uintptr_t) inSock, 0, me->server->queue );
-	require_action( me->readSource, exit, err = kNoResourcesErr );
-	me->readSuspended = true;
-	
-	me->writeSource = dispatch_source_create( DISPATCH_SOURCE_TYPE_WRITE, (uintptr_t) inSock, 0, me->server->queue );
-	require_action( me->writeSource, exit, err = kNoResourcesErr );
-	me->writeSuspended = true;
-	
-	sockCtx = SocketContextCreateEx( inSock, me, SocketContextFinalizerCF, &err );
-	require_noerr( err, exit );
-	CFRetain( me );
-	
-	SocketContextRetain( sockCtx );
-	dispatch_set_context( me->readSource, sockCtx );
-	dispatch_source_set_event_handler_f( me->readSource, _DNSServerConnectionReadHandler );
-	dispatch_source_set_cancel_handler_f( me->readSource, SocketContextCancelHandler );
-	dispatch_resume_if_suspended( me->readSource, &me->readSuspended );
-	
-	SocketContextRetain( sockCtx );
-	dispatch_set_context( me->writeSource, sockCtx );
-	dispatch_source_set_event_handler_f( me->writeSource, _DNSServerConnectionWriteHandler );
-	dispatch_source_set_cancel_handler_f( me->writeSource, SocketContextCancelHandler );
-	
-	_DNSServerConnectionRenewExpiration( me );
-	
-exit:
-	if( sockCtx ) SocketContextRelease( sockCtx );
-	if( err ) _DNSServerConnectionStop( me, true );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionStop( DNSServerConnectionRef me, Boolean inRemoveFromList )
-{
-	dispatch_source_forget_ex( &me->readSource, &me->readSuspended );
-	dispatch_source_forget_ex( &me->writeSource, &me->writeSuspended );
-	if( inRemoveFromList )
-	{
-		DNSServerConnectionRef *		ptr;
-		
-		ptr = &me->server->connectionList;
-		while( *ptr && ( *ptr != me ) ) ptr = &( *ptr )->next;
-		if( *ptr )
-		{
-			*ptr = me->next;
-			me->next = NULL;
-			CFRelease( me );
-		}
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionReadHandler( void *inContext )
-{
-	OSStatus							err;
-	const SocketContext * const			sockCtx	= (SocketContext *) inContext;
-	const DNSServerConnectionRef		me		= (DNSServerConnectionRef) sockCtx->userContext;
-	uint8_t *							respPtr	= NULL;	// malloc'd
-	size_t								respLen;
-	
-	// Receive message length.
-	
-	if( !me->haveLen )
-	{
-		err = SocketReadData( sockCtx->sock, me->lenBuf, sizeof( me->lenBuf ), &me->offset );
-		if( ( err == EWOULDBLOCK ) || ( err == kConnectionErr ) ) goto exit;
-		require_noerr( err, exit );
-		
-		me->haveLen	= true;
-		me->offset	= 0;
-		me->msgLen	= ReadBig16( me->lenBuf );
-		if( me->msgLen < kDNSHeaderLength )
-		{
-			ds_ulog( kLogLevelInfo, "TCP: Message length of %zu bytes from %##a to %##a is too small (< %d bytes)\n",
-				me->msgLen, &me->remote, &me->local, kDNSHeaderLength );
-			err = kSizeErr;
-			goto exit;
-		}
-		me->msgPtr = malloc( me->msgLen );
-		require_action( me->msgPtr, exit, err = kNoMemoryErr );
-	}
-	
-	// Receive message.
-	
-	err = SocketReadData( sockCtx->sock, me->msgPtr, me->msgLen, &me->offset );
-	if( ( err == EWOULDBLOCK ) || ( err == kConnectionErr ) ) goto exit;
-	require_noerr( err, exit );
-	dispatch_suspend_if_resumed( me->readSource, &me->readSuspended );
-	me->offset	= 0;
-	me->haveLen	= false;
-	
-	ds_ulog( kLogLevelInfo, "TCP: Received %zu bytes from %##a to %##a -- %.1{du:dnsmsg}\n",
-		me->msgLen, &me->remote, &me->local, me->msgPtr, me->msgLen );
-	
-	// Create response.
-	
-	err = _DNSServerAnswerQueryForTCP( me->server, me->msgPtr, me->msgLen, me->index + 1, &respPtr, &respLen );
-	if( err == kSkipErr ) ds_ulog( kLogLevelInfo, "TCP: Ignoring query\n" );
-	require_noerr_quiet( err, exit );
-	
-	_DNSServerConnectionRenewExpiration( me );
-	
-	// Prepare to send response.
-	
-	FreeNullSafe( me->msgPtr );
-	me->msgPtr = respPtr;
-	me->msgLen = respLen;
-	respPtr = NULL;
-	
-	ds_ulog( kLogLevelInfo, "TCP: Sending %zu byte response from %##a to %##a -- %.1{du:dnsmsg}\n",
-		me->msgLen, &me->local, &me->remote, me->msgPtr, me->msgLen );
-	
-	check( me->msgLen <= UINT16_MAX );
-	WriteBig16Typed( me->lenBuf, (uint16_t) me->msgLen );
-	me->iov[ 0 ].iov_base	= me->lenBuf;
-	me->iov[ 0 ].iov_len	= sizeof( me->lenBuf );
-	me->iov[ 1 ].iov_base	= me->msgPtr;
-	me->iov[ 1 ].iov_len	= me->msgLen;
-	me->iovPtr				= me->iov;
-	me->iovCount			= 2;
-	dispatch_resume_if_suspended( me->writeSource, &me->writeSuspended );
-	
-exit:
-	FreeNullSafe( respPtr );
-	if( err && ( err != EWOULDBLOCK ) )
-	{
-		_DNSServerConnectionStop( me, true );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionWriteHandler( void *inContext )
-{
-	OSStatus							err;
-	const SocketContext * const			sockCtx	= (SocketContext *) inContext;
-	const DNSServerConnectionRef		me		= (DNSServerConnectionRef) sockCtx->userContext;
-	
-	err = SocketWriteData( sockCtx->sock, &me->iovPtr, &me->iovCount );
-	if( !err )
-	{
-		me->iovPtr		= NULL;
-		me->iovCount	= 0;
-		memset( me->iov, 0, sizeof( me->iov ) );
-		ForgetPtrLen( &me->msgPtr, &me->msgLen );
-		dispatch_suspend_if_resumed( me->writeSource, &me->writeSuspended );
-		dispatch_resume_if_suspended( me->readSource, &me->readSuspended );
-	}
-	else if( err != EWOULDBLOCK )
-	{
-		_DNSServerConnectionStop( me, true );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSServerConnectionRenewExpiration( DNSServerConnectionRef me )
-{
-	me->expirationTicks = UpTicks() + SecondsToUpTicks( kDNSServerConnectionExpirationTimeSecs );
-}
-
-//===========================================================================================================================
-//	MDNSReplierCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	uint8_t *				hostname;			// Used as the base name for hostnames and service names.
-	uint8_t *				serviceLabel;		// Label containing the base service name.
-	unsigned int			maxInstanceCount;	// Maximum number of service instances and hostnames.
-	uint64_t *				bitmaps;			// Array of 64-bit bitmaps for keeping track of needed responses.
-	size_t					bitmapCount;		// Number of 64-bit bitmaps.
-	dispatch_source_t		readSourceV4;		// Read dispatch source for IPv4 socket.
-	dispatch_source_t		readSourceV6;		// Read dispatch source for IPv6 socket.
-	uint32_t				ifIndex;			// Index of the interface to run on.
-	unsigned int			recordCountA;		// Number of A records per hostname.
-	unsigned int			recordCountAAAA;	// Number of AAAA records per hostname.
-	unsigned int			maxDropCount;		// If > 0, the drop rates apply to only the first <maxDropCount> responses.
-	double					ucastDropRate;		// Probability of dropping a unicast response.
-	double					mcastDropRate;		// Probability of dropping a multicast query or response.
-	uint8_t *				dropCounters;		// If maxDropCount > 0, array of <maxInstanceCount> response drop counters.
-	Boolean					noAdditionals;		// True if responses are to not include additional records.
-	Boolean					useIPv4;			// True if the replier is to use IPv4.
-	Boolean					useIPv6;			// True if the replier is to use IPv6.
-	uint8_t					msgBuf[ kMDNSMessageSizeMax ];	// Buffer for received mDNS message.
-#if( TARGET_OS_DARWIN )
-	dispatch_source_t		processMonitor;		// Process monitor source for process being followed, if any.
-	pid_t					followPID;			// PID of process being followed, if any. (If it exits, we exit).
-#endif
-	
-}	MDNSReplierContext;
-
-typedef struct MRResourceRecord		MRResourceRecord;
-struct MRResourceRecord
-{
-	MRResourceRecord *		next;		// Next item in list.
-	uint8_t *				name;		// Resource record name.
-	uint16_t				type;		// Resource record type.
-	uint16_t				class;		// Resource record class.
-	uint32_t				ttl;		// Resource record TTL.
-	uint16_t				rdlength;	// Resource record data length.
-	uint8_t *				rdata;		// Resource record data.
-	const uint8_t *			target;		// For SRV records, pointer to target in RDATA.
-};
-
-typedef struct MRNameOffsetItem		MRNameOffsetItem;
-struct MRNameOffsetItem
-{
-	MRNameOffsetItem *	next;		// Next item in list.
-	uint16_t			offset;		// Offset of domain name in response message.
-	uint8_t				name[ 1 ];	// Variable-length array for domain name.
-};
-
-#if( TARGET_OS_DARWIN )
-static void		_MDNSReplierFollowedProcessHandler( void *inContext );
-#endif
-static void		_MDNSReplierReadHandler( void *inContext );
-static OSStatus
-	_MDNSReplierAnswerQuery(
-		MDNSReplierContext *	inContext,
-		const uint8_t *			inQueryPtr,
-		size_t					inQueryLen,
-		sockaddr_ip *			inSender,
-		SocketRef				inSock,
-		unsigned int			inIndex );
-static OSStatus
-	_MDNSReplierAnswerListAdd(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord **		inAnswerList,
-		unsigned int			inIndex,
-		const uint8_t *			inName,
-		unsigned int			inType,
-		unsigned int			inClass );
-static void
-	_MDNSReplierAnswerListRemovePTR(
-		MRResourceRecord **	inAnswerListPtr,
-		const uint8_t *		inName,
-		const uint8_t *		inRData );
-static OSStatus
-	_MDNSReplierSendOrDropResponse(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord *		inAnswerList,
-		sockaddr_ip *			inQuerier,
-		SocketRef				inSock,
-		unsigned int			inIndex,
-		Boolean					inUnicast );
-static OSStatus
-	_MDNSReplierCreateResponse(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord *		inAnswerList,
-		unsigned int			inIndex,
-		uint8_t **				outResponsePtr,
-		size_t *				outResponseLen );
-static OSStatus
-	_MDNSReplierAppendNameToResponse(
-		DataBuffer *		inResponse,
-		const uint8_t *		inName,
-		MRNameOffsetItem **	inNameOffsetListPtr );
-static Boolean
-	_MDNSReplierServiceTypeMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outTXTSize,
-		unsigned int *				outCount );
-static Boolean
-	_MDNSReplierServiceInstanceNameMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outIndex,
-		unsigned int *				outTXTSize,
-		unsigned int *				outCount );
-static Boolean	_MDNSReplierAboutRecordNameMatch( const MDNSReplierContext *inContext, const uint8_t *inName );
-static Boolean
-	_MDNSReplierHostnameMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outIndex );
-static OSStatus	_MDNSReplierCreateTXTRecord( const uint8_t *inRecordName, size_t inSize, uint8_t **outTXT );
-static OSStatus
-	_MRResourceRecordCreate(
-		uint8_t *			inName,
-		uint16_t			inType,
-		uint16_t			inClass,
-		uint32_t			inTTL,
-		uint16_t			inRDLength,
-		uint8_t *			inRData,
-		MRResourceRecord **	outRecord );
-static void		_MRResourceRecordFree( MRResourceRecord *inRecord );
-static void		_MRResourceRecordFreeList( MRResourceRecord *inList );
-static OSStatus	_MRNameOffsetItemCreate( const uint8_t *inName, uint16_t inOffset, MRNameOffsetItem **outItem );
-static void		_MRNameOffsetItemFree( MRNameOffsetItem *inItem );
-static void		_MRNameOffsetItemFreeList( MRNameOffsetItem *inList );
-
-ulog_define_ex( kDNSSDUtilIdentifier, MDNSReplier, kLogLevelInfo, kLogFlags_None, "MDNSReplier", NULL );
-#define mr_ulog( LEVEL, ... )		ulog( &log_category_from_name( MDNSReplier ), (LEVEL), __VA_ARGS__ )
-
-static void	MDNSReplierCmd( void )
-{
-	OSStatus					err;
-	MDNSReplierContext *		context;
-	SocketRef					sockV4	= kInvalidSocketRef;
-	SocketRef					sockV6	= kInvalidSocketRef;
-	const char *				ifname;
-	size_t						len;
-	uint8_t						name[ 1 + kDomainLabelLengthMax + 1 ];
-	char						ifnameBuf[ IF_NAMESIZE + 1 ];
-	
-	err = CheckIntegerArgument( gMDNSReplier_MaxInstanceCount, "max instance count", 1, UINT16_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSReplier_RecordCountA, "A record count", 0, 255 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSReplier_RecordCountAAAA, "AAAA record count", 0, 255 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckDoubleArgument( gMDNSReplier_UnicastDropRate, "unicast drop rate", 0.0, 1.0 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckDoubleArgument( gMDNSReplier_MulticastDropRate, "multicast drop rate", 0.0, 1.0 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSReplier_MaxDropCount, "drop count", 0, 255 );
-	require_noerr_quiet( err, exit );
-	
-	if( gMDNSReplier_Foreground )
-	{
-		LogControl( "MDNSReplier:output=file;stdout,MDNSReplier:flags=time;prefix" );
-	}
-	
-	context = (MDNSReplierContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->maxInstanceCount	= (unsigned int) gMDNSReplier_MaxInstanceCount;
-	context->recordCountA		= (unsigned int) gMDNSReplier_RecordCountA;
-	context->recordCountAAAA	= (unsigned int) gMDNSReplier_RecordCountAAAA;
-	context->maxDropCount		= (unsigned int) gMDNSReplier_MaxDropCount;
-	context->ucastDropRate		= gMDNSReplier_UnicastDropRate;
-	context->mcastDropRate		= gMDNSReplier_MulticastDropRate;
-	context->noAdditionals		= gMDNSReplier_NoAdditionals ? true : false;
-	context->useIPv4			= ( gMDNSReplier_UseIPv4 || !gMDNSReplier_UseIPv6 ) ? true : false;
-	context->useIPv6			= ( gMDNSReplier_UseIPv6 || !gMDNSReplier_UseIPv4 ) ? true : false;
-	context->bitmapCount		= ( context->maxInstanceCount + 63 ) / 64;
-	
-#if( TARGET_OS_DARWIN )
-	if( gMDNSReplier_FollowPID )
-	{
-		context->followPID = _StringToPID( gMDNSReplier_FollowPID, &err );
-		if( err || ( context->followPID < 0 ) )
-		{
-			FPrintF( stderr, "error: Invalid follow PID: %s\n", gMDNSReplier_FollowPID );
-			goto exit;
-		}
-		
-		err = DispatchProcessMonitorCreate( context->followPID, DISPATCH_PROC_EXIT, dispatch_get_main_queue(),
-			_MDNSReplierFollowedProcessHandler, NULL, context, &context->processMonitor );
-		require_noerr( err, exit );
-		dispatch_resume( context->processMonitor );
-	}
-	else
-	{
-		context->followPID = -1;
-	}
-#endif
-	
-	if( context->maxDropCount > 0 )
-	{
-		context->dropCounters = (uint8_t *) calloc( context->maxInstanceCount, sizeof( *context->dropCounters ) );
-		require_action( context->dropCounters, exit, err = kNoMemoryErr );
-	}
-	
-	context->bitmaps = (uint64_t *) calloc( context->bitmapCount, sizeof( *context->bitmaps ) );
-	require_action( context->bitmaps, exit, err = kNoMemoryErr );
-	
-	// Create the base hostname label.
-	
-	len = strlen( gMDNSReplier_Hostname );
-	if( context->maxInstanceCount > 1 )
-	{
-		unsigned int		maxInstanceCount, digitCount;
-		
-		// When there's more than one instance, extra bytes are needed to append " (<instance index>)" or
-		// "-<instance index>" to the base hostname.
-		
-		maxInstanceCount = context->maxInstanceCount;
-		for( digitCount = 0; maxInstanceCount > 0; ++digitCount ) maxInstanceCount /= 10;
-		len += ( 3 + digitCount );
-	}
-	
-	if( len <= kDomainLabelLengthMax )
-	{
-		uint8_t *		dst = &name[ 1 ];
-		uint8_t *		lim = &name[ countof( name ) ];
-		
-		SNPrintF_Add( (char **) &dst, (char *) lim, "%s", gMDNSReplier_Hostname );
-		name[ 0 ] = (uint8_t)( dst - &name[ 1 ] );
-		
-		err = DomainNameDupLower( name, &context->hostname, NULL );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Base name \"%s\" is too long for max instance count of %u.\n",
-			gMDNSReplier_Hostname, context->maxInstanceCount );
-		goto exit;
-	}
-	
-	// Create the service label.
-	
-	len = strlen( gMDNSReplier_ServiceTypeTag ) + 3;	// We need three extra bytes for the service type prefix "_t-".
-	if( len <= kDomainLabelLengthMax )
-	{
-		uint8_t *		dst = &name[ 1 ];
-		uint8_t *		lim = &name[ countof( name ) ];
-		
-		SNPrintF_Add( (char **) &dst, (char *) lim, "_t-%s", gMDNSReplier_ServiceTypeTag );
-		name[ 0 ] = (uint8_t)( dst - &name[ 1 ] );
-		
-		err = DomainNameDupLower( name, &context->serviceLabel, NULL );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Service type tag is too long.\n" );
-		goto exit;
-	}
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	ifname = if_indextoname( context->ifIndex, ifnameBuf );
-	require_action( ifname, exit, err = kNameErr );
-	
-	// Set up IPv4 socket.
-	
-	if( context->useIPv4 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV4(), kMDNSPort, ifname, context->ifIndex, true, NULL, &sockV4 );
-		require_noerr( err, exit );
-	}
-	
-	// Set up IPv6 socket.
-	
-	if( context->useIPv6 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV6(), kMDNSPort, ifname, context->ifIndex, true, NULL, &sockV6 );
-		require_noerr( err, exit );
-	}
-	
-	// Create dispatch read sources for socket(s).
-	
-	if( IsValidSocket( sockV4 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV4, context, &err );
-		require_noerr( err, exit );
-		sockV4 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, _MDNSReplierReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV4 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV4 );
-	}
-	
-	if( IsValidSocket( sockV6 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV6, context, &err );
-		require_noerr( err, exit );
-		sockV6 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, _MDNSReplierReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV6 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV6 );
-	}
-	
-	dispatch_main();
-	
-exit:
-	ForgetSocket( &sockV4 );
-	ForgetSocket( &sockV6 );
-	exit( 1 );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	_MDNSReplierFollowedProcessHandler
-//===========================================================================================================================
-
-static void	_MDNSReplierFollowedProcessHandler( void *inContext )
-{
-	MDNSReplierContext * const		context = (MDNSReplierContext *) inContext;
-	
-	if( dispatch_source_get_data( context->processMonitor ) & DISPATCH_PROC_EXIT )
-	{
-		mr_ulog( kLogLevelNotice, "Exiting: followed process (%lld) exited.\n", (int64_t) context->followPID );
-		exit( 0 );
-	}
-}
-#endif
-
-//===========================================================================================================================
-//	_MDNSReplierReadHandler
-//===========================================================================================================================
-
-#define ShouldDrop( P )		( ( (P) > 0.0 ) && ( ( (P) >= 1.0 ) || RandomlyTrue( P ) ) )
-
-static void	_MDNSReplierReadHandler( void *inContext )
-{
-	OSStatus						err;
-	SocketContext * const			sockCtx = (SocketContext *) inContext;
-	MDNSReplierContext * const		context = (MDNSReplierContext *) sockCtx->userContext;
-	size_t							msgLen;
-	sockaddr_ip						sender;
-	const DNSHeader *				hdr;
-	unsigned int					flags, questionCount, i, j;
-	const uint8_t *					ptr;
-	int								drop, isMetaQuery;
-	
-	err = SocketRecvFrom( sockCtx->sock, context->msgBuf, sizeof( context->msgBuf ), &msgLen, &sender, sizeof( sender ),
-		NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	
-	if( msgLen < kDNSHeaderLength )
-	{
-		mr_ulog( kLogLevelInfo, "Message is too small (%zu < %d).\n", msgLen, kDNSHeaderLength );
-		goto exit;
-	}
-	
-	// Perform header field checks.
-	// The message ID and most flag bits are silently ignored (see <https://tools.ietf.org/html/rfc6762#section-18>).
-	
-	hdr = (DNSHeader *) context->msgBuf;
-	flags = DNSHeaderGetFlags( hdr );
-	require_quiet( ( flags & kDNSHeaderFlag_Response ) == 0, exit );		// Reject responses.
-	require_quiet( DNSFlagsGetOpCode( flags ) == kDNSOpCode_Query, exit );	// Reject opcodes other than standard query.
-	require_quiet( DNSFlagsGetRCode( flags )  == kDNSRCode_NoError, exit );	// Reject non-zero rcodes.
-	
-	drop = ( !context->maxDropCount && ShouldDrop( context->mcastDropRate ) ) ? true : false;
-	
-	mr_ulog( kLogLevelInfo, "Received %zu byte message from %##a%?s -- %#.1{du:dnsmsg}\n",
-		msgLen, &sender, drop, " (dropping)", context->msgBuf, msgLen );
-	
-	// Based on the QNAMEs in the query message, determine from which sets of records we may possibly need answers.
-	
-	questionCount = DNSHeaderGetQuestionCount( hdr );
-	require_quiet( questionCount > 0, exit );
-	
-	memset( context->bitmaps, 0, context->bitmapCount * sizeof_element( context->bitmaps ) );
-	
-	isMetaQuery = false;
-	ptr = (const uint8_t *) &hdr[ 1 ];
-	for( i = 0; i < questionCount; ++i )
-	{
-		unsigned int		count, index;
-		uint16_t			qtype, qclass;
-		uint8_t				qname[ kDomainNameLengthMax ];
-		
-		err = DNSMessageExtractQuestion( context->msgBuf, msgLen, ptr, qname, &qtype, &qclass, &ptr );
-		require_noerr_quiet( err, exit );
-		
-		if( ( qclass & ~kMDNSClassUnicastResponseBit ) != kDNSServiceClass_IN ) continue;
-		
-		if( _MDNSReplierHostnameMatch( context, qname, &index ) ||
-			_MDNSReplierServiceInstanceNameMatch( context, qname, &index, NULL, NULL ) )
-		{
-			if( ( index >= 1 ) && ( index <= context->maxInstanceCount ) )
-			{
-				context->bitmaps[ ( index - 1 ) / 64 ] |= ( UINT64_C( 1 ) << ( ( index - 1 ) % 64 ) );
-			}
-		}
-		else if( _MDNSReplierServiceTypeMatch( context, qname, NULL, &count ) )
-		{
-			if( ( count >= 1 ) && ( count <= context->maxInstanceCount ) )
-			{
-				for( j = 0; j < (unsigned int) context->bitmapCount; ++j )
-				{
-					if( count < 64 )
-					{
-						context->bitmaps[ j ] |= ( ( UINT64_C( 1 ) << count ) - 1 );
-						break;
-					}
-					else
-					{
-						context->bitmaps[ j ] = ~UINT64_C( 0 );
-						count -= 64;
-					}
-				}
-			}
-		}
-		else if( _MDNSReplierAboutRecordNameMatch( context, qname ) )
-		{
-			isMetaQuery = true;
-		}
-	}
-	
-	// Attempt to answer the query message using selected record sets.
-	
-	if( isMetaQuery )
-	{
-		err = _MDNSReplierAnswerQuery( context, context->msgBuf, msgLen, &sender, sockCtx->sock, 0 );
-		check_noerr( err );
-	}
-	if( drop ) goto exit;
-	
-	for( i = 0; i < context->bitmapCount; ++i )
-	{
-		for( j = 0; ( context->bitmaps[ i ] != 0 ) && ( j < 64 ); ++j )
-		{
-			const uint64_t		bitmask = UINT64_C( 1 ) << j;
-			
-			if( context->bitmaps[ i ] & bitmask )
-			{
-				context->bitmaps[ i ] &= ~bitmask;
-				
-				err = _MDNSReplierAnswerQuery( context, context->msgBuf, msgLen, &sender, sockCtx->sock,
-					( i * 64 ) + j + 1 );
-				check_noerr( err );
-			}
-		}
-	}
-	
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	_MDNSReplierAnswerQuery
-//===========================================================================================================================
-
-static OSStatus
-	_MDNSReplierAnswerQuery(
-		MDNSReplierContext *	inContext,
-		const uint8_t *			inQueryPtr,
-		size_t					inQueryLen,
-		sockaddr_ip *			inSender,
-		SocketRef				inSock,
-		unsigned int			inIndex )
-{
-	OSStatus				err;
-	const DNSHeader *		hdr;
-	const uint8_t *			ptr;
-	unsigned int			questionCount, answerCount, i;
-	MRResourceRecord *		ucastAnswerList = NULL;
-	MRResourceRecord *		mcastAnswerList = NULL;
-	
-	require_action( inIndex <= inContext->maxInstanceCount, exit, err = kRangeErr );
-	
-	// Get answers for questions.
-	
-	check( inQueryLen >= kDNSHeaderLength );
-	hdr = (const DNSHeader *) inQueryPtr;
-	questionCount = DNSHeaderGetQuestionCount( hdr );
-	
-	ptr = (const uint8_t *) &hdr[ 1 ];
-	for( i = 0; i < questionCount; ++i )
-	{
-		MRResourceRecord **		answerListPtr;
-		uint16_t				qtype, qclass;
-		uint8_t					qname[ kDomainNameLengthMax ];
-		
-		err = DNSMessageExtractQuestion( inQueryPtr, inQueryLen, ptr, qname, &qtype, &qclass, &ptr );
-		require_noerr_quiet( err, exit );
-		
-		if( qclass & kMDNSClassUnicastResponseBit )
-		{
-			qclass &= ~kMDNSClassUnicastResponseBit;
-			answerListPtr = &ucastAnswerList;
-		}
-		else
-		{
-			answerListPtr = &mcastAnswerList;
-		}
-		
-		err = _MDNSReplierAnswerListAdd( inContext, answerListPtr, inIndex, qname, qtype, qclass );
-		require_noerr( err, exit );
-	}
-	require_action_quiet( mcastAnswerList || ucastAnswerList, exit, err = kNoErr );
-	
-	// Suppress known answers.
-	// Records in the Answer section of the query message are known answers, so remove them from the answer lists.
-	// See <https://tools.ietf.org/html/rfc6762#section-7.1>.
-	
-	answerCount = DNSHeaderGetAnswerCount( hdr );
-	for( i = 0; i < answerCount; ++i )
-	{
-		const uint8_t *		rdataPtr;
-		const uint8_t *		recordPtr;
-		uint16_t			type, class;
-		uint8_t				name[ kDomainNameLengthMax ];
-		uint8_t				instance[ kDomainNameLengthMax ];
-		
-		recordPtr = ptr;
-		err = DNSMessageExtractRecord( inQueryPtr, inQueryLen, ptr, NULL, &type, &class, NULL, NULL, NULL, &ptr );
-		require_noerr_quiet( err, exit );
-		
-		if( ( type != kDNSServiceType_PTR ) || ( class != kDNSServiceClass_IN ) ) continue;
-		
-		err = DNSMessageExtractRecord( inQueryPtr, inQueryLen, recordPtr, name, NULL, NULL, NULL, &rdataPtr, NULL, NULL );
-		require_noerr( err, exit );
-		
-		err = DNSMessageExtractDomainName( inQueryPtr, inQueryLen, rdataPtr, instance, NULL );
-		require_noerr_quiet( err, exit );
-		
-		if( ucastAnswerList ) _MDNSReplierAnswerListRemovePTR( &ucastAnswerList, name, instance );
-		if( mcastAnswerList ) _MDNSReplierAnswerListRemovePTR( &mcastAnswerList, name, instance );
-	}
-	require_action_quiet( mcastAnswerList || ucastAnswerList, exit, err = kNoErr );
-	
-	// Send or drop responses.
-	
-	if( ucastAnswerList )
-	{
-		err = _MDNSReplierSendOrDropResponse( inContext, ucastAnswerList, inSender, inSock, inIndex, true );
-		require_noerr( err, exit );
-	}
-	
-	if( mcastAnswerList )
-	{
-		err = _MDNSReplierSendOrDropResponse( inContext, mcastAnswerList, inSender, inSock, inIndex, false );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	_MRResourceRecordFreeList( ucastAnswerList );
-	_MRResourceRecordFreeList( mcastAnswerList );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierAnswerListAdd
-//===========================================================================================================================
-
-static OSStatus
-	_MDNSReplierAnswerListAdd(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord **		inAnswerList,
-		unsigned int			inIndex,
-		const uint8_t *			inName,
-		unsigned int			inType,
-		unsigned int			inClass )
-{
-	OSStatus					err;
-	uint8_t *					recordName	= NULL;
-	uint8_t *					rdataPtr	= NULL;
-	size_t						rdataLen;
-	MRResourceRecord *			answer;
-	MRResourceRecord **			answerPtr;
-	const uint8_t * const		hostname	= inContext->hostname;
-	unsigned int				i;
-	uint32_t					index;
-	unsigned int				count, txtSize;
-	
-	require_action( inIndex <= inContext->maxInstanceCount, exit, err = kRangeErr );
-	require_action_quiet( inClass == kDNSServiceClass_IN, exit, err = kNoErr );
-	
-	for( answerPtr = inAnswerList; ( answer = *answerPtr ) != NULL; answerPtr = &answer->next )
-	{
-		if( ( answer->type == inType ) && DomainNameEqual( answer->name, inName ) )
-		{
-			err = kNoErr;
-			goto exit;
-		}
-	}
-	
-	// Index 0 is reserved for answering queries about the mdnsreplier, while all other index values up to the maximum
-	// instance count are for answering queries about service instances.
-	
-	if( inIndex == 0 )
-	{
-		if( _MDNSReplierAboutRecordNameMatch( inContext, inName ) )
-		{
-			int		listHasTXT = false;
-			
-			if( inType == kDNSServiceType_ANY )
-			{
-				for( answer = *inAnswerList; answer; answer = answer->next )
-				{
-					if( ( answer->type == kDNSServiceType_TXT ) && DomainNameEqual( answer->name, inName ) )
-					{
-						listHasTXT = true;
-						break;
-					}
-				}
-			}
-			
-			if( ( inType == kDNSServiceType_TXT ) || ( ( inType == kDNSServiceType_ANY ) && !listHasTXT ) )
-			{
-				err = DomainNameDupLower( inName, &recordName, NULL );
-				require_noerr( err, exit );
-				
-				err = CreateTXTRecordDataFromString( "ready=yes", ',', &rdataPtr, &rdataLen );
-				require_noerr( err, exit );
-				
-				err = _MRResourceRecordCreate( recordName, kDNSServiceType_TXT, kDNSServiceClass_IN, kMDNSRecordTTL_Other,
-					(uint16_t) rdataLen, rdataPtr, &answer );
-				require_noerr( err, exit );
-				recordName	= NULL;
-				rdataPtr	= NULL;
-				
-				*answerPtr = answer;
-			}
-			else if( inType == kDNSServiceType_NSEC )
-			{
-				err = DomainNameDupLower( inName, &recordName, NULL );
-				require_noerr( err, exit );
-				
-				err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 1, kDNSServiceType_TXT );
-				require_noerr( err, exit );
-				
-				err = _MRResourceRecordCreate( recordName, kDNSServiceType_NSEC, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-					(uint16_t) rdataLen, rdataPtr, &answer );
-				require_noerr( err, exit );
-				recordName	= NULL;
-				rdataPtr	= NULL;
-				
-				*answerPtr = answer;
-			}
-		}
-	}
-	else if( _MDNSReplierHostnameMatch( inContext, inName, &index ) && ( index == inIndex ) )
-	{
-		int		listHasA	= false;
-		int		listHasAAAA	= false;
-		
-		if( inType == kDNSServiceType_ANY )
-		{
-			for( answer = *inAnswerList; answer; answer = answer->next )
-			{
-				if( answer->type == kDNSServiceType_A )
-				{
-					if( !listHasA && DomainNameEqual( answer->name, inName ) ) listHasA = true;
-				}
-				else if( answer->type == kDNSServiceType_AAAA )
-				{
-					if( !listHasAAAA && DomainNameEqual( answer->name, inName ) ) listHasAAAA = true;
-				}
-				if( listHasA && listHasAAAA ) break;
-			}
-		}
-		
-		if( ( inType == kDNSServiceType_A ) || ( ( inType == kDNSServiceType_ANY ) && !listHasA ) )
-		{
-			for( i = 1; i <= inContext->recordCountA; ++i )
-			{
-				err = DomainNameDupLower( inName, &recordName, NULL );
-				require_noerr( err, exit );
-				
-				rdataLen = 4;
-				rdataPtr = (uint8_t *) malloc( rdataLen );
-				require_action( rdataPtr, exit, err = kNoMemoryErr );
-				
-				rdataPtr[ 0 ] = 0;
-				WriteBig16Typed( &rdataPtr[ 1 ], (uint16_t) inIndex );
-				rdataPtr[ 3 ] = (uint8_t) i;
-				
-				err = _MRResourceRecordCreate( recordName, kDNSServiceType_A, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-					(uint16_t) rdataLen, rdataPtr, &answer );
-				require_noerr( err, exit );
-				recordName	= NULL;
-				rdataPtr	= NULL;
-				
-				*answerPtr = answer;
-				 answerPtr = &answer->next;
-			}
-		}
-		
-		if( ( inType == kDNSServiceType_AAAA ) || ( ( inType == kDNSServiceType_ANY ) && !listHasAAAA ) )
-		{
-			for( i = 1; i <= inContext->recordCountAAAA; ++i )
-			{
-				const uint8_t		( *baseAddr )[ 16 ];
-				
-				err = DomainNameDupLower( inName, &recordName, NULL );
-				require_noerr( err, exit );
-				
-				rdataLen = 16;
-				baseAddr = ( i == 1 ) ? &kMDNSReplierLinkLocalBaseAddrV6 : &kMDNSReplierBaseAddrV6;
-				rdataPtr = (uint8_t *) _memdup( baseAddr, rdataLen );
-				require_action( rdataPtr, exit, err = kNoMemoryErr );
-				
-				WriteBig16Typed( &rdataPtr[ 12 ], (uint16_t) inIndex );
-				rdataPtr[ 15 ] = (uint8_t) i;
-				
-				err = _MRResourceRecordCreate( recordName, kDNSServiceType_AAAA, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-					(uint16_t) rdataLen, rdataPtr, &answer );
-				require_noerr( err, exit );
-				recordName	= NULL;
-				rdataPtr	= NULL;
-				
-				*answerPtr = answer;
-				 answerPtr = &answer->next;
-			}
-		}
-		else if( inType == kDNSServiceType_NSEC )
-		{
-			err = DomainNameDupLower( inName, &recordName, NULL );
-			require_noerr( err, exit );
-			
-			if( ( inContext->recordCountA > 0 ) && ( inContext->recordCountAAAA > 0 ) )
-			{
-				err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 2, kDNSServiceType_A, kDNSServiceType_AAAA );
-				require_noerr( err, exit );
-			}
-			else if( inContext->recordCountA > 0 )
-			{
-				err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 1, kDNSServiceType_A );
-				require_noerr( err, exit );
-			}
-			else if( inContext->recordCountAAAA > 0 )
-			{
-				err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 1, kDNSServiceType_AAAA );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 0 );
-				require_noerr( err, exit );
-			}
-			
-			err = _MRResourceRecordCreate( recordName, kDNSServiceType_NSEC, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-				(uint16_t) rdataLen, rdataPtr, &answer );
-			require_noerr( err, exit );
-			recordName	= NULL;
-			rdataPtr	= NULL;
-			
-			*answerPtr = answer;
-		}
-	}
-	else if( _MDNSReplierServiceTypeMatch( inContext, inName, NULL, &count ) && ( count >= inIndex ) )
-	{
-		int		listHasPTR = false;
-		
-		if( inType == kDNSServiceType_ANY )
-		{
-			for( answer = *inAnswerList; answer; answer = answer->next )
-			{
-				if( ( answer->type == kDNSServiceType_PTR ) && DomainNameEqual( answer->name, inName ) )
-				{
-					listHasPTR = true;
-					break;
-				}
-			}
-		}
-		
-		if( ( inType == kDNSServiceType_PTR ) || ( ( inType == kDNSServiceType_ANY ) && !listHasPTR ) )
-		{
-			size_t				recordNameLen;
-			uint8_t *			ptr;
-			uint8_t *			lim;
-			
-			err = DomainNameDupLower( inName, &recordName, &recordNameLen );
-			require_noerr( err, exit );
-			
-			rdataLen = 1 + hostname[ 0 ] + 10 + recordNameLen;
-			rdataPtr = (uint8_t *) malloc( rdataLen );
-			require_action( rdataPtr, exit, err = kNoMemoryErr );
-			
-			lim = &rdataPtr[ rdataLen ];
-			
-			ptr = &rdataPtr[ 1 ];
-			memcpy( ptr, &hostname[ 1 ], hostname[ 0 ] );
-			ptr += hostname[ 0 ];
-			if( inIndex != 1 ) SNPrintF_Add( (char **) &ptr, (char *) lim, " (%u)", inIndex );
-			rdataPtr[ 0 ] = (uint8_t)( ptr - &rdataPtr[ 1 ] );
-			
-			check( (size_t)( lim - ptr ) >= recordNameLen );
-			memcpy( ptr, recordName, recordNameLen );
-			ptr += recordNameLen;
-			
-			rdataLen = (size_t)( ptr - rdataPtr );
-			
-			err = _MRResourceRecordCreate( recordName, kDNSServiceType_PTR, kDNSServiceClass_IN, kMDNSRecordTTL_Other,
-				(uint16_t) rdataLen, rdataPtr, &answer );
-			require_noerr( err, exit );
-			recordName	= NULL;
-			rdataPtr	= NULL;
-			
-			*answerPtr = answer;
-		}
-	}
-	else if( _MDNSReplierServiceInstanceNameMatch( inContext, inName, &index, &txtSize, &count ) &&
-		( index == inIndex ) && ( count >= inIndex ) )
-	{
-		int		listHasSRV = false;
-		int		listHasTXT = false;
-		
-		if( inType == kDNSServiceType_ANY )
-		{
-			for( answer = *inAnswerList; answer; answer = answer->next )
-			{
-				if( answer->type == kDNSServiceType_SRV )
-				{
-					if( !listHasSRV && DomainNameEqual( answer->name, inName ) ) listHasSRV = true;
-				}
-				else if( answer->type == kDNSServiceType_TXT )
-				{
-					if( !listHasTXT && DomainNameEqual( answer->name, inName ) ) listHasTXT = true;
-				}
-				if( listHasSRV && listHasTXT ) break;
-			}
-		}
-		
-		if( ( inType == kDNSServiceType_SRV ) || ( ( inType == kDNSServiceType_ANY ) && !listHasSRV ) )
-		{
-			dns_fixed_fields_srv *		fields;
-			uint8_t *					ptr;
-			uint8_t *					lim;
-			uint8_t *					targetPtr;
-			
-			err = DomainNameDupLower( inName, &recordName, NULL );
-			require_noerr( err, exit );
-			
-			rdataLen = sizeof( dns_fixed_fields_srv ) + 1 + hostname[ 0 ] + 10 + kLocalNameLen;
-			rdataPtr = (uint8_t *) malloc( rdataLen );
-			require_action( rdataPtr, exit, err = kNoMemoryErr );
-			
-			lim = &rdataPtr[ rdataLen ];
-			
-			fields = (dns_fixed_fields_srv *) rdataPtr;
-			dns_fixed_fields_srv_init( fields, 0, 0, (uint16_t)( kMDNSReplierPortBase + txtSize ) );
-			
-			targetPtr = (uint8_t *) &fields[ 1 ];
-			
-			ptr = &targetPtr[ 1 ];
-			memcpy( ptr, &hostname[ 1 ], hostname[ 0 ] );
-			ptr += hostname[ 0 ];
-			if( inIndex != 1 ) SNPrintF_Add( (char **) &ptr, (char *) lim, "-%u", inIndex );
-			targetPtr[ 0 ] = (uint8_t)( ptr - &targetPtr[ 1 ] );
-			
-			check( (size_t)( lim - ptr ) >= kLocalNameLen );
-			memcpy( ptr, kLocalName, kLocalNameLen );
-			ptr += kLocalNameLen;
-			
-			rdataLen = (size_t)( ptr - rdataPtr );
-			
-			err = _MRResourceRecordCreate( recordName, kDNSServiceType_SRV, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-				(uint16_t) rdataLen, rdataPtr, &answer );
-			require_noerr( err, exit );
-			recordName	= NULL;
-			rdataPtr	= NULL;
-			
-			*answerPtr = answer;
-			 answerPtr = &answer->next;
-		}
-		
-		if( ( inType == kDNSServiceType_TXT ) || ( ( inType == kDNSServiceType_ANY ) && !listHasTXT ) )
-		{
-			err = DomainNameDupLower( inName, &recordName, NULL );
-			require_noerr( err, exit );
-			
-			rdataLen = txtSize;
-			err = _MDNSReplierCreateTXTRecord( inName, rdataLen, &rdataPtr );
-			require_noerr( err, exit );
-			
-			err = _MRResourceRecordCreate( recordName, kDNSServiceType_TXT, kDNSServiceClass_IN, kMDNSRecordTTL_Other,
-				(uint16_t) rdataLen, rdataPtr, &answer );
-			require_noerr( err, exit );
-			recordName	= NULL;
-			rdataPtr	= NULL;
-			
-			*answerPtr = answer;
-		}
-		else if( inType == kDNSServiceType_NSEC )
-		{
-			err = DomainNameDupLower( inName, &recordName, NULL );
-			require_noerr( err, exit );
-			
-			err = CreateNSECRecordData( recordName, &rdataPtr, &rdataLen, 2, kDNSServiceType_TXT, kDNSServiceType_SRV );
-			require_noerr( err, exit );
-			
-			err = _MRResourceRecordCreate( recordName, kDNSServiceType_NSEC, kDNSServiceClass_IN, kMDNSRecordTTL_Host,
-				(uint16_t) rdataLen, rdataPtr, &answer );
-			require_noerr( err, exit );
-			recordName	= NULL;
-			rdataPtr	= NULL;
-			
-			*answerPtr = answer;
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( recordName );
-	FreeNullSafe( rdataPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierAnswerListRemovePTR
-//===========================================================================================================================
-
-static void
-	_MDNSReplierAnswerListRemovePTR(
-		MRResourceRecord **	inAnswerListPtr,
-		const uint8_t *		inName,
-		const uint8_t *		inRData )
-{
-	MRResourceRecord *		answer;
-	MRResourceRecord **		answerPtr;
-	
-	for( answerPtr = inAnswerListPtr; ( answer = *answerPtr ) != NULL; answerPtr = &answer->next )
-	{
-		if( ( answer->type == kDNSServiceType_PTR ) && ( answer->class == kDNSServiceClass_IN ) &&
-			DomainNameEqual( answer->name, inName ) && DomainNameEqual( answer->rdata, inRData ) ) break;
-	}
-	if( answer )
-	{
-		*answerPtr = answer->next;
-		_MRResourceRecordFree( answer );
-	}
-}
-
-//===========================================================================================================================
-//	_MDNSReplierSendOrDropResponse
-//===========================================================================================================================
-
-static OSStatus
-	_MDNSReplierSendOrDropResponse(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord *		inAnswerList,
-		sockaddr_ip *			inQuerier,
-		SocketRef				inSock,
-		unsigned int			inIndex,
-		Boolean					inUnicast )
-{
-	OSStatus					err;
-	uint8_t *					responsePtr	= NULL;
-	size_t						responseLen;
-	const struct sockaddr *		destAddr;
-	ssize_t						n;
-	const double				dropRate	= inUnicast ? inContext->ucastDropRate : inContext->mcastDropRate;
-	int							drop;
-	
-	check( inIndex <= inContext->maxInstanceCount );
-	
-	// If maxDropCount > 0, then the drop rates apply only to the first maxDropCount responses. Otherwise, all messages are
-	// subject to their respective drop rate. Also, responses to queries about mDNS replier itself (indicated by index 0),
-	// as opposed to those for service instance records, are never dropped.
-	
-	drop = false;
-	if( inIndex > 0 )
-	{
-		if( inContext->maxDropCount > 0 )
-		{
-			uint8_t * const		dropCount = &inContext->dropCounters[ inIndex - 1 ];
-			
-			if( *dropCount < inContext->maxDropCount )
-			{
-				if( ShouldDrop( dropRate ) ) drop = true;
-				*dropCount += 1;
-			}
-		}
-		else if( ShouldDrop( dropRate ) )
-		{
-			drop = true;
-		}
-	}
-	
-	err = _MDNSReplierCreateResponse( inContext, inAnswerList, inIndex, &responsePtr, &responseLen );
-	require_noerr( err, exit );
-	
-	if( inUnicast )
-	{
-		destAddr = &inQuerier->sa;
-	}
-	else
-	{
-		destAddr = ( inQuerier->sa.sa_family == AF_INET ) ? GetMDNSMulticastAddrV4() : GetMDNSMulticastAddrV6();
-	}
-	
-	mr_ulog( kLogLevelInfo, "%s %zu byte response to %##a -- %#.1{du:dnsmsg}\n",
-		drop ? "Dropping" : "Sending", responseLen, destAddr, responsePtr, responseLen );
-	
-	if( !drop )
-	{
-		n = sendto( inSock, (char *) responsePtr, responseLen, 0, destAddr, SockAddrGetSize( destAddr ) );
-		err = map_socket_value_errno( inSock, n == (ssize_t) responseLen, n );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	FreeNullSafe( responsePtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierCreateResponse
-//===========================================================================================================================
-
-static OSStatus
-	_MDNSReplierCreateResponse(
-		MDNSReplierContext *	inContext,
-		MRResourceRecord *		inAnswerList,
-		unsigned int			inIndex,
-		uint8_t **				outResponsePtr,
-		size_t *				outResponseLen )
-{
-	OSStatus				err;
-	DataBuffer				responseDB;
-	DNSHeader				hdr;
-	MRResourceRecord *		answer;
-	uint8_t *				responsePtr;
-	size_t					responseLen, len;
-	unsigned int			answerCount, recordCount;
-	MRNameOffsetItem *		nameOffsetList = NULL;
-	
-	DataBuffer_Init( &responseDB, NULL, 0, SIZE_MAX );
-	
-	// The current answers in the answer list will make up the response's Answer Record Section.
-	
-	answerCount = 0;
-	for( answer = inAnswerList; answer; answer = answer->next ) { ++answerCount; }
-	
-	// Unless configured not to, add any additional answers to the answer list for the Additional Record Section.
-	
-	if( !inContext->noAdditionals )
-	{
-		for( answer = inAnswerList; answer; answer = answer->next )
-		{
-			switch( answer->type )
-			{
-				case kDNSServiceType_PTR:
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->rdata, kDNSServiceType_SRV,
-						answer->class );
-					require_noerr( err, exit );
-					
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->rdata, kDNSServiceType_TXT,
-						answer->class );
-					require_noerr( err, exit );
-					break;
-				
-				case kDNSServiceType_SRV:
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->target, kDNSServiceType_A,
-						answer->class );
-					require_noerr( err, exit );
-					
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->target, kDNSServiceType_AAAA,
-						answer->class );
-					require_noerr( err, exit );
-					
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_NSEC,
-						answer->class );
-					require_noerr( err, exit );
-					break;
-				
-				case kDNSServiceType_TXT:
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_NSEC,
-						answer->class );
-					require_noerr( err, exit );
-					break;
-				
-				case kDNSServiceType_A:
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_AAAA,
-						answer->class );
-					require_noerr( err, exit );
-					
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_NSEC,
-						answer->class );
-					require_noerr( err, exit );
-					break;
-				
-				case kDNSServiceType_AAAA:
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_A,
-						answer->class );
-					require_noerr( err, exit );
-					
-					err = _MDNSReplierAnswerListAdd( inContext, &inAnswerList, inIndex, answer->name, kDNSServiceType_NSEC,
-						answer->class );
-					require_noerr( err, exit );
-					break;
-				
-				default:
-					break;
-			}
-		}
-	}
-	
-	// Append a provisional header to the response message.
-	
-	memset( &hdr, 0, sizeof( hdr ) );
-	DNSHeaderSetFlags( &hdr, kDNSHeaderFlag_Response | kDNSHeaderFlag_AuthAnswer );
-	
-	err = DataBuffer_Append( &responseDB, &hdr, sizeof( hdr ) );
-	require_noerr( err, exit );
-	
-	// Append answers to response message.
-	
-	responseLen = DataBuffer_GetLen( &responseDB );
-	recordCount = 0;
-	for( answer = inAnswerList; answer; answer = answer->next )
-	{
-		dns_fixed_fields_record		fields;
-		unsigned int				class;
-		
-		// Append record NAME.
-		
-		err = _MDNSReplierAppendNameToResponse( &responseDB, answer->name, &nameOffsetList );
-		require_noerr( err, exit );
-		
-		// Append record TYPE, CLASS, TTL, and provisional RDLENGTH.
-		
-		class = answer->class;
-		if( ( answer->type == kDNSServiceType_SRV ) || ( answer->type == kDNSServiceType_TXT )  ||
-			( answer->type == kDNSServiceType_A )   || ( answer->type == kDNSServiceType_AAAA ) ||
-			( answer->type == kDNSServiceType_NSEC ) )
-		{
-			class |= kMDNSClassCacheFlushBit;
-		}
-		
-		dns_fixed_fields_record_init( &fields, answer->type, (uint16_t) class, answer->ttl, (uint16_t) answer->rdlength );
-		err = DataBuffer_Append( &responseDB, &fields, sizeof( fields ) );
-		require_noerr( err, exit );
-		
-		// Append record RDATA.
-		// The RDATA of PTR, SRV, and NSEC records contain domain names, which are subject to name compression.
-		
-		if( ( answer->type == kDNSServiceType_PTR ) || ( answer->type == kDNSServiceType_SRV ) ||
-			( answer->type == kDNSServiceType_NSEC ) )
-		{
-			size_t				rdlength;
-			uint8_t *			rdLengthPtr;
-			const size_t		rdLengthOffset	= DataBuffer_GetLen( &responseDB ) - 2;
-			const size_t		rdataOffset		= DataBuffer_GetLen( &responseDB );
-			
-			if( answer->type == kDNSServiceType_PTR )
-			{
-				err = _MDNSReplierAppendNameToResponse( &responseDB, answer->rdata, &nameOffsetList );
-				require_noerr( err, exit );
-			}
-			else if( answer->type == kDNSServiceType_SRV )
-			{
-				require_fatal( answer->target == &answer->rdata[ 6 ], "Bad SRV record target pointer." );
-				
-				err = DataBuffer_Append( &responseDB, answer->rdata, (size_t)( answer->target - answer->rdata ) );
-				require_noerr( err, exit );
-				
-				err = _MDNSReplierAppendNameToResponse( &responseDB, answer->target, &nameOffsetList );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				const size_t		nameLen = DomainNameLength( answer->rdata );
-				
-				err = _MDNSReplierAppendNameToResponse( &responseDB, answer->rdata, &nameOffsetList );
-				require_noerr( err, exit );
-				
-				require_fatal( answer->rdlength > nameLen, "Bad NSEC record data length." );
-				
-				err = DataBuffer_Append( &responseDB, &answer->rdata[ nameLen ], answer->rdlength - nameLen );
-				require_noerr( err, exit );
-			}
-			
-			// Set the actual RDLENGTH, which may be less than the original due to name compression.
-			
-			rdlength = DataBuffer_GetLen( &responseDB ) - rdataOffset;
-			check( rdlength <= UINT16_MAX );
-			
-			rdLengthPtr = DataBuffer_GetPtr( &responseDB ) + rdLengthOffset;
-			WriteBig16Typed( rdLengthPtr, (uint16_t) rdlength );
-		}
-		else
-		{
-			err = DataBuffer_Append( &responseDB, answer->rdata, answer->rdlength );
-			require_noerr( err, exit );
-		}
-		
-		if( DataBuffer_GetLen( &responseDB ) > kMDNSMessageSizeMax ) break;
-		responseLen = DataBuffer_GetLen( &responseDB );
-		++recordCount;
-	}
-	
-	// Set the response header's Answer and Additional record counts.
-	// Note: recordCount may be less than answerCount if including all answerCount records would cause the size of the
-	// response message to exceed the maximum mDNS message size.
-	
-	if( recordCount <= answerCount )
-	{
-		DNSHeaderSetAnswerCount( (DNSHeader *) DataBuffer_GetPtr( &responseDB ), recordCount );
-	}
-	else
-	{
-		DNSHeaderSetAnswerCount( (DNSHeader *) DataBuffer_GetPtr( &responseDB ), answerCount );
-		DNSHeaderSetAdditionalCount( (DNSHeader *) DataBuffer_GetPtr( &responseDB ), recordCount - answerCount );
-	}
-	
-	err = DataBuffer_Detach( &responseDB, &responsePtr, &len );
-	require_noerr( err, exit );
-	
-	if( outResponsePtr ) *outResponsePtr = responsePtr;
-	if( outResponseLen ) *outResponseLen = responseLen;
-	
-exit:
-	_MRNameOffsetItemFreeList( nameOffsetList );
-	DataBuffer_Free( &responseDB );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierAppendNameToResponse
-//===========================================================================================================================
-
-static OSStatus
-	_MDNSReplierAppendNameToResponse(
-		DataBuffer *		inResponse,
-		const uint8_t *		inName,
-		MRNameOffsetItem **	inNameOffsetListPtr )
-{
-	OSStatus				err;
-	const uint8_t *			subname;
-	const uint8_t *			limit;
-	size_t					nameOffset;
-	MRNameOffsetItem *		item;
-	uint8_t					compressionPtr[ 2 ];
-	
-	nameOffset = DataBuffer_GetLen( inResponse );
-	
-	// Find the name's longest subname (more accurately, its longest sub-FQDN) in the name compression list.
-	
-	for( subname = inName; subname[ 0 ] != 0; subname += ( 1 + subname[ 0 ] ) )
-	{
-		for( item = *inNameOffsetListPtr; item; item = item->next )
-		{
-			if( DomainNameEqual( item->name, subname ) ) break;
-		}
-		
-		// If an item was found for this subname, then append a name compression pointer and we're done. Otherwise, append
-		// the subname's first label.
-		
-		if( item )
-		{
-			DNSMessageWriteLabelPointer( compressionPtr, item->offset );
-			
-			err = DataBuffer_Append( inResponse, compressionPtr, sizeof( compressionPtr ) );
-			require_noerr( err, exit );
-			break;
-		}
-		else
-		{
-			err = DataBuffer_Append( inResponse, subname, 1 + subname[ 0 ] );
-			require_noerr( err, exit );
-		}
-	}
-		
-	// If we made it to the root label, then no subname was able to be compressed. All of the name's labels up to the root
-	// label were appended to the response message, so a root label is needed to terminate the complete name.
-	
-	if( subname[ 0 ] == 0 )
-	{
-		err = DataBuffer_Append( inResponse, "", 1 );
-		require_noerr( err, exit );
-	}
-	
-	// Add subnames that weren't able to be compressed and their offsets to the name compression list.
-	
-	limit = subname;
-	for( subname = inName; subname < limit; subname += ( 1 + subname[ 0 ] ) )
-	{
-		const size_t		subnameOffset = nameOffset + (size_t)( subname - inName );
-		
-		if( subnameOffset > kDNSCompressionOffsetMax ) break;
-		
-		err = _MRNameOffsetItemCreate( subname, (uint16_t) subnameOffset, &item );
-		require_noerr( err, exit );
-		
-		item->next = *inNameOffsetListPtr;
-		*inNameOffsetListPtr = item;
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierServiceTypeMatch
-//===========================================================================================================================
-
-static Boolean
-	_MDNSReplierServiceTypeMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outTXTSize,
-		unsigned int *				outCount )
-{
-	OSStatus					err;
-	const char *				ptr;
-	const char *				end;
-	uint32_t					txtSize, count;
-	const uint8_t * const		serviceLabel	= inContext->serviceLabel;
-	int							nameMatches		= false;
-	
-	require_quiet( inName[ 0 ] >= serviceLabel[ 0 ], exit );
-	if( _memicmp( &inName[ 1 ], &serviceLabel[ 1 ], serviceLabel[ 0 ] ) != 0 ) goto exit;
-	
-	ptr = (const char *) &inName[ 1 + serviceLabel[ 0 ] ];
-	end = (const char *) &inName[ 1 + inName[ 0 ] ];
-	
-	require_quiet( ( ptr < end ) && ( *ptr == '-' ), exit );
-	++ptr;
-	
-	err = DecimalTextToUInt32( ptr, end, &txtSize, &ptr );
-	require_noerr_quiet( err, exit );
-	require_quiet( txtSize <= UINT16_MAX, exit );
-	
-	require_quiet( ( ptr < end ) && ( *ptr == '-' ), exit );
-	++ptr;
-	
-	err = DecimalTextToUInt32( ptr, end, &count, &ptr );
-	require_noerr_quiet( err, exit );
-	require_quiet( count <= UINT16_MAX, exit );
-	require_quiet( ptr == end, exit );
-	
-	if( !DomainNameEqual( (const uint8_t *) ptr, (const uint8_t *) "\x04" "_tcp" "\x05" "local" ) ) goto exit;
-	nameMatches = true;
-	
-	if( outTXTSize )	*outTXTSize	= txtSize;
-	if( outCount )		*outCount	= count;
-	
-exit:
-	return( nameMatches ? true : false );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierServiceInstanceNameMatch
-//===========================================================================================================================
-
-static Boolean
-	_MDNSReplierServiceInstanceNameMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outIndex,
-		unsigned int *				outTXTSize,
-		unsigned int *				outCount )
-{
-	OSStatus					err;
-	const uint8_t *				ptr;
-	const uint8_t *				end;
-	uint32_t					index;
-	unsigned int				txtSize, count;
-	const uint8_t * const		hostname	= inContext->hostname;
-	int							nameMatches	= false;
-	
-	require_quiet( inName[ 0 ] >= hostname[ 0 ], exit );
-	if( _memicmp( &inName[ 1 ], &hostname[ 1 ], hostname[ 0 ] ) != 0 ) goto exit;
-	
-	ptr = &inName[ 1 + hostname[ 0 ] ];
-	end = &inName[ 1 + inName[ 0 ] ];
-	if( ptr < end )
-	{
-		require_quiet( ( end - ptr ) >= 2, exit );
-		require_quiet( ( ptr[ 0 ] == ' ' ) && ( ptr[ 1 ] == '(' ), exit );
-		ptr += 2;
-		
-        err = DecimalTextToUInt32( (const char *) ptr, (const char *) end, &index, (const char **) &ptr );
-		require_noerr_quiet( err, exit );
-		require_quiet( ( index >= 2 ) && ( index <= UINT16_MAX ), exit );
-		
-		require_quiet( ( ( end - ptr ) == 1 ) && ( *ptr == ')' ), exit );
-		++ptr;
-	}
-	else
-	{
-		index = 1;
-	}
-	
-	if( !_MDNSReplierServiceTypeMatch( inContext, ptr, &txtSize, &count ) ) goto exit;
-	nameMatches = true;
-	
-	if( outIndex )		*outIndex	= index;
-	if( outTXTSize )	*outTXTSize	= txtSize;
-	if( outCount )		*outCount	= count;
-	
-exit:
-	return( nameMatches ? true : false );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierAboutRecordNameMatch
-//===========================================================================================================================
-
-#define _MemIEqual( PTR1, LEN1, PTR2, LEN2 ) \
-	( ( ( LEN1 ) == ( LEN2 ) ) && ( _memicmp( ( PTR1 ), ( PTR2 ), ( LEN1 ) ) == 0 ) )
-
-static Boolean	_MDNSReplierAboutRecordNameMatch( const MDNSReplierContext *inContext, const uint8_t *inName )
-{
-	const uint8_t *				subname;
-	const uint8_t * const		hostname	= inContext->hostname;
-	int							nameMatches	= false;
-	
-	if( strnicmpx( &inName[ 1 ], inName[ 0 ], "about" ) != 0 ) goto exit;
-	subname = DomainNameGetNextLabel( inName );
-	
-	if( !_MemIEqual( &subname[ 1 ], subname[ 0 ], &hostname[ 1 ], hostname[ 0 ] ) ) goto exit;
-	subname = DomainNameGetNextLabel( subname );
-	
-	if( !DomainNameEqual( subname, kLocalName ) ) goto exit;
-	nameMatches = true;
-	
-exit:
-	return( nameMatches ? true : false );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierHostnameMatch
-//===========================================================================================================================
-
-static Boolean
-	_MDNSReplierHostnameMatch(
-		const MDNSReplierContext *	inContext,
-		const uint8_t *				inName,
-		unsigned int *				outIndex )
-{
-	OSStatus					err;
-	const uint8_t *				ptr;
-	const uint8_t *				end;
-	uint32_t					index;
-	const uint8_t * const		hostname	= inContext->hostname;
-	int							nameMatches	= false;
-	
-	require_quiet( inName[ 0 ] >= hostname[ 0 ], exit );
-	if( _memicmp( &inName[ 1 ], &hostname[ 1 ], hostname[ 0 ] ) != 0 ) goto exit;
-	
-	ptr = &inName[ 1 + hostname[ 0 ] ];
-	end = &inName[ 1 + inName[ 0 ] ];
-	if( ptr < end )
-	{
-		require_quiet( *ptr == '-', exit );
-		++ptr;
-		
-		err = DecimalTextToUInt32( (const char *) ptr, (const char *) end, &index, (const char **) &ptr );
-		require_noerr_quiet( err, exit );
-		require_quiet( ( index >= 2 ) && ( index <= UINT16_MAX ), exit );
-		require_quiet( ptr == end, exit );
-	}
-	else
-	{
-		index = 1;
-	}
-	
-	if( !DomainNameEqual( ptr, kLocalName ) ) goto exit;
-	nameMatches = true;
-	
-	if( outIndex ) *outIndex = index;
-	
-exit:
-	return( nameMatches ? true : false );
-}
-
-//===========================================================================================================================
-//	_MDNSReplierCreateTXTRecord
-//===========================================================================================================================
-
-static OSStatus	_MDNSReplierCreateTXTRecord( const uint8_t *inRecordName, size_t inSize, uint8_t **outTXT )
-{
-	OSStatus		err;
-	uint8_t *		txt;
-	uint8_t *		ptr;
-	size_t			i, wholeCount, remCount;
-	uint32_t		hash;
-	int				n;
-	uint8_t			txtStr[ 16 ];
-	
-	require_action_quiet( inSize > 0, exit, err = kSizeErr );
-	
-	txt = (uint8_t *) malloc( inSize );
-	require_action( txt, exit, err = kNoMemoryErr );
-	
-	hash = _FNV1( inRecordName, DomainNameLength( inRecordName ) );
-	
-	txtStr[ 0 ] = 15;
-	n = MemPrintF( &txtStr[ 1 ], 15, "hash=0x%08X", hash );
-	check( n == 15 );
-	
-	ptr = txt;
-	wholeCount = inSize / 16;
-	for( i = 0; i < wholeCount; ++i )
-	{
-		memcpy( ptr, txtStr, 16 );
-		ptr += 16;
-	}
-	
-	remCount = inSize % 16;
-	if( remCount > 0 )
-	{
-		txtStr[ 0 ] = (uint8_t)( remCount - 1 );
-		memcpy( ptr, txtStr, remCount );
-		ptr += remCount;
-	}
-	check( ptr == &txt[ inSize ] );
-	
-	*outTXT = txt;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MRResourceRecordCreate
-//===========================================================================================================================
-
-static OSStatus
-	_MRResourceRecordCreate(
-		uint8_t *			inName,
-		uint16_t			inType,
-		uint16_t			inClass,
-		uint32_t			inTTL,
-		uint16_t			inRDLength,
-		uint8_t *			inRData,
-		MRResourceRecord **	outRecord )
-{
-	OSStatus				err;
-	MRResourceRecord *		obj;
-	
-	obj = (MRResourceRecord *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name		= inName;
-	obj->type		= inType;
-	obj->class		= inClass;
-	obj->ttl		= inTTL;
-	obj->rdlength	= inRDLength;
-	obj->rdata		= inRData;
-	
-	if( inType == kDNSServiceType_SRV )
-	{
-		require_action_quiet( obj->rdlength > sizeof( dns_fixed_fields_srv ), exit, err = kMalformedErr );
-		obj->target = obj->rdata + sizeof( dns_fixed_fields_srv );
-	}
-	
-	*outRecord = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MRResourceRecordFree
-//===========================================================================================================================
-
-static void	_MRResourceRecordFree( MRResourceRecord *inRecord )
-{
-	ForgetMem( &inRecord->name );
-	ForgetMem( &inRecord->rdata );
-	free( inRecord );
-}
-
-//===========================================================================================================================
-//	_MRResourceRecordFreeList
-//===========================================================================================================================
-
-static void	_MRResourceRecordFreeList( MRResourceRecord *inList )
-{
-	MRResourceRecord *		record;
-	
-	while( ( record = inList ) != NULL )
-	{
-		inList = record->next;
-		_MRResourceRecordFree( record );
-	}
-}
-
-//===========================================================================================================================
-//	_MRNameOffsetItemCreate
-//===========================================================================================================================
-
-static OSStatus	_MRNameOffsetItemCreate( const uint8_t *inName, uint16_t inOffset, MRNameOffsetItem **outItem )
-{
-	OSStatus				err;
-	MRNameOffsetItem *		obj;
-	size_t					nameLen;
-	
-	require_action_quiet( inOffset <= kDNSCompressionOffsetMax, exit, err = kSizeErr );
-	
-	nameLen = DomainNameLength( inName );
-	obj = (MRNameOffsetItem *) calloc( 1, offsetof( MRNameOffsetItem, name ) + nameLen );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->offset = inOffset;
-	memcpy( obj->name, inName, nameLen );
-	
-	*outItem = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MRNameOffsetItemFree
-//===========================================================================================================================
-
-static void	_MRNameOffsetItemFree( MRNameOffsetItem *inItem )
-{
-	free( inItem );
-}
-
-//===========================================================================================================================
-//	_MRNameOffsetItemFreeList
-//===========================================================================================================================
-
-static void	_MRNameOffsetItemFreeList( MRNameOffsetItem *inList )
-{
-	MRNameOffsetItem *		item;
-	
-	while( ( item = inList ) != NULL )
-	{
-		inList = item->next;
-		_MRNameOffsetItemFree( item );
-	}
-}
-
-//===========================================================================================================================
-//	GAIPerfCmd
-//===========================================================================================================================
-
-#define kGAIPerfStandardTTL		( 1 * kSecondsPerHour )
-
-typedef struct GAITesterPrivate *		GAITesterRef;
-typedef struct GAITestCase				GAITestCase;
-
-typedef struct
-{
-	const char *		name;				// Domain name that was resolved.
-	uint64_t			connectionTimeUs;	// Time in microseconds that it took to create a DNS-SD connection.
-	uint64_t			firstTimeUs;		// Time in microseconds that it took to get the first address result.
-	uint64_t			timeUs;				// Time in microseconds that it took to get all expected address results.
-	OSStatus			error;
-	
-}	GAITestItemResult;
-
-typedef void ( *GAITesterStopHandler_f )( void *inContext, OSStatus inError );
-typedef void
-	( *GAITesterResultsHandler_f )(
-		const char *				inCaseTitle,
-		NanoTime64					inCaseStartTime,
-		NanoTime64					inCaseEndTime,
-		const GAITestItemResult *	inResultArray,
-		size_t						inResultCount,
-		void *						inContext );
-
-typedef unsigned int		GAITestAddrType;
-#define kGAITestAddrType_None		0
-#define kGAITestAddrType_IPv4		( 1U << 0 )
-#define kGAITestAddrType_IPv6		( 1U << 1 )
-#define kGAITestAddrType_Both		( kGAITestAddrType_IPv4 | kGAITestAddrType_IPv6 )
-
-#define GAITestAddrTypeIsValid( X ) \
-	( ( (X) & kGAITestAddrType_Both ) && ( ( (X) & ~kGAITestAddrType_Both ) == 0 ) )
-
-typedef struct
-{
-	GAITesterRef			tester;				// GAI tester object.
-	CFMutableArrayRef		testCaseResults;	// Array of test case results.
-	unsigned int			iterTimeLimitMs;	// Amount of time to allow each iteration to complete.
-	unsigned int			callDelayMs;		// Amount of time to wait before calling DNSServiceGetAddrInfo().
-	unsigned int			serverDelayMs;		// Amount of additional time to have server delay its responses.
-	unsigned int			defaultIterCount;	// Default test case iteration count.
-	dispatch_source_t		sigIntSource;		// Dispatch source for SIGINT.
-	dispatch_source_t		sigTermSource;		// Dispatch source for SIGTERM.
-	char *					outputFilePath;		// File to write test results to. If NULL, then write to stdout.
-	OutputFormatType		outputFormat;		// Format of test results output.
-	DNSProtocol				protocol;			// DNS protocol to use, e.g., Do53, DoT, or DoH.
-	Boolean					skipPathEval;		// True if DNSServiceGetAddrInfo() path evaluation is to be skipped.
-	Boolean					badUDPMode;			// True if the test DNS server is to run in Bad UDP mode.
-	Boolean					testFailed;			// True if at least one test case iteration failed.
-	
-}	GAIPerfContext;
-
-static void		GAIPerfContextFree( GAIPerfContext *inContext );
-static OSStatus	GAIPerfAddAdvancedTestCases( GAIPerfContext *inContext );
-static OSStatus	GAIPerfAddBasicTestCases( GAIPerfContext *inContext );
-static void		GAIPerfTesterStopHandler( void *inContext, OSStatus inError );
-static void
-	GAIPerfResultsHandler(
-		const char *				inCaseTitle,
-		NanoTime64					inCaseStartTime,
-		NanoTime64					inCaseEndTime,
-		const GAITestItemResult *	inResultArray,
-		size_t						inResultCount,
-		void *						inContext );
-static void		GAIPerfSignalHandler( void *inContext );
-
-static CFTypeID	GAITesterGetTypeID( void );
-static OSStatus
-	GAITesterCreate(
-		dispatch_queue_t	inQueue,
-		DNSProtocol			inProtocol,
-		unsigned int		inCallDelayMs,
-		int					inServerDelayMs,
-		int					inServerDefaultTTL,
-		Boolean				inSkipPathEvaluation,
-		Boolean				inBadUDPMode,
-		GAITesterRef *		outTester );
-static void		GAITesterStart( GAITesterRef inTester );
-static void		GAITesterStop( GAITesterRef inTester );
-static OSStatus	GAITesterAddTestCase( GAITesterRef inTester, GAITestCase *inCase );
-static void
-	GAITesterSetStopHandler(
-		GAITesterRef			inTester,
-		GAITesterStopHandler_f	inEventHandler,
-		void *					inEventContext );
-static void
-	GAITesterSetResultsHandler(
-		GAITesterRef				inTester,
-		GAITesterResultsHandler_f	inResultsHandler,
-		void *						inResultsContext );
-
-static OSStatus	GAITestCaseCreate( const char *inTitle, GAITestCase **outCase );
-static void		GAITestCaseFree( GAITestCase *inCase );
-static OSStatus
-	GAITestCaseAddItem(
-		GAITestCase *	inCase,
-		unsigned int	inAliasCount,
-		unsigned int	inAddressCount,
-		int				inTTL,
-		GAITestAddrType	inHasAddrs,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		unsigned int	inItemCount );
-static OSStatus
-	GAITestCaseAddLocalHostItem(
-		GAITestCase *	inCase,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		unsigned int	inItemCount );
-
-static void	GAIPerfCmd( void )
-{
-	OSStatus				err;
-	GAIPerfContext *		context = NULL;
-	
-	err = CheckRootUser();
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gGAIPerf_CallDelayMs, "call delay (ms)", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gGAIPerf_ServerDelayMs, "server delay (ms)", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gGAIPerf_IterationCount, "iteration count", 1, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gGAIPerf_IterationTimeLimitMs, "iteration time limit (ms)", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	context = (GAIPerfContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->testCaseResults = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( context->testCaseResults, exit, err = kNoMemoryErr );
-	
-	context->iterTimeLimitMs	= (unsigned int) gGAIPerf_IterationTimeLimitMs;
-	context->callDelayMs		= (unsigned int) gGAIPerf_CallDelayMs;
-	context->serverDelayMs		= (unsigned int) gGAIPerf_ServerDelayMs;
-	context->defaultIterCount	= (unsigned int) gGAIPerf_IterationCount;
-	context->skipPathEval		= gGAIPerf_SkipPathEvalulation	? true : false;
-	context->badUDPMode			= gGAIPerf_BadUDPMode			? true : false;
-	
-	context->protocol = (DNSProtocol) CLIArgToValue( "protocol", gGAIPerf_Protocol, &err,
-		kDNSProtocolStr_Do53,	(int) kDNSProtocol_Do53,
-		kDNSProtocolStr_DoT,	(int) kDNSProtocol_DoT,
-		kDNSProtocolStr_DoH,	(int) kDNSProtocol_DoH,
-		NULL );
-	require_noerr_quiet( err, exit );
-	
-	if( gGAIPerf_OutputFilePath )
-	{
-		context->outputFilePath = strdup( gGAIPerf_OutputFilePath );
-		require_action( context->outputFilePath, exit, err = kNoMemoryErr );
-	}
-	
-	err = OutputFormatFromArgString( gGAIPerf_OutputFormat, &context->outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = GAITesterCreate( dispatch_get_main_queue(), context->protocol, context->callDelayMs, (int) context->serverDelayMs,
-		kGAIPerfStandardTTL, context->skipPathEval, context->badUDPMode, &context->tester );
-	require_noerr( err, exit );
-	
-	check( gGAIPerf_TestSuite );
-	if( strcasecmp( gGAIPerf_TestSuite, kGAIPerfTestSuiteName_Basic ) == 0 )
-	{
-		err = GAIPerfAddBasicTestCases( context );
-		require_noerr( err, exit );
-	}
-	else if( strcasecmp( gGAIPerf_TestSuite, kGAIPerfTestSuiteName_Advanced ) == 0 )
-	{
-		err = GAIPerfAddAdvancedTestCases( context );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Invalid test suite name: %s.\n", gGAIPerf_TestSuite );
-		goto exit;
-	}
-	
-	GAITesterSetStopHandler( context->tester, GAIPerfTesterStopHandler, context );
-	GAITesterSetResultsHandler( context->tester, GAIPerfResultsHandler, context );
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), GAIPerfSignalHandler, context,
-		&context->sigIntSource );
-	require_noerr( err, exit );
-	dispatch_resume( context->sigIntSource );
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, dispatch_get_main_queue(), GAIPerfSignalHandler, context,
-		&context->sigTermSource );
-	require_noerr( err, exit );
-	dispatch_resume( context->sigTermSource );
-	
-	GAITesterStart( context->tester );
-	dispatch_main();
-	
-exit:
-	if( context ) GAIPerfContextFree( context );
-	exit( 1 );
-}
-
-//===========================================================================================================================
-//	GAIPerfContextFree
-//===========================================================================================================================
-
-static void	GAIPerfContextFree( GAIPerfContext *inContext )
-{
-	ForgetCF( &inContext->tester );
-	ForgetCF( &inContext->testCaseResults );
-	ForgetMem( &inContext->outputFilePath );
-	dispatch_source_forget( &inContext->sigIntSource );
-	dispatch_source_forget( &inContext->sigTermSource );
-	free( inContext );
-}
-
-//===========================================================================================================================
-//	GAIPerfAddAdvancedTestCases
-//===========================================================================================================================
-
-#define kTestCaseTitleBufferSize		128
-
-static void
-	_GAIPerfWriteTestCaseTitle(
-		char			inBuffer[ kTestCaseTitleBufferSize ],
-		unsigned int	inCNAMERecordCount,
-		unsigned int	inARecordCount,
-		unsigned int	inAAAARecordCount,
-		GAITestAddrType	inRequested,
-		unsigned int	inIterationCount,
-		Boolean			inIterationsAreUnique );
-static void
-	_GAIPerfWriteLocalHostTestCaseTitle(
-		char			inBuffer[ kTestCaseTitleBufferSize ],
-		GAITestAddrType	inRequested,
-		unsigned int	inIterationCount );
-
-#define kGAIPerfAdvancedTestSuite_MaxAliasCount		4
-#define kGAIPerfAdvancedTestSuite_MaxAddrCount		8
-
-static OSStatus	GAIPerfAddAdvancedTestCases( GAIPerfContext *inContext )
-{
-	OSStatus			err;
-	unsigned int		aliasCount, addressCount, i;
-	GAITestCase *		testCase = NULL;
-	char				title[ kTestCaseTitleBufferSize ];
-	
-	aliasCount = 0;
-	while( aliasCount <= kGAIPerfAdvancedTestSuite_MaxAliasCount )
-	{
-		for( addressCount = 1; addressCount <= kGAIPerfAdvancedTestSuite_MaxAddrCount; addressCount *= 2 )
-		{
-			// Add a test case to resolve a domain name with
-			//
-			//     <aliasCount> CNAME records, <addressCount> A records, and <addressCount> AAAA records
-			//
-			// to its IPv4 and IPv6 addresses. Each iteration resolves a unique instance of such a domain name, which
-			// requires server queries.
-			
-			_GAIPerfWriteTestCaseTitle( title, aliasCount, addressCount, addressCount, kGAITestAddrType_Both,
-				inContext->defaultIterCount, true );
-			
-			err = GAITestCaseCreate( title, &testCase );
-			require_noerr( err, exit );
-			
-			for( i = 0; i < inContext->defaultIterCount; ++i )
-			{
-				err = GAITestCaseAddItem( testCase, aliasCount, addressCount, kGAIPerfStandardTTL,
-					kGAITestAddrType_Both, kGAITestAddrType_Both, inContext->iterTimeLimitMs, 1 );
-				require_noerr( err, exit );
-			}
-			
-			err = GAITesterAddTestCase( inContext->tester, testCase );
-			require_noerr( err, exit );
-			testCase = NULL;
-			
-			// Add a test case to resolve a domain name with
-			//
-			//     <aliasCount> CNAME records, <addressCount> A records, and <addressCount> AAAA records
-			//
-			// to its IPv4 and IPv6 addresses. A preliminary iteration resolves a unique domain name, which requires a server
-			// query. The subsequent iterations resolve the same domain name as the preliminary iteration, which should
-			// ideally require no server queries, i.e., the results should come from the cache.
-			
-			_GAIPerfWriteTestCaseTitle( title, aliasCount, addressCount, addressCount, kGAITestAddrType_Both,
-				inContext->defaultIterCount, false );
-			
-			err = GAITestCaseCreate( title, &testCase );
-			require_noerr( err, exit );
-			
-			err = GAITestCaseAddItem( testCase, aliasCount, addressCount, kGAIPerfStandardTTL,
-				kGAITestAddrType_Both, kGAITestAddrType_Both, inContext->iterTimeLimitMs, inContext->defaultIterCount + 1 );
-			require_noerr( err, exit );
-			
-			err = GAITesterAddTestCase( inContext->tester, testCase );
-			require_noerr( err, exit );
-			testCase = NULL;
-		}
-		
-		aliasCount = ( aliasCount == 0 ) ? 1 : ( 2 * aliasCount );
-	}
-	
-	// Finally, add a test case to resolve localhost to its IPv4 and IPv6 addresses.
-	
-	_GAIPerfWriteLocalHostTestCaseTitle( title, kGAITestAddrType_Both, inContext->defaultIterCount );
-	
-	err = GAITestCaseCreate( title, &testCase );
-	require_noerr( err, exit );
-	
-	err = GAITestCaseAddLocalHostItem( testCase, kGAITestAddrType_Both, inContext->iterTimeLimitMs,
-		inContext->defaultIterCount );
-	require_noerr( err, exit );
-	
-	err = GAITesterAddTestCase( inContext->tester, testCase );
-	require_noerr( err, exit );
-	testCase = NULL;
-	
-exit:
-	if( testCase ) GAITestCaseFree( testCase );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_GAIPerfWriteTestCaseTitle
-//===========================================================================================================================
-
-#define GAITestAddrTypeToRequestKeyValue( X ) (				\
-	( (X) == kGAITestAddrType_Both ) ? "ipv4\\,ipv6"	:	\
-	( (X) == kGAITestAddrType_IPv4 ) ? "ipv4"			:	\
-	( (X) == kGAITestAddrType_IPv6 ) ? "ipv6"			:	\
-									   "" )
-
-static void
-	_GAIPerfWriteTestCaseTitle(
-		char			inBuffer[ kTestCaseTitleBufferSize ],
-		unsigned int	inCNAMERecordCount,
-		unsigned int	inARecordCount,
-		unsigned int	inAAAARecordCount,
-		GAITestAddrType	inRequested,
-		unsigned int	inIterationCount,
-		Boolean			inIterationsAreUnique )
-{
-	SNPrintF( inBuffer, kTestCaseTitleBufferSize, "name=dynamic,cname=%u,a=%u,aaaa=%u,req=%s,iterations=%u%?s",
-		inCNAMERecordCount, inARecordCount, inAAAARecordCount, GAITestAddrTypeToRequestKeyValue( inRequested ),
-		inIterationCount, inIterationsAreUnique, ",unique" );
-}
-
-//===========================================================================================================================
-//	_GAIPerfWriteLocalHostTestCaseTitle
-//===========================================================================================================================
-
-static void
-	_GAIPerfWriteLocalHostTestCaseTitle(
-		char			inBuffer[ kTestCaseTitleBufferSize ],
-		GAITestAddrType	inRequested,
-		unsigned int	inIterationCount )
-{
-	SNPrintF( inBuffer, kTestCaseTitleBufferSize, "name=localhost,req=%s,iterations=%u",
-		GAITestAddrTypeToRequestKeyValue( inRequested ), inIterationCount );
-}
-
-//===========================================================================================================================
-//	GAIPerfAddBasicTestCases
-//===========================================================================================================================
-
-#define kGAIPerfBasicTestSuite_AliasCount		2
-#define kGAIPerfBasicTestSuite_AddrCount		4
-
-static OSStatus	GAIPerfAddBasicTestCases( GAIPerfContext *inContext )
-{
-	OSStatus			err;
-	GAITestCase *		testCase = NULL;
-	char				title[ kTestCaseTitleBufferSize ];
-	unsigned int		i;
-	
-	// Test Case #1:
-	// Resolve a domain name with
-	//
-	//     2 CNAME records, 4 A records, and 4 AAAA records
-	//
-	// to its IPv4 and IPv6 addresses. Each of the iterations resolves a unique domain name, which requires server
-	// queries.
-	
-	_GAIPerfWriteTestCaseTitle( title, kGAIPerfBasicTestSuite_AliasCount,
-		kGAIPerfBasicTestSuite_AddrCount, kGAIPerfBasicTestSuite_AddrCount, kGAITestAddrType_Both,
-		inContext->defaultIterCount, true );
-	
-	err = GAITestCaseCreate( title, &testCase );
-	require_noerr( err, exit );
-	
-	for( i = 0; i < inContext->defaultIterCount; ++i )
-	{
-		err = GAITestCaseAddItem( testCase, kGAIPerfBasicTestSuite_AliasCount, kGAIPerfBasicTestSuite_AddrCount,
-			kGAIPerfStandardTTL, kGAITestAddrType_Both, kGAITestAddrType_Both, inContext->iterTimeLimitMs, 1 );
-		require_noerr( err, exit );
-	}
-	
-	err = GAITesterAddTestCase( inContext->tester, testCase );
-	require_noerr( err, exit );
-	testCase = NULL;
-	
-	// Test Case #2:
-	// Resolve a domain name with
-	//
-	//     2 CNAME records, 4 A records, and 4 AAAA records
-	//
-	// to its IPv4 and IPv6 addresses. A preliminary iteration resolves a unique instance of such a domain name, which
-	// requires server queries. Each of the subsequent iterations resolves the same domain name as the preliminary
-	// iteration, which should ideally require no additional server queries, i.e., the results should come from the cache.
-	
-	_GAIPerfWriteTestCaseTitle( title, kGAIPerfBasicTestSuite_AliasCount,
-		kGAIPerfBasicTestSuite_AddrCount, kGAIPerfBasicTestSuite_AddrCount, kGAITestAddrType_Both,
-		inContext->defaultIterCount, false );
-	
-	err = GAITestCaseCreate( title, &testCase );
-	require_noerr( err, exit );
-	
-	err = GAITestCaseAddItem( testCase, kGAIPerfBasicTestSuite_AliasCount, kGAIPerfBasicTestSuite_AddrCount,
-		kGAIPerfStandardTTL, kGAITestAddrType_Both, kGAITestAddrType_Both, inContext->iterTimeLimitMs,
-		inContext->defaultIterCount + 1 );
-	require_noerr( err, exit );
-	
-	err = GAITesterAddTestCase( inContext->tester, testCase );
-	require_noerr( err, exit );
-	testCase = NULL;
-	
-	// Test Case #3:
-	// Each iteration resolves localhost to its IPv4 and IPv6 addresses.
-	
-	_GAIPerfWriteLocalHostTestCaseTitle( title, kGAITestAddrType_Both, inContext->defaultIterCount );
-	
-	err = GAITestCaseCreate( title, &testCase );
-	require_noerr( err, exit );
-	
-	err = GAITestCaseAddLocalHostItem( testCase, kGAITestAddrType_Both, inContext->iterTimeLimitMs,
-		inContext->defaultIterCount );
-	require_noerr( err, exit );
-	
-	err = GAITesterAddTestCase( inContext->tester, testCase );
-	require_noerr( err, exit );
-	testCase = NULL;
-	
-exit:
-	if( testCase ) GAITestCaseFree( testCase );
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAIPerfTesterStopHandler
-//===========================================================================================================================
-
-#define kGAIPerfResultsKey_Info				CFSTR( "info" )
-#define kGAIPerfResultsKey_TestCases		CFSTR( "testCases" )
-#define kGAIPerfResultsKey_Success			CFSTR( "success" )
-
-#define kGAIPerfInfoKey_CallDelay			CFSTR( "callDelayMs" )
-#define kGAIPerfInfoKey_Protocol			CFSTR( "protocol" )
-#define kGAIPerfInfoKey_ServerDelay			CFSTR( "serverDelayMs" )
-#define kGAIPerfInfoKey_SkippedPathEval		CFSTR( "skippedPathEval" )
-#define kGAIPerfInfoKey_UsedBadUDPMode		CFSTR( "usedBadUPDMode" )
-
-static void	GAIPerfTesterStopHandler( void *inContext, OSStatus inError )
-{
-	OSStatus					err;
-	GAIPerfContext * const		context = (GAIPerfContext *) inContext;
-	CFPropertyListRef			plist;
-	int							exitCode;
-	
-	err = inError;
-	require_noerr_quiet( err, exit );
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO="			// info
-			"{"
-				"%kO=%lli"	// callDelayMs
-				"%kO=%s"	// protocol
-				"%kO=%lli"	// serverDelayMs
-				"%kO=%b"	// skippedPathEval
-				"%kO=%b"	// usedBadUPDMode
-			"}"
-			"%kO=%O"		// testCases
-			"%kO=%b"		// success
-		"}",
-		kGAIPerfResultsKey_Info,
-		kGAIPerfInfoKey_CallDelay,			(int64_t) context->callDelayMs,
-		kGAIPerfInfoKey_Protocol,			_DNSProtocolToString( context->protocol ),
-		kGAIPerfInfoKey_ServerDelay,		(int64_t) context->serverDelayMs,
-		kGAIPerfInfoKey_SkippedPathEval,	context->skipPathEval,
-		kGAIPerfInfoKey_UsedBadUDPMode,		context->badUDPMode,
-		kGAIPerfResultsKey_TestCases,		context->testCaseResults,
-		kGAIPerfResultsKey_Success,			!context->testFailed );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( plist, context->outputFormat, context->outputFilePath );
-	CFRelease( plist );
-	require_noerr( err, exit );
-	
-exit:
-	exitCode = err ? 1 : ( context->testFailed ? 2 : 0 );
-	GAIPerfContextFree( context );
-	exit( exitCode );
-}
-
-//===========================================================================================================================
-//	GAIPerfResultsHandler
-//===========================================================================================================================
-
-// Keys for test case dictionary
-
-#define kGAIPerfTestCaseKey_Title				CFSTR( "title" )
-#define kGAIPerfTestCaseKey_StartTime			CFSTR( "startTime" )
-#define kGAIPerfTestCaseKey_EndTime				CFSTR( "endTime" )
-#define kGAIPerfTestCaseKey_Results				CFSTR( "results" )
-#define kGAIPerfTestCaseKey_FirstStats			CFSTR( "firstStats" )
-#define kGAIPerfTestCaseKey_ConnectionStats		CFSTR( "connectionStats" )
-#define kGAIPerfTestCaseKey_Stats				CFSTR( "stats" )
-
-// Keys for test case results array entry dictionaries
-
-#define kGAIPerfTestCaseResultKey_Name					CFSTR( "name" )
-#define kGAIPerfTestCaseResultKey_ConnectionTime		CFSTR( "connectionTimeUs" )
-#define kGAIPerfTestCaseResultKey_FirstTime				CFSTR( "firstTimeUs" )
-#define kGAIPerfTestCaseResultKey_Time					CFSTR( "timeUs" )
-
-// Keys for test case stats dictionaries
-
-#define kGAIPerfTestCaseStatsKey_Count		CFSTR( "count" )
-#define kGAIPerfTestCaseStatsKey_Min		CFSTR( "min" )
-#define kGAIPerfTestCaseStatsKey_Max		CFSTR( "max" )
-#define kGAIPerfTestCaseStatsKey_Mean		CFSTR( "mean" )
-#define kGAIPerfTestCaseStatsKey_StdDev		CFSTR( "sd" )
-
-typedef struct
-{
-	double		min;
-	double		max;
-	double		mean;
-	double		stdDev;
-	
-}	GAIPerfStats;
-
-#define GAIPerfStatsInit( X ) \
-	do { (X)->min = DBL_MAX; (X)->max = DBL_MIN; (X)->mean = 0.0; (X)->stdDev = 0.0; } while( 0 )
-
-static void
-	GAIPerfResultsHandler(
-		const char *				inCaseTitle,
-		NanoTime64					inCaseStartTime,
-		NanoTime64					inCaseEndTime,
-		const GAITestItemResult *	inResultArray,
-		size_t						inResultCount,
-		void *						inContext )
-{
-	OSStatus						err;
-	GAIPerfContext * const			context	= (GAIPerfContext *) inContext;
-	int								namesAreDynamic, namesAreUnique;
-	const char *					ptr;
-	size_t							startIndex;
-	CFMutableArrayRef				results	= NULL;
-	GAIPerfStats					stats, firstStats, connStats;
-	double							sum, firstSum, connSum;
-	size_t							keyValueLen, i;
-	uint32_t						count;
-	char							keyValue[ 16 ];	// Size must be at least strlen( "name=dynamic" ) + 1 bytes.
-	char							startTime[ 32 ];
-	char							endTime[ 32 ];
-	const GAITestItemResult *		result;
-	
-	// If this test case resolves the same "d.test." name in each iteration (title contains the "name=dynamic" key-value
-	// pair, but not the "unique" key), then don't count the first iteration, whose purpose is to populate the cache with
-	// the domain name's CNAME, A, and AAAA records.
-	
-	namesAreDynamic	= false;
-	namesAreUnique	= false;
-	ptr = inCaseTitle;
-	while( _ParseQuotedEscapedString( ptr, NULL, ",", keyValue, sizeof( keyValue ), &keyValueLen, NULL, &ptr ) )
-	{
-		if( strnicmpx( keyValue, keyValueLen, "name=dynamic" ) == 0 )
-		{
-			namesAreDynamic = true;
-		}
-		else if( strnicmpx( keyValue, keyValueLen, "unique" ) == 0 )
-		{
-			namesAreUnique = true;
-		}
-		if( namesAreDynamic && namesAreUnique ) break;
-	}
-	
-	startIndex = ( ( inResultCount > 0 ) && namesAreDynamic && !namesAreUnique ) ? 1 : 0;
-	results = CFArrayCreateMutable( NULL, (CFIndex)( inResultCount - startIndex ), &kCFTypeArrayCallBacks );
-	require_action( results, exit, err = kNoMemoryErr );
-	
-	GAIPerfStatsInit( &stats );
-	GAIPerfStatsInit( &firstStats );
-	GAIPerfStatsInit( &connStats );
-	
-	sum			= 0.0;
-	firstSum	= 0.0;
-	connSum		= 0.0;
-	count		= 0;
-	for( i = startIndex; i < inResultCount; ++i )
-	{
-		double		value;
-		
-		result = &inResultArray[ i ];
-		
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, results,
-			"{"
-				"%kO=%s"	// name
-				"%kO=%lli"	// connectionTimeUs
-				"%kO=%lli"	// firstTimeUs
-				"%kO=%lli"	// timeUs
-				"%kO=%lli"	// error
-			"}",
-			kGAIPerfTestCaseResultKey_Name,				result->name,
-			kGAIPerfTestCaseResultKey_ConnectionTime,	(int64_t) result->connectionTimeUs,
-			kGAIPerfTestCaseResultKey_FirstTime,		(int64_t) result->firstTimeUs,
-			kGAIPerfTestCaseResultKey_Time,				(int64_t) result->timeUs,
-			CFSTR( "error" ),							(int64_t) result->error );
-		require_noerr( err, exit );
-		
-		if( !result->error )
-		{
-			value = (double) result->timeUs;
-			if( value < stats.min ) stats.min = value;
-			if( value > stats.max ) stats.max = value;
-			sum += value;
-			
-			value = (double) result->firstTimeUs;
-			if( value < firstStats.min ) firstStats.min = value;
-			if( value > firstStats.max ) firstStats.max = value;
-			firstSum += value;
-			
-			value = (double) result->connectionTimeUs;
-			if( value < connStats.min ) connStats.min = value;
-			if( value > connStats.max ) connStats.max = value;
-			connSum += value;
-			
-			++count;
-		}
-		else
-		{
-			context->testFailed = true;
-		}
-	}
-	
-	if( count > 0 )
-	{
-		stats.mean		= sum      / (double) count;
-		firstStats.mean	= firstSum / (double) count;
-		connStats.mean	= connSum  / (double) count;
-		
-		sum			= 0.0;
-		firstSum	= 0.0;
-		connSum		= 0.0;
-		for( i = startIndex; i < inResultCount; ++i )
-		{
-			double		diff;
-			
-			result = &inResultArray[ i ];
-			if( result->error ) continue;
-			
-			diff		 = stats.mean - (double) result->timeUs;
-			sum			+= ( diff * diff );
-			
-			diff		 = firstStats.mean - (double) result->firstTimeUs;
-			firstSum	+= ( diff * diff );
-			
-			diff		 = connStats.mean - (double) result->connectionTimeUs;
-			connSum		+= ( diff * diff );
-		}
-		stats.stdDev		= sqrt( sum      / (double) count );
-		firstStats.stdDev	= sqrt( firstSum / (double) count );
-		connStats.stdDev	= sqrt( connSum  / (double) count );
-	}
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, context->testCaseResults,
-		"{"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%O"
-			"%kO="
-			"{"
-				"%kO=%lli"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-			"}"
-			"%kO="
-			"{"
-				"%kO=%lli"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-			"}"
-			"%kO="
-			"{"
-				"%kO=%lli"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-				"%kO=%f"
-			"}"
-		"}",
-		kGAIPerfTestCaseKey_Title,			inCaseTitle,
-		kGAIPerfTestCaseKey_StartTime,		_NanoTime64ToTimestamp( inCaseStartTime, startTime, sizeof( startTime ) ),
-		kGAIPerfTestCaseKey_EndTime,		_NanoTime64ToTimestamp( inCaseEndTime, endTime, sizeof( endTime ) ),
-		kGAIPerfTestCaseKey_Results,		results,
-		kGAIPerfTestCaseKey_Stats,
-		kGAIPerfTestCaseStatsKey_Count,		(int64_t) count,
-		kGAIPerfTestCaseStatsKey_Min,		stats.min,
-		kGAIPerfTestCaseStatsKey_Max,		stats.max,
-		kGAIPerfTestCaseStatsKey_Mean,		stats.mean,
-		kGAIPerfTestCaseStatsKey_StdDev,	stats.stdDev,
-		kGAIPerfTestCaseKey_FirstStats,
-		kGAIPerfTestCaseStatsKey_Count,		(int64_t) count,
-		kGAIPerfTestCaseStatsKey_Min,		firstStats.min,
-		kGAIPerfTestCaseStatsKey_Max,		firstStats.max,
-		kGAIPerfTestCaseStatsKey_Mean,		firstStats.mean,
-		kGAIPerfTestCaseStatsKey_StdDev,	firstStats.stdDev,
-		kGAIPerfTestCaseKey_ConnectionStats,
-		kGAIPerfTestCaseStatsKey_Count,		(int64_t) count,
-		kGAIPerfTestCaseStatsKey_Min,		connStats.min,
-		kGAIPerfTestCaseStatsKey_Max,		connStats.max,
-		kGAIPerfTestCaseStatsKey_Mean,		connStats.mean,
-		kGAIPerfTestCaseStatsKey_StdDev,	connStats.stdDev );
-	require_noerr( err, exit );
-	
-exit:
-	CFReleaseNullSafe( results );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	GAIPerfSignalHandler
-//===========================================================================================================================
-
-static void	GAIPerfSignalHandler( void *inContext )
-{
-	GAIPerfContext * const		context = (GAIPerfContext *) inContext;
-	
-	if( !context->tester ) exit( 1 );
-	GAITesterStop( context->tester );
-	context->tester = NULL;
-}
-
-//===========================================================================================================================
-//	GAITesterCreate
-//===========================================================================================================================
-
-// A character set of lower-case alphabet characters and digits and a string length of six allows for 36^6 = 2,176,782,336
-// possible strings to use in the Tag label.
-
-#define kGAITesterTagStringLen		6
-
-typedef struct GAITestItem		GAITestItem;
-struct GAITestItem
-{
-	GAITestItem *		next;				// Next test item in list.
-	char *				name;				// Domain name to resolve.
-	uint64_t			connectionTimeUs;	// Time in microseconds that it took to create a DNS-SD connection.
-	uint64_t			firstTimeUs;		// Time in microseconds that it took to get the first address result.
-	uint64_t			timeUs;				// Time in microseconds that it took to get all expected address results.
-	unsigned int		addressCount;		// Address count of the domain name, i.e., the Count label argument.
-	OSStatus			error;				// Current status/error.
-	unsigned int		timeLimitMs;		// Time limit in milliseconds for the test item's completion.
-	Boolean				hasV4;				// True if the domain name has one or more IPv4 addresses.
-	Boolean				hasV6;				// True if the domain name has one or more IPv6 addresses.
-	Boolean				wantV4;				// True if DNSServiceGetAddrInfo() should be called to get IPv4 addresses.
-	Boolean				wantV6;				// True if DNSServiceGetAddrInfo() should be called to get IPv6 addresses.
-};
-
-struct GAITestCase
-{
-	GAITestCase *		next;		// Next test case in list.
-	GAITestItem *		itemList;	// List of test items.
-	char *				title;		// Title of the test case.
-};
-
-struct GAITesterPrivate
-{
-	CFRuntimeBase					base;				// CF object base.
-	dispatch_queue_t				queue;				// Serial work queue.
-	DNSServiceRef					connection;			// Reference to the shared DNS-SD connection.
-	DNSServiceRef					getAddrInfo;		// Reference to the current DNSServiceGetAddrInfo operation.
-	GAITestCase *					caseList;			// List of test cases.
-	GAITestCase *					currentCase;		// Pointer to the current test case.
-	GAITestItem *					currentItem;		// Pointer to the current test item.
-	const char *					protocolStr;		// DNS protocol to use, e.g., Do53, DoT, or DoH.
-	NanoTime64						caseStartTime;		// Start time of current test case in Unix time as nanoseconds.
-	NanoTime64						caseEndTime;		// End time of current test case in Unix time as nanoseconds.
-	unsigned int					callDelayMs;		// Amount of time to wait before calling DNSServiceGetAddrInfo().
-	Boolean							skipPathEval;		// True if DNSServiceGetAddrInfo() path evaluation is to be skipped.
-	Boolean							stopped;			// True if the tester has been stopped.
-	Boolean							badUDPMode;			// True if the test DNS server is to run in Bad UDP mode.
-	dispatch_source_t				timer;				// Timer for enforcing a test item's time limit.
-	pcap_t *						pcap;				// Captures traffic between mDNSResponder and test DNS server.
-	pid_t							serverPID;			// PID of the test DNS server.
-	int								serverDelayMs;		// Additional time to have the server delay its responses by.
-	int								serverDefaultTTL;	// Default TTL for the server's records.
-	GAITesterStopHandler_f			stopHandler;		// User's stop handler.
-	void *							stopContext;		// User's event handler context.
-	GAITesterResultsHandler_f		resultsHandler;		// User's results handler.
-	void *							resultsContext;		// User's results handler context.
-	int								probeTryCount;		// Number of remaining probe queries.
-	
-	// Variables for current test item.
-	
-	uint64_t						bitmapV4;		// Bitmap of IPv4 results that have yet to be received.
-	uint64_t						bitmapV6;		// Bitmap of IPv6 results that have yet to be received.
-	uint64_t						startTicks;		// Start ticks of DNSServiceGetAddrInfo().
-	uint64_t						connTicks;		// Ticks when the connection was created.
-	uint64_t						firstTicks;		// Ticks when the first DNSServiceGetAddrInfo result was received.
-	uint64_t						endTicks;		// Ticks when the last DNSServiceGetAddrInfo result was received.
-	Boolean							gotFirstResult;	// True if the first result has been received.
-};
-
-CF_CLASS_DEFINE( GAITester );
-
-static void		_GAITesterStartNextTest( GAITesterRef inTester );
-static OSStatus	_GAITesterCreatePacketCapture( pcap_t **outPCap );
-static void		_GAITesterProbeTimerEventHandler( void *inContext );
-static void		_GAITesterTimeout( void *inContext );
-static void DNSSD_API
-	_GAITesterProbeCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void DNSSD_API
-	_GAITesterGetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void		_GAITesterCompleteCurrentTest( GAITesterRef inTester, OSStatus inError );
-
-#define ForgetPacketCapture( X )		ForgetCustom( X, pcap_close )
-
-static OSStatus
-	GAITestItemCreate(
-		const char *	inName,
-		unsigned int	inAddressCount,
-		GAITestAddrType	inHasAddrs,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		GAITestItem **	outItem );
-static OSStatus	GAITestItemDup( const GAITestItem *inItem, GAITestItem **outItem );
-static void		GAITestItemFree( GAITestItem *inItem );
-
-static OSStatus
-	GAITesterCreate(
-		dispatch_queue_t	inQueue,
-		DNSProtocol			inProtocol,
-		unsigned int		inCallDelayMs,
-		int					inServerDelayMs,
-		int					inServerDefaultTTL,
-		Boolean				inSkipPathEvaluation,
-		Boolean				inBadUDPMode,
-		GAITesterRef *		outTester )
-{
-	OSStatus			err;
-	GAITesterRef		obj = NULL;
-	
-	CF_OBJECT_CREATE( GAITester, obj, err, exit );
-	
-	obj->protocolStr = _DNSProtocolToString( inProtocol );
-	require_action_quiet( obj->protocolStr, exit, err = kValueErr );
-	
-	ReplaceDispatchQueue( &obj->queue, inQueue );
-	obj->callDelayMs		= inCallDelayMs;
-	obj->serverPID			= -1;
-	obj->serverDelayMs		= inServerDelayMs;
-	obj->serverDefaultTTL	= inServerDefaultTTL;
-	obj->skipPathEval		= inSkipPathEvaluation;
-	obj->badUDPMode			= inBadUDPMode;
-	
-	*outTester = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	CFReleaseNullSafe( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_GAITesterFinalize
-//===========================================================================================================================
-
-static void	_GAITesterFinalize( CFTypeRef inObj )
-{
-	GAITesterRef const		me = (GAITesterRef) inObj;
-	GAITestCase *			testCase;
-	
-	check( !me->getAddrInfo );
-	check( !me->connection );
-	check( !me->timer );
-	dispatch_forget( &me->queue );
-	while( ( testCase = me->caseList ) != NULL )
-	{
-		me->caseList = testCase->next;
-		GAITestCaseFree( testCase );
-	}
-}
-
-//===========================================================================================================================
-//	GAITesterStart
-//===========================================================================================================================
-
-static void	_GAITesterStart( void *inContext );
-static void	_GAITesterStop( GAITesterRef me, OSStatus inError );
-
-static void	GAITesterStart( GAITesterRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _GAITesterStart );
-}
-
-static void	_GAITesterStart( void *inContext )
-{
-	OSStatus				err;
-	GAITesterRef const		me = (GAITesterRef) inContext;
-	
-	err = _SpawnCommand( &me->serverPID, NULL, NULL,
-		"dnssdutil server --loopback --follow %lld --protocol %s%?s%?d%?s%?d%?s",
-		(int64_t) getpid(),
-		me->protocolStr,
-		me->serverDefaultTTL >= 0,	" --defaultTTL ",
-		me->serverDefaultTTL >= 0,	me->serverDefaultTTL,
-		me->serverDelayMs    >= 0,	" --responseDelay ",
-		me->serverDelayMs    >= 0,	me->serverDelayMs,
-		me->badUDPMode,				" --badUDPMode" );
-	require_noerr_quiet( err, exit );
-	
-	me->probeTryCount = 4;
-	err = DispatchTimerCreate( DISPATCH_TIME_NOW, 1 * kNanosecondsPerSecond, 0, me->queue, _GAITesterProbeTimerEventHandler,
-		NULL, me, &me->timer );
-	require_noerr( err, exit );
-	
-	dispatch_resume( me->timer );
-	
-exit:
-	if( err ) _GAITesterStop( me, err );
-}
-
-//===========================================================================================================================
-//	GAITesterStop
-//===========================================================================================================================
-
-static void	_GAITesterUserStop( void *inContext );
-
-static void	GAITesterStop( GAITesterRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _GAITesterUserStop );
-}
-
-static void	_GAITesterUserStop( void *inContext )
-{
-	GAITesterRef const		me = (GAITesterRef) inContext;
-	
-	_GAITesterStop( me, kCanceledErr );
-	CFRelease( me );
-}
-
-static void	_GAITesterStop( GAITesterRef me, OSStatus inError )
-{
-	OSStatus		err;
-	
-	ForgetPacketCapture( &me->pcap );
-	dispatch_source_forget( &me->timer );
-	DNSServiceForget( &me->getAddrInfo );
-	DNSServiceForget( &me->connection );
-	if( me->serverPID != -1 )
-	{
-		err = kill( me->serverPID, SIGTERM );
-		err = map_global_noerr_errno( err );
-		check_noerr( err );
-		me->serverPID = -1;
-	}
-	
-	if( !me->stopped )
-	{
-		me->stopped = true;
-		if( me->stopHandler ) me->stopHandler( me->stopContext, inError );
-		CFRelease( me );
-	}
-}
-
-//===========================================================================================================================
-//	GAITesterAddTestCase
-//===========================================================================================================================
-
-static OSStatus	GAITesterAddTestCase( GAITesterRef me, GAITestCase *inCase )
-{
-	OSStatus			err;
-	GAITestCase **		ptr;
-	
-	require_action_quiet( inCase->itemList, exit, err = kCountErr );
-	
-	for( ptr = &me->caseList; *ptr; ptr = &( *ptr )->next ) {}
-	*ptr = inCase;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITesterSetStopHandler
-//===========================================================================================================================
-
-static void	GAITesterSetStopHandler( GAITesterRef me, GAITesterStopHandler_f inStopHandler, void *inStopContext )
-{
-	me->stopHandler = inStopHandler;
-	me->stopContext = inStopContext;
-}
-
-//===========================================================================================================================
-//	GAITesterSetResultsHandler
-//===========================================================================================================================
-
-static void	GAITesterSetResultsHandler( GAITesterRef me, GAITesterResultsHandler_f inResultsHandler, void *inResultsContext )
-{
-	me->resultsHandler = inResultsHandler;
-	me->resultsContext = inResultsContext;
-}
-
-//===========================================================================================================================
-//	_GAITesterStartNextTest
-//===========================================================================================================================
-
-static void	_GAITesterStartNextTest( GAITesterRef me )
-{
-	OSStatus				err;
-	GAITestItem *			item;
-	DNSServiceFlags			flags;
-	DNSServiceProtocol		protocols;
-	int						done = false;
-	
-	if( me->currentItem ) me->currentItem = me->currentItem->next;
-	
-	if( !me->currentItem )
-	{
-		if( me->currentCase )
-		{
-			// No more test items means that the current test case has completed.
-			
-			me->caseEndTime = NanoTimeGetCurrent();
-			
-			if( me->resultsHandler )
-			{
-				size_t					resultCount, i;
-				GAITestItemResult *		resultArray;
-				
-				resultCount	= 0;
-				for( item = me->currentCase->itemList; item; item = item->next ) ++resultCount;
-				check( resultCount > 0 );
-				
-				resultArray = (GAITestItemResult *) calloc( resultCount, sizeof( *resultArray ) );
-				require_action( resultArray, exit, err = kNoMemoryErr );
-				
-				item = me->currentCase->itemList;
-				for( i = 0; i < resultCount; ++i )
-				{
-					resultArray[ i ].name				= item->name;
-					resultArray[ i ].connectionTimeUs	= item->connectionTimeUs;
-					resultArray[ i ].firstTimeUs		= item->firstTimeUs;
-					resultArray[ i ].timeUs				= item->timeUs;
-					resultArray[ i ].error				= item->error;
-					item = item->next;
-				}
-				me->resultsHandler( me->currentCase->title, me->caseStartTime, me->caseEndTime, resultArray, resultCount,
-					me->resultsContext );
-				ForgetMem( &resultArray );
-			}
-			
-			me->currentCase = me->currentCase->next;
-			if( !me->currentCase )
-			{
-				done = true;
-				err = kNoErr;
-				goto exit;
-			}
-		}
-		else
-		{
-			me->currentCase = me->caseList;
-		}
-		require_action_quiet( me->currentCase->itemList, exit, err = kInternalErr );
-		me->currentItem = me->currentCase->itemList;
-	}
-	
-	item = me->currentItem;
-	check( ( item->addressCount >= 1 ) && ( item->addressCount <= 64 ) );
-	
-	if(      !item->wantV4 )			me->bitmapV4 = 0;
-	else if( !item->hasV4 )				me->bitmapV4 = 1;
-	else if(  item->addressCount < 64 )	me->bitmapV4 = ( UINT64_C( 1 ) << item->addressCount ) - 1;
-	else								me->bitmapV4 =  ~UINT64_C( 0 );
-	
-	if(      !item->wantV6 )			me->bitmapV6 = 0;
-	else if( !item->hasV6 )				me->bitmapV6 = 1;
-	else if(  item->addressCount < 64 )	me->bitmapV6 = ( UINT64_C( 1 ) << item->addressCount ) - 1;
-	else								me->bitmapV6 =  ~UINT64_C( 0 );
-	check( ( me->bitmapV4 != 0 ) || ( me->bitmapV6 != 0 ) );
-	me->gotFirstResult = false;
-	
-	// Perform preliminary tasks if this is the start of a new test case.
-	
-	if( item == me->currentCase->itemList )
-	{
-		// Flush mDNSResponder's cache.
-		
-		err = systemf( NULL, "killall -HUP mDNSResponder" );
-		require_noerr( err, exit );
-		sleep( 1 );
-		
-		me->caseStartTime	= NanoTimeGetCurrent();
-		me->caseEndTime		= kNanoTime_Invalid;
-	}
-	
-	// Start a packet capture for Do53 traffic.
-	
-	if( strcasecmp( me->protocolStr, kDNSProtocolStr_Do53 ) == 0 )
-	{
-		check( !me->pcap );
-		err = _GAITesterCreatePacketCapture( &me->pcap );
-		require_noerr( err, exit );
-	}
-	
-	// Start timer for test item's time limit.
-	
-	check( !me->timer );
-	if( item->timeLimitMs > 0 )
-	{
-		unsigned int		timeLimitMs;
-		
-		timeLimitMs = item->timeLimitMs;
-		if( me->callDelayMs   > 0 ) timeLimitMs += (unsigned int) me->callDelayMs;
-		if( me->serverDelayMs > 0 ) timeLimitMs += (unsigned int) me->serverDelayMs;
-		
-		err = DispatchTimerCreate( dispatch_time_milliseconds( timeLimitMs ), DISPATCH_TIME_FOREVER,
-			( (uint64_t) timeLimitMs ) * kNanosecondsPerMillisecond / 10,
-			me->queue, _GAITesterTimeout, NULL, me, &me->timer );
-		require_noerr( err, exit );
-		dispatch_resume( me->timer );
-	}
-	
-	// Call DNSServiceGetAddrInfo().
-	
-	if( me->callDelayMs > 0 ) usleep( ( (useconds_t) me->callDelayMs ) * kMicrosecondsPerMillisecond );
-	
-	flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsReturnIntermediates;
-	if( me->skipPathEval ) flags |= kDNSServiceFlagsPathEvaluationDone;
-	
-	protocols = 0;
-	if( item->wantV4 ) protocols |= kDNSServiceProtocol_IPv4;
-	if( item->wantV6 ) protocols |= kDNSServiceProtocol_IPv6;
-	
-	me->startTicks = UpTicks();
-	
-	check( !me->connection );
-	err = DNSServiceCreateConnection( &me->connection );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( me->connection, me->queue );
-	require_noerr( err, exit );
-	
-	me->connTicks = UpTicks();
-	
-	check( !me->getAddrInfo );
-	me->getAddrInfo = me->connection;
-	err = DNSServiceGetAddrInfo( &me->getAddrInfo, flags, kDNSServiceInterfaceIndexAny, protocols, item->name,
-		_GAITesterGetAddrInfoCallback, me );
-	require_noerr( err, exit );
-	
-exit:
-	if( err || done ) _GAITesterStop( me, err );
-}
-
-//===========================================================================================================================
-//	_GAITesterCreatePacketCapture
-//===========================================================================================================================
-
-static OSStatus	_GAITesterCreatePacketCapture( pcap_t **outPCap )
-{
-	OSStatus				err;
-	pcap_t *				pcap;
-	struct bpf_program		program;
-	char					errBuf[ PCAP_ERRBUF_SIZE ];
-	
-	pcap = pcap_create( "lo0", errBuf );
-	require_action_string( pcap, exit, err = kUnknownErr, errBuf );
-	
-	err = pcap_set_buffer_size( pcap, 512 * kBytesPerKiloByte );
-	require_noerr_action( err, exit, err = kUnknownErr );
-	
-	err = pcap_set_snaplen( pcap, 512 );
-	require_noerr_action( err, exit, err = kUnknownErr );
-	
-	err = pcap_set_immediate_mode( pcap, 0 );
-	require_noerr_action_string( err, exit, err = kUnknownErr, pcap_geterr( pcap ) );
-	
-	err = pcap_activate( pcap );
-	require_noerr_action_string( err, exit, err = kUnknownErr, pcap_geterr( pcap ) );
-	
-	err = pcap_setdirection( pcap, PCAP_D_INOUT );
-	require_noerr_action_string( err, exit, err = kUnknownErr, pcap_geterr( pcap ) );
-	
-	err = pcap_setnonblock( pcap, 1, errBuf );
-	require_noerr_action_string( err, exit, err = kUnknownErr, errBuf );
-	
-	err = pcap_compile( pcap, &program, "udp port 53", 1, PCAP_NETMASK_UNKNOWN );
-	require_noerr_action_string( err, exit, err = kUnknownErr, pcap_geterr( pcap ) );
-	
-	err = pcap_setfilter( pcap, &program );
-	pcap_freecode( &program );
-	require_noerr_action_string( err, exit, err = kUnknownErr, pcap_geterr( pcap ) );
-	
-	*outPCap = pcap;
-	pcap = NULL;
-	
-exit:
-	if( pcap ) pcap_close( pcap );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_GAITesterProbeTimerEventHandler
-//===========================================================================================================================
-
-static void	_GAITesterProbeTimerEventHandler( void *inContext )
-{
-	OSStatus				err;
-	GAITesterRef const		me = (GAITesterRef) inContext;
-	
-	if( me->probeTryCount > 0 )
-	{
-		DNSServiceFlags		flags;
-		char				name[ 64 ];
-		char				tag[ kGAITesterTagStringLen + 1 ];
-		
-		flags = 0;
-		if( me->skipPathEval ) flags |= kDNSServiceFlagsPathEvaluationDone;
-		
-		SNPrintF( name, sizeof( name ), "tag-gaitester-probe-%s.ipv4.d.test.",
-			_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-		
-		DNSServiceForget( &me->getAddrInfo );
-		err = DNSServiceGetAddrInfo( &me->getAddrInfo, flags, kDNSServiceInterfaceIndexAny, kDNSServiceProtocol_IPv4, name,
-			_GAITesterProbeCallback, me );
-		require_noerr( err, exit );
-		
-		err = DNSServiceSetDispatchQueue( me->getAddrInfo, me->queue );
-		require_noerr( err, exit );
-		
-		--me->probeTryCount;
-	}
-	else
-	{
-		err = kNotPreparedErr;
-	}
-	
-exit:
-	if( err ) _GAITesterStop( me, err );
-}
-
-//===========================================================================================================================
-//	_GAITesterTimeout
-//===========================================================================================================================
-
-static void	_GAITesterTimeout( void *inContext )
-{
-	GAITesterRef const		me = (GAITesterRef) inContext;
-	
-	_GAITesterCompleteCurrentTest( me, kTimeoutErr );
-}
-
-//===========================================================================================================================
-//	_GAITesterProbeCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_GAITesterProbeCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	GAITesterRef const		me = (GAITesterRef) inContext;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inHostname );
-	Unused( inSockAddr );
-	Unused( inTTL );
-	
-	if( ( inFlags & kDNSServiceFlagsAdd ) && !inError )
-	{
-		dispatch_source_forget( &me->timer );
-		DNSServiceForget( &me->getAddrInfo );
-		
-		_GAITesterStartNextTest( me );
-	}
-}
-
-//===========================================================================================================================
-//	_GAITesterGetAddrInfoCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_GAITesterGetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus						err;
-	GAITesterRef const				me		= (GAITesterRef) inContext;
-	GAITestItem * const				item	= me->currentItem;
-	const sockaddr_ip * const		sip		= (const sockaddr_ip *) inSockAddr;
-	uint64_t						nowTicks;
-	uint64_t *						bitmapPtr;
-	uint64_t						bitmask;
-	int								hasAddr;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inHostname );
-	Unused( inTTL );
-	
-	nowTicks = UpTicks();
-	
-	require_action_quiet( inFlags & kDNSServiceFlagsAdd, exit, err = kFlagErr );
-	
-	// Check if we were expecting an IP address result of this type.
-	
-	if( sip->sa.sa_family == AF_INET )
-	{
-		bitmapPtr	= &me->bitmapV4;
-		hasAddr		= item->hasV4;
-	}
-	else if( sip->sa.sa_family == AF_INET6 )
-	{
-		bitmapPtr	= &me->bitmapV6;
-		hasAddr		= item->hasV6;
-	}
-	else
-	{
-		err = kTypeErr;
-		goto exit;
-	}
-	
-	bitmask = 0;
-	if( hasAddr )
-	{
-		uint32_t		addrOffset;
-		
-		require_noerr_action_quiet( inError, exit, err = inError );
-		
-		if( sip->sa.sa_family == AF_INET )
-		{
-			const uint32_t		addrV4 = ntohl( sip->v4.sin_addr.s_addr );
-			
-			if( strcasecmp( item->name, "localhost." ) == 0 )
-			{
-				if( addrV4 == INADDR_LOOPBACK ) bitmask = 1;
-			}
-			else
-			{
-				addrOffset = addrV4 - kDNSServerBaseAddrV4;
-				if( ( addrOffset >= 1 ) && ( addrOffset <= item->addressCount ) )
-				{
-					bitmask = UINT64_C( 1 ) << ( addrOffset - 1 );
-				}
-			}
-		}
-		else
-		{
-			const uint8_t * const		addrV6 = sip->v6.sin6_addr.s6_addr;
-			
-			if( strcasecmp( item->name, "localhost." ) == 0 )
-			{
-				if( memcmp( addrV6, in6addr_loopback.s6_addr, 16 ) == 0 ) bitmask = 1;
-			}
-			else if( memcmp( addrV6, kDNSServerBaseAddrV6, 15 ) == 0 )
-			{
-				addrOffset = addrV6[ 15 ];
-				if( ( addrOffset >= 1 ) && ( addrOffset <= item->addressCount ) )
-				{
-					bitmask = UINT64_C( 1 ) << ( addrOffset - 1 );
-				}
-			}
-		}
-	}
-	else
-	{
-		require_action_quiet( inError == kDNSServiceErr_NoSuchRecord, exit, err = inError ? inError : kUnexpectedErr );
-		bitmask = 1;
-	}
-	require_action_quiet( bitmask != 0, exit, err = kValueErr );
-	require_action_quiet( *bitmapPtr & bitmask, exit, err = kDuplicateErr );
-	
-	*bitmapPtr &= ~bitmask;
-	if( !me->gotFirstResult )
-	{
-		me->firstTicks		= nowTicks;
-		me->gotFirstResult	= true;
-	}
-	err = kNoErr;
-	
-exit:
-	if( err || ( ( me->bitmapV4 == 0 ) && ( me->bitmapV6 == 0 ) ) )
-	{
-		me->endTicks = nowTicks;
-		_GAITesterCompleteCurrentTest( me, err );
-	}
-}
-
-//===========================================================================================================================
-//	_GAITesterCompleteCurrentTest
-//===========================================================================================================================
-
-static OSStatus
-	_GAITesterGetDNSMessageFromPacket(
-		const uint8_t *		inPacketPtr,
-		size_t				inPacketLen,
-		const uint8_t **	outMsgPtr,
-		size_t *			outMsgLen );
-
-static void	_GAITesterCompleteCurrentTest( GAITesterRef me, OSStatus inError )
-{
-	OSStatus				err;
-	GAITestItem * const		item	= me->currentItem;
-	struct timeval			timeStamps[ 4 ];
-	struct timeval *		tsPtr;
-	struct timeval *		tsQA	= NULL;
-	struct timeval *		tsQAAAA	= NULL;
-	struct timeval *		tsRA	= NULL;
-	struct timeval *		tsRAAAA	= NULL;
-	struct timeval *		t1;
-	struct timeval *		t2;
-	int64_t					idleTimeUs;
-	uint8_t					name[ kDomainNameLengthMax ];
-	
-	dispatch_source_forget( &me->timer );
-	DNSServiceForget( &me->getAddrInfo );
-	DNSServiceForget( &me->connection );
-	
-	item->error = inError;
-	if( item->error )
-	{
-		err = kNoErr;
-		goto exit;
-	}
-	
-	err = DomainNameFromString( name, item->name, NULL );
-	require_noerr( err, exit );
-	
-	tsPtr = &timeStamps[ 0 ];
-	if( me->pcap )
-	{
-		for( ;; )
-		{
-			int							status;
-			struct pcap_pkthdr *		pktHdr;
-			const uint8_t *				packet;
-			const uint8_t *				msgPtr;
-			size_t						msgLen;
-			const DNSHeader *			hdr;
-			unsigned int				flags;
-			const uint8_t *				ptr;
-			uint16_t					qtype, qclass;
-			uint8_t						qname[ kDomainNameLengthMax ];
-			
-			status = pcap_next_ex( me->pcap, &pktHdr, &packet );
-			if( status != 1 ) break;
-			if( _GAITesterGetDNSMessageFromPacket( packet, pktHdr->caplen, &msgPtr, &msgLen ) != kNoErr ) continue;
-			if( msgLen < kDNSHeaderLength ) continue;
-			
-			hdr = (const DNSHeader *) msgPtr;
-			flags = DNSHeaderGetFlags( hdr );
-			if( DNSFlagsGetOpCode( flags ) != kDNSOpCode_Query ) continue;
-			if( DNSHeaderGetQuestionCount( hdr ) < 1 ) continue;
-			
-			ptr = (const uint8_t *) &hdr[ 1 ];
-			if( DNSMessageExtractQuestion( msgPtr, msgLen, ptr, qname, &qtype, &qclass, NULL ) != kNoErr ) continue;
-			if( qclass != kDNSServiceClass_IN ) continue;
-			if( !DomainNameEqual( qname, name ) ) continue;
-			
-			if( item->wantV4 && ( qtype == kDNSServiceType_A ) )
-			{
-				if( flags & kDNSHeaderFlag_Response )
-				{
-					if( tsQA && !tsRA )
-					{
-						tsRA  = tsPtr++;
-						*tsRA = pktHdr->ts;
-					}
-				}
-				else if( !tsQA )
-				{
-					tsQA  = tsPtr++;
-					*tsQA = pktHdr->ts;
-				}
-			}
-			else if( item->wantV6 && ( qtype == kDNSServiceType_AAAA ) )
-			{
-				if( flags & kDNSHeaderFlag_Response )
-				{
-					if( tsQAAAA && !tsRAAAA )
-					{
-						tsRAAAA  = tsPtr++;
-						*tsRAAAA = pktHdr->ts;
-					}
-				}
-				else if( !tsQAAAA )
-				{
-					tsQAAAA  = tsPtr++;
-					*tsQAAAA = pktHdr->ts;
-				}
-			}
-		}
-	}
-	// t1 is the time when the last query was sent.
-	
-	if( tsQA && tsQAAAA )	t1 = TIMEVAL_GT( *tsQA, *tsQAAAA ) ? tsQA : tsQAAAA;
-	else					t1 = tsQA ? tsQA : tsQAAAA;
-	
-	// t2 is when the first response was received.
-	
-	if( tsRA && tsRAAAA )	t2 = TIMEVAL_LT( *tsRA, *tsRAAAA ) ? tsRA : tsRAAAA;
-	else					t2 = tsRA ? tsRA : tsRAAAA;
-	
-	if( t1 && t2 )
-	{
-		idleTimeUs = TIMEVAL_USEC64_DIFF( *t2, *t1 );
-		if( idleTimeUs < 0 ) idleTimeUs = 0;
-	}
-	else
-	{
-		idleTimeUs = 0;
-	}
-	
-	item->connectionTimeUs	= UpTicksToMicroseconds( me->connTicks  - me->startTicks );
-	item->firstTimeUs		= UpTicksToMicroseconds( me->firstTicks - me->connTicks  ) - (uint64_t) idleTimeUs;
-	item->timeUs			= UpTicksToMicroseconds( me->endTicks   - me->connTicks  ) - (uint64_t) idleTimeUs;
-	
-exit:
-	ForgetPacketCapture( &me->pcap );
-	if( err )	_GAITesterStop( me, err );
-	else		_GAITesterStartNextTest( me );
-}
-
-//===========================================================================================================================
-//	_GAITesterGetDNSMessageFromPacket
-//===========================================================================================================================
-
-#define kHeaderSizeNullLink		 4
-#define kHeaderSizeIPv4Min		20
-#define kHeaderSizeIPv6			40
-#define kHeaderSizeUDP			 8
-
-#define kIPProtocolUDP		0x11
-
-static OSStatus
-	_GAITesterGetDNSMessageFromPacket(
-		const uint8_t *		inPacketPtr,
-		size_t				inPacketLen,
-		const uint8_t **	outMsgPtr,
-		size_t *			outMsgLen )
-{
-	OSStatus					err;
-	const uint8_t *				nullLink;
-	uint32_t					addressFamily;
-	const uint8_t *				ip;
-	int							ipHeaderLen;
-	int							protocol;
-	const uint8_t *				msg;
-	const uint8_t * const		end = &inPacketPtr[ inPacketLen ];
-	
-	nullLink = &inPacketPtr[ 0 ];
-	require_action_quiet( ( end - nullLink ) >= kHeaderSizeNullLink, exit, err = kUnderrunErr );
-	addressFamily = ReadHost32( &nullLink[ 0 ] );
-	
-	ip = &nullLink[ kHeaderSizeNullLink ];
-	if( addressFamily == AF_INET )
-	{
-		require_action_quiet( ( end - ip ) >= kHeaderSizeIPv4Min, exit, err = kUnderrunErr );
-		ipHeaderLen	= ( ip[ 0 ] & 0x0F ) * 4;
-		protocol	=   ip[ 9 ];
-	}
-	else if( addressFamily == AF_INET6 )
-	{
-		require_action_quiet( ( end - ip ) >= kHeaderSizeIPv6, exit, err = kUnderrunErr );
-		ipHeaderLen	= kHeaderSizeIPv6;
-		protocol	= ip[ 6 ];
-	}
-	else
-	{
-		err = kTypeErr;
-		goto exit;
-	}
-	require_action_quiet( protocol == kIPProtocolUDP, exit, err = kTypeErr );
-	require_action_quiet( ( end - ip ) >= ( ipHeaderLen + kHeaderSizeUDP ), exit, err = kUnderrunErr );
-	
-	msg = &ip[ ipHeaderLen + kHeaderSizeUDP ];
-	
-	*outMsgPtr = msg;
-	*outMsgLen = (size_t)( end - msg );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestCaseCreate
-//===========================================================================================================================
-
-static OSStatus	GAITestCaseCreate( const char *inTitle, GAITestCase **outCase )
-{
-	OSStatus			err;
-	GAITestCase *		obj;
-	
-	obj = (GAITestCase *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->title = strdup( inTitle );
-	require_action( obj->title, exit, err = kNoMemoryErr );
-	
-	*outCase = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) GAITestCaseFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestCaseFree
-//===========================================================================================================================
-
-static void	GAITestCaseFree( GAITestCase *inCase )
-{
-	GAITestItem *		item;
-	
-	while( ( item = inCase->itemList ) != NULL )
-	{
-		inCase->itemList = item->next;
-		GAITestItemFree( item );
-	}
-	ForgetMem( &inCase->title );
-	free( inCase );
-}
-
-//===========================================================================================================================
-//	GAITestCaseAddItem
-//===========================================================================================================================
-
-static OSStatus
-	GAITestCaseAddItem(
-		GAITestCase *	inCase,
-		unsigned int	inAliasCount,
-		unsigned int	inAddressCount,
-		int				inTTL,
-		GAITestAddrType	inHasAddrs,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		unsigned int	inItemCount )
-{
-	OSStatus			err;
-	GAITestItem *		item;
-	GAITestItem *		item2;
-	GAITestItem *		newItemList = NULL;
-	GAITestItem **		itemPtr;
-	char *				ptr;
-	char *				end;
-	unsigned int		i;
-	char				name[ 64 ];
-	char				tag[ kGAITesterTagStringLen + 1 ];
-	
-	require_action_quiet( inItemCount > 0, exit, err = kNoErr );
-	
-	// Limit address count to 64 because we use 64-bit bitmaps for keeping track of addresses.
-	
-	require_action_quiet( ( inAddressCount >= 1 ) && ( inAddressCount <= 64 ), exit, err = kCountErr );
-	require_action_quiet( ( inAliasCount >= 0 ) && ( inAliasCount <= INT32_MAX ), exit, err = kCountErr );
-	require_action_quiet( GAITestAddrTypeIsValid( inHasAddrs ), exit, err = kValueErr );
-	
-	ptr = &name[ 0 ];
-	end = &name[ countof( name ) ];
-	
-	// Add Alias label.
-	
-	if(      inAliasCount == 1 ) SNPrintF_Add( &ptr, end, "alias." );
-	else if( inAliasCount >= 2 ) SNPrintF_Add( &ptr, end, "alias-%u.", inAliasCount );
-	
-	// Add Count label.
-	
-	SNPrintF_Add( &ptr, end, "count-%u.", inAddressCount );
-	
-	// Add TTL label.
-	
-	if( inTTL >= 0 ) SNPrintF_Add( &ptr, end, "ttl-%d.", inTTL );
-	
-	// Add Tag label.
-	
-	SNPrintF_Add( &ptr, end, "tag-%s.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	
-	// Add IPv4 or IPv6 label if necessary.
-	
-	if(      inHasAddrs == kGAITestAddrType_IPv4 ) SNPrintF_Add( &ptr, end, "ipv4." );
-	else if( inHasAddrs == kGAITestAddrType_IPv6 ) SNPrintF_Add( &ptr, end, "ipv6." );
-	
-	// Finally, add the d.test. labels.
-	
-	SNPrintF_Add( &ptr, end, "d.test." );
-	
-	// Create item.
-	
-	err = GAITestItemCreate( name, inAddressCount, inHasAddrs, inWantAddrs, inTimeLimitMs, &item );
-	require_noerr( err, exit );
-	
-	newItemList	= item;
-	itemPtr		= &item->next;
-	
-	// Create repeat items.
-	
-	for( i = 1; i < inItemCount; ++i )
-	{
-		err = GAITestItemDup( item, &item2 );
-		require_noerr( err, exit );
-		
-		*itemPtr	= item2;
-		itemPtr		= &item2->next;
-	}
-	
-	// Append to test case's item list.
-	
-	for( itemPtr = &inCase->itemList; *itemPtr; itemPtr = &( *itemPtr )->next ) {}
-	*itemPtr	= newItemList;
-	newItemList	= NULL;
-	
-exit:
-	while( ( item = newItemList ) != NULL )
-	{
-		newItemList = item->next;
-		GAITestItemFree( item );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestCaseAddLocalHostItem
-//===========================================================================================================================
-
-static OSStatus
-	GAITestCaseAddLocalHostItem(
-		GAITestCase *	inCase,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		unsigned int	inItemCount )
-{
-	OSStatus			err;
-	GAITestItem *		item;
-	GAITestItem *		item2;
-	GAITestItem *		newItemList = NULL;
-	GAITestItem **		itemPtr;
-	unsigned int		i;
-	
-	require_action_quiet( inItemCount > 1, exit, err = kNoErr );
-	
-	err = GAITestItemCreate( "localhost.", 1, kGAITestAddrType_Both, inWantAddrs, inTimeLimitMs, &item );
-	require_noerr( err, exit );
-	
-	newItemList	= item;
-	itemPtr		= &item->next;
-	
-	// Create repeat items.
-	
-	for( i = 1; i < inItemCount; ++i )
-	{
-		err = GAITestItemDup( item, &item2 );
-		require_noerr( err, exit );
-		
-		*itemPtr	= item2;
-		itemPtr		= &item2->next;
-	}
-	
-	for( itemPtr = &inCase->itemList; *itemPtr; itemPtr = &( *itemPtr )->next ) {}
-	*itemPtr	= newItemList;
-	newItemList	= NULL;
-	
-exit:
-	while( ( item = newItemList ) != NULL )
-	{
-		newItemList = item->next;
-		GAITestItemFree( item );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestItemCreate
-//===========================================================================================================================
-
-static OSStatus
-	GAITestItemCreate(
-		const char *	inName,
-		unsigned int	inAddressCount,
-		GAITestAddrType	inHasAddrs,
-		GAITestAddrType	inWantAddrs,
-		unsigned int	inTimeLimitMs,
-		GAITestItem **	outItem )
-{
-	OSStatus			err;
-	GAITestItem *		obj = NULL;
-	
-	require_action_quiet( inAddressCount >= 1, exit, err = kCountErr );
-	require_action_quiet( GAITestAddrTypeIsValid( inHasAddrs ), exit, err = kValueErr );
-	require_action_quiet( GAITestAddrTypeIsValid( inWantAddrs ), exit, err = kValueErr );
-	
-	obj = (GAITestItem *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	obj->addressCount	= inAddressCount;
-	obj->hasV4			= ( inHasAddrs  & kGAITestAddrType_IPv4 ) ? true : false;
-	obj->hasV6			= ( inHasAddrs  & kGAITestAddrType_IPv6 ) ? true : false;
-	obj->wantV4			= ( inWantAddrs & kGAITestAddrType_IPv4 ) ? true : false;
-	obj->wantV6			= ( inWantAddrs & kGAITestAddrType_IPv6 ) ? true : false;
-	obj->error			= kInProgressErr;
-	obj->timeLimitMs	= inTimeLimitMs;
-	
-	*outItem = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) GAITestItemFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestItemDup
-//===========================================================================================================================
-
-static OSStatus	GAITestItemDup( const GAITestItem *inItem, GAITestItem **outItem )
-{
-	OSStatus			err;
-	GAITestItem *		obj;
-	
-	obj = (GAITestItem *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	*obj = *inItem;
-	obj->next = NULL;
-	if( inItem->name )
-	{
-		obj->name = strdup( inItem->name );
-		require_action( obj->name, exit, err = kNoMemoryErr );
-	}
-	
-	*outItem = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) GAITestItemFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	GAITestItemFree
-//===========================================================================================================================
-
-static void	GAITestItemFree( GAITestItem *inItem )
-{
-	ForgetMem( &inItem->name );
-	free( inItem );
-}
-
-//===========================================================================================================================
-//	MDNSDiscoveryTestCmd
-//===========================================================================================================================
-
-#define kMDNSDiscoveryTestFirstQueryTimeoutSecs		4
-
-typedef struct
-{
-	DNSServiceRef			query;					// Reference to DNSServiceQueryRecord for replier's "about" TXT record.
-	dispatch_source_t		queryTimer;				// Used to time out the "about" TXT record query.
-	NanoTime64				startTime;				// When the test started.
-	NanoTime64				endTime;				// When the test ended.
-	pid_t					replierPID;				// PID of mDNS replier.
-	uint32_t				ifIndex;				// Index of interface to run the replier on.
-	unsigned int			instanceCount;			// Desired number of service instances.
-	unsigned int			txtSize;				// Desired size of each service instance's TXT record data.
-	unsigned int			recordCountA;			// Desired number of A records per replier hostname.
-	unsigned int			recordCountAAAA;		// Desired number of AAAA records per replier hostname.
-	unsigned int			maxDropCount;			// Replier's --maxDropCount option argument.
-	double					ucastDropRate;			// Replier's probability of dropping a unicast response.
-	double					mcastDropRate;			// Replier's probability of dropping a multicast query or response.
-	Boolean					noAdditionals;			// True if the replier is to not include additional records in responses.
-	Boolean					useIPv4;				// True if the replier is to use IPv4.
-	Boolean					useIPv6;				// True if the replier is to use IPv6.
-	Boolean					useNewGAI;				// True if the browser is to use dnssd_getaddrinfo to resolve hostnames.
-	Boolean					flushedCache;			// True if mDNSResponder's record cache was flushed before testing.
-	char *					replierCommand;			// Command used to run the replier.
-	char *					serviceType;			// Type of services to browse for.
-	ServiceBrowserRef		browser;				// Service browser.
-	unsigned int			browseTimeSecs;			// Amount of time to spend browsing in seconds.
-	const char *			outputFilePath;			// File to write test results to. If NULL, then write to stdout.
-	OutputFormatType		outputFormat;			// Format of test results output.
-	Boolean					outputAppendNewline;	// True if a newline character should be appended to JSON output.
-	char					hostname[ 16 + 1 ];		// Base hostname that the replier is to use for instance and host names.
-	char					tag[ 4 + 1 ];			// Tag that the replier is to use in its service types.
-	
-}	MDNSDiscoveryTestContext;
-
-static void		_MDNSDiscoveryTestFirstQueryTimeout( void *inContext );
-static void DNSSD_API
-	_MDNSDiscoveryTestAboutQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void
-	_MDNSDiscoveryTestServiceBrowserCallback(
-		ServiceBrowserResults *	inResults,
-		OSStatus				inError,
-		void *					inContext );
-static Boolean	_MDNSDiscoveryTestTXTRecordIsValid( const uint8_t *inRecordName, const uint8_t *inTXTPtr, size_t inTXTLen );
-
-static void	MDNSDiscoveryTestCmd( void )
-{
-	OSStatus						err;
-	MDNSDiscoveryTestContext *		context;
-	char							queryName[ sizeof_field( MDNSDiscoveryTestContext, hostname ) + 15 ];
-	
-	context = (MDNSDiscoveryTestContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_InstanceCount, "instance count", 1, UINT16_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_TXTSize, "TXT size", 1, UINT16_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_BrowseTimeSecs, "browse time (seconds)", 1, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_RecordCountA, "A record count", 0, 64 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_RecordCountAAAA, "AAAA record count", 0, 64 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckDoubleArgument( gMDNSDiscoveryTest_UnicastDropRate, "unicast drop rate", 0.0, 1.0 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckDoubleArgument( gMDNSDiscoveryTest_MulticastDropRate, "multicast drop rate", 0.0, 1.0 );
-	require_noerr_quiet( err, exit );
-	
-	err = CheckIntegerArgument( gMDNSDiscoveryTest_MaxDropCount, "drop count", 0, 255 );
-	require_noerr_quiet( err, exit );
-	
-	context->replierPID				= -1;
-	context->instanceCount			= (unsigned int) gMDNSDiscoveryTest_InstanceCount;
-	context->txtSize				= (unsigned int) gMDNSDiscoveryTest_TXTSize;
-	context->browseTimeSecs			= (unsigned int) gMDNSDiscoveryTest_BrowseTimeSecs;
-	context->recordCountA			= (unsigned int) gMDNSDiscoveryTest_RecordCountA;
-	context->recordCountAAAA		= (unsigned int) gMDNSDiscoveryTest_RecordCountAAAA;
-	context->ucastDropRate			= gMDNSDiscoveryTest_UnicastDropRate;
-	context->mcastDropRate			= gMDNSDiscoveryTest_MulticastDropRate;
-	context->maxDropCount			= (unsigned int) gMDNSDiscoveryTest_MaxDropCount;
-	context->outputFilePath			= gMDNSDiscoveryTest_OutputFilePath;
-	context->outputAppendNewline	= gMDNSDiscoveryTest_OutputAppendNewline	? true : false;
-	context->noAdditionals			= gMDNSDiscoveryTest_NoAdditionals			? true : false;
-	context->useIPv4				= ( gMDNSDiscoveryTest_UseIPv4 || !gMDNSDiscoveryTest_UseIPv6 ) ? true : false;
-	context->useIPv6				= ( gMDNSDiscoveryTest_UseIPv6 || !gMDNSDiscoveryTest_UseIPv4 ) ? true : false;
-	context->useNewGAI				= gMDNSDiscoveryTest_UseNewGAI				? true : false;
-	
-	if( gMDNSDiscoveryTest_Interface )
-	{
-		err = InterfaceIndexFromArgString( gMDNSDiscoveryTest_Interface, &context->ifIndex );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		err = _MDNSInterfaceGetAny( kMDNSInterfaceSubset_All, NULL, &context->ifIndex );
-		require_noerr_quiet( err, exit );
-	}
-	
-	err = OutputFormatFromArgString( gMDNSDiscoveryTest_OutputFormat, &context->outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	if( gMDNSDiscoveryTest_FlushCache )
-	{
-		err = CheckRootUser();
-		require_noerr_quiet( err, exit );
-		
-		err = systemf( NULL, "killall -HUP mDNSResponder" );
-		require_noerr( err, exit );
-		sleep( 1 );
-		context->flushedCache = true;
-	}
-	
-	_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( context->hostname ) - 1,
-		context->hostname );
-	_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( context->tag ) - 1, context->tag );
-	
-	ASPrintF( &context->serviceType, "_t-%s-%u-%u._tcp", context->tag, context->txtSize, context->instanceCount );
-	require_action( context->serviceType, exit, err = kUnknownErr );
-	
-	ASPrintF( &context->replierCommand,
-		"dnssdutil mdnsreplier --follow %lld --interface %u --hostname %s --tag %s --maxInstanceCount %u "
-		"--countA %u --countAAAA %u --udrop %.1f --mdrop %.1f --maxDropCount %u %?s%?s%?s",
-		(int64_t) getpid(),
-		context->ifIndex,
-		context->hostname,
-		context->tag,
-		context->instanceCount,
-		context->recordCountA,
-		context->recordCountAAAA,
-		context->ucastDropRate,
-		context->mcastDropRate,
-		context->maxDropCount,
-		context->noAdditionals,	" --noAdditionals",
-		context->useIPv4,		" --ipv4",
-		context->useIPv6,		" --ipv6" );
-	require_action_quiet( context->replierCommand, exit, err = kUnknownErr );
-	
-	err = _SpawnCommand( &context->replierPID, NULL, NULL, "%s", context->replierCommand );
-	require_noerr_quiet( err, exit );
-	
-	// Query for the replier's about TXT record. A response means that it's fully up and running.
-	
-	SNPrintF( queryName, sizeof( queryName ), "about.%s.local.", context->hostname );
-	err = DNSServiceQueryRecord( &context->query, kDNSServiceFlagsForceMulticast, context->ifIndex, queryName,
-		kDNSServiceType_TXT, kDNSServiceClass_IN, _MDNSDiscoveryTestAboutQueryCallback, context );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( context->query, dispatch_get_main_queue() );
-	require_noerr( err, exit );
-	
-	err = DispatchTimerCreate( dispatch_time_seconds( kMDNSDiscoveryTestFirstQueryTimeoutSecs ),
-		DISPATCH_TIME_FOREVER, UINT64_C_safe( kMDNSDiscoveryTestFirstQueryTimeoutSecs ) * kNanosecondsPerSecond / 10, NULL,
-		_MDNSDiscoveryTestFirstQueryTimeout, NULL, context, &context->queryTimer );
-	require_noerr( err, exit );
-	dispatch_resume( context->queryTimer );
-	
-	context->startTime = NanoTimeGetCurrent();
-	dispatch_main();
-	
-exit:
-	exit( 1 );
-}
-
-//===========================================================================================================================
-//	_MDNSDiscoveryTestFirstQueryTimeout
-//===========================================================================================================================
-
-static void	_MDNSDiscoveryTestFirstQueryTimeout( void *inContext )
-{
-	MDNSDiscoveryTestContext * const		context = (MDNSDiscoveryTestContext *) inContext;
-	
-	dispatch_source_forget( &context->queryTimer );
-	
-	FPrintF( stderr, "error: Query for mdnsreplier's \"about\" TXT record timed out.\n" );
-	exit( 1 );
-}
-
-//===========================================================================================================================
-//	_MDNSDiscoveryTestAboutQueryCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_MDNSDiscoveryTestAboutQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus								err;
-	MDNSDiscoveryTestContext * const		context = (MDNSDiscoveryTestContext *) inContext;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inFullName );
-	Unused( inType );
-	Unused( inClass );
-	Unused( inRDataLen );
-	Unused( inRDataPtr );
-	Unused( inTTL );
-	
-	err = inError;
-	require_noerr( err, exit );
-	require_quiet( inFlags & kDNSServiceFlagsAdd, exit );
-	
-	DNSServiceForget( &context->query );
-	dispatch_source_forget( &context->queryTimer );
-	
-	err = ServiceBrowserCreate( dispatch_get_main_queue(), 0, "local.", context->browseTimeSecs, false, &context->browser );
-	require_noerr( err, exit );
-	
-	err = ServiceBrowserAddServiceType( context->browser, context->serviceType );
-	require_noerr( err, exit );
-	
-	ServiceBrowserSetUseNewGAI( context->browser, context->useNewGAI );
-	ServiceBrowserSetCallback( context->browser, _MDNSDiscoveryTestServiceBrowserCallback, context );
-	ServiceBrowserStart( context->browser );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_MDNSDiscoveryTestServiceBrowserCallback
-//===========================================================================================================================
-
-#define kMDNSDiscoveryTestResultsKey_ReplierInfo					CFSTR( "replierInfo" )
-#define kMDNSDiscoveryTestResultsKey_StartTime						CFSTR( "startTime" )
-#define kMDNSDiscoveryTestResultsKey_EndTime						CFSTR( "endTime" )
-#define kMDNSDiscoveryTestResultsKey_BrowseTimeSecs					CFSTR( "browseTimeSecs" )
-#define kMDNSDiscoveryTestResultsKey_ServiceType					CFSTR( "serviceType" )
-#define kMDNSDiscoveryTestResultsKey_FlushedCache					CFSTR( "flushedCache" )
-#define kMDNSDiscoveryTestResultsKey_UsedNewGAI						CFSTR( "usedNewGAI" )
-#define kMDNSDiscoveryTestResultsKey_UnexpectedInstances			CFSTR( "unexpectedInstances" )
-#define kMDNSDiscoveryTestResultsKey_MissingInstances				CFSTR( "missingInstances" )
-#define kMDNSDiscoveryTestResultsKey_IncorrectInstances				CFSTR( "incorrectInstances" )
-#define kMDNSDiscoveryTestResultsKey_Success						CFSTR( "success" )
-#define kMDNSDiscoveryTestResultsKey_TotalResolveTime				CFSTR( "totalResolveTimeUs" )
-
-#define kMDNSDiscoveryTestReplierInfoKey_Command					CFSTR( "command" )
-#define kMDNSDiscoveryTestReplierInfoKey_InstanceCount				CFSTR( "instanceCount" )
-#define kMDNSDiscoveryTestReplierInfoKey_TXTSize					CFSTR( "txtSize" )
-#define kMDNSDiscoveryTestReplierInfoKey_RecordCountA				CFSTR( "recordCountA" )
-#define kMDNSDiscoveryTestReplierInfoKey_RecordCountAAAA			CFSTR( "recordCountAAAA" )
-#define kMDNSDiscoveryTestReplierInfoKey_Hostname					CFSTR( "hostname" )
-#define kMDNSDiscoveryTestReplierInfoKey_NoAdditionals				CFSTR( "noAdditionals" )
-#define kMDNSDiscoveryTestReplierInfoKey_UnicastDropRate			CFSTR( "ucastDropRate" )
-#define kMDNSDiscoveryTestReplierInfoKey_MulticastDropRate			CFSTR( "mcastDropRate" )
-#define kMDNSDiscoveryTestReplierInfoKey_MaxDropCount				CFSTR( "maxDropCount" )
-
-#define kMDNSDiscoveryTestUnexpectedInstanceKey_Name				CFSTR( "name" )
-#define kMDNSDiscoveryTestUnexpectedInstanceKey_InterfaceIndex		CFSTR( "interfaceIndex" )
-
-#define kMDNSDiscoveryTestIncorrectInstanceKey_Name					CFSTR( "name" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_DidResolve			CFSTR( "didResolve" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_BadHostname			CFSTR( "badHostname" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_BadPort				CFSTR( "badPort" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_BadTXT				CFSTR( "badTXT" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_UnexpectedAddrs		CFSTR( "unexpectedAddrs" )
-#define kMDNSDiscoveryTestIncorrectInstanceKey_MissingAddrs			CFSTR( "missingAddrs" )
-
-static void	_MDNSDiscoveryTestServiceBrowserCallback( ServiceBrowserResults *inResults, OSStatus inError, void *inContext )
-{
-	OSStatus								err;
-	MDNSDiscoveryTestContext * const		context			= (MDNSDiscoveryTestContext *) inContext;
-	const SBRDomain *						domain;
-	const SBRServiceType *					type;
-	const SBRServiceInstance *				instance;
-	const SBRServiceInstance **				instanceArray	= NULL;
-	const SBRIPAddress *					ipaddr;
-	size_t									hostnameLen;
-	const char *							ptr;
-	const char *							end;
-	unsigned int							i;
-	uint32_t								u32;
-	CFMutableArrayRef						unexpectedInstances;
-	CFMutableArrayRef						missingInstances;
-	CFMutableArrayRef						incorrectInstances;
-	CFMutableDictionaryRef					plist			= NULL;
-	CFMutableDictionaryRef					badDict			= NULL;
-	CFMutableArrayRef						unexpectedAddrs	= NULL;
-	CFMutableArrayRef						missingAddrs	= NULL;
-	uint64_t								maxResolveTimeUs;
-	int										success			= false;
-	char									startTime[ 32 ];
-	char									endTime[ 32 ];
-	
-	context->endTime = NanoTimeGetCurrent();
-	
-	err = inError;
-	require_noerr( err, exit );
-	
-	_NanoTime64ToTimestamp( context->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( context->endTime, endTime, sizeof( endTime ) );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO="
-			"{"
-				"%kO=%s"	// replierCommand
-				"%kO=%lli"	// txtSize
-				"%kO=%lli"	// instanceCount
-				"%kO=%lli"	// recordCountA
-				"%kO=%lli"	// recordCountAAAA
-				"%kO=%s"	// hostname
-				"%kO=%b"	// noAdditionals
-				"%kO=%f"	// ucastDropRate
-				"%kO=%f"	// mcastDropRate
-				"%kO=%i"	// maxDropCount
-			"}"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%lli"	// browseTimeSecs
-			"%kO=%s"	// serviceType
-			"%kO=%b"	// flushedCache
-		#if( MDNSRESPONDER_PROJECT )
-			"%kO=%b"	// usedNewGAI
-		#endif
-			"%kO=[%@]"	// unexpectedInstances
-			"%kO=[%@]"	// missingInstances
-			"%kO=[%@]"	// incorrectInstances
-		"}",
-		kMDNSDiscoveryTestResultsKey_ReplierInfo,
-		kMDNSDiscoveryTestReplierInfoKey_Command,			context->replierCommand,
-		kMDNSDiscoveryTestReplierInfoKey_InstanceCount,		(int64_t) context->instanceCount,
-		kMDNSDiscoveryTestReplierInfoKey_TXTSize,			(int64_t) context->txtSize,
-		kMDNSDiscoveryTestReplierInfoKey_RecordCountA,		(int64_t) context->recordCountA,
-		kMDNSDiscoveryTestReplierInfoKey_RecordCountAAAA,	(int64_t) context->recordCountAAAA,
-		kMDNSDiscoveryTestReplierInfoKey_Hostname,			context->hostname,
-		kMDNSDiscoveryTestReplierInfoKey_NoAdditionals,		context->noAdditionals,
-		kMDNSDiscoveryTestReplierInfoKey_UnicastDropRate,	context->ucastDropRate,
-		kMDNSDiscoveryTestReplierInfoKey_MulticastDropRate,	context->mcastDropRate,
-		kMDNSDiscoveryTestReplierInfoKey_MaxDropCount,		context->maxDropCount,
-		kMDNSDiscoveryTestResultsKey_StartTime,				startTime,
-		kMDNSDiscoveryTestResultsKey_EndTime,				endTime,
-		kMDNSDiscoveryTestResultsKey_BrowseTimeSecs,		(int64_t) context->browseTimeSecs,
-		kMDNSDiscoveryTestResultsKey_ServiceType,			context->serviceType,
-		kMDNSDiscoveryTestResultsKey_FlushedCache,			context->flushedCache,
-	#if( MDNSRESPONDER_PROJECT )
-		kMDNSDiscoveryTestResultsKey_UsedNewGAI,			context->useNewGAI,
-	#endif
-		kMDNSDiscoveryTestResultsKey_UnexpectedInstances,	&unexpectedInstances,
-		kMDNSDiscoveryTestResultsKey_MissingInstances,		&missingInstances,
-		kMDNSDiscoveryTestResultsKey_IncorrectInstances,	&incorrectInstances );
-	require_noerr( err, exit );
-	
-	for( domain = inResults->domainList; domain && ( strcasecmp( domain->name, "local." ) != 0 ); domain = domain->next ) {}
-	require_action( domain, exit, err = kInternalErr );
-	
-	for( type = domain->typeList; type && ( strcasecmp( type->name, context->serviceType ) != 0 ); type = type->next ) {}
-	require_action( type, exit, err = kInternalErr );
-	
-	instanceArray = (const SBRServiceInstance **) calloc( context->instanceCount, sizeof( *instanceArray ) );
-	require_action( instanceArray, exit, err = kNoMemoryErr );
-	
-	hostnameLen = strlen( context->hostname );
-	for( instance = type->instanceList; instance; instance = instance->next )
-	{
-		unsigned int		instanceNumber = 0;
-		
-		if( strcmp_prefix( instance->name, context->hostname ) == 0 )
-		{
-			ptr = &instance->name[ hostnameLen ];
-			if( ( ptr[ 0 ] == ' ' ) && ( ptr[ 1 ] == '(' ) )
-			{
-				ptr += 2;
-				for( end = ptr; isdigit_safe( *end ); ++end ) {}
-				if( DecimalTextToUInt32( ptr, end, &u32, &ptr ) == kNoErr )
-				{
-					if( ( u32 >= 2 ) && ( u32 <= context->instanceCount ) && ( ptr[ 0 ] == ')' ) && ( ptr[ 1 ] == '\0' ) )
-					{
-						instanceNumber = u32;
-					}
-				}
-			}
-			else if( *ptr == '\0' )
-			{
-				instanceNumber = 1;
-			}
-		}
-		if( ( instanceNumber != 0 ) && ( instance->ifIndex == context->ifIndex ) )
-		{
-			check( !instanceArray[ instanceNumber - 1 ] );
-			instanceArray[ instanceNumber - 1 ] = instance;
-		}
-		else
-		{
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, unexpectedInstances,
-				"{"
-					"%kO=%s"
-					"%kO=%lli"
-				"}",
-				kMDNSDiscoveryTestUnexpectedInstanceKey_Name,			instance->name,
-				kMDNSDiscoveryTestUnexpectedInstanceKey_InterfaceIndex,	(int64_t) instance->ifIndex );
-			require_noerr( err, exit );
-		}
-	}
-	
-	maxResolveTimeUs = 0;
-	for( i = 1; i <= context->instanceCount; ++i )
-	{
-		int		isHostnameValid;
-		int		isTXTValid;
-		
-		instance = instanceArray[ i - 1 ];
-		if( !instance )
-		{
-			if( i == 1 )
-			{
-				err = CFPropertyListAppendFormatted( kCFAllocatorDefault, missingInstances, "%s", context->hostname );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				char *		instanceName = NULL;
-				
-				ASPrintF( &instanceName, "%s (%u)", context->hostname, i );
-				require_action( instanceName, exit, err = kUnknownErr );
-				
-				err = CFPropertyListAppendFormatted( kCFAllocatorDefault, missingInstances, "%s", instanceName );
-				free( instanceName );
-				require_noerr( err, exit );
-			}
-			continue;
-		}
-		
-		if( !instance->hostname )
-		{
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, incorrectInstances,
-				"{"
-					"%kO=%s"
-					"%kO=%b"
-				"}",
-				kMDNSDiscoveryTestIncorrectInstanceKey_Name,		instance->name,
-				kMDNSDiscoveryTestIncorrectInstanceKey_DidResolve,	false );
-			require_noerr( err, exit );
-			continue;
-		}
-		
-		badDict = CFDictionaryCreateMutable( NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-		require_action( badDict, exit, err = kNoMemoryErr );
-		
-		isHostnameValid = false;
-		if( strcmp_prefix( instance->hostname, context->hostname ) == 0 )
-		{
-			ptr = &instance->hostname[ hostnameLen ];
-			if( i == 1 )
-			{
-				if( strcmp( ptr, ".local." ) == 0 ) isHostnameValid = true;
-			}
-			else if( *ptr == '-' )
-			{
-				++ptr;
-				for( end = ptr; isdigit_safe( *end ); ++end ) {}
-				if( DecimalTextToUInt32( ptr, end, &u32, &ptr ) == kNoErr )
-				{
-					if( ( u32 == i ) && ( strcmp( ptr, ".local." ) == 0 ) ) isHostnameValid = true;
-				}
-			}
-		}
-		if( !isHostnameValid )
-		{
-			err = CFDictionarySetCString( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_BadHostname, instance->hostname,
-				kSizeCString );
-			require_noerr( err, exit );
-		}
-		
-		if( instance->port != (uint16_t)( kMDNSReplierPortBase + context->txtSize ) )
-		{
-			err = CFDictionarySetInt64( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_BadPort, instance->port );
-			require_noerr( err, exit );
-		}
-		
-		isTXTValid = false;
-		if( instance->txtLen == context->txtSize )
-		{
-			uint8_t		name[ kDomainNameLengthMax ];
-			
-			err = DomainNameFromString( name, instance->name, NULL );
-			require_noerr( err, exit );
-			
-			err = DomainNameAppendString( name, type->name, NULL );
-			require_noerr( err, exit );
-			
-			err = DomainNameAppendString( name, "local", NULL );
-			require_noerr( err, exit );
-			
-			if( _MDNSDiscoveryTestTXTRecordIsValid( name, instance->txtPtr, instance->txtLen ) ) isTXTValid = true;
-		}
-		if( !isTXTValid )
-		{
-			char *		hexStr = NULL;
-			
-			ASPrintF( &hexStr, "%.4H", instance->txtPtr, (int) instance->txtLen, (int) instance->txtLen );
-			require_action( hexStr, exit, err = kUnknownErr );
-			
-			err = CFDictionarySetCString( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_BadTXT, hexStr, kSizeCString );
-			free( hexStr );
-			require_noerr( err, exit );
-		}
-		
-		if( isHostnameValid )
-		{
-			uint64_t			addrV4Bitmap, addrV6Bitmap, bitmask, resolveTimeUs;
-			unsigned int		j;
-			uint8_t				addrV4[ 4 ];
-			uint8_t				addrV6[ 16 ];
-			uint8_t				addrV6LL[ 16 ];
-			
-			if( context->recordCountA < 64 )	addrV4Bitmap = ( UINT64_C( 1 ) << context->recordCountA ) - 1;
-			else								addrV4Bitmap =  ~UINT64_C( 0 );
-			
-			if( context->recordCountAAAA < 64 ) addrV6Bitmap = ( UINT64_C( 1 ) << context->recordCountAAAA ) - 1;
-			else								addrV6Bitmap =  ~UINT64_C( 0 );
-			
-			addrV4[ 0 ] = 0;
-			WriteBig16Typed( &addrV4[ 1 ], (uint16_t) i );
-			addrV4[ 3 ] = 0;
-			
-			memcpy( addrV6, kMDNSReplierBaseAddrV6, 16 );
-			WriteBig16Typed( &addrV6[ 12 ], (uint16_t) i );
-			
-			memcpy( addrV6LL, kMDNSReplierLinkLocalBaseAddrV6, 16 );
-			WriteBig16Typed( &addrV6LL[ 12 ], (uint16_t) i );
-			
-			unexpectedAddrs = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-			require_action( unexpectedAddrs, exit, err = kNoMemoryErr );
-			
-			resolveTimeUs = 0;
-			for( ipaddr = instance->ipaddrList; ipaddr; ipaddr = ipaddr->next )
-			{
-				const uint8_t *		addrPtr;
-				unsigned int		lsb;
-				int					isAddrValid = false;
-				
-				if( ipaddr->sip.sa.sa_family == AF_INET )
-				{
-					addrPtr	= (const uint8_t *) &ipaddr->sip.v4.sin_addr.s_addr;
-					lsb		= addrPtr[ 3 ];
-					if( ( memcmp( addrPtr, addrV4, 3 ) == 0 ) && ( lsb >= 1 ) && ( lsb <= context->recordCountA ) )
-					{
-						bitmask = UINT64_C( 1 ) << ( lsb - 1 );
-						addrV4Bitmap &= ~bitmask;
-						isAddrValid = true;
-					}
-				}
-				else if( ipaddr->sip.sa.sa_family == AF_INET6 )
-				{
-					const struct sockaddr_in6 * const		sin6 = &ipaddr->sip.v6;
-					
-					addrPtr	= sin6->sin6_addr.s6_addr;
-					lsb		= addrPtr[ 15 ];
-					if( ( lsb >= 1 ) && ( lsb <= context->recordCountAAAA ) )
-					{
-						const uint32_t		scopeID = ( lsb == 1 ) ? context->ifIndex : 0;
-						
-						if( ( memcmp( addrPtr, ( lsb == 1 ) ? addrV6LL : addrV6, 15 ) == 0 ) &&
-							( sin6->sin6_scope_id == scopeID ) )
-						{
-							bitmask = UINT64_C( 1 ) << ( lsb - 1 );
-							addrV6Bitmap &= ~bitmask;
-							isAddrValid = true;
-						}
-					}
-				}
-				if( isAddrValid )
-				{
-					if( ipaddr->resolveTimeUs > resolveTimeUs ) resolveTimeUs = ipaddr->resolveTimeUs;
-				}
-				else
-				{
-					err = CFPropertyListAppendFormatted( kCFAllocatorDefault, unexpectedAddrs, "%##a", &ipaddr->sip );
-					require_noerr( err, exit );
-				}
-			}
-			
-			resolveTimeUs += ( instance->discoverTimeUs + instance->resolveTimeUs );
-			if( resolveTimeUs > maxResolveTimeUs ) maxResolveTimeUs = resolveTimeUs;
-			
-			if( CFArrayGetCount( unexpectedAddrs ) > 0 )
-			{
-				CFDictionarySetValue( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_UnexpectedAddrs, unexpectedAddrs );
-			}
-			ForgetCF( &unexpectedAddrs );
-			
-			missingAddrs = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-			require_action( missingAddrs, exit, err = kNoMemoryErr );
-			
-			for( j = 1; addrV4Bitmap != 0; ++j )
-			{
-				bitmask = UINT64_C( 1 ) << ( j - 1 );
-				if( addrV4Bitmap & bitmask )
-				{
-					addrV4Bitmap &= ~bitmask;
-					addrV4[ 3 ] = (uint8_t) j;
-					err = CFPropertyListAppendFormatted( kCFAllocatorDefault, missingAddrs, "%.4a", addrV4 );
-					require_noerr( err, exit );
-				}
-			}
-			for( j = 1; addrV6Bitmap != 0; ++j )
-			{
-				bitmask = UINT64_C( 1 ) << ( j - 1 );
-				if( addrV6Bitmap & bitmask )
-				{
-					struct sockaddr_in6		sin6;
-					uint8_t					missingIPv6[ 16 ];
-					
-					addrV6Bitmap &= ~bitmask;
-					memcpy( missingIPv6, ( j == 1 ) ? addrV6LL : addrV6, 16 );
-					missingIPv6[ 15 ] = (uint8_t) j;
-					_SockAddrInitIPv6( &sin6, missingIPv6, ( j == 1 ) ? context->ifIndex : 0, 0 );
-					err = CFPropertyListAppendFormatted( kCFAllocatorDefault, missingAddrs, "%##a", &sin6 );
-					require_noerr( err, exit );
-				}
-			}
-			
-			if( CFArrayGetCount( missingAddrs ) > 0 )
-			{
-				CFDictionarySetValue( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_MissingAddrs, missingAddrs );
-			}
-			ForgetCF( &missingAddrs );
-		}
-		
-		if( CFDictionaryGetCount( badDict ) > 0 )
-		{
-			err = CFDictionarySetCString( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_Name, instance->name,
-				kSizeCString );
-			require_noerr( err, exit );
-			
-			CFDictionarySetBoolean( badDict, kMDNSDiscoveryTestIncorrectInstanceKey_DidResolve, true );
-			CFArrayAppendValue( incorrectInstances, badDict );
-		}
-		ForgetCF( &badDict );
-	}
-	
-	if( ( CFArrayGetCount( unexpectedInstances ) == 0 ) &&
-		( CFArrayGetCount( missingInstances )    == 0 ) &&
-		( CFArrayGetCount( incorrectInstances )  == 0 ) )
-	{
-		err = CFDictionarySetInt64( plist, kMDNSDiscoveryTestResultsKey_TotalResolveTime, (int64_t) maxResolveTimeUs );
-		require_noerr( err, exit );
-		success = true;
-	}
-	else
-	{
-		success = false;
-	}
-	CFDictionarySetBoolean( plist, kMDNSDiscoveryTestResultsKey_Success, success );
-	
-	err = OutputPropertyList( plist, context->outputFormat, context->outputFilePath );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	ForgetCF( &context->browser );
-	if( context->replierPID != -1 )
-	{
-		kill( context->replierPID, SIGTERM );
-		context->replierPID = -1;
-	}
-	FreeNullSafe( instanceArray );
-	CFReleaseNullSafe( plist );
-	CFReleaseNullSafe( badDict );
-	CFReleaseNullSafe( unexpectedAddrs );
-	CFReleaseNullSafe( missingAddrs );
-	exit( err ? 1 : ( success ? 0 : 2 ) );
-}
-
-//===========================================================================================================================
-//	_MDNSDiscoveryTestTXTRecordIsValid
-//===========================================================================================================================
-
-static Boolean	_MDNSDiscoveryTestTXTRecordIsValid( const uint8_t *inRecordName, const uint8_t *inTXTPtr, size_t inTXTLen )
-{
-	uint32_t			hash;
-	int					n;
-	const uint8_t *		ptr;
-	size_t				i, wholeCount, remCount;
-	uint8_t				txtStr[ 16 ];
-	
-	if( inTXTLen == 0 ) return( false );
-	
-	hash = _FNV1( inRecordName, DomainNameLength( inRecordName ) );
-	
-	txtStr[ 0 ] = 15;
-	n = MemPrintF( &txtStr[ 1 ], 15, "hash=0x%08X", hash );
-	check( n == 15 );
-	
-	ptr = inTXTPtr;
-	wholeCount = inTXTLen / 16;
-	for( i = 0; i < wholeCount; ++i )
-	{
-		if( memcmp( ptr, txtStr, 16 ) != 0 ) return( false );
-		ptr += 16;
-	}
-	
-	remCount = inTXTLen % 16;
-	if( remCount > 0 )
-	{
-		txtStr[ 0 ] = (uint8_t)( remCount - 1 );
-		if( memcmp( ptr, txtStr, remCount ) != 0 ) return( false );
-		ptr += remCount;
-	}
-	check( ptr == &inTXTPtr[ inTXTLen ] );
-	return( true );
-}
-
-//===========================================================================================================================
-//	DotLocalTestCmd
-//===========================================================================================================================
-
-#define kDotLocalTestPreparationTimeLimitSecs		5
-#define kDotLocalTestSubtestDurationSecs			5
-
-// Constants for SRV record query subtest.
-
-#define kDotLocalTestSRV_Priority		1
-#define kDotLocalTestSRV_Weight			0
-#define kDotLocalTestSRV_Port			80
-#define kDotLocalTestSRV_TargetName		( (const uint8_t *) "\x03" "www" "\x07" "example" "\x03" "com" )
-#define kDotLocalTestSRV_TargetStr		"www.example.com."
-#define kDotLocalTestSRV_ResultStr		"1 0 80 " kDotLocalTestSRV_TargetStr
-
-typedef enum
-{
-	kDotLocalTestState_Unset				= 0,
-	kDotLocalTestState_Preparing			= 1,
-	kDotLocalTestState_GAIMDNSOnly			= 2,
-	kDotLocalTestState_GAIDNSOnly			= 3,
-	kDotLocalTestState_GAIBoth				= 4,
-	kDotLocalTestState_GAINeither			= 5,
-	kDotLocalTestState_GAINoSuchRecord		= 6,
-	kDotLocalTestState_QuerySRV				= 7,
-	kDotLocalTestState_Done					= 8
-	
-}	DotLocalTestState;
-
-typedef struct
-{
-	const char *			testDesc;			// Description of the current subtest.
-	char *					queryName;			// Query name for GetAddrInfo or QueryRecord operation.
-	dispatch_source_t		timer;				// Timer used for limiting the time for each subtest.
-	NanoTime64				startTime;			// Timestamp of when the subtest started.
-	NanoTime64				endTime;			// Timestamp of when the subtest ended.
-	CFMutableArrayRef		correctResults;		// Operation results that were expected.
-	CFMutableArrayRef		duplicateResults;	// Operation results that were expected, but were already received.
-	CFMutableArrayRef		unexpectedResults;	// Operation results that were unexpected.
-	OSStatus				error;				// Subtest's error code.
-	uint32_t				addrDNSv4;			// If hasDNSv4 is true, the expected DNS IPv4 address for queryName.
-	uint32_t				addrMDNSv4;			// If hasMDNSv4 is true, the expected MDNS IPv4 address for queryName.
-	uint8_t					addrDNSv6[ 16 ];	// If hasDNSv6 is true, the expected DNS IPv6 address for queryName.
-	uint8_t					addrMDNSv6[ 16 ];	// If hasMDNSv6 is true, the expected MDNS IPv6 address for queryName.
-	Boolean					hasDNSv4;			// True if queryName has a DNS IPv4 address.
-	Boolean					hasDNSv6;			// True if queryName has a DNS IPv6 address.
-	Boolean					hasMDNSv4;			// True if queryName has an MDNS IPv4 address.
-	Boolean					hasMDNSv6;			// True if queryName has an MDNS IPv6 address.
-	Boolean					needDNSv4;			// True if operation is expecting, but hasn't received a DNS IPv4 result.
-	Boolean					needDNSv6;			// True if operation is expecting, but hasn't received a DNS IPv6 result.
-	Boolean					needMDNSv4;			// True if operation is expecting, but hasn't received an MDNS IPv4 result.
-	Boolean					needMDNSv6;			// True if operation is expecting, but hasn't received an MDNS IPv6 result.
-	Boolean					needSRV;			// True if operation is expecting, but hasn't received an SRV result.
-	
-}	DotLocalSubtest;
-
-typedef struct
-{
-	dispatch_source_t		timer;				// Timer used for limiting the time for each state/subtest.
-	DotLocalSubtest *		subtest;			// Current subtest's state.
-	DNSServiceRef			connection;			// Shared connection for DNS-SD operations.
-	DNSServiceRef			op;					// Reference for the current DNS-SD operation.
-	DNSServiceRef			op2;				// Reference for mdnsreplier probe query used during preparing state.
-	DNSRecordRef			localSOARef;		// Reference returned by DNSServiceRegisterRecord() for local. SOA record.
-	char *					replierCmd;			// Command used to invoke the mdnsreplier.
-	char *					serverCmd;			// Command used to invoke the test DNS server.
-	CFMutableArrayRef		reportsGAI;			// Reports for subtests that use DNSServiceGetAddrInfo.
-	CFMutableArrayRef		reportsQuerySRV;	// Reports for subtests that use DNSServiceQueryRecord for SRV records.
-	NanoTime64				startTime;			// Timestamp for when the test started.
-	NanoTime64				endTime;			// Timestamp for when the test ended.
-	DotLocalTestState		state;				// The test's current state.
-	pid_t					replierPID;			// PID of spawned mdnsreplier.
-	pid_t					serverPID;			// PID of spawned test DNS server.
-	uint32_t				ifIndex;			// Interface index used for mdnsreplier.
-	char *					outputFilePath;		// File to write test results to. If NULL, then write to stdout.
-	OutputFormatType		outputFormat;		// Format of test results output.
-	Boolean					registeredSOA;		// True if the dummy local. SOA record was successfully registered.
-	Boolean					serverIsReady;		// True if response was received for test DNS server probe query.
-	Boolean					replierIsReady;		// True if response was received for mdnsreplier probe query.
-	Boolean					testFailed;			// True if at least one subtest failed.
-	char					labelStr[ 20 + 1 ];	// Unique label string used for for making the query names used by subtests.
-												// The format of this string is "dotlocal-test-<six random chars>".
-}	DotLocalTestContext;
-
-static void	_DotLocalTestStateMachine( DotLocalTestContext *inContext );
-static void DNSSD_API
-	_DotLocalTestProbeQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void DNSSD_API
-	_DotLocalTestRegisterRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSRecordRef		inRecordRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		void *				inContext );
-static void	_DotLocalTestTimerHandler( void *inContext );
-static void DNSSD_API
-	_DotLocalTestGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void DNSSD_API
-	_DotLocalTestQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-static void	DotLocalTestCmd( void )
-{
-	OSStatus					err;
-	DotLocalTestContext *		context;
-	uint8_t *					rdataPtr;
-	size_t						rdataLen;
-	DNSServiceFlags				flags;
-	char						queryName[ 64 ];
-	char						randBuf[ 6 + 1 ];	// Large enough for four and six character random strings below.
-	
-	context = (DotLocalTestContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->startTime	= NanoTimeGetCurrent();
-	context->endTime	= kNanoTime_Invalid;
-	
-	context->state = kDotLocalTestState_Preparing;
-	
-	if( gDotLocalTest_Interface )
-	{
-		err = InterfaceIndexFromArgString( gDotLocalTest_Interface, &context->ifIndex );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		err = _MDNSInterfaceGetAny( kMDNSInterfaceSubset_All, NULL, &context->ifIndex );
-		require_noerr_quiet( err, exit );
-	}
-	
-	if( gDotLocalTest_OutputFilePath )
-	{
-		context->outputFilePath = strdup( gDotLocalTest_OutputFilePath );
-		require_action( context->outputFilePath, exit, err = kNoMemoryErr );
-	}
-	
-	err = OutputFormatFromArgString( gDotLocalTest_OutputFormat, &context->outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	context->reportsGAI = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( context->reportsGAI, exit, err = kNoMemoryErr );
-	
-	context->reportsQuerySRV = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( context->reportsQuerySRV, exit, err = kNoMemoryErr );
-	
-	SNPrintF( context->labelStr, sizeof( context->labelStr ), "dotlocal-test-%s",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, 6, randBuf ) );
-	
-	// Spawn an mdnsreplier.
-	
-	ASPrintF( &context->replierCmd,
-		"dnssdutil mdnsreplier --follow %lld --interface %u --hostname %s --tag %s --maxInstanceCount 2 --countA 1"
-		" --countAAAA 1",
-		(int64_t) getpid(), context->ifIndex, context->labelStr,
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, 4, randBuf ) );
-	require_action_quiet( context->replierCmd, exit, err = kUnknownErr );
-	
-	err = _SpawnCommand( &context->replierPID, NULL, NULL, "%s", context->replierCmd );
-	require_noerr( err, exit );
-	
-	// Spawn a test DNS server
-	
-	ASPrintF( &context->serverCmd,
-		"dnssdutil server --loopback --follow %lld --port 0 --defaultTTL 300 --domain %s.local.",
-		(int64_t) getpid(), context->labelStr );
-	require_action_quiet( context->serverCmd, exit, err = kUnknownErr );
-	
-	err = _SpawnCommand( &context->serverPID, NULL, NULL, "%s", context->serverCmd );
-	require_noerr( err, exit );
-	
-	// Create a shared DNS-SD connection.
-	
-	err = DNSServiceCreateConnection( &context->connection );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( context->connection, dispatch_get_main_queue() );
-	require_noerr( err, exit );
-	
-	// Create probe query for DNS server, i.e., query for any name that has an A record.
-	
-	SNPrintF( queryName, sizeof( queryName ), "tag-dotlocal-test-probe.ipv4.%s.local.", context->labelStr );
-	
-	flags = kDNSServiceFlagsShareConnection;
-#if( TARGET_OS_WATCH )
-	flags |= kDNSServiceFlagsPathEvaluationDone;
-#endif
-	
-	context->op = context->connection;
-	err = DNSServiceQueryRecord( &context->op, flags, kDNSServiceInterfaceIndexAny, queryName, kDNSServiceType_A,
-		kDNSServiceClass_IN, _DotLocalTestProbeQueryRecordCallback, context );
-	require_noerr( err, exit );
-	
-	// Create probe query for mdnsreplier's "about" TXT record.
-	
-	SNPrintF( queryName, sizeof( queryName ), "about.%s.local.", context->labelStr );
-	
-	flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsForceMulticast;
-#if( TARGET_OS_WATCH )
-	flags |= kDNSServiceFlagsPathEvaluationDone;
-#endif
-	
-	context->op2 = context->connection;
-	err = DNSServiceQueryRecord( &context->op2, flags, context->ifIndex, queryName, kDNSServiceType_TXT, kDNSServiceClass_IN,
-		_DotLocalTestProbeQueryRecordCallback, context );
-	require_noerr( err, exit );
-	
-	// Register a dummy local. SOA record.
-	
-	err = CreateSOARecordData( kRootLabel, kRootLabel, 1976040101, 1 * kSecondsPerDay, 2 * kSecondsPerHour,
-		1000 * kSecondsPerHour, 2 * kSecondsPerDay, &rdataPtr, &rdataLen );
-	require_noerr( err, exit );
-	
-	err = DNSServiceRegisterRecord( context->connection, &context->localSOARef, kDNSServiceFlagsUnique,
-		kDNSServiceInterfaceIndexLocalOnly, "local.", kDNSServiceType_SOA, kDNSServiceClass_IN,
-		(uint16_t) rdataLen, rdataPtr, 1 * kSecondsPerHour, _DotLocalTestRegisterRecordCallback, context );
-	require_noerr( err, exit );
-	
-	// Start timer for probe responses and SOA record registration.
-	
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDotLocalTestPreparationTimeLimitSecs ),
-		INT64_C_safe( kDotLocalTestPreparationTimeLimitSecs ) * kNanosecondsPerSecond / 10, dispatch_get_main_queue(),
-		_DotLocalTestTimerHandler, context, &context->timer );
-	require_noerr( err, exit );
-	dispatch_resume( context->timer );
-	
-	dispatch_main();
-	
-exit:
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestStateMachine
-//===========================================================================================================================
-
-static OSStatus	_DotLocalSubtestCreate( DotLocalSubtest **outSubtest );
-static void		_DotLocalSubtestFree( DotLocalSubtest *inSubtest );
-static OSStatus	_DotLocalTestStartSubtest( DotLocalTestContext *inContext );
-static OSStatus	_DotLocalTestFinalizeSubtest( DotLocalTestContext *inContext );
-static void		_DotLocalTestFinalizeAndExit( DotLocalTestContext *inContext ) ATTRIBUTE_NORETURN;
-
-static void	_DotLocalTestStateMachine( DotLocalTestContext *inContext )
-{
-	OSStatus				err;
-	DotLocalTestState		nextState;
-	
-	DNSServiceForget( &inContext->op );
-	DNSServiceForget( &inContext->op2 );
-	dispatch_source_forget( &inContext->timer );
-	
-	switch( inContext->state )
-	{
-		case kDotLocalTestState_Preparing:			nextState = kDotLocalTestState_GAIMDNSOnly;		break;
-		case kDotLocalTestState_GAIMDNSOnly:		nextState = kDotLocalTestState_GAIDNSOnly;		break;
-		case kDotLocalTestState_GAIDNSOnly:			nextState = kDotLocalTestState_GAIBoth;			break;
-		case kDotLocalTestState_GAIBoth:			nextState = kDotLocalTestState_GAINeither;		break;
-		case kDotLocalTestState_GAINeither:			nextState = kDotLocalTestState_GAINoSuchRecord;	break;
-		case kDotLocalTestState_GAINoSuchRecord:	nextState = kDotLocalTestState_QuerySRV;		break;
-		case kDotLocalTestState_QuerySRV:			nextState = kDotLocalTestState_Done;			break;
-		default:									err = kStateErr;								goto exit;
-	}
-	
-	if( inContext->state == kDotLocalTestState_Preparing )
-	{
-		if( !inContext->registeredSOA || !inContext->serverIsReady || !inContext->replierIsReady )
-		{
-			FPrintF( stderr, "Preparation timed out: Registered SOA? %s. Server ready? %s. mdnsreplier ready? %s.\n",
-				YesNoStr( inContext->registeredSOA ),
-				YesNoStr( inContext->serverIsReady ),
-				YesNoStr( inContext->replierIsReady ) );
-			err = kNotPreparedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = _DotLocalTestFinalizeSubtest( inContext );
-		require_noerr( err, exit );
-	}
-	
-	inContext->state = nextState;
-	if( inContext->state == kDotLocalTestState_Done ) _DotLocalTestFinalizeAndExit( inContext );
-	err = _DotLocalTestStartSubtest( inContext );
-	
-exit:
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_DotLocalSubtestCreate
-//===========================================================================================================================
-
-static OSStatus	_DotLocalSubtestCreate( DotLocalSubtest **outSubtest )
-{
-	OSStatus				err;
-	DotLocalSubtest *		obj;
-	
-	obj = (DotLocalSubtest *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->correctResults = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->correctResults, exit, err = kNoMemoryErr );
-	
-	obj->duplicateResults = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->duplicateResults, exit, err = kNoMemoryErr );
-	
-	obj->unexpectedResults = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->unexpectedResults, exit, err = kNoMemoryErr );
-	
-	*outSubtest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _DotLocalSubtestFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_DotLocalSubtestFree
-//===========================================================================================================================
-
-static void	_DotLocalSubtestFree( DotLocalSubtest *inSubtest )
-{
-	ForgetMem( &inSubtest->queryName );
-	ForgetCF( &inSubtest->correctResults );
-	ForgetCF( &inSubtest->duplicateResults );
-	ForgetCF( &inSubtest->unexpectedResults );
-	free( inSubtest );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestStartSubtest
-//===========================================================================================================================
-
-static OSStatus	_DotLocalTestStartSubtest( DotLocalTestContext *inContext )
-{
-	OSStatus				err;
-	DotLocalSubtest *		subtest	= NULL;
-	DNSServiceRef			op		= NULL;
-	DNSServiceFlags			flags;
-	
-	err = _DotLocalSubtestCreate( &subtest );
-	require_noerr( err, exit );
-	
-	if( inContext->state == kDotLocalTestState_GAIMDNSOnly )
-	{
-		ASPrintF( &subtest->queryName, "%s-2.local.", inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->hasMDNSv4 = subtest->needMDNSv4 = true;
-		subtest->hasMDNSv6 = subtest->needMDNSv6 = true;
-		
-		subtest->addrMDNSv4 = htonl( 0x00000201 );							// 0.0.2.1
-		memcpy( subtest->addrMDNSv6, kMDNSReplierLinkLocalBaseAddrV6, 16 );	// fe80::2:1
-		subtest->addrMDNSv6[ 13 ] = 2;
-		subtest->addrMDNSv6[ 15 ] = 1;
-		
-		subtest->testDesc = kDotLocalTestSubtestDesc_GAIMDNSOnly;
-	}
-	
-	else if( inContext->state == kDotLocalTestState_GAIDNSOnly )
-	{
-		ASPrintF( &subtest->queryName, "tag-dns-only.%s.local.", inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->hasDNSv4 = subtest->needDNSv4 = true;
-		subtest->hasDNSv6 = subtest->needDNSv6 = true;
-		
-		subtest->addrDNSv4 = htonl( kDNSServerBaseAddrV4 + 1 );				// 203.0.113.1
-		memcpy( subtest->addrDNSv6, kDNSServerBaseAddrV6, 16 );				// 2001:db8:1::1
-		subtest->addrDNSv6[ 15 ] = 1;
-		
-		subtest->testDesc = kDotLocalTestSubtestDesc_GAIDNSOnly;
-	}
-	
-	else if( inContext->state == kDotLocalTestState_GAIBoth )
-	{
-		ASPrintF( &subtest->queryName, "%s.local.", inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->hasDNSv4	= subtest->needDNSv4	= true;
-		subtest->hasDNSv6	= subtest->needDNSv6	= true;
-		subtest->hasMDNSv4	= subtest->needMDNSv4	= true;
-		subtest->hasMDNSv6	= subtest->needMDNSv6	= true;
-		
-		subtest->addrDNSv4 = htonl( kDNSServerBaseAddrV4 + 1 );				// 203.0.113.1
-		memcpy( subtest->addrDNSv6, kDNSServerBaseAddrV6, 16 );				// 2001:db8:1::1
-		subtest->addrDNSv6[ 15 ] = 1;
-		
-		subtest->addrMDNSv4 = htonl( 0x00000101 );							// 0.0.1.1
-		memcpy( subtest->addrMDNSv6, kMDNSReplierLinkLocalBaseAddrV6, 16 );	// fe80::1:1
-		subtest->addrMDNSv6[ 13 ] = 1;
-		subtest->addrMDNSv6[ 15 ] = 1;
-		
-		subtest->testDesc = kDotLocalTestSubtestDesc_GAIBoth;
-	}
-	
-	else if( inContext->state == kDotLocalTestState_GAINeither )
-	{
-		ASPrintF( &subtest->queryName, "doesnotexit-%s.local.", inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->testDesc = kDotLocalTestSubtestDesc_GAINeither;
-	}
-	
-	else if( inContext->state == kDotLocalTestState_GAINoSuchRecord )
-	{
-		ASPrintF( &subtest->queryName, "doesnotexit-dns.%s.local.", inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->hasDNSv4 = subtest->needDNSv4 = true;
-		subtest->hasDNSv6 = subtest->needDNSv6 = true;
-		subtest->testDesc = kDotLocalTestSubtestDesc_GAINoSuchRecord;
-	}
-	
-	else if( inContext->state == kDotLocalTestState_QuerySRV )
-	{
-		ASPrintF( &subtest->queryName, "_http._tcp.srv-%u-%u-%u.%s%s.local.",
-			kDotLocalTestSRV_Priority, kDotLocalTestSRV_Weight, kDotLocalTestSRV_Port, kDotLocalTestSRV_TargetStr,
-			inContext->labelStr );
-		require_action_quiet( subtest->queryName, exit, err = kNoMemoryErr );
-		
-		subtest->needSRV	= true;
-		subtest->testDesc	= kDotLocalTestSubtestDesc_QuerySRV;
-	}
-	
-	else
-	{
-		err = kStateErr;
-		goto exit;
-	}
-	
-	// Start new operation.
-	
-	flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsReturnIntermediates;
-#if( TARGET_OS_WATCH )
-	flags |= kDNSServiceFlagsPathEvaluationDone;
-#endif
-	
-	subtest->startTime	= NanoTimeGetCurrent();
-	subtest->endTime	= kNanoTime_Invalid;
-	
-	if( inContext->state == kDotLocalTestState_QuerySRV )
-	{
-		op = inContext->connection;
-		err = DNSServiceQueryRecord( &op, flags, kDNSServiceInterfaceIndexAny, subtest->queryName,
-			kDNSServiceType_SRV, kDNSServiceClass_IN, _DotLocalTestQueryRecordCallback, inContext );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		op = inContext->connection;
-		err = DNSServiceGetAddrInfo( &op, flags, kDNSServiceInterfaceIndexAny,
-			kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6, subtest->queryName, _DotLocalTestGAICallback, inContext );
-		require_noerr( err, exit );
-	}
-	
-	// Start timer.
-	
-	check( !inContext->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDotLocalTestSubtestDurationSecs ),
-		INT64_C_safe( kDotLocalTestSubtestDurationSecs ) * kNanosecondsPerSecond / 10, dispatch_get_main_queue(),
-		_DotLocalTestTimerHandler, inContext, &inContext->timer );
-	require_noerr( err, exit );
-	dispatch_resume( inContext->timer );
-	
-	check( !inContext->op );
-	inContext->op = op;
-	op = NULL;
-	
-	check( !inContext->subtest );
-	inContext->subtest = subtest;
-	subtest = NULL;
-	
-exit:
-	if( subtest )	_DotLocalSubtestFree( subtest );
-	if( op )		DNSServiceRefDeallocate( op );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestFinalizeSubtest
-//===========================================================================================================================
-
-#define kDotLocalTestReportKey_StartTime				CFSTR( "startTime" )		// String.
-#define kDotLocalTestReportKey_EndTime					CFSTR( "endTime" )			// String.
-#define kDotLocalTestReportKey_Success					CFSTR( "success" )			// Boolean.
-#define kDotLocalTestReportKey_MDNSReplierCmd			CFSTR( "replierCmd" )		// String.
-#define kDotLocalTestReportKey_DNSServerCmd				CFSTR( "serverCmd" )		// String.
-#define kDotLocalTestReportKey_GetAddrInfoTests			CFSTR( "testsGAI" )			// Array of Dictionaries.
-#define kDotLocalTestReportKey_QuerySRVTests			CFSTR( "testsQuerySRV" )	// Array of Dictionaries.
-#define kDotLocalTestReportKey_Description				CFSTR( "description" )		// String.
-#define kDotLocalTestReportKey_QueryName				CFSTR( "queryName" )		// String.
-#define kDotLocalTestReportKey_Error					CFSTR( "error" )			// Integer.
-#define kDotLocalTestReportKey_Results					CFSTR( "results" )			// Dictionary of Arrays.
-#define kDotLocalTestReportKey_CorrectResults			CFSTR( "correct" )			// Array of Strings
-#define kDotLocalTestReportKey_DuplicateResults			CFSTR( "duplicates" )		// Array of Strings.
-#define kDotLocalTestReportKey_UnexpectedResults		CFSTR( "unexpected" )		// Array of Strings.
-#define kDotLocalTestReportKey_MissingResults			CFSTR( "missing" )			// Array of Strings.
-
-static OSStatus	_DotLocalTestFinalizeSubtest( DotLocalTestContext *inContext )
-{
-	OSStatus					err;
-	DotLocalSubtest *			subtest;
-	CFMutableDictionaryRef		reportDict;
-	CFMutableDictionaryRef		resultsDict;
-	CFMutableArrayRef			missingResults, reportArray;
-	char						startTime[ 32 ];
-	char						endTime[ 32 ];
-	
-	subtest = inContext->subtest;
-	inContext->subtest = NULL;
-	
-	subtest->endTime = NanoTimeGetCurrent();
-	_NanoTime64ToTimestamp( subtest->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( subtest->endTime, endTime, sizeof( endTime ) );
-	
-	reportDict = NULL;
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &reportDict,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// queryName
-			"%kO=%s"	// description
-			"%kO={%@}"	// results
-		"}",
-		kDotLocalTestReportKey_StartTime,	startTime,
-		kDotLocalTestReportKey_EndTime,		endTime,
-		kDotLocalTestReportKey_QueryName,	subtest->queryName,
-		kDotLocalTestReportKey_Description,	subtest->testDesc,
-		kDotLocalTestReportKey_Results,		&resultsDict );
-	require_noerr( err, exit );
-	
-	missingResults = NULL;
-	switch( inContext->state )
-	{
-		case kDotLocalTestState_GAIMDNSOnly:
-		case kDotLocalTestState_GAIDNSOnly:
-		case kDotLocalTestState_GAIBoth:
-		case kDotLocalTestState_GAINeither:
-			if( subtest->needDNSv4 || subtest->needDNSv6 || subtest->needMDNSv4 || subtest->needMDNSv6 )
-			{
-				err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &missingResults,
-					"["
-						"%.4a"	// Expected DNS IPv4 address
-						"%.16a"	// Expected DNS IPv6 address
-						"%.4a"	// Expected MDNS IPv4 address
-						"%.16a"	// Expected MDNS IPv6 address
-					"]",
-					subtest->needDNSv4  ? &subtest->addrDNSv4  : NULL,
-					subtest->needDNSv6  ?  subtest->addrDNSv6  : NULL,
-					subtest->needMDNSv4 ? &subtest->addrMDNSv4 : NULL,
-					subtest->needMDNSv6 ?  subtest->addrMDNSv6 : NULL );
-				require_noerr( err, exit );
-			}
-			break;
-		
-		case kDotLocalTestState_QuerySRV:
-			if( subtest->needSRV )
-			{
-				err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &missingResults,
-					"["
-						"%s"	// Expected SRV record data as a string.
-					"]",
-					kDotLocalTestSRV_ResultStr );
-				require_noerr( err, exit );
-			}
-			break;
-		
-		case kDotLocalTestState_GAINoSuchRecord:
-			if( subtest->needDNSv4 || subtest->needDNSv6 )
-			{
-				err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &missingResults,
-					"["
-						"%s" // No Such Record (A)
-						"%s" // No Such Record (AAAA)
-					"]",
-					subtest->needDNSv4 ? kNoSuchRecordAStr    : NULL,
-					subtest->needDNSv6 ? kNoSuchRecordAAAAStr : NULL );
-				require_noerr( err, exit );
-			}
-			break;
-		
-		default:
-			err = kStateErr;
-			goto exit;
-	}
-	
-	CFDictionarySetValue( resultsDict, kDotLocalTestReportKey_CorrectResults, subtest->correctResults );
-	
-	if( missingResults )
-	{
-		CFDictionarySetValue( resultsDict, kDotLocalTestReportKey_MissingResults, missingResults );
-		ForgetCF( &missingResults );
-		if( !subtest->error ) subtest->error = kNotFoundErr;
-	}
-	
-	if( CFArrayGetCount( subtest->unexpectedResults ) > 0 )
-	{
-		CFDictionarySetValue( resultsDict, kDotLocalTestReportKey_UnexpectedResults, subtest->unexpectedResults );
-		if( !subtest->error ) subtest->error = kUnexpectedErr;
-	}
-	
-	if( CFArrayGetCount( subtest->duplicateResults ) > 0 )
-	{
-		CFDictionarySetValue( resultsDict, kDotLocalTestReportKey_DuplicateResults, subtest->duplicateResults );
-		if( !subtest->error ) subtest->error = kDuplicateErr;
-	}
-	
-	if( subtest->error ) inContext->testFailed = true;
-	err = CFDictionarySetInt64( reportDict, kDotLocalTestReportKey_Error, subtest->error );
-	require_noerr( err, exit );
-	
-	reportArray = ( inContext->state == kDotLocalTestState_QuerySRV ) ? inContext->reportsQuerySRV : inContext->reportsGAI;
-	CFArrayAppendValue( reportArray, reportDict );
-	
-exit:
-	_DotLocalSubtestFree( subtest );
-	CFReleaseNullSafe( reportDict );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestFinalizeAndExit
-//===========================================================================================================================
-
-static void	_DotLocalTestFinalizeAndExit( DotLocalTestContext *inContext )
-{
-	OSStatus				err;
-	CFPropertyListRef		plist;
-	char					timestampStart[ 32 ];
-	char					timestampEnd[ 32 ];
-	
-	check( !inContext->subtest );
-	inContext->endTime = NanoTimeGetCurrent();
-	
-	if( inContext->replierPID != -1 )
-	{
-		kill( inContext->replierPID, SIGTERM );
-		inContext->replierPID = -1;
-	}
-	if( inContext->serverPID != -1 )
-	{
-		kill( inContext->serverPID, SIGTERM );
-		inContext->serverPID = -1;
-	}
-	err = DNSServiceRemoveRecord( inContext->connection, inContext->localSOARef, 0 );
-	require_noerr( err, exit );
-	
-	_NanoTime64ToTimestamp( inContext->startTime, timestampStart, sizeof( timestampStart ) );
-	_NanoTime64ToTimestamp( inContext->endTime, timestampEnd, sizeof( timestampEnd ) );
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%O"	// testsGAI
-			"%kO=%O"	// testsQuerySRV
-			"%kO=%b"	// success
-			"%kO=%s"	// replierCmd
-			"%kO=%s"	// serverCmd
-		"}",
-		kDotLocalTestReportKey_StartTime,			timestampStart,
-		kDotLocalTestReportKey_EndTime,				timestampEnd,
-		kDotLocalTestReportKey_GetAddrInfoTests,	inContext->reportsGAI,
-		kDotLocalTestReportKey_QuerySRVTests,		inContext->reportsQuerySRV,
-		kDotLocalTestReportKey_Success,				inContext->testFailed ? false : true,
-		kDotLocalTestReportKey_MDNSReplierCmd,		inContext->replierCmd,
-		kDotLocalTestReportKey_DNSServerCmd,		inContext->serverCmd );
-	require_noerr( err, exit );
-	
-	ForgetCF( &inContext->reportsGAI );
-	ForgetCF( &inContext->reportsQuerySRV );
-	
-	err = OutputPropertyList( plist, inContext->outputFormat, inContext->outputFilePath );
-	CFRelease( plist );
-	require_noerr( err, exit );
-	
-	exit( inContext->testFailed ? 2 : 0 );
-	
-exit:
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestProbeQueryRecordCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DotLocalTestProbeQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	DotLocalTestContext * const		context = (DotLocalTestContext *) inContext;
-	
-	Unused( inInterfaceIndex );
-	Unused( inFullName );
-	Unused( inType );
-	Unused( inClass );
-	Unused( inRDataLen );
-	Unused( inRDataPtr );
-	Unused( inTTL );
-	
-	check( context->state == kDotLocalTestState_Preparing );
-	
-	require_quiet( ( inFlags & kDNSServiceFlagsAdd ) && !inError, exit );
-	
-	if( inSDRef == context->op )
-	{
-		DNSServiceForget( &context->op );
-		context->serverIsReady = true;
-	}
-	else if( inSDRef == context->op2 )
-	{
-		DNSServiceForget( &context->op2 );
-		context->replierIsReady = true;
-	}
-	
-	if( context->registeredSOA && context->serverIsReady && context->replierIsReady )
-	{
-		_DotLocalTestStateMachine( context );
-	}
-	
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	_DotLocalTestRegisterRecordCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DotLocalTestRegisterRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSRecordRef		inRecordRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		void *				inContext )
-{
-	DotLocalTestContext * const		context = (DotLocalTestContext *) inContext;
-	
-	Unused( inSDRef );
-	Unused( inRecordRef );
-	Unused( inFlags );
-	
-	if( inError ) ErrQuit( 1, "error: local. SOA record registration failed: %#m\n", inError );
-	
-	if( !context->registeredSOA )
-	{
-		context->registeredSOA = true;
-		if( context->serverIsReady && context->replierIsReady ) _DotLocalTestStateMachine( context );
-	}
-}
-
-//===========================================================================================================================
-//	_DotLocalTestTimerHandler
-//===========================================================================================================================
-
-static void	_DotLocalTestTimerHandler( void *inContext )
-{
-	_DotLocalTestStateMachine( (DotLocalTestContext *) inContext );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestGAICallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DotLocalTestGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus						err;
-	DotLocalTestContext * const		context = (DotLocalTestContext *) inContext;
-	DotLocalSubtest * const			subtest	= context->subtest;
-	const sockaddr_ip * const		sip		= (const sockaddr_ip *) inSockAddr;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inHostname );
-	Unused( inTTL );
-	
-	require_action_quiet( inFlags & kDNSServiceFlagsAdd, exit, err = kFlagErr );
-	require_action_quiet( ( sip->sa.sa_family == AF_INET ) || ( sip->sa.sa_family == AF_INET6 ), exit, err = kTypeErr );
-	
-	if( context->state == kDotLocalTestState_GAINoSuchRecord )
-	{
-		if( inError == kDNSServiceErr_NoSuchRecord )
-		{
-			CFMutableArrayRef		array = NULL;	
-			const char *			noSuchRecordStr;
-			
-			if( sip->sa.sa_family == AF_INET )
-			{
-				array = subtest->needDNSv4 ? subtest->correctResults : subtest->duplicateResults;
-				subtest->needDNSv4 = false;
-				
-				noSuchRecordStr = kNoSuchRecordAStr;
-			}
-			else
-			{
-				array = subtest->needDNSv6 ? subtest->correctResults : subtest->duplicateResults;
-				subtest->needDNSv6 = false;
-				
-				noSuchRecordStr = kNoSuchRecordAAAAStr;
-			}
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, array, "%s", noSuchRecordStr );
-			require_noerr( err, fatal );
-		}
-		else if( !inError )
-		{
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, subtest->unexpectedResults, "%##a", sip );
-			require_noerr( err, fatal );
-		}
-		else
-		{
-			err = inError;
-			goto exit;
-		}
-	}
-	else
-	{
-		if( !inError )
-		{
-			CFMutableArrayRef		array = NULL;	
-			
-			if( sip->sa.sa_family == AF_INET )
-			{
-				const uint32_t		addrV4 = sip->v4.sin_addr.s_addr;
-				
-				if( subtest->hasDNSv4 && ( addrV4 == subtest->addrDNSv4 ) )
-				{
-					array = subtest->needDNSv4 ? subtest->correctResults : subtest->duplicateResults;
-					subtest->needDNSv4 = false;
-				}
-				else if( subtest->hasMDNSv4 && ( addrV4 == subtest->addrMDNSv4 ) )
-				{
-					array = subtest->needMDNSv4 ? subtest->correctResults : subtest->duplicateResults;
-					subtest->needMDNSv4 = false;
-				}
-			}
-			else
-			{
-				const uint8_t * const		addrV6 = sip->v6.sin6_addr.s6_addr;
-				
-				if( subtest->hasDNSv6 && ( memcmp( addrV6, subtest->addrDNSv6, 16 ) == 0 ) )
-				{
-					array = subtest->needDNSv6 ? subtest->correctResults : subtest->duplicateResults;
-					subtest->needDNSv6 = false;
-				}
-				else if( subtest->hasMDNSv6 && ( memcmp( addrV6, subtest->addrMDNSv6, 16 ) == 0 ) )
-				{
-					array = subtest->needMDNSv6 ? subtest->correctResults : subtest->duplicateResults;
-					subtest->needMDNSv6 = false;
-				}
-			}
-			if( !array ) array = subtest->unexpectedResults;
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, array, "%##a", sip );
-			require_noerr( err, fatal );
-		}
-		else if( inError == kDNSServiceErr_NoSuchRecord )
-		{
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, subtest->unexpectedResults, "%s",
-				( sip->sa.sa_family == AF_INET ) ? kNoSuchRecordAStr : kNoSuchRecordAAAAStr );
-			require_noerr( err, fatal );
-		}
-		else
-		{
-			err = inError;
-			goto exit;
-		}
-	}
-	
-exit:
-	if( err )
-	{
-		subtest->error = err;
-		_DotLocalTestStateMachine( context );
-	}
-	return;
-	
-fatal:
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_DotLocalTestQueryRecordCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DotLocalTestQueryRecordCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus							err;
-	DotLocalTestContext * const			context = (DotLocalTestContext *) inContext;
-	DotLocalSubtest * const				subtest = context->subtest;
-	const dns_fixed_fields_srv *		fields;
-	const uint8_t *						target;
-	const uint8_t *						ptr;
-	const uint8_t *						end;
-	char *								rdataStr;
-	unsigned int						priority, weight, port;
-	CFMutableArrayRef					array;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inFullName );
-	Unused( inTTL );
-	
-	check( context->state == kDotLocalTestState_QuerySRV );
-	
-	err = inError;
-	require_noerr_quiet( err, exit );
-	require_action_quiet( inFlags & kDNSServiceFlagsAdd, exit, err = kFlagErr );
-	require_action_quiet( ( inType == kDNSServiceType_SRV ) && ( inClass == kDNSServiceClass_IN ), exit, err = kTypeErr );
-	require_action_quiet( inRDataLen > sizeof( dns_fixed_fields_srv ), exit, err = kSizeErr );
-	
-	fields		= (const dns_fixed_fields_srv *) inRDataPtr;
-	priority	= dns_fixed_fields_srv_get_priority( fields );
-	weight		= dns_fixed_fields_srv_get_weight( fields );
-	port		= dns_fixed_fields_srv_get_port( fields );
-	target		= (const uint8_t *) &fields[ 1 ];
-	end			= ( (const uint8_t *) inRDataPtr ) + inRDataLen;
-	for( ptr = target; ( ptr < end ) && ( *ptr != 0 ); ptr += ( 1 + *ptr ) ) {}
-	
-	if( ( priority == kDotLocalTestSRV_Priority ) &&
-		( weight   == kDotLocalTestSRV_Weight )   &&
-		( port     == kDotLocalTestSRV_Port )     &&
-		( ptr < end ) && DomainNameEqual( target, kDotLocalTestSRV_TargetName ) )
-	{
-		array = subtest->needSRV ? subtest->correctResults : subtest->duplicateResults;
-		subtest->needSRV = false;
-	}
-	else
-	{
-		array = subtest->unexpectedResults;
-	}
-	
-	rdataStr = NULL;
-	DNSRecordDataToString( inRDataPtr, inRDataLen, kDNSServiceType_SRV, &rdataStr );
-	if( !rdataStr )
-	{
-		ASPrintF( &rdataStr, "%#H", inRDataPtr, inRDataLen, inRDataLen );
-		require_action( rdataStr, fatal, err = kNoMemoryErr );
-	}
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, array, "%s", rdataStr );
-	free( rdataStr );
-	require_noerr( err, fatal );
-	
-exit:
-	if( err )
-	{
-		subtest->error = err;
-		_DotLocalTestStateMachine( context );
-	}
-	return;
-	
-fatal:
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	ProbeConflictTestCmd
-//===========================================================================================================================
-
-#define kProbeConflictTestService_DefaultName		"pctest-name"
-#define kProbeConflictTestService_Port				60000
-
-#define kProbeConflictTestTXTPtr		"\x13" "PROBE-CONFLICT-TEST"
-#define kProbeConflictTestTXTLen		sizeof_string( kProbeConflictTestTXTPtr )
-
-typedef struct
-{
-	const char *		description;
-	const char *		program;
-	Boolean				expectsRename;
-	
-}	ProbeConflictTestCase;
-
-// Wait 1 second before sending gratuitous response.
-
-#define kPCTProgPreWait		"wait 1000;"
-
-// Wait at least 10 seconds after sending gratuitous response. This allows ~2.75 seconds for probing, ~5 seconds for a
-// rename, and a 2 second fudge factor for unexpected system delays.
-
-#define kProbeConflictTestPostWaitMs		( 10 * kMillisecondsPerSecond )
-
-static const ProbeConflictTestCase		kProbeConflictTestCases[] =
-{
-	// No conflicts
-	
-	{ "No probe conflicts.",                       kPCTProgPreWait "probes n-n-n;"       "send;", false },
-	
-	// One multicast probe conflict
-	
-	{ "One multicast probe conflict (1).",         kPCTProgPreWait "probes m;"           "send;", false },
-	{ "One multicast probe conflict (2).",         kPCTProgPreWait "probes n-m;"         "send;", false },
-	{ "One multicast probe conflict (3).",         kPCTProgPreWait "probes n-n-m;"       "send;", false },
-	
-	// One unicast probe conflict
-	
-	{ "One unicast probe conflict (1).",           kPCTProgPreWait "probes u;"           "send;", true },
-	{ "One unicast probe conflict (2).",           kPCTProgPreWait "probes n-u;"         "send;", true },
-	{ "One unicast probe conflict (3).",           kPCTProgPreWait "probes n-n-u;"       "send;", true },
-	
-	// One multicast and one unicast probe conflict
-	
-	{ "Multicast and unicast probe conflict (1).", kPCTProgPreWait "probes m-u;"         "send;", true },
-	{ "Multicast and unicast probe conflict (2).", kPCTProgPreWait "probes m-n-u;"       "send;", true },
-	{ "Multicast and unicast probe conflict (3).", kPCTProgPreWait "probes m-n-n-u;"     "send;", true },
-	{ "Multicast and unicast probe conflict (4).", kPCTProgPreWait "probes n-m-u;"       "send;", true },
-	{ "Multicast and unicast probe conflict (5).", kPCTProgPreWait "probes n-m-n-u;"     "send;", true },
-	{ "Multicast and unicast probe conflict (6).", kPCTProgPreWait "probes n-m-n-n-u;"   "send;", true },
-	{ "Multicast and unicast probe conflict (7).", kPCTProgPreWait "probes n-n-m-u;"     "send;", true },
-	{ "Multicast and unicast probe conflict (8).", kPCTProgPreWait "probes n-n-m-n-u;"   "send;", true },
-	{ "Multicast and unicast probe conflict (9).", kPCTProgPreWait "probes n-n-m-n-n-u;" "send;", true },
-	
-	// Two multicast probe conflicts
-	
-	{ "Two multicast probe conflicts (1).",        kPCTProgPreWait "probes m-m;"         "send;", true },
-	{ "Two multicast probe conflicts (2).",        kPCTProgPreWait "probes m-n-m;"       "send;", true },
-	{ "Two multicast probe conflicts (3).",        kPCTProgPreWait "probes m-n-n-m;"     "send;", true },
-	{ "Two multicast probe conflicts (4).",        kPCTProgPreWait "probes n-m-m;"       "send;", true },
-	{ "Two multicast probe conflicts (5).",        kPCTProgPreWait "probes n-m-n-m-n;"   "send;", true },
-	{ "Two multicast probe conflicts (6).",        kPCTProgPreWait "probes n-m-n-n-m;"   "send;", true },
-	{ "Two multicast probe conflicts (7).",        kPCTProgPreWait "probes n-n-m-m;"     "send;", true },
-	{ "Two multicast probe conflicts (8).",        kPCTProgPreWait "probes n-n-m-n-m;"   "send;", true },
-	{ "Two multicast probe conflicts (9).",        kPCTProgPreWait "probes n-n-m-n-n-m;" "send;", true },
-};
-
-#define kProbeConflictTestCaseCount		countof( kProbeConflictTestCases )
-
-typedef struct
-{
-	DNSServiceRef				registration;		// Test service registration.
-	NanoTime64					testStartTime;		// Test's start time.
-	NanoTime64					startTime;			// Current test case's start time.
-	MDNSColliderRef				collider;			// mDNS collider object.
-	CFMutableArrayRef			results;			// Array of test case results.
-	char *						serviceName;		// Test service's instance name as a string. (malloced)
-	char *						serviceType;		// Test service's service type as a string. (malloced)
-	uint8_t *					recordName;			// FQDN of collider's record (same as test service's records). (malloced)
-	dispatch_source_t			sigSourceINT;		// SIGINT signal handler.
-	dispatch_source_t			sigSourceTERM;		// SIGTERM signal handler.
-	CFStringRef					exComputerName;		// Previous ComputerName.
-	CFStringRef					exLocalHostName;	// Previous LocalHostName.
-	CFStringEncoding			exCompNameEnc;		// Previous ComputerName's encoding.
-	unsigned int				testCaseIndex;		// Index of the current test case.
-	uint32_t					conflictIfIndex;	// Index of the interface that the collider is to operate on.
-	uint32_t					registerIfIndex;	// Index of the interface to register the test service on.
-	uint32_t					extraWaitMs;		// Extra amount of time to wait for renames in milliseconds.
-	MDNSColliderProtocols		protocol;			// mDNS collider's IP protocol.
-	char *						outputFilePath;		// File to write test results to. If NULL, write to stdout. (malloced)
-	OutputFormatType			outputFormat;		// Format of test report output.
-	Boolean						registered;			// True if the test service instance is currently registered.
-	Boolean						testFailed;			// True if at least one test case failed.
-	
-}	ProbeConflictTestContext;
-
-static void DNSSD_API
-	_ProbeConflictTestRegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain,
-		void *				inContext );
-static void		_ProbeConflictTestColliderStopHandler( void *inContext, OSStatus inError );
-static OSStatus	_ProbeConflictTestStartNextTest( ProbeConflictTestContext *inContext );
-static OSStatus	_ProbeConflictTestStopCurrentTest( ProbeConflictTestContext *inContext, Boolean inRenamed );
-static void		_ProbeConflictTestFinalizeAndExit( ProbeConflictTestContext *inContext ) ATTRIBUTE_NORETURN;
-static void		_ProbeConflictTestRestoreSystemNames( ProbeConflictTestContext *inContext );
-static void		_ProbeConflictTestSignalHandler( void *inContext );
-
-static void	ProbeConflictTestCmd( void )
-{
-	OSStatus						err;
-	ProbeConflictTestContext *		context;
-	const char *					serviceName;
-	CFStringRef						computerName	= NULL;
-	CFStringRef						localHostName	= NULL;
-	char *							uniqueName;
-	char							tag[ 6 + 1 ];
-	
-	context = (ProbeConflictTestContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	if( gProbeConflictTest_Interface )
-	{
-		err = InterfaceIndexFromArgString( gProbeConflictTest_Interface, &context->conflictIfIndex );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		err = _MDNSInterfaceGetAny( kMDNSInterfaceSubset_All, NULL, &context->conflictIfIndex );
-		require_noerr_quiet( err, exit );
-	}
-	
-	if( gProbeConflictTest_UseIPv6 )
-	{
-		if( gProbeConflictTest_UseIPv4 )
-		{
-			FPrintF( stderr, "error: --ipv4 and --ipv6 are mutually exclusive options.\n" );
-			goto exit;
-		}
-		context->protocol = kMDNSColliderProtocol_IPv6;
-	}
-	else
-	{
-		context->protocol = kMDNSColliderProtocol_IPv4;
-	}
-	context->registerIfIndex = gProbeConflictTest_RegisterOnAny ? kDNSServiceInterfaceIndexAny : context->conflictIfIndex;
-	
-	// Make sure that the sum of kProbeConflictTestPostWaitMs and extraWaitMs doesn't wrap under uint32_t arithmetic.
-	
-	check_compile_time_code( INT_MAX <= ( UINT32_MAX - kProbeConflictTestPostWaitMs ) );
-	err = CheckIntegerArgument( gProbeConflictTest_ExtraWaitMs, "extraWait", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	context->extraWaitMs = (uint32_t) gProbeConflictTest_ExtraWaitMs;
-	if( gProbeConflictTest_OutputFilePath )
-	{
-		context->outputFilePath = strdup( gProbeConflictTest_OutputFilePath );
-		require_action( context->outputFilePath, exit, err = kNoMemoryErr );
-	}
-	
-	err = OutputFormatFromArgString( gProbeConflictTest_OutputFormat, &context->outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	context->results = CFArrayCreateMutable( NULL, kProbeConflictTestCaseCount, &kCFTypeArrayCallBacks );
-	require_action( context->results, exit, err = kNoMemoryErr );
-	
-	context->testStartTime = NanoTimeGetCurrent();
-	
-	// Set a unique ComputerName.
-	
-	computerName = SCDynamicStoreCopyComputerName( NULL, &context->exCompNameEnc );
-	err = map_scerror( computerName );
-	require_noerr( err, exit );
-	
-	_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag );
-	ASPrintF( &uniqueName, "dnssdutil-pctest-computer-name-%s", tag );
-	require_action( uniqueName, exit, err = kNoMemoryErr );
-	
-	err = _SetComputerNameWithUTF8CString( uniqueName );
-	ForgetMem( &uniqueName );
-	require_noerr( err, exit );
-	context->exComputerName = computerName;
-	computerName = NULL;
-	
-	// Set a unique LocalHostName.
-	
-	localHostName = SCDynamicStoreCopyLocalHostName( NULL );
-	err = map_scerror( localHostName );
-	require_noerr( err, exit );
-	
-	ASPrintF( &uniqueName, "dnssdutil-pctest-local-hostname-%s", tag );
-	require_action( uniqueName, exit, err = kNoMemoryErr );
-	
-	err = _SetLocalHostNameWithUTF8CString( uniqueName );
-	ForgetMem( &uniqueName );
-	require_noerr( err, exit );
-	context->exLocalHostName = localHostName;
-	localHostName = NULL;
-	
-	// Set up SIGINT signal handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), _ProbeConflictTestSignalHandler, context,
-		&context->sigSourceINT );
-	require_noerr( err, exit );
-	dispatch_resume( context->sigSourceINT );
-	
-	// Set up SIGTERM signal handler.
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, dispatch_get_main_queue(), _ProbeConflictTestSignalHandler, context,
-		&context->sigSourceTERM );
-	require_noerr( err, exit );
-	dispatch_resume( context->sigSourceTERM );
-	
-	// Register the test service instance.
-	
-	serviceName = gProbeConflictTest_UseComputerName ? NULL : kProbeConflictTestService_DefaultName;
-	
-	ASPrintF( &context->serviceType, "_pctest-%s._udp", tag );
-	require_action( context->serviceType, exit, err = kNoMemoryErr );
-	
-	err = DNSServiceRegister( &context->registration, 0, context->registerIfIndex, serviceName, context->serviceType,
-		"local.", NULL, htons( kProbeConflictTestService_Port ), 0, NULL, _ProbeConflictTestRegisterCallback, context );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( context->registration, dispatch_get_main_queue() );
-	require_noerr( err, exit );
-	
-	dispatch_main();
-	
-exit:
-	CFReleaseNullSafe( computerName );
-	CFReleaseNullSafe( localHostName );
-	if( context ) _ProbeConflictTestRestoreSystemNames( context );
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestRegisterCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ProbeConflictTestRegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	OSStatus								err;
-	ProbeConflictTestContext * const		context = (ProbeConflictTestContext *) inContext;
-	
-	Unused( inSDRef );
-	Unused( inType );
-	Unused( inDomain );
-	
-	err = inError;
-	require_noerr( err, exit );
-	
-	if( !context->registered )
-	{
-		if( inFlags & kDNSServiceFlagsAdd )
-		{
-			uint8_t *			ptr;
-			size_t				recordNameLen;
-			unsigned int		len;
-			uint8_t				name[ kDomainNameLengthMax ];
-			
-			context->registered = true;
-			
-			FreeNullSafe( context->serviceName );
-			context->serviceName = strdup( inName );
-			require_action( context->serviceName, exit, err = kNoMemoryErr );
-			
-			err = DomainNameFromString( name, context->serviceName, NULL );
-			require_noerr( err, exit );
-			
-			err = DomainNameAppendString( name, context->serviceType, NULL );
-			require_noerr( err, exit );
-			
-			err = DomainNameAppendString( name, "local", NULL );
-			require_noerr( err, exit );
-			
-			ForgetMem( &context->recordName );
-			err = DomainNameDup( name, &context->recordName, &recordNameLen );
-			require_noerr( err, exit );
-			require_fatal( recordNameLen > 0, "Record name length is zero." );	// Prevents dubious static analyzer warning.
-			
-			// Make the first label all caps so that it's easier to spot in system logs.
-			
-			ptr = context->recordName;
-			for( len = *ptr++; len > 0; --len, ++ptr ) *ptr = (uint8_t) toupper_safe( *ptr );
-			
-			err = _ProbeConflictTestStartNextTest( context );
-			require_noerr( err, exit );
-		}
-	}
-	else
-	{
-		if( !( inFlags & kDNSServiceFlagsAdd ) )
-		{
-			context->registered = false;
-			err = _ProbeConflictTestStopCurrentTest( context, true );
-			require_noerr( err, exit );
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestColliderStopHandler
-//===========================================================================================================================
-
-static void	_ProbeConflictTestColliderStopHandler( void *inContext, OSStatus inError )
-{
-	OSStatus								err;
-	ProbeConflictTestContext * const		context = (ProbeConflictTestContext *) inContext;
-	
-	err = inError;
-	require_noerr_quiet( err, exit );
-	
-	ForgetCF( &context->collider );
-	
-	err = _ProbeConflictTestStopCurrentTest( context, false );
-	require_noerr( err, exit );
-	
-	err = _ProbeConflictTestStartNextTest( context );
-	require_noerr( err, exit );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestStartNextTest
-//===========================================================================================================================
-
-static OSStatus	_ProbeConflictTestStartNextTest( ProbeConflictTestContext * const inContext )
-{
-	OSStatus							err;
-	const ProbeConflictTestCase *		testCase;
-	char *								program = NULL;
-	uint32_t							totalWaitMs;
-	
-	check( !inContext->collider );
-	
-	if( inContext->testCaseIndex < kProbeConflictTestCaseCount )
-	{
-		testCase = &kProbeConflictTestCases[ inContext->testCaseIndex ];
-	}
-	else
-	{
-		_ProbeConflictTestFinalizeAndExit( inContext );
-	}
-	
-	err = MDNSColliderCreate( dispatch_get_main_queue(), &inContext->collider );
-	require_noerr( err, exit );
-	
-	totalWaitMs = kProbeConflictTestPostWaitMs + inContext->extraWaitMs;
-	ASPrintF( &program, "%s wait %u;", testCase->program, totalWaitMs );
-	require_action( program, exit, err = kNoMemoryErr );
-	
-	err = MDNSColliderSetProgram( inContext->collider, program );
-	require_noerr( err, exit );
-	
-	err = MDNSColliderSetRecord( inContext->collider, inContext->recordName, kDNSServiceType_TXT,
-		kProbeConflictTestTXTPtr, kProbeConflictTestTXTLen );
-	require_noerr( err, exit );
-	
-	MDNSColliderSetProtocols( inContext->collider, inContext->protocol );
-	MDNSColliderSetInterfaceIndex( inContext->collider, inContext->conflictIfIndex );
-	MDNSColliderSetStopHandler( inContext->collider, _ProbeConflictTestColliderStopHandler, inContext );
-	
-	inContext->startTime = NanoTimeGetCurrent();
-	err = MDNSColliderStart( inContext->collider );
-	require_noerr( err, exit );
-	
-exit:
-	ForgetMem( &program );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestStopCurrentTest
-//===========================================================================================================================
-
-#define kProbeConflictTestCaseResultKey_Description			CFSTR( "description" )
-#define kProbeConflictTestCaseResultKey_StartTime			CFSTR( "startTime" )
-#define kProbeConflictTestCaseResultKey_EndTime				CFSTR( "endTime" )
-#define kProbeConflictTestCaseResultKey_ExpectedRename		CFSTR( "expectedRename" )
-#define kProbeConflictTestCaseResultKey_ServiceName			CFSTR( "serviceName" )
-#define kProbeConflictTestCaseResultKey_Passed				CFSTR( "passed" )
-
-static OSStatus	_ProbeConflictTestStopCurrentTest( ProbeConflictTestContext *inContext, Boolean inRenamed )
-{
-	OSStatus							err;
-	const ProbeConflictTestCase *		testCase;
-	NanoTime64							now;
-	Boolean								passed;
-	char								startTime[ 32 ];
-	char								endTime[ 32 ];
-	
-	now = NanoTimeGetCurrent();
-	
-	if( inContext->collider )
-	{
-		MDNSColliderSetStopHandler( inContext->collider, NULL, NULL );
-		MDNSColliderStop( inContext->collider );
-		CFRelease( inContext->collider );
-		inContext->collider = NULL;
-	}
-	
-	testCase = &kProbeConflictTestCases[ inContext->testCaseIndex ];
-	passed = ( ( testCase->expectsRename && inRenamed ) || ( !testCase->expectsRename && !inRenamed ) ) ? true : false;
-	if( !passed ) inContext->testFailed = true;
-	
-	_NanoTime64ToTimestamp( inContext->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, inContext->results,
-		"{"
-			"%kO=%s"	// description
-			"%kO=%b"	// expectedRename
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// serviceName
-			"%kO=%b"	// passed
-		"}",
-		kProbeConflictTestCaseResultKey_Description,	testCase->description,
-		kProbeConflictTestCaseResultKey_ExpectedRename,	testCase->expectsRename,
-		kProbeConflictTestCaseResultKey_StartTime,		startTime,
-		kProbeConflictTestCaseResultKey_EndTime,		endTime,
-		kProbeConflictTestCaseResultKey_ServiceName,	inContext->serviceName,
-		kProbeConflictTestCaseResultKey_Passed,			passed );
-	require_noerr( err, exit );
-	
-	++inContext->testCaseIndex;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestFinalizeAndExit
-//===========================================================================================================================
-
-#define kProbeConflictTestReportKey_StartTime				CFSTR( "startTime" )
-#define kProbeConflictTestReportKey_EndTime					CFSTR( "endTime" )
-#define kProbeConflictTestReportKey_ServiceType				CFSTR( "serviceType" )
-#define kProbeConflictTestReportKey_RegistrationInterface	CFSTR( "registrationInterface" )
-#define kProbeConflictTestReportKey_ConflictInterface		CFSTR( "conflictInterface" )
-#define kProbeConflictTestReportKey_Index					CFSTR( "index" )
-#define kProbeConflictTestReportKey_Name					CFSTR( "name" )
-#define kProbeConflictTestReportKey_ExtraWaitMs				CFSTR( "extraWaitMs" )
-#define kProbeConflictTestReportKey_Results					CFSTR( "results" )
-#define kProbeConflictTestReportKey_Passed					CFSTR( "passed" )
-
-static void	_ProbeConflictTestFinalizeAndExit( ProbeConflictTestContext *inContext )
-{
-	OSStatus				err;
-	CFPropertyListRef		plist;
-	NanoTime64				now;
-	int						exitCode;
-	char					startTime[ 32 ];
-	char					endTime[ 32 ];
-	char					registerIfName[ kInterfaceNameBufLen ];
-	char					conflictIfName[ kInterfaceNameBufLen ];
-	
-	now = NanoTimeGetCurrent();
-	
-	check( !inContext->collider );
-	
-	_NanoTime64ToTimestamp( inContext->testStartTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-	InterfaceIndexToName( inContext->registerIfIndex, registerIfName );
-	InterfaceIndexToName( inContext->conflictIfIndex, conflictIfName );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// serviceType
-			"%kO="		// registrationInterface
-			"{"
-				"%kO=%lli"	// index
-				"%kO=%s"	// name
-			"}"
-			"%kO="		// conflictInterface
-			"{"
-				"%kO=%lli"	// index
-				"%kO=%s"	// name
-			"}"
-			"%kO=%lli"	// extraWaitMs
-			"%kO=%O"	// results
-			"%kO=%b"	// passed
-		"}",
-		kProbeConflictTestReportKey_StartTime,				startTime,
-		kProbeConflictTestReportKey_EndTime,				endTime,
-		kProbeConflictTestReportKey_ServiceType,			inContext->serviceType,
-		kProbeConflictTestReportKey_RegistrationInterface,
-		kProbeConflictTestReportKey_Index,					(int64_t) inContext->registerIfIndex,
-		kProbeConflictTestReportKey_Name,					registerIfName,
-		kProbeConflictTestReportKey_ConflictInterface,
-		kProbeConflictTestReportKey_Index,					(int64_t) inContext->conflictIfIndex,
-		kProbeConflictTestReportKey_Name,					conflictIfName,
-		kProbeConflictTestReportKey_ExtraWaitMs,			(int64_t) inContext->extraWaitMs,
-		kProbeConflictTestReportKey_Results,				inContext->results,
-		kProbeConflictTestReportKey_Passed,					inContext->testFailed ? false : true );
-	require_noerr( err, exit );
-	ForgetCF( &inContext->results );
-	
-	err = OutputPropertyList( plist, inContext->outputFormat, inContext->outputFilePath );
-	CFRelease( plist );
-	require_noerr( err, exit );
-	
-exit:
-	_ProbeConflictTestRestoreSystemNames( inContext );
-	if( err )
-	{
-		FPrintF( stderr, "error: %#m\n", err );
-		exitCode = 1;
-	}
-	else
-	{
-		exitCode = inContext->testFailed ? 2 : 0;
-	}
-	exit( exitCode );
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestRestoreSystemNames
-//===========================================================================================================================
-
-static void	_ProbeConflictTestRestoreSystemNames( ProbeConflictTestContext *inContext )
-{
-	OSStatus		err;
-	
-	if( inContext->exComputerName )
-	{
-		err = _SetComputerName( inContext->exComputerName, inContext->exCompNameEnc );
-		check_noerr( err );
-		ForgetCF( &inContext->exComputerName );
-	}
-	if( inContext->exLocalHostName )
-	{
-		err = _SetLocalHostName( inContext->exLocalHostName );
-		check_noerr( err );
-		ForgetCF( &inContext->exLocalHostName );
-	}
-}
-
-//===========================================================================================================================
-//	_ProbeConflictTestSignalHandler
-//===========================================================================================================================
-
-static void	_ProbeConflictTestSignalHandler( void *inContext )
-{
-	_ProbeConflictTestRestoreSystemNames( inContext );
-	FPrintF( stderr, "Probe conflict test got a SIGINT or SIGTERM signal, exiting...\n" );
-	exit( 1 );
-}
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//    FallbackTestCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	unsigned int		serverIndex;		// Index of server that is soley capable of answering query.
-	
-}	FallbackSubtestParams;
-
-#define kFallbackTestSubtestCount		8
-
-const FallbackSubtestParams		kFallbackSubtestParams[] = { { 2 }, { 4 }, { 1 }, { 3 }, { 2 }, { 1 }, { 4 }, { 3 } };
-check_compile_time( countof( kFallbackSubtestParams ) == kFallbackTestSubtestCount );
-
-typedef struct
-{
-	char *			hostname;	// Hostname to resolve.
-	NanoTime64		startTime;	// Subtest's start time.
-	NanoTime64		endTime;	// Subtest's end time.
-	OSStatus		error;		// Subtest's current error.
-	
-}	FallbackSubtest;
-
-typedef struct
-{
-	dispatch_queue_t			queue;			// Serial queue for test events.
-	dispatch_semaphore_t		doneSem;		// Semaphore to signal when the test is done.
-	DNSServiceRef				gai;			// Current DNSServiceGetAddrInfo request.
-	dispatch_source_t			timer;			// Timer for enforcing time limit on current DNSServiceGetAddrInfo request.
-	size_t						subtestIndex;	// Index of current subtest.
-	pid_t						serverPID;		// PID of spawned test DNS server.
-	OSStatus					error;			// Current test error.
-	NanoTime64					startTime;		// Test's start time.
-	NanoTime64					endTime;		// Test's end time.
-	char *						serverCmd;		// Command used to invoke the test DNS server.
-	char *						probeHostname;	// Hostname queried to verify that server is up and running.
-	FallbackSubtest				subtests[ kFallbackTestSubtestCount ];
-	Boolean						useRefused;		// True if server uses Refused RCODE for queries it's not allowed to answer.
-	
-}	FallbackTest;
-
-static OSStatus	_FallbackTestCreate( FallbackTest **outTest );
-static OSStatus	_FallbackTestRun( FallbackTest *inTest );
-static void		_FallbackTestFree( FallbackTest *inTest );
-
-ulog_define_ex( kDNSSDUtilIdentifier, FallbackTest, kLogLevelInfo, kLogFlags_None, "FallbackTest", NULL );
-#define ft_ulog( LEVEL, ... )		ulog( &log_category_from_name( FallbackTest ), (LEVEL), __VA_ARGS__ )
-
-static void	FallbackTestCmd( void )
-{
-	OSStatus				err;
-	FallbackTest *			test		= NULL;
-	CFPropertyListRef		plist		= NULL;
-	OutputFormatType		outputFormat;
-	size_t					i;
-	CFMutableArrayRef		results;
-	Boolean					testPassed	= false;
-	Boolean					subtestFailed;
-	char					startTime[ 32 ];
-	char					endTime[ 32 ];
-	
-	err = CheckRootUser();
-	require_noerr_quiet( err, exit );
-	
-	err = OutputFormatFromArgString( gFallbackTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _FallbackTestCreate( &test );
-	require_noerr( err, exit );
-	
-	if( gFallbackTest_UseRefused ) test->useRefused = true;
-	err = _FallbackTestRun( test );
-	require_noerr( err, exit );
-	
-	_NanoTime64ToTimestamp( test->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( test->endTime, endTime, sizeof( endTime ) );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// serverCmd
-			"%kO=[%@]"	// results
-		"}",
-		CFSTR( "startTime" ),	startTime,
-		CFSTR( "endTime" ),		endTime,
-		CFSTR( "serverCmd" ),	test->serverCmd,
-		CFSTR( "results" ),		&results );
-	require_noerr( err, exit );
-	
-	subtestFailed = false;
-	check( test->subtestIndex == kFallbackTestSubtestCount );
-	for( i = 0; i < kFallbackTestSubtestCount; ++i )
-	{
-		CFMutableDictionaryRef		resultDict;
-		FallbackSubtest * const		subtest = &test->subtests[ i ];
-		char						errorDesc[ 128 ];
-		
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, results, "{%@}", &resultDict );
-		require_noerr( err, exit );
-		
-		err = CFDictionarySetCString( resultDict, CFSTR( "name" ), subtest->hostname, kSizeCString );
-		require_noerr( err, exit );
-		
-		_NanoTime64ToTimestamp( subtest->startTime, startTime, sizeof( startTime ) );
-		err = CFDictionarySetCString( resultDict, CFSTR( "startTime" ), startTime, kSizeCString );
-		require_noerr( err, exit );
-		
-		_NanoTime64ToTimestamp( subtest->endTime, endTime, sizeof( endTime ) );
-		err = CFDictionarySetCString( resultDict, CFSTR( "endTime" ), endTime, kSizeCString );
-		require_noerr( err, exit );
-		
-		SNPrintF( errorDesc, sizeof( errorDesc ), "%m", subtest->error );
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, resultDict,
-			"%kO="
-			"{"
-				"%kO=%lli"	// code
-				"%kO=%s"	// description
-			"}",
-			CFSTR( "error" ),
-			CFSTR( "code" ),		(int64_t) subtest->error,
-			CFSTR( "description" ),	errorDesc );
-		require_noerr( err, exit );
-		
-		if( subtest->error ) subtestFailed = true;
-	}
-	if( !subtestFailed ) testPassed = true;
-	CFPropertyListAppendFormatted( kCFAllocatorDefault, plist, "%kO=%b", CFSTR( "pass" ), testPassed );
-	
-	err = OutputPropertyList( plist, outputFormat, gFallbackTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _FallbackTestFree( test );
-	CFReleaseNullSafe( plist );
-	gExitCode = err ? 1 : ( testPassed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static void		_FallbackTestStart( void *inContext );
-static void		_FallbackTestStop( FallbackTest *inTest, OSStatus inError );
-static void DNSSD_API
-	_FallbackTestProbeGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void		_FallbackTestProbeTimerHandler( void *inContext );
-static void DNSSD_API
-	_FallbackTestGetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void		_FallbackTestGAITimerHandler( void *inContext );
-static OSStatus	_FallbackTestStartSubtest( FallbackTest *inTest );
-static void		_FallbackTestForgetSources( FallbackTest *inTest );
-
-#define kFallbackTestProbeTimeLimitSecs		 5
-#define kFallbackTestGAITimeLimitSecs		75
-
-static OSStatus	_FallbackTestCreate( FallbackTest **outTest )
-{
-	OSStatus			err;
-	FallbackTest *		test;
-	
-	test = (FallbackTest *) calloc( 1, sizeof( *test ) );
-	require_action( test, exit, err = kNoMemoryErr );
-	
-	test->error		= kInProgressErr;
-	test->serverPID	= -1;
-	
-	test->queue = dispatch_queue_create( "com.apple.dnssdutil.fallback-test", DISPATCH_QUEUE_SERIAL );
-	require_action( test->queue, exit, err = kNoResourcesErr );
-	
-	test->doneSem = dispatch_semaphore_create( 0 );
-	require_action( test->doneSem, exit, err = kNoResourcesErr );
-	
-	*outTest = test;
-	test = NULL;
-	err = kNoErr;
-	
-exit:
-	if( test ) _FallbackTestFree( test );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_FallbackTestRun( FallbackTest *inTest )
-{
-	dispatch_async_f( inTest->queue, inTest, _FallbackTestStart );
-	dispatch_semaphore_wait( inTest->doneSem, DISPATCH_TIME_FOREVER );
-	return( inTest->error );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestFree( FallbackTest *inTest )
-{
-	size_t		i;
-	
-	check( !inTest->gai );
-	check( !inTest->timer );
-	check( inTest->serverPID < 0 );
-	
-	ForgetMem( &inTest->serverCmd );
-	ForgetMem( &inTest->probeHostname );
-	dispatch_forget( &inTest->queue );
-	dispatch_forget( &inTest->doneSem );
-	for( i = 0; i < kFallbackTestSubtestCount; ++i )
-	{
-		FallbackSubtest * const		subtest = &inTest->subtests[ i ];
-		
-		ForgetMem( &subtest->hostname );
-	}
-	free( inTest );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestStart( void *inContext )
-{
-	OSStatus					err;
-	FallbackTest * const		test = (FallbackTest *) inContext;
-	char						tag[ 6 + 1 ];
-	
-	test->startTime = NanoTimeGetCurrent();
-	
-	// The "dnssdutil server" command will create a resolver entry for the server's "d.test." domain containing an array
-	// of the server's IP addresses. Because configd favors IPv6 addresses, when there's a mix of IPv4 and IPv6
-	// addresses, configd may rearrange the array in order to ensure that IPv6 addresses come before the IPv4 addresses.
-	// To preserve the original address order, the server is specified to run in IPv6-only mode. This way,
-	// mDNSResponder's view of the address will be such that address with index value 1 is first, address with index
-	// value 2 is second, etc.
-	
-	ASPrintF( &test->serverCmd, "dnssdutil server --loopback --follow %lld --ipv6 --extraIPv6 3%s",
-		(int64_t) getpid(), test->useRefused ? " --useRefused" : "" );
-	require_action_quiet( test->serverCmd, exit, err = kUnknownErr );
-	
-	err = _SpawnCommand( &test->serverPID, "/dev/null", "/dev/null", "%s", test->serverCmd );
-	require_noerr( err, exit );
-	
-	ASPrintF( &test->probeHostname, "tag-fallback-test-probe-%s.count-1.ipv4.ttl-900.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( test->probeHostname, exit, err = kNoMemoryErr );
-	
-	ft_ulog( kLogLevelInfo, "Starting GetAddrInfo request for %s\n", test->probeHostname );
-	
-	err = DNSServiceGetAddrInfo( &test->gai, 0, kDNSServiceInterfaceIndexAny, kDNSServiceProtocol_IPv4,
-		test->probeHostname, _FallbackTestProbeGAICallback, test );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( test->gai, test->queue );
-	require_noerr( err, exit );
-	
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kFallbackTestProbeTimeLimitSecs ),
-		kFallbackTestProbeTimeLimitSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ), test->queue,
-		_FallbackTestProbeTimerHandler, test, &test->timer );
-	require_noerr( err, exit );
-	dispatch_resume( test->timer );
-	
-exit:
-	if( err ) _FallbackTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestStop( FallbackTest *inTest, OSStatus inError )
-{
-	inTest->error	= inError;
-	inTest->endTime	= NanoTimeGetCurrent();
-	_FallbackTestForgetSources( inTest );
-	if( inTest->serverPID >= 0 )
-	{
-		OSStatus		err;
-		
-		err = kill( inTest->serverPID, SIGTERM );
-		err = map_global_noerr_errno( err );
-		check_noerr( err );
-		inTest->serverPID = -1;
-	}
-	dispatch_semaphore_signal( inTest->doneSem );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_FallbackTestProbeGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus					err;
-	FallbackTest * const		test = (FallbackTest *) inContext;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inHostname );
-	Unused( inTTL );
-	
-	if( ( inFlags & kDNSServiceFlagsAdd ) && !inError )
-	{
-		_FallbackTestForgetSources( test );
-		
-		ft_ulog( kLogLevelInfo, "Probe: Got GAI address %##a for %s\n", inSockAddr, test->probeHostname );
-		
-		check( test->subtestIndex == 0 );
-		err = _FallbackTestStartSubtest( test );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) _FallbackTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestProbeTimerHandler( void *inContext )
-{
-	FallbackTest * const		test = (FallbackTest *) inContext;
-	
-	ft_ulog( kLogLevelInfo, "GetAddrInfo probe request for \"%s\" timed out.\n", test->probeHostname );
-	_FallbackTestStop( test, kNotPreparedErr );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_FallbackTestGetAddrInfoCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus					err;
-	struct sockaddr_in			sin;
-	FallbackTest * const		test		= (FallbackTest *) inContext;
-	FallbackSubtest *const		subtest		= &test->subtests[ test->subtestIndex ];
-	Boolean						complete	= false;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inTTL );
-	
-	_FallbackTestForgetSources( test );
-	
-	if( strcasecmp( inHostname, subtest->hostname ) != 0 )
-	{
-		ft_ulog( kLogLevelError, "GetAddrInfo(%s) result: Got unexpected hostname \"%s\".\n",
-			subtest->hostname, inHostname );
-		err = kUnexpectedErr;
-		goto done;
-	}
-	if( inError )
-	{
-		ft_ulog( kLogLevelError, "GetAddrInfo(%s) result: Got unexpected error %#m.\n", subtest->hostname, inError );
-		err = inError;
-		goto done;
-	}
-	if( ( inFlags & kDNSServiceFlagsAdd ) == 0 )
-	{
-		ft_ulog( kLogLevelError, "GetAddrInfo(%s) result: Missing Add flag.\n", subtest->hostname );
-		err = kUnexpectedErr;
-		goto done;
-	}
-	_SockAddrInitIPv4( &sin, kDNSServerBaseAddrV4 + 1, 0 );
-	if( SockAddrCompareAddr( inSockAddr, &sin ) != 0 )
-	{
-		ft_ulog( kLogLevelError, "GetAddrInfo(%s) result: Got unexpected address %##a (expected %##a).\n",
-			subtest->hostname, inSockAddr, &sin );
-		err = kUnexpectedErr;
-		goto done;
-	}
-	ft_ulog( kLogLevelInfo, "Subtest %zu/%d: Got expected GAI address %##a for %s\n",
-		test->subtestIndex + 1, kFallbackTestSubtestCount, inSockAddr, subtest->hostname );
-	err = kNoErr;
-	
-done:
-	subtest->endTime	= NanoTimeGetCurrent();
-	subtest->error		= err;
-	err = kNoErr;
-	if( ++test->subtestIndex < kFallbackTestSubtestCount )
-	{
-		err = _FallbackTestStartSubtest( test );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		complete = true;
-	}
-	
-exit:
-	if( err || complete ) _FallbackTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestGAITimerHandler( void *inContext )
-{
-	OSStatus					err;
-	FallbackTest * const		test		= (FallbackTest *) inContext;
-	FallbackSubtest * const		subtest		= &test->subtests[ test->subtestIndex ];
-	Boolean						complete	= false;
-	
-	_FallbackTestForgetSources( test );
-	
-	ft_ulog( kLogLevelInfo, "GetAddrInfo request for \"%s\" timed out.\n", subtest->hostname );
-	
-	subtest->endTime	= NanoTimeGetCurrent();
-	subtest->error		= kTimeoutErr;
-	if( ++test->subtestIndex < kFallbackTestSubtestCount )
-	{
-		err = _FallbackTestStartSubtest( test );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		complete = true;
-		err = kNoErr;
-	}
-	
-exit:
-	if( err || complete ) _FallbackTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_FallbackTestStartSubtest( FallbackTest *inTest )
-{
-	OSStatus					err;
-	FallbackSubtest * const		subtest = &inTest->subtests[ inTest->subtestIndex ];
-	char						tag[ 6 + 1 ];
-	
-	subtest->error		= kInProgressErr;
-	subtest->startTime	= NanoTimeGetCurrent();
-	
-	ForgetMem( &subtest->hostname );
-	ASPrintF( &subtest->hostname, "index-%u.tag-fallback-test-%s.count-1.ipv4.ttl-900.d.test.",
-		kFallbackSubtestParams[ inTest->subtestIndex ].serverIndex,
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( subtest->hostname, exit, err = kNoMemoryErr );
-	
-	ft_ulog( kLogLevelInfo, "Starting GetAddrInfo request for %s\n", subtest->hostname );
-	
-	check( !inTest->gai );
-	err = DNSServiceGetAddrInfo( &inTest->gai, 0, kDNSServiceInterfaceIndexAny, kDNSServiceProtocol_IPv4,
-		subtest->hostname, _FallbackTestGetAddrInfoCallback, inTest );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( inTest->gai, inTest->queue );
-	require_noerr( err, exit );
-	
-	check( !inTest->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kFallbackTestGAITimeLimitSecs ),
-		kFallbackTestGAITimeLimitSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ), inTest->queue,
-		_FallbackTestGAITimerHandler, inTest, &inTest->timer );
-	require_noerr( err, exit );
-	dispatch_resume( inTest->timer );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_FallbackTestForgetSources( FallbackTest *inTest )
-{
-	DNSServiceForget( &inTest->gai );
-	dispatch_source_forget( &inTest->timer );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedsTestCmd
-//===========================================================================================================================
-
-#define NOTIFICATION_TIME_THRESHOLD 1500    // The maximum wating time allowed before notification happens
-#define TEST_REPETITION             2       // the number of repetition that one test has to passed
-#define LOOPBACK_INTERFACE_NAME     "lo0"
-#define WIFI_TEST_QUESTION_NAME     "www.example.com"
-#define EXPENSIVE_CONSTRAINED_MAX_RETRIES 1
-#define EXPENSIVE_CONSTRAINED_TEST_INTERVAL 5
-// Use "-n tag-expensive-test.ttl-86400.d.test." to run the test locally
-// #define LOOPBACK_TEST_QUESTION_NAME "tag-expensive-test.ttl-86400.d.test."
-
-#define EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_START_TIME                CFSTR( "Start Time" )
-#define EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_END_TIME                  CFSTR( "End Time" )
-#define EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_ALL_PASSED                CFSTR( "All Tests Passed" )
-#define EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_SUBTEST_RESULT            CFSTR( "Subtest Results" )
-
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_START_TIME             CFSTR( "Start Time" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_END_TIME               CFSTR( "End Time" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_QNAME                  CFSTR( "Question Name" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_FLAGS                  CFSTR( "DNS Service Flags" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_PROTOCOLS              CFSTR( "Protocols" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_INDEX        CFSTR( "Interface Index" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_NAME         CFSTR( "Interface Name" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_RESULT                 CFSTR( "Result" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_ERROR                  CFSTR( "Error Description" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_TEST_PROGRESS          CFSTR( "Test Progress" )
-
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_START_TIME           CFSTR( "Start Time" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_END_TIME             CFSTR( "End Time" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_STATE                CFSTR( "State" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_EXPECT_RESULT        CFSTR( "Expected Result" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_ACTUAL_RESULT        CFSTR( "Actual Result" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_EXPENSIVE_PREV_NOW   CFSTR( "Expensive Prev->Now" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_CONSTRAINED_PREV_NOW CFSTR( "Constrained Prev->Now" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_CALL_BACK            CFSTR( "Call Back" )
-
-#define EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_TIMESTAMP       CFSTR( "Timestamp" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_NAME            CFSTR( "Answer Name" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_FLAGS           CFSTR( "Add or Remove" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_INTERFACE       CFSTR( "Interface Index" )
-#define EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_ADDRESS         CFSTR( "Address" )
-
-// All the states that ends with _PREPARE represents the state where the test state is reset and initialized.
-enum ExpensiveConstrainedTestState
-{
-    TEST_BEGIN,
-    TEST_EXPENSIVE_PREPARE,
-    TEST_EXPENSIVE,                     // Test if mDNSResponder can handle "expensive" status change of the corresponding interface
-    TEST_CONSTRAINED_PREPARE,
-    TEST_CONSTRAINED,                   // Test if mDNSResponder can handle "constrained" status change of the corresponding interface
-    TEST_EXPENSIVE_CONSTRAINED_PREPARE,
-    TEST_EXPENSIVE_CONSTRAINED,          // Test if mDNSResponder can handle "expensive" and "constrained" status change of the corresponding interface at the same time
-    TEST_FAILED,
-    TEST_SUCCEEDED
-};
-enum ExpensiveConstrainedTestOperation
-{
-    RESULT_ADD, // received response for the given query, which means mDNSResponder is able to send out the query over the interface, because the interface status is changed.
-    RESULT_RMV, // received negative response for the given query, which means mDNSResponder is not able to send out the query over the interface, because the interface status is changed.
-    NO_UPDATE   // no status update notification
-};
-
-typedef struct
-{
-    uint32_t                    subtestIndex;           // The index of parameter for the subtest
-    DNSServiceRef               opRef;                  // sdRef for the DNSServiceGetAddrInfo operation.
-    const char *                name;                   // Hostname to resolve.
-    DNSServiceFlags             flags;                  // Flags argument for DNSServiceGetAddrInfo().
-    DNSServiceProtocol          protocols;              // Protocols argument for DNSServiceGetAddrInfo().
-    uint32_t                    ifIndex;                // Interface index argument for DNSServiceGetAddrInfo().
-    char                        ifName[IFNAMSIZ];       // Interface name for the given interface index.
-    dispatch_source_t           timer;                  // The test will check if the current behavior is valid, which is called by
-                                                        // the timer per 2s.
-    pid_t                       serverPID;
-    Boolean                     isExpensivePrev;        // If the interface is expensive in the previous test step.
-    Boolean                     isExpensiveNow;         // If the interface is expensive now.
-    Boolean                     isConstrainedPrev;      // If the interface is constrained in the previous test step.
-    Boolean                     isConstrainedNow;       // If the interface is constrained now.
-    Boolean                     startFromExpensive;     // All the test will start from expensive/constrained interface, so there won's be an answer until the interface is changed.
-    uint8_t                     numOfRetries;           // the number of retries we can have if the test fail
-    struct timeval              updateTime;             // The time when interface status(expensive or constrained) is changed.
-    struct timeval              notificationTime;       // The time when callback function, which is passed to DNSServiceGetAddrInfo, gets called.
-    uint32_t                    counter;                // To record how many times the test has repeated.
-    enum ExpensiveConstrainedTestState          state;              // The current test state.
-    enum ExpensiveConstrainedTestOperation      expectedOperation;  // the test expects this kind of notification
-    enum ExpensiveConstrainedTestOperation      operation;          // represents what notification the callback function gets.
-
-    NanoTime64                  testReport_startTime;       // when the entire test starts
-    CFMutableArrayRef           subtestReport;              // stores the log message for every subtest
-    NanoTime64                  subtestReport_startTime;    // when the subtest starts
-    CFMutableArrayRef           subtestProgress;            // one test iteration
-    NanoTime64                  subtestProgress_startTime;  // when the test iteration starts
-    CFMutableArrayRef           subtestProgress_callBack;   // array of ADD/REMOVE events
-    char *                      outputFilePath;             // File to write test results to. If NULL, then write to stdout. (malloced)
-    OutputFormatType            outputFormat;               // Format of test report output.
-} ExpensiveConstrainedContext;
-
-// structure that controls how the subtest is run
-typedef struct
-{
-    const char  *qname;                 // the name of the query, when the ends with ".d.test.", test will send query to local DNS server
-    Boolean     deny_expensive;         // if the query should avoid using expensive interface
-    Boolean     deny_constrained;       // if the query should avoid using constrained interface
-    Boolean     start_from_expensive;   // if the query should starts from using an expensive interface
-    Boolean     ipv4_query;             // only allow IPv4 query
-    Boolean     ipv6_query;             // only allow IPv6 query
-    int8_t      test_passed;            // if the subtest passes
-} ExpensiveConstrainedTestParams;
-
-static ExpensiveConstrainedTestParams   ExpensiveConstrainedSubtestParams[] =
-{
-//  qname                                                   deny_expensive  deny_constrained    start_from_expensive    ipv4_query  ipv6_query
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              false,                  true,       true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              true,                   true,       true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               false,                  true,       true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               true,                   true,       true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               false,                  true,       true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               true,                   true,       true,       -1},
-// IPv4 Only
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              false,                  true,       false,      -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              true,                   true,       false,      -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               false,                  true,       false,      -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               true,                   true,       false,      -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               false,                  true,       false,      -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               true,                   true,       false,      -1},
-// IPv6 Only
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              false,                  false,      true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           false,              true,                   false,      true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               false,                  false,      true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    false,          true,               true,                   false,      true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               false,                  false,      true,       -1},
-    {"tag-expensive_constrained-test.ttl-86400.d.test.",    true,           true,               true,                   false,      true,       -1}
-};
-
-static void ExpensiveConstrainedSetupLocalDNSServer( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedStartTestHandler( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedStopTestHandler( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedSetupTimer( ExpensiveConstrainedContext *context, uint32_t second );
-static void ExpensiveConstrainedTestTimerEventHandler( ExpensiveConstrainedContext *context );
-static void DNSSD_API
-    ExpensiveConstrainedCallback(
-        DNSServiceRef           inSDRef,
-        DNSServiceFlags         inFlags,
-        uint32_t                inInterfaceIndex,
-        DNSServiceErrorType     inError,
-        const char *            inHostname,
-        const struct sockaddr * inSockAddr,
-        uint32_t                inTTL,
-        void *                  inContext );
-static void ExpensiveConstrainedInitializeContext( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedStopAndCleanTheTest( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedSubtestProgressReport( ExpensiveConstrainedContext *context );
-static void ExpensiveConstrainedSubtestReport( ExpensiveConstrainedContext *context, const char *error_description );
-static void ExpensiveConstrainedFinalResultReport( ExpensiveConstrainedContext *context, Boolean allPassed );
-static const char *ExpensiveConstrainedProtocolString(DNSServiceProtocol protocol);
-static const char *ExpensiveConstrainedStateString(enum ExpensiveConstrainedTestState state);
-static const char *ExpensiveConstrainedOperationString(enum ExpensiveConstrainedTestOperation operation);
-static Boolean expensiveConstrainedEndsWith( const char *str, const char *suffix );
-
-//===========================================================================================================================
-//    ExpensiveConstrainedTestCmd
-//===========================================================================================================================
-
-static void ExpensiveConstrainedTestCmd( void )
-{
-    OSStatus                        err;
-    dispatch_source_t               signalSource   = NULL;
-    ExpensiveConstrainedContext *   context        = NULL;
-
-    // Set up SIGINT handler.
-    signal( SIGINT, SIG_IGN );
-    err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-    require_noerr( err, exit );
-    dispatch_resume( signalSource );
-
-    // create the test context
-    context = (ExpensiveConstrainedContext *) calloc( 1, sizeof(*context) );
-    require_action( context, exit, err = kNoMemoryErr );
-
-    // get the command line option
-    err = OutputFormatFromArgString( gExpensiveConstrainedTest_OutputFormat, &context->outputFormat );
-    require_noerr_quiet( err, exit );
-    if ( gExpensiveConstrainedTest_OutputFilePath )
-    {
-        context->outputFilePath = strdup( gExpensiveConstrainedTest_OutputFilePath );
-        require_noerr_quiet( context->outputFilePath, exit );
-    }
-
-    // initialize context
-    context->subtestIndex = 0;
-    context->numOfRetries = EXPENSIVE_CONSTRAINED_MAX_RETRIES;
-
-    // initialize the CFArray used to store the log
-    context->subtestReport = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-    context->testReport_startTime = NanoTimeGetCurrent();
-
-    // setup local DNS server
-    ExpensiveConstrainedSetupLocalDNSServer( context );
-
-    ExpensiveConstrainedStartTestHandler( context );
-
-    dispatch_main();
-
-exit:
-    exit( 1 );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedSetupLocalDNSServer
-//===========================================================================================================================
-
-static void ExpensiveConstrainedSetupLocalDNSServer( ExpensiveConstrainedContext *context )
-{
-    pid_t current_pid = getpid();
-    OSStatus err = _SpawnCommand( &context->serverPID, NULL, NULL, "dnssdutil server -l --port 0 --follow %d", current_pid );
-    if (err != 0)
-    {
-        FPrintF( stdout, "dnssdutil server -l --port 0 --follow <PID> failed, error: %d\n", err );
-        exit( 1 );
-    }
-    sleep(2);
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedStartTestHandler
-//===========================================================================================================================
-
-static void ExpensiveConstrainedStartTestHandler( ExpensiveConstrainedContext *context )
-{
-    // setup 3s timer
-    ExpensiveConstrainedSetupTimer( context, EXPENSIVE_CONSTRAINED_TEST_INTERVAL );
-
-    // set the event handler for the 3s timer
-    dispatch_source_set_event_handler( context->timer, ^{
-        ExpensiveConstrainedTestTimerEventHandler( context );
-    } );
-
-    dispatch_resume( context->timer );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedStartTestHandler
-//===========================================================================================================================
-
-static void ExpensiveConstrainedStopTestHandler( ExpensiveConstrainedContext *context )
-{
-    dispatch_cancel( context->timer );
-    dispatch_release( context->timer );
-    context->timer = NULL;
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedSetupTimer
-//===========================================================================================================================
-
-static void ExpensiveConstrainedSetupTimer( ExpensiveConstrainedContext *context, uint32_t second )
-{
-    // set the timer source, the event handler will be called for every "second" seconds
-    context->timer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue() );
-    if ( context->timer == NULL )
-    {
-        FPrintF( stdout, "dispatch_source_create:DISPATCH_SOURCE_TYPE_TIMER failed\n" );
-        exit( 1 );
-    }
-    // the first block will be put into the queue "second"s after calling dispatch_resume
-    dispatch_source_set_timer( context->timer, dispatch_time( DISPATCH_TIME_NOW, second * NSEC_PER_SEC ),
-                               (unsigned long long)(second) * NSEC_PER_SEC, 100ull * NSEC_PER_MSEC );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedTestTimerEventHandler
-//===========================================================================================================================
-
-static void ExpensiveConstrainedTestTimerEventHandler( ExpensiveConstrainedContext *context )
-{
-    OSStatus    err;
-    char        buffer[ 1024 ];
-    const char *errorDescription = NULL;
-
-    // do not log the state if we are in transition state
-    if (context->state != TEST_BEGIN
-        && context->state != TEST_SUCCEEDED
-        && context->state != TEST_CONSTRAINED_PREPARE
-        && context->state != TEST_EXPENSIVE_CONSTRAINED_PREPARE)
-        ExpensiveConstrainedSubtestProgressReport( context );
-
-    switch ( context->state ) {
-        case TEST_BEGIN:
-        {
-            ExpensiveConstrainedStopTestHandler( context );
-
-            // clear mDNSResponder cache
-            err = systemf( NULL, "killall -HUP mDNSResponder" );
-            require_noerr_action( err, test_failed, errorDescription = "systemf failed");
-
-            // initialize the global parameters
-            ExpensiveConstrainedInitializeContext( context );
-
-            // The local DNS server is set up on the local only interface.
-            gExpensiveConstrainedTest_Interface = LOOPBACK_INTERFACE_NAME;
-            strncpy( context->ifName, gExpensiveConstrainedTest_Interface, sizeof( context->ifName ) );
-
-            // The local DNS server is unscoped, so we must set our question to unscoped.
-            context->ifIndex = kDNSServiceInterfaceIndexAny;
-
-            // The question name must end with "d.test.", "tag-expensive-test.ttl-86400.d.test." for example, then the test will
-            // use the local dns server set up previously to run the test locally.
-            require_action( gExpensiveConstrainedTest_Name != NULL && expensiveConstrainedEndsWith( gExpensiveConstrainedTest_Name, "d.test." ), test_failed,
-                           SNPrintF( buffer, sizeof( buffer ), "The question name (%s) must end with \"d.test.\".\n", gExpensiveConstrainedTest_Name );
-                           errorDescription = buffer );
-
-            // get the quesion name
-            context->name = gExpensiveConstrainedTest_Name;
-
-            // set the initial state for the interface
-            context->startFromExpensive = gExpensiveConstrainedTest_StartFromExpensive;
-            err = systemf( NULL, "ifconfig %s %sexpensive && ifconfig %s -constrained", context->ifName, context->startFromExpensive ? "" : "-", context->ifName );
-            require_noerr_action( err, test_failed, errorDescription = "systemf failed");
-            sleep( 5 ); // wait for 5s to allow the interface change event de delivered to others
-
-            // get question flag
-            if ( gExpensiveConstrainedTest_DenyExpensive )    context->flags     |= kDNSServiceFlagsDenyExpensive;
-            if ( gExpensiveConstrainedTest_DenyConstrained )  context->flags     |= kDNSServiceFlagsDenyConstrained;
-            if ( gExpensiveConstrainedTest_ProtocolIPv4 )     context->protocols |= kDNSServiceProtocol_IPv4;
-            if ( gExpensiveConstrainedTest_ProtocolIPv6 )     context->protocols |= kDNSServiceProtocol_IPv6;
-
-            // prevent mDNSResponder from doing extra path evaluation and changing the interface to others(such as Bluetooth)
-            #if( TARGET_OS_WATCH )
-            context->flags |= kDNSServiceFlagsPathEvaluationDone;
-            #endif
-
-            // start the query
-            DNSServiceGetAddrInfo( &context->opRef, context->flags, context->ifIndex, context->protocols, context->name, ExpensiveConstrainedCallback, context );
-
-            // set the initial test status
-            context->subtestReport_startTime    = NanoTimeGetCurrent();
-            context->subtestProgress_startTime  = NanoTimeGetCurrent();
-            context->state                      = TEST_EXPENSIVE_PREPARE; // start from expensive test
-            context->isExpensiveNow             = context->startFromExpensive ? true : false;
-            context->isConstrainedNow           = false;
-            context->expectedOperation          = context->isExpensiveNow && ( context->flags & kDNSServiceFlagsDenyExpensive ) ? NO_UPDATE : RESULT_ADD;
-            context->operation                  = NO_UPDATE;
-            context->subtestProgress            = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks);
-            require_action( context->subtestProgress != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-            context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks);
-            require_action( context->subtestProgress != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-            // set the queue where the callback will be called when there is an answer for the query
-            err = DNSServiceSetDispatchQueue( context->opRef, dispatch_get_main_queue() );
-            require_noerr( err, test_failed );
-
-            ExpensiveConstrainedStartTestHandler( context );
-        }
-            break;
-        case TEST_EXPENSIVE_PREPARE:
-            require_action( context->isConstrainedNow == false, test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "Interface %s should be unconstrained.\n", context->ifName );
-                            errorDescription = buffer );
-            require_action( context->expectedOperation == context->operation, test_failed,
-                            errorDescription = "Operation is not expected" );
-
-            context->subtestProgress_startTime  = NanoTimeGetCurrent();
-            context->state                      = TEST_EXPENSIVE;   // begin to test expensive flag
-            context->counter                    = 0;                // the number of test repetition that has passed
-            context->isExpensivePrev            = context->isExpensiveNow;
-            context->isExpensiveNow             = !context->isExpensiveNow; // flip the expensive status
-            context->isConstrainedPrev          = false;            // the interface is currently unconstrained
-            context->isConstrainedNow           = false;            // the interface will be unconstrained in the current test
-            if ( gExpensiveConstrainedTest_DenyExpensive )
-                context->expectedOperation      = context->isExpensiveNow ? RESULT_RMV : RESULT_ADD;
-            else
-                context->expectedOperation      = NO_UPDATE;
-            context->operation                  = NO_UPDATE;        // NO_UPDATE means the call back function has not been called
-            context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-            require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-            err = systemf( NULL, "ifconfig %s %sexpensive", context->ifName, context->isExpensiveNow ? "" : "-" );
-            require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-            // record the starting timestamp
-            gettimeofday( &context->updateTime, NULL );
-
-            break;
-        case TEST_EXPENSIVE:
-            // Since we are testing expensive flag, we should always turn the expensive flag on and off.
-            require_action( context->isExpensivePrev ^ context->isExpensiveNow, test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "The current expensive status should be different with the previous one: %d -> %d\n", context->isExpensivePrev, context->isExpensiveNow);
-                            errorDescription = buffer );
-            // constrained flag is always turned off when testing expensive
-            require_action( context->isConstrainedNow == false, test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "The interface %s should be unconstrained when testing \"expensive\"\n", context->ifName );
-                            errorDescription = buffer );
-            require_action( context->expectedOperation == context->operation, test_failed, errorDescription = "Operation is not expected" );
-
-            context->counter++; // one test repetition has passed
-            if ( context->counter == TEST_REPETITION ) // expensive test finished
-            {
-                // prepare to test constrained flag
-                context->state = TEST_CONSTRAINED_PREPARE;
-
-                // reset the interface
-                err = systemf( NULL, "ifconfig %s -expensive && ifconfig %s -constrained", context->ifName, context->ifName );
-                require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-                context->isExpensiveNow = false;
-                context->isConstrainedNow = false;
-                gettimeofday( &context->updateTime, NULL );
-            }
-            else
-            {
-                context->subtestProgress_startTime  = NanoTimeGetCurrent();
-                context->isExpensivePrev            = context->isExpensiveNow;
-                context->isExpensiveNow             = !context->isExpensiveNow; // flip the expensive status
-                if ( gExpensiveConstrainedTest_DenyExpensive )
-                    context->expectedOperation      = context->isExpensiveNow ? RESULT_RMV : RESULT_ADD;
-                else
-                    context->expectedOperation      = NO_UPDATE;
-                context->operation                  = NO_UPDATE;
-                context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-                require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-                err = systemf( NULL, "ifconfig %s %sexpensive", context->ifName, context->isExpensiveNow ? "" : "-" );
-                require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-                gettimeofday( &context->updateTime, NULL );
-            }
-            break;
-        case TEST_CONSTRAINED_PREPARE:
-            // The interface should be inexpensive and unconstrained when the constrained test starts
-            require_action( context->isExpensiveNow == false, test_failed, SNPrintF( buffer, sizeof( buffer ), "Interface %s should be inexpensive.", context->ifName );
-                            errorDescription = buffer );
-            require_action( context->isConstrainedNow == false, test_failed, SNPrintF( buffer, sizeof( buffer ), "Interface %s should be unconstrained.\n", context->ifName );
-                            errorDescription = buffer );
-
-            context->subtestProgress_startTime  = NanoTimeGetCurrent();
-            context->state                      = TEST_CONSTRAINED; // constrained interface is now under testing
-            context->counter                    = 0;
-            context->isExpensivePrev            = false;
-            context->isExpensiveNow             = false;
-            context->isConstrainedPrev          = false;
-            context->isConstrainedNow           = true;             // will set constrained flag on the interface
-            if ( gExpensiveConstrainedTest_DenyConstrained )
-                context->expectedOperation      = RESULT_RMV;
-            else
-                context->expectedOperation      = NO_UPDATE;
-            context->operation                  = NO_UPDATE;
-            context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-            require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-            // change interface to the constrained one
-            err = systemf( NULL, "ifconfig %s -expensive && ifconfig %s constrained", context->ifName, context->ifName );
-            require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-            gettimeofday( &context->updateTime, NULL );
-            break;
-        case TEST_CONSTRAINED:
-            // Since we are testing constrained flag, we should always turn the constrained flag on and off.
-            require_action( context->isConstrainedPrev ^ context->isConstrainedNow, test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "The current constrained status should be different with the previous one: %d -> %d\n", context->isConstrainedPrev, context->isConstrainedNow );
-                            errorDescription = buffer );
-            require_action( context->isExpensiveNow == false, test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "The interface %s should be inexpensive when testing \"constrained\"\n", context->ifName );
-                            errorDescription = buffer );
-            require_action( context->expectedOperation == context->operation, test_failed, errorDescription = "Operation is not expected");
-
-            context->counter++;
-            if (context->counter == TEST_REPETITION)
-            {
-                // test changing expensive and constrained flags at the same time
-                context->state = TEST_EXPENSIVE_CONSTRAINED_PREPARE;
-
-                // reset interface
-                err = systemf( NULL, "ifconfig %s -expensive && ifconfig %s -constrained", context->ifName, context->ifName );
-                require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-                context->isExpensiveNow = false;
-                context->isConstrainedNow = false;
-                gettimeofday( &context->updateTime, NULL );
-            }
-            else
-            {
-                context->subtestProgress_startTime  = NanoTimeGetCurrent();
-                context->isConstrainedPrev          = context->isConstrainedNow;
-                context->isConstrainedNow           = !context->isConstrainedNow; // flip constrained flag
-                if ( gExpensiveConstrainedTest_DenyConstrained )
-                    context->expectedOperation      = context->isConstrainedNow ? RESULT_RMV : RESULT_ADD;
-                else
-                    context->expectedOperation      = NO_UPDATE;
-                context->operation                  = NO_UPDATE;
-                context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-                require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-                err = systemf( NULL, "ifconfig %s %sconstrained", context->ifName, context->isConstrainedNow ? "" : "-" );
-                require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-                gettimeofday(&context->updateTime, NULL);
-            }
-            break;
-        case TEST_EXPENSIVE_CONSTRAINED_PREPARE:
-            // The interface should be inexpensive and unconstrained when the constrained test starts
-            require_action( context->isExpensiveNow == false,   test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "Interface %s should be inexpensive.\n", context->ifName );
-                            errorDescription = buffer );
-            require_action( context->isConstrainedNow == false, test_failed,
-                            SNPrintF(buffer, sizeof( buffer ), "Interface %s should be unconstrained.\n", context->ifName );
-                            errorDescription = buffer );
-
-            // now flip expensive and constrained at the same time
-            context->subtestProgress_startTime  = NanoTimeGetCurrent();
-            context->state                      = TEST_EXPENSIVE_CONSTRAINED;
-            context->counter                    = 0;
-            context->isExpensivePrev            = false;
-            context->isExpensiveNow             = true;
-            context->isConstrainedPrev          = false;
-            context->isConstrainedNow           = true;
-            if (gExpensiveConstrainedTest_DenyConstrained || gExpensiveConstrainedTest_DenyExpensive)
-                context->expectedOperation      = RESULT_RMV;
-            else
-                context->expectedOperation      = NO_UPDATE;
-            context->operation                  = NO_UPDATE;
-            context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-            require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-            err = systemf(NULL, "ifconfig %s expensive && ifconfig %s constrained", context->ifName, context->ifName );
-            require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-            gettimeofday( &context->updateTime, NULL );
-            break;
-        case TEST_EXPENSIVE_CONSTRAINED:
-            // expensive and constrained flag should always be changed
-            require_action( ( context->isExpensivePrev ^ context->isExpensiveNow ) && ( context->isConstrainedPrev ^ context->isConstrainedNow ), test_failed,
-                            SNPrintF( buffer, sizeof( buffer ), "Both expensive and constrained status need to be changed" );
-                            errorDescription = buffer );
-            require_action( context->isExpensiveNow == context->isConstrainedNow, test_failed, errorDescription = "context->isExpensiveNow != context->isConstrainedNow" );
-            require_action( context->expectedOperation == context->operation, test_failed, errorDescription = "Operation is not expected" );
-
-            context->counter++;
-            if ( context->counter == TEST_REPETITION )
-            {
-                context->state = TEST_SUCCEEDED;
-            }
-            else
-            {
-                context->subtestProgress_startTime  = NanoTimeGetCurrent();
-                context->isExpensivePrev            = context->isExpensiveNow;
-                context->isExpensiveNow             = !context->isExpensiveNow;
-                context->isConstrainedPrev          = context->isConstrainedNow;
-                context->isConstrainedNow           = !context->isConstrainedNow;
-                if (gExpensiveConstrainedTest_DenyConstrained || gExpensiveConstrainedTest_DenyExpensive)
-                    context->expectedOperation      = context->isExpensiveNow ? RESULT_RMV : RESULT_ADD;
-                else
-                    context->expectedOperation      = NO_UPDATE;
-                context->operation                  = NO_UPDATE;
-                context->subtestProgress_callBack   = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-                require_action( context->subtestProgress_callBack != NULL, test_failed, errorDescription = "CFArrayCreateMutable failed" );
-
-                err = systemf( NULL, "ifconfig %s %sexpensive && ifconfig %s %sconstrained", context->ifName, context->isExpensiveNow ? "" : "-", context->ifName, context->isConstrainedNow ? "" : "-" );
-                require_noerr_action( err, test_failed, errorDescription = "systemf failed" );
-
-                gettimeofday( &context->updateTime, NULL );
-            }
-            break;
-        case TEST_FAILED:
-        test_failed:
-            ExpensiveConstrainedSubtestReport( context, errorDescription );
-            ExpensiveConstrainedStopAndCleanTheTest( context );
-            if ( context->numOfRetries > 0 )
-            {
-                context->state = TEST_BEGIN;
-                context->numOfRetries--;
-                break;
-            }
-            ExpensiveConstrainedSubtestParams[context->subtestIndex++].test_passed = 0;
-            if (context->subtestIndex == (int) countof( ExpensiveConstrainedSubtestParams ))
-            {
-                ExpensiveConstrainedFinalResultReport( context, false );
-                exit( 2 );
-            }
-            if (context->timer == NULL)
-            {
-                // If timer is NULL, it means that we encounter error before we set up the test handler, which is unrecoverable.
-                ExpensiveConstrainedFinalResultReport( context, false );
-                exit( 1 );
-            }
-            context->state = TEST_BEGIN;
-            break;
-        case TEST_SUCCEEDED:
-            ExpensiveConstrainedSubtestReport( context, NULL );
-            ExpensiveConstrainedStopAndCleanTheTest( context );
-            ExpensiveConstrainedSubtestParams[context->subtestIndex++].test_passed = 1;
-            if (context->subtestIndex == (int) countof( ExpensiveConstrainedSubtestParams ))
-            {
-                // all the subtests have been run
-                Boolean hasFailed = false;
-                for ( int i = 0; i < (int) countof( ExpensiveConstrainedSubtestParams ) && !hasFailed; i++ )
-                    hasFailed = ( ExpensiveConstrainedSubtestParams[i].test_passed != 1 );
-
-                ExpensiveConstrainedFinalResultReport( context, !hasFailed );
-                exit( hasFailed ? 2 : 0 );
-            }
-            context->state = TEST_BEGIN;
-            break;
-        default:
-            FPrintF( stdout, "unknown error\n" );
-            exit( 1 );
-    }
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-    ExpensiveConstrainedCallback(
-        __unused DNSServiceRef  inSDRef,
-        DNSServiceFlags         inFlags,
-        uint32_t                inInterfaceIndex,
-        DNSServiceErrorType     inError,
-        const char *            inHostname,
-        const struct sockaddr * inSockAddr,
-        __unused uint32_t       inTTL,
-        void *                  inContext )
-{
-    ExpensiveConstrainedContext * const   context = (ExpensiveConstrainedContext *)inContext;
-    OSStatus                                    err;
-    const char *                                addrStr;
-    char                                        addrStrBuf[ kSockAddrStringMaxSize ];
-    char                                        inFlagsDescription[ 128 ];
-    NanoTime64                                  now;
-    char                                        nowTimestamp[ 32 ];
-
-    switch ( inError ) {
-        case kDNSServiceErr_NoError:
-        case kDNSServiceErr_NoSuchRecord:
-            break;
-
-        case kDNSServiceErr_Timeout:
-            Exit( kExitReason_Timeout );
-
-        default:
-            err = inError;
-            goto exit;
-    }
-
-    if( ( inSockAddr->sa_family != AF_INET ) && ( inSockAddr->sa_family != AF_INET6 ) )
-    {
-        dlogassert( "Unexpected address family: %d", inSockAddr->sa_family );
-        err = kTypeErr;
-        goto exit;
-    }
-
-    if( !inError )
-    {
-        err = SockAddrToString( inSockAddr, kSockAddrStringFlagsNone, addrStrBuf );
-        require_noerr( err, exit );
-        addrStr = addrStrBuf;
-    }
-    else
-    {
-        addrStr = ( inSockAddr->sa_family == AF_INET ) ? kNoSuchRecordAStr : kNoSuchRecordAAAAStr;
-    }
-
-    now = NanoTimeGetCurrent();
-    _NanoTime64ToTimestamp( now, nowTimestamp, sizeof( nowTimestamp ) );
-    SNPrintF( inFlagsDescription, sizeof( inFlagsDescription ), "%{du:cbflags}", inFlags );
-    err = CFPropertyListAppendFormatted( kCFAllocatorDefault,  context->subtestProgress_callBack,
-        "{"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%lli"
-            "%kO=%s"
-        "}",
-        EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_TIMESTAMP,  nowTimestamp,
-        EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_NAME,       inHostname,
-        EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_FLAGS,      inFlagsDescription,
-        EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_INTERFACE,  (int64_t) inInterfaceIndex,
-        EXPENSIVE_CONSTRAINED_SUBTEST_ACTUAL_RESULT_KEY_ADDRESS,    addrStr
-    );
-    require_noerr_quiet( err, exit );
-
-    if ( inFlags & kDNSServiceFlagsMoreComing )
-        return;
-
-    if ( inFlags & kDNSServiceFlagsAdd )
-        context->operation = RESULT_ADD;
-    else
-        context->operation = RESULT_RMV;
-
-    gettimeofday(&context->notificationTime, NULL);
-exit:
-    if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedInitializeContext
-//===========================================================================================================================
-
-static void ExpensiveConstrainedInitializeContext( ExpensiveConstrainedContext *context )
-{
-    // clear the flags of the previous subtest
-    context->flags      = 0;
-    context->protocols  = 0;
-
-    // get the parameter for the current subtest
-    const ExpensiveConstrainedTestParams *param     = &ExpensiveConstrainedSubtestParams[context->subtestIndex];
-    gExpensiveConstrainedTest_Name                  = param->qname;
-    gExpensiveConstrainedTest_DenyExpensive         = param->deny_expensive;
-    gExpensiveConstrainedTest_DenyConstrained       = param->deny_constrained;
-    gExpensiveConstrainedTest_StartFromExpensive    = param->start_from_expensive;
-    gExpensiveConstrainedTest_ProtocolIPv4          = param->ipv4_query;
-    gExpensiveConstrainedTest_ProtocolIPv6          = param->ipv6_query;
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedStopAndCleanTheTest
-//===========================================================================================================================
-
-static void ExpensiveConstrainedStopAndCleanTheTest( ExpensiveConstrainedContext *context )
-{
-    // Stop the ongoing query
-    if ( context->opRef != NULL )
-        DNSServiceRefDeallocate( context->opRef );
-
-    context->opRef      = NULL;
-    context->flags      = 0;
-    context->protocols  = 0;
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedSubtestProgressReport
-//===========================================================================================================================
-
-static void ExpensiveConstrainedSubtestProgressReport( ExpensiveConstrainedContext *context )
-{
-    OSStatus            err;
-    NanoTime64          now;
-    char                startTime[ 32 ];
-    char                endTime[ 32 ];
-    char                expensive[ 32 ];
-    char                constrained[ 32 ];
-
-    now = NanoTimeGetCurrent();
-    _NanoTime64ToTimestamp( context->subtestProgress_startTime, startTime, sizeof( startTime ) );
-    _NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-
-    snprintf( expensive, sizeof( expensive ), "%s -> %s", context->isExpensivePrev ? "True" : "False", context->isExpensiveNow ? "True" : "False" );
-    snprintf( constrained, sizeof( constrained ), "%s -> %s", context->isConstrainedPrev ? "True" : "False", context->isConstrainedNow ? "True" : "False" );
-
-    err = CFPropertyListAppendFormatted( kCFAllocatorDefault, context->subtestProgress,
-        "{"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%O"
-        "}",
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_START_TIME,              startTime,
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_END_TIME,                endTime,
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_STATE,                   ExpensiveConstrainedStateString(context->state),
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_EXPECT_RESULT,           ExpensiveConstrainedOperationString(context->expectedOperation),
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_ACTUAL_RESULT,           ExpensiveConstrainedOperationString(context->operation),
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_EXPENSIVE_PREV_NOW,      expensive,
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_CONSTRAINED_PREV_NOW,    constrained,
-        EXPENSIVE_CONSTRAINED_SUBTEST_PROGRESS_KEY_CALL_BACK,               context->subtestProgress_callBack
-    );
-    require_noerr( err, exit );
-    ForgetCF( &context->subtestProgress_callBack );
-    return;
-
-exit:
-    ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedFinalSubtestReport
-//===========================================================================================================================
-
-static void ExpensiveConstrainedSubtestReport( ExpensiveConstrainedContext *context, const char *error_description )
-{
-    OSStatus            err;
-    NanoTime64          now;
-    char                startTime[ 32 ];
-    char                endTime[ 32 ];
-    char                flagDescription[ 1024 ];
-
-    now = NanoTimeGetCurrent();
-    _NanoTime64ToTimestamp( context->subtestReport_startTime, startTime, sizeof( startTime ) );
-    _NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-    SNPrintF( flagDescription, sizeof( flagDescription ), "%#{flags}", context->flags, kDNSServiceFlagsDescriptors );
-
-    if (error_description != NULL)
-    {
-        err = CFPropertyListAppendFormatted( kCFAllocatorDefault, context->subtestReport,
-            "{"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%lli"
-                "%kO=%s"
-                "%kO=%O"
-                "%kO=%s"
-                "%kO=%O"
-            "}",
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_START_TIME,        startTime,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_END_TIME,          endTime,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_QNAME,             context->name,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_FLAGS,             flagDescription,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_PROTOCOLS,         ExpensiveConstrainedProtocolString( context->protocols ),
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_INDEX,   (int64_t) context->ifIndex,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_NAME,    context->ifName,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_RESULT,            CFSTR( "Fail" ),
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_ERROR,             error_description,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_TEST_PROGRESS,     context->subtestProgress
-        );
-    }
-    else
-    {
-        err = CFPropertyListAppendFormatted( kCFAllocatorDefault, context->subtestReport,
-            "{"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%s"
-                "%kO=%lli"
-                "%kO=%s"
-                "%kO=%O"
-                "%kO=%O"
-            "}",
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_START_TIME,        startTime,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_END_TIME,          endTime,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_QNAME,             context->name,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_FLAGS,             flagDescription,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_PROTOCOLS,         ExpensiveConstrainedProtocolString( context->protocols ),
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_INDEX,   (int64_t) context->ifIndex,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_INTERFACE_NAME,    context->ifName,
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_RESULT,            CFSTR( "Pass" ),
-            EXPENSIVE_CONSTRAINED_SUBTEST_REPORT_KEY_TEST_PROGRESS,     context->subtestProgress
-        );
-    }
-
-    require_noerr( err, exit );
-    ForgetCF( &context->subtestProgress );
-    return;
-exit:
-    ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedFinalResultReport
-//===========================================================================================================================
-
-static void ExpensiveConstrainedFinalResultReport( ExpensiveConstrainedContext *context, Boolean allPassed )
-{
-    OSStatus            err;
-    CFPropertyListRef   plist;
-    NanoTime64          now;
-    char                startTime[ 32 ];
-    char                endTime[ 32 ];
-
-    now = NanoTimeGetCurrent();
-    _NanoTime64ToTimestamp( context->testReport_startTime, startTime, sizeof( startTime ) );
-    _NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-
-    err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-        "{"
-            "%kO=%s"
-            "%kO=%s"
-            "%kO=%b"
-            "%kO=%O"
-        "}",
-        EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_START_TIME,       startTime,
-        EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_END_TIME,         endTime,
-        EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_ALL_PASSED,       allPassed,
-        EXPENSIVE_CONSTRAINED_TEST_REPORT_KEY_SUBTEST_RESULT,   context->subtestReport
-    );
-    require_noerr( err, exit );
-    ForgetCF( &context->subtestReport );
-
-    err = OutputPropertyList( plist, context->outputFormat, context->outputFilePath );
-    CFRelease( plist );
-    require_noerr( err, exit );
-
-    return;
-exit:
-    ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedProtocolString
-//===========================================================================================================================
-
-static const char *ExpensiveConstrainedProtocolString( DNSServiceProtocol protocol )
-{
-    const char *str = NULL;
-    switch ( protocol ) {
-        case kDNSServiceProtocol_IPv4:
-            str = "IPv4";
-            break;
-        case kDNSServiceProtocol_IPv6:
-            str = "IPv6";
-            break;
-        case kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6:
-            str = "IPv4 & IPv6";
-            break;
-        default:
-            break;
-    }
-    return str;
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedStateString
-//===========================================================================================================================
-
-static const char *ExpensiveConstrainedStateString( enum ExpensiveConstrainedTestState state )
-{
-    const char *str = NULL;
-    switch ( state ) {
-        case TEST_BEGIN:
-            str = "TEST_BEGIN";
-            break;
-        case TEST_EXPENSIVE_PREPARE:
-            str = "TEST_EXPENSIVE_PREPARE";
-            break;
-        case TEST_EXPENSIVE:
-            str = "TEST_EXPENSIVE";
-            break;
-        case TEST_CONSTRAINED_PREPARE:
-            str = "TEST_CONSTRAINED_PREPARE";
-            break;
-        case TEST_CONSTRAINED:
-            str = "TEST_CONSTRAINED";
-            break;
-        case TEST_EXPENSIVE_CONSTRAINED_PREPARE:
-            str = "TEST_EXPENSIVE_CONSTRAINED_PREPARE";
-            break;
-        case TEST_EXPENSIVE_CONSTRAINED:
-            str = "TEST_EXPENSIVE_CONSTRAINED";
-            break;
-        case TEST_FAILED:
-            str = "TEST_FAILED";
-            break;
-        case TEST_SUCCEEDED:
-            str = "TEST_SUCCEEDED";
-            break;
-        default:
-            str = "UNKNOWN";
-            break;
-    }
-
-    return str;
-}
-
-//===========================================================================================================================
-//    ExpensiveConstrainedOperationString
-//===========================================================================================================================
-
-static const char *ExpensiveConstrainedOperationString( enum ExpensiveConstrainedTestOperation operation )
-{
-    const char *str = NULL;
-    switch ( operation ) {
-        case RESULT_ADD:
-            str = "RESULT_ADD";
-            break;
-        case RESULT_RMV:
-            str = "RESULT_RMV";
-            break;
-        case NO_UPDATE:
-            str = "NO_UPDATE";
-            break;
-        default:
-            str = "UNKNOWN";
-            break;
-    }
-    return str;
-}
-
-//===========================================================================================================================
-//    expensiveConstrainedEndsWith
-//===========================================================================================================================
-static Boolean expensiveConstrainedEndsWith( const char *str, const char *suffix )
-{
-    if ( !str || !suffix )
-        return false;
-    size_t lenstr = strlen( str );
-    size_t lensuffix = strlen( suffix );
-    if ( lensuffix > lenstr )
-        return false;
-    return strncmp( str + lenstr - lensuffix, suffix, lensuffix ) == 0;
-}
-
-//===========================================================================================================================
-//	DNSProxyTestCmd
-//===========================================================================================================================
-
-// DNS Proxy Test Mode Parameters
-
-typedef enum
-{
-	kDNSProxyTestMode_Normal = 0,
-	kDNSProxyTestMode_ForceAAAASynthesis,
-	kDNSProxyTestMode_Count
-	
-}	DNSProxyTestMode;
-
-check_compile_time( kDNSProxyTestMode_Count > 0 );
-
-// DNS Proxy Test DNS64 Prefix Parameters
-// See <https://tools.ietf.org/html/rfc6052#section-2.2>.
-
-static const char * const		kDNSProxyTestParams_DNS64Prefixes[] =
-{
-	NULL,								// No prefix.
-	"3ffe:ffff::/32",					// 32-bit prefix. Note: Prefix is from deprecated 3ffe::/16 block (see RFC 3701).
-	"2001:db8:ff00::/40",				// 40-bit prefix.
-	"2001:db8:ffff::/48",				// 48-bit prefix.
-	"2001:db8:ffff:ff00::/56",			// 56-bit prefix.
-	"2001:db8:ffff:ffff::/64",			// 64-bit prefix.
-	"2001:db8:ffff:ff00:ffff:ffff::/96"	// 96-bit prefix. Note: bits 64 - 71 MUST be zero.
-};
-
-// DNS Proxy Test Transport Parameters
-
-typedef enum
-{
-	kDNSProxyTestTransport_UDPv4 = 0,
-	kDNSProxyTestTransport_TCPv4,
-	kDNSProxyTestTransport_UDPv6,
-	kDNSProxyTestTransport_TCPv6,
-	kDNSProxyTestTransport_Count
-	
-}	DNSProxyTestTransport;
-
-check_compile_time( kDNSProxyTestTransport_Count > 0 );
-
-// DNS Proxy Test Query Parameters
-
-typedef enum
-{
-	kDNSProxyTestQuery_A = 0,
-	kDNSProxyTestQuery_AAAA,
-	kDNSProxyTestQuery_IPv6OnlyA,
-	kDNSProxyTestQuery_IPv6OnlyAAAA,
-	kDNSProxyTestQuery_IPv4OnlyAAAA,
-	kDNSProxyTestQuery_AliasA,
-	kDNSProxyTestQuery_AliasAAAA,
-	kDNSProxyTestQuery_AliasIPv6OnlyA,
-	kDNSProxyTestQuery_AliasIPv6OnlyAAAA,
-	kDNSProxyTestQuery_AliasIPv4OnlyAAAA,
-	kDNSProxyTestQuery_NXDomainA,
-	kDNSProxyTestQuery_NXDomainAAAA,
-	kDNSProxyTestQuery_ReverseIPv6,
-	kDNSProxyTestQuery_ReverseIPv6NXDomain,
-	kDNSProxyTestQuery_ReverseIPv6DNS64,
-	kDNSProxyTestQuery_ReverseIPv6DNS64NXDomain,
-	kDNSProxyTestQuery_Count
-	
-}	DNSProxyTestQuery;
-
-check_compile_time( kDNSProxyTestQuery_Count > 0 );
-
-#define kDNSProxyTestQueryIterationCount		2
-
-typedef struct DNSProxyTest *		DNSProxyTestRef;
-struct DNSProxyTest
-{
-	dispatch_queue_t			queue;				// Serial queue for test events.
-	dispatch_semaphore_t		doneSem;			// Semaphore to signal when the test is done.
-	DNSServiceRef				probeGAI;			// Probe GAI for DNS server.
-	char *						probeHostname;		// Probe hostname.
-	mrc_dns_proxy_t				dnsProxy;			// DNS proxy reference.
-	DNSXConnRef					dnsProxyLegacy;		// Legacy DNS proxy connection reference.
-	dispatch_source_t			timer;				// Timer to put time limit on queries.
-	mdns_resolver_t				resolver;			// Resolver to represent the DNS proxy as a DNS service.
-	CFMutableDictionaryRef		report;				// Test's report.
-	CFMutableArrayRef			modeResults;		// "Weak" pointer to the 1st-level array of mode results.
-	CFMutableArrayRef			prefixResults;		// "Weak" pointer to current 2nd-level array of DNS64 prefix results.
-	CFMutableArrayRef			transportResults;	// "Weak" pointer to current 3rd-level array of transport results.
-	CFMutableArrayRef			queryResults;		// "Weak" pointer to current 4th-level array of query results.
-	DNSProxyTestMode			modeParam;			// Current mode parameter.
-	unsigned int				prefixParamIdx;		// Current DNS64 prefix parameter index.
-	DNSProxyTestTransport		transportParam;		// Current transport parameter.
-	DNSProxyTestQuery			queryParam;			// Current query parameter.
-	unsigned int				queryParamIter;		// Current query iteration.
-	uint32_t					loopbackIndex;		// Loopback interface's index.
-	mdns_querier_t				querier;			// Subtest's querier to send queries to DNS proxy.
-	NanoTime64					startTime;			// Subtest's start time.
-	char *						subtestDesc;		// Subtest's description.
-	char *						qnameStr;			// Subtest's query QNAME as a C string.
-	uint8_t *					qname;				// Subtest's query QNAME in label format.
-	uint16_t					qtype;				// Subtest's query QTYPE.
-	unsigned int				aliasCount;			// Subtest's expected number of CNAMEs in response answer section.
-	unsigned int				answerCount;		// Subtest's expected number of QTYPE records.
-	int							responseCode;		// Subtest's expected response code.
-	uint8_t *					canonicalName;		// Subtest's expected CNAME rdata for reverse IPv6 queries.
-	uint8_t *					answerName;			// Subtest's expected PTR rdata for reverse IPv6 queries.
-	pid_t						serverPID;			// PID of spawned DNS server.
-	int							subtestCount;		// Number of subtests that have completed or are in progress.
-	int							subtestPassCount;	// Number of subtests that have passed so far.
-	int32_t						refCount;			// Test object's reference count.
-	OSStatus					error;				// Overall test's error.
-	int							dns64PrefixBitLen;	// Current DNS64 prefix length (valid if > 0).
-	uint8_t						dns64Prefix[ 16 ];	// Current DNS64 prefix (valid if dns64PrefixBitLen > 0).
-	char						tag[ 6 + 1 ];		// Current subtest's random tag to uniquify QNAMEs.
-	Boolean						useLegacyDNSProxy;	// True if the legacy DNS proxy should be used.
-	Boolean						synthesizedAAAA;	// True if the current subtest expects DNS64 synthesized AAAA records.
-	Boolean						startedSubtests;	// True if the test has started running subtests.
-};
-
-ulog_define_ex( kDNSSDUtilIdentifier, DNSProxyTest, kLogLevelInfo, kLogFlags_None, "DNSProxyTest", NULL );
-#define dpt_ulog( LEVEL, ... )		ulog( &log_category_from_name( DNSProxyTest ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	_DNSProxyTestCreate( DNSProxyTestRef *outTest );
-static OSStatus	_DNSProxyTestRun( DNSProxyTestRef inTest, Boolean *outPassed );
-static void		_DNSProxyTestRetain( DNSProxyTestRef inTest );
-static void		_DNSProxyTestRelease( DNSProxyTestRef inTest );
-
-static void	DNSProxyTestCmd( void )
-{
-	OSStatus				err;
-	OutputFormatType		outputFormat;
-	DNSProxyTestRef			test	= NULL;
-	Boolean					passed	= false;
-	
-	err = OutputFormatFromArgString( gDNSProxyTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _DNSProxyTestCreate( &test );
-	require_noerr( err, exit );
-	
-	test->useLegacyDNSProxy = gDNSProxyTest_UseLegacyDNSProxy ? true : false;
-	err = _DNSProxyTestRun( test, &passed );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( test->report, outputFormat, gDNSProxyTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _DNSProxyTestRelease( test );
-    gExitCode = err ? 1 : ( passed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static void				_DNSProxyTestStart( void *inCtx );
-static void				_DNSProxyTestStop( DNSProxyTestRef inTest, OSStatus inError );
-static OSStatus			_DNSProxyTestContinue( DNSProxyTestRef inTest, OSStatus inSubtestError, Boolean *outDone );
-static const char *		_DNSProxyTestGetCurrentDNS64PrefixParam( DNSProxyTestRef inTest );
-static OSStatus			_DNSProxyTestPrepareMode( DNSProxyTestRef inTest );
-static OSStatus			_DNSProxyTestPrepareDNSProxy( DNSProxyTestRef inTest );
-static OSStatus			_DNSProxyTestPrepareResolver( DNSProxyTestRef inTest );
-static OSStatus			_DNSProxyTestStartQuery( DNSProxyTestRef inTest, Boolean *outSkipQuery );
-static OSStatus
-	_DNSProxyTestSynthesizeIPv6(
-		const uint8_t *	inIPv6Prefix,
-		int				inIPv6PrefixBitLen,
-		uint32_t		inIPv4Addr,
-		uint8_t			outIPv6Addr[ STATIC_PARAM 16 ] );
-static void	_DNSProxyTestHandleQuerierResult( DNSProxyTestRef inTest );
-static OSStatus
-	_DNSProxyTestVerifyAddressResponse(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inQName,
-		uint16_t		inQType,
-		int				inResponseCode,
-		unsigned int	inAliasCount,
-		unsigned int	inAnswerCount,
-		const uint8_t *	inDNS64Prefix,
-		int				inDNS64PrefixBitLen );
-static OSStatus
-	_DNSProxyTestVerifyReverseIPv6Response(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inQName,
-		int				inResponseCode,
-		const uint8_t *	inCanonicalName,
-		const uint8_t *	inAnswerName );
-static void DNSSD_API
-	_DNSProxyTestProbeGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inCtx );
-static void			_DNSProxyTestProbeTimerHandler( void *inCtx );
-
-static OSStatus	_DNSProxyTestCreate( DNSProxyTestRef *outTest )
-{
-	OSStatus			err;
-	DNSProxyTestRef		obj;
-	
-	obj = (DNSProxyTestRef) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	obj->error		= kInProgressErr;
-	obj->serverPID	= -1;
-	
-	obj->queue = dispatch_queue_create( "com.apple.dnssdutil.dns-proxy-test", DISPATCH_QUEUE_SERIAL );
-	require_action( obj->queue, exit, err = kNoResourcesErr );
-	
-	obj->doneSem = dispatch_semaphore_create( 0 );
-	require_action( obj->doneSem, exit, err = kNoResourcesErr );
-	
-	*outTest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _DNSProxyTestRelease( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSProxyTestRun( DNSProxyTestRef me, Boolean *outPassed )
-{
-	Boolean		passed;
-	
-	dispatch_async_f( me->queue, me, _DNSProxyTestStart );
-	dispatch_semaphore_wait( me->doneSem, DISPATCH_TIME_FOREVER );
-	
-	passed = ( !me->error && ( me->subtestPassCount == me->subtestCount ) ) ? true : false;
-	CFDictionarySetBoolean( me->report, CFSTR( "pass" ), passed );
-	dpt_ulog( kLogLevelInfo, "Test result: %s\n", passed ? "pass" : "fail" );
-	
-	if( outPassed ) *outPassed = passed;
-	return( me->error );
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestRetain( DNSProxyTestRef me )
-{
-	atomic_add_32( &me->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestRelease( DNSProxyTestRef me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->probeGAI );
-		check( !me->probeHostname );
-		check( !me->dnsProxy );
-		check( !me->dnsProxyLegacy );
-		check( !me->timer );
-		check( !me->resolver );
-		check( !me->modeResults );
-		check( !me->prefixResults );
-		check( !me->transportResults );
-		check( !me->queryResults );
-		check( !me->querier );
-		check( !me->subtestDesc );
-		check( !me->qnameStr );
-		check( !me->qname );
-		check( !me->canonicalName );
-		check( !me->answerName );
-		check( me->serverPID < 0 );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->doneSem );
-		ForgetCF( &me->report );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-
-#define kDNSProxyTestProbeQueryTimeoutSecs		5
-
-static void _DNSProxyTestStart( void *inCtx )
-{
-	OSStatus					err;
-	const DNSProxyTestRef		me			= (DNSProxyTestRef) inCtx;
-	char *						serverCmd	= NULL;
-	NanoTime64					startTime;
-	char						startTimeStr[ 32 ];
-	char						tag[ 6 + 1 ];
-	
-	startTime = NanoTimeGetCurrent();
-	
-	dpt_ulog( kLogLevelInfo, "Starting test\n" );
-	
-	me->error			= kInProgressErr;
-	me->loopbackIndex	= if_nametoindex( "lo0" );
-	err = map_global_value_errno( me->loopbackIndex != 0, me->loopbackIndex );
-	require_noerr_action_quiet( err, exit, dpt_ulog( kLogLevelError, "Failed to get interface index for lo0: %#m", err ) );
-	
-	serverCmd = NULL;
-	ASPrintF( &serverCmd, "dnssdutil server --loopback --follow %lld --port 0 --defaultTTL 300 --responseDelay 10",
-		(int64_t) getpid() );
-	require_action_quiet( serverCmd, exit, err = kUnknownErr );
-	
-	err = _SpawnCommand( &me->serverPID, "/dev/null", "/dev/null", "%s", serverCmd );
-	require_noerr( err, exit );
-	
-	check( !me->probeHostname );
-	ASPrintF( &me->probeHostname, "tag-dns-proxy-test-probe-%s.ipv4.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->probeHostname, exit, err = kNoMemoryErr );
-	
-	err = DNSServiceGetAddrInfo( &me->probeGAI, 0, kDNSServiceInterfaceIndexAny, kDNSServiceProtocol_IPv4,
-		me->probeHostname, _DNSProxyTestProbeGAICallback, me );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( me->probeGAI, me->queue );
-	require_noerr( err, exit );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDNSProxyTestProbeQueryTimeoutSecs ),
-		kDNSProxyTestProbeQueryTimeoutSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ),
-		me->queue, _DNSProxyTestProbeTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	dispatch_resume( me->timer );
-	
-	_NanoTime64ToTimestamp( startTime, startTimeStr, sizeof( startTimeStr ) );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &me->report,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// serverCmd
-			"%kO=%s"	// probeHostname
-			"%kO=[%@]"	// results
-		"}",
-		CFSTR( "startTime" ),		startTimeStr,
-		CFSTR( "serverCmd" ),		serverCmd,
-		CFSTR( "probeHostname" ),	me->probeHostname,
-		CFSTR( "results" ),			&me->modeResults );
-	require_noerr( err, exit );
-	
-exit:
-	FreeNullSafe( serverCmd );
-	if( err ) _DNSProxyTestStop( me, err );
-}
-
-//===========================================================================================================================
-
-static void		_DNSProxyTestSubtestCleanup( DNSProxyTestRef inTest );
-
-#define _DNSXForget( X )			ForgetCustom( X, DNSXRefDeAlloc )
-#define _mrc_dns_proxy_forget( X )	ForgetCustomEx( X, mrc_dns_proxy_invalidate, mrc_release )
-
-static void	_DNSProxyTestStop( DNSProxyTestRef me, OSStatus inError )
-{
-	OSStatus		err;
-	NanoTime64		endTime;
-	char			endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	me->error = inError;
-	dpt_ulog( kLogLevelInfo, "Stopping test with error: %#m\n", me->error );
-	
-	DNSServiceForget( &me->probeGAI );
-	ForgetMem( &me->probeHostname );
-	_mrc_dns_proxy_forget( &me->dnsProxy );
-	_DNSXForget( &me->dnsProxyLegacy );
-	dispatch_source_forget( &me->timer );
-	mdns_resolver_forget( &me->resolver );
-	me->prefixResults		= NULL;
-	me->modeResults			= NULL;
-	me->transportResults	= NULL;
-	me->queryResults		= NULL;
-	_DNSProxyTestSubtestCleanup( me );
-	if( me->serverPID >= 0 )
-	{
-		OSStatus		killErr;
-		
-		killErr = kill( me->serverPID, SIGTERM );
-		killErr = map_global_noerr_errno( killErr );
-		check_noerr( killErr );
-		me->serverPID = -1;
-	}
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->report,
-		"%kO=%s"		// endTime
-		"%kO=%lli"		// subtestCount
-		"%kO=%lli",		// subtestPassCount
-		CFSTR( "endTime" ),				endTimeStr,
-		CFSTR( "subtestCount" ),		(int64_t) me->subtestCount,
-		CFSTR( "subtestPassCount" ),	(int64_t) me->subtestPassCount );
-	check_noerr( err );
-	if( err && !me->error ) me->error = err;
-	dispatch_semaphore_signal( me->doneSem );
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestSubtestCleanup( DNSProxyTestRef me )
-{
-	dispatch_source_forget( &me->timer );
-	mdns_querier_forget( &me->querier );
-	ForgetMem( &me->subtestDesc );
-	ForgetMem( &me->qnameStr );
-	ForgetMem( &me->qname );
-	ForgetMem( &me->canonicalName );
-	ForgetMem( &me->answerName );
-}
-
-//===========================================================================================================================
-
-static OSStatus		_DNSProxyTestHandleSubtestCompletion( DNSProxyTestRef inTest, OSStatus inSubtestError );
-static char *		_DNSProxyTestCreateSubtestDescription( DNSProxyTestRef inTest );
-static const char *	_DNSProxyTestQueryToString( DNSProxyTestQuery inQuery );
-static const char *	_DNSProxyTestTransportToString( DNSProxyTestTransport inTransport );
-static const char *	_DNSProxyTestModeToString( DNSProxyTestMode inMode );
-
-static OSStatus	_DNSProxyTestContinue( DNSProxyTestRef me, OSStatus inSubtestError, Boolean *outDone )
-{
-	OSStatus		err;
-	Boolean			skipQueries	= false;
-	Boolean			done		= false;
-	
-	do
-	{
-		if( me->startedSubtests )
-		{
-			if( !skipQueries )
-			{
-				err = _DNSProxyTestHandleSubtestCompletion( me, inSubtestError );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				dpt_ulog( kLogLevelInfo, "Skipped subtest: %s\n", me->subtestDesc );
-			}
-			_DNSProxyTestSubtestCleanup( me );
-			if( skipQueries || ( ++me->queryParamIter == kDNSProxyTestQueryIterationCount ) )
-			{
-				me->queryParamIter = 0;
-				if( ++me->queryParam == kDNSProxyTestQuery_Count )
-				{
-					me->queryParam		= 0;
-					me->queryResults	= NULL;
-					dpt_ulog( kLogLevelInfo, "Invalidating resolver: %@\n", me->resolver );
-					mdns_resolver_forget( &me->resolver );
-					if( ++me->transportParam == kDNSProxyTestTransport_Count )
-					{
-						me->transportParam		= 0;
-						me->transportResults	= NULL;
-						dpt_ulog( kLogLevelInfo, "Disabling DNS proxy\n" );
-						_mrc_dns_proxy_forget( &me->dnsProxy );
-						_DNSXForget( &me->dnsProxyLegacy );
-						if( ++me->prefixParamIdx == countof( kDNSProxyTestParams_DNS64Prefixes ) )
-						{
-							me->prefixParamIdx	= 0;
-							me->prefixResults	= NULL;
-							if( ++me->modeParam == kDNSProxyTestMode_Count )
-							{
-								me->modeParam	= 0;
-								me->modeResults	= NULL;
-								done			= true;
-								err				= kNoErr;
-								goto exit;
-							}
-						}
-					}
-				}
-			}
-		}
-		else
-		{
-			me->startedSubtests = true;
-		}
-		if( ( me->queryParamIter == 0 ) && ( me->queryParam == 0 ) )
-		{
-			if( me->transportParam == 0 )
-			{
-				if( me->prefixParamIdx == 0 )
-				{
-					err = _DNSProxyTestPrepareMode( me );
-					require_noerr( err, exit );
-				}
-				err = _DNSProxyTestPrepareDNSProxy( me );
-				require_noerr( err, exit );
-			}
-			err = _DNSProxyTestPrepareResolver( me );
-			require_noerr( err, exit );
-		}
-		err = _DNSProxyTestStartQuery( me, &skipQueries );
-		require_noerr( err, exit );
-		
-		check( !me->subtestDesc );
-		me->subtestDesc = _DNSProxyTestCreateSubtestDescription( me );
-		require_action( me->subtestDesc, exit, err = kNoMemoryErr );
-		
-	}	while( skipQueries );
-	
-	++me->subtestCount;
-	dpt_ulog( kLogLevelInfo, "Started subtest #%d: %s\n", me->subtestCount, me->subtestDesc );
-	
-exit:
-	if( outDone ) *outDone = done;
-	return( err );
-}
-
-static OSStatus	_DNSProxyTestHandleSubtestCompletion( DNSProxyTestRef me, OSStatus inSubtestError )
-{
-	OSStatus		err;
-	NanoTime64		endTime;
-	char			errorStr[ 128 ];
-	char			startTimeStr[ 32 ];
-	char			endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	
-	if( !inSubtestError ) ++me->subtestPassCount;
-	
-	dpt_ulog( kLogLevelInfo, "Subtest #%d result: %s (pass rate: %d/%d)\n",
-		me->subtestCount, inSubtestError ? "fail" : "pass", me->subtestPassCount, me->subtestCount );
-	
-	_NanoTime64ToTimestamp( me->startTime, startTimeStr, sizeof( startTimeStr ) );
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	SNPrintF( errorStr, sizeof( errorStr ), "%m", inSubtestError );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->queryResults,
-		"{"
-			"%kO=%s"		// description
-			"%kO=%s"		// startTime
-			"%kO=%s"		// endTime
-			"%kO=%s"		// qname
-			"%kO=%s"		// qtype
-			"%kO=%b"		// pass
-			"%kO="			// error
-			"{"
-				"%kO=%lli"	// code
-				"%kO=%s"	// description
-			"}"
-		"}",
-		CFSTR( "description" ),	me->subtestDesc,
-		CFSTR( "startTime" ),	startTimeStr,
-		CFSTR( "endTime" ),		endTimeStr,
-		CFSTR( "qname" ),		me->qnameStr,
-		CFSTR( "qtype" ),		DNSRecordTypeValueToString( me->qtype ),
-		CFSTR( "pass" ),		inSubtestError ? false : true,
-		CFSTR( "error" ),
-		CFSTR( "code" ),		(int64_t) inSubtestError,
-		CFSTR( "description" ),	errorStr );
-	return( err );
-}
-
-static char *	_DNSProxyTestCreateSubtestDescription( DNSProxyTestRef me )
-{
-	const char *		queryStr;
-	const char *		transportStr;
-	const char *		dns64PrefixStr;
-	const char *		modeStr;
-	char *				description;
-	
-	queryStr		= _DNSProxyTestQueryToString( me->queryParam );
-	transportStr	= _DNSProxyTestTransportToString( me->transportParam );
-	dns64PrefixStr	= _DNSProxyTestGetCurrentDNS64PrefixParam( me );
-	modeStr			= _DNSProxyTestModeToString( me->modeParam );
-	description		= NULL;
-	if( dns64PrefixStr )
-	{
-		ASPrintF( &description, "%s over %s to DNS proxy using DNS64 prefix %s in %s mode (%u of %d)",
-			queryStr, transportStr, dns64PrefixStr, modeStr, me->queryParamIter + 1, kDNSProxyTestQueryIterationCount );
-	}
-	else
-	{
-		ASPrintF( &description, "%s over %s to DNS proxy in %s mode (%u of %d)",
-			queryStr, transportStr, modeStr, me->queryParamIter + 1, kDNSProxyTestQueryIterationCount );
-	}
-	return( description );
-}
-
-//===========================================================================================================================
-
-static const char *	_DNSProxyTestQueryToString( DNSProxyTestQuery inQuery )
-{
-	switch( inQuery )
-	{
-		case kDNSProxyTestQuery_A:							return( "A record query" );
-		case kDNSProxyTestQuery_AAAA:						return( "AAAA record query" );
-		case kDNSProxyTestQuery_IPv6OnlyA:					return( "IPv6-only A record query" );
-		case kDNSProxyTestQuery_IPv6OnlyAAAA:				return( "IPv6-only AAAA record query" );
-		case kDNSProxyTestQuery_IPv4OnlyAAAA:				return( "IPv4-only AAAA record query" );
-		case kDNSProxyTestQuery_AliasA:						return( "A record query with CNAMEs" );
-		case kDNSProxyTestQuery_AliasAAAA:					return( "AAAA record query with CNAMEs" );
-		case kDNSProxyTestQuery_AliasIPv6OnlyA:				return( "IPv6-only A record query with CNAMEs" );
-		case kDNSProxyTestQuery_AliasIPv6OnlyAAAA:			return( "IPv6-only AAAA record query with CNAMEs" );
-		case kDNSProxyTestQuery_AliasIPv4OnlyAAAA:			return( "IPv4-only AAAA record query with CNAMEs" );
-		case kDNSProxyTestQuery_NXDomainA:					return( "A record query (NXDomain)" );
-		case kDNSProxyTestQuery_NXDomainAAAA:				return( "AAAA record query (NXDomain)" );
-		case kDNSProxyTestQuery_ReverseIPv6:				return( "Reverse IPv6 query" );
-		case kDNSProxyTestQuery_ReverseIPv6NXDomain:		return( "Reverse IPv6 query (NXDomain)" );
-		case kDNSProxyTestQuery_ReverseIPv6DNS64:			return( "Reverse IPv6 query with DNS64 prefix" );
-		case kDNSProxyTestQuery_ReverseIPv6DNS64NXDomain:	return( "Reverse IPv6 query with DNS64 prefix (NXDomain)" );
-		default:											return( "<INVALID QUERY>" );
-    }
-}
-
-//===========================================================================================================================
-
-static const char *	_DNSProxyTestTransportToString( DNSProxyTestTransport inTransport )
-{
-    switch( inTransport )
-	{
-		case kDNSProxyTestTransport_UDPv4:	return( "IPv4-UDP" );
-		case kDNSProxyTestTransport_TCPv4:	return( "IPv4-TCP" );
-		case kDNSProxyTestTransport_UDPv6:	return( "IPv6-UDP" );
-		case kDNSProxyTestTransport_TCPv6:	return( "IPv6-TCP" );
-		default:							return( "<INVALID TRANSPORT>" );
-	}
-}
-
-//===========================================================================================================================
-
-static const char *	_DNSProxyTestModeToString( DNSProxyTestMode inMode )
-{
-    switch( inMode )
-	{
-		case kDNSProxyTestMode_Normal:				return( "normal" );
-		case kDNSProxyTestMode_ForceAAAASynthesis:	return( "force-AAAA-synthesis" );
-		default:									return( "<INVALID MODE>" );
-	}
-}
-
-//===========================================================================================================================
-
-static const char *	_DNSProxyTestGetCurrentDNS64PrefixParam( DNSProxyTestRef me )
-{
-	const unsigned int		index = me->prefixParamIdx;
-	const unsigned int		count = countof( kDNSProxyTestParams_DNS64Prefixes );
-	
-	require_fatal( index < count, "DNSProxyTest DNS Proxy DNS64 prefix parameter index %u out-of-range.", index );
-	return( kDNSProxyTestParams_DNS64Prefixes[ index ] );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSProxyTestPrepareMode( DNSProxyTestRef me )
-{
-	OSStatus		err;
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->modeResults,
-		"{"
-			"%kO=%s"	// mode
-			"%kO=[%@]"	// results
-		"}",
-		CFSTR( "mode" ),	_DNSProxyTestModeToString( me->modeParam ),
-		CFSTR( "results" ),	&me->prefixResults );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestDNSProxyCallback( DNSXConnRef inDNSProxy, DNSXErrorType inError );
-
-static OSStatus	_DNSProxyTestPrepareDNSProxy( DNSProxyTestRef me )
-{
-	OSStatus			err;
-	const char *		dns64PrefixStr;
-	Boolean				forceAAAASynthesis;
-	
-	me->dns64PrefixBitLen = 0;
-	memset( me->dns64Prefix, 0, sizeof( me->dns64Prefix ) );
-	dns64PrefixStr = _DNSProxyTestGetCurrentDNS64PrefixParam( me );
-	if( dns64PrefixStr )
-	{
-		const char *		end;
-		
-		err = _StringToIPv6Address( dns64PrefixStr, kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoScope,
-			me->dns64Prefix, NULL, NULL, &me->dns64PrefixBitLen, &end );
-		if( !err && ( *end != '\0' ) ) err = kMalformedErr;
-		require_noerr_quiet( err, exit );
-	}
-	switch( me->modeParam )
-	{
-		case kDNSProxyTestMode_Normal:
-			forceAAAASynthesis = false;
-			break;
-		
-		case kDNSProxyTestMode_ForceAAAASynthesis:
-			forceAAAASynthesis = true;
-			break;
-		
-		default:
-			FatalErrorF( "Unhandled DNSProxyTestMode value %ld", (long) me->modeParam );
-	}
-	if( me->useLegacyDNSProxy )
-	{
-		IfIndex		interfaces[ MaxInputIf ];
-		
-		memset( interfaces, 0, sizeof( interfaces ) );
-		interfaces[ 0 ] = me->loopbackIndex;
-		
-		check( !me->dnsProxyLegacy );
-		if( dns64PrefixStr )
-		{
-			DNSXProxyFlags		flags;
-			
-			dpt_ulog( kLogLevelInfo, "Enabling legacy DNS proxy with DNS64 prefix %.16a/%d\n",
-				me->dns64Prefix, me->dns64PrefixBitLen );
-			flags = forceAAAASynthesis ? kDNSXProxyFlagForceAAAASynthesis : kDNSXProxyFlagNull;
-			err = DNSXEnableProxy64( &me->dnsProxyLegacy, kDNSProxyEnable, interfaces, 0, me->dns64Prefix,
-				me->dns64PrefixBitLen, flags, me->queue, _DNSProxyTestDNSProxyCallback );
-			require_noerr_quiet( err, exit );
-		}
-		else
-		{
-			dpt_ulog( kLogLevelInfo, "Enabling legacy DNS proxy (without a DNS64 prefix)\n" );
-			err = DNSXEnableProxy( &me->dnsProxyLegacy, kDNSProxyEnable, interfaces, 0, me->queue,
-				_DNSProxyTestDNSProxyCallback );
-			require_noerr_quiet( err, exit );
-		}
-	}
-	else
-	{
-		mrc_dns_proxy_parameters_t		params;
-		
-		params = mrc_dns_proxy_parameters_create( &err );
-		require_noerr( err, exit );
-		
-		mrc_dns_proxy_parameters_add_input_interface( params, me->loopbackIndex );
-		mrc_dns_proxy_parameters_set_output_interface( params, 0 );
-		if( dns64PrefixStr )
-		{
-			mrc_dns_proxy_parameters_set_nat64_prefix( params, me->dns64Prefix, (size_t) me->dns64PrefixBitLen );
-			if( forceAAAASynthesis ) mrc_dns_proxy_parameters_set_force_aaaa_synthesis( params, true );
-			dpt_ulog( kLogLevelInfo, "Starting DNS proxy with DNS64 prefix %.16a/%d\n",
-				me->dns64Prefix, me->dns64PrefixBitLen );
-		}
-		else
-		{
-			dpt_ulog( kLogLevelInfo, "Starting DNS proxy (without a DNS64 prefix)\n" );
-		}
-		check( !me->dnsProxy );
-		me->dnsProxy = mrc_dns_proxy_create( params, &err );
-		mrc_forget( &params );
-		require_noerr_quiet( err, exit );
-		
-		mrc_dns_proxy_set_queue( me->dnsProxy, me->queue );
-		mrc_dns_proxy_set_event_handler( me->dnsProxy,
-		^( const mrc_dns_proxy_event_t inEvent, const OSStatus inError )
-		{
-			switch( inEvent )
-			{
-				case mrc_dns_proxy_event_started:
-					dpt_ulog( kLogLevelInfo, "DNS proxy was started\n" );
-					break;
-				
-				case mrc_dns_proxy_event_interruption:
-					dpt_ulog( kLogLevelInfo, "DNS proxy was interrupted\n" );
-					break;
-				
-				case mrc_dns_proxy_event_invalidation:
-					if( inError )	dpt_ulog( kLogLevelError, "DNS proxy invalidated with error: %#m\n", inError );
-					else			dpt_ulog( kLogLevelInfo, "DNS proxy invalidated\n" );
-					break;
-				
-				default:
-				case mrc_dns_proxy_event_none:
-					FatalErrorF( "Unhandled DNS proxy event value: %d", inEvent );
-			}
-		} );
-		mrc_dns_proxy_activate( me->dnsProxy );
-	}
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->prefixResults,
-		"{"
-			"%kO=%s"	// dns64Prefix
-			"%kO=[%@]"	// results
-		"}",
-		CFSTR( "dns64Prefix" ),	dns64PrefixStr ? dns64PrefixStr : "",
-		CFSTR( "results" ),		&me->transportResults );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-static void	_DNSProxyTestDNSProxyCallback( DNSXConnRef inDNSProxy, DNSXErrorType inError )
-{
-	Unused( inDNSProxy );
-	
-	if( !inError )	dpt_ulog( kLogLevelInfo, "DNS proxy callback: no error\n" );
-	else			dpt_ulog( kLogLevelError, "DNS proxy callback: error %#m\n", inError );
-}
-
-//===========================================================================================================================
-
-#define kDNSProxyTestDNSProxyAddrStr_IPv4		"127.0.0.1:53"
-#define kDNSProxyTestDNSProxyAddrStr_IPv6		"[::1]:53"
-
-static OSStatus	_DNSProxyTestPrepareResolver( DNSProxyTestRef me )
-{
-	OSStatus					err;
-	const char *				addrStr;
-	mdns_address_t				addr = NULL;
-	mdns_resolver_type_t		resolverType;
-	
-	switch( me->transportParam )
-	{
-		case kDNSProxyTestTransport_UDPv4:
-			addrStr			= kDNSProxyTestDNSProxyAddrStr_IPv4;
-			resolverType	= mdns_resolver_type_normal;
-			break;
-		
-		case kDNSProxyTestTransport_TCPv4:
-			addrStr			= kDNSProxyTestDNSProxyAddrStr_IPv4;
-			resolverType	= mdns_resolver_type_tcp;
-			break;
-		
-		case kDNSProxyTestTransport_UDPv6:
-			addrStr			= kDNSProxyTestDNSProxyAddrStr_IPv6;
-			resolverType	= mdns_resolver_type_normal;
-			break;
-		
-		case kDNSProxyTestTransport_TCPv6:
-			addrStr			= kDNSProxyTestDNSProxyAddrStr_IPv6;
-			resolverType	= mdns_resolver_type_tcp;
-			break;
-		
-		default:
-			FatalErrorF( "Unhandled DNSProxyTestTransport value %ld", (long) me->transportParam );
-	}
-	check( !me->resolver );
-	me->resolver = mdns_resolver_create( resolverType, 0, &err );
-	require_noerr( err, exit );
-	
-	addr = mdns_address_create_from_ip_address_string( addrStr );
-	require_action( addr, exit, err = kUnknownErr );
-	
-	err = mdns_resolver_add_server_address( me->resolver, addr );
-	mdns_forget( &addr );
-	require_noerr( err, exit );
-	
-	dpt_ulog( kLogLevelInfo, "Activating resolver: %@\n", me->resolver );
-	mdns_resolver_activate( me->resolver );
-	
-	_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( me->tag ) - 1, me->tag );
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->transportResults,
-		"{"
-			"%kO=%s"	// transport
-			"%kO=[%@]"	// results
-		"}",
-		CFSTR( "transport" ),	_DNSProxyTestTransportToString( me->transportParam ),
-		CFSTR( "results" ),		&me->queryResults );
-	require_noerr( err, exit );
-	
-exit:
-	mdns_release_null_safe( addr );
-	return( err );
-}
-
-//===========================================================================================================================
-
-#define kDNSProxyTestQuerierTimeLimitSecs		5
-#define kDNSProxyTestRecordTTL					( 5 * kSecondsPerMinute )
-#define kDNSProxyTestAddressCount				4
-#define kDNSProxyTestAliasCount					4
-
-static void	_DNSProxyTestQuerierTimerHandler( void *inCtx );
-
-static OSStatus	_DNSProxyTestStartQuery( DNSProxyTestRef me, Boolean *outSkipQuery )
-{
-	OSStatus			err;
-	mdns_querier_t		querier;
-	uint8_t				tmpName[ kDomainNameLengthMax ];
-	Boolean				skipQuery = false;
-	
-	me->startTime		= NanoTimeGetCurrent();
-	me->qtype			= 0;
-	me->aliasCount		= 0;
-	me->answerCount		= 0;
-	me->responseCode	= 0;
-	me->canonicalName	= NULL;
-	me->answerName		= NULL;
-	me->synthesizedAAAA	= false;
-	
-	check( !me->qnameStr );
-	switch( me->queryParam )
-	{
-		case kDNSProxyTestQuery_A:
-			me->qtype			= kDNSRecordType_A;
-			me->answerCount		= kDNSProxyTestAddressCount;
-			me->responseCode	= kDNSRCode_NoError;
-			ASPrintF( &me->qnameStr, "count-%u.ttl-%u.tag-a-%s.d.test.",
-				kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->answerCount		= kDNSProxyTestAddressCount;
-			me->responseCode	= kDNSRCode_NoError;
-			if( ( me->dns64PrefixBitLen > 0 ) && ( me->modeParam == kDNSProxyTestMode_ForceAAAASynthesis ) )
-			{
-				me->synthesizedAAAA = true;
-			}
-			else
-			{
-				me->synthesizedAAAA = false;
-			}
-			ASPrintF( &me->qnameStr, "count-%u.ttl-%u.tag-aaaa-%s.d.test.",
-				kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_IPv6OnlyA:
-			me->qtype			= kDNSRecordType_A;
-			me->answerCount		= 0;
-			me->responseCode	= kDNSRCode_NoError;
-			ASPrintF( &me->qnameStr, "ipv6.ttl-%u.tag-ipv6-only-a-%s.d.test.", kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_IPv6OnlyAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->responseCode	= kDNSRCode_NoError;
-			if( ( me->dns64PrefixBitLen > 0 ) && ( me->modeParam == kDNSProxyTestMode_ForceAAAASynthesis ) )
-			{
-				me->answerCount = 0;
-			}
-			else
-			{
-				me->answerCount = kDNSProxyTestAddressCount;
-			}
-			ASPrintF( &me->qnameStr, "count-%u.ipv6.ttl-%u.tag-ipv6-only-aaaa-%s.d.test.",
-				kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_IPv4OnlyAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->responseCode	= kDNSRCode_NoError;
-			if( me->dns64PrefixBitLen > 0 )
-			{
-				me->answerCount		= kDNSProxyTestAddressCount;
-				me->synthesizedAAAA	= true;
-			}
-			else
-			{
-				me->answerCount		= 0;
-				me->synthesizedAAAA	= false;
-			}
-			ASPrintF( &me->qnameStr, "count-%u.ipv4.ttl-%u.tag-ipv4-only-aaaa-%s.d.test.",
-				kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AliasA:
-			me->qtype			= kDNSRecordType_A;
-			me->aliasCount		= kDNSProxyTestAliasCount;
-			me->answerCount		= kDNSProxyTestAddressCount;
-			me->responseCode	= kDNSRCode_NoError;
-			ASPrintF( &me->qnameStr, "alias-%u.count-%u.ttl-%u.tag-alias-a-%s.d.test.",
-				kDNSProxyTestAliasCount, kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AliasAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->aliasCount		= kDNSProxyTestAliasCount;
-			me->answerCount		= kDNSProxyTestAddressCount;
-			me->responseCode	= kDNSRCode_NoError;
-			if( ( me->dns64PrefixBitLen > 0 ) && ( me->modeParam == kDNSProxyTestMode_ForceAAAASynthesis ) )
-			{
-				me->synthesizedAAAA = true;
-			}
-			else
-			{
-				me->synthesizedAAAA = false;
-			}
-			ASPrintF( &me->qnameStr, "alias-%u.count-%u.ttl-%u.tag-alias-aaaa-%s.d.test.",
-				kDNSProxyTestAliasCount, kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AliasIPv6OnlyA:
-			me->qtype			= kDNSRecordType_A;
-			me->aliasCount		= kDNSProxyTestAliasCount;
-			me->answerCount		= 0;
-			me->responseCode	= kDNSRCode_NoError;
-			ASPrintF( &me->qnameStr, "alias-%u.ipv6.ttl-%u.tag-alias-ipv6-only-a-%s.d.test.",
-				kDNSProxyTestAliasCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AliasIPv6OnlyAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->aliasCount		= kDNSProxyTestAliasCount;
-			me->responseCode	= kDNSRCode_NoError;
-			if( ( me->dns64PrefixBitLen > 0 ) && ( me->modeParam == kDNSProxyTestMode_ForceAAAASynthesis ) )
-			{
-				me->answerCount	= 0;
-			}
-			else
-			{
-				me->answerCount	= kDNSProxyTestAddressCount;
-			}
-			ASPrintF( &me->qnameStr, "alias-%u.ipv6.count-%u.ttl-%u.tag-alias-ipv6-only-aaaa-%s.d.test.",
-				kDNSProxyTestAliasCount, kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_AliasIPv4OnlyAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->aliasCount		= kDNSProxyTestAliasCount;
-			me->responseCode	= kDNSRCode_NoError;
-			if( me->dns64PrefixBitLen > 0 )
-			{
-				me->answerCount		= kDNSProxyTestAddressCount;
-				me->synthesizedAAAA	= true;
-			}
-			else
-			{
-				me->answerCount		= 0;
-				me->synthesizedAAAA	= false;
-			}
-			ASPrintF( &me->qnameStr, "alias-%u.count-%u.ipv4.ttl-%u.tag-alias-ipv4-only-aaaa-%s.d.test.",
-				kDNSProxyTestAliasCount, kDNSProxyTestAddressCount, kDNSProxyTestRecordTTL, me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_NXDomainA:
-			me->qtype			= kDNSRecordType_A;
-			me->answerCount		= 0;
-			me->responseCode	= kDNSRCode_NXDomain;
-			ASPrintF( &me->qnameStr, "does-not-exist.tag-nx-domain-a-%s.d.test.", me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_NXDomainAAAA:
-			me->qtype			= kDNSRecordType_AAAA;
-			me->answerCount		= 0;
-			me->responseCode	= kDNSRCode_NXDomain;
-			ASPrintF( &me->qnameStr, "does-not-exist.tag-nx-domain-aaaa-%s.d.test.", me->tag );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		
-		case kDNSProxyTestQuery_ReverseIPv6:
-		case kDNSProxyTestQuery_ReverseIPv6NXDomain:
-		{
-			unsigned int		hostID;
-			uint8_t				ipv6Addr[ 16 ];
-			char				reverseIPv6NameStr[ kReverseIPv6DomainNameBufLen ];
-			
-			// To force mDNSResponder to have to send a query on the first query iteration, use a different reverse IPv6
-			// PTR query for each mode/DNS64 prefix/transport combination.
-			
-			check_compile_time_code( kDNSProxyTestTransport_Count <= 4 );
-			check_compile_time_code( countof( kDNSProxyTestParams_DNS64Prefixes ) <= 8 );
-			check_compile_time_code( kDNSProxyTestMode_Count <= 4 );
-			hostID  =   ( (unsigned int) me->transportParam ) & 0x03;			// Set bits 1 - 0 to transport param.
-			hostID |= (   me->prefixParamIdx                  & 0x07 ) << 2;	// Set bits 4 - 2 to prefix param index.
-			hostID |= ( ( (unsigned int) me->modeParam )      & 0x03 ) << 5;	// Set bits 6 - 5 to mode param.
-			hostID |= 1U << 7;													// Set bit 7 to ensure a non-zero hostID.
-			check( ( hostID >= 1 ) && ( hostID <= 255 ) );
-			
-			memcpy( ipv6Addr, kDNSServerBaseAddrV6, 16 );
-			ipv6Addr[ 15 ] = (uint8_t) hostID;
-			
-			me->qtype = kDNSRecordType_PTR;
-			if( me->queryParam == kDNSProxyTestQuery_ReverseIPv6 )
-			{
-				char				answerNameStr[ 128 ];
-				char *				dst = answerNameStr;
-				char * const		lim = &answerNameStr[ countof( answerNameStr ) ];
-				int					i;
-				
-				me->responseCode = kDNSRCode_NoError;
-				
-				// Create the expected RDATA.
-				
-				SNPrintF_Add( &dst, lim, "ipv6" );
-				for( i = 0; i < 8; ++i )
-				{
-					SNPrintF_Add( &dst, lim, "-%04x", ReadBig16( &ipv6Addr[ i * 2 ] ) );
-				}
-				SNPrintF_Add( &dst, lim, ".d.test." );
-				err = DomainNameFromString( tmpName, answerNameStr, NULL );
-				require_noerr_quiet( err, exit );
-				
-				err = DomainNameDup( tmpName, &me->answerName, NULL );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				me->responseCode	= kDNSRCode_NXDomain;
-				me->answerName		= NULL;
-				
-				// Make the IPv6 address invalid by setting bits 15-8. This makes the host identifier bogus.
-				// The DNS server's IPv6 prefix is 96 bits, but only host identifiers in [1, 255] are recognized.
-				
-				ipv6Addr[ 14 ] = 0xFF;
-			}
-			_WriteReverseIPv6DomainNameString( ipv6Addr, reverseIPv6NameStr );
-			me->qnameStr = strdup( reverseIPv6NameStr );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		}
-		case kDNSProxyTestQuery_ReverseIPv6DNS64:
-		case kDNSProxyTestQuery_ReverseIPv6DNS64NXDomain:
-		{
-			uint32_t	ipv4Addr;
-			uint8_t		ipv6Addr[ 16 ];
-			char		reverseIPNameStr[ kReverseIPv6DomainNameBufLen ];
-			
-			if( me->dns64PrefixBitLen <= 0 )
-			{
-				skipQuery = true;
-				err = kNoErr;
-				goto exit;
-			}
-			me->qtype = kDNSRecordType_PTR;
-			if( me->queryParam == kDNSProxyTestQuery_ReverseIPv6DNS64 )
-			{
-				char		answerNameStr[ 64 ];
-				
-				me->responseCode = kDNSRCode_NoError;
-				
-				ipv4Addr = kDNSServerBaseAddrV4 + 1;
-				_WriteReverseIPv4DomainNameString( ipv4Addr, reverseIPNameStr );
-				
-				err = DomainNameFromString( tmpName, reverseIPNameStr, NULL );
-				require_noerr_quiet( err, exit );
-				
-				err = DomainNameDup( tmpName, &me->canonicalName, NULL );
-				require_noerr( err, exit );
-				
-				SNPrintF( answerNameStr, sizeof( answerNameStr ), "ipv4-%u-%u-%u-%u.d.test.",
-					( ipv4Addr >> 24 ) & 0xFF,
-					( ipv4Addr >> 16 ) & 0xFF,
-					( ipv4Addr >>  8 ) & 0xFF,
-					  ipv4Addr         & 0xFF );
-				err = DomainNameFromString( tmpName, answerNameStr, NULL );
-				require_noerr_quiet( err, exit );
-				
-				err = DomainNameDup( tmpName, &me->answerName, NULL );
-				require_noerr( err, exit );
-			}
-			else
-			{
-				ipv4Addr = kDNSServerBaseAddrV4 + 0;
-				
-				me->responseCode	= kDNSRCode_NXDomain;
-				me->canonicalName	= NULL;
-				me->answerName		= NULL;
-			}
-			err = _DNSProxyTestSynthesizeIPv6( me->dns64Prefix, me->dns64PrefixBitLen, ipv4Addr, ipv6Addr );
-			require_noerr( err, exit );
-			
-			_WriteReverseIPv6DomainNameString( ipv6Addr, reverseIPNameStr );
-			me->qnameStr = strdup( reverseIPNameStr );
-			require_action( me->qnameStr, exit, err = kNoMemoryErr );
-			break;
-		}
-		default:
-			FatalErrorF( "Unhandled DNSProxyTestQuery value %ld", (long) me->queryParam );
-	}
-	check( !me->qname );
-	err = DomainNameFromString( tmpName, me->qnameStr, NULL );
-	require_noerr_quiet( err, exit );
-	
-	err = DomainNameDup( tmpName, &me->qname, NULL );
-	require_noerr( err, exit );
-	
-	check( !me->querier );
-	me->querier = mdns_resolver_create_querier( me->resolver, &err );
-	require_noerr( err, exit );
-	
-	err = mdns_querier_set_query( me->querier, me->qname, me->qtype, kDNSClassType_IN );
-	require_noerr( err, exit );
-	
-	mdns_querier_set_queue( me->querier, me->queue );
-	_DNSProxyTestRetain( me );
-	querier = me->querier;
-	mdns_retain( querier );
-	mdns_querier_set_result_handler( me->querier,
-	^{
-		if( me->querier == querier ) _DNSProxyTestHandleQuerierResult( me );
-		_DNSProxyTestRelease( me );
-		mdns_release( querier );
-	} );
-	mdns_querier_activate( me->querier );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDNSProxyTestQuerierTimeLimitSecs ),
-		kDNSProxyTestQuerierTimeLimitSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ),
-		me->queue, _DNSProxyTestQuerierTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	dispatch_resume( me->timer );
-	
-exit:
-	if( outSkipQuery ) *outSkipQuery = skipQuery;
-	return( err );
-}
-
-static void	_DNSProxyTestQuerierTimerHandler( void *inCtx )
-{
-	OSStatus					err;
-	const DNSProxyTestRef		me = (DNSProxyTestRef) inCtx;
-	Boolean						done;
-	
-	dpt_ulog( kLogLevelInfo, "Query for '%{du:dname}' timed out.\n", me->qname );
-	
-	err = _DNSProxyTestContinue( me, kTimeoutErr, &done );
-	check_noerr( err );
-	if( err || done ) _DNSProxyTestStop( me, err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSProxyTestSynthesizeIPv6(
-		const uint8_t *	inIPv6Prefix,
-		int				inIPv6PrefixBitLen,
-		uint32_t		inIPv4Addr,
-		uint8_t			outIPv6Addr[ STATIC_PARAM 16 ] )
-{
-	// From <https://tools.ietf.org/html/rfc6052#section-2.2>:
-	//
-	// 2.2.  IPv4-Embedded IPv6 Address Format
-	//
-	//   IPv4-converted IPv6 addresses and IPv4-translatable IPv6 addresses
-	//   follow the same format, described here as the IPv4-embedded IPv6
-	//   address Format.  IPv4-embedded IPv6 addresses are composed of a
-	//   variable-length prefix, the embedded IPv4 address, and a variable-
-	//   length suffix, as presented in the following diagram, in which PL
-	//   designates the prefix length:
-	//
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |32|     prefix    |v4(32)         | u | suffix                    |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |40|     prefix        |v4(24)     | u |(8)| suffix                |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |48|     prefix            |v4(16) | u | (16)  | suffix            |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |56|     prefix                |(8)| u |  v4(24)   | suffix        |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |64|     prefix                    | u |   v4(32)      | suffix    |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//    |96|     prefix                                    |    v4(32)     |
-	//    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-	//
-	//                                 Figure 1
-	switch( inIPv6PrefixBitLen )
-	{
-		case 32:
-		case 40:
-		case 48:
-		case 56:
-		case 64:
-		case 96:
-		{
-			const int		prefixLen = inIPv6PrefixBitLen / 8;
-			int				i, j;
-			uint8_t			v4Addr[ 4 ];
-			
-			memcpy( outIPv6Addr, inIPv6Prefix, (size_t) prefixLen );
-			WriteBig32Typed( v4Addr, inIPv4Addr );
-			
-			// 1. Bits 64 - 71, i.e., reserved octet "u", MUST be zero.
-			// 2. Except for bits 64 - 71, the 32 bits following the prefix are the bits of the embedded IPv4 address.
-			// 3. The remaining bits, if any, are the suffix bits, which SHOULD be zero.
-			
-			j = 0;
-			for( i = prefixLen; i < 16; ++i )
-			{
-				if( ( j < 4 ) && ( i != 8 ) )	outIPv6Addr[ i ] = v4Addr[ j++ ];
-				else							outIPv6Addr[ i ] = 0;
-			}
-			return( kNoErr );
-		}
-		default:
-			return( kSizeErr );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestHandleQuerierResult( DNSProxyTestRef me )
-{
-	OSStatus								err, verifyErr;
-	const uint8_t *							msgPtr;
-	size_t									msgLen;
-	const mdns_querier_result_type_t		resultType	= mdns_querier_get_result_type( me->querier );
-	Boolean									done		= false;
-	
-	if( resultType == mdns_querier_result_type_response )
-	{
-		msgPtr = mdns_querier_get_response_ptr( me->querier );
-		msgLen = mdns_querier_get_response_length( me->querier );
-		dpt_ulog( kLogLevelInfo, "Querier response: %.1{du:dnsmsg}\n", msgPtr, msgLen );
-	}
-	else
-	{
-		if( resultType == mdns_querier_result_type_error )
-		{
-			err = mdns_querier_get_error( me->querier );
-			if( !err ) err = kUnknownErr;
-		}
-		else
-		{
-			err = kUnexpectedErr;
-		}
-		dpt_ulog( kLogLevelError, "Querier result: %s, error: %#m\n", mdns_querier_get_result_type( me->querier ), err );
-		goto exit;
-	}
-	switch( me->queryParam )
-	{
-		case kDNSProxyTestQuery_A:
-		case kDNSProxyTestQuery_AAAA:
-		case kDNSProxyTestQuery_IPv6OnlyA:
-		case kDNSProxyTestQuery_IPv6OnlyAAAA:
-		case kDNSProxyTestQuery_IPv4OnlyAAAA:
-		case kDNSProxyTestQuery_AliasA:
-		case kDNSProxyTestQuery_AliasAAAA:
-		case kDNSProxyTestQuery_AliasIPv6OnlyA:
-		case kDNSProxyTestQuery_AliasIPv6OnlyAAAA:
-		case kDNSProxyTestQuery_AliasIPv4OnlyAAAA:
-		case kDNSProxyTestQuery_NXDomainA:
-		case kDNSProxyTestQuery_NXDomainAAAA:
-			verifyErr = _DNSProxyTestVerifyAddressResponse( msgPtr, msgLen, me->qname, me->qtype, me->responseCode,
-				me->aliasCount, me->answerCount,
-				me->synthesizedAAAA ? me->dns64Prefix : NULL,
-				me->synthesizedAAAA ? me->dns64PrefixBitLen : 0 );
-			break;
-		
-		case kDNSProxyTestQuery_ReverseIPv6:
-		case kDNSProxyTestQuery_ReverseIPv6NXDomain:
-		case kDNSProxyTestQuery_ReverseIPv6DNS64:
-		case kDNSProxyTestQuery_ReverseIPv6DNS64NXDomain:
-			verifyErr = _DNSProxyTestVerifyReverseIPv6Response( msgPtr, msgLen, me->qname, me->responseCode,
-				me->canonicalName, me->answerName );
-			break;
-		
-		default:
-			FatalErrorF( "Unhandled DNSProxyTestQuery value %ld", (long) me->queryParam );
-	}
-	err = _DNSProxyTestContinue( me, verifyErr, &done );
-	require_noerr( err, exit );
-	
-exit:
-	if( err || done ) _DNSProxyTestStop( me, err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSProxyTestVerifyAddressResponse(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inQName,
-		uint16_t		inQType,
-		int				inResponseCode,
-		unsigned int	inAliasCount,
-		unsigned int	inAnswerCount,
-		const uint8_t *	inDNS64Prefix,
-		int				inDNS64PrefixBitLen )
-{
-	OSStatus				err;
-	const DNSHeader *		hdr;
-	const uint8_t *			ptr;
-	const uint8_t *			answerSection;
-	unsigned int			flags, qCount, answerCount;
-	int						rcode;
-	uint16_t				qtype, qclass;
-	uint8_t					qname[ kDomainNameLengthMax ];
-	
-	require_action_quiet( inMsgLen >= kDNSHeaderLength, exit, err = kMalformedErr );
-	
-	hdr		= (const DNSHeader *) inMsgPtr;
-	flags	= DNSHeaderGetFlags( hdr );
-	rcode	= DNSFlagsGetRCode( flags );
-	require_action_quiet( rcode == inResponseCode, exit, err = kValueErr );
-	
-	qCount = DNSHeaderGetQuestionCount( hdr );
-	require_action_quiet( qCount == 1, exit, err = kCountErr );
-	
-	ptr = (const uint8_t *) &hdr[ 1 ];
-	err = DNSMessageExtractQuestion( inMsgPtr, inMsgLen, ptr, qname, &qtype, &qclass, &ptr );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( DomainNameEqual( qname, inQName ), exit, err = kNameErr );
-	require_action_quiet( qtype  == inQType, exit, err = kTypeErr );
-	require_action_quiet( qclass == kDNSClassType_IN, exit, kTypeErr );
-	
-	answerCount = DNSHeaderGetAnswerCount( hdr );
-	require_action_quiet( answerCount == ( inAliasCount + inAnswerCount ), exit, err = kCountErr );
-	
-	answerSection = ptr;
-	if( inAliasCount > 0 )
-	{
-		unsigned int		i;
-		const uint8_t *		parentDomain;
-		uint8_t				target[ kDomainNameLengthMax ];
-		
-		parentDomain = DomainNameGetNextLabel( inQName );
-		require_fatal( parentDomain, "Invalid qname '%{du:dname}' for non-zero alias count.", inQName );
-		
-		target[ 0 ] = 0;
-		err = DomainNameAppendDomainName( target, inQName, NULL );
-		require_noerr( err, exit );
-		
-		for( i = 0; i < inAliasCount; ++i )
-		{
-			unsigned int			j;
-			const unsigned int		aliasNumber	= inAliasCount - i;
-			Boolean					foundCNAME	= false;
-			
-			ptr = answerSection;
-			for( j = 0; j < answerCount; ++j )
-			{
-				const uint8_t *		rdataPtr;
-				unsigned int		nextAliasNumber;
-				uint16_t			type;
-				uint16_t			class;
-				uint8_t				name[ kDomainNameLengthMax ];
-				char				aliasLabelStr[ 32 ];
-				
-				err = DNSMessageExtractRecord( inMsgPtr, inMsgLen, ptr, name, &type, &class, NULL, &rdataPtr, NULL, &ptr );
-				require_noerr( err, exit );
-				
-				if( type  != kDNSRecordType_CNAME )		continue;
-				if( class != kDNSClassType_IN )		continue;
-				if( !DomainNameEqual( name, target ) )	continue;
-				
-				target[ 0 ] = 0;
-				nextAliasNumber = aliasNumber - 1;
-				if( nextAliasNumber >= 2 )
-				{
-					SNPrintF( aliasLabelStr, sizeof( aliasLabelStr ), "alias-%u", nextAliasNumber );
-					err = DomainNameAppendString( target, aliasLabelStr, NULL );
-					require_noerr( err, exit );
-				}
-				else if( nextAliasNumber == 1 )
-				{
-					SNPrintF( aliasLabelStr, sizeof( aliasLabelStr ), "alias" );
-					err = DomainNameAppendString( target, aliasLabelStr, NULL );
-					require_noerr( err, exit );
-				}
-				err = DomainNameAppendDomainName( target, parentDomain, NULL );
-				require_noerr( err, exit );
-				
-				err = DNSMessageExtractDomainName( inMsgPtr, inMsgLen, rdataPtr, name, NULL );
-				require_noerr( err, exit );
-				
-				if( !DomainNameEqual( name, target ) ) continue;
-				foundCNAME = true;
-				break;
-			}
-			require_action_quiet( foundCNAME, exit, err = kNotFoundErr );
-		}
-	}
-	if( inAnswerCount > 0 )
-	{
-		const uint8_t *		target;
-		unsigned int		i;
-		
-		if( inAliasCount > 0 )
-		{
-			target = DomainNameGetNextLabel( inQName );
-			require_fatal( target, "Invalid qname '%{du:dname}' for non-zero alias count.", inQName );
-		}
-		else
-		{
-			target = inQName;
-		}
-		for( i = 0; i < inAnswerCount; ++i )
-		{
-			unsigned int		j;
-			size_t				expectedLen;
-			uint8_t				expectedData[ 16 ];
-			Boolean				foundRecord = false;
-			
-			if( inQType == kDNSRecordType_A )
-			{
-				const uint32_t		ipv4Addr = kDNSServerBaseAddrV4 + ( i + 1 );
-				
-				WriteBig32Typed( expectedData, ipv4Addr );
-				expectedLen = 4;
-			}
-			else
-			{
-				if( inDNS64PrefixBitLen != 0 )
-				{
-					const uint32_t		ipv4Addr = kDNSServerBaseAddrV4 + ( i + 1 );
-					
-					err = _DNSProxyTestSynthesizeIPv6( inDNS64Prefix, inDNS64PrefixBitLen, ipv4Addr, expectedData );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					memcpy( expectedData, kDNSServerBaseAddrV6, 16 );
-					expectedData[ 15 ] = (uint8_t)( i + 1 );
-				}
-				expectedLen = 16;
-			}
-			ptr = answerSection;
-			for( j = 0; j < answerCount; ++j )
-			{
-				const uint8_t *		rdataPtr;
-				size_t				rdataLen;
-				uint16_t			type;
-				uint16_t			class;
-				uint8_t				name[ kDomainNameLengthMax ];
-				
-				err = DNSMessageExtractRecord( inMsgPtr, inMsgLen, ptr, name, &type, &class, NULL, &rdataPtr, &rdataLen,
-					&ptr );
-				require_noerr( err, exit );
-				
-				if( type  != inQType )												continue;
-				if( class != kDNSClassType_IN )										continue;
-				if( !DomainNameEqual( name, target ) )								continue;
-				if( !MemEqual( rdataPtr, rdataLen, expectedData, expectedLen ) )	continue;
-				foundRecord = true;
-				break;
-			}
-			require_action_quiet( foundRecord, exit, err = kNotFoundErr );
-		}
-	}
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_DNSProxyTestFindDomainNameRecord(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inRecordSection,
-		unsigned int	inRecordCount,
-		const uint8_t *	inRecordName,
-		uint16_t		inRecordType,
-		const uint8_t *	inRDataName );
-
-static OSStatus
-	_DNSProxyTestVerifyReverseIPv6Response(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inQName,
-		int				inResponseCode,
-		const uint8_t *	inCanonicalName,
-		const uint8_t *	inAnswerName )
-{
-	OSStatus				err;
-	const DNSHeader *		hdr;
-	const uint8_t *			ptr;
-	const uint8_t *			answerSection;
-	const uint8_t *			ownerName;
-	unsigned int			flags, qCount, answerCount, answerCountExpected;
-	int						rcode;
-	uint16_t				qtype, qclass;
-	uint8_t					qname[ kDomainNameLengthMax ];
-	
-	require_action_quiet( inMsgLen >= kDNSHeaderLength, exit, err = kMalformedErr );
-	
-	hdr		= (const DNSHeader *) inMsgPtr;
-	flags	= DNSHeaderGetFlags( hdr );
-	rcode	= DNSFlagsGetRCode( flags );
-	require_action_quiet( rcode == inResponseCode, exit, err = kValueErr );
-	
-	qCount = DNSHeaderGetQuestionCount( hdr );
-	require_action_quiet( qCount == 1, exit, err = kCountErr );
-	
-	ptr = (const uint8_t *) &hdr[ 1 ];
-	err = DNSMessageExtractQuestion( inMsgPtr, inMsgLen, ptr, qname, &qtype, &qclass, &ptr );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( DomainNameEqual( qname, inQName ), exit, err = kNameErr );
-	require_action_quiet( qtype  == kDNSRecordType_PTR, exit, err = kTypeErr );
-	require_action_quiet( qclass == kDNSClassType_IN, exit, kTypeErr );
-	
-	answerCountExpected	= ( inCanonicalName ? 1 : 0 ) + ( inAnswerName ? 1 : 0 );
-	answerCount			= DNSHeaderGetAnswerCount( hdr );
-	require_action_quiet( answerCount == answerCountExpected, exit, err = kCountErr );
-	
-	answerSection	= ptr;
-	ownerName		= inQName;
-	if( inCanonicalName )
-	{
-		err = _DNSProxyTestFindDomainNameRecord( inMsgPtr, inMsgLen, answerSection, answerCount, ownerName,
-			kDNSRecordType_CNAME, inCanonicalName );
-		require_noerr( err, exit );
-		
-		ownerName = inCanonicalName;
-	}
-	if( inAnswerName )
-	{
-		err = _DNSProxyTestFindDomainNameRecord( inMsgPtr, inMsgLen, answerSection, answerCount, ownerName,
-			kDNSRecordType_PTR, inAnswerName );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return( err );
-}
-
-static OSStatus
-	_DNSProxyTestFindDomainNameRecord(
-		const uint8_t *	inMsgPtr,
-		size_t			inMsgLen,
-		const uint8_t *	inRecordSection,
-		unsigned int	inRecordCount,
-		const uint8_t *	inRecordName,
-		uint16_t		inRecordType,
-		const uint8_t *	inRDataName )
-{
-	OSStatus			err;
-	const uint8_t *		ptr;
-	unsigned int		i;
-	Boolean				found = false;
-	
-	ptr = inRecordSection;
-	for( i = 0; i < inRecordCount; ++i )
-	{
-		const uint8_t *		rdataPtr;
-		uint16_t			type;
-		uint16_t			class;
-		uint8_t				name[ kDomainNameLengthMax ];
-		
-		err = DNSMessageExtractRecord( inMsgPtr, inMsgLen, ptr, name, &type, &class, NULL, &rdataPtr, NULL, &ptr );
-		require_noerr( err, exit );
-		
-		if( type  != inRecordType )						continue;
-		if( class != kDNSClassType_IN )					continue;
-		if( !DomainNameEqual( name, inRecordName ) )	continue;
-		
-		err = DNSMessageExtractDomainName( inMsgPtr, inMsgLen, rdataPtr, name, NULL );
-		require_noerr( err, exit );
-		
-		if( !DomainNameEqual( name, inRDataName ) ) continue;
-		found = true;
-		break;
-	}
-	err = found ? kNoErr : kNotFoundErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DNSProxyTestProbeGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inCtx )
-{
-	OSStatus					err;
-	const DNSProxyTestRef		me		= (DNSProxyTestRef) inCtx;
-	Boolean						done	= false;
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inHostname );
-	Unused( inTTL );
-	
-	if( ( inFlags & kDNSServiceFlagsAdd ) && !inError )
-	{
-		DNSServiceForget( &me->probeGAI );
-		dispatch_source_forget( &me->timer );
-		
-		dpt_ulog( kLogLevelInfo, "Probe: Got GAI address %##a for %s\n", inSockAddr, me->probeHostname );
-		
-		err = _DNSProxyTestContinue( me, kNoErr, &done );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err || done ) _DNSProxyTestStop( me, err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSProxyTestProbeTimerHandler( void *inCtx )
-{
-	const DNSProxyTestRef		me = (DNSProxyTestRef) inCtx;
-	
-	dpt_ulog( kLogLevelInfo, "Probe: GAI request for '%s' timed out.\n", me->probeHostname );
-	_DNSProxyTestStop( me, kNotPreparedErr );
-}
-
-//===========================================================================================================================
-//	RCodeTestCmd
-//===========================================================================================================================
-
-#define kRCodeTestMaxRCodeValue		15
-
-typedef struct RCodeTest *		RCodeTestRef;
-struct RCodeTest
-{
-	dispatch_queue_t			queue;				// Serial queue for test events.
-	dispatch_semaphore_t		doneSem;			// Semaphore to signal when the test is done.
-	dnssd_getaddrinfo_t			gai;				// Current subtest's GAI object. (Also used for probing test DNS server.)
-	dispatch_source_t			timer;				// Timer for enforcing time limit on current dnssd_getaddrinfo.
-	CFMutableDictionaryRef		report;				// Test's report, as a plist.
-	CFMutableArrayRef			subtestResults;		// Pointer to report's subtest results.
-	CFMutableArrayRef			gaiResults;			// Array of dnssd_getaddrinfo_result objects for the current GAI.
-	char *						hostname;			// Current subtest's hostname. (Also used for probing test DNS server.)
-	char *						description;		// Current subtest description.
-	NanoTime64					startTime;			// Current subtest's start time.
-	pid_t						serverPID;			// PID of spawned test DNS server.
-	OSStatus					error;				// Current test error.
-	int32_t						refCount;			// Test's reference count.
-	int							rcode;				// Argument to use in current subtest's hostname's RCODE label.
-	int							indexIdx;			// Index of argument to use in current subtest's hostname's Index label.
-	int							subtestCount;		// Number of subtests that have completed or are in progress.
-	int							subtestPassCount;	// Number of subtests that have passed so far.
-	Boolean						hostnameIsAlias;	// True if current subtest's hostname is an alias.
-	Boolean						hostnameHasAddr;	// True if current subtest's hostname that has an IPv4 address.
-	Boolean						done;				// True if all subtests have completed.
-};
-
-ulog_define_ex( kDNSSDUtilIdentifier, RCodeTest, kLogLevelInfo, kLogFlags_None, "RCodeTest", NULL );
-#define rct_ulog( LEVEL, ... )		ulog( &log_category_from_name( RCodeTest ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	_RCodeTestCreate( RCodeTestRef *outTest );
-static OSStatus	_RCodeTestRun( RCodeTestRef inTest, Boolean *outPassed );
-static void		_RCodeTestRetain( RCodeTestRef inTest );
-static void		_RCodeTestRelease( RCodeTestRef inTest );
-
-static void	RCodeTestCmd( void )
-{
-	OSStatus				err;
-	OutputFormatType		outputFormat;
-	RCodeTestRef			test	= NULL;
-	Boolean					passed	= false;
-	
-	err = CheckRootUser();
-	require_noerr_quiet( err, exit );
-	
-	err = OutputFormatFromArgString( gRCodeTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _RCodeTestCreate( &test );
-	require_noerr( err, exit );
-	
-	err = _RCodeTestRun( test, &passed );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( test->report, outputFormat, gRCodeTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _RCodeTestRelease( test );
-    gExitCode = err ? 1 : ( passed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RCodeTestCreate( RCodeTestRef *outTest )
-{
-	OSStatus			err;
-	RCodeTestRef		obj;
-	
-	obj = (RCodeTestRef) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	obj->error		= kInProgressErr;
-	obj->serverPID	= -1;
-	
-	obj->queue = dispatch_queue_create( "com.apple.dnssdutil.rcode-test", DISPATCH_QUEUE_SERIAL );
-	require_action( obj->queue, exit, err = kNoResourcesErr );
-	
-	obj->doneSem = dispatch_semaphore_create( 0 );
-	require_action( obj->doneSem, exit, err = kNoResourcesErr );
-	
-	obj->report = CFDictionaryCreateMutable( NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-	require_action( obj->report, exit, err = kNoMemoryErr );
-	
-	obj->indexIdx = -1;
-	*outTest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _RCodeTestRelease( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void		_RCodeTestStart( void *inCtx );
-static void		_RCodeTestStop( RCodeTestRef inTest, OSStatus inError );
-static OSStatus	_RCodeTestStartSubtest( RCodeTestRef inTest );
-static OSStatus	_RCodeTestContinue( RCodeTestRef inType, OSStatus inSubtestError, Boolean *outDone );
-static Boolean	_RCodeTestRCodeIsGood( const int inRCode );
-
-static OSStatus	_RCodeTestRun( RCodeTestRef me, Boolean *outPassed )
-{
-	Boolean		passed;
-	
-	dispatch_async_f( me->queue, me, _RCodeTestStart );
-	dispatch_semaphore_wait( me->doneSem, DISPATCH_TIME_FOREVER );
-	
-	passed = ( !me->error && ( me->subtestPassCount == me->subtestCount ) ) ? true : false;
-	CFDictionarySetBoolean( me->report, CFSTR( "pass" ), passed );
-	rct_ulog( kLogLevelInfo, "Test result: %s\n", passed ? "pass" : "fail" );
-	
-	if( outPassed ) *outPassed = passed;
-	return( me->error );
-}
-
-//===========================================================================================================================
-
-static void	_RCodeTestRetain( const RCodeTestRef me )
-{
-	atomic_add_32( &me->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_RCodeTestRelease( const RCodeTestRef me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->gai );
-		check( !me->timer );
-		check( !me->subtestResults );
-		check( !me->gaiResults );
-		check( !me->hostname );
-		check( !me->description );
-		check( me->serverPID < 0 );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->doneSem );
-		ForgetCF( &me->report );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-
-#define kRCodeTestProbeQueryTimeoutSecs		5
-
-static void	_RCodeTestHandleGAIProbeResults( RCodeTestRef inTest, dnssd_getaddrinfo_result_t *inResults, size_t inCount );
-static void	_RCodeTestProbeQueryTimerHandler( void *inCtx );
-
-static void	_RCodeTestStart( void * const inCtx )
-{
-	OSStatus				err;
-	const RCodeTestRef		me			= (RCodeTestRef) inCtx;
-	char *					serverCmd	= NULL;
-	dnssd_getaddrinfo_t		gai;
-	NanoTime64				startTime;
-	char					startTimeStr[ 32 ];
-	char					tag[ 6 + 1 ];
-	
-	startTime = NanoTimeGetCurrent();
-	rct_ulog( kLogLevelInfo, "Starting test\n" );
-	
-	// The "dnssdutil server" command will create a resolver entry for the server's "d.test." domain containing an array
-	// of the server's IP addresses. Because configd favors IPv6 addresses, when there's a mix of IPv4 and IPv6
-	// addresses, configd may rearrange the array in order to ensure that IPv6 addresses come before the IPv4 addresses.
-	// To preserve the original address order, the server is specified to run in IPv6-only mode. This way,
-	// mDNSResponder's view of the address will be such that address with index value 1 is first, address with index
-	// value 2 is second, etc.
-	
-	serverCmd = NULL;
-	ASPrintF( &serverCmd,
-		"dnssdutil server --loopback --follow %lld --responseDelay 20 --ipv6 --extraIPv6 3", (int64_t) getpid() );
-	require_action_quiet( serverCmd, exit, err = kNoMemoryErr );
-	
-	err = _SpawnCommand( &me->serverPID, "/dev/null", "/dev/null", "%s", serverCmd );
-	require_noerr( err, exit );
-	
-	check( !me->hostname );
-	me->hostname = NULL;
-	ASPrintF( &me->hostname, "tag-rcode-test-probe-%s.ipv4.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->hostname, exit, err = kNoMemoryErr );
-	
-	check( !me->gai );
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->hostname );
-	dnssd_getaddrinfo_set_flags( me->gai, 0 );
-	dnssd_getaddrinfo_set_interface_index( me->gai, kDNSServiceInterfaceIndexAny );
-	dnssd_getaddrinfo_set_protocols( me->gai, kDNSServiceProtocol_IPv4 );
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	gai = me->gai;
-	dnssd_retain( gai );
-	_RCodeTestRetain( me );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-	{
-		require_return( me->gai == gai );
-		_RCodeTestHandleGAIProbeResults( me, inResults, inCount );
-	} );
-	dnssd_getaddrinfo_set_event_handler( me->gai,
-	^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-	{
-		if( inEvent == dnssd_event_invalidated )
-		{
-			dnssd_release( gai );
-			_RCodeTestRelease( me );
-		}
-		else if( inEvent == dnssd_event_error )
-		{
-			require_return( me->gai == gai );
-			rct_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-			_RCodeTestStop( me, inGAIError );
-		}
-	} );
-	dnssd_getaddrinfo_activate( me->gai );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kRCodeTestProbeQueryTimeoutSecs ),
-		kRCodeTestProbeQueryTimeoutSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ),
-		me->queue, _RCodeTestProbeQueryTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	dispatch_resume( me->timer );
-	
-	_NanoTime64ToTimestamp( startTime, startTimeStr, sizeof( startTimeStr ) );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->report,
-		"%kO=%s"	// startTime
-		"%kO=%s"	// serverCmd
-		"%kO=%s"	// probeHostname
-		"%kO=[%@]",	// results
-		CFSTR( "startTime" ),		startTimeStr,
-		CFSTR( "serverCmd" ),		serverCmd,
-		CFSTR( "probeHostname" ),	me->hostname,
-		CFSTR( "results" ),			&me->subtestResults );
-	require_noerr( err, exit );
-	
-exit:
-	FreeNullSafe( serverCmd );
-	if( err ) _RCodeTestStop( me, err );
-}
-
-static void
-	_RCodeTestHandleGAIProbeResults(
-		const RCodeTestRef					me,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	size_t		i;
-	Boolean		startSubtests = false;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		if( dnssd_getaddrinfo_result_get_type( result ) == dnssd_getaddrinfo_result_type_add )
-		{
-			rct_ulog( kLogLevelInfo, "Probe GAI got %##a for %s\n",
-				dnssd_getaddrinfo_result_get_address( result ), me->hostname );
-			startSubtests = true;
-			break;
-		}
-	}
-	if( startSubtests )
-	{
-		OSStatus		err;
-		
-		dnssd_getaddrinfo_forget( &me->gai );
-		dispatch_source_forget( &me->timer );
-		err = _RCodeTestStartSubtest( me );
-		if( err ) _RCodeTestStop( me, err );
-	}
-}
-
-static void	_RCodeTestProbeQueryTimerHandler( void * const inCtx )
-{
-	const RCodeTestRef		me = (RCodeTestRef) inCtx;
-	
-	rct_ulog( kLogLevelInfo, "Probe GAI request for '%s' timed out.\n", me->hostname );
-	_RCodeTestStop( me, kNotPreparedErr );
-}
-
-//===========================================================================================================================
-
-static void	_RCodeTestStop( RCodeTestRef me, OSStatus inError )
-{
-	OSStatus		err;
-	NanoTime64		endTime;
-	char			endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	me->error = inError;
-	rct_ulog( kLogLevelInfo, "Stopping test with error: %#m\n", me->error );
-	
-	dnssd_getaddrinfo_forget( &me->gai );
-	dispatch_source_forget( &me->timer );
-	me->subtestResults = NULL;
-	ForgetCF( &me->gaiResults );
-	ForgetMem( &me->hostname );
-	ForgetMem( &me->description );
-	if( me->serverPID >= 0 )
-	{
-		OSStatus		killErr;
-		
-		killErr = kill( me->serverPID, SIGTERM );
-		killErr = map_global_noerr_errno( killErr );
-		check_noerr( killErr );
-		me->serverPID = -1;
-	}
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->report,
-		"%kO=%s"		// endTime
-		"%kO=%lli"		// subtestCount
-		"%kO=%lli",		// subtestPassCount
-		CFSTR( "endTime" ),				endTimeStr,
-		CFSTR( "subtestCount" ),		(int64_t) me->subtestCount,
-		CFSTR( "subtestPassCount" ),	(int64_t) me->subtestPassCount );
-	check_noerr( err );
-	if( err && !me->error ) me->error = err;
-	dispatch_semaphore_signal( me->doneSem );
-}
-
-//===========================================================================================================================
-
-#define kRCodeSubtestRegularTimeLimitSecs		4
-#define kRCodeSubtestExtendedTimeLimitSecs		12	// Allow three seconds for each of the four server addresses.
-
-static void	_RCodeSubtestHandleGAIResults( RCodeTestRef inTest, dnssd_getaddrinfo_result_t *inResults, size_t inCount );
-static void	_RCodeSubtestTimerHandler( void *inCtx );
-
-static const void *	_DNSSDObjectCFArrayCallbackRetain( CFAllocatorRef inAllocator, const void *inObject );
-static void			_DNSSDObjectCFArrayCallbackRelease( CFAllocatorRef inAllocator, const void *inObject );
-
-static const CFArrayCallBacks kDNSSDObjectArrayCallbacks =
-{
-	.version	= 0,
-	.retain		= _DNSSDObjectCFArrayCallbackRetain,
-	.release	= _DNSSDObjectCFArrayCallbackRelease
-};
-
-// Arguments to use for Index labels. Since the test uses a test DNS server with four IPv6 addresses, which
-// mDNSResponder views as four different servers, this is an arbitrary mix of the four possible index values. An Index
-// label makes it so that only the server specified by the Index label's argument responds with the correct response.
-// The point of the mix is to force mDNSResponder to have to send queries to more than one server before it gets the
-// right response.
-
-static const int		kRCodeTestIndexArguments[] = { 2, 4, 1, 3, 2, 1, 4, 3 };
-#define kRCodeTestMaxIndexArgumentIndex		( countof( kRCodeTestIndexArguments ) - 1 )
-
-static OSStatus	_RCodeTestStartSubtest( const RCodeTestRef me )
-{
-	OSStatus				err;
-	dnssd_getaddrinfo_t		gai;
-	const char *			rcodeStr;
-	int						index;
-	unsigned int			timeLimitSecs;
-	char					rcodeStrBuf[ 32 ];
-	char					indexLabelStr[ 32 ];
-	char					rcodeLabelStr[ 32 ];
-	char					tag[ 6 + 1 ];
-	
-	require_action_quiet( !me->done, exit, err = kInternalErr );
-	
-	check( !me->gai );
-	check( !me->timer );
-	
-	me->startTime = NanoTimeGetCurrent();
-	
-	if( me->indexIdx < 0 )
-	{
-		index = -1;
-		indexLabelStr[ 0 ] = '\0';
-		require_fatal( ( me->rcode >= 0 ) && ( me->rcode <= kRCodeTestMaxRCodeValue ),
-			"Unexpected subtest rcode value %d.", me->rcode );
-	}
-	else
-	{
-		index = kRCodeTestIndexArguments[ me->indexIdx ];
-		SNPrintF( indexLabelStr, sizeof( indexLabelStr ), "index-%d.", index );
-		me->hostnameHasAddr = true;
-		me->hostnameIsAlias = true;
-		require_fatal( ( me->rcode >= -1 ) && ( me->rcode <= kRCodeTestMaxRCodeValue ),
-			"Unexpected subtest rcode value %d.", me->rcode );
-	}
-	if( me->rcode > 0 )
-	{
-		SNPrintF( rcodeLabelStr, sizeof( rcodeLabelStr ), "rcode-%d.", me->rcode );
-	}
-	else
-	{
-		rcodeLabelStr[ 0 ] = '\0';
-	}
-	ForgetMem( &me->hostname );
-	ASPrintF( &me->hostname, "%s%s%scount-%d.tag-rcode-test-%s.d.test.",
-		me->hostnameIsAlias ? "alias." : "", indexLabelStr, rcodeLabelStr, me->hostnameHasAddr ? 1 : 0,
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->hostname, exit, err = kNoMemoryErr );
-	
-	CFReleaseNullSafe( me->gaiResults );
-	me->gaiResults = CFArrayCreateMutable( NULL, 0, &kDNSSDObjectArrayCallbacks );
-	require_action( me->gaiResults, exit, err = kNoMemoryErr );
-	
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->hostname );
-	dnssd_getaddrinfo_set_flags( me->gai, kDNSServiceFlagsReturnIntermediates );
-	dnssd_getaddrinfo_set_interface_index( me->gai, kDNSServiceInterfaceIndexAny );
-	dnssd_getaddrinfo_set_protocols( me->gai, kDNSServiceProtocol_IPv4 );
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	gai = me->gai;
-	dnssd_retain( gai );
-	_RCodeTestRetain( me );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-	{
-		require_return( me->gai == gai );
-		_RCodeSubtestHandleGAIResults( me, inResults, inCount );
-	} );
-	dnssd_getaddrinfo_set_event_handler( gai,
-	^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-	{
-		if( inEvent == dnssd_event_invalidated )
-		{
-			dnssd_release( gai );
-			_RCodeTestRelease( me );
-		}
-		else if( inEvent == dnssd_event_error )
-		{
-			OSStatus		testErr;
-			Boolean			done;
-			
-			require_return( me->gai == gai );
-			rct_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-			testErr = _RCodeTestContinue( me, inGAIError, &done );
-			if( testErr || done ) _RCodeTestStop( me, testErr );
-		}
-	} );
-	
-	// If an Index label is being used without an RCode label, then only the server specified by the index label will
-	// respond to the query, so we need more time to allow for query retries due to unresponsive servers.
-	
-	if( ( index > 0 ) && ( me->rcode < 0 ) )
-	{
-		timeLimitSecs = kRCodeSubtestExtendedTimeLimitSecs;
-	}
-	else
-	{
-		timeLimitSecs = kRCodeSubtestRegularTimeLimitSecs;
-	}
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( timeLimitSecs ),
-		timeLimitSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 20 ),
-		me->queue, _RCodeSubtestTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	
-	rcodeStr = DNSRCodeToString( me->rcode );
-	if( !rcodeStr )
-	{
-		SNPrintF( rcodeStrBuf, sizeof( rcodeStrBuf ), "RCODE%d", me->rcode );
-		rcodeStr = rcodeStrBuf;
-	}
-	ForgetMem( &me->description );
-	if( me->indexIdx < 0 )
-	{
-		ASPrintF( &me->description, "DNS response with RCODE %s (%d), %s CNAME record, and %s A record from all servers",
-			rcodeStr, me->rcode, me->hostnameIsAlias ? "one" : "no", me->hostnameHasAddr ? "one" : "no" );
-		require_action( me->description, exit, err = kNoMemoryErr );
-	}
-	else
-	{
-		int		n;
-		
-		ASPrintF( &me->description, "DNS response with RCODE NoError (0), %s CNAME record, and %s A record from server #%d.",
-			me->hostnameIsAlias ? "one" : "no", me->hostnameHasAddr ? "one" : "no", index );
-		require_action( me->description, exit, err = kNoMemoryErr );
-		
-		if( me->rcode < 0 )
-		{
-			n = AppendPrintF( &me->description, " No DNS respones from all other servers." );
-			require_action( n >= 0, exit, err = kNoMemoryErr );
-		}
-		else
-		{
-			n = AppendPrintF( &me->description, " DNS responses with RCODE %s (%d) and no records from all other servers.",
-				rcodeStr, me->rcode );
-			require_action( n >= 0, exit, err = kNoMemoryErr );
-		}
-	}
-	++me->subtestCount;
-	rct_ulog( kLogLevelInfo, "Starting subtest #%d: %s\n", me->subtestCount, me->description );
-	
-	dnssd_getaddrinfo_activate( me->gai );
-	dispatch_resume( me->timer );
-	
-exit:
-	return( err );
-}
-
-static void
-	_RCodeSubtestHandleGAIResults(
-		const RCodeTestRef					me,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	size_t			i;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		rct_ulog( kLogLevelInfo, "GAI result -- %@\n", result );
-		CFArrayAppendValue( me->gaiResults, result );
-	}
-}
-
-static void	_RCodeSubtestTimerHandler( void * const inCtx )
-{
-	OSStatus							err;
-	const RCodeTestRef					me = (RCodeTestRef) inCtx;
-	dnssd_getaddrinfo_result_t			result;
-	const sockaddr_ip *					sip;
-	const uint8_t *						targetName;
-	CFIndex								n;
-	dnssd_getaddrinfo_result_type_t		resultType;
-	int									expectedResultCount;
-	uint8_t								hostname[ kDomainNameLengthMax ];
-	uint8_t								actualHostname[ kDomainNameLengthMax ];
-	Boolean								expectAddress, expectCanonName, done;
-	
-	// mDNSResponder has traditionally ignored responses with RCODEs not equal to NoError, NXDomain, or NotAuth.
-	// Such responses result in a kDNSServiceErr_NoSuchRecord error, or NoAddress in the case of dnssd_getaddrinfo.
-	
-	if( ( me->indexIdx >= 0 ) || _RCodeTestRCodeIsGood( me->rcode ) )
-	{
-		expectAddress		= me->hostnameHasAddr;
-		expectCanonName		= me->hostnameIsAlias;
-		expectedResultCount	= 1;
-	}
-	else
-	{
-		expectAddress		= false;
-		expectCanonName		= false;
-		expectedResultCount	= 1;
-	}
-	n = CFArrayGetCount( me->gaiResults );
-	require_action_quiet( n == expectedResultCount, exit, err = kCountErr );
-	
-	if( n != 0 )
-	{
-		result = (dnssd_getaddrinfo_result_t) CFArrayGetValueAtIndex( me->gaiResults, 0 );
-		resultType = dnssd_getaddrinfo_result_get_type( result );
-		
-		sip = (const sockaddr_ip *) dnssd_getaddrinfo_result_get_address( result );
-		require_action_quiet( sip->sa.sa_family == AF_INET, exit, err = kAddressErr );
-		
-		if( expectAddress )
-		{
-			require_action_quiet( resultType == dnssd_getaddrinfo_result_type_add, exit, err = kTypeErr );
-			require_action_quiet( ntohl( sip->v4.sin_addr.s_addr ) == ( kDNSServerBaseAddrV4 + 1 ), exit, err = kAddressErr );
-		}
-		else
-		{
-			require_action_quiet( resultType == dnssd_getaddrinfo_result_type_no_address, exit, err = kTypeErr );
-		}
-		err = DomainNameFromString( hostname, me->hostname, NULL );
-		require_noerr_fatal( err, "Failed to convert hostname to DNS wire format -- hostname: %s, error: %#m",
-			me->hostname, err );
-		
-		err = DomainNameFromString( actualHostname, dnssd_getaddrinfo_result_get_actual_hostname( result ), NULL );
-		require_noerr_quiet( err, exit );
-		
-		if( expectCanonName )
-		{
-			size_t		firstLabelLen;
-			
-			firstLabelLen = hostname[ 0 ];
-			require_fatal( firstLabelLen > 0, "Hostname's first label length is zero -- hostname: %s", me->hostname );
-			
-			targetName = &hostname[ 1 + firstLabelLen ];
-		}
-		else
-		{
-			targetName = hostname;
-		}
-		require_action_quiet( DomainNameEqual( actualHostname, targetName ), exit, err = kNameErr );
-	}
-	err = kNoErr;
-	
-exit:
-	err = _RCodeTestContinue( me, err, &done );
-	if( err || done ) _RCodeTestStop( me, err );
-}
-
-static const void *	_DNSSDObjectCFArrayCallbackRetain( __unused const CFAllocatorRef inAllocator, const void *inObject )
-{
-	dnssd_retain( (dnssd_object_t) inObject );
-	return inObject;
-}
-
-static void	_DNSSDObjectCFArrayCallbackRelease( __unused const CFAllocatorRef inAllocator, const void *inObject )
-{
-	dnssd_release( (dnssd_object_t) inObject );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RCodeTestStopSubtest( RCodeTestRef inTest, OSStatus inError );
-
-static OSStatus	_RCodeTestContinue( const RCodeTestRef me, OSStatus inSubtestError, Boolean *outDone )
-{
-	OSStatus		err;
-	
-	require_action_quiet( !me->done, exit, err = kNoErr );
-	
-	err = _RCodeTestStopSubtest( me, inSubtestError );
-	require_noerr( err, exit );
-	require_action_quiet( !me->done, exit, err = kNoErr );
-	
-	err = _RCodeTestStartSubtest( me );
-	require_noerr( err, exit );
-	
-exit:
-	if( outDone ) *outDone = me->done;
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RCodeTestStopSubtest( const RCodeTestRef me, const OSStatus inError )
-{
-	OSStatus				err;
-	NanoTime64				endTime;
-	CFMutableArrayRef		gaiResultDescs;
-	char					errorStr[ 128 ];
-	char					startTimeStr[ 32 ];
-	char					endTimeStr[ 32 ];
-	CFIndex					i, n;
-	
-	dnssd_getaddrinfo_forget( &me->gai );
-	dispatch_source_forget( &me->timer );
-	
-	endTime = NanoTimeGetCurrent();
-	
-	if( !inError ) ++me->subtestPassCount;
-	
-	rct_ulog( kLogLevelInfo, "Subtest #%d result: %s (pass rate: %d/%d)\n",
-		me->subtestCount, inError ? "fail" : "pass", me->subtestPassCount, me->subtestCount );
-	
-	_NanoTime64ToTimestamp( me->startTime, startTimeStr, sizeof( startTimeStr ) );
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	SNPrintF( errorStr, sizeof( errorStr ), "%m", inError );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->subtestResults,
-		"{"
-			"%kO=%s"		// description
-			"%kO=%s"		// startTime
-			"%kO=%s"		// endTime
-			"%kO=%s"		// hostname
-			"%kO=%b"		// pass
-			"%kO="			// error
-			"{"
-				"%kO=%lli"	// code
-				"%kO=%s"	// description
-			"}"
-			"%kO=[%@]"		// GAIResults
-		"}",
-		CFSTR( "description" ),	me->description,
-		CFSTR( "startTime" ),	startTimeStr,
-		CFSTR( "endTime" ),		endTimeStr,
-		CFSTR( "hostname" ),	me->hostname,
-		CFSTR( "pass" ),		!inError ? true : false,
-		CFSTR( "error" ),
-		CFSTR( "code" ),		(int64_t) inError,
-		CFSTR( "description" ),	errorStr,
-		CFSTR( "GAIResults" ),	&gaiResultDescs );
-	require_noerr( err, exit );
-	
-	n = CFArrayGetCount( me->gaiResults );
-	for( i = 0; i < n; ++ i )
-	{
-		dnssd_getaddrinfo_result_t		result = (dnssd_getaddrinfo_result_t) CFArrayGetValueAtIndex( me->gaiResults, i );
-		char *							resultDesc;
-		
-		resultDesc = dnssd_copy_description( result );
-		require_action_quiet( resultDesc, exit, err = kNoMemoryErr );
-		
-		err = CFPropertyListAppendFormatted( NULL, gaiResultDescs, "%s", resultDesc );
-		ForgetMem( &resultDesc );
-		require_noerr( err, exit );
-	}
-	
-	if( me->indexIdx < 0 )
-	{
-		// Each subtest is one of the 64 possible combinations of
-		// rcode ∈ {0, 1, 2, …, 15}, hostnameIsAlias ∈ {false, true}, hostnameHasAddr ∈ {false, true}.
-		
-		if( !me->hostnameHasAddr )
-		{
-			me->hostnameHasAddr = true;
-		}
-		else
-		{
-			me->hostnameHasAddr = false;
-			if( !me->hostnameIsAlias )
-			{
-				me->hostnameIsAlias = true;
-			}
-			else
-			{
-				me->hostnameIsAlias = false;
-				if( me->rcode < kRCodeTestMaxRCodeValue )
-				{
-					++me->rcode;
-				}
-				else
-				{
-					me->indexIdx	= 0;	// At this point we move on to using Index labels.
-					me->rcode		= -1;	// Start with rcode set to -1 to indicate no RCode label.
-				}
-			}
-		}
-	}
-	else
-	{
-		if( me->indexIdx < (int) kRCodeTestMaxIndexArgumentIndex )
-		{
-			++me->indexIdx;
-		}
-		else
-		{
-			me->indexIdx = 0;
-			
-			// When using Index labels to limit responses to one server, we want the other servers to respond
-			// with bad RCODEs, so if the current RCODE value is good, try incrementing again.
-			
-			do
-			{
-				if( me->rcode < kRCodeTestMaxRCodeValue )
-				{
-					++me->rcode;
-				}
-				else
-				{
-					me->done = true;
-				}
-				
-			}	while( !me->done && _RCodeTestRCodeIsGood( me->rcode ) );
-		}
-	}
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static Boolean	_RCodeTestRCodeIsGood( const int inRCode )
-{
-	return( ( inRCode == kDNSRCode_NoError ) || ( inRCode == kDNSRCode_NXDomain ) || ( inRCode == kDNSRCode_NotAuth ) );
-}
-
-//===========================================================================================================================
-//	DNSQueryTestCmd
-//===========================================================================================================================
-
-typedef uint32_t DNSQueryTestGAIOpts;
-#define kDNSQueryTestGAIOpts_None			0
-#define kDNSQueryTestGAIOpts_WantIPv4		( 1U << 0 )
-#define kDNSQueryTestGAIOpts_WantIPv6		( 1U << 1 )
-
-typedef struct
-{
-	unsigned int			cnameCount;
-	unsigned int			addrCount;
-	DNSQueryTestGAIOpts		gaiOpts;
-	
-}	DNSQuerySubtestParams;
-
-const DNSQuerySubtestParams		kDNSQuerySubtestParams[] =
-{
-	{ .cnameCount = 0, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 },
-	{ .cnameCount = 0, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 0, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 | kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 3, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 },
-	{ .cnameCount = 3, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 3, .addrCount = 1, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 | kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 0, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 },
-	{ .cnameCount = 0, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 0, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 | kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 3, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 },
-	{ .cnameCount = 3, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv6 },
-	{ .cnameCount = 3, .addrCount = 3, .gaiOpts = kDNSQueryTestGAIOpts_WantIPv4 | kDNSQueryTestGAIOpts_WantIPv6 }
-};
-
-typedef struct DNSQueryTest *		DNSQueryTestRef;
-struct DNSQueryTest
-{
-	dispatch_queue_t			queue;				// Serial queue for test events.
-	dispatch_semaphore_t		doneSem;			// Semaphore to signal when the test is done.
-	dnssd_getaddrinfo_t			gai;				// Current subtest's GAI object. (Also used for probing test DNS server.)
-	dispatch_source_t			timer;				// Timer for enforcing time limit on current dnssd_getaddrinfo.
-	CFMutableDictionaryRef		report;				// Test's report, as a plist.
-	CFMutableArrayRef			subtestResults;		// Pointer to report's subtest results.
-	CFMutableArrayRef			gaiResults;			// All dnssd_getaddrinfo_result objects from the current GAI.
-	CFMutableArrayRef			unexpectedResults;	// Unexpected dnssd_getaddrinfo_result from the current GAI.
-	CFMutableArrayRef			missingAddrs;		// Address results missing from the current GAI.
-	CFMutableArrayRef			queryCountStats;	// Stats regarding a subtests query counts.
-	char *						hostname;			// Current subtest's hostname. (Also used for probing test DNS server.)
-	char *						domain;				// High-level domain of current hostname.
-	char *						description;		// Current subtest description.
-	pcap_t *					pcap;				// Captures traffic between mDNSResponder and test DNS server.
-	NanoTime64					startTime;			// Current subtest's start time.
-	size_t						subtestIndex;		// Index of the current subtest.
-	pid_t						serverPID;			// PID of spawned test DNS server.
-	uint32_t					addressOffset;		// Current subtest's address offset for hostname addresses.
-	int32_t						refCount;			// Test's reference count.
-	OSStatus					error;				// Current test error.
-	int							subtestCount;		// Number of subtests that have completed or are in progress.
-	int							subtestPassCount;	// Number of subtests that have passed so far.
-	Boolean						haveBadQueryCounts;	// True if the current subtest's query counts are incorrect.
-	Boolean						done;				// True if all subtests have completed.
-};
-
-ulog_define_ex( kDNSSDUtilIdentifier, DNSQueryTest, kLogLevelInfo, kLogFlags_None, "DNSQueryTest", NULL );
-#define dqt_ulog( LEVEL, ... )		ulog( &log_category_from_name( DNSQueryTest ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	_DNSQueryTestCreate( DNSQueryTestRef *outTest );
-static OSStatus	_DNSQueryTestRun( DNSQueryTestRef inTest, Boolean *outPassed );
-static void		_DNSQueryTestRetain( DNSQueryTestRef inTest );
-static void		_DNSQueryTestRelease( DNSQueryTestRef inTest );
-
-static void	DNSQueryTestCmd( void )
-{
-	OSStatus				err;
-	OutputFormatType		outputFormat;
-	DNSQueryTestRef			test	= NULL;
-	Boolean					passed	= false;
-	
-	err = CheckRootUser();
-	require_noerr_quiet( err, exit );
-	
-	err = OutputFormatFromArgString( gDNSQueryTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _DNSQueryTestCreate( &test );
-	require_noerr( err, exit );
-	
-	err = _DNSQueryTestRun( test, &passed );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( test->report, outputFormat, gDNSQueryTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _DNSQueryTestRelease( test );
-    gExitCode = err ? 1 : ( passed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSQueryTestCreate( DNSQueryTestRef * const outTest )
-{
-	OSStatus			err;
-	DNSQueryTestRef		obj;
-	
-	obj = (DNSQueryTestRef) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	obj->error		= kInProgressErr;
-	obj->serverPID	= -1;
-	
-	obj->queue = dispatch_queue_create( "com.apple.dnssdutil.dns-query-test", DISPATCH_QUEUE_SERIAL );
-	require_action( obj->queue, exit, err = kNoResourcesErr );
-	
-	obj->doneSem = dispatch_semaphore_create( 0 );
-	require_action( obj->doneSem, exit, err = kNoResourcesErr );
-	
-	obj->report = CFDictionaryCreateMutable( NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-	require_action( obj->report, exit, err = kNoMemoryErr );
-	
-	*outTest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _DNSQueryTestRelease( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void		_DNSQueryTestStart( void *inCtx );
-static void		_DNSQueryTestStop( DNSQueryTestRef inTest, OSStatus inError );
-static OSStatus	_DNSQueryTestStartSubtest( DNSQueryTestRef inTest );
-static OSStatus	_DNSQueryTestContinue( DNSQueryTestRef inType, OSStatus inSubtestError );
-
-static OSStatus	_DNSQueryTestRun( const DNSQueryTestRef me, Boolean * const outPassed )
-{
-	Boolean		passed;
-	
-	dispatch_async_f( me->queue, me, _DNSQueryTestStart );
-	dispatch_semaphore_wait( me->doneSem, DISPATCH_TIME_FOREVER );
-	
-	passed = ( !me->error && ( me->subtestPassCount == me->subtestCount ) ) ? true : false;
-	CFDictionarySetBoolean( me->report, CFSTR( "pass" ), passed );
-	dqt_ulog( kLogLevelInfo, "Test result: %s\n", passed ? "pass" : "fail" );
-	
-	if( outPassed ) *outPassed = passed;
-	return( me->error );
-}
-
-//===========================================================================================================================
-
-static void	_DNSQueryTestRetain( const DNSQueryTestRef me )
-{
-	atomic_add_32( &me->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_DNSQueryTestRelease( const DNSQueryTestRef me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->gai );
-		check( !me->timer );
-		check( !me->subtestResults );
-		check( !me->gaiResults );
-		check( !me->unexpectedResults );
-		check( !me->missingAddrs );
-		check( !me->queryCountStats );
-		check( !me->hostname );
-		check( !me->domain );
-		check( !me->description );
-		check( !me->pcap );
-		check( me->serverPID < 0 );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->doneSem );
-		ForgetCF( &me->report );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-
-#define kDNSQueryTestProbeQueryTimeoutSecs		5
-
-static void
-	_DNSQueryTestHandleGAIProbeResults(
-		DNSQueryTestRef					inTest,
-		dnssd_getaddrinfo_result_t *	inResults,
-		size_t							inCount );
-static void	_DNSQueryTestProbeQueryTimerHandler( void *inCtx );
-static void	_DNSQueryTestSubtestCleanup( DNSQueryTestRef test );
-
-static void	_DNSQueryTestStart( void * const inCtx )
-{
-	OSStatus					err;
-	const DNSQueryTestRef		me			= (DNSQueryTestRef) inCtx;
-	char *						serverCmd	= NULL;
-	dnssd_getaddrinfo_t			gai;
-	NanoTime64					startTime;
-	char						startTimeStr[ 32 ];
-	char						tag[ 6 + 1 ];
-	
-	startTime = NanoTimeGetCurrent();
-	dqt_ulog( kLogLevelInfo, "Starting test\n" );
-	
-	serverCmd = NULL;
-	ASPrintF( &serverCmd, "dnssdutil server --loopback --follow %lld --responseDelay 10", (int64_t) getpid() );
-	require_action_quiet( serverCmd, exit, err = kNoMemoryErr );
-	
-	err = _SpawnCommand( &me->serverPID, "/dev/null", "/dev/null", "%s", serverCmd );
-	require_noerr( err, exit );
-	
-	check( !me->hostname );
-	ASPrintF( &me->hostname, "tag-dns-query-test-probe-%s.ipv4.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->hostname, exit, err = kNoMemoryErr );
-	
-	check( !me->gai );
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->hostname );
-	dnssd_getaddrinfo_set_flags( me->gai, 0 );
-	dnssd_getaddrinfo_set_interface_index( me->gai, kDNSServiceInterfaceIndexAny );
-	dnssd_getaddrinfo_set_protocols( me->gai, kDNSServiceProtocol_IPv4 );
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	gai = me->gai;
-	dnssd_retain( gai );
-	_DNSQueryTestRetain( me );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-	{
-		require_return( me->gai == gai );
-		_DNSQueryTestHandleGAIProbeResults( me, inResults, inCount );
-	} );
-	dnssd_getaddrinfo_set_event_handler( me->gai,
-	^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-	{
-		if( inEvent == dnssd_event_invalidated )
-		{
-			dnssd_release( gai );
-			_DNSQueryTestRelease( me );
-		}
-		else if( inEvent == dnssd_event_error )
-		{
-			require_return( me->gai == gai );
-			dqt_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-			_DNSQueryTestStop( me, inGAIError );
-		}
-	} );
-	dnssd_getaddrinfo_activate( me->gai );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDNSQueryTestProbeQueryTimeoutSecs ),
-		kDNSQueryTestProbeQueryTimeoutSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ),
-		me->queue, _DNSQueryTestProbeQueryTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	dispatch_resume( me->timer );
-	
-	_NanoTime64ToTimestamp( startTime, startTimeStr, sizeof( startTimeStr ) );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->report,
-		"%kO=%s"	// startTime
-		"%kO=%s"	// serverCmd
-		"%kO=%s"	// probeHostname
-		"%kO=[%@]",	// results
-		CFSTR( "startTime" ),		startTimeStr,
-		CFSTR( "serverCmd" ),		serverCmd,
-		CFSTR( "probeHostname" ),	me->hostname,
-		CFSTR( "results" ),			&me->subtestResults );
-	require_noerr( err, exit );
-	
-exit:
-	FreeNullSafe( serverCmd );
-	if( err ) _DNSQueryTestStop( me, err );
-}
-
-static void
-	_DNSQueryTestHandleGAIProbeResults(
-		const DNSQueryTestRef				me,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	size_t		i;
-	Boolean		startSubtests = false;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		if( dnssd_getaddrinfo_result_get_type( result ) == dnssd_getaddrinfo_result_type_add )
-		{
-			dqt_ulog( kLogLevelInfo, "Probe GAI got %##a for %s\n",
-				dnssd_getaddrinfo_result_get_address( result ), me->hostname );
-			startSubtests = true;
-			break;
-		}
-	}
-	if( startSubtests )
-	{
-		OSStatus		err;
-		
-		_DNSQueryTestSubtestCleanup( me );
-		err = _DNSQueryTestStartSubtest( me );
-		if( err ) _DNSQueryTestStop( me, err );
-	}
-}
-
-static void	_DNSQueryTestProbeQueryTimerHandler( void * const inCtx )
-{
-	const DNSQueryTestRef		me = (DNSQueryTestRef) inCtx;
-	
-	dqt_ulog( kLogLevelInfo, "Probe GAI request for '%s' timed out.\n", me->hostname );
-	_DNSQueryTestStop( me, kNotPreparedErr );
-}
-
-//===========================================================================================================================
-
-static void	_DNSQueryTestStop( const DNSQueryTestRef me, const OSStatus inError )
-{
-	OSStatus		err;
-	NanoTime64		endTime;
-	char			endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	me->error = inError;
-	dqt_ulog( kLogLevelInfo, "Stopping test with error: %#m\n", me->error );
-	
-	_DNSQueryTestSubtestCleanup( me );
-	me->subtestResults = NULL;
-	if( me->serverPID >= 0 )
-	{
-		OSStatus		killErr;
-		
-		killErr = kill( me->serverPID, SIGTERM );
-		killErr = map_global_noerr_errno( killErr );
-		check_noerr( killErr );
-		me->serverPID = -1;
-	}
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->report,
-		"%kO=%s"	// endTime
-		"%kO=%i"	// subtestCount
-		"%kO=%i",	// subtestPassCount
-		CFSTR( "endTime" ),				endTimeStr,
-		CFSTR( "subtestCount" ),		me->subtestCount,
-		CFSTR( "subtestPassCount" ),	me->subtestPassCount );
-	check_noerr( err );
-	if( err && !me->error ) me->error = err;
-	dispatch_semaphore_signal( me->doneSem );
-}
-
-//===========================================================================================================================
-
-typedef struct
-{
-	size_t		queryCountA;
-	size_t		queryCountAAAA;
-	size_t		queryCountOther;
-	
-}	DNSQueryPCapStats;
-
-static void
-	_DNSQuerySubtestHandleGAIResults(
-		DNSQueryTestRef					inTest,
-		dnssd_getaddrinfo_result_t *	inResults,
-		size_t							inCount );
-static void		_DNSQuerySubtestTimerHandler( void *inCtx );
-static OSStatus	_DNSQuerySubtestProcessResults( DNSQueryTestRef inTest );
-static OSStatus	_DNSQueryTestProcessPacketCapture( pcap_t *inPCap, const char *inDomain, DNSQueryPCapStats *outStats );
-
-#define kDNSQuerySubtestTimeSecs		5
-
-static OSStatus	_DNSQueryTestStartSubtest( const DNSQueryTestRef me )
-{
-	OSStatus								err;
-	dnssd_getaddrinfo_t						gai;
-	const DNSQuerySubtestParams * const		params = &kDNSQuerySubtestParams[ me->subtestIndex ];
-	DNSServiceProtocol						protocols;
-	char									aliasLabelStr[ 32 ];
-	char									tag[ 6 + 1 ];
-	const Boolean							wantIPv4 = ( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv4 ) != 0;
-	const Boolean							wantIPv6 = ( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv6 ) != 0;
-	
-	require_action_quiet( !me->done, exit, err = kInternalErr );
-	
-	check( !me->gai );
-	check( !me->timer );
-	
-	me->startTime = NanoTimeGetCurrent();
-	
-	switch( params->cnameCount )
-	{
-		case 0:
-			aliasLabelStr[ 0 ] = '\0';
-			break;
-		
-		case 1:
-			SNPrintF( aliasLabelStr, sizeof( aliasLabelStr ), "alias." );
-			break;
-		
-		default:
-			SNPrintF( aliasLabelStr, sizeof( aliasLabelStr ), "alias-%u.", params->cnameCount );
-			break;
-	}
-	check( !me->domain );
-	ASPrintF( &me->domain, "tag-dns-query-test-%s.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->domain, exit, err = kNoMemoryErr );
-	
-	me->addressOffset = RandomRange( 0, 255 );
-	check( !me->hostname );
-	ASPrintF( &me->hostname, "%scount-%u.offset-%u.pdelay-100.%s",
-		aliasLabelStr, params->addrCount, me->addressOffset, me->domain );
-	require_action( me->hostname, exit, err = kNoMemoryErr );
-	
-	check( !me->gaiResults );
-	me->gaiResults = CFArrayCreateMutable( NULL, 0, &kDNSSDObjectArrayCallbacks );
-	require_action( me->gaiResults, exit, err = kNoMemoryErr );
-	
-	check( !me->gai );
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->hostname );
-	dnssd_getaddrinfo_set_flags( me->gai, kDNSServiceFlagsReturnIntermediates );
-	dnssd_getaddrinfo_set_interface_index( me->gai, kDNSServiceInterfaceIndexAny );
-	protocols = 0;
-	if( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv4 ) protocols |= kDNSServiceProtocol_IPv4;
-	if( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv6 ) protocols |= kDNSServiceProtocol_IPv6;
-	dnssd_getaddrinfo_set_protocols( me->gai, protocols );
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	gai = me->gai;
-	dnssd_retain( gai );
-	_DNSQueryTestRetain( me );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-	{
-		require_return( me->gai == gai );
-		_DNSQuerySubtestHandleGAIResults( me, inResults, inCount );
-	} );
-	dnssd_getaddrinfo_set_event_handler( gai,
-	^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-	{
-		if( inEvent == dnssd_event_invalidated )
-		{
-			dnssd_release( gai );
-			_DNSQueryTestRelease( me );
-		}
-		else if( inEvent == dnssd_event_error )
-		{
-			OSStatus		testErr;
-			
-			require_return( me->gai == gai );
-			dqt_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-			testErr = _DNSQueryTestContinue( me, inGAIError );
-			if( testErr || me->done ) _DNSQueryTestStop( me, testErr );
-		}
-	} );
-	
-	check( !me->pcap );
-	err = _GAITesterCreatePacketCapture( &me->pcap );
-	require_noerr( err, exit );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kDNSQuerySubtestTimeSecs ),
-		kDNSQuerySubtestTimeSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 20 ),
-		me->queue, _DNSQuerySubtestTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	
-	check( !me->description );
-	ASPrintF( &me->description, "%s%s%s GAI request for hostname with %u CNAME records and %u address records",
-		wantIPv4 ? "IPv4" : "", ( wantIPv4 && wantIPv6 ) ? "+" : "", wantIPv6 ? "IPv6" : "", params->cnameCount,
-		params->addrCount );
-	require_action( me->description, exit, err = kNoMemoryErr );
-	
-	++me->subtestCount;
-	dqt_ulog( kLogLevelInfo, "Starting subtest #%d: %s\n", me->subtestCount, me->description );
-	
-	dnssd_getaddrinfo_activate( me->gai );
-	dispatch_resume( me->timer );
-	
-exit:
-	return( err );
-}
-
-static void
-	_DNSQuerySubtestHandleGAIResults(
-		const DNSQueryTestRef				me,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	size_t		i;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		dqt_ulog( kLogLevelInfo, "GAI result -- %@\n", result );
-		CFArrayAppendValue( me->gaiResults, result );
-	}
-}
-
-static void	_DNSQuerySubtestTimerHandler( void * const inCtx )
-{
-	OSStatus					err;
-	const DNSQueryTestRef		me = (DNSQueryTestRef) inCtx;
-	
-	err = _DNSQuerySubtestProcessResults( me );
-	require_noerr( err, exit );
-	
-	err = _DNSQueryTestContinue( me, kNoErr );
-	require_noerr( err, exit );
-	
-exit:
-	if( err || me->done ) _DNSQueryTestStop( me, err );
-}
-
-static OSStatus	_DNSQuerySubtestProcessResults( const DNSQueryTestRef me )
-{
-	OSStatus								err;
-	DNSQueryPCapStats						stats;
-	const DNSQuerySubtestParams * const		params = &kDNSQuerySubtestParams[ me->subtestIndex ];
-	uint64_t								addrBitmapV4, addrBitmapV6;
-	CFIndex									i, n;
-	unsigned int							expectedQueryCountA, expectedQueryCountAAAA, j;
-	const Boolean							wantIPv4 = ( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv4 ) != 0;
-	const Boolean							wantIPv6 = ( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv6 ) != 0;
-	
-	err = _DNSQueryTestProcessPacketCapture( me->pcap, me->domain, &stats );
-	ForgetPacketCapture( &me->pcap );
-	require_noerr( err, exit );
-	
-	expectedQueryCountA		= wantIPv4 ? 1 : 0;
-	expectedQueryCountAAAA	= wantIPv6 ? 1 : 0;
-	me->haveBadQueryCounts	= ( stats.queryCountA != expectedQueryCountA ) ||
-		( stats.queryCountAAAA != expectedQueryCountAAAA ) || ( stats.queryCountOther != 0 );
-	
-	check( !me->queryCountStats );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &me->queryCountStats,
-		"{"
-			"%kO=%lli"	// expectedQueryCountA
-			"%kO=%lli"	// expectedQueryCountAAAA
-			"%kO=%lli"	// expectedQueryCountOther
-			"%kO=%lli"	// actualQueryCountA
-			"%kO=%lli"	// actualQueryCountAAAA
-			"%kO=%lli"	// actualQueryCountOther
-		"}",
-		CFSTR( "expectedQueryCountA" ),		(int64_t) expectedQueryCountA,
-		CFSTR( "expectedQueryCountAAAA" ),	(int64_t) expectedQueryCountAAAA,
-		CFSTR( "expectedQueryCountOther" ),	(int64_t) 0,
-		CFSTR( "actualQueryCountA" ),		(int64_t) stats.queryCountA,
-		CFSTR( "actualQueryCountAAAA" ),	(int64_t) stats.queryCountAAAA,
-		CFSTR( "actualQueryCountOther" ),	(int64_t) stats.queryCountOther );
-	require_noerr( err, exit );
-	require_noerr( err, exit );
-	
-	check( ( params->addrCount >= 0 ) && ( params->addrCount <= 64 ) );
-	addrBitmapV4 = 0;
-	if( wantIPv4 )
-	{
-		if( params->addrCount < 64 )	addrBitmapV4 = ( UINT64_C( 1 ) << params->addrCount ) - 1;
-		else							addrBitmapV4 =  ~UINT64_C( 0 );
-	}
-	addrBitmapV6 = 0;
-	if( wantIPv6 )
-	{
-		if( params->addrCount < 64 )	addrBitmapV6 = ( UINT64_C( 1 ) << params->addrCount ) - 1;
-		else							addrBitmapV6 =  ~UINT64_C( 0 );
-	}
-	n = CFArrayGetCount( me->gaiResults );
-	for( i = 0; i < n; ++i )
-	{
-		dnssd_getaddrinfo_result_t			result;
-		const sockaddr_ip *					sip;
-		dnssd_getaddrinfo_result_type_t		resultType;
-		Boolean								validResult	= false;
-		
-		result = (dnssd_getaddrinfo_result_t) CFArrayGetValueAtIndex( me->gaiResults, i );
-		resultType = dnssd_getaddrinfo_result_get_type( result );
-		if( resultType == dnssd_getaddrinfo_result_type_add )
-		{
-			uint64_t *		bitmapPtr = NULL;
-			uint32_t		addrValue = 0;
-			
-			sip = (const sockaddr_ip *) dnssd_getaddrinfo_result_get_address( result );
-			switch( sip->sa.sa_family )
-			{
-				case AF_INET:
-					if( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv4 )
-					{
-						const uint32_t		addr = ntohl( sip->v4.sin_addr.s_addr );
-						
-						if( ( addr & UINT32_C( 0xFFFFFF00 ) ) == kDNSServerBaseAddrV4 )
-						{
-							addrValue = addr & 0xFFU;
-							bitmapPtr = &addrBitmapV4;
-						}
-					}
-					break;
-				
-				case AF_INET6:
-					if( params->gaiOpts & kDNSQueryTestGAIOpts_WantIPv6 )
-					{
-						const uint8_t * const		addr = sip->v6.sin6_addr.s6_addr;
-						
-						if( memcmp( addr, kDNSServerBaseAddrV6, 15 ) == 0 )
-						{
-							addrValue = addr[ 15 ];
-							bitmapPtr = &addrBitmapV6;
-						}
-					}
-					break;
-			}
-			if( bitmapPtr )
-			{
-				addrValue = ( addrValue - me->addressOffset ) % 256;
-				if( ( addrValue >= 1 ) && ( addrValue <= params->addrCount ) )
-				{
-					const uint64_t		bitmask = UINT64_C( 1 ) << ( addrValue - 1 );
-					
-					if( *bitmapPtr & bitmask )
-					{
-						*bitmapPtr &= ~bitmask;
-						validResult = true;
-					}
-				}
-			}
-		}
-		if( !validResult )
-		{
-			if( !me->unexpectedResults )
-			{
-				me->unexpectedResults = CFArrayCreateMutable( NULL, 0, &kDNSSDObjectArrayCallbacks );
-				require_action( me->unexpectedResults, exit, err = kNoMemoryErr );
-			}
-			CFArrayAppendValue( me->unexpectedResults, result );
-		}
-	}
-	if( ( addrBitmapV4 != 0 ) || ( addrBitmapV6 != 0 ) )
-	{
-		check( !me->missingAddrs );
-		me->missingAddrs = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-		require_action( me->missingAddrs, exit, err = kNoMemoryErr );
-	}
-	for( j = 1; ( j <= 64 ) && ( addrBitmapV4 != 0 ); ++j )
-	{
-		const uint64_t		bitmask = UINT64_C( 1 ) << ( j - 1 );
-		
-		if( addrBitmapV4 & bitmask )
-		{
-			uint8_t		missingAddr[ 4 ];
-			
-			addrBitmapV4 &= ~bitmask;
-			WriteBig32Typed( missingAddr, kDNSServerBaseAddrV4 );
-			missingAddr[ 3 ] = (uint8_t)( ( me->addressOffset + j ) % 256 );
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->missingAddrs, "%.4a", missingAddr );
-			require_noerr( err, exit );
-		}
-	}
-	for( j = 1; ( j <= 64 ) && ( addrBitmapV6 != 0 ); ++j )
-	{
-		const uint64_t		bitmask = UINT64_C( 1 ) << ( j - 1 );
-		
-		if( addrBitmapV6 & bitmask )
-		{
-			uint8_t		missingAddr[ 16 ];
-			
-			addrBitmapV6 &= ~bitmask;
-			memcpy( missingAddr, kDNSServerBaseAddrV6, 16 );
-			missingAddr[ 15 ] = (uint8_t)( ( me->addressOffset + j ) % 256 );
-			err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->missingAddrs, "%.16a", missingAddr );
-			require_noerr( err, exit );
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-static OSStatus
-	_DNSQueryTestProcessPacketCapture(
-		pcap_t * const				inPCap,
-		const char * const			inDomain,
-		DNSQueryPCapStats * const	outStats )
-{
-	OSStatus		err;
-	int				domainLabelCount;
-	uint8_t			domain[ kDomainNameLengthMax ];
-	
-	err = DomainNameFromString(	domain, inDomain, NULL );
-	require_noerr( err, exit );
-	
-	domainLabelCount = DomainNameLabelCount( domain );
-	if( outStats ) memset( outStats, 0, sizeof( *outStats ) );
-	for( ;; )
-	{
-		int							status;
-		struct pcap_pkthdr *		pktHdr;
-		const uint8_t *				packet;
-		const uint8_t *				msgPtr;
-		size_t						msgLen;
-		const DNSHeader *			hdr;
-		unsigned int				flags;
-		int							labelDiff;
-		const uint8_t *				questionSection;
-		const uint8_t *				qnameAncestor;
-		uint16_t					qtype, qclass;
-		uint8_t						qname[ kDomainNameLengthMax ];
-		
-		status = pcap_next_ex( inPCap, &pktHdr, &packet );
-		if( status != 1 ) break;
-		if( _GAITesterGetDNSMessageFromPacket( packet, pktHdr->caplen, &msgPtr, &msgLen ) != kNoErr ) continue;
-		if( msgLen < kDNSHeaderLength ) continue;
-		
-		hdr = (const DNSHeader *) msgPtr;
-		flags = DNSHeaderGetFlags( hdr );
-		if( DNSFlagsGetOpCode( flags ) != kDNSOpCode_Query ) continue;
-		if( DNSHeaderGetQuestionCount( hdr ) < 1 ) continue;
-		
-		questionSection = (const uint8_t *) &hdr[ 1 ];
-		if( DNSMessageExtractQuestion( msgPtr, msgLen, questionSection, qname, &qtype, &qclass, NULL ) != kNoErr ) continue;
-		if( qclass != kDNSServiceClass_IN ) continue;
-		
-		labelDiff = DomainNameLabelCount( qname ) - domainLabelCount;
-		if( labelDiff < 0 ) continue;
-		
-		qnameAncestor = qname;
-		while( labelDiff-- > 0 )
-		{
-			qnameAncestor = DomainNameGetNextLabel( qnameAncestor );
-		}
-		if( !DomainNameEqual( qnameAncestor, domain ) ) continue;
-		
-		if( outStats && ( flags & kDNSHeaderFlag_Response ) )
-		{
-			switch( qtype )
-			{
-				case kDNSRecordType_A:		++outStats->queryCountA;		break;
-				case kDNSRecordType_AAAA:	++outStats->queryCountAAAA;		break;
-				default:					++outStats->queryCountOther;	break;
-			}
-		}
-	}
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_DNSQueryTestStopSubtest( DNSQueryTestRef inTest, OSStatus inError );
-
-static OSStatus	_DNSQueryTestContinue( const DNSQueryTestRef me, const OSStatus inSubtestError )
-{
-	OSStatus		err;
-	
-	require_action_quiet( !me->done, exit, err = kNoErr );
-	
-	err = _DNSQueryTestStopSubtest( me, inSubtestError );
-	require_noerr( err, exit );
-	require_action_quiet( !me->done, exit, err = kNoErr );
-	
-	err = _DNSQueryTestStartSubtest( me );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_DNSQueryTestSubtestCleanup( const DNSQueryTestRef me )
-{
-	dnssd_getaddrinfo_forget( &me->gai );
-	dispatch_source_forget( &me->timer );
-	CFForget( &me->gaiResults );
-	CFForget( &me->unexpectedResults );
-	CFForget( &me->missingAddrs );
-	CFForget( &me->queryCountStats );
-	ForgetMem( &me->hostname );
-	ForgetMem( &me->domain );
-	ForgetMem( &me->description );
-	ForgetPacketCapture( &me->pcap );
-	me->haveBadQueryCounts = false;
-}
-
-static OSStatus	_DNSQueryTestStopSubtest( const DNSQueryTestRef me, const OSStatus inError )
-{
-	OSStatus				err, subtestErr;
-	NanoTime64				endTime;
-	CFMutableArrayRef		gaiResultStrings, unexpectedResultStrings;
-	CFIndex					i, n;
-	char					errorStr[ 128 ];
-	char					startTimeStr[ 32 ];
-	char					endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	
-	if( inError )						subtestErr = inError;
-	else if( me->missingAddrs )			subtestErr = kAddressErr;
-	else if( me->unexpectedResults )	subtestErr = kUnexpectedErr;
-	else if( me->haveBadQueryCounts )	subtestErr = kCountErr;
-	else								subtestErr = kNoErr;
-	if( !subtestErr ) ++me->subtestPassCount;
-	dqt_ulog( kLogLevelInfo, "Subtest #%d result: %s (pass rate: %d/%d)\n",
-		me->subtestCount, subtestErr ? "fail" : "pass", me->subtestPassCount, me->subtestCount );
-	
-	_NanoTime64ToTimestamp( me->startTime, startTimeStr, sizeof( startTimeStr ) );
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	SNPrintF( errorStr, sizeof( errorStr ), "%m", subtestErr );
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, me->subtestResults,
-		"{"
-			"%kO=%s"		// description
-			"%kO=%s"		// startTime
-			"%kO=%s"		// endTime
-			"%kO=%s"		// hostname
-			"%kO=%b"		// pass
-			"%kO=[%@]"		// GAIResults
-			"%kO=%O"		// queryCountStats
-			"%kO=[%@]"		// unexpectedResults
-			"%kO=%O"		// missingAddrs
-			"%kO="			// error
-			"{"
-				"%kO=%lli"	// code
-				"%kO=%s"	// description
-			"}"
-		"}",
-		CFSTR( "description" ),			me->description,
-		CFSTR( "startTime" ),			startTimeStr,
-		CFSTR( "endTime" ),				endTimeStr,
-		CFSTR( "hostname" ),			me->hostname,
-		CFSTR( "pass" ),				!subtestErr,
-		CFSTR( "GAIResults" ),			&gaiResultStrings,
-		CFSTR( "queryCountStats" ),		me->queryCountStats,
-		CFSTR( "unexpectedResults" ),	&unexpectedResultStrings,
-		CFSTR( "missingAddrs" ),		me->missingAddrs,
-		CFSTR( "error" ),
-		CFSTR( "code" ),				(int64_t) subtestErr,
-		CFSTR( "description" ),			errorStr );
-	require_noerr( err, exit );
-	
-	n = CFArrayGetCount( me->gaiResults );
-	for( i = 0; i < n; ++ i )
-	{
-		CFStringRef		resultStr;
-		
-		resultStr = CFStringCreateF( &err, "%@", CFArrayGetValueAtIndex( me->gaiResults, i ) );
-		require( resultStr, exit );
-		
-		CFArrayAppendValue( gaiResultStrings, resultStr );
-		CFForget( &resultStr );
-	}
-	n = CFArrayGetCountNullSafe( me->unexpectedResults );
-	for( i = 0; i < n; ++ i )
-	{
-		CFStringRef		resultStr;
-		
-		resultStr = CFStringCreateF( &err, "%@", CFArrayGetValueAtIndex( me->unexpectedResults, i ) );
-		require( resultStr, exit );
-		
-		CFArrayAppendValue( unexpectedResultStrings, resultStr );
-		CFForget( &resultStr );
-	}
-	if( me->subtestIndex < ( countof( kDNSQuerySubtestParams ) - 1 ) )
-	{
-		++me->subtestIndex;
-	}
-	else
-	{
-		me->done = true;
-	}
-	
-exit:
-	_DNSQueryTestSubtestCleanup( me );
-	return( err );
-}
-
-//===========================================================================================================================
-//	FastRecoveryTestCmd
-//===========================================================================================================================
-
-typedef struct
-{
-	dnssd_getaddrinfo_t		gai;			// GAI object.
-	char *					hostname;		// Hostname to be resolved.
-	Boolean					gotResultIPv4;	// True if the IPv4 GAI result was received.
-	Boolean					gotResultIPv6;	// True if the IPv6 GAI result was received.
-	
-}	FastRecoveryGAI;
-
-typedef struct FastRecoveryTest *		FastRecoveryTestRef;
-struct FastRecoveryTest
-{
-	dispatch_queue_t			queue;			// Serial queue for test events.
-	dispatch_semaphore_t		doneSem;		// Semaphore to signal when the test is done.
-	dnssd_getaddrinfo_t			gai;			// GAI object for probing/suspending and resuming the test DNS server.
-	FastRecoveryGAI				gaiArray[ 5 ];	// Array of regular GAI operations to test fast recovery.
-	size_t						gaiCount;		// Number of regular GAI operations that are in progress.
-	dispatch_source_t			timer;			// Timer for enforcing time limit on current dnssd_getaddrinfo.
-	CFMutableDictionaryRef		report;			// Test's report, as a plist.
-	CFMutableArrayRef			gaiResults;		// Pointer to report's GAI results.
-	char *						domain;			// High-level domain for test's hostnames.
-	char *						probeQNAME;		// QNAME used in probe query for test DNS server.
-	char *						resumeQNAME;	// QNAME used in query to resume the test DNS server.
-	NanoTime64					startTime;		// Current subtest's start time.
-	pid_t						serverPID;		// PID of spawned test DNS server.
-	int32_t						refCount;		// Test's reference count.
-	OSStatus					error;			// Current test error.
-	Boolean						suspended;		// True if the test DNS server is currently suspended.
-	Boolean						done;			// True if all subtests have completed.
-};
-
-ulog_define_ex( kDNSSDUtilIdentifier, FastRecoveryTest, kLogLevelInfo, kLogFlags_None, "FastRecoveryTest", NULL );
-#define frt_ulog( LEVEL, ... )		ulog( &log_category_from_name( FastRecoveryTest ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	_FastRecoveryTestCreate( FastRecoveryTestRef *outTest );
-static OSStatus	_FastRecoveryTestRun( FastRecoveryTestRef inTest, Boolean *outPassed );
-static void		_FastRecoveryTestRetain( FastRecoveryTestRef inTest );
-static void		_FastRecoveryTestRelease( FastRecoveryTestRef inTest );
-
-static void	FastRecoveryTestCmd( void )
-{
-	OSStatus				err;
-	OutputFormatType		outputFormat;
-	FastRecoveryTestRef		test	= NULL;
-	Boolean					passed	= false;
-	
-	err = OutputFormatFromArgString( gFastRecoveryTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _FastRecoveryTestCreate( &test );
-	require_noerr( err, exit );
-	
-	err = _FastRecoveryTestRun( test, &passed );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( test->report, outputFormat, gFastRecoveryTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _FastRecoveryTestRelease( test );
-    gExitCode = err ? 1 : ( passed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_FastRecoveryTestCreate( FastRecoveryTestRef * const outTest )
-{
-	OSStatus				err;
-	FastRecoveryTestRef		obj;
-	
-	obj = (FastRecoveryTestRef) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount	= 1;
-	obj->error		= kInProgressErr;
-	obj->serverPID	= -1;
-	
-	obj->queue = dispatch_queue_create( "com.apple.dnssdutil.fast-recovery-test", DISPATCH_QUEUE_SERIAL );
-	require_action( obj->queue, exit, err = kNoResourcesErr );
-	
-	obj->doneSem = dispatch_semaphore_create( 0 );
-	require_action( obj->doneSem, exit, err = kNoResourcesErr );
-	
-	obj->report = CFDictionaryCreateMutable( NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-	require_action( obj->report, exit, err = kNoMemoryErr );
-	
-	*outTest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _FastRecoveryTestRelease( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void		_FastRecoveryTestStart( void *inCtx );
-static void		_FastRecoveryTestStop( FastRecoveryTestRef inTest, OSStatus inError );
-
-static OSStatus	_FastRecoveryTestRun( const FastRecoveryTestRef me, Boolean * const outPassed )
-{
-	Boolean		passed;
-	
-	dispatch_async_f( me->queue, me, _FastRecoveryTestStart );
-	dispatch_semaphore_wait( me->doneSem, DISPATCH_TIME_FOREVER );
-	
-	passed = !me->error;
-	CFDictionarySetBoolean( me->report, CFSTR( "pass" ), passed );
-	frt_ulog( kLogLevelInfo, "Test result: %s\n", passed ? "pass" : "fail" );
-	
-	if( outPassed ) *outPassed = passed;
-	return( me->error );
-}
-
-//===========================================================================================================================
-
-static void	_FastRecoveryTestRetain( const FastRecoveryTestRef me )
-{
-	atomic_add_32( &me->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_FastRecoveryTestRelease( const FastRecoveryTestRef me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->gai );
-		check( !me->timer );
-		check( !me->gaiResults );
-		check( !me->domain );
-		check( !me->probeQNAME );
-		check( !me->resumeQNAME );
-		check( me->serverPID < 0 );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->doneSem );
-		ForgetCF( &me->report );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-
-#define kFastRecoveryTestProbeQueryTimeoutSecs		5
-
-static void
-	_FastRecoveryTestHandleGAIProbeResults(
-		FastRecoveryTestRef				inTest,
-		dnssd_getaddrinfo_result_t *	inResults,
-		size_t							inCount );
-static void		_FastRecoveryTestProbeQueryTimerHandler( void *inCtx );
-static OSStatus	_FastRecoveryTestStartGAIRequests( FastRecoveryTestRef inTest );
-
-static void	_FastRecoveryTestStart( void * const inCtx )
-{
-	OSStatus						err;
-	const FastRecoveryTestRef		me			= (FastRecoveryTestRef) inCtx;
-	char *							serverCmd	= NULL;
-	dnssd_getaddrinfo_t				gai;
-	NanoTime64						startTime;
-	char							startTimeStr[ 32 ];
-	char							tag[ 6 + 1 ];
-	
-	startTime = NanoTimeGetCurrent();
-	frt_ulog( kLogLevelInfo, "Starting test\n" );
-	
-	serverCmd = NULL;
-	ASPrintF( &serverCmd, "dnssdutil server --loopback --follow %lld --responseDelay 10", (int64_t) getpid() );
-	require_action_quiet( serverCmd, exit, err = kNoMemoryErr );
-	
-	err = _SpawnCommand( &me->serverPID, "/dev/null", "/dev/null", "%s", serverCmd );
-	require_noerr( err, exit );
-	
-	check( !me->domain );
-	ASPrintF( &me->domain, "tag-fast-recovery-test-%s.d.test.",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( me->domain, exit, err = kNoMemoryErr );
-	
-	check( !me->probeQNAME );
-	ASPrintF( &me->probeQNAME, "tag-fast-recovery-test-probe.ttl-300.command-suspend.%s", me->domain );
-	require_action( me->probeQNAME, exit, err = kNoMemoryErr );
-	
-	check( !me->gai );
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->probeQNAME );
-	dnssd_getaddrinfo_set_flags( me->gai, 0 );
-	dnssd_getaddrinfo_set_interface_index( me->gai, kDNSServiceInterfaceIndexAny );
-	dnssd_getaddrinfo_set_protocols( me->gai, kDNSServiceProtocol_IPv4 );
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	gai = me->gai;
-	dnssd_retain( gai );
-	_FastRecoveryTestRetain( me );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-	{
-		require_return( me->gai == gai );
-		_FastRecoveryTestHandleGAIProbeResults( me, inResults, inCount );
-	} );
-	dnssd_getaddrinfo_set_event_handler( me->gai,
-	^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-	{
-		if( inEvent == dnssd_event_invalidated )
-		{
-			dnssd_release( gai );
-			_FastRecoveryTestRelease( me );
-		}
-		else if( inEvent == dnssd_event_error )
-		{
-			require_return( me->gai == gai );
-			frt_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-			_FastRecoveryTestStop( me, inGAIError );
-		}
-	} );
-	dnssd_getaddrinfo_activate( me->gai );
-	
-	check( !me->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kFastRecoveryTestProbeQueryTimeoutSecs ),
-		kFastRecoveryTestProbeQueryTimeoutSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 10 ),
-		me->queue, _FastRecoveryTestProbeQueryTimerHandler, me, &me->timer );
-	require_noerr( err, exit );
-	dispatch_resume( me->timer );
-	
-	_NanoTime64ToTimestamp( startTime, startTimeStr, sizeof( startTimeStr ) );
-	err = CFPropertyListAppendFormatted( NULL, me->report,
-		"%kO=%s"	// startTime
-		"%kO=%s"	// serverCmd
-		"%kO=%s"	// probeQNAME
-		"%kO=[%@]",	// results
-		CFSTR( "startTime" ),	startTimeStr,
-		CFSTR( "serverCmd" ),	serverCmd,
-		CFSTR( "probeQNAME" ),	me->probeQNAME,
-		CFSTR( "results" ),		&me->gaiResults );
-	require_noerr( err, exit );
-	
-exit:
-	FreeNullSafe( serverCmd );
-	if( err ) _FastRecoveryTestStop( me, err );
-}
-
-static void
-	_FastRecoveryTestHandleGAIProbeResults(
-		const FastRecoveryTestRef			me,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	size_t		i;
-	Boolean		startGAIRequests = false;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		if( dnssd_getaddrinfo_result_get_type( result ) == dnssd_getaddrinfo_result_type_add )
-		{
-			frt_ulog( kLogLevelInfo,
-				"Probe GAI got %##a for %s\n", dnssd_getaddrinfo_result_get_address( result ), me->probeQNAME );
-			startGAIRequests = true;
-			break;
-		}
-	}
-	if( startGAIRequests )
-	{
-		OSStatus		err;
-		
-		me->suspended = true;
-		dispatch_source_forget( &me->timer );
-		dnssd_getaddrinfo_forget( &me->gai );
-		err = _FastRecoveryTestStartGAIRequests( me );
-		if( err ) _FastRecoveryTestStop( me, err );
-	}
-}
-
-static void	_FastRecoveryTestProbeQueryTimerHandler( void * const inCtx )
-{
-	const FastRecoveryTestRef		me = (FastRecoveryTestRef) inCtx;
-	
-	frt_ulog( kLogLevelInfo, "Probe GAI request for '%s' timed out.\n", me->probeQNAME );
-	_FastRecoveryTestStop( me, kNotPreparedErr );
-}
-
-//===========================================================================================================================
-
-static void	_FastRecoveryTestStop( const FastRecoveryTestRef me, const OSStatus inError )
-{
-	OSStatus		err;
-	NanoTime64		endTime;
-	size_t			i;
-	char			endTimeStr[ 32 ];
-	
-	endTime = NanoTimeGetCurrent();
-	me->error = inError;
-	frt_ulog( kLogLevelInfo, "Stopping test with error: %#m\n", me->error );
-	
-	dnssd_getaddrinfo_forget( &me->gai );
-	dispatch_source_forget( &me->timer );
-	for( i = 0; i < countof( me->gaiArray ); ++i )
-	{
-		FastRecoveryGAI * const		frGAI = &me->gaiArray[ i ];
-		
-		ForgetMem( &frGAI->hostname );
-		dnssd_getaddrinfo_forget( &frGAI->gai );
-	}
-	ForgetMem( &me->domain );
-	ForgetMem( &me->probeQNAME );
-	ForgetMem( &me->resumeQNAME );
-	me->gaiResults = NULL;
-	if( me->serverPID >= 0 )
-	{
-		OSStatus		killErr;
-		
-		killErr = kill( me->serverPID, SIGTERM );
-		killErr = map_global_noerr_errno( killErr );
-		check_noerr( killErr );
-		me->serverPID = -1;
-	}
-	_NanoTime64ToTimestamp( endTime, endTimeStr, sizeof( endTimeStr ) );
-	err = CFPropertyListAppendFormatted( NULL, me->report, "%kO=%s", CFSTR( "endTime" ), endTimeStr );
-	check_noerr( err );
-	if( err && !me->error ) me->error = err;
-	dispatch_semaphore_signal( me->doneSem );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_FastRecoveryTestStartQuerier( FastRecoveryTestRef inTest );
-
-#define kFastRecoveryTestQuerierStartIntervalSecs		5
-
-static OSStatus	_FastRecoveryTestStartGAIRequests( const FastRecoveryTestRef me )
-{
-	OSStatus		err;
-	
-	check( !me->timer );
-	me->timer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, me->queue );
-	require_action( me->timer, exit, err = kNoResourcesErr );
-	
-	dispatch_source_set_timer( me->timer, _dispatch_monotonictime_after_sec( kFastRecoveryTestQuerierStartIntervalSecs ),
-		kFastRecoveryTestQuerierStartIntervalSecs * UINT64_C_safe( kNanosecondsPerSecond ),
-		kFastRecoveryTestQuerierStartIntervalSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 20 ) );
-	dispatch_set_context( me->timer, me );
-	dispatch_source_set_event_handler( me->timer,
-	^{
-		OSStatus		startErr;
-		
-		startErr = _FastRecoveryTestStartQuerier( me );
-		if( startErr ) _FastRecoveryTestStop( me, startErr );
-	} );
-	dispatch_activate( me->timer );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-#define kFastRecoveryTestFinalTimeoutSecs		2
-
-static void
-	_FastRecoveryTestHandleGAIResuts(
-		FastRecoveryTestRef				inTest,
-		FastRecoveryGAI *				inGAI,
-		dnssd_getaddrinfo_result_t *	inResults,
-		size_t							inCount );
-static void	_FastRecoveryTestComplete( FastRecoveryTestRef inTest );
-
-static OSStatus	_FastRecoveryTestStartQuerier( const FastRecoveryTestRef me )
-{
-	OSStatus		err;
-	
-	if( me->gaiCount < countof( me->gaiArray ) )
-	{
-		dnssd_getaddrinfo_t			gai;
-		FastRecoveryGAI * const		frGAI = &me->gaiArray[ me->gaiCount++ ];
-		char						tag[ 6 + 1 ];
-		
-		check( !frGAI->hostname );
-		ASPrintF( &frGAI->hostname, "count-1.tag-%s.%s",
-			_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ),
-			me->domain );
-		require_action( frGAI->hostname, exit, err = kNoMemoryErr );
-		
-		gai = dnssd_getaddrinfo_create();
-		require_action( gai, exit, err = kNoResourcesErr );
-		
-		dnssd_getaddrinfo_set_hostname( gai, frGAI->hostname );
-		dnssd_getaddrinfo_set_flags( gai, 0 );
-		dnssd_getaddrinfo_set_interface_index( gai, kDNSServiceInterfaceIndexAny );
-		dnssd_getaddrinfo_set_protocols( gai, kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6 );
-		dnssd_getaddrinfo_set_queue( gai, me->queue );
-		dnssd_retain( gai );
-		_FastRecoveryTestRetain( me );
-		dnssd_getaddrinfo_set_result_handler( gai,
-		^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-		{
-			require_return( frGAI->gai == gai );
-			_FastRecoveryTestHandleGAIResuts( me, frGAI, inResults, inCount );
-		} );
-		dnssd_getaddrinfo_set_event_handler( gai,
-		^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-		{
-			switch( inEvent )
-			{
-				case dnssd_event_invalidated:
-					dnssd_release( gai );
-					_FastRecoveryTestRelease( me );
-					break;
-				
-				case dnssd_event_error:
-					require_return( frGAI->gai == gai );
-					frt_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-					_FastRecoveryTestStop( me, inGAIError );
-					break;
-				
-				default:
-					break;
-			}
-		} );
-		frGAI->gai = gai;
-		gai = NULL;
-		dnssd_getaddrinfo_activate( frGAI->gai );
-	}
-	else
-	{
-		dnssd_getaddrinfo_t		gai;
-		
-		dispatch_source_forget( &me->timer );
-		me->timer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, me->queue );
-		require_action( me->timer, exit, err = kNoResourcesErr );
-		
-		dispatch_source_set_timer( me->timer, _dispatch_monotonictime_after_sec( kFastRecoveryTestFinalTimeoutSecs ),
-			kFastRecoveryTestFinalTimeoutSecs * UINT64_C_safe( kNanosecondsPerSecond ),
-			kFastRecoveryTestFinalTimeoutSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 20 ) );
-		dispatch_set_context( me->timer, me );
-		dispatch_source_set_event_handler( me->timer,
-		^{
-			_FastRecoveryTestComplete( me );
-		} );
-		dispatch_activate( me->timer );
-		
-		check( !me->resumeQNAME );
-		ASPrintF( &me->resumeQNAME, "tag-fast-recovery-test-probe.command-resume.%s", me->domain );
-		require_action( me->resumeQNAME, exit, err = kNoMemoryErr );
-		
-		err = CFPropertyListAppendFormatted( NULL, me->report, "%kO=%s", CFSTR( "resumeQNAME" ), me->resumeQNAME );
-		require_noerr( err, exit );
-		
-		gai = dnssd_getaddrinfo_create();
-		require_action( gai, exit, err = kNoResourcesErr );
-		
-		dnssd_getaddrinfo_set_hostname( gai, me->resumeQNAME );
-		dnssd_getaddrinfo_set_flags( gai, 0 );
-		dnssd_getaddrinfo_set_interface_index( gai, kDNSServiceInterfaceIndexAny );
-		dnssd_getaddrinfo_set_protocols( gai, kDNSServiceProtocol_IPv4 );
-		dnssd_getaddrinfo_set_queue( gai, me->queue );
-		dnssd_retain( gai );
-		_FastRecoveryTestRetain( me );
-		dnssd_getaddrinfo_set_result_handler( gai,
-		^( dnssd_getaddrinfo_result_t * const inResults, const size_t inCount )
-		{
-			size_t		i;
-			
-			require_return( me->gai == gai );
-			
-			for( i = 0; i < inCount; ++i )
-			{
-				frt_ulog( kLogLevelInfo, "GAI result -- %@\n", inResults[ i ] );
-			}
-		} );
-		dnssd_getaddrinfo_set_event_handler( gai,
-		^( const dnssd_event_t inEvent, const DNSServiceErrorType inGAIError )
-		{
-			switch( inEvent )
-			{
-				case dnssd_event_invalidated:
-					dnssd_release( gai );
-					_FastRecoveryTestRelease( me );
-					break;
-				
-				case dnssd_event_error:
-					require_return( me->gai == gai );
-					frt_ulog( kLogLevelError, "dnssd_getaddrinfo error: %#m\n", inGAIError );
-					_FastRecoveryTestStop( me, inGAIError );
-					break;
-				
-				default:
-					break;
-			}
-		} );
-		me->gai = gai;
-		gai = NULL;
-		dnssd_getaddrinfo_activate( me->gai );
-		me->suspended = false; // The resume command query will resume the DNS server.
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void
-	_FastRecoveryTestHandleGAIResuts(
-		const FastRecoveryTestRef			me,
-		FastRecoveryGAI * const				inGAI,
-		dnssd_getaddrinfo_result_t * const	inResults,
-		const size_t						inCount )
-{
-	OSStatus		err;
-	size_t			i;
-	
-	for( i = 0; i < inCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t		result = inResults[ i ];
-		
-		frt_ulog( kLogLevelInfo, "GAI result -- %@\n", result );
-		if( !me->suspended )
-		{
-			const sockaddr_ip *							sip;
-			const dnssd_getaddrinfo_result_type_t		type = dnssd_getaddrinfo_result_get_type( result );
-			
-			require_action_quiet( type == dnssd_getaddrinfo_result_type_add, exit, err = kTypeErr );
-			sip = (const sockaddr_ip *) dnssd_getaddrinfo_result_get_address( result );
-			switch( sip->sa.sa_family )
-			{
-				case AF_INET:
-					require_action_quiet( !inGAI->gotResultIPv4, exit, err = kUnexpectedErr );
-					inGAI->gotResultIPv4 = true;
-					break;
-				
-				case AF_INET6:
-					require_action_quiet( !inGAI->gotResultIPv6, exit, err = kUnexpectedErr );
-					inGAI->gotResultIPv6 = true;
-					break;
-				
-				default:
-					err = kTypeErr;
-					goto exit;
-			}
-			if( inGAI->gotResultIPv4 && inGAI->gotResultIPv6 ) dnssd_getaddrinfo_forget( &inGAI->gai );
-		}
-	}
-	err = me->suspended ? kUnexpectedErr : kNoErr;
-	
-exit:
-	if( err ) _FastRecoveryTestStop( me, err );
-}
-
-//===========================================================================================================================
-
-static void	_FastRecoveryTestComplete( const FastRecoveryTestRef me )
-{
-	OSStatus		err;
-	size_t			i;
-	Boolean			resultsMissing = false;
-	
-	for( i = 0; i < countof( me->gaiArray ); ++i )
-	{
-		FastRecoveryGAI * const		frGAI = &me->gaiArray[ i ];
-		
-		err = CFPropertyListAppendFormatted( NULL, me->gaiResults,
-			"{"
-				"%kO=%s"	// hostname
-				"%kO=%b"	// gotResultIPv4
-				"%kO=%b"	// gotResultIPv6
-			"}",
-			CFSTR( "hostname" ),		frGAI->hostname,
-			CFSTR( "gotResultIPv4" ),	frGAI->gotResultIPv4,
-			CFSTR( "gotResultIPv6" ),	frGAI->gotResultIPv6 );
-		require_noerr( err, exit );
-		
-		if( !frGAI->gotResultIPv4 || !frGAI->gotResultIPv6 ) resultsMissing = true;
-	}
-	err = resultsMissing ? kUnderrunErr : kNoErr;
-	
-exit:
-	_FastRecoveryTestStop( me, err );
-}
-#endif	// MDNSRESPONDER_PROJECT
-
-//===========================================================================================================================
-//	RegistrationTestCmd
-//===========================================================================================================================
-
-typedef struct RegistrationSubtest		RegistrationSubtest;
-
-typedef struct
-{
-	CFMutableArrayRef			subtestReports;				// Array of subtest reports.
-	dispatch_source_t			timer;						// Timer to enforce subtest durations.
-	dispatch_source_t			sigSourceINT;				// SIGINT signal handler for a clean test exit.
-	dispatch_source_t			sigSourceTERM;				// SIGTERM signal handler for a clean test exit.
-	RegistrationSubtest *		subtest;					// Current subtest.
-	char *						outputFilePath;				// Path of test result output file. If NULL, stdout will be used.
-	OutputFormatType			outputFormat;				// Format of test results output.
-	CFStringRef					computerNamePrev;			// Previous ComputerName.
-	CFStringRef					localHostNamePrev;			// Previous LocalHostName.
-	NanoTime64					startTime;					// Test's start time.
-	char *						computerName;				// Temporary ComputerName to set during testing. (malloc'd)
-	char *						localHostName;				// Temporary LocalHostName to set during testing. (malloc'd)
-	CFStringEncoding			computerNamePrevEncoding;	// Previous ComputerName's encoding.
-	int							subtestIndex;				// Index of current subtest.
-	Boolean						computerNameSet;			// True if a temporary ComputerName was set.
-	Boolean						localHostNameSet;			// True if a temporary LocalHostName was set.
-	Boolean						failed;						// True if at least one non-skipped subtest failed.
-	Boolean						forBATS;					// True if the test is running in a BATS environment.
-	
-}	RegistrationTest;
-
-typedef enum
-{
-	kRegistrationInterfaceSet_Null			= 0,
-	kRegistrationInterfaceSet_All			= 1,
-	kRegistrationInterfaceSet_AllPlusAWDL	= 2,
-	kRegistrationInterfaceSet_LoopbackOnly	= 3,
-	kRegistrationInterfaceSet_AWDLOnly		= 4
-	
-}	RegistrationInterfaceSet;
-
-typedef struct
-{
-	RegistrationInterfaceSet		interfaceSet;	// Interfaces to register the service over.
-	Boolean							useDefaultName;	// True if registration is to use the default service name.
-	Boolean							useLODiscovery;	// True if discovery is to use kDNSServiceInterfaceIndexLocalOnly.
-	
-}	RegistrationSubtestParams;
-
-static const RegistrationSubtestParams		kRegistrationSubtestParams[] =
-{
-	{ kRegistrationInterfaceSet_All,			true,	false },
-	{ kRegistrationInterfaceSet_All,			false,	false },
-	{ kRegistrationInterfaceSet_AllPlusAWDL,	true,	false },
-	{ kRegistrationInterfaceSet_AllPlusAWDL,	false,	false },
-	{ kRegistrationInterfaceSet_LoopbackOnly,	true,	false },
-	{ kRegistrationInterfaceSet_LoopbackOnly,	false,	false },
-	{ kRegistrationInterfaceSet_AWDLOnly,		true,	false },
-	{ kRegistrationInterfaceSet_AWDLOnly,		false,	false },
-	{ kRegistrationInterfaceSet_All,			true,	true  },
-	{ kRegistrationInterfaceSet_All,			false,	true  },
-	{ kRegistrationInterfaceSet_AllPlusAWDL,	true,	true  },
-	{ kRegistrationInterfaceSet_AllPlusAWDL,	false,	true  },
-	{ kRegistrationInterfaceSet_LoopbackOnly,	true,	true  },
-	{ kRegistrationInterfaceSet_LoopbackOnly,	false,	true  },
-	{ kRegistrationInterfaceSet_AWDLOnly,		true,	true  },
-	{ kRegistrationInterfaceSet_AWDLOnly,		false,	true  }
-};
-
-typedef struct
-{
-	NanoTime64		browseResultTime;	// Per-interface browse result time.
-	NanoTime64		querySRVResultTime;	// Per-interface SRV record query result time.
-	NanoTime64		queryTXTResultTime;	// Per-interface TXT record query result time.
-	
-}	RegistrationResultTimes;
-
-typedef struct
-{
-	MDNSInterfaceItem			base;	// Underlying MDNSInterface linked-list item.
-	RegistrationResultTimes		times;	// Per-interface result times.
-	
-}	RegistrationInterfaceItem;
-
-struct RegistrationSubtest
-{
-	DNSServiceRef					registration;		// DNS-SD service registration.
-	DNSServiceRef					connection;			// Shared DNS-SD connection.
-	DNSServiceRef					browse;				// DNS-SD browse for service's type.
-	DNSServiceRef					querySRV;			// DNS-SD query request for service's SRV record.
-	DNSServiceRef					queryTXT;			// DNS-SD query request for service's TXT record.
-	CFMutableArrayRef				unexpected;			// Array of unexpected registration, browse, and query results.
-#if( TARGET_OS_WATCH )
-	CFMutableArrayRef				ignored;			// Array of unexpected, but ignored, browse and query results.
-#endif
-	const char *					serviceName;		// Service's name.
-	char *							serviceNameCustom;	// Service's name if using a custom name. (malloc'd)
-	char *							serviceType;		// Service's service type. (malloc'd)
-	size_t							serviceTypeLen;		// C string length of service's service type.
-	char *							serviceFQDN;		// Service's FQDN, i.e., name of its SRV and TXT records.
-	uint8_t *						txtPtr;				// Pointer to service's TXT record data. (malloc'd)
-	size_t							txtLen;				// Length of service's TXT record data.
-	RegistrationInterfaceItem *		ifList;				// If ifIndex == 0, interfaces that service should register over.
-	RegistrationResultTimes			ifTimes;			// If ifIndex != 0, result times for interface with that index.
-	RegistrationTest *				test;				// Pointer to parent test.
-	NanoTime64						startTime;			// Subtest's start time.
-	char *							description;		// Subtest's description. (malloc'd)
-	uint32_t						ifIndex;			// Interface index used for service registration.
-	uint16_t						port;				// Service's port number.
-	Boolean							useLODiscovery;		// True if discovery is to use kDNSServiceInterfaceIndexLocalOnly.
-	Boolean							includeAWDL;		// True if the IncludeAWDL flag was used during registration.
-	Boolean							ifIsAWDL;			// True if ifIndex is the index of an AWDL interface.
-	Boolean							skipped;			// True if this subtest is to be skipped.
-	Boolean							registered;			// True if the test service was successfully registered.
-	Boolean							useDefaultName;		// True if the service is to use the default service name.
-};
-
-static OSStatus	_RegistrationTestCreate( RegistrationTest **outTest );
-static void		_RegistrationTestFree( RegistrationTest *inTest );
-static void		_RegistrationTestBegin( void *inContext );
-static void		_RegistrationTestProceed( RegistrationTest *inTest );
-static OSStatus	_RegistrationTestStart( RegistrationTest *inTest );
-static void		_RegistrationTestStop( RegistrationTest *inTest );
-#define _RegistrationTestForget( X )		ForgetCustomEx( X, _RegistrationTestStop, _RegistrationTestFree )
-static OSStatus
-	_RegistrationTestStartSubtest(
-		RegistrationTest *					inTest,
-		const RegistrationSubtestParams *	inParams,
-		Boolean *							outSkipped );
-static OSStatus	_RegistrationTestEndSubtest( RegistrationTest *inTest );
-static void		_RegistrationTestEnd( RegistrationTest *inTest ) ATTRIBUTE_NORETURN;
-static void		_RegistrationTestExit( RegistrationTest *inTest, OSStatus inError ) ATTRIBUTE_NORETURN;
-static OSStatus	_RegistrationSubtestCreate( RegistrationSubtest **outSubtest );
-static void		_RegistrationSubtestStop( RegistrationSubtest *inSubtest );
-static void		_RegistrationSubtestFree( RegistrationSubtest *inSubtest );
-#define _RegistrationSubtestForget( X )		ForgetCustomEx( X, _RegistrationSubtestStop, _RegistrationSubtestFree )
-static OSStatus	_RegistrationTestInterfaceListCreate( Boolean inIncludeAWDL, RegistrationInterfaceItem **outList );
-static OSStatus
-	_RegistrationTestCreateRandomTXTRecord(
-		size_t		inMinLen,
-		size_t		inMaxLen,
-		uint8_t **	outTXTPtr,
-		size_t *	outTXTLen );
-static void DNSSD_API
-	_RegistrationSubtestRegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inType,
-		const char *		inDomain,
-		void *				inContext );
-static void DNSSD_API
-	_RegistrationSubtestBrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inIfIndex,
-		DNSServiceErrorType	inError,
-		const char *		inServiceName,
-		const char *		inServiceType,
-		const char *		inDomain,
-		void *				inContext );
-static void DNSSD_API
-	_RegistrationSubtestQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inIfIndex,
-		DNSServiceErrorType		inError,
-		const char *			inName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-static Boolean	_RegistrationSubtestValidServiceType( const RegistrationSubtest *inSubtest, const char *inServiceType );
-static RegistrationResultTimes *
-	_RegistrationSubtestGetInterfaceResultTimes(
-		RegistrationSubtest *	inSubtest,
-		uint32_t				inIfIndex,
-		Boolean *				outIsAWDL );
-static void		_RegistrationTestTimerHandler( void *inContext );
-#if( TARGET_OS_WATCH )
-static Boolean	_RegistrationTestInterfaceIsWiFi( const char *inIfName );
-#endif
-
-static void	RegistrationTestCmd( void )
-{
-	OSStatus				err;
-	RegistrationTest *		test = NULL;
-	
-	err = _RegistrationTestCreate( &test );
-	require_noerr( err, exit );
-	
-	if( gRegistrationTest_BATSEnvironment ) test->forBATS = true;
-	if( gRegistrationTest_OutputFilePath )
-	{
-		test->outputFilePath = strdup( gRegistrationTest_OutputFilePath );
-		require_action( test->outputFilePath, exit, err = kNoMemoryErr );
-	}
-	
-	err = OutputFormatFromArgString( gRegistrationTest_OutputFormat, &test->outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	dispatch_async_f( dispatch_get_main_queue(), test, _RegistrationTestBegin );
-	dispatch_main();
-	
-exit:
-	if( test ) _RegistrationTestFree( test );
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RegistrationTestCreate( RegistrationTest **outTest )
-{
-	OSStatus				err;
-	RegistrationTest *		obj;
-	
-	obj = (RegistrationTest *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->subtestReports = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->subtestReports, exit, err = kNoMemoryErr );
-	
-	*outTest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _RegistrationTestFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestFree( RegistrationTest *inTest )
-{
-	check( !inTest->timer );
-	check( !inTest->sigSourceINT );
-	check( !inTest->sigSourceTERM );
-	check( !inTest->computerNameSet );
-	check( !inTest->localHostNameSet );
-	check( !inTest->subtest );
-	ForgetCF( &inTest->subtestReports );
-	ForgetMem( &inTest->outputFilePath );
-	ForgetCF( &inTest->computerNamePrev );
-	ForgetCF( &inTest->localHostNamePrev );
-	ForgetMem( &inTest->computerName );
-	ForgetMem( &inTest->localHostName );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestBegin( void *inContext )
-{
-	_RegistrationTestProceed( (RegistrationTest *) inContext );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestProceed( RegistrationTest *inTest )
-{
-	OSStatus		err;
-	Boolean			skippedSubtest;
-	
-	do
-	{
-		int		subtestIndex;
-		
-		if( !inTest->startTime )
-		{
-			err = _RegistrationTestStart( inTest );
-			require_noerr_quiet( err, exit );
-			
-			inTest->startTime = NanoTimeGetCurrent();
-		}
-		else
-		{
-			err = _RegistrationTestEndSubtest( inTest );
-			require_noerr( err, exit );
-			
-			++inTest->subtestIndex;
-		}
-		
-		subtestIndex = inTest->subtestIndex;
-		if( subtestIndex < (int) countof( kRegistrationSubtestParams ) )
-		{
-			err = _RegistrationTestStartSubtest( inTest, &kRegistrationSubtestParams[ subtestIndex ], &skippedSubtest );
-			require_noerr_quiet( err, exit );
-		}
-		else
-		{
-			_RegistrationTestEnd( inTest );
-		}
-		
-	}	while( skippedSubtest );
-	
-exit:
-	if( err ) _RegistrationTestExit( inTest, err );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestSignalHandler( void *inContext );
-
-static OSStatus	_RegistrationTestStart( RegistrationTest *inTest )
-{
-	OSStatus		err;
-	char			tag[ 6 + 1 ];
-	
-	// Save original ComputerName and LocalHostName.
-	
-	check( !inTest->computerNamePrev );
-	inTest->computerNamePrev = SCDynamicStoreCopyComputerName( NULL, &inTest->computerNamePrevEncoding );
-	err = map_scerror( inTest->computerNamePrev );
-	require_noerr( err, exit );
-	
-	check( !inTest->localHostNamePrev );
-	inTest->localHostNamePrev = SCDynamicStoreCopyLocalHostName( NULL );
-	err = map_scerror( inTest->localHostNamePrev );
-	require_noerr( err, exit );
-	
-	// Generate a unique test ComputerName.
-	
-	check( !inTest->computerName ); 
-	ASPrintF( &inTest->computerName, "dnssdutil-regtest-computer-name-%s",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( inTest->computerName, exit, err = kNoMemoryErr );
-	
-	// Generate a unique test LocalHostName.
-	
-	check( !inTest->localHostName ); 
-	ASPrintF( &inTest->localHostName, "dnssdutil-regtest-local-hostname-%s",
-		_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-	require_action( inTest->localHostName, exit, err = kNoMemoryErr );
-	
-	// Set up SIGINT signal handler.
-	
-	signal( SIGINT, SIG_IGN );
-	check( !inTest->sigSourceINT ); 
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), _RegistrationTestSignalHandler, inTest,
-		&inTest->sigSourceINT );
-	require_noerr( err, exit );
-	dispatch_resume( inTest->sigSourceINT );
-	
-	// Set up SIGTERM signal handler.
-	
-	signal( SIGTERM, SIG_IGN );
-	check( !inTest->sigSourceTERM ); 
-	err = DispatchSignalSourceCreate( SIGTERM, dispatch_get_main_queue(), _RegistrationTestSignalHandler, inTest,
-		&inTest->sigSourceTERM );
-	require_noerr( err, exit );
-	dispatch_resume( inTest->sigSourceTERM );
-	
-	// Set test ComputerName.
-	
-	check( !inTest->computerNameSet );
-	err = _SetComputerNameWithUTF8CString( inTest->computerName );
-	require_noerr( err, exit );
-	inTest->computerNameSet = true;
-	
-	// Set test LocalHostName.
-	
-	check( !inTest->localHostNameSet );
-	err = _SetLocalHostNameWithUTF8CString( inTest->localHostName );
-	require_noerr( err, exit );
-	inTest->localHostNameSet = true;
-	
-exit:
-	if( err ) _RegistrationTestStop( inTest );
-	return( err );
-}
-
-static void	_RegistrationTestSignalHandler( void *inContext )
-{
-	RegistrationTest * const		test = (RegistrationTest *) inContext;
-	
-	FPrintF( stderr, "Registration test got a SIGINT or SIGTERM signal, exiting..." );
-	
-	_RegistrationTestExit( test, kCanceledErr );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestStop( RegistrationTest *inTest )
-{
-	OSStatus		err;
-	
-	dispatch_source_forget( &inTest->timer );
-	dispatch_source_forget( &inTest->sigSourceINT );
-	dispatch_source_forget( &inTest->sigSourceTERM );
-	_RegistrationSubtestForget( &inTest->subtest );
-	if( inTest->computerNameSet )
-	{
-		err = _SetComputerName( inTest->computerNamePrev, inTest->computerNamePrevEncoding );
-		check_noerr( err );
-		if( !err ) inTest->computerNameSet = false;
-	}
-	if( inTest->localHostNameSet )
-	{
-		err = _SetLocalHostName( inTest->localHostNamePrev );
-		check_noerr( err );
-		if( !err ) inTest->localHostNameSet = false;
-	}
-}
-
-//===========================================================================================================================
-
-#define kRegistrationTestSubtestDurationSecs		5
-
-static OSStatus
-	_RegistrationTestStartSubtest(
-		RegistrationTest *					inTest,
-		const RegistrationSubtestParams *	inParams,
-		Boolean *							outSkipped )
-{
-	OSStatus					err;
-	RegistrationSubtest *		subtest;
-	const char *				interfaceDesc;
-	DNSServiceFlags				flags;
-	char						tag[ 6 + 1 ];
-	
-	subtest	= NULL;
-	err = _RegistrationSubtestCreate( &subtest );
-	require_noerr( err, exit );
-	
-	subtest->test			= inTest;
-	subtest->useDefaultName	= inParams->useDefaultName;
-	subtest->useLODiscovery	= inParams->useLODiscovery;
-	
-	// Determine registration interfaces.
-	
-	switch( inParams->interfaceSet )
-	{
-		case kRegistrationInterfaceSet_All:
-			subtest->ifIndex = kDNSServiceInterfaceIndexAny;
-			
-			if( !subtest->useLODiscovery )
-			{
-				err = _RegistrationTestInterfaceListCreate( false, &subtest->ifList );
-				require_noerr( err, exit );
-			}
-			interfaceDesc = "all interfaces (excluding AWDL)";
-			break;
-		
-		case kRegistrationInterfaceSet_AllPlusAWDL:
-			subtest->ifIndex		= kDNSServiceInterfaceIndexAny;
-			subtest->includeAWDL	= true;
-			
-			if( !subtest->useLODiscovery )
-			{
-				err = _RegistrationTestInterfaceListCreate( true, &subtest->ifList );
-				require_noerr( err, exit );
-			}
-			interfaceDesc = "all interfaces (including AWDL)";
-			break;
-		
-		case kRegistrationInterfaceSet_LoopbackOnly:
-			subtest->ifIndex = if_nametoindex( "lo0" );
-			if( subtest->ifIndex == 0 )
-			{
-				FPrintF( stderr, "Failed to get index for loopback interface lo0.\n" );
-				err = kNoResourcesErr;
-				goto exit;
-			}
-			interfaceDesc = "loopback interface";
-			break;
-		
-		case kRegistrationInterfaceSet_AWDLOnly:
-			err = _MDNSInterfaceGetAny( kMDNSInterfaceSubset_AWDL, NULL, &subtest->ifIndex );
-			if( err == kNotFoundErr )
-			{
-				FPrintF( stderr, "Warning: No mDNS-capable AWDL interface is available.\n" );
-				subtest->skipped = true;
-				err = kNoErr;
-			}
-			require_noerr( err, exit );
-			
-			subtest->ifIsAWDL = true;
-			interfaceDesc = "AWDL interface";
-			break;
-		
-		default:
-			err = kParamErr;
-			goto exit;
-	}
-	
-	// Create description.
-	
-	ASPrintF( &subtest->description, "Service registration over %s using %s service name.%s",
-		interfaceDesc, subtest->useDefaultName ? "default" : "custom",
-		subtest->useLODiscovery ? " (LocalOnly discovery)" : "" );
-	require_action( subtest->description, exit, err = kNoMemoryErr );
-	
-	if( subtest->skipped )
-	{
-		subtest->startTime = NanoTimeGetCurrent();
-	}
-	else
-	{
-		// Generate a service name.
-		
-		if( subtest->useDefaultName )
-		{
-			subtest->serviceName = inTest->computerName;
-		}
-		else
-		{
-			ASPrintF( &subtest->serviceNameCustom, "dnssdutil-regtest-service-name-%s",
-				_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-			require_action( subtest->serviceNameCustom, exit, err = kNoMemoryErr );
-			
-			subtest->serviceName = subtest->serviceNameCustom;
-		}
-		
-		// Generate a service type.
-		
-		ASPrintF( &subtest->serviceType, "_regtest-%s._udp",
-			_RandomStringExact( kLowerAlphaNumericCharSet, kLowerAlphaNumericCharSetSize, sizeof( tag ) - 1, tag ) );
-		require_action( subtest->serviceType, exit, err = kNoMemoryErr );
-		
-		subtest->serviceTypeLen = strlen( subtest->serviceType );
-		
-		// Create SRV and TXT record name FQDN.
-		
-		ASPrintF( &subtest->serviceFQDN, "%s.%s.local.", subtest->serviceName, subtest->serviceType );
-		require_action( subtest->serviceFQDN, exit, err = kNoMemoryErr );
-		
-		// Generate a port number.
-		
-		subtest->port = (uint16_t) RandomRange( 60000, 65535 );
-		
-		// Generate TXT record data.
-		
-		err = _RegistrationTestCreateRandomTXTRecord( 100, 1000, &subtest->txtPtr, &subtest->txtLen );
-		require_noerr( err, exit );
-		
-		// Register service.
-		
-		subtest->startTime = NanoTimeGetCurrent();
-		
-		flags = kDNSServiceFlagsNoAutoRename;
-		if( subtest->includeAWDL ) flags |= kDNSServiceFlagsIncludeAWDL;
-		err = DNSServiceRegister( &subtest->registration, flags, subtest->ifIndex,
-			subtest->useDefaultName ? NULL : subtest->serviceNameCustom, subtest->serviceType, "local.",
-			NULL, htons( subtest->port ), (uint16_t) subtest->txtLen, subtest->txtPtr,
-			_RegistrationSubtestRegisterCallback, subtest );
-		require_noerr( err, exit );
-		
-		err = DNSServiceSetDispatchQueue( subtest->registration, dispatch_get_main_queue() );
-		require_noerr( err, exit );
-		
-		// Start timer.
-		
-		check( !inTest->timer );
-		err = DispatchTimerOneShotCreate( dispatch_time_seconds( kRegistrationTestSubtestDurationSecs ),
-			INT64_C_safe( kRegistrationTestSubtestDurationSecs ) * kNanosecondsPerSecond / 10, dispatch_get_main_queue(),
-			_RegistrationTestTimerHandler, inTest, &inTest->timer );
-		require_noerr( err, exit );
-		dispatch_resume( inTest->timer );
-	}
-	
-	*outSkipped = subtest->skipped;
-	
-	check( !inTest->subtest );
-	inTest->subtest = subtest;
-	subtest = NULL;
-	
-exit:
-	_RegistrationSubtestForget( &subtest );
-	return( err );
-}
-
-//===========================================================================================================================
-
-#define kRegistrationTestReportKey_ComputerName			CFSTR( "computerName" )			// String
-#define kRegistrationTestReportKey_Description			CFSTR( "description" )			// String
-#define kRegistrationTestReportKey_Domain				CFSTR( "domain" )				// String
-#define kRegistrationTestReportKey_EndTime				CFSTR( "endTime" )				// String
-#define kRegistrationTestReportKey_Error				CFSTR( "error" )				// Integer
-#define kRegistrationTestReportKey_Flags				CFSTR( "flags" )				// Integer
-#define kRegistrationTestReportKey_IgnoredResults		CFSTR( "ignoredResults" )		// Array of dictionaries
-#define kRegistrationTestReportKey_InterfaceIndex		CFSTR( "ifIndex" )				// Integer
-#define kRegistrationTestReportKey_InterfaceName		CFSTR( "ifName" )				// String
-#define kRegistrationTestReportKey_LocalHostName		CFSTR( "localHostName" )		// String
-#define kRegistrationTestReportKey_MissingResults		CFSTR( "missingResults" )		// Array of dictionaries
-#define kRegistrationTestReportKey_Pass					CFSTR( "pass" )					// Boolean
-#define kRegistrationTestReportKey_Port					CFSTR( "port" )					// Integer
-#define kRegistrationTestReportKey_RDataFormatted		CFSTR( "rdataFormatted" )		// String
-#define kRegistrationTestReportKey_RDataHexString		CFSTR( "rdataHexString" )		// String
-#define kRegistrationTestReportKey_RecordClass			CFSTR( "recordClass" )			// Integer
-#define kRegistrationTestReportKey_RecordType			CFSTR( "recordType" )			// Integer
-#define kRegistrationTestReportKey_Registered			CFSTR( "registered" )			// Boolean
-#define kRegistrationTestReportKey_ResultType			CFSTR( "resultType" )			// String
-#define kRegistrationTestReportKey_ServiceFQDN			CFSTR( "serviceFQDN" )			// String
-#define kRegistrationTestReportKey_ServiceName			CFSTR( "serviceName" )			// String
-#define kRegistrationTestReportKey_ServiceType			CFSTR( "serviceType" )			// String
-#define kRegistrationTestReportKey_Skipped				CFSTR( "skipped" )				// Boolean
-#define kRegistrationTestReportKey_StartTime			CFSTR( "startTime" )			// String
-#define kRegistrationTestReportKey_Subtests				CFSTR( "subtests" )				// Array of dictionaries
-#define kRegistrationTestReportKey_Timestamp			CFSTR( "timestamp" )			// String
-#define kRegistrationTestReportKey_TXT					CFSTR( "txt" )					// String
-#define kRegistrationTestReportKey_UnexpectedResults	CFSTR( "unexpectedResults" )	// Array of dictionaries
-#define kRegistrationTestReportKey_UsedDefaultName		CFSTR( "usedDefaultName" )		// Boolean
-#define kRegistrationTestReportKey_UsedLODiscovery		CFSTR( "usedLODiscovery" )		// Boolean
-
-#define kRegistrationTestResultType_Browse				CFSTR( "browse" )
-#define kRegistrationTestResultType_Query				CFSTR( "query" )
-#define kRegistrationTestResultType_QuerySRV			CFSTR( "querySRV" )
-#define kRegistrationTestResultType_QueryTXT			CFSTR( "queryTXT" )
-#define kRegistrationTestResultType_Registration		CFSTR( "registration" )
-
-static OSStatus
-	_RegistrationTestAppendMissingResults(
-		CFMutableArrayRef				inMissingResults,
-		const RegistrationResultTimes *	inTimes,
-		uint32_t						inIfIndex,
-		const char *					inIfName );
-
-static OSStatus	_RegistrationTestEndSubtest( RegistrationTest *inTest )
-{
-	OSStatus					err;
-	RegistrationSubtest *		subtest;
-	CFMutableDictionaryRef		subtestReport;
-	CFMutableArrayRef			missing;
-	char *						txtStr;
-	NanoTime64					now;
-	Boolean						subtestFailed;
-	char						startTime[ 32 ];
-	char						endTime[ 32 ];
-	char						ifNameBuf[ IF_NAMESIZE + 1 ];
-	
-	now = NanoTimeGetCurrent();
-	
-	subtest = inTest->subtest;
-	inTest->subtest = NULL;
-	_RegistrationSubtestStop( subtest );
-	
-	missing			= NULL;
-	subtestReport	= NULL;
-	txtStr			= NULL;
-	if( subtest->txtPtr )
-	{
-		err = DNSRecordDataToString( subtest->txtPtr, subtest->txtLen, kDNSServiceType_TXT, &txtStr );
-		require_noerr( err, exit );
-	}
-	_NanoTime64ToTimestamp( subtest->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &subtestReport,
-		"{"
-			"%kO=%s"	// description
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// serviceFQDN
-			"%kO=%lli"	// ifIndex
-			"%kO=%s"	// ifName
-			"%kO=%lli"	// port
-			"%kO=%s"	// txt
-			"%kO=%b"	// registered
-			"%kO=%b"	// usedDefaultName
-			"%kO=%b"	// usedLODiscovery
-		"}",
-		kRegistrationTestReportKey_Description,		subtest->description,
-		kRegistrationTestReportKey_StartTime,		startTime,
-		kRegistrationTestReportKey_EndTime,			endTime,
-		kRegistrationTestReportKey_ServiceFQDN,		subtest->serviceFQDN,
-		kRegistrationTestReportKey_InterfaceIndex,	(int64_t) subtest->ifIndex,
-		kRegistrationTestReportKey_InterfaceName,	if_indextoname( subtest->ifIndex, ifNameBuf ),
-		kRegistrationTestReportKey_Port,			(int64_t) subtest->port,
-		kRegistrationTestReportKey_TXT,				txtStr,
-		kRegistrationTestReportKey_Registered,		(int) subtest->registered,
-		kRegistrationTestReportKey_UsedDefaultName,	(int) subtest->useDefaultName,
-		kRegistrationTestReportKey_UsedLODiscovery,	(int) subtest->useLODiscovery );
-	ForgetMem( &txtStr );
-	require_noerr( err, exit );
-	
-	if( !subtest->skipped && subtest->registered )
-	{
-		missing = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-		require_action( missing, exit, err = kNoMemoryErr );
-		
-		if( subtest->ifList )
-		{
-			RegistrationInterfaceItem *		item;
-			
-			for( item = subtest->ifList; item; item = (RegistrationInterfaceItem *) item->base.next )
-			{
-			#if( TARGET_OS_WATCH )
-				if( inTest->forBATS && item->base.isWiFi ) continue;
-			#endif
-				err = _RegistrationTestAppendMissingResults( missing, &item->times, item->base.ifIndex, item->base.ifName );
-				require_noerr( err, exit );
-			}
-		}
-		else
-		{
-			err = _RegistrationTestAppendMissingResults( missing, &subtest->ifTimes, subtest->ifIndex, NULL );
-			require_noerr( err, exit );
-		}
-		
-		subtestFailed = false;
-		if( CFArrayGetCount( missing ) > 0 )
-		{
-			subtestFailed = true;
-			CFDictionarySetValue( subtestReport, kRegistrationTestReportKey_MissingResults, missing );
-		}
-		if( CFArrayGetCount( subtest->unexpected ) > 0 )
-		{
-			subtestFailed = true;
-			CFDictionarySetValue( subtestReport, kRegistrationTestReportKey_UnexpectedResults, subtest->unexpected );
-		}
-	#if( TARGET_OS_WATCH )
-		if( CFArrayGetCount( subtest->ignored ) > 0 )
-		{
-			CFDictionarySetValue( subtestReport, kRegistrationTestReportKey_IgnoredResults, subtest->ignored );
-		}
-	#endif
-	}
-	else
-	{
-		subtestFailed = true;
-	}
-	
-	CFDictionarySetBoolean( subtestReport, kRegistrationTestReportKey_Pass, subtestFailed ? false : true );
-	if( subtestFailed )
-	{
-		CFDictionarySetBoolean( subtestReport, kRegistrationTestReportKey_Skipped, subtest->skipped );
-		if( !subtest->skipped ) inTest->failed = true;
-	}
-	CFArrayAppendValue( inTest->subtestReports, subtestReport );
-	
-exit:
-	CFReleaseNullSafe( missing );
-	CFReleaseNullSafe( subtestReport );
-	_RegistrationSubtestFree( subtest );
-	return( err );
-}
-
-static OSStatus
-	_RegistrationTestAppendMissingResult(
-		CFMutableArrayRef	inMissingResults,
-		CFStringRef			inType,
-		uint32_t			inIfIndex,
-		const char *		inIfName );
-
-static OSStatus
-	_RegistrationTestAppendMissingResults(
-		CFMutableArrayRef				inMissingResults,
-		const RegistrationResultTimes *	inTimes,
-		uint32_t						inIfIndex,
-		const char *					inIfName )
-{
-	OSStatus		err;
-	
-	if( !inTimes->browseResultTime )
-	{
-		err = _RegistrationTestAppendMissingResult( inMissingResults, kRegistrationTestResultType_Browse,
-			inIfIndex, inIfName );
-		require_noerr( err, exit );
-	}
-	if( !inTimes->querySRVResultTime )
-	{
-		err = _RegistrationTestAppendMissingResult( inMissingResults, kRegistrationTestResultType_QuerySRV,
-			inIfIndex, inIfName );
-		require_noerr( err, exit );
-	}
-	if( !inTimes->queryTXTResultTime )
-	{
-		err = _RegistrationTestAppendMissingResult( inMissingResults, kRegistrationTestResultType_QueryTXT,
-			inIfIndex, inIfName );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-static OSStatus
-	_RegistrationTestAppendMissingResult(
-		CFMutableArrayRef	inMissingResults,
-		CFStringRef			inType,
-		uint32_t			inIfIndex,
-		const char *		inIfName )
-{
-	OSStatus		err;
-	char			ifName[ IF_NAMESIZE + 1 ];
-	
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, inMissingResults,
-		"{"
-			"%kO=%O"	// resultType
-			"%kO=%lli"	// ifIndex
-			"%kO=%s"	// ifName
-		"}",
-		kRegistrationTestReportKey_ResultType,		inType,
-		kRegistrationTestReportKey_InterfaceIndex,	(int64_t) inIfIndex,
-		kRegistrationTestReportKey_InterfaceName,	inIfName ? inIfName : if_indextoname( inIfIndex, ifName ) );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestEnd( RegistrationTest *inTest )
-{
-	OSStatus				err;
-	NanoTime64				now;
-	CFPropertyListRef		plist;
-	char					startTime[ 32 ];
-	char					endTime[ 32 ];
-	
-	now = NanoTimeGetCurrent();
-	_NanoTime64ToTimestamp( inTest->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-	
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=%s"	// computerName
-			"%kO=%s"	// localHostName
-			"%kO=%O"	// subtests
-			"%kO=%b"	// pass
-		"}",
-		kRegistrationTestReportKey_StartTime,		startTime,
-		kRegistrationTestReportKey_EndTime,			endTime,
-		kRegistrationTestReportKey_ComputerName,	inTest->computerName,
-		kRegistrationTestReportKey_LocalHostName,	inTest->localHostName,
-		kRegistrationTestReportKey_Subtests,		inTest->subtestReports,
-		kRegistrationTestReportKey_Pass,			inTest->failed ? false : true );
-	require_noerr( err, exit );
-	
-	err = OutputPropertyList( plist, inTest->outputFormat, inTest->outputFilePath );
-	CFRelease( plist );
-	require_noerr( err, exit );
-	
-exit:
-	_RegistrationTestExit( inTest, err );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestExit( RegistrationTest *inTest, OSStatus inError )
-{
-	int		exitCode;
-	
-	if( inError )
-	{
-		FPrintF( stderr, "error: %#m\n", inError );
-		exitCode = 1;
-	}
-	else
-	{
-		exitCode = inTest->failed ? 2 : 0;
-	}
-	_RegistrationTestForget( &inTest );
-	exit( exitCode );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RegistrationSubtestCreate( RegistrationSubtest **outSubtest )
-{
-	OSStatus					err;
-	RegistrationSubtest *		obj;
-	
-	obj = (RegistrationSubtest *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->unexpected = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->unexpected, exit, err = kNoMemoryErr );
-	
-#if( TARGET_OS_WATCH )
-	obj->ignored = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	require_action( obj->ignored, exit, err = kNoMemoryErr );
-#endif
-	
-	*outSubtest = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _RegistrationSubtestFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationSubtestFree( RegistrationSubtest *inSubtest )
-{
-	check( !inSubtest->registration );
-	check( !inSubtest->browse );
-	check( !inSubtest->querySRV );
-	check( !inSubtest->queryTXT );
-	check( !inSubtest->connection );
-	ForgetMem( &inSubtest->serviceNameCustom );
-	ForgetMem( &inSubtest->serviceType );
-	ForgetMem( &inSubtest->serviceFQDN );
-	ForgetMem( &inSubtest->txtPtr );
-	ForgetCF( &inSubtest->unexpected );
-#if( TARGET_OS_WATCH )
-	ForgetCF( &inSubtest->ignored );
-#endif
-	_MDNSInterfaceListForget( (MDNSInterfaceItem **) &inSubtest->ifList );
-	ForgetMem( &inSubtest->description );
-	free( inSubtest );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationSubtestStop( RegistrationSubtest *inSubtest )
-{
-	DNSServiceForget( &inSubtest->registration );
-	DNSServiceForget( &inSubtest->browse );
-	DNSServiceForget( &inSubtest->querySRV );
-	DNSServiceForget( &inSubtest->queryTXT );
-	DNSServiceForget( &inSubtest->connection );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_RegistrationTestInterfaceListCreate( Boolean inIncludeAWDL, RegistrationInterfaceItem **outList )
-{
-	OSStatus						err;
-	RegistrationInterfaceItem *		list;
-	const MDNSInterfaceSubset		subset = inIncludeAWDL ? kMDNSInterfaceSubset_All : kMDNSInterfaceSubset_NonAWDL;
-	
-	err = _MDNSInterfaceListCreate( subset, sizeof( *list ), (MDNSInterfaceItem **) &list );
-	require_noerr( err, exit );
-	
-	*outList = list;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus
-	_RegistrationTestCreateRandomTXTRecord(
-		size_t		inMinLen,
-		size_t		inMaxLen,
-		uint8_t **	outTXTPtr,
-		size_t *	outTXTLen )
-{
-	OSStatus			err;
-	uint8_t *			ptr;
-	const uint8_t *		txtEnd;
-	uint8_t *			txtPtr = NULL;
-	size_t				txtLen;
-	
-	require_action_quiet( inMinLen <= inMaxLen, exit, err = kSizeErr );
-	
-	txtLen = RandomRange( inMinLen, inMaxLen );
-	txtPtr = (uint8_t *) malloc( txtLen + 1 );
-	require_action( txtPtr, exit, err = kNoMemoryErr );
-	
-	_RandomStringExact( kAlphaNumericCharSet, sizeof_string( kAlphaNumericCharSet ), txtLen, (char *)txtPtr );
-	
-	ptr		= txtPtr;
-	txtEnd	= &txtPtr[ txtLen ];
-	while( ptr < txtEnd )
-	{
-		size_t		maxLen, len;
-		
-		maxLen = ( (size_t)( txtEnd - ptr ) ) - 1;
-		len = RandomRange( 1, 255 );
-		if( len > maxLen ) len = maxLen;
-		
-		*ptr = (uint8_t) len;
-		ptr += ( 1 + len );
-	}
-	check( ptr == txtEnd );
-	
-	if( outTXTPtr )
-	{
-		*outTXTPtr = txtPtr;
-		txtPtr = NULL;
-	}
-	if( outTXTLen ) *outTXTLen = txtLen;
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( txtPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_RegistrationSubtestRegisterCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		DNSServiceErrorType	inError,
-		const char *		inServiceName,
-		const char *		inServiceType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	OSStatus						err;
-	const NanoTime64				now		= NanoTimeGetCurrent();
-	RegistrationSubtest * const		subtest	= (RegistrationSubtest *) inContext;
-	
-	Unused( inSDRef );
-	
-	if( ( inFlags & kDNSServiceFlagsAdd ) && !inError &&
-		( strcasecmp( inServiceName, subtest->serviceName ) == 0 ) &&
-		_RegistrationSubtestValidServiceType( subtest, inServiceType ) &&
-		( strcasecmp( inDomain, "local." ) == 0 ) )
-	{
-		if( !subtest->registered )
-		{
-			DNSServiceRef				sdRef;
-			const DNSServiceFlags		flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsIncludeAWDL;
-			
-			subtest->registered = true;
-			
-			// Create shared connection.
-			
-			check( !subtest->connection );
-			err = DNSServiceCreateConnection( &subtest->connection );
-			require_noerr( err, exit );
-			
-			err = DNSServiceSetDispatchQueue( subtest->connection, dispatch_get_main_queue() );
-			require_noerr( err, exit );
-			
-			// Start browse.
-			
-			check( !subtest->browse );
-			sdRef = subtest->connection;
-			err = DNSServiceBrowse( &sdRef, flags,
-				subtest->useLODiscovery ? kDNSServiceInterfaceIndexLocalOnly : kDNSServiceInterfaceIndexAny,
-				subtest->serviceType, "local.", _RegistrationSubtestBrowseCallback, subtest );
-			require_noerr( err, exit );
-			
-			subtest->browse = sdRef;
-		}
-	}
-	else
-	{
-		char		timestamp[ 32 ];
-		
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, subtest->unexpected,
-			"{"
-				"%kO=%O"	// resultType
-				"%kO=%s"	// timestamp
-				"%kO=%lli"	// flags
-				"%kO=%lli"	// error
-				"%kO=%s"	// serviceName
-				"%kO=%s"	// serviceType
-				"%kO=%s"	// domain
-			"}",
-			kRegistrationTestReportKey_ResultType,	kRegistrationTestResultType_Registration,
-			kRegistrationTestReportKey_Timestamp,	_NanoTime64ToTimestamp( now, timestamp, sizeof( timestamp ) ),
-			kRegistrationTestReportKey_Flags,		(int64_t) inFlags,
-			kRegistrationTestReportKey_Error,		(int64_t) inError,
-			kRegistrationTestReportKey_ServiceName,	inServiceName,
-			kRegistrationTestReportKey_ServiceType,	inServiceType,
-			kRegistrationTestReportKey_Domain,		inDomain );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) _RegistrationTestExit( subtest->test, err );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_RegistrationSubtestBrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inIfIndex,
-		DNSServiceErrorType	inError,
-		const char *		inServiceName,
-		const char *		inServiceType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	OSStatus						err;
-	NanoTime64						now;
-	RegistrationSubtest * const		subtest = (RegistrationSubtest *) inContext;
-	Boolean							serviceIsCorrect, resultIsExpected;
-	
-	Unused( inSDRef );
-	
-	now = NanoTimeGetCurrent();
-	if( !inError && ( strcasecmp( inServiceName, subtest->serviceName ) == 0 ) &&
-		_RegistrationSubtestValidServiceType( subtest, inServiceType ) && ( strcasecmp( inDomain, "local." ) == 0 ) )
-	{
-		serviceIsCorrect = true;
-	}
-	else
-	{
-		serviceIsCorrect = false;
-	}
-	
-	resultIsExpected = false;
-	if( serviceIsCorrect && ( inFlags & kDNSServiceFlagsAdd ) )
-	{
-		RegistrationResultTimes *		times;
-		
-		times = _RegistrationSubtestGetInterfaceResultTimes( subtest, inIfIndex, NULL );
-		if( times )
-		{
-			DNSServiceRef				sdRef;
-			const DNSServiceFlags		flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsIncludeAWDL;
-			uint32_t					ifIndex;
-			
-			resultIsExpected = true;
-			if( !times->browseResultTime ) times->browseResultTime = now;
-			
-			ifIndex = subtest->useLODiscovery ? kDNSServiceInterfaceIndexLocalOnly : kDNSServiceInterfaceIndexAny;
-			if( !subtest->querySRV )
-			{
-				// Start SRV record query.
-				
-				sdRef = subtest->connection;
-				err = DNSServiceQueryRecord( &sdRef, flags, ifIndex, subtest->serviceFQDN, kDNSServiceType_SRV,
-					kDNSServiceClass_IN, _RegistrationSubtestQueryCallback, subtest );
-				require_noerr( err, exit );
-				
-				subtest->querySRV = sdRef;
-			}
-			if( !subtest->queryTXT )
-			{
-				// Start TXT record query.
-				
-				sdRef = subtest->connection;
-				err = DNSServiceQueryRecord( &sdRef, flags, ifIndex, subtest->serviceFQDN, kDNSServiceType_TXT,
-					kDNSServiceClass_IN, _RegistrationSubtestQueryCallback, subtest );
-				require_noerr( err, exit );
-				
-				subtest->queryTXT = sdRef;
-			}
-		}
-	}
-	
-	if( !resultIsExpected )
-	{
-		CFMutableArrayRef		resultArray;
-		char					timestamp[ 32 ];
-		const char *			ifNamePtr;
-		char					ifNameBuf[ IF_NAMESIZE + 1 ];
-		
-		ifNamePtr = if_indextoname( inIfIndex, ifNameBuf );
-		resultArray = subtest->unexpected;
-	#if( TARGET_OS_WATCH )
-		if( subtest->test->forBATS && ( subtest->ifIndex == kDNSServiceInterfaceIndexAny ) &&
-			ifNamePtr && _RegistrationTestInterfaceIsWiFi( ifNamePtr ) && serviceIsCorrect )
-		{
-			resultArray = subtest->ignored;
-		}
-	#endif
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, resultArray,
-			"{"
-				"%kO=%O"	// resultType
-				"%kO=%s"	// timestamp
-				"%kO=%lli"	// flags
-				"%kO=%lli"	// ifIndex
-				"%kO=%s"	// ifName
-				"%kO=%lli"	// error
-				"%kO=%s"	// serviceName
-				"%kO=%s"	// serviceType
-				"%kO=%s"	// domain
-			"}",
-			kRegistrationTestReportKey_ResultType,		kRegistrationTestResultType_Browse,
-			kRegistrationTestReportKey_Timestamp,		_NanoTime64ToTimestamp( now, timestamp, sizeof( timestamp ) ),
-			kRegistrationTestReportKey_Flags,			(int64_t) inFlags,
-			kRegistrationTestReportKey_InterfaceIndex,	(int64_t) inIfIndex,
-			kRegistrationTestReportKey_InterfaceName,	ifNamePtr,
-			kRegistrationTestReportKey_Error,			(int64_t) inError,
-			kRegistrationTestReportKey_ServiceName,		inServiceName,
-			kRegistrationTestReportKey_ServiceType,		inServiceType,
-			kRegistrationTestReportKey_Domain,			inDomain );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) _RegistrationTestExit( subtest->test, err );
-}
-
-//===========================================================================================================================
-
-static Boolean
-	_RegistrationSubtestIsSRVRecordDataValid(
-		RegistrationSubtest *	inSubtest,
-		const uint8_t *			inRDataPtr,
-		size_t					inRDataLen,
-		Boolean					inExpectRandHostname );
-
-static void DNSSD_API
-	_RegistrationSubtestQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inIfIndex,
-		DNSServiceErrorType		inError,
-		const char *			inName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus						err;
-	NanoTime64						now;
-	RegistrationSubtest * const		subtest = (RegistrationSubtest *) inContext;
-	Boolean							resultIsExpected;
-	
-	Unused( inSDRef );
-	Unused( inTTL );
-	
-	now = NanoTimeGetCurrent();
-	resultIsExpected = false;
-	if( ( inFlags & kDNSServiceFlagsAdd ) && !inError && ( strcasecmp( inName, subtest->serviceFQDN ) == 0 ) &&
-		( inClass == kDNSServiceClass_IN ) )
-	{
-		RegistrationResultTimes *		times;
-		Boolean							isAWDL;
-		
-		times = _RegistrationSubtestGetInterfaceResultTimes( subtest, inIfIndex, &isAWDL );
-		if( times )
-		{
-			if( inType == kDNSServiceType_SRV )
-			{
-				Boolean		expectRandHostname;
-				
-				if( isAWDL || ( ( subtest->ifIndex == kDNSServiceInterfaceIndexAny ) && subtest->includeAWDL ) )
-				{
-					expectRandHostname = true;
-				}
-				else
-				{
-					expectRandHostname = false;
-				}
-				if( _RegistrationSubtestIsSRVRecordDataValid( subtest, inRDataPtr, inRDataLen, expectRandHostname ) )
-				{
-					resultIsExpected = true;
-					if( !times->querySRVResultTime ) times->querySRVResultTime = now;
-				}
-			}
-			else if( inType == kDNSServiceType_TXT )
-			{
-				if( MemEqual( inRDataPtr, inRDataLen, subtest->txtPtr, subtest->txtLen ) )
-				{
-					resultIsExpected = true;
-					if( !times->queryTXTResultTime ) times->queryTXTResultTime = now;
-				}
-			}
-		}
-	}
-	
-	if( !resultIsExpected )
-	{
-		CFMutableArrayRef			resultArray;
-		CFMutableDictionaryRef		resultDict;
-		CFStringRef					rdataKey;
-		char *						rdataStr;
-		const char *				ifNamePtr;
-		char						timestamp[ 32 ];
-		char						ifNameBuf[ IF_NAMESIZE + 1 ];
-		
-		ifNamePtr = if_indextoname( inIfIndex, ifNameBuf );
-		resultArray = subtest->unexpected;
-	#if( TARGET_OS_WATCH )
-		if( subtest->test->forBATS && ( subtest->ifIndex == kDNSServiceInterfaceIndexAny ) &&
-			ifNamePtr && _RegistrationTestInterfaceIsWiFi( ifNamePtr ) && !inError &&
-			( strcasecmp( inName, subtest->serviceFQDN ) == 0 ) )
-		{
-			if( inType == kDNSServiceType_SRV )
-			{
-				const Boolean		expectRandHostname = subtest->includeAWDL ? true : false;
-				
-				if( _RegistrationSubtestIsSRVRecordDataValid( subtest, inRDataPtr, inRDataLen, expectRandHostname ) )
-				{
-					resultArray = subtest->ignored;
-				}
-			}
-			else if( inType == kDNSServiceType_TXT )
-			{
-				if( MemEqual( inRDataPtr, inRDataLen, subtest->txtPtr, subtest->txtLen ) )
-				{
-					resultArray = subtest->ignored;
-				}
-			}
-		}
-	#endif
-		err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &resultDict,
-			"{"
-				"%kO=%O"	// resultType
-				"%kO=%s"	// timestamp
-				"%kO=%lli"	// flags
-				"%kO=%lli"	// ifIndex
-				"%kO=%s"	// ifName
-				"%kO=%lli"	// error
-				"%kO=%s"	// serviceFQDN
-				"%kO=%lli"	// recordType
-				"%kO=%lli"	// class
-			"}",
-			kRegistrationTestReportKey_ResultType,		kRegistrationTestResultType_Query,
-			kRegistrationTestReportKey_Timestamp,		_NanoTime64ToTimestamp( now, timestamp, sizeof( timestamp ) ),
-			kRegistrationTestReportKey_Flags,			(int64_t) inFlags,
-			kRegistrationTestReportKey_InterfaceIndex,	(int64_t) inIfIndex,
-			kRegistrationTestReportKey_InterfaceName,	ifNamePtr,
-			kRegistrationTestReportKey_Error,			(int64_t) inError,
-			kRegistrationTestReportKey_ServiceFQDN,		inName,
-			kRegistrationTestReportKey_RecordType,		(int64_t) inType,
-			kRegistrationTestReportKey_RecordClass,		(int64_t) inClass );
-		require_noerr( err, exit );
-		
-		rdataStr = NULL;
-		DNSRecordDataToString( inRDataPtr, inRDataLen, inType, &rdataStr );
-		if( rdataStr )
-		{
-			rdataKey = kRegistrationTestReportKey_RDataFormatted;
-		}
-		else
-		{
-			ASPrintF( &rdataStr, "%#H", inRDataPtr, inRDataLen, inRDataLen );
-			require_action( rdataStr, exit, err = kNoMemoryErr );
-			
-			rdataKey = kRegistrationTestReportKey_RDataHexString;
-		}
-		err = CFDictionarySetCString( resultDict, rdataKey, rdataStr, kSizeCString );
-		ForgetMem( &rdataStr );
-		if( err ) CFRelease( resultDict );
-		require_noerr( err, exit );
-		
-		CFArrayAppendValue( resultArray, resultDict );
-		CFRelease( resultDict );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err ) _RegistrationTestExit( subtest->test, err );
-}
-
-static Boolean
-	_RegistrationSubtestIsSRVRecordDataValid(
-		RegistrationSubtest *	inSubtest,
-		const uint8_t *			inRDataPtr,
-		size_t					inRDataLen,
-		Boolean					inExpectRandHostname )
-{
-	const dns_fixed_fields_srv *		fields;
-	const uint8_t * const				end		= &inRDataPtr[ inRDataLen ];
-	const uint8_t *						label;
-	size_t								len;
-	uint16_t							port;
-	Boolean								isValid;
-	
-	isValid = false;
-	require_quiet( inRDataLen >= sizeof( dns_fixed_fields_srv ), exit );
-	
-	fields	= (const dns_fixed_fields_srv *) inRDataPtr;
-	port	= dns_fixed_fields_srv_get_port( fields );
-	require_quiet( port == inSubtest->port, exit );
-	
-	// First target label should be a UUID string for the AWDL interface.
-	
-	label = (const uint8_t *) &fields[ 1 ];
-	require_quiet( ( end - label ) >= 1, exit );
-	
-	len = label[ 0 ];
-	require_quiet( ( (size_t)( end - label ) ) >= ( 1 + len ), exit );
-	
-	if( inExpectRandHostname )
-	{
-		if( StringToUUID( (const char *) &label[ 1 ], len, false, NULL ) != kNoErr ) goto exit;
-	}
-	else
-	{
-		if( strnicmpx( &label[ 1 ], len, inSubtest->test->localHostName ) != 0 ) goto exit;
-	}
-	
-	// Second target label should be "local".
-	
-	label = &label[ 1 + len ];
-	require_quiet( ( end - label ) >= 1, exit );
-	
-	len = label[ 0 ];
-	require_quiet( ( (size_t)( end - label ) ) >= ( 1 + len ), exit );
-	
-	if( ( len != kLocalLabel[ 0 ] ) || ( _memicmp( &label[ 1 ], &kLocalLabel[ 1 ], kLocalLabel[ 0 ] ) != 0 ) ) goto exit;
-	
-	// Third target label should be the root label.
-	
-	label = &label[ 1 + len ];
-	require_quiet( ( end - label ) >= 1, exit );
-	
-	len = label[ 0 ];
-	if( len != 0 ) goto exit;
-	
-	isValid = true;
-	
-exit:
-	return( isValid );
-}
-
-//===========================================================================================================================
-
-static Boolean	_RegistrationSubtestValidServiceType( const RegistrationSubtest *inSubtest, const char *inServiceType )
-{
-	if( stricmp_prefix( inServiceType, inSubtest->serviceType ) == 0 )
-	{
-		const char * const		ptr = &inServiceType[ inSubtest->serviceTypeLen ];
-		
-		if( ( ptr[ 0 ] == '\0' ) || ( ( ptr[ 0 ] == '.' ) && ( ptr[ 1 ] == '\0' ) ) ) return( true );
-	}
-	return( false );
-}
-
-//===========================================================================================================================
-
-static RegistrationResultTimes *
-	_RegistrationSubtestGetInterfaceResultTimes(
-		RegistrationSubtest *	inSubtest,
-		uint32_t				inIfIndex,
-		Boolean *				outIsAWDL )
-{
-	if( inSubtest->ifList )
-	{
-		RegistrationInterfaceItem *		item;
-		
-		for( item = inSubtest->ifList; item; item = (RegistrationInterfaceItem *) item->base.next )
-		{
-			if( inIfIndex == item->base.ifIndex )
-			{
-				if( outIsAWDL ) *outIsAWDL = item->base.isAWDL ? true : false;
-				return( &item->times );
-			}
-		}
-	}
-	else
-	{
-		if( inIfIndex == inSubtest->ifIndex )
-		{
-			if( outIsAWDL ) *outIsAWDL = inSubtest->ifIsAWDL ? true : false;
-			return( &inSubtest->ifTimes );
-		}
-	}
-	return( NULL );
-}
-
-//===========================================================================================================================
-
-static void	_RegistrationTestTimerHandler( void *inContext )
-{
-	RegistrationTest * const		test = (RegistrationTest *) inContext;
-	
-	dispatch_source_forget( &test->timer );
-	_RegistrationTestProceed( test );
-}
-
-//===========================================================================================================================
-
-#if( TARGET_OS_WATCH )
-static Boolean	_RegistrationTestInterfaceIsWiFi( const char *inIfName )
-{
-	NetTransportType		type = kNetTransportType_Undefined;
-	
-	SocketGetInterfaceInfo( kInvalidSocketRef, inIfName, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &type );
-	return( ( type == kNetTransportType_WiFi ) ? true : false );
-}
-#endif
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	KeepAliveTestCmd
-//===========================================================================================================================
-
-typedef enum
-{
-	kKeepAliveCallVariant_Null				= 0,
-	kKeepAliveCallVariant_TakesSocket		= 1, // DNSServiceSleepKeepalive(), which takes a connected socket.
-	kKeepAliveCallVariant_TakesSockAddrs	= 2, // DNSServiceSleepKeepalive_sockaddr(), which takes connection's sockaddrs.
-	
-}	KeepAliveCallVariant;
-
-typedef struct
-{
-	int							family;			// TCP connection's address family.
-	KeepAliveCallVariant		callVariant;	// Describes which DNSServiceSleepKeepalive* call to use.
-	const char *				description;	// Subtest description.
-	
-}	KeepAliveSubtestParams;
-
-const KeepAliveSubtestParams		kKeepAliveSubtestParams[] =
-{
-	{ AF_INET,  kKeepAliveCallVariant_TakesSocket,    "Calls DNSServiceSleepKeepalive() for IPv4 TCP connection." },
-	{ AF_INET,  kKeepAliveCallVariant_TakesSockAddrs, "Calls DNSServiceSleepKeepalive_sockaddr() for IPv4 TCP connection." },
-	{ AF_INET6, kKeepAliveCallVariant_TakesSocket,    "Calls DNSServiceSleepKeepalive() for IPv6 TCP connection." },
-	{ AF_INET6, kKeepAliveCallVariant_TakesSockAddrs, "Calls DNSServiceSleepKeepalive_sockaddr() for IPv6 TCP connection." }
-};
-
-typedef struct
-{
-	sockaddr_ip			local;			// TCP connection's local address and port.
-	sockaddr_ip			remote;			// TCP connection's remote address and port.
-	NanoTime64			startTime;		// Subtest's start time.
-	NanoTime64			endTime;		// Subtest's end time.
-	SocketRef			clientSock;		// Socket for client-side of TCP connection.
-	SocketRef			serverSock;		// Socket for server-side of TCP connection.
-	char *				recordName;		// Keepalive record's name.
-	char *				dataStr;		// Data expected to be contained in keepalive record's data.
-	const char *		description;	// Subtests's description.
-	unsigned int		timeoutKA;		// Randomly-generated timeout value that gets put in keepalive record's rdata.
-	OSStatus			error;			// Subtest's error.
-	
-}	KeepAliveSubtest;
-
-typedef struct KeepAliveTest *		KeepAliveTestRef;
-
-typedef struct
-{
-	KeepAliveTestRef		test;	// Weak back pointer to test.
-	
-}	KeepAliveTestConnectionContext;
-
-struct KeepAliveTest
-{
-	dispatch_queue_t						queue;			// Serial queue for test events.
-	dispatch_semaphore_t					doneSem;		// Semaphore to signal when the test is done.
-	dispatch_source_t						readSource;		// Read source for TCP listener socket.
-	DNSServiceRef							keepalive;		// DNSServiceSleepKeepalive{,sockaddr} operation.
-	DNSServiceRef							query;			// Query to verify registered keepalive record.
-	dispatch_source_t						timer;			// Timer to put time limit on query.
-	AsyncConnectionRef						connection;		// Establishes current subtest's TCP connection.
-	KeepAliveTestConnectionContext *		connectionCtx;	// Weak pointer to connection's context.
-	NanoTime64								startTime;		// Test's start time.
-	NanoTime64								endTime;		// Test's end time.
-	OSStatus								error;			// Test's error.
-	size_t									subtestIdx;		// Index of current subtest.
-	KeepAliveSubtest						subtests[ 4 ];	// Subtest array.
-};
-check_compile_time( countof_field( struct KeepAliveTest, subtests ) == countof( kKeepAliveSubtestParams ) );
-
-ulog_define_ex( kDNSSDUtilIdentifier, KeepAliveTest, kLogLevelInfo, kLogFlags_None, "KeepAliveTest", NULL );
-#define kat_ulog( LEVEL, ... )		ulog( &log_category_from_name( KeepAliveTest ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	_KeepAliveTestCreate( KeepAliveTestRef *outTest );
-static OSStatus	_KeepAliveTestRun( KeepAliveTestRef inTest );
-static void		_KeepAliveTestFree( KeepAliveTestRef inTest );
-
-static void	KeepAliveTestCmd( void )
-{
-	OSStatus				err;
-	OutputFormatType		outputFormat;
-	KeepAliveTestRef		test		= NULL;
-	CFPropertyListRef		plist		= NULL;
-	CFMutableArrayRef		subtests;
-	size_t					i;
-	size_t					subtestFailCount;
-	Boolean					testPassed	= false;
-	char					startTime[ 32 ];
-	char					endTime[ 32 ];
-	
-	err = OutputFormatFromArgString( gKeepAliveTest_OutputFormat, &outputFormat );
-	require_noerr_quiet( err, exit );
-	
-	err = _KeepAliveTestCreate( &test );
-	require_noerr( err, exit );
-	
-	err = _KeepAliveTestRun( test );
-	require_noerr( err, exit );
-	
-	_NanoTime64ToTimestamp( test->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( test->endTime, endTime, sizeof( endTime ) );
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"	// startTime
-			"%kO=%s"	// endTime
-			"%kO=[%@]"	// subtests
-		"}",
-		CFSTR( "startTime" ),	startTime,
-		CFSTR( "endTime" ),		endTime,
-		CFSTR( "subtests" ),	&subtests );
-	require_noerr( err, exit );
-	
-	subtestFailCount = 0;
-	check( test->subtestIdx == countof( test->subtests ) );
-	for( i = 0; i < countof( test->subtests ); ++i )
-	{
-		KeepAliveSubtest * const		subtest = &test->subtests[ i ];
-		char							errorDesc[ 128 ];
-		
-		_NanoTime64ToTimestamp( subtest->startTime, startTime, sizeof( startTime ) );
-		_NanoTime64ToTimestamp( subtest->endTime, endTime, sizeof( endTime ) );
-		SNPrintF( errorDesc, sizeof( errorDesc ), "%m", subtest->error );
-		err = CFPropertyListAppendFormatted( kCFAllocatorDefault, subtests,
-			"{"
-				"%kO=%s"		// startTime
-				"%kO=%s"		// endTime
-				"%kO=%s"		// description
-				"%kO=%##a"		// localAddr
-				"%kO=%##a"		// remoteAddr
-				"%kO=%s"		// recordName
-				"%kO=%s"		// expectedRData
-				"%kO="			// error
-				"{"
-					"%kO=%lli"	// code
-					"%kO=%s"	// description
-				"}"
-			"}",
-			CFSTR( "startTime" ),		startTime,
-			CFSTR( "endTime" ),			endTime,
-			CFSTR( "description" ),		subtest->description,
-			CFSTR( "localAddr" ),		&subtest->local.sa,
-			CFSTR( "remoteAddr" ),		&subtest->remote.sa,
-			CFSTR( "recordName" ),		subtest->recordName,
-			CFSTR( "expectedRData" ),	subtest->dataStr,
-			CFSTR( "error" ),
-			CFSTR( "code" ),			(int64_t) subtest->error,
-			CFSTR( "description" ),		errorDesc
-		);
-		require_noerr( err, exit );
-		if( subtest->error ) ++subtestFailCount;
-	}
-	if( subtestFailCount == 0 ) testPassed = true;
-	CFPropertyListAppendFormatted( kCFAllocatorDefault, plist, "%kO=%b", CFSTR( "pass" ), testPassed );
-	
-	err = OutputPropertyList( plist, outputFormat, gKeepAliveTest_OutputFilePath );
-	require_noerr( err, exit );
-	
-exit:
-	if( test ) _KeepAliveTestFree( test );
-	CFReleaseNullSafe( plist );
-    gExitCode = err ? 1 : ( testPassed ? 0 : 2 );
-}
-
-//===========================================================================================================================
-
-static void					_KeepAliveTestStart( void *inCtx );
-static void					_KeepAliveTestStop( KeepAliveTestRef inTest, OSStatus inError );
-static OSStatus				_KeepAliveTestStartSubtest( KeepAliveTestRef inTest );
-static void					_KeepAliveTestStopSubtest( KeepAliveTestRef inTest );
-static KeepAliveSubtest *	_KeepAliveTestGetSubtest( KeepAliveTestRef inTest );
-static const char *			_KeepAliveTestGetSubtestLogPrefix( KeepAliveTestRef inTest, char *inBufPtr, size_t inBufLen );
-static OSStatus				_KeepAliveTestContinue( KeepAliveTestRef inTest, OSStatus inSubtestError, Boolean *outDone );
-static void					_KeepAliveTestTCPAcceptHandler( void *inCtx );
-static void					_KeepAliveTestConnectionHandler( SocketRef inSock, OSStatus inError, void *inArg );
-static void					_KeepAliveTestHandleConnection( KeepAliveTestRef inTest, SocketRef inSock, OSStatus inError );
-static void					_KeepAliveTestForgetConnection( KeepAliveTestRef inTest );
-static void DNSSD_API		_KeepAliveTestKeepaliveCallback( DNSServiceRef inSDRef, DNSServiceErrorType inErr, void *inCtx );
-static void					_KeepAliveTestQueryTimerHandler( void *inCtx );
-static void DNSSD_API
-	_KeepAliveTestQueryRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inFullName,
-		uint16_t			inType,
-		uint16_t			inClass,
-		uint16_t			inRDataLen,
-		const void *		inRDataPtr,
-		uint32_t			inTTL,
-		void *				inCtx );
-
-static OSStatus	_KeepAliveTestCreate( KeepAliveTestRef *outTest )
-{
-	OSStatus				err;
-	KeepAliveTestRef		test;
-	size_t					i;
-	
-	test = (KeepAliveTestRef) calloc( 1, sizeof( *test ) );
-	require_action( test, exit, err = kNoMemoryErr );
-	
-	test->error = kInProgressErr;
-	for( i = 0; i < countof( test->subtests ); ++i )
-	{
-		KeepAliveSubtest * const		subtest = &test->subtests[ i ];
-		
-		subtest->local.sa.sa_family		= AF_UNSPEC;
-		subtest->remote.sa.sa_family	= AF_UNSPEC;
-		subtest->clientSock				= kInvalidSocketRef;
-		subtest->serverSock				= kInvalidSocketRef;
-	}
-	test->queue = dispatch_queue_create( "com.apple.dnssdutil.keepalive-test", DISPATCH_QUEUE_SERIAL );
-	require_action( test->queue, exit, err = kNoResourcesErr );
-	
-	test->doneSem = dispatch_semaphore_create( 0 );
-	require_action( test->doneSem, exit, err = kNoResourcesErr );
-	
-	*outTest = test;
-	test = NULL;
-	err = kNoErr;
-	
-exit:
-	if( test ) _KeepAliveTestFree( test );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_KeepAliveTestRun( KeepAliveTestRef inTest )
-{
-	dispatch_async_f( inTest->queue, inTest, _KeepAliveTestStart );
-	dispatch_semaphore_wait( inTest->doneSem, DISPATCH_TIME_FOREVER );
-	return( inTest->error );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestFree( KeepAliveTestRef inTest )
-{
-	size_t		i;
-	
-	check( !inTest->readSource );
-	check( !inTest->query );
-	check( !inTest->timer );
-	check( !inTest->keepalive );
-	check( !inTest->connection );
-	check( !inTest->connectionCtx );
-	dispatch_forget( &inTest->queue );
-	dispatch_forget( &inTest->doneSem );
-	for( i = 0; i < countof( inTest->subtests ); ++i )
-	{
-		KeepAliveSubtest * const		subtest = &inTest->subtests[ i ];
-		
-		check( !IsValidSocket( subtest->clientSock ) );
-		check( !IsValidSocket( subtest->serverSock ) );
-		ForgetMem( &subtest->recordName );
-		ForgetMem( &subtest->dataStr );
-	}
-	free( inTest );
-}
-
-//===========================================================================================================================
-
-static void _KeepAliveTestStart( void *inCtx )
-{
-	OSStatus					err;
-	const KeepAliveTestRef		test = (KeepAliveTestRef) inCtx;
-	
-	test->error		= kInProgressErr;
-	test->startTime	= NanoTimeGetCurrent();
-	err = _KeepAliveTestStartSubtest( test );
-	require_noerr( err, exit );
-	
-exit:
-	if( err ) _KeepAliveTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestStop( KeepAliveTestRef inTest, OSStatus inError )
-{
-	size_t		i;
-	
-	inTest->error	= inError;
-	inTest->endTime	= NanoTimeGetCurrent();
-	_KeepAliveTestStopSubtest( inTest );
-	for( i = 0; i < countof( inTest->subtests ); ++i )
-	{
-		KeepAliveSubtest * const		subtest = &inTest->subtests[ i ];
-		
-		ForgetSocket( &subtest->clientSock );
-		ForgetSocket( &subtest->serverSock );
-	}
-	dispatch_semaphore_signal( inTest->doneSem );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_KeepAliveTestStartSubtest( KeepAliveTestRef inTest )
-{
-	OSStatus									err;
-	KeepAliveSubtest * const					subtest		= _KeepAliveTestGetSubtest( inTest );
-	const KeepAliveSubtestParams * const		params		= &kKeepAliveSubtestParams[ inTest->subtestIdx ];
-	int											port;
-	SocketRef									sock		= kInvalidSocketRef;
-	const uint32_t								loopbackV4	= htonl( INADDR_LOOPBACK );
-	SocketContext *								sockCtx		= NULL;
-	KeepAliveTestConnectionContext *			cnxCtx		= NULL;
-	Boolean										useIPv4;
-	char										serverAddrStr[ 64 ];
-	char										prefix[ 64 ];
-	
-	subtest->error			= kInProgressErr;
-	subtest->startTime		= NanoTimeGetCurrent();
-	subtest->description	= params->description;
-	
-	require_action( ( params->family == AF_INET ) || ( params->family == AF_INET6 ), exit, err = kInternalErr );
-	
-	// Create TCP listener socket.
-	
-	useIPv4 = ( params->family == AF_INET ) ? true : false;
-	err = ServerSocketOpenEx( params->family, SOCK_STREAM, IPPROTO_TCP,
-		useIPv4 ? ( (const void *) &loopbackV4 ) : ( (const void *) &in6addr_loopback ), kSocketPort_Auto, &port,
-		kSocketBufferSize_DontSet, &sock );
-	require_noerr( err, exit );
-	
-	if( useIPv4 )	SNPrintF( serverAddrStr, sizeof( serverAddrStr ), "%.4a:%d", &loopbackV4, port );
-	else			SNPrintF( serverAddrStr, sizeof( serverAddrStr ), "[%.16a]:%d", in6addr_loopback.s6_addr, port );
-	_KeepAliveTestGetSubtestLogPrefix( inTest, prefix, sizeof( prefix ) );
-	kat_ulog( kLogLevelInfo, "%s: Will listen for connections on %s\n", prefix, serverAddrStr );
-	
-	sockCtx = SocketContextCreate( sock, inTest, &err );
-	require_noerr( err, exit );
-	sock = kInvalidSocketRef;
-	
-	// Create read source for TCP listener socket.
-	
-	check( !inTest->readSource );
-	err = DispatchReadSourceCreate( sockCtx->sock, inTest->queue, _KeepAliveTestTCPAcceptHandler,
-		SocketContextCancelHandler, sockCtx, &inTest->readSource );
-	require_noerr( err, exit );
-	sockCtx = NULL;
-	dispatch_resume( inTest->readSource );
-	
-	cnxCtx = (KeepAliveTestConnectionContext *) calloc( 1, sizeof( *cnxCtx ) );
-	require_action( cnxCtx, exit, err = kNoMemoryErr );
-	
-	// Start asynchronous connection to listener socket.
-	
-	kat_ulog( kLogLevelInfo, "%s: Will connect to %s\n", prefix, serverAddrStr );
-	
-	check( !inTest->connection );
-	err = AsyncConnection_Connect( &inTest->connection, serverAddrStr, 0, kAsyncConnectionFlags_None,
-		5 * UINT64_C_safe( kNanosecondsPerSecond ), kSocketBufferSize_DontSet, kSocketBufferSize_DontSet,
-		NULL, NULL, _KeepAliveTestConnectionHandler, cnxCtx, inTest->queue );
-	require_noerr( err, exit );
-	
-	cnxCtx->test = inTest;
-	check( !inTest->connectionCtx );
-	inTest->connectionCtx = cnxCtx;
-	cnxCtx = NULL;
-	
-exit:
-	ForgetSocket( &sock );
-	if( sockCtx ) SocketContextRelease( sockCtx );
-	FreeNullSafe( cnxCtx );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestStopSubtest( KeepAliveTestRef inTest )
-{
-	dispatch_source_forget( &inTest->readSource );
-	DNSServiceForget( &inTest->keepalive );
-	DNSServiceForget( &inTest->query );
-	dispatch_source_forget( &inTest->timer );
-	_KeepAliveTestForgetConnection( inTest );
-}
-
-//===========================================================================================================================
-
-static KeepAliveSubtest *	_KeepAliveTestGetSubtest( KeepAliveTestRef inTest )
-{
-	return( ( inTest->subtestIdx < countof( inTest->subtests ) ) ? &inTest->subtests[ inTest->subtestIdx ] : NULL );
-}
-
-//===========================================================================================================================
-
-static const char *	_KeepAliveTestGetSubtestLogPrefix( KeepAliveTestRef inTest, char *inBufPtr, size_t inBufLen )
-{
-	SNPrintF( inBufPtr, inBufLen, "Subtest %zu/%zu", inTest->subtestIdx + 1, countof( inTest->subtests ) );
-	return( inBufPtr );
-}
-
-//===========================================================================================================================
-
-static OSStatus	_KeepAliveTestContinue( KeepAliveTestRef inTest, OSStatus inSubtestError, Boolean *outDone )
-{
-	OSStatus				err;
-	KeepAliveSubtest *		subtest;
-	
-	require_action( inTest->subtestIdx <= countof( inTest->subtests ), exit, err = kInternalErr );
-	
-	if( inTest->subtestIdx < countof( inTest->subtests ) )
-	{
-		subtest = _KeepAliveTestGetSubtest( inTest );
-		_KeepAliveTestStopSubtest( inTest );
-		subtest->endTime	= NanoTimeGetCurrent();
-		subtest->error		= inSubtestError;
-		if( ++inTest->subtestIdx < countof( inTest->subtests ) )
-		{
-			err = _KeepAliveTestStartSubtest( inTest );
-			require_noerr_quiet( err, exit );
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	if( outDone ) *outDone = ( !err && ( inTest->subtestIdx == countof( inTest->subtests ) ) ) ? true : false;
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestTCPAcceptHandler( void *inCtx )
-{
-	OSStatus						err;
-	const SocketContext * const		sockCtx	= (SocketContext *) inCtx;
-	const KeepAliveTestRef			test	= (KeepAliveTestRef) sockCtx->userContext;
-	KeepAliveSubtest * const		subtest	= _KeepAliveTestGetSubtest( test );
-	sockaddr_ip						peer;
-	socklen_t						len;
-	char							prefix[ 64 ];
-	
-	check( !IsValidSocket( subtest->serverSock ) );
-	len = (socklen_t) sizeof( peer );
-	subtest->serverSock = accept( sockCtx->sock, &peer.sa, &len );
-	err = map_socket_creation_errno( subtest->serverSock );
-	require_noerr( err, exit );
-	
-	_KeepAliveTestGetSubtestLogPrefix( test, prefix, sizeof( prefix ) );
-	kat_ulog( kLogLevelInfo, "%s: Accepted connection from %##a\n", prefix, &peer.sa );
-	
-	dispatch_source_forget( &test->readSource );
-	
-exit:
-	if( err ) _KeepAliveTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestConnectionHandler( SocketRef inSock, OSStatus inError, void *inArg )
-{
-	KeepAliveTestConnectionContext *		ctx		= (KeepAliveTestConnectionContext *) inArg;
-	const KeepAliveTestRef					test	= ctx->test;
-	
-	if( test )
-	{
-		_KeepAliveTestForgetConnection( test );
-		_KeepAliveTestHandleConnection( test, inSock, inError );
-		inSock = kInvalidSocketRef;
-	}
-	ForgetSocket( &inSock );
-	free( ctx );
-}
-
-//===========================================================================================================================
-
-#define kKeepAliveTestQueryTimeoutSecs		5
-
-static void	_KeepAliveTestHandleConnection( KeepAliveTestRef inTest, SocketRef inSock, OSStatus inError )
-{
-	OSStatus								err;
-	KeepAliveSubtest * const				subtest			= _KeepAliveTestGetSubtest( inTest );
-	const KeepAliveSubtestParams * const	params			= &kKeepAliveSubtestParams[ inTest->subtestIdx ];
-	socklen_t								len;
-    uint32_t								value;
-	int										family, i;
-	Boolean									subtestFailed	= false;
-	Boolean									done;
-	char									prefix[ 64 ];
-	
-	require_noerr_action( inError, exit, err = inError );
-	
-	check( !IsValidSocket( subtest->clientSock ) );
-	subtest->clientSock = inSock;
-	inSock = kInvalidSocketRef;
-	
-	// Get local and remote IP addresses.
-	
-	len = (socklen_t) sizeof( subtest->local );
-	err = getsockname( subtest->clientSock, &subtest->local.sa, &len );
-	err = map_global_noerr_errno( err );
-	require_noerr( err, exit );
-	
-	len = (socklen_t) sizeof( subtest->remote );
-	err = getpeername( subtest->clientSock, &subtest->remote.sa, &len );
-	err = map_global_noerr_errno( err );
-	require_noerr( err, exit );
-	
-	_KeepAliveTestGetSubtestLogPrefix( inTest, prefix, sizeof( prefix ) );
-	kat_ulog( kLogLevelInfo, "%s: Connection established: %##a <-> %##a\n",
-		prefix, &subtest->local.sa, &subtest->remote.sa );
-	
-	// Call either DNSServiceSleepKeepalive() or DNSServiceSleepKeepalive_sockaddr().
-	
-	check( subtest->timeoutKA == 0 );
-	subtest->timeoutKA = (unsigned int) RandomRange( 1, UINT_MAX );
-	
-    switch( params->callVariant )
-	{
-		case kKeepAliveCallVariant_TakesSocket:
-			kat_ulog( kLogLevelInfo, "%s: Will call DNSServiceSleepKeepalive() for client-side socket\n", prefix );
-			check( !inTest->keepalive );
-			err = DNSServiceSleepKeepalive( &inTest->keepalive, 0, subtest->clientSock,
-				subtest->timeoutKA, _KeepAliveTestKeepaliveCallback, inTest );
-			require_noerr( err, exit );
-			
-			err = DNSServiceSetDispatchQueue( inTest->keepalive, inTest->queue );
-			require_noerr( err, exit );
-			break;
-		
-		case kKeepAliveCallVariant_TakesSockAddrs:
-			kat_ulog( kLogLevelInfo,
-				"%s: Will call DNSServiceSleepKeepalive_sockaddr() for local and remote sockaddrs\n", prefix );
-			check( !inTest->keepalive );
-			err = DNSServiceSleepKeepalive_sockaddr( &inTest->keepalive, 0, &subtest->local.sa, &subtest->remote.sa,
-				subtest->timeoutKA, _KeepAliveTestKeepaliveCallback, inTest );
-			require_noerr( err, exit );
-			
-			err = DNSServiceSetDispatchQueue( inTest->keepalive, inTest->queue );
-			require_noerr( err, exit );
-			break;
-		
-		default:
-			kat_ulog( kLogLevelError, "%s: Invalid KeepAliveCallVariant value %d\n", prefix, (int) params->callVariant );
-			err = kInternalErr;
-			goto exit;
-	}
-	// Use the same logic that the DNSServiceSleepKeepalive functions use to derive a record name and rdata.
-	
-	value = 0;
-	family = subtest->local.sa.sa_family;
-	if( family == AF_INET )
-	{
-		const struct sockaddr_in * const		sin = &subtest->local.v4;
-		const uint8_t *							ptr;
-		
-		check_compile_time_code( sizeof( sin->sin_addr.s_addr ) == 4 );
-		ptr = (const uint8_t *) &sin->sin_addr.s_addr;
-		for( i = 0; i < 4; ++i ) value += ptr[ i ];
-		value += sin->sin_port;	// Note: No ntohl(). This is what DNSServiceSleepKeepalive does.
-		
-		check( subtest->remote.sa.sa_family == AF_INET );
-		ASPrintF( &subtest->dataStr, "t=%u h=%.4a d=%.4a l=%u r=%u",
-			subtest->timeoutKA, &subtest->local.v4.sin_addr.s_addr, &subtest->remote.v4.sin_addr.s_addr,
-			ntohs( subtest->local.v4.sin_port ), ntohs( subtest->remote.v4.sin_port ) );
-		require_action( subtest->dataStr, exit, err = kNoMemoryErr );
-	}
-	else if( family == AF_INET6 )
-	{
-		const struct sockaddr_in6 * const		sin6 = &subtest->local.v6;
-		
-		check_compile_time_code( countof( sin6->sin6_addr.s6_addr ) == 16 );
-		for( i = 0; i < 16; ++i ) value += sin6->sin6_addr.s6_addr[ i ];
-		value += sin6->sin6_port; // Note: No ntohl(). This is what DNSServiceSleepKeepalive does.
-		
-		check( subtest->remote.sa.sa_family == AF_INET6 );
-		ASPrintF( &subtest->dataStr, "t=%u H=%.16a D=%.16a l=%u r=%u",
-			subtest->timeoutKA, subtest->local.v6.sin6_addr.s6_addr, subtest->remote.v6.sin6_addr.s6_addr,
-			ntohs( subtest->local.v6.sin6_port ), ntohs( subtest->remote.v6.sin6_port ) );
-		require_action( subtest->dataStr, exit, err = kNoMemoryErr );
-	}
-	else
-	{
-		kat_ulog( kLogLevelError, "%s: Unexpected local address family %d\n", prefix, family );
-		err = kInternalErr;
-		goto exit;
-	}
-	
-	// Start query for the new keepalive record.
-	
-	check( !subtest->recordName );
-	ASPrintF( &subtest->recordName, "%u._keepalive._dns-sd._udp.local.", value );
-	require_action( subtest->recordName, exit, err = kNoMemoryErr );
-	
-	kat_ulog( kLogLevelInfo, "%s: Will query for %s NULL record\n", prefix, subtest->recordName );
-	check( !inTest->query );
-	err = DNSServiceQueryRecord( &inTest->query, 0, kDNSServiceInterfaceIndexLocalOnly, subtest->recordName,
-		kDNSServiceType_NULL, kDNSServiceClass_IN, _KeepAliveTestQueryRecordCallback, inTest );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( inTest->query, inTest->queue );
-	require_noerr( err, exit );
-	
-	// Start timer to enforce a time limit on the query.
-	
-	check( !inTest->timer );
-	err = DispatchTimerOneShotCreate( dispatch_time_seconds( kKeepAliveTestQueryTimeoutSecs ),
-		kKeepAliveTestQueryTimeoutSecs * ( INT64_C_safe( kNanosecondsPerSecond ) / 20 ), inTest->queue,
-		_KeepAliveTestQueryTimerHandler, inTest, &inTest->timer );
-	require_noerr( err, exit );
-	dispatch_resume( inTest->timer );
-	
-exit:
-	ForgetSocket( &inSock );
-	if( subtestFailed )
-	{
-		err = _KeepAliveTestContinue( inTest, err, &done );
-		check_noerr( err );
-	}
-	else
-	{
-		done = false;
-	}
-	if( err || done ) _KeepAliveTestStop( inTest, err );
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestForgetConnection( KeepAliveTestRef inTest )
-{
-	if( inTest->connection )
-	{
-		check( inTest->connectionCtx );
-		inTest->connectionCtx->test	= NULL; // Unset the connection's back pointer to test.
-		inTest->connectionCtx		= NULL; // Context will be freed by the connection's handler.
-		AsyncConnection_Forget( &inTest->connection );
-	}
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API	_KeepAliveTestKeepaliveCallback( DNSServiceRef inSDRef, DNSServiceErrorType inError, void *inCtx )
-{
-	OSStatus					err;
-	const KeepAliveTestRef		test	= (KeepAliveTestRef) inCtx;
-	char						prefix[ 64 ];
-	
-	Unused( inSDRef );
-	
-	_KeepAliveTestGetSubtestLogPrefix( test, prefix, sizeof( prefix ) );
-	kat_ulog( kLogLevelInfo, "%s: Keepalive callback error: %#m\n", prefix, inError );
-	
-	if( inError )
-	{
-		Boolean		done;
-		
-		err = _KeepAliveTestContinue( test, inError, &done );
-		check_noerr( err );
-		if( err || done ) _KeepAliveTestStop( test, err );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_KeepAliveTestQueryTimerHandler( void *inCtx )
-{
-	OSStatus						err;
-	const KeepAliveTestRef			test	= (KeepAliveTestRef) inCtx;
-	KeepAliveSubtest * const		subtest	= _KeepAliveTestGetSubtest( test );
-	Boolean							done;
-	char							prefix[ 64 ];
-	
-	_KeepAliveTestGetSubtestLogPrefix( test, prefix, sizeof( prefix ) );
-	kat_ulog( kLogLevelInfo, "%s: Query for \"%s\" timed out.\n", prefix, subtest->recordName );
-	
-	err = _KeepAliveTestContinue( test, kTimeoutErr, &done );
-	check_noerr( err );
-	if( err || done ) _KeepAliveTestStop( test, err );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_KeepAliveTestQueryRecordCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inFullName,
-		uint16_t			inType,
-		uint16_t			inClass,
-		uint16_t			inRDataLen,
-		const void *		inRDataPtr,
-		uint32_t			inTTL,
-		void *				inCtx )
-{
-	OSStatus						err;
-	const KeepAliveTestRef			test	= (KeepAliveTestRef) inCtx;
-	KeepAliveSubtest * const		subtest	= _KeepAliveTestGetSubtest( test );
-	const uint8_t *					ptr;
-	size_t							dataStrLen, minLen;
-	Boolean							done;
-	char							prefix[ 64 ];
-	
-	Unused( inSDRef );
-	Unused( inInterfaceIndex );
-	Unused( inTTL );
-	
-	_KeepAliveTestGetSubtestLogPrefix( test, prefix, sizeof( prefix ) );
-	if( strcasecmp( inFullName, subtest->recordName ) != 0 )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: Got unexpected record name \"%s\".\n",
-			prefix, subtest->recordName, inFullName );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	if( inType != kDNSServiceType_NULL )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: Got unexpected record type %d (%s) != %d (NULL).\n",
-			prefix, subtest->recordName, inType, RecordTypeToString( inType ), kDNSServiceType_NULL );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	if( inClass != kDNSServiceClass_IN )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: Got unexpected record class %d != %d (IN).\n",
-			prefix, subtest->recordName, inClass, kDNSServiceClass_IN );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	if( inError )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: Got unexpected error %#m.\n",
-			prefix, subtest->recordName, inError );
-		err = inError;
-		goto exit;
-	}
-	if( ( inFlags & kDNSServiceFlagsAdd ) == 0 )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: Missing Add flag.\n", prefix, subtest->recordName );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	kat_ulog( kLogLevelInfo, "%s: QueryRecord(%s) result rdata: %#H\n",
-		prefix, subtest->recordName, inRDataPtr, inRDataLen, inRDataLen );
-	
-	dataStrLen	= strlen( subtest->dataStr ) + 1;	// There's a NUL terminator at the end of the rdata.
-	minLen		= 1 + dataStrLen;					// The first byte of the rdata is a length byte.
-	if( inRDataLen < minLen )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: rdata length (%d) is less than expected minimum (%zu).\n",
-			prefix, subtest->recordName, inRDataLen, minLen );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	ptr = (const uint8_t *) inRDataPtr;
-	if( ptr[ 0 ] < dataStrLen )
-	{
-		kat_ulog( kLogLevelError,
-			"%s: QueryRecord(%s) result: rdata length byte value (%d) is less than expected minimum (%zu).\n",
-			prefix, subtest->recordName, ptr[ 0 ], dataStrLen );
-		err = kUnexpectedErr;
-		goto exit;
-	}
-	if( memcmp( &ptr[ 1 ], subtest->dataStr, dataStrLen - 1 ) != 0 )
-	{
-		kat_ulog( kLogLevelError, "%s: QueryRecord(%s) result: rdata body doesn't contain '%s'.\n",
-			prefix, subtest->recordName, subtest->dataStr );
-	}
-	err = kNoErr;
-	
-exit:
-	err = _KeepAliveTestContinue( test, err, &done );
-	check_noerr( err );
-	if( err || done ) _KeepAliveTestStop( test, kNoErr );
-}
-#endif	// TARGET_OS_DARWIN
-
-#if ( ENABLE_DNSSDUTIL_DNSSEC_TEST == 1 )
-//===========================================================================================================================
-//	DNSSECTestCmd
-//===========================================================================================================================
-
-#define kDNSSECTestQueryTimeoutSecs 4
-
-typedef struct DNSSECTest_BasicValidationContext
-{
-	uint32_t number_of_answers;		// The number of answers expected to receive in the "basic validation" test
-
-}	DNSSECTest_BasicValidationContext;
-
-//===========================================================================================================================
-
-typedef struct
-{
-	DNSServiceRef		query;
-	dispatch_source_t	queryTimer;			// Used to setup timeout timer, to prevent from waiting forever.
-	Boolean				testStarted;
-	const char *		testName;			// The name of the curreent running test case.
-	const char *		testCaseName;		// The query name in the subtest of the test case.
-	union {
-		DNSSECTest_BasicValidationContext	basicValidation;
-	} testCaseContext;						// Contains different customized context pointer, which can be used by different test cases.
-	const char *		subtestQueryName;	// The query name that is passed to mDNSResponder API
-	int					subtestIndex;		// The index of the current case in the test input array.
-	pid_t				localServerPID;		// The pid of the dnssdutil server
-	NanoTime64			startTime;			// The time when the DNSSEC test case starts.
-	CFMutableArrayRef	subtestReport;		// The reference to the CFMutableArrayRef, which contains subtest reports for different subtests
-	NanoTime64			subtestStartTime;	// The time when the subtest starts
-	Boolean				subtestFailed;		// Indicate if any subtest failed before.
-
-	char *				outputFilePath;		// File to write test results to. If NULL, then write to stdout. (malloced)
-	OutputFormatType	outputFormat;		// Format of test report output.
-} DNSSECTestContext;
-
-//===========================================================================================================================
-
-typedef struct
-{
-	const char *	testCaseName;										// The name of the test case that will be run.
-	void			(*testCaseHandler)( DNSSECTestContext * context );	// The main function of the test case.
-} DNSSECTestTestCase;
-
-//===========================================================================================================================
-
-static void DNSSECTestSetupLocalDNSServer( DNSSECTestContext *context );
-static void DNSSECTestStartTestCase( DNSSECTestContext *context );
-
-//===========================================================================================================================
-
-// DNSSEC test cases
-static void DNSSECTest_BasicValidation( DNSSECTestContext *context );
-
-static DNSSECTestTestCase DNSSECTestTestCases[] =
-{
-	{ "basic validation", DNSSECTest_BasicValidation }
-};
-
-//===========================================================================================================================
-
-// The main function to start the DNSSEC test
-static void
-	DNSSECTestCmd( void )
-{
-	OSStatus			err;
-	dispatch_source_t	signalSource	= NULL;
-	DNSSECTestContext *	context			= NULL;
-
-	// Set up SIGINT handler.
-    signal( SIGINT, SIG_IGN );
-    err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-    require_noerr( err, exit );
-    dispatch_resume( signalSource );
-
-	// Create the test context.
-	context = (DNSSECTestContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-
-	context->testStarted = false;
-
-	// Get the command line option.
-	context->testCaseName = strdup( gDNSSECTest_TestCaseName );
-	require( context->testCaseName , exit );
-
-	// Start the subtest from index 0
-	context->subtestIndex = 0;
-
-	// Get the output format.
-	err = OutputFormatFromArgString( gDNSSECTest_OutputFormat, &context->outputFormat );
-	require_noerr_quiet( err, exit );
-
-	// Get the output file path.
-	if( gDNSSECTest_OutputFilePath )
-	{
-		context->outputFilePath = strdup( gDNSSECTest_OutputFilePath );
-		require_noerr_quiet( context->outputFilePath , exit );
-	}
-
-	// Initialize the CFArray to store the test result.
-	context->subtestReport	= CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
-	context->startTime 		= NanoTimeGetCurrent();
-
-	// Start the local dnssdutil server.
-	DNSSECTestSetupLocalDNSServer( context );
-
-	// Start the test.
-	DNSSECTestStartTestCase( context );
-
-exit:
-	exit( 1 );
-}
-
-//===========================================================================================================================
-
-// Start the local DNS server with dnssdutil server command.
-static void
-	DNSSECTestSetupLocalDNSServer( DNSSECTestContext *context )
-{
-	Unused( context );
-	pid_t pid = getpid();
-
-	OSStatus err = _SpawnCommand( &context->localServerPID, NULL, NULL, "dnssdutil server --loopback --follow %lld",
-		(int64_t) pid );
-	require_noerr_action( err, exit,
-		FPrintF( stderr, "dnssdutil server --loopback --follow %lld failed, error: %d\n", (int64_t) pid, err ) );
-
-	// Wait long enough to allow the DNS server being setup.
-	sleep( 2 );
-
-	return;
-exit:
-	exit( 1 );
-}
-
-//===========================================================================================================================
-
-// Start the test case that user specifies.
-static void
-	DNSSECTestStartTestCase( DNSSECTestContext *context )
-{
-	Boolean findTestCase = false;
-
-	for ( int i = 0; i < (int)countof( DNSSECTestTestCases ); i++ )
-	{
-		if( strcmp( context->testCaseName, DNSSECTestTestCases[i].testCaseName ) == 0 )
-		{
-			DNSSECTestTestCases[ i ].testCaseHandler( context );
-			findTestCase = true;
-		}
-	}
-
-	if( !findTestCase )
-	{
-		FPrintF( stdout, "Unknown test case \"%s\"\n", context->testCaseName );
-		exit( 1 );
-	}
-}
-
-//===========================================================================================================================
-
-// Write the current subtest status into the report list. When this function is called, either some error occurs or the
-// subtest finishes.
-static void
-	_DNSSECTestQueryWriteSubtestReport( DNSSECTestContext *inContext, const char *errorDescription )
-{
-	OSStatus	err;
-	NanoTime64	now;
-	char		startTime[ 32 ];
-	char		endTime[ 32 ];
-
-	now = NanoTimeGetCurrent();
-	_NanoTime64ToTimestamp( inContext->subtestStartTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-
-	err = CFPropertyListAppendFormatted( kCFAllocatorDefault, inContext->subtestReport,
-		"{"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%s"
-		"}",
-		CFSTR( "Start Time" ),			startTime,
-		CFSTR( "End Time" ),			endTime,
-		CFSTR( "Subtest Query Name" ),	inContext->subtestQueryName,
-		CFSTR( "Result" ),				errorDescription ? "Fail" : "Pass",
-		CFSTR( "Error Description" ),	errorDescription ? errorDescription : "No Error"
-	);
-
-	require_noerr( err, exit );
-	return;
-
-exit:
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-
-// Output the final test result to the file (path specified by the user) in the disk.
-static void
-	_DNSSECTestQueryOutputFinalReport( DNSSECTestContext *inContext )
-{
-	OSStatus			err;
-	CFPropertyListRef	plist;
-	NanoTime64			now;
-	char				startTime[ 32 ];
-	char				endTime[ 32 ];
-
-	now = NanoTimeGetCurrent();
-	_NanoTime64ToTimestamp( inContext->startTime, startTime, sizeof( startTime ) );
-	_NanoTime64ToTimestamp( now, endTime, sizeof( endTime ) );
-
-	err = CFPropertyListCreateFormatted( kCFAllocatorDefault, &plist,
-		"{"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%s"
-			"%kO=%b"
-			"%kO=%O"
-		"}",
-		CFSTR( "Start Time" ),		startTime,
-		CFSTR( "End Time" ),		endTime,
-		CFSTR( "Test Case Name" ),	inContext->testCaseName,
-		CFSTR( "All Passed" ),		!inContext->subtestFailed,
-		CFSTR( "Subtest Reports" ),	inContext->subtestReport
-	);
-	require_noerr( err, exit );
-	ForgetCF( &inContext->subtestReport );
-
-	err = OutputPropertyList( plist, inContext->outputFormat, inContext->outputFilePath );
-	CFRelease( plist );
-	require_noerr( err, exit );
-
-	return;
-exit:
-	ErrQuit( 1, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-
-// The handler that will be called when timeout happens. When timeout happens it always means something bad happen, and
-// it might be possible that all the remaning tests timeout too, so the function exits directly instead of continuing.
-static void
-	_DNSSECTestQueryTimeoutHandler( void *inContext )
-{
-	DNSSECTestContext * const context = (DNSSECTestContext *) inContext;
-
-	DNSServiceForget( &context->query );
-	dispatch_source_forget( &context->queryTimer );
-
-	context->subtestFailed = true;
-	_DNSSECTestQueryWriteSubtestReport( context, "Query for DNSSEC-related records timed out" );
-	_DNSSECTestQueryOutputFinalReport( context );
-
-	exit( 1 );
-}
-
-//===========================================================================================================================
-#pragma mark - Test case "basic validation"
-
-//===========================================================================================================================
-
-typedef struct DNSSECTest_BasicValidationTestCase
-{
-	const char *	queryName;		// The query name that controls the behavior of the local DNS server.
-	uint16_t		queryType;		// The DNS record being queried.
-	uint32_t		num_of_answers;	// How many anwers are expected to be returned.
-
-}	DNSSECTest_BasicValidationTestCase;
-
-//===========================================================================================================================
-
-DNSSECTest_BasicValidationTestCase DNSSECTest_BasicValidationTestCases[] =
-{
-	// kDNSSECAlgorithm_RSASHA1 5
-	{ "count-1.z-5-1.z-5-2.z-5-3.dnssec.test.",		kDNSServiceType_A,		1 },
-	{ "count-2.z-5-1.z-5-2.z-5-3.dnssec.test.",		kDNSServiceType_A,		2 },
-	{ "count-1.z-5-1.z-5-2.z-5-3.dnssec.test.",		kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-5-1.z-5-2.z-5-3.dnssec.test.",		kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-5-1.z-5-2.z-5-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	// kDNSSECAlgorithm_RSASHA256 8
-	{ "count-1.z-8-1.z-8-2.z-8-3.dnssec.test.",		kDNSServiceType_A,		1 },
-	{ "count-2.z-8-1.z-8-2.z-8-3.dnssec.test.",		kDNSServiceType_A,		2 },
-	{ "count-1.z-8-1.z-8-2.z-8-3.dnssec.test.",		kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-8-1.z-8-2.z-8-3.dnssec.test.",		kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-8-1.z-8-2.z-8-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	// kDNSSECAlgorithm_RSASHA512 10
-	{ "count-1.z-10-1.z-10-2.z-10-3.dnssec.test.",	kDNSServiceType_A,		1 },
-	{ "count-2.z-10-1.z-10-2.z-10-3.dnssec.test.",	kDNSServiceType_A,		2 },
-	{ "count-1.z-10-1.z-10-2.z-10-3.dnssec.test.",	kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-10-1.z-10-2.z-10-3.dnssec.test.",	kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-10-1.z-10-2.z-10-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	// kDNSSECAlgorithm_ECDSAP256SHA256 13
-	{ "count-1.z-13-1.z-13-2.z-13-3.dnssec.test.",	kDNSServiceType_A,		1 },
-	{ "count-2.z-13-1.z-13-2.z-13-3.dnssec.test.",	kDNSServiceType_A,		2 },
-	{ "count-1.z-13-1.z-13-2.z-13-3.dnssec.test.",	kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-13-1.z-13-2.z-13-3.dnssec.test.",	kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-13-1.z-13-2.z-13-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	// kDNSSECAlgorithm_ECDSAP384SHA384 14
-	{ "count-1.z-14-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_A,		1 },
-	{ "count-2.z-14-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_A,		2 },
-	{ "count-1.z-14-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-14-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-14-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	// Mixed use of mutiple DNSKEY algorithms
-	{ "count-1.z-5-1.z-8-2.z-10-3.dnssec.test.",	kDNSServiceType_A,		1 },
-	{ "count-2.z-5-1.z-5-2.z-8-3.dnssec.test.",		kDNSServiceType_A,		2 },
-	{ "count-1.z-8-1.z-5-2.z-5-3.dnssec.test.",		kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-10-1.z-8-2.z-8-3.dnssec.test.",	kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-10-1.z-8-2.z-5-3.dnssec.test.",	kDNSServiceType_A,		10 },
-	{ "count-1.z-13-1.z-14-2.z-14-3.dnssec.test.",	kDNSServiceType_A,		1 },
-	{ "count-2.z-14-1.z-13-2.z-8-3.dnssec.test.",	kDNSServiceType_A,		2 },
-	{ "count-1.z-5-1.z-14-2.z-8-3.dnssec.test.",	kDNSServiceType_AAAA,	1 },
-	{ "count-2.z-10-1.z-8-2.z-13-3.dnssec.test.",	kDNSServiceType_AAAA,	2 },
-	{ "count-10.z-14-1.z-13-2.z-5-3.dnssec.test.",	kDNSServiceType_A,		10 }
-};
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DNSSECTest_BasicValidationCallBack(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-
-//===========================================================================================================================
-
-static Boolean
-	_DNSSECTest_BasicValidationVerifyTheResponse(
-		DNSSECTestContext *	inContext,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inFullName,
-		uint16_t			inType,
-		uint16_t			inClass,
-		uint16_t			inRDataLen,
-		const void *		inRDataPtr,
-		uint32_t			inTTL,
-		char *				inStrBuffer,
-		uint32_t			inBufferLen,
-		Boolean *			outExpectMore );
-
-//===========================================================================================================================
-
-static void DNSSECTest_BasicValidation( DNSSECTestContext *inContext )
-{
-	OSStatus		err;
-	const char *	error_description = NULL;
-
-	// Get the current subtest
-	DNSSECTest_BasicValidationTestCase * testCases = &DNSSECTest_BasicValidationTestCases[ inContext->subtestIndex ];
-	inContext->subtestQueryName = testCases->queryName;
-	inContext->testCaseContext.basicValidation.number_of_answers = testCases->num_of_answers;
-
-	// Issue the query.
-	err = DNSServiceQueryRecord( &inContext->query,
-		kDNSServiceFlagsEnableDNSSEC, 0, testCases->queryName, testCases->queryType, kDNSServiceClass_IN,
-		_DNSSECTest_BasicValidationCallBack, inContext );
-	require_noerr_action( err, exit, error_description = "DNSServiceQueryRecord failed" );
-
-	// Set the dispatch queue.
-	err = DNSServiceSetDispatchQueue( inContext->query,
-		dispatch_get_main_queue() );
-	require_noerr_action( err, exit, error_description = "DNSServiceSetDispatchQueue failed" );
-
-	// Create a timer to handle timeout.
-	err = DispatchTimerCreate( dispatch_time_seconds( kDNSSECTestQueryTimeoutSecs ), DISPATCH_TIME_FOREVER,
-		UINT64_C_safe( kDNSSECTestQueryTimeoutSecs ) * kNanosecondsPerSecond / 10, NULL, _DNSSECTestQueryTimeoutHandler,
-		NULL, inContext, &inContext->queryTimer );
-	require_noerr_action( err, exit, error_description = "DispatchTimerCreate failed" );
-	dispatch_resume( inContext->queryTimer );
-
-	// start the current subtest, and record the start time.
-	inContext->subtestStartTime	= NanoTimeGetCurrent();
-	if( !inContext->testStarted )
-	{
-		// Only call dispatch_main once, when we first start the test.
-		inContext->testStarted = true;
-		dispatch_main();
-	}
-
-	return;
-exit:
-	_DNSSECTestQueryWriteSubtestReport( inContext, error_description );
-	_DNSSECTestQueryOutputFinalReport( inContext );
-	exit( 1 );
-}
-
-//===========================================================================================================================
-
-static void DNSSD_API
-	_DNSSECTest_BasicValidationCallBack(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	char						err_desp_str[1024];
-	Boolean						valid;
-	Boolean						expectMore;
-	DNSSECTestContext * const	context = (DNSSECTestContext *)inContext;
-
-	Unused( inSDRef );
-
-	err_desp_str[0] = '\0';
-
-	// Verify if the response is expected
-	valid = _DNSSECTest_BasicValidationVerifyTheResponse(context, inFlags, inInterfaceIndex, inError, inFullName, inType,
-		inClass, inRDataLen, inRDataPtr, inTTL, err_desp_str, sizeof( err_desp_str ), &expectMore);
-
-	// If more answers are expected to be returned.
-	if( expectMore )
-	{
-		return;
-	}
-
-	// Cancel the current request and its corresponding timer.
-	DNSServiceForget( &context->query );
-	dispatch_source_forget( &context->queryTimer );
-
-	// Check if the test fails.
-	if( !valid )
-	{
-		context->subtestFailed = true;
-	}
-	_DNSSECTestQueryWriteSubtestReport( context, valid ? NULL : err_desp_str );
-
-	// Increment the index.
-	context->subtestIndex++;
-	if( context->subtestIndex == countof( DNSSECTest_BasicValidationTestCases ) )
-	{
-		// All test cases have been run
-		_DNSSECTestQueryOutputFinalReport( context );
-		exit( context->subtestFailed ? 2 : 0 );
-	}
-
-	// Start the next subtest.
-	DNSSECTest_BasicValidation( context );
-}
-
-//===========================================================================================================================
-
-// Check if the response is expected. Return true if the response is expected, otherwise return false.
-static Boolean
-_DNSSECTest_BasicValidationVerifyTheResponse(
-	DNSSECTestContext *	inContext,
-	DNSServiceFlags		inFlags,
-	uint32_t			inInterfaceIndex,
-	DNSServiceErrorType	inError,
-	const char *		inFullName,
-	uint16_t			inType,
-	uint16_t			inClass,
-	uint16_t			inRDataLen,
-	const void *		inRDataPtr,
-	uint32_t			inTTL,
-	char *				inStrBuffer,
-	uint32_t			inBufferLen,
-	Boolean *			outExpectMore )
-{
-	const char * const						queryName	= inContext->subtestQueryName;
-	DNSSECTest_BasicValidationTestCase *	testCases 	= &DNSSECTest_BasicValidationTestCases[ inContext->subtestIndex ];
-	DNSSECTest_BasicValidationContext *		subContext	= &inContext->testCaseContext.basicValidation;
-	Boolean									expectMore	= false;
-
-	Unused( inClass );
-	Unused( inRDataLen );
-	Unused( inRDataPtr );
-	Unused( inTTL );
-
-	require_noerr_action( inError, exit, SNPrintF( inStrBuffer, inBufferLen, "Unexpected DNSServiceErrorType: %d", inError ) );
-
-	require_action( inFlags & kDNSServiceFlagsAdd, exit,
-		SNPrintF( inStrBuffer, inBufferLen, "Unexpected add/remove event: %#{flags}", inFlags, kDNSServiceFlagsDescriptors )
-	);
-
-	require_action( inInterfaceIndex == kDNSServiceInterfaceIndexAny, exit,
-		SNPrintF( inStrBuffer, inBufferLen, "Non-local-only interface is used: %u", inInterfaceIndex ) );
-
-	require_action( strcmp( queryName, inFullName ) == 0, exit,
-		SNPrintF( inStrBuffer, inBufferLen, "Mismatched name: %s", inFullName ) );
-
-	require_action( inType == testCases->queryType, exit,
-		SNPrintF( inStrBuffer, inBufferLen, "Mismatched query type: %s", RecordTypeToString( inType ) ) );
-
-	require_action( (inFlags & kDNSServiceFlagsSecure) == kDNSServiceFlagsSecure, exit,
-		SNPrintF( inStrBuffer, inBufferLen, "Unexpected DNSSEC result: %#{flags}", (inFlags & kDNSServiceFlagsSecure),
-			kDNSServiceFlagsDescriptors )
-	);
-
-	if( --subContext->number_of_answers != 0 )
-	{
-		expectMore = true;
-	}
-
-
-exit:
-	if( outExpectMore )
-	{
-		*outExpectMore = expectMore;
-	}
-
-	return inStrBuffer[0] != '\0' ? false : true;
-}
-#else
-static void DNSSECTestCmd( void )
-{
-	exit( 0 );
-}
-#endif // #if ( ENABLE_DNSSDUTIL_DNSSEC_TEST == 1 )
-
-//===========================================================================================================================
-//	SSDPDiscoverCmd
-//===========================================================================================================================
-
-#define kSSDPPort		1900
-
-typedef struct
-{
-	HTTPHeader				header;			// HTTP header object for sending and receiving.
-	dispatch_source_t		readSourceV4;	// Read dispatch source for IPv4 socket.
-	dispatch_source_t		readSourceV6;	// Read dispatch source for IPv6 socket.
-	int						receiveSecs;	// After send, the amount of time to spend receiving.
-	uint32_t				ifindex;		// Index of the interface over which to send the query.
-	Boolean					useIPv4;		// True if the query should be sent via IPv4 multicast.
-	Boolean					useIPv6;		// True if the query should be sent via IPv6 multicast.
-	
-}	SSDPDiscoverContext;
-
-static void		SSDPDiscoverPrintPrologue( const SSDPDiscoverContext *inContext );
-static void		SSDPDiscoverReadHandler( void *inContext );
-static int		SocketToPortNumber( SocketRef inSock );
-static OSStatus	WriteSSDPSearchRequest( HTTPHeader *inHeader, const void *inHostSA, int inMX, const char *inST );
-
-static void	SSDPDiscoverCmd( void )
-{
-	OSStatus					err;
-	struct timeval				now;
-	SSDPDiscoverContext *		context;
-	dispatch_source_t			signalSource	= NULL;
-	SocketRef					sockV4			= kInvalidSocketRef;
-	SocketRef					sockV6			= kInvalidSocketRef;
-	ssize_t						n;
-	int							sendCount;
-	
-	// Set up SIGINT handler.
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), Exit, kExitReason_SIGINT, &signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	// Check command parameters.
-	
-	if( gSSDPDiscover_ReceiveSecs < -1 )
-	{
-		FPrintF( stdout, "Invalid receive time: %d seconds.\n", gSSDPDiscover_ReceiveSecs );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	// Create context.
-	
-	context = (SSDPDiscoverContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->receiveSecs	= gSSDPDiscover_ReceiveSecs;
-	context->useIPv4		= ( gSSDPDiscover_UseIPv4 || !gSSDPDiscover_UseIPv6 ) ? true : false;
-	context->useIPv6		= ( gSSDPDiscover_UseIPv6 || !gSSDPDiscover_UseIPv4 ) ? true : false;
-	
-	err = InterfaceIndexFromArgString( gInterface, &context->ifindex );
-	require_noerr_quiet( err, exit );
-	
-	// Set up IPv4 socket.
-	
-	if( context->useIPv4 )
-	{
-		int port;
-		err = UDPClientSocketOpen( AF_INET, NULL, 0, -1, &port, &sockV4 );
-		require_noerr( err, exit );
-		
-		err = SocketSetMulticastInterface( sockV4, NULL, context->ifindex );
-		require_noerr( err, exit );
-		
-		err = setsockopt( sockV4, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &(uint8_t){ 1 }, (socklen_t) sizeof( uint8_t ) );
-		err = map_socket_noerr_errno( sockV4, err );
-		require_noerr( err, exit );
-	}
-	
-	// Set up IPv6 socket.
-	
-	if( context->useIPv6 )
-	{
-		err = UDPClientSocketOpen( AF_INET6, NULL, 0, -1, NULL, &sockV6 );
-		require_noerr( err, exit );
-		
-		err = SocketSetMulticastInterface( sockV6, NULL, context->ifindex );
-		require_noerr( err, exit );
-		
-		err = setsockopt( sockV6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &(int){ 1 }, (socklen_t) sizeof( int ) );
-		err = map_socket_noerr_errno( sockV6, err );
-		require_noerr( err, exit );
-	}
-	
-	// Print prologue.
-	
-	SSDPDiscoverPrintPrologue( context );
-	
-	// Send mDNS query message.
-	
-	sendCount = 0;
-	if( IsValidSocket( sockV4 ) )
-	{
-		struct sockaddr_in		mcastAddr4;
-		
-		_SockAddrInitIPv4( &mcastAddr4, UINT32_C( 0xEFFFFFFA ), kSSDPPort );	// 239.255.255.250
-		
-		err = WriteSSDPSearchRequest( &context->header, &mcastAddr4, gSSDPDiscover_MX, gSSDPDiscover_ST );
-		require_noerr( err, exit );
-		
-		n = sendto( sockV4, context->header.buf, context->header.len, 0, (const struct sockaddr *) &mcastAddr4,
-			(socklen_t) sizeof( mcastAddr4 ) );
-		err = map_socket_value_errno( sockV4, n == (ssize_t) context->header.len, n );
-		if( err )
-		{
-			FPrintF( stderr, "*** Failed to send query on IPv4 socket with error %#m\n", err );
-			ForgetSocket( &sockV4 );
-		}
-		else
-		{
-			if( gSSDPDiscover_Verbose )
-			{
-				gettimeofday( &now, NULL );
-				FPrintF( stdout, "---\n" );
-				FPrintF( stdout, "Send time:    %{du:time}\n",	&now );
-				FPrintF( stdout, "Source Port:  %d\n",			SocketToPortNumber( sockV4 ) );
-				FPrintF( stdout, "Destination:  %##a\n",		&mcastAddr4 );
-				FPrintF( stdout, "Message size: %zu\n",			context->header.len );
-				FPrintF( stdout, "HTTP header:\n%1{text}",		context->header.buf, context->header.len );
-			}
-			++sendCount;
-		}
-	}
-	
-	if( IsValidSocket( sockV6 ) )
-	{
-		struct sockaddr_in6		mcastAddr6;
-		
-		memset( &mcastAddr6, 0, sizeof( mcastAddr6 ) );
-		SIN6_LEN_SET( &mcastAddr6 );
-		mcastAddr6.sin6_family				= AF_INET6;
-		mcastAddr6.sin6_port				= htons( kSSDPPort );
-		mcastAddr6.sin6_addr.s6_addr[  0 ]	= 0xFF;	// SSDP IPv6 link-local multicast address FF02::C
-		mcastAddr6.sin6_addr.s6_addr[  1 ]	= 0x02;
-		mcastAddr6.sin6_addr.s6_addr[ 15 ]	= 0x0C;
-		
-		err = WriteSSDPSearchRequest( &context->header, &mcastAddr6, gSSDPDiscover_MX, gSSDPDiscover_ST );
-		require_noerr( err, exit );
-		
-		n = sendto( sockV6, context->header.buf, context->header.len, 0, (const struct sockaddr *) &mcastAddr6,
-			(socklen_t) sizeof( mcastAddr6 ) );
-		err = map_socket_value_errno( sockV6, n == (ssize_t) context->header.len, n );
-		if( err )
-		{
-			FPrintF( stderr, "*** Failed to send query on IPv6 socket with error %#m\n", err );
-			ForgetSocket( &sockV6 );
-		}
-		else
-		{
-			if( gSSDPDiscover_Verbose )
-			{
-				gettimeofday( &now, NULL );
-				FPrintF( stdout, "---\n" );
-				FPrintF( stdout, "Send time:    %{du:time}\n",	&now );
-				FPrintF( stdout, "Source Port:  %d\n",			SocketToPortNumber( sockV6 ) );
-				FPrintF( stdout, "Destination:  %##a\n",		&mcastAddr6 );
-				FPrintF( stdout, "Message size: %zu\n",			context->header.len );
-				FPrintF( stdout, "HTTP header:\n%1{text}",		context->header.buf, context->header.len );
-			}
-			++sendCount;
-		}
-	}
-	require_action_quiet( sendCount > 0, exit, err = kUnexpectedErr );
-	
-	// If there's no wait period after the send, then exit.
-	
-	if( context->receiveSecs == 0 ) goto exit;
-	
-	// Create dispatch read sources for socket(s).
-	
-	if( IsValidSocket( sockV4 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV4, context, &err );
-		require_noerr( err, exit );
-		sockV4 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, SSDPDiscoverReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV4 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV4 );
-	}
-	
-	if( IsValidSocket( sockV6 ) )
-	{
-		SocketContext *		sockCtx;
-		
-		sockCtx = SocketContextCreate( sockV6, context, &err );
-		require_noerr( err, exit );
-		sockV6 = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, NULL, SSDPDiscoverReadHandler, SocketContextCancelHandler, sockCtx,
-			&context->readSourceV6 );
-		if( err ) ForgetSocketContext( &sockCtx );
-		require_noerr( err, exit );
-		
-		dispatch_resume( context->readSourceV6 );
-	}
-	
-	if( context->receiveSecs > 0 )
-	{
-		dispatch_after_f( dispatch_time_seconds( context->receiveSecs ), dispatch_get_main_queue(), kExitReason_Timeout,
-			Exit );
-	}
-	dispatch_main();
-	
-exit:
-	ForgetSocket( &sockV4 );
-	ForgetSocket( &sockV6 );
-	dispatch_source_forget( &signalSource );
-	exit( err ? 1 : 0 );
-}
-
-static int	SocketToPortNumber( SocketRef inSock )
-{
-	OSStatus		err;
-	sockaddr_ip		sip;
-	socklen_t		len;
-	
-	len = (socklen_t) sizeof( sip );
-	err = getsockname( inSock, &sip.sa, &len );
-	err = map_socket_noerr_errno( inSock, err );
-	check_noerr( err );
-	return( err ? -1 : SockAddrGetPort( &sip ) );
-}
-
-static OSStatus	WriteSSDPSearchRequest( HTTPHeader *inHeader, const void *inHostSA, int inMX, const char *inST )
-{
-	OSStatus		err;
-	
-	err = HTTPHeader_InitRequest( inHeader, "M-SEARCH", "*", "HTTP/1.1" );
-	require_noerr( err, exit );
-	
-	err = HTTPHeader_SetField( inHeader, "Host", "%##a", inHostSA );
-	require_noerr( err, exit );
-	
-	err = HTTPHeader_SetField( inHeader, "ST", "%s", inST ? inST : "ssdp:all" );
-	require_noerr( err, exit );
-	
-	err = HTTPHeader_SetField( inHeader, "Man", "\"ssdp:discover\"" );
-	require_noerr( err, exit );
-	
-	err = HTTPHeader_SetField( inHeader, "MX", "%d", inMX );
-	require_noerr( err, exit );
-	
-	err = HTTPHeader_Commit( inHeader );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	SSDPDiscoverPrintPrologue
-//===========================================================================================================================
-
-static void	SSDPDiscoverPrintPrologue( const SSDPDiscoverContext *inContext )
-{
-	const int				receiveSecs = inContext->receiveSecs;
-	const char *			ifName;
-	char					ifNameBuf[ IF_NAMESIZE + 1 ];
-	NetTransportType		ifType;
-	
-	ifName = if_indextoname( inContext->ifindex, ifNameBuf );
-	
-	ifType = kNetTransportType_Undefined;
-	if( ifName ) SocketGetInterfaceInfo( kInvalidSocketRef, ifName, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ifType );
-	
-	FPrintF( stdout, "Interface:        %s/%d/%s\n",
-		ifName ? ifName : "?", inContext->ifindex, NetTransportTypeToString( ifType ) );
-	FPrintF( stdout, "IP protocols:     %?s%?s%?s\n",
-		inContext->useIPv4, "IPv4", ( inContext->useIPv4 && inContext->useIPv6 ), ", ", inContext->useIPv6, "IPv6" );
-	FPrintF( stdout, "Receive duration: " );
-	if( receiveSecs >= 0 )	FPrintF( stdout, "%d second%?c\n", receiveSecs, receiveSecs != 1, 's' );
-	else					FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time:       %{du:time}\n", NULL );
-}
-
-//===========================================================================================================================
-//	SSDPDiscoverReadHandler
-//===========================================================================================================================
-
-static Boolean	_HTTPHeader_Validate( HTTPHeader *inHeader );
-
-static void	SSDPDiscoverReadHandler( void *inContext )
-{
-	OSStatus						err;
-	struct timeval					now;
-	SocketContext * const			sockCtx	= (SocketContext *) inContext;
-	SSDPDiscoverContext * const		context	= (SSDPDiscoverContext *) sockCtx->userContext;
-	HTTPHeader * const				header	= &context->header;
-	sockaddr_ip						fromAddr;
-	size_t							msgLen;
-	
-	gettimeofday( &now, NULL );
-	
-	err = SocketRecvFrom( sockCtx->sock, header->buf, sizeof( header->buf ), &msgLen, &fromAddr, sizeof( fromAddr ),
-		NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "Receive time: %{du:time}\n",	&now );
-	FPrintF( stdout, "Source:       %##a\n", 		&fromAddr );
-	FPrintF( stdout, "Message size: %zu\n",			msgLen );
-	header->len = msgLen;
-	if( _HTTPHeader_Validate( header ) )
-	{
-		FPrintF( stdout, "HTTP header:\n%1{text}", header->buf, header->len );
-		if( header->extraDataLen > 0 )
-		{
-			FPrintF( stdout, "HTTP body: %1.1H", header->extraDataPtr, (int) header->extraDataLen, INT_MAX );
-		}
-	}
-	else
-	{
-		FPrintF( stdout, "Invalid HTTP message:\n%1.1H", header->buf, (int) msgLen, INT_MAX );
-		goto exit;
-	}
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	_HTTPHeader_Validate
-//
-//	Parses for the end of an HTTP header and updates the HTTPHeader structure so it's ready to parse. Returns true if valid.
-//	This assumes the "buf" and "len" fields are set. The other fields are set by this function.
-//
-//	Note: This was copied from CoreUtils because the HTTPHeader_Validate function is currently not exported in the framework.
-//===========================================================================================================================
-
-static Boolean	_HTTPHeader_Validate( HTTPHeader *inHeader )
-{
-	const char *		src;
-	const char *		end;
-	
-	// Check for interleaved binary data (4 byte header that begins with $). See RFC 2326 section 10.12.
-	
-	require( inHeader->len < sizeof( inHeader->buf ), exit );
-	src = inHeader->buf;
-	end = src + inHeader->len;
-	if( ( ( end - src ) >= 4 ) && ( src[ 0 ] == '$' ) )
-	{
-		src += 4;
-	}
-	else
-	{
-		// Search for an empty line (HTTP-style header/body separator). CRLFCRLF, LFCRLF, or LFLF accepted.
-		// $$$ TO DO: Start from the last search location to avoid re-searching the same data over and over.
-		
-		for( ;; )
-		{
-			while( ( src < end ) && ( src[ 0 ] != '\n' ) ) ++src;
-			if( src >= end ) goto exit;
-			++src;
-			if( ( ( end - src ) >= 2 ) && ( src[ 0 ] == '\r' ) && ( src[ 1 ] == '\n' ) ) // CFLFCRLF or LFCRLF
-			{
-				src += 2;
-				break;
-			}
-			else if( ( ( end - src ) >= 1 ) && ( src[ 0 ] == '\n' ) ) // LFLF
-			{
-				src += 1;
-				break;
-			}
-		}
-	}
-	inHeader->extraDataPtr	= src;
-	inHeader->extraDataLen	= (size_t)( end - src );
-	inHeader->len			= (size_t)( src - inHeader->buf );
-	return( true );
-	
-exit:
-	return( false );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	ResQueryCmd
-//===========================================================================================================================
-
-// res_query() from libresolv is actually called res_9_query (see /usr/include/resolv.h).
-
-SOFT_LINK_LIBRARY_EX( "/usr/lib", resolv );
-SOFT_LINK_FUNCTION_EX( resolv, res_9_query,
-	int,
-	( const char *dname, int class, int type, u_char *answer, int anslen ),
-	( dname, class, type, answer, anslen ) );
-
-// res_query() from libinfo
-
-SOFT_LINK_LIBRARY_EX( "/usr/lib", info );
-SOFT_LINK_FUNCTION_EX( info, res_query,
-	int,
-	( const char *dname, int class, int type, u_char *answer, int anslen ),
-	( dname, class, type, answer, anslen ) );
-
-typedef int ( *res_query_f )( const char *dname, int class, int type, u_char *answer, int anslen );
-
-static void	ResQueryCmd( void )
-{
-	OSStatus		err;
-	res_query_f		res_query_ptr;
-	int				n;
-	uint16_t		type, class;
-	uint8_t			answer[ 1024 ];
-	
-	// Get pointer to one of the res_query() functions.
-	
-	if( gResQuery_UseLibInfo )
-	{
-		if( !SOFT_LINK_HAS_FUNCTION( info, res_query ) )
-		{
-			FPrintF( stderr, "Failed to soft link res_query from libinfo.\n" );
-			err = kNotFoundErr;
-			goto exit;
-		}
-		res_query_ptr = soft_res_query;
-	}
-	else
-	{
-		if( !SOFT_LINK_HAS_FUNCTION( resolv, res_9_query ) )
-		{
-			FPrintF( stderr, "Failed to soft link res_query from libresolv.\n" );
-			err = kNotFoundErr;
-			goto exit;
-		}
-		res_query_ptr = soft_res_9_query;
-	}
-	
-	// Get record type.
-	
-	err = RecordTypeFromArgString( gResQuery_Type, &type );
-	require_noerr( err, exit );
-	
-	// Get record class.
-	
-	if( gResQuery_Class )
-	{
-		err = RecordClassFromArgString( gResQuery_Class, &class );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		class = kDNSServiceClass_IN;
-	}
-	
-	// Print prologue.
-	
-	FPrintF( stdout, "Name:       %s\n",			gResQuery_Name );
-	FPrintF( stdout, "Type:       %s (%u)\n",		RecordTypeToString( type ), type );
-	FPrintF( stdout, "Class:      %s (%u)\n",		( class == kDNSServiceClass_IN ) ? "IN" : "???", class );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	// Call res_query().
-	
-	n = res_query_ptr( gResQuery_Name, class, type, (u_char *) answer, (int) sizeof( answer ) );
-	if( n < 0 )
-	{
-		FPrintF( stderr, "res_query() failed with error: %d (%s).\n", h_errno, hstrerror( h_errno ) );
-		err = kUnknownErr;
-		goto exit;
-	}
-	
-	// Print result.
-	
-	FPrintF( stdout, "Message size: %d\n\n%{du:dnsmsg}\n", n, answer, (size_t) n );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	ResolvDNSQueryCmd
-//===========================================================================================================================
-
-// dns_handle_t is defined as a pointer to a privately-defined struct in /usr/include/dns.h. It's defined as a void * here to
-// avoid including the header file.
-
-typedef void *		dns_handle_t;
-
-SOFT_LINK_FUNCTION_EX( resolv, dns_open, dns_handle_t, ( const char *path ), ( path ) );
-SOFT_LINK_FUNCTION_VOID_RETURN_EX( resolv, dns_free, ( dns_handle_t *dns ), ( dns ) );
-SOFT_LINK_FUNCTION_EX( resolv, dns_query,
-	int32_t, (
-		dns_handle_t		dns,
-		const char *		name,
-		uint32_t			dnsclass,
-		uint32_t			dnstype,
-		char *				buf,
-		uint32_t			len,
-		struct sockaddr *	from,
-		uint32_t *			fromlen ),
-	( dns, name, dnsclass, dnstype, buf, len, from, fromlen ) );
-
-static void	ResolvDNSQueryCmd( void )
-{
-	OSStatus			err;
-	int					n;
-	dns_handle_t		dns = NULL;
-	uint16_t			type, class;
-	sockaddr_ip			from;
-	uint32_t			fromLen;
-	uint8_t				answer[ 1024 ];
-	
-	// Make sure that the required symbols are available.
-	
-	if( !SOFT_LINK_HAS_FUNCTION( resolv, dns_open ) )
-	{
-		FPrintF( stderr, "Failed to soft link dns_open from libresolv.\n" );
-		err = kNotFoundErr;
-		goto exit;
-	}
-	
-	if( !SOFT_LINK_HAS_FUNCTION( resolv, dns_free ) )
-	{
-		FPrintF( stderr, "Failed to soft link dns_free from libresolv.\n" );
-		err = kNotFoundErr;
-		goto exit;
-	}
-	
-	if( !SOFT_LINK_HAS_FUNCTION( resolv, dns_query ) )
-	{
-		FPrintF( stderr, "Failed to soft link dns_query from libresolv.\n" );
-		err = kNotFoundErr;
-		goto exit;
-	}
-	
-	// Get record type.
-	
-	err = RecordTypeFromArgString( gResolvDNSQuery_Type, &type );
-	require_noerr( err, exit );
-	
-	// Get record class.
-	
-	if( gResolvDNSQuery_Class )
-	{
-		err = RecordClassFromArgString( gResolvDNSQuery_Class, &class );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		class = kDNSServiceClass_IN;
-	}
-	
-	// Get dns handle.
-	
-	dns = soft_dns_open( gResolvDNSQuery_Path );
-	if( !dns )
-	{
-		FPrintF( stderr, "dns_open( %s ) failed.\n", gResolvDNSQuery_Path );
-		err = kUnknownErr;
-		goto exit;
-	}
-	
-	// Print prologue.
-	
-	FPrintF( stdout, "Name:       %s\n",			gResolvDNSQuery_Name );
-	FPrintF( stdout, "Type:       %s (%u)\n",		RecordTypeToString( type ), type );
-	FPrintF( stdout, "Class:      %s (%u)\n",		( class == kDNSServiceClass_IN ) ? "IN" : "???", class );
-	FPrintF( stdout, "Path:       %s\n",			gResolvDNSQuery_Path ? gResolvDNSQuery_Name : "<NULL>" );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	// Call dns_query().
-	
-	memset( &from, 0, sizeof( from ) );
-	fromLen = (uint32_t) sizeof( from );
-	n = soft_dns_query( dns, gResolvDNSQuery_Name, class, type, (char *) answer, (uint32_t) sizeof( answer ), &from.sa,
-		&fromLen );
-	if( n < 0 )
-	{
-		FPrintF( stderr, "dns_query() failed with error: %d (%s).\n", h_errno, hstrerror( h_errno ) );
-		err = kUnknownErr;
-		goto exit;
-	}
-	
-	// Print result.
-	
-	FPrintF( stdout, "From:         %##a\n", &from );
-	FPrintF( stdout, "Message size: %d\n\n%{du:dnsmsg}\n", n, answer, (size_t) n );
-	
-exit:
-	if( dns ) soft_dns_free( dns );
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	CFHostCmd
-//===========================================================================================================================
-
-static void
-	_CFHostResolveCallback(
-		CFHostRef				inHost,
-		CFHostInfoType			inInfoType,
-		const CFStreamError *	inError,
-		void *					inInfo );
-
-static void	CFHostCmd( void )
-{
-	OSStatus				err;
-	CFStringRef				name;
-	Boolean					success;
-	CFHostRef				host = NULL;
-	CFHostClientContext		context;
-	CFStreamError			streamErr;
-	
-	name = CFStringCreateWithCString( kCFAllocatorDefault, gCFHost_Name, kCFStringEncodingUTF8 );
-	require_action( name, exit, err = kUnknownErr );
-	
-	host = CFHostCreateWithName( kCFAllocatorDefault, name );
-	ForgetCF( &name );
-	require_action( host, exit, err = kUnknownErr );
-	
-	memset( &context, 0, sizeof( context ) );
-	success = CFHostSetClient( host, _CFHostResolveCallback, &context );
-	require_action( success, exit, err = kUnknownErr );
-	
-	CFHostScheduleWithRunLoop( host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
-	
-	// Print prologue.
-	
-	FPrintF( stdout, "Hostname:   %s\n",			gCFHost_Name );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	success = CFHostStartInfoResolution( host, kCFHostAddresses, &streamErr );
-	require_action( success, exit, err = kUnknownErr );
-	err = kNoErr;
-	
-	CFRunLoopRun();
-	
-exit:
-	CFReleaseNullSafe( host );
-	if( err ) exit( 1 );
-}
-
-static void	_CFHostResolveCallback( CFHostRef inHost, CFHostInfoType inInfoType, const CFStreamError *inError, void *inInfo )
-{
-	OSStatus			err;
-	struct timeval		now;
-	
-	gettimeofday( &now, NULL );
-	
-	Unused( inInfoType );
-	Unused( inInfo );
-	
-	if( inError && ( inError->domain != 0 ) && ( inError->error ) )
-	{
-		err = inError->error;
-		if( inError->domain == kCFStreamErrorDomainNetDB )
-		{
-			FPrintF( stderr, "Error %d: %s.\n", err, gai_strerror( err ) );
-		}
-		else
-		{
-			FPrintF( stderr, "Error %#m\n", err );
-		}
-	}
-	else
-	{
-		CFArrayRef					addresses;
-		CFIndex						count, i;
-		CFDataRef					addrData;
-		const struct sockaddr *		sockAddr;
-		Boolean						wasResolved = false;
-		
-		addresses = CFHostGetAddressing( inHost, &wasResolved );
-		check( wasResolved );
-		
-		if( addresses )
-		{
-			count = CFArrayGetCount( addresses );
-			for( i = 0; i < count; ++i )
-			{
-				addrData = CFArrayGetCFDataAtIndex( addresses, i, &err );
-				require_noerr( err, exit );
-				
-				sockAddr = (const struct sockaddr *) CFDataGetBytePtr( addrData );
-				FPrintF( stdout, "%##a\n", sockAddr );
-			}
-		}
-		err = kNoErr;
-	}
-	
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:   %{du:time}\n", &now );
-	
-	if( gCFHost_WaitSecs > 0 ) sleep( (unsigned int) gCFHost_WaitSecs );
-	
-exit:
-	exit( err ? 1 : 0 );
-}
-
-//===========================================================================================================================
-//	DNSConfigAddCmd
-//
-//	Note: Based on ajn's supplemental test tool.
-//===========================================================================================================================
-
-static void	DNSConfigAddCmd( void )
-{
-	OSStatus					err;
-	mdns_dns_configurator_t		configurator;
-	uint32_t					order;
-	size_t						i;
-	
-	configurator = mdns_dns_configurator_create_with_cfstring_id( gDNSConfigAdd_ID, &err );
-	require_noerr( err, exit );
-	
-	for( i = 0; i < gDNSConfigAdd_IPAddrCount; ++i )
-	{
-		err = mdns_dns_configurator_add_server_address_string( configurator, gDNSConfigAdd_IPAddrArray[ i ] );
-		require_noerr( err, exit );
-	}
-	order = ( gDNSConfigAdd_SearchOrder > 0 ) ? ( (uint32_t) gDNSConfigAdd_SearchOrder ) : 0;
-	if( gDNSConfigAdd_DomainCount > 0 )
-	{
-		for( i = 0; i < gDNSConfigAdd_DomainCount; ++i )
-		{
-			err = mdns_dns_configurator_add_domain( configurator, gDNSConfigAdd_DomainArray[ i ], order );
-			require_noerr( err, exit );
-		}
-	}
-	else
-	{
-		// There are no domains, but the domain array needs to be non-empty, so add a zero-length domain.
-		
-		err = mdns_dns_configurator_add_domain( configurator, "", order );
-		require_noerr( err, exit );
-	}
-	
-	if( gDNSConfigAdd_Interface )
-	{
-		err = mdns_dns_configurator_set_interface( configurator, gDNSConfigAdd_Interface );
-		require_noerr( err, exit );
-	}
-	err = mdns_dns_configurator_register( configurator, CFSTR( kDNSSDUtilIdentifier ) );
-	require_noerr( err, exit );
-	
-exit:
-	mdns_forget( &configurator );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-//	DNSConfigRemoveCmd
-//===========================================================================================================================
-
-static void	DNSConfigRemoveCmd( void )
-{
-	OSStatus err = mdns_dns_configurator_deregister_configuration( gDNSConfigRemove_ID, CFSTR( kDNSSDUtilIdentifier ) );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-//	XPCSendCommand
-//===========================================================================================================================
-
-static OSStatus	_XPCDictionaryCreateFromString( const char *inString, xpc_object_t *outDict );
-
-typedef struct
-{
-	dispatch_queue_t			queue;				// Dispatch queue.
-	dispatch_semaphore_t		doneSem;			// Semaphore to signal when done.
-	char *						serviceName;		// Mach service name.
-	char *						msgStr;				// Message to send as a string.
-	xpc_connection_t			connection;			// XPC connection.
-	dispatch_source_t			cancelTimer;		// Timer cancelling the XPC connection.
-	dispatch_source_t			sourceSigInt;		// Dispatch source for SIGINT.
-	dispatch_source_t			sourceSigTerm;		// Dispatch source for SIGTERM.
-	int32_t						refCount;			// Reference count.
-	int							cancelDelaySecs;	// Number of seconds to wait before cancelling the connection.
-	OSStatus					error;				// Command's final error.
-	Boolean						noReply;			// True if there was a message to send and a reply is expected.
-	Boolean						done;				// True if the command is done.
-	
-}	XPCSendCmd;
-
-static OSStatus	_XPCSendCmdCreate( XPCSendCmd **outCmd );
-static void		_XPCSendCmdRetain( XPCSendCmd *inCmd );
-static void		_XPCSendCmdRelease( XPCSendCmd *inCmd );
-static OSStatus	_XPCSendCmdRun( XPCSendCmd *inCmd );
-static void		_XPCSendCmdStart( void *inCtx );
-static void		_XPCSendCmdStop( XPCSendCmd *inCmd, OSStatus inError );
-static OSStatus	_XPCSendCmdScheduleConnectionCancellation( XPCSendCmd *inCmd );
-
-static void	XPCSendCommand( void )
-{
-	OSStatus			err;
-	XPCSendCmd *		cmd = NULL;
-	
-	err = _XPCSendCmdCreate( &cmd );
-	require_noerr( err, exit );
-	
-	cmd->serviceName = strdup( gXPCSend_ServiceName );
-	require_action( cmd->serviceName, exit, err = kNoMemoryErr );
-	
-	if( gXPCSend_MessageStr )
-	{
-		cmd->msgStr = strdup( gXPCSend_MessageStr );
-		require_action( cmd->msgStr, exit, err = kNoMemoryErr );
-	}
-	cmd->cancelDelaySecs	= gXPCSend_CancelDelaySecs;
-	cmd->noReply			= gXPCSend_NoReply ? true : false;
-	
-	err = _XPCSendCmdRun( cmd );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	if( err ) FPrintF( stderr, "error: %#m\n", err );
-	if( cmd ) _XPCSendCmdRelease( cmd );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-
-static OSStatus	_XPCSendCmdCreate( XPCSendCmd ** const outCmd )
-{
-	OSStatus			err;
-	XPCSendCmd *		cmd;
-	
-	cmd = (XPCSendCmd *) calloc( 1, sizeof( *cmd ) );
-	require_action( cmd, exit, err = kNoResourcesErr );
-	
-	cmd->refCount	= 1;
-	cmd->error		= kInProgressErr;
-	
-	cmd->queue = dispatch_queue_create( "com.apple.dnssdutil.xpc-send-command", DISPATCH_QUEUE_SERIAL );
-	require_action( cmd->queue, exit, err = kNoResourcesErr );
-	
-	cmd->doneSem = dispatch_semaphore_create( 0 );
-	require_action( cmd->doneSem, exit, err = kNoResourcesErr );
-	
-	*outCmd = cmd;
-	cmd = NULL;
-	err = kNoErr;
-	
-exit:
-	if( cmd ) _XPCSendCmdRelease( cmd );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_XPCSendCmdRetain( XPCSendCmd * const me )
-{
-	atomic_add_32( &me->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_XPCSendCmdRelease( XPCSendCmd * const me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->connection );
-		check( !me->cancelTimer );
-		check( !me->sourceSigInt );
-		check( !me->sourceSigTerm );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->doneSem );
-		ForgetMem( &me->serviceName );
-		ForgetMem( &me->msgStr );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-
-static OSStatus	_XPCSendCmdRun( XPCSendCmd * const me )
-{
-	dispatch_async_f( me->queue, me, _XPCSendCmdStart );
-    dispatch_semaphore_wait( me->doneSem, DISPATCH_TIME_FOREVER );
-	return( me->error );
-}
-
-//===========================================================================================================================
-
-static void	_XPCSendCmdStart( void * const inCtx )
-{
-	OSStatus				err;
-	XPCSendCmd * const		me				= (XPCSendCmd *) inCtx;
-	xpc_object_t			msg				= NULL;
-	dispatch_source_t		sourceSigInt	= NULL;
-	dispatch_source_t		sourceSigTerm	= NULL;
-	
-	sourceSigInt = dispatch_source_create( DISPATCH_SOURCE_TYPE_SIGNAL, SIGINT, 0, me->queue );
-	require_action( sourceSigInt, exit, err = kNoResourcesErr );
-	
-	sourceSigTerm = dispatch_source_create( DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, me->queue );
-	require_action( sourceSigInt, exit, err = kNoResourcesErr );
-	
-	me->sourceSigInt	= sourceSigInt;
-	sourceSigInt		= NULL;
-	me->sourceSigTerm	= sourceSigTerm;
-	sourceSigTerm		= NULL;
-	
-	signal( SIGINT, SIG_IGN );
-	signal( SIGTERM, SIG_IGN );
-	dispatch_source_set_event_handler( me->sourceSigInt,
-	^{
-		FPrintF( stdout, "*** Got SIGINT signal ***\n" );
-		_XPCSendCmdStop( me, kNoErr );
-	} );
-	dispatch_activate( me->sourceSigInt );
-	dispatch_source_set_event_handler( me->sourceSigTerm,
-	^{
-		FPrintF( stdout, "*** Got SIGTERM signal ***\n" );
-		_XPCSendCmdStop( me, kNoErr );
-	} );
-	dispatch_activate( me->sourceSigTerm );
-	
-	if( me->msgStr )
-	{
-		err = _XPCDictionaryCreateFromString( me->msgStr, &msg );
-		require_noerr_quiet( err, exit );
-	}
-	FPrintF( stdout, "Service:    %s\n",			me->serviceName );
-	FPrintF( stdout, "Message:    '%s'\n",			me->msgStr );
-	FPrintF( stdout, "Wait:       %d second%s\n",	me->cancelDelaySecs, ( me->cancelDelaySecs != 1 ) ? "s" : "" );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	if( msg ) FPrintF( stdout, "XPC Message:\n%{xpc}\n", msg );
-	
-	me->connection = xpc_connection_create_mach_service( me->serviceName, me->queue, 0 );
-	require_action( me->connection, exit, err = kNoResourcesErr );
-	
-	_XPCSendCmdRetain( me );
-	xpc_connection_set_event_handler( me->connection,
-	^( const xpc_object_t inEvent )
-	{
-		if( !me->done ) FPrintF( stdout, "[%{du:time}] Connection Event:\n%{xpc}\n", NULL, inEvent );
-		if( inEvent == XPC_ERROR_CONNECTION_INVALID )
-		{
-			_XPCSendCmdRelease( me );
-		}
-	} );
-	xpc_connection_activate( me->connection );
-	
-	if( msg )
-	{
-		if( me->noReply )
-		{
-			xpc_connection_send_message( me->connection, msg );
-			_XPCSendCmdRetain( me );
-			xpc_connection_send_barrier( me->connection,
-			^{
-				if( !me->done )
-				{
-					OSStatus		localErr;
-					
-					localErr = _XPCSendCmdScheduleConnectionCancellation( me );
-					if( localErr ) _XPCSendCmdStop( me, localErr );
-				}
-				_XPCSendCmdRelease( me );
-			} );
-		}
-		else
-		{
-			_XPCSendCmdRetain( me );
-			xpc_connection_send_message_with_reply( me->connection, msg, me->queue,
-			^( const xpc_object_t inReply )
-			{
-				if( !me->done )
-				{
-					OSStatus		localErr;
-					
-					FPrintF( stdout, "[%{du:time}] Reply:\n%{xpc}\n", NULL, inReply );
-					localErr = _XPCSendCmdScheduleConnectionCancellation( me );
-					if( localErr ) _XPCSendCmdStop( me, localErr );
-				}
-				_XPCSendCmdRelease( me );
-			} );
-		}
-	}
-	else
-	{
-		err = _XPCSendCmdScheduleConnectionCancellation( me );
-		require_noerr( err, exit );
-	}
-	err = kNoErr;
-	
-exit:
-	xpc_forget( &msg );
-	dispatch_forget( &sourceSigInt );
-	dispatch_forget( &sourceSigTerm );
-	if( err ) _XPCSendCmdStop( me, err );
-}
-
-//===========================================================================================================================
-
-static void	_XPCSendCmdStop( XPCSendCmd * const me, const OSStatus inError )
-{
-	if( !me->done )
-	{
-		me->done	= true;
-		me->error	= inError;
-		xpc_connection_forget( &me->connection );
-		dispatch_source_forget( &me->cancelTimer );
-		dispatch_source_forget( &me->sourceSigInt );
-		dispatch_source_forget( &me->sourceSigTerm );
-		FPrintF( stdout, "---\n" );
-		FPrintF( stdout, "End time:   %{du:time}\n", NULL );
-		dispatch_semaphore_signal( me->doneSem );
-	}
-}
-
-//===========================================================================================================================
-
-static OSStatus	_XPCSendCmdScheduleConnectionCancellation( XPCSendCmd * const me )
-{
-	OSStatus		err;
-	
-	if( me->cancelDelaySecs >= 0 )
-	{
-		me->cancelTimer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, me->queue );
-		require_action( me->cancelTimer, exit, err = kNoResourcesErr );
-		
-		dispatch_source_set_timer( me->cancelTimer, dispatch_time_seconds( me->cancelDelaySecs ), DISPATCH_TIME_FOREVER, 0 );
-		dispatch_source_set_event_handler( me->cancelTimer,
-		^{
-			_XPCSendCmdStop( me, kNoErr );
-		} );
-		dispatch_activate( me->cancelTimer );
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_XPCDictionaryCreateFromString
-//===========================================================================================================================
-
-#define kXPCObjectPrefix_Bool			"bool:"
-#define kXPCObjectPrefix_BoolAbbr		"b:"
-#define kXPCObjectPrefix_Data			"data:"
-#define kXPCObjectPrefix_DataAbbr		"d:"
-#define kXPCObjectPrefix_Int64			"int:"
-#define kXPCObjectPrefix_Int64Abbr		"i:"
-#define kXPCObjectPrefix_String			"string:"
-#define kXPCObjectPrefix_StringAbbr		"s:"
-#define kXPCObjectPrefix_UInt64			"uint:"
-#define kXPCObjectPrefix_UInt64Abbr		"u:"
-#define kXPCObjectPrefix_UUID			"uuid:"
-
-typedef struct XPCListItem		XPCListItem;
-struct XPCListItem
-{
-	XPCListItem *		next;
-	xpc_object_t		obj;
-	char *				key;
-};
-
-static OSStatus	_XPCListItemCreate( xpc_object_t inObject, const char *inKey, XPCListItem **outItem );
-static void		_XPCListItemFree( XPCListItem *inItem );
-static void		_XPCListFree( XPCListItem *inList );
-
-static OSStatus	_XPCObjectFromString( const char *inString, xpc_object_t *outObject );
-
-static OSStatus	_XPCDictionaryCreateFromString( const char *inString, xpc_object_t *outDict )
-{
-	OSStatus				err;
-	xpc_object_t			dict;
-	xpc_object_t			container	= NULL;
-	char *					keyMem		= NULL;
-	const char *			ptr			= inString;
-	const char * const		end			= inString + strlen( inString );
-	XPCListItem *			stack		= NULL;
-	
-	dict = xpc_dictionary_create( NULL, NULL, 0 );
-	require_action( dict, exit, err = kNoMemoryErr );
-	
-	container = xpc_retain( dict );
-	while( *ptr )
-	{
-		xpc_type_t		containerType;
-		int				c;
-		
-		// At this point, zero or more of the current container's elements have been parsed.
-		// Skip the white space leading up to the container's next element, if any, or the container's end.
-		
-		while( isspace_safe( *ptr ) ) ++ptr;
-		c = *ptr;
-		if( c == '\0' ) break;
-		
-		// Check if we're done with the current container.
-		
-		containerType = xpc_get_type( container );
-		if( ( ( containerType == XPC_TYPE_DICTIONARY ) && ( c == '}' ) ) ||
-			( ( containerType == XPC_TYPE_ARRAY )      && ( c == ']' ) ) )
-		{
-			XPCListItem *		item;
-			
-			item = stack;
-			require_action_quiet( item, exit, err = kMalformedErr );
-			
-			// Add the current container to its parent container.
-			
-			if( item->key )
-			{
-				xpc_dictionary_set_value( item->obj, item->key, container );
-			}
-			else
-			{
-				xpc_array_append_value( item->obj, container );
-			}
-			
-			// Pop the parent container from the stack and continue with the parent container.
-			
-			xpc_forget( &container );
-			container = xpc_retain( item->obj );
-			stack = item->next;
-			_XPCListItemFree( item );
-			++ptr; // Increment past the end of the container.
-		}
-		else
-		{
-			const char *		keyStr;
-			char				keyBuf[ 64 ];
-			
-			// If the current container is a dictionary, parse the key string.
-			
-			if( containerType == XPC_TYPE_DICTIONARY )
-			{
-				ForgetMem( &keyMem );
-				err = _ParseEscapedStringWithCopy( ptr, end, "={}[]" kWhiteSpaceCharSet, keyBuf, sizeof( keyBuf ),
-					&keyStr, &keyMem, &ptr );
-				require_noerr_quiet( err, exit );
-				require_action_quiet( *ptr == '=', exit, err = kMalformedErr );
-				++ptr;
-				check( keyStr );
-			}
-			else
-			{
-				keyStr = NULL;
-			}
-			
-			// Parse the value string.
-			
-			c = *ptr;
-			if( ( c == '{' ) || ( c == '[' ) )	// Check if the value is a container.
-			{
-				XPCListItem *		item;
-				
-				// Push the current container onto the container stack.
-				
-				err = _XPCListItemCreate( container, keyStr, &item );
-				require_noerr( err, exit );
-				
-				item->next = stack;
-				stack = item;
-				item = NULL;
-				
-				// Create and continue with the child container.
-				
-				xpc_forget( &container );
-				if( c == '{' )
-				{
-					container = xpc_dictionary_create( NULL, NULL, 0 );
-					require_action( container, exit, err = kNoMemoryErr );
-				}
-				else
-				{
-					container = xpc_array_create( NULL, 0 );
-					require_action( container, exit, err = kNoMemoryErr );
-				}
-				++ptr; // Increment past the start of the container.
-			}
-			else
-			{
-				const char *		valStr;
-				char *				valMem;
-				xpc_object_t		value;
-				char				valBuf[ 64 ];
-				
-				err = _ParseEscapedStringWithCopy( ptr, end, "{}[]" kWhiteSpaceCharSet, valBuf, sizeof( valBuf ),
-					&valStr, &valMem, &ptr );
-				require_noerr_quiet( err, exit );
-				
-				err = _XPCObjectFromString( valStr, &value );
-				valStr = NULL;
-				ForgetMem( &valMem );
-				require_noerr_quiet( err, exit );
-				
-				if( keyStr )
-				{
-					xpc_dictionary_set_value( container, keyStr, value );
-				}
-				else
-				{
-					xpc_array_append_value( container, value );
-				}
-				xpc_forget( &value );
-			}
-		}
-	}
-	
-	// There should be no containers left on the stack.
-	
-	require_action_quiet( !stack, exit, err = kMalformedErr );
-	check( container == dict );
-	
-	*outDict = dict;
-	dict = NULL;
-	err = kNoErr;
-	
-exit:
-	xpc_forget( &dict );
-	xpc_forget( &container );
-	ForgetMem( &keyMem );
-	if( stack ) _XPCListFree( stack );
-	return( err );
-}
-
-typedef enum
-{
-	kXPCObjectType_Invalid	= 0,
-	kXPCObjectType_Bool		= 1,
-	kXPCObjectType_Data		= 2,
-	kXPCObjectType_Int64	= 3,
-	kXPCObjectType_String	= 4,
-	kXPCObjectType_UInt64	= 5,
-	kXPCObjectType_UUID		= 6
-	
-}	XPCObjectType;
-
-static OSStatus	_XPCObjectFromString( const char *inString, xpc_object_t *outObject )
-{
-	OSStatus			err;
-	xpc_object_t		object;
-	const char *		valStr;
-	size_t				valOffset;
-	XPCObjectType		type;
-	
-	if( 0 ) {}
-	
-	// Bool
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_Bool ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_Bool );
-		type = kXPCObjectType_Bool;
-	}
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_BoolAbbr ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_BoolAbbr );
-		type = kXPCObjectType_Bool;
-	}
-	
-	// Data
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_Data ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_Data );
-		type = kXPCObjectType_Data;
-	}
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_DataAbbr ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_DataAbbr );
-		type = kXPCObjectType_Data;
-	}
-	
-	// Int64
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_Int64 ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_Int64 );
-		type = kXPCObjectType_Int64;
-	}
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_Int64Abbr ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_Int64Abbr );
-		type = kXPCObjectType_Int64;
-	}
-	
-	// String
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_String ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_String );
-		type = kXPCObjectType_String;
-	}
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_StringAbbr ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_StringAbbr );
-		type = kXPCObjectType_String;
-	}
-	
-	// UInt64
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_UInt64 ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_UInt64 );
-		type = kXPCObjectType_UInt64;
-	}
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_UInt64Abbr ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_UInt64Abbr );
-		type = kXPCObjectType_UInt64;
-	}
-	
-	// UUID
-	
-	else if( stricmp_prefix( inString, kXPCObjectPrefix_UUID ) == 0 )
-	{
-		valOffset = sizeof_string( kXPCObjectPrefix_UUID );
-		type = kXPCObjectType_UUID;
-	}
-
-	// Unsupported prefix
-	
-	else
-	{
-		err = kValueErr;
-		goto exit;
-	}
-	
-	valStr = &inString[ valOffset ];
-	switch( type )
-	{
-		case kXPCObjectType_Bool:
-		{
-			if( IsTrueString( valStr, kSizeCString ) )
-			{
-				object = xpc_bool_create( true );
-			}
-			else if( IsFalseString( valStr, kSizeCString ) )
-			{
-				object = xpc_bool_create( false );
-			}
-			else
-			{
-				err = kValueErr;
-				goto exit;
-			}
-			break;
-		}
-		case kXPCObjectType_Data:
-		{
-			uint8_t *		dataPtr;
-			size_t			dataLen;
-			
-			err = HexToDataCopy( valStr, kSizeCString, kHexToData_DefaultFlags, &dataPtr, &dataLen, NULL );
-			require_noerr( err, exit );
-			
-			object = xpc_data_create( dataPtr, dataLen );
-			free( dataPtr );
-			require_action( object, exit, err = kNoMemoryErr );
-			break;
-		}
-		case kXPCObjectType_Int64:
-		{
-			int64_t		i64;
-			
-			i64 = _StringToInt64( valStr, &err );
-			require_noerr_quiet( err, exit );
-			
-			object = xpc_int64_create( i64 );
-			require_action( object, exit, err = kNoMemoryErr );
-			break;
-		}
-		case kXPCObjectType_String:
-		{
-			object = xpc_string_create( valStr );
-			require_action( object, exit, err = kNoMemoryErr );
-			break;
-		}
-		case kXPCObjectType_UInt64:
-		{
-			uint64_t		u64;
-			
-			u64 = _StringToUInt64( valStr, &err );
-			require_noerr_quiet( err, exit );
-			
-			object = xpc_uint64_create( u64 );
-			require_action( object, exit, err = kNoMemoryErr );
-			break;
-		}
-		case kXPCObjectType_UUID:
-		{
-			uuid_t		uuid;
-			
-			err = uuid_parse( valStr, uuid );
-			require_noerr_action_quiet( err, exit, err = kValueErr );
-			
-			object = xpc_uuid_create( uuid );
-			require_action( object, exit, err = kNoMemoryErr );
-			break;
-		}
-		default:
-		{
-			FatalErrorF( "Unhandled XPCObjectType %ld", (long) type );
-		}
-	}
-	check( object );
-	*outObject = object;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-static OSStatus	_XPCListItemCreate( xpc_object_t inObject, const char *inKey, XPCListItem **outItem )
-{
-	OSStatus			err;
-	XPCListItem *		item;
-	
-	item = (XPCListItem *) calloc( 1, sizeof( *item ) );
-	require_action( item, exit, err = kNoMemoryErr );
-	
-	item->obj = xpc_retain( inObject );
-	if( ( xpc_get_type( item->obj ) == XPC_TYPE_DICTIONARY ) && inKey )
-	{
-		item->key = strdup( inKey );
-		require_action( item->key, exit, err = kNoMemoryErr );
-	}
-	
-	*outItem = item;
-	item = NULL;
-	err = kNoErr;
-	
-exit:
-	if( item ) _XPCListItemFree( item );
-	return( err );
-}
-
-static void	_XPCListItemFree( XPCListItem *inItem )
-{
-	xpc_forget( &inItem->obj );
-	ForgetMem( &inItem->key );
-	free( inItem );
-}
-
-static void _XPCListFree( XPCListItem *inList )
-{
-	XPCListItem *		item;
-	
-	while( ( item = inList ) != NULL )
-	{
-		inList = item->next;
-		_XPCListItemFree( item );
-	}
-}
-#endif	// TARGET_OS_DARWIN
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	InterfaceMonitorCmd
-//===========================================================================================================================
-
-static void	_InterfaceMonitorPrint( mdns_interface_monitor_t inMonitor, mdns_interface_flags_t inUpdateFlags );
-static void	_InterfaceMonitorSignalHandler( void *inContext );
-
-static void	InterfaceMonitorCmd( void )
-{
-	OSStatus						err;
-	mdns_interface_monitor_t		monitor;
-	dispatch_source_t				signalSource = NULL;
-	uint32_t						ifIndex;
-	__block int						exitCode;
-	
-	err = InterfaceIndexFromArgString( gInterface, &ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	monitor = mdns_interface_monitor_create( ifIndex );
-	require_action( monitor, exit, err = kNoResourcesErr );
-	
-	exitCode = 0;
-	mdns_interface_monitor_set_queue( monitor, dispatch_get_main_queue() );
-	mdns_interface_monitor_set_event_handler( monitor,
-	^( mdns_event_t inEvent, OSStatus inError )
-	{
-		switch( inEvent )
-		{
-			case mdns_event_error:
-				FPrintF( stderr, "error: Interface monitor failed: %#m\n", inError );
-				mdns_interface_monitor_invalidate( monitor );
-				exitCode = 1;
-				break;
-			
-			case mdns_event_invalidated:
-				FPrintF( stdout, "Interface monitor invalidated.\n" );
-				mdns_release( monitor );
-				exit( exitCode );
-			
-			default:
-				FPrintF( stdout, "Unhandled event '%s' (%ld)\n", mdns_event_to_string( inEvent ), (long) inEvent );
-				break;
-		}
-	} );
-	mdns_interface_monitor_set_update_handler( monitor,
-	^( __unused mdns_interface_flags_t inUpdateFlags )
-	{
-		_InterfaceMonitorPrint( monitor, inUpdateFlags );
-	} );
-	
-	_InterfaceMonitorPrint( monitor, 0 );
-	mdns_interface_monitor_activate( monitor );
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), _InterfaceMonitorSignalHandler, monitor,
-		&signalSource );
-	require_noerr( err, exit );
-	dispatch_resume( signalSource );
-	
-	dispatch_main();
-	
-exit:
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-static void
-	_InterfaceMonitorPrint(
-		const mdns_interface_monitor_t	inMonitor,
-		const mdns_interface_flags_t	inUpdateFlags )
-{
-	FPrintF( stdout, "%{du:time} %@%s\n",
-		NULL, inMonitor, ( inUpdateFlags & mdns_interface_flag_network ) ? " (network changed)" : "" );
-}
-
-static void	_InterfaceMonitorSignalHandler( void *inContext )
-{
-	mdns_interface_monitor_invalidate( (mdns_interface_monitor_t) inContext );
-}
-
-//===========================================================================================================================
-//	QuerierCommand
-//===========================================================================================================================
-
-typedef struct
-{
-	dispatch_queue_t				queue;					// Serial queue for command's events.
-	dispatch_semaphore_t			doneSem;				// Semaphore to signal when command is done.
-	uint8_t *						qname;					// Name of record to query for.
-	mdns_querier_t					querier;				// Querier.
-	dispatch_source_t				sourceSigInt;			// Dispatch source for SIGINT.
-	dispatch_source_t				sourceSigTerm;			// Dispatch source for SIGTERM.
-	int32_t							refCount;				// Reference count.
-	OSStatus						error;					// Command's error.
-	uint32_t						ifIndex;				// Interface index for scoping.
-	int32_t							startTimeLeewayMs;		// Start time leeway in milliseconds.
-	uint16_t						qtype;					// Type of record to query for.
-	uint16_t						qclass;					// Class of record to query for.
-	pid_t							delegatorPID;			// Delegator PID.
-	uint8_t							delegatorUUID[ 16 ];	// Delegator UUID.
-	Boolean							haveDelegatorPID;		// True if delegatorPID is set.
-	Boolean							haveDelegatorUUID;		// True if delegatorUUID is set.
-	Boolean							dnssecOK;				// True if queries need an OPT record with the DO bit set.
-	Boolean							checkingDisabled;		// True if queries need the CD bit set.
-	Boolean							haveStartTimeLeeway;	// True if the start time leeway was set.
-	Boolean							done;					// True if the command is done.
-	
-	// Variables for resolver.
-	
-	mdns_resolver_type_t			resolverType;			// Type of resolver to use.
-	mdns_resolver_t					resolver;				// Resolver.
-	CFMutableArrayRef				serverAddrs;			// Server addresses to use for resolver.
-	char *							providerName;			// Provider name for resolver.
-	char *							connectionHostname;		// Overrides hostname used for transport layer connection.
-	char *							urlPath;				// URL path for resolver.
-	void *							identityRefPtr;			// Keychain identity reference.
-	size_t							identityRefLen;			// Keychain identity reference length.
-	void *							odohCfgPtr;				// Oblivious DoH configuration.
-	size_t							odohCfgLen;				// Oblivious DoH configuration length.
-	Boolean							noConnectionReuse;		// True if connection reuse is to be disabled.
-	Boolean							squashCNAMEs;			// True if CNAMEs should be squashed.
-	
-	// Variables for DNS service manager.
-	
-	mdns_dns_service_manager_t		manager;				// DNS service manager.
-	mdns_dns_service_t				service;				// DNS service for query.
-	mdns_dns_service_definition_t	definition;				// DNS service definition.
-	mdns_dns_service_id_t			registered_service_id;	// ID of DNS service registered with DNS service definition.
-	
-}	QuerierCmd;
-
-static OSStatus	_QuerierCmdCreate( QuerierCmd **outCmd );
-static void		_QuerierCmdRetain( QuerierCmd *inCmd );
-static void		_QuerierCmdRelease( QuerierCmd *inCmd );
-static OSStatus	_QuerierCmdRun( QuerierCmd *inCmd );
-
-static void	QuerierCommand( void )
-{
-	OSStatus			err;
-	QuerierCmd *		cmd = NULL;
-	size_t				i;
-	uint8_t				qname[ kDomainNameLengthMax ];
-	
-	err = _QuerierCmdCreate( &cmd );
-	require_noerr( err, exit );
-	
-	if( gInterface )
-	{
-		err = InterfaceIndexFromArgString( gInterface, &cmd->ifIndex );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		cmd->ifIndex = 0;
-	}
-	err = DomainNameFromString( qname, gQuerier_Name, NULL );
-	if( err )
-	{
-		FPrintF( stderr, "error: Invalid domain name: '%s'\n", gDNSQuery_Name );
-		goto exit;
-	}
-	err = DomainNameDup( qname, &cmd->qname, NULL );
-	require_noerr( err, exit );
-	
-	err = RecordTypeFromArgString( gQuerier_Type, &cmd->qtype );
-	require_noerr_quiet( err, exit );
-	
-	err = RecordClassFromArgString( gQuerier_Class, &cmd->qclass );
-	require_noerr( err, exit );
-	
-	if( gQuerier_Delegator )
-	{
-		err = StringToUUID( gQuerier_Delegator, kSizeCString, false, cmd->delegatorUUID );
-		if( !err )
-		{
-			cmd->haveDelegatorUUID = true;
-		}
-		else
-		{
-			cmd->delegatorPID = _StringToPID( gQuerier_Delegator, &err );
-			if( err )
-			{
-				FPrintF( stderr, "error: Invalid delegator PID or UUID: %s\n", gQuerier_Delegator );
-				err = kParamErr;
-				goto exit;
-			}
-			cmd->haveDelegatorPID = true;
-		}
-	}
-	if( gQuerier_ResolverType )
-	{
-		cmd->resolverType = (mdns_resolver_type_t) CLIArgToValue( "resolverType", gQuerier_ResolverType, &err,
-			kMDNSResolverTypeStr_Normal,	(int) mdns_resolver_type_normal,
-			kMDNSResolverTypeStr_TCPOnly,	(int) mdns_resolver_type_tcp,
-			kMDNSResolverTypeStr_TLS,		(int) mdns_resolver_type_tls,
-			kMDNSResolverTypeStr_HTTPS,		(int) mdns_resolver_type_https,
-			NULL );
-		require_noerr_quiet( err, exit );
-		
-		for( i = 0; i < gQuerier_ServerAddrCount; ++i )
-		{
-			const char * const		addrStr = gQuerier_ServerAddrs[ i ];
-			mdns_address_t			serverAddr;
-			
-			serverAddr = mdns_address_create_from_ip_address_string( addrStr );
-			if( !serverAddr )
-			{
-				FPrintF( stderr, "error: Failed to create address for '%s'\n", addrStr );
-				err = kParamErr;
-				goto exit;
-			}
-			CFArrayAppendValue( cmd->serverAddrs, serverAddr );
-			mdns_release( serverAddr );
-		}
-		if( gQuerier_ProviderName )
-		{
-			cmd->providerName = strdup( gQuerier_ProviderName );
-			require_action( cmd->providerName, exit, err = kNoMemoryErr );
-		}
-		if( gQuerier_ConnectionHostname )
-		{
-			cmd->connectionHostname = strdup( gQuerier_ConnectionHostname );
-			require_action( cmd->connectionHostname, exit, err = kNoMemoryErr );
-		}
-		if( gQuerier_URLPath )
-		{
-			cmd->urlPath = strdup( gQuerier_URLPath );
-			require_action( cmd->urlPath, exit, err = kNoMemoryErr );
-		}
-		if( gQuerier_IdentityReference )
-		{
-			err = HexToDataCopy( gQuerier_IdentityReference, kSizeCString, kHexToData_DefaultFlags, &cmd->identityRefPtr,
-				&cmd->identityRefLen, NULL );
-			require_noerr_action( err, exit, FPrintF( stderr,
-				"error: Failed to parse identity reference hex string: '%s'\n", gQuerier_IdentityReference ) );
-		}
-		if( gQuerier_ODoHConfig )
-		{
-			err = HexToDataCopy( gQuerier_ODoHConfig, kSizeCString, kHexToData_DefaultFlags, &cmd->odohCfgPtr,
-				&cmd->odohCfgLen, NULL );
-			require_noerr_action( err, exit, FPrintF( stderr,
-				"error: Failed to parse ODoH config hex string: '%s'\n", gQuerier_ODoHConfig ) );
-		}
-		cmd->noConnectionReuse	= gQuerier_NoConnectionReuse ? true : false;
-		cmd->squashCNAMEs		= gQuerier_SquashCNAMEs		 ? true : false;
-	}
-	else if ( ( gQuerier_ServerAddrCount > 0 ) || ( gQuerier_DomainCount > 0 ) )
-	{
-		cmd->definition = mdns_dns_service_definition_create();
-		require_action( cmd->definition, exit, err = kNoResourcesErr );
-		
-		if( cmd->ifIndex != 0 ) mdns_dns_service_definition_set_interface_index( cmd->definition, cmd->ifIndex, true );
-		for( i = 0; i < gQuerier_ServerAddrCount; ++i )
-		{
-			const char * const		addrStr = gQuerier_ServerAddrs[ i ];
-			mdns_address_t			serverAddr;
-			
-			serverAddr = mdns_address_create_from_ip_address_string( addrStr );
-			if( !serverAddr )
-			{
-				FPrintF( stderr, "error: Failed to create address for '%s'\n", addrStr );
-				err = kParamErr;
-				goto exit;
-			}
-			err = mdns_dns_service_definition_append_server_address( cmd->definition, serverAddr );
-			mdns_forget( &serverAddr );
-			require_noerr( err, exit );
-		}
-		for( i = 0; i < gQuerier_DomainCount; ++i )
-		{
-			const char * const		domainStr = gQuerier_Domains[ i ];
-			mdns_domain_name_t		domain;
-			
-			domain = mdns_domain_name_create( domainStr, mdns_domain_name_create_opts_none, &err );
-			if( !domain )
-			{
-				FPrintF( stderr, "error: Failed to create domain name for '%s': %#m\n", domainStr, err );
-				goto exit;
-			}
-			mdns_dns_service_definition_add_domain( cmd->definition, domain );
-			mdns_forget( &domain );
-		}
-	}
-	cmd->dnssecOK			= gQuerier_DNSSECOK			? true : false;
-	cmd->checkingDisabled	= gQuerier_CheckingDisabled	? true : false;
-	if( gQuerier_StartLeewayMs )
-	{
-		err = StringToInt32( gQuerier_StartLeewayMs, &cmd->startTimeLeewayMs );
-		require_noerr_action_quiet( err, exit, FPrintF( stderr,
-			"Invalid startLeeway value: '%s'\n", gQuerier_StartLeewayMs ) );
-
-		cmd->haveStartTimeLeeway = true;
-	}
-	err = _QuerierCmdRun( cmd );
-	require_noerr( err, exit );
-	
-exit:
-	if( cmd ) _QuerierCmdRelease( cmd );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-
-static OSStatus	_QuerierCmdCreate( QuerierCmd **outCmd )
-{
-	OSStatus			err;
-	QuerierCmd *		cmd;
-	
-	cmd = (QuerierCmd *) calloc( 1, sizeof( *cmd ) );
-	require_action( cmd, exit, err = kNoResourcesErr );
-	
-	cmd->refCount		= 1;
-	cmd->resolverType	= mdns_resolver_type_null;
-	
-	cmd->queue = dispatch_queue_create( "com.apple.dnssdutil.querier-command", DISPATCH_QUEUE_SERIAL );
-	require_action( cmd->queue, exit, err = kNoResourcesErr );
-	
-	cmd->doneSem = dispatch_semaphore_create( 0 );
-	require_action( cmd->doneSem, exit, err = kNoResourcesErr );
-	
-	cmd->serverAddrs = CFArrayCreateMutable( kCFAllocatorDefault, 0, &mdns_cfarray_callbacks );
-	require_action( cmd->serverAddrs, exit, err = kNoResourcesErr );
-	
-	*outCmd = cmd;
-	cmd = NULL;
-	err = kNoErr;
-	
-exit:
-	if( cmd ) _QuerierCmdRelease( cmd );
-	return( err );
-}
-
-//===========================================================================================================================
-
-static void	_QuerierCmdRetain( QuerierCmd *inCmd )
-{
-	atomic_add_32( &inCmd->refCount, 1 );
-}
-
-//===========================================================================================================================
-
-static void	_QuerierCmdRelease( QuerierCmd *inCmd )
-{
-	if( atomic_add_and_fetch_32( &inCmd->refCount, -1 ) == 0 )
-	{
-		check( !inCmd->sourceSigInt );
-		check( !inCmd->sourceSigTerm );
-		check( !inCmd->resolver );
-		check( !inCmd->manager );
-		check( !inCmd->service );
-		check( !inCmd->querier );
-		dispatch_forget( &inCmd->queue );
-		dispatch_forget( &inCmd->doneSem );
-		ForgetMem( &inCmd->qname );
-		ForgetCF( &inCmd->serverAddrs );
-		ForgetMem( &inCmd->providerName );
-		ForgetMem( &inCmd->connectionHostname );
-		ForgetMem( &inCmd->urlPath );
-		ForgetPtrLen( &inCmd->identityRefPtr, &inCmd->identityRefLen );
-		ForgetPtrLen( &inCmd->odohCfgPtr, &inCmd->odohCfgLen );
-		mdns_forget( &inCmd->definition );
-		free( inCmd );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_QuerierCmdStart( void *inCtx );
-static void	_QuerierCmdStop( QuerierCmd *inCmd, OSStatus inError );
-static void	_QuerierCmdSigIntHandler( void *inCtx );
-static void	_QuerierCmdSigTermHandler( void *inCtx );
-
-static OSStatus	_QuerierCmdRun( QuerierCmd *inCmd )
-{
-	dispatch_async_f( inCmd->queue, inCmd, _QuerierCmdStart );
-    dispatch_semaphore_wait( inCmd->doneSem, DISPATCH_TIME_FOREVER );
-	return( inCmd->error );
-}
-
-static void	_QuerierCmdStart( void *inCtx )
-{
-	OSStatus				err;
-	QuerierCmd * const		cmd		= (QuerierCmd *) inCtx;
-	dns_config_t *			config	= NULL;
-	const char *			ifNamePtr;
-	char					ifNameBuf[ IF_NAMESIZE + 1 ];
-	
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, cmd->queue, _QuerierCmdSigIntHandler, cmd, &cmd->sourceSigInt );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigInt );
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, cmd->queue, _QuerierCmdSigTermHandler, cmd, &cmd->sourceSigTerm );
-	require_noerr( err, exit );
-	dispatch_resume( cmd->sourceSigTerm );
-	
-	ifNamePtr = if_indextoname( cmd->ifIndex, ifNameBuf );
-	FPrintF( stdout, "Interface:            %u (%s)\n",		cmd->ifIndex, ifNamePtr ? ifNamePtr : "?" );
-	FPrintF( stdout, "Name:                 %{du:dname}\n",	cmd->qname );
-	FPrintF( stdout, "Type:                 %s (%u)\n",		RecordTypeToString( cmd->qtype ), cmd->qtype );
-	FPrintF( stdout, "Class:                %s (%u)\n",		RecordClassToString( cmd->qclass ), cmd->qclass );
-	if( cmd->haveStartTimeLeeway )
-	{
-		FPrintF( stdout, "Start leeway:         " );
-		if( cmd->startTimeLeewayMs >= 0 )	FPrintF( stdout, "%d ms\n", cmd->startTimeLeewayMs );
-		else								FPrintF( stdout, "∞ ms\n" );
-	}
-	if( cmd->definition || ( cmd->resolverType == mdns_resolver_type_null ) )
-	{
-		FPrintF( stdout, "Start time:           %{du:time}\n", NULL );
-		FPrintF( stdout, "---\n" );
-		
-		cmd->manager = mdns_dns_service_manager_create( cmd->queue, &err );
-		require_noerr( err, exit );
-		
-		_QuerierCmdRetain( cmd );
-		mdns_dns_service_manager_set_event_handler( cmd->manager,
-		^( mdns_event_t inEvent, OSStatus inError )
-		{
-			switch( inEvent )
-			{
-				case mdns_event_error:
-					if( !cmd->done )
-					{
-						FPrintF( stderr, "error: DNS service manager failed: %#m\n", inError );
-						_QuerierCmdStop( cmd, inError );
-					}
-					break;
-				
-				case mdns_event_invalidated:
-					_QuerierCmdRelease( cmd );
-					break;
-				
-				default:
-					break;
-			}
-		} );
-		if( cmd->definition )
-		{
-			cmd->registered_service_id = mdns_dns_service_manager_register_native_service( cmd->manager, cmd->definition,
-				&err );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			config = dns_configuration_copy();
-			require_action( config, exit, err = kUnknownErr );
-			
-			mdns_dns_service_manager_apply_dns_config( cmd->manager, config );
-		}
-		
-		if( cmd->definition )
-		{
-			if( cmd->ifIndex == 0 )
-			{
-				cmd->service = mdns_dns_service_manager_get_unscoped_native_service( cmd->manager, cmd->qname );
-			}
-			else
-			{
-				cmd->service = mdns_dns_service_manager_get_interface_scoped_native_service( cmd->manager, cmd->qname,
-					cmd->ifIndex );
-			}
-		}
-		else
-		{
-			if( cmd->ifIndex == 0 )
-			{
-				cmd->service = mdns_dns_service_manager_get_unscoped_system_service( cmd->manager, cmd->qname );
-			}
-			else
-			{
-				cmd->service = mdns_dns_service_manager_get_interface_scoped_system_service( cmd->manager, cmd->qname,
-					cmd->ifIndex );
-			}
-		}
-		if( !cmd->service )
-		{
-			FPrintF( stderr, "error: Failed to get DNS service for %{du:dname}\n", cmd->qname );
-			err = kNotFoundErr;
-			goto exit;
-		}
-		mdns_retain( cmd->service );
-		FPrintF( stdout, "Using DNS service -- %@\n\n", cmd->service );
-		
-		cmd->querier = mdns_dns_service_create_querier( cmd->service, &err );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		CFIndex		n, i;
-		
-		FPrintF( stdout, "Resolver Type:        %s\n", mdns_resolver_type_to_string( cmd->resolverType ) );
-		if( cmd->providerName )			FPrintF( stdout, "Provider Name:        %s\n", cmd->providerName );
-		if( cmd->connectionHostname )	FPrintF( stdout, "Connection Hostname:  %s\n", cmd->connectionHostname );
-		if( cmd->urlPath )				FPrintF( stdout, "URL path:             %s\n", cmd->urlPath );
-		if( cmd->identityRefPtr )
-		{
-			FPrintF( stdout, "Identity Reference:   %H\n", cmd->identityRefPtr, (int) cmd->identityRefLen, INT_MAX );
-		}
-		if( cmd->odohCfgPtr )
-		{
-			FPrintF( stdout, "ODoH Config:          %H\n", cmd->odohCfgPtr, (int) cmd->odohCfgLen, INT_MAX );
-		}
-		FPrintF( stdout, "Server(s):            " );
-		n = CFArrayGetCount( cmd->serverAddrs );
-		for( i = 0; i < n; ++i )
-		{
-			FPrintF( stdout, "%s%@", ( i == 0 ) ? "" : ", ", CFArrayGetValueAtIndex( cmd->serverAddrs, i ) );
-		}
-		FPrintF( stdout, "\n" );
-		FPrintF( stdout, "Start time:           %{du:time}\n", NULL );
-		FPrintF( stdout, "---\n" );
-		
-		cmd->resolver = mdns_resolver_create( cmd->resolverType, cmd->ifIndex, &err );
-		require_noerr( err, exit );
-		
-		if( cmd->providerName )
-		{
-			err = mdns_resolver_set_provider_name( cmd->resolver, cmd->providerName );
-			require_noerr( err, exit );
-		}
-		if( cmd->connectionHostname )
-		{
-			err = mdns_resolver_set_connection_hostname( cmd->resolver, cmd->connectionHostname );
-			require_noerr( err, exit );
-		}
-		if( cmd->urlPath )
-		{
-			err = mdns_resolver_set_url_path( cmd->resolver, cmd->urlPath );
-			require_noerr( err, exit );
-		}
-		if( cmd->identityRefPtr )
-		{
-			err = mdns_resolver_set_identity_reference( cmd->resolver, cmd->identityRefPtr, cmd->identityRefLen );
-			require_noerr( err, exit );
-		}
-		if( cmd->odohCfgPtr )
-		{
-			err = mdns_resolver_update_odoh_config( cmd->resolver, cmd->providerName, cmd->urlPath, cmd->odohCfgPtr,
-				cmd->odohCfgLen, NULL );
-			require_noerr( err, exit );
-		}
-		if( cmd->noConnectionReuse ) mdns_resolver_disable_connection_reuse( cmd->resolver, true );
-		if( cmd->squashCNAMEs ) mdns_resolver_set_squash_cnames( cmd->resolver, true );
-		for( i = 0; i < n; ++i )
-		{
-			const mdns_address_t		addr = (mdns_address_t) CFArrayGetValueAtIndex( cmd->serverAddrs, i );
-			
-			err = mdns_resolver_add_server_address( cmd->resolver, addr );
-			require_noerr( err, exit );
-		}
-		mdns_resolver_activate( cmd->resolver );
-		
-		cmd->querier = mdns_resolver_create_querier( cmd->resolver, &err );
-		require_noerr( err, exit );
-	}
-	err = mdns_querier_set_query( cmd->querier, cmd->qname, cmd->qtype, cmd->qclass );
-	require_noerr( err, exit );
-	
-	if( cmd->haveDelegatorPID )			mdns_querier_set_delegator_pid( cmd->querier, cmd->delegatorPID );
-	else if( cmd->haveDelegatorUUID )	mdns_querier_set_delegator_uuid( cmd->querier, cmd->delegatorUUID );
-	if( cmd->dnssecOK )					mdns_querier_set_dnssec_ok( cmd->querier, true );
-	if( cmd->checkingDisabled )			mdns_querier_set_checking_disabled( cmd->querier, true );
-	if( cmd->haveStartTimeLeeway )		mdns_querier_set_start_time_leeway( cmd->querier, cmd->startTimeLeewayMs );
-	
-	_QuerierCmdRetain( cmd );
-	mdns_querier_set_queue( cmd->querier, cmd->queue );
-	mdns_querier_set_result_handler( cmd->querier,
-	^ {
-		if( !cmd->done )
-		{
-			const mdns_querier_result_type_t		resultType = mdns_querier_get_result_type( cmd->querier );
-			
-			if( resultType == mdns_querier_result_type_response )
-			{
-				const uint8_t * const		msgPtr = mdns_querier_get_response_ptr( cmd->querier );
-				const size_t				msgLen = mdns_querier_get_response_length( cmd->querier );
-				
-				FPrintF( stdout, "Message size:     %zu bytes\n", msgLen );
-				FPrintF( stdout, "%{du:dnsmsg}\n", msgPtr, msgLen );
-				_QuerierCmdStop( cmd, kNoErr );
-			}
-			else
-			{
-				OSStatus		querierErr;
-				
-				if( resultType == mdns_querier_result_type_error )
-				{
-					querierErr = mdns_querier_get_error( cmd->querier );
-					if( !querierErr ) querierErr = kUnknownErr;
-				}
-				else
-				{
-					querierErr = kUnexpectedErr;
-				}
-				FPrintF( stderr, "error: Unexpected querier result: %s, error: %#m\n",
-					mdns_querier_result_type_to_string( resultType ), querierErr );
-				_QuerierCmdStop( cmd, querierErr );
-			}
-		}
-		_QuerierCmdRelease( cmd );
-	} );
-	mdns_querier_activate( cmd->querier );
-	
-exit:
-	if( config ) dns_configuration_free( config );
-	if( err ) _QuerierCmdStop( cmd, err );
-}
-
-//===========================================================================================================================
-
-#define mdns_dns_service_manager_forget( X )		ForgetCustomEx( X, mdns_dns_service_manager_invalidate, mdns_release )
-
-static void	_QuerierCmdStop( QuerierCmd *inCmd, OSStatus inError )
-{
-	if( !inCmd->done )
-	{
-		inCmd->done		= true;
-		inCmd->error	= inError;
-		dispatch_source_forget( &inCmd->sourceSigInt );
-		dispatch_source_forget( &inCmd->sourceSigTerm );
-		mdns_querier_forget( &inCmd->querier );
-		mdns_resolver_forget( &inCmd->resolver );
-		if( inCmd->manager && ( inCmd->registered_service_id != 0 ) )
-		{
-			mdns_dns_service_manager_deregister_native_service( inCmd->manager, inCmd->registered_service_id );
-		}
-		mdns_dns_service_manager_forget( &inCmd->manager );
-		mdns_forget( &inCmd->service );
-		mdns_forget( &inCmd->definition );
-		FPrintF( stdout, "---\n" );
-		FPrintF( stdout, "End time:       %{du:time}\n", NULL );
-		dispatch_semaphore_signal( inCmd->doneSem );
-	}
-}
-
-//===========================================================================================================================
-
-static void	_QuerierCmdSigIntHandler( void *inCtx )
-{
-	FPrintF( stdout, "*** Got SIGINIT signal ***\n" );
-	_QuerierCmdStop( (QuerierCmd *) inCtx, kCanceledErr );
-}
-
-//===========================================================================================================================
-
-static void	_QuerierCmdSigTermHandler( void *inCtx )
-{
-	FPrintF( stdout, "*** Got SIGTERM signal ***\n" );
-	_QuerierCmdStop( (QuerierCmd *) inCtx, kCanceledErr );
-}
-
-//===========================================================================================================================
-//	DNSProxyCmd
-//===========================================================================================================================
-
-static void	_DNSProxyCmdSignalHandler( void *inContext );
-
-static void	DNSProxyCmd( void )
-{
-	OSStatus						err;
-	size_t							i;
-	mrc_dns_proxy_parameters_t		params			= NULL;
-	mrc_dns_proxy_t					dnsProxy		= NULL;
-	dispatch_source_t				sigIntSource	= NULL;
-	dispatch_source_t				sigTermSource	= NULL;
-	__block const char *			separator;
-	uint32_t						outputIfIndex;
-	char							ifName[ kInterfaceNameBufLen ];
-	uint8_t							dns64Prefix[ 16 ];
-	int								dns64PrefixBitLen;
-	
-	params = mrc_dns_proxy_parameters_create( &err );
-	require_noerr( err, exit );
-	
-	for( i = 0; i < gDNSProxy_InputInterfaceCount; ++i )
-	{
-		uint32_t		ifIndex;
-		
-		err = InterfaceIndexFromArgString( gDNSProxy_InputInterfaces[ i ], &ifIndex );
-		require_noerr_quiet( err, exit );
-		
-		mrc_dns_proxy_parameters_add_input_interface( params, ifIndex );
-	}
-	
-	if( gDNSProxy_OutputInterface )
-	{
-		err = InterfaceIndexFromArgString( gDNSProxy_OutputInterface, &outputIfIndex );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		outputIfIndex = 0;
-	}
-	mrc_dns_proxy_parameters_set_output_interface( params, outputIfIndex );
-	
-	dns64PrefixBitLen = 0;
-	if( gDNSProxy_DNS64IPv6Prefix )
-	{
-		const char *		end;
-		
-		err = _StringToIPv6Address( gDNSProxy_DNS64IPv6Prefix,
-			kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoScope, dns64Prefix, NULL, NULL, &dns64PrefixBitLen,
-			&end );
-		if( !err && ( *end != '\0' ) ) err = kMalformedErr;
-		require_noerr_quiet( err, exit );
-		
-		mrc_dns_proxy_parameters_set_nat64_prefix( params, dns64Prefix, (size_t) dns64PrefixBitLen );
-	}
-	if( gDNSProxy_ForceAAAASynthesis ) mrc_dns_proxy_parameters_set_force_aaaa_synthesis( params, true );
-	FPrintF( stdout, "Input Interfaces:    " );
-	separator = "";
-	mrc_dns_proxy_parameters_enumerate_input_interfaces( params,
-	^ bool ( const uint32_t inIfIndex )
-	{
-		char		inputIfName[ kInterfaceNameBufLen ];
-		
-		FPrintF( stdout, "%s %u (%s)", separator, inIfIndex, InterfaceIndexToName( inIfIndex, inputIfName ) );
-		separator = ",";
-		return( true );
-	} );
-	FPrintF( stdout, "\n" );
-	FPrintF( stdout, "Output Interface:     %u (%s)\n",		outputIfIndex, InterfaceIndexToName( outputIfIndex, ifName ) );
-	if( gDNSProxy_DNS64IPv6Prefix ) FPrintF( stdout, "DNS64 prefix:         %.16a/%d\n", dns64Prefix, dns64PrefixBitLen );
-	FPrintF( stdout, "Force AAAA synthesis: %s\n", YesNoStr( mrc_dns_proxy_parameters_get_force_aaaa_synthesis( params ) ) );
-	FPrintF( stdout, "Start time:           %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	dnsProxy = mrc_dns_proxy_create( params, &err );
-	mrc_forget( &params );
-	require_noerr_quiet( err, exit );
-	
-	mrc_dns_proxy_set_queue( dnsProxy, dispatch_get_main_queue() );
-	mrc_dns_proxy_set_event_handler( dnsProxy,
-	^( const mrc_dns_proxy_event_t inEvent, const OSStatus inError )
-	{
-		switch( inEvent )
-		{
-			case mrc_dns_proxy_event_started:
-			{
-				FPrintF( stdout, "%{du:time}  DNS proxy was started\n", NULL );
-				break;
-			}
-			case mrc_dns_proxy_event_interruption:
-			{
-				FPrintF( stdout, "%{du:time}  DNS proxy was interrupted\n", NULL );
-				break;
-			}
-			case mrc_dns_proxy_event_invalidation:
-			{
-				struct timeval		now;
-				
-				gettimeofday( &now, NULL );
-				
-				mrc_release( dnsProxy );
-				
-				FPrintF( stdout, "---\n" );
-				FPrintF( stdout, "Error:    %#m\n", inError );
-				FPrintF( stdout, "End time: %{du:time}\n", &now );
-				exit( 0 );
-			}
-			case mrc_dns_proxy_event_none:
-				break;
-		}
-	} );
-	signal( SIGINT, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGINT, dispatch_get_main_queue(), _DNSProxyCmdSignalHandler, dnsProxy,
-		&sigIntSource );
-	require_noerr( err, exit );
-	dispatch_activate( sigIntSource );
-	
-	signal( SIGTERM, SIG_IGN );
-	err = DispatchSignalSourceCreate( SIGTERM, dispatch_get_main_queue(), _DNSProxyCmdSignalHandler, dnsProxy,
-		&sigTermSource );
-	require_noerr( err, exit );
-	dispatch_activate( sigTermSource );
-	
-	mrc_dns_proxy_activate( dnsProxy );
-	dispatch_main();
-	
-exit:
-	if( err ) ErrQuit( 1, "error: %#m\n", err );
-}
-
-static void	_DNSProxyCmdSignalHandler( void *inContext )
-{
-	mrc_dns_proxy_invalidate( (mrc_dns_proxy_t) inContext );
-}
-
-//===========================================================================================================================
-//	DNSProxyStateCmd
-//===========================================================================================================================
-
-static void	DNSProxyStateCmd( void )
-{
-	OSStatus							err;
-	dispatch_queue_t					queue;
-	dispatch_semaphore_t				doneSem	= NULL;
-	mrc_dns_proxy_state_inquiry_t		inquiry	= NULL;
-	
-	queue = dispatch_queue_create( "com.apple.dnssdutil.dns-proxy-state-command", DISPATCH_QUEUE_SERIAL );
-	require_action( queue, exit, err = kNoResourcesErr );
-	
-	doneSem = dispatch_semaphore_create( 0 );
-	require_action( doneSem, exit, err = kNoResourcesErr );
-	
-	inquiry = mrc_dns_proxy_state_inquiry_create();
-	require_action( inquiry, exit, err = kNoResourcesErr );
-	
-	mrc_dns_proxy_state_inquiry_set_queue( inquiry, queue );
-	mrc_dns_proxy_state_inquiry_set_handler( inquiry,
-	^( const char * const inState, const OSStatus inError )
-	{
-		if( inError ) FPrintF( stderr, "error: %#m\n", inError );
-		if( inState ) FPrintF( stdout, "%s\n", inState );
-		dispatch_semaphore_signal( doneSem );
-	} );
-	mrc_dns_proxy_state_inquiry_activate( inquiry );
-	
-	// Wait for the DNS proxy state inquiry to complete.
-	// Note: We intentionally use a semaphore that will be signalled by the asynchronous handler. The analyzer considers
-	// this an antipattern, which is OK for the purposes of this internal test tool. Actual well-written production code
-	// would usually not have to emulate this type of synchronous behavior.
-	
-#if( !COMPILER_CLANG_ANALYZER )
-    dispatch_semaphore_wait( doneSem, DISPATCH_TIME_FOREVER );
-#endif
-	err = kNoErr;
-	
-exit:
-	dispatch_forget( &queue );
-	dispatch_forget( &doneSem );
-	mrc_forget( &inquiry );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-//	GetAddrInfoNewCommand
-//===========================================================================================================================
-
-
-typedef enum
-{
-	kDelegationType_None		= 0,	// No delegation.
-	kDelegationType_PID			= 1,	// Delegation by PID.
-	kDelegationType_UUID		= 2,	// Delegation by UUID.
-	kDelegationType_AuditToken	= 3		// Delegation by audit token.
-	
-}	DelegationType;
-
-typedef struct
-{
-	DelegationType			type;		// Type of delegation.
-	union
-	{
-		pid_t				pid;		// Delegator's PID if type is kDelegationType_PID.
-		uuid_t				uuid;		// Delegator's UUID if type is kDelegationType_UUID.
-		audit_token_t		auditToken;	// Delegator's audit token if type is kDelegationType_AuditToken.
-		
-	}	ident;							// Delegator's identifier.
-	
-}	Delegation;
-
-typedef struct
-{
-	dispatch_queue_t		queue;					// Serial queue for command's events.
-	dispatch_group_t		group;					// GCD group to know when command is done.
-	dnssd_getaddrinfo_t		gai;					// dnssd_getaddrinfo object.
-	dispatch_source_t		timer;					// Timer to impose time limit on dnssd_getaddrinfo activity.
-	dispatch_source_t		sigint;					// Dispatch source for SIGINT.
-	dispatch_source_t		sigterm;				// Dispatch source for SIGTERM.
-	const char *			hostname;				// dnssd_getaddrinfo's hostname argument.
-	const char *			serviceScheme;			// dnssd_getaddrinfo's service scheme argument.
-	const char *			accountID;				// dnssd_getaddrinfo's account ID argument.
-	char *					stopReason;				// Reason for stopping the command.
-	uuid_t *				resolverUUID;			// UUID of libnetwork DNS resolver configuration to use.
-	Delegation				delegation;				// Specifies the type of delegation to use for dnssd_getaddrinfo, if any.
-	int32_t					refCount;				// Reference count.
-	DNSServiceFlags			flags;					// dnssd_getaddrinfo's flags argument.
-	DNSServiceProtocol		protocols;				// dnssd_getaddrinfo's protocols argument.
-	uint32_t				ifIndex;				// dnssd_getaddrinfo's interface index argument.
-	unsigned int			timeLimitSecs;			// Time limit in seconds for dnssd_getaddrinfo activity.
-	OSStatus				error;					// Command's error.
-	Boolean					needAuthTags;			// True if authentication tags are needed.
-	Boolean					showTracker;			// True if tracker hostname, if any, should be displayed.
-	Boolean					useFailover;			// True if DNS service failover should be used if necessary.
-	Boolean					prohibitEncryptedDNS;	// True if use of encrypted DNS protocols is prohibited.
-	Boolean					stopped;				// True if the command has been stopped.
-	Boolean					oneshot;				// True if the command should stop after first set of results.
-	Boolean					printedHeader;			// True if the results header has been printed.
-	
-}	GetAddrInfoNewCmd;
-
-static GetAddrInfoNewCmd *	_GetAddrInfoNewCmdCreateEx( qos_class_t inQoS, Boolean inUseQoS, OSStatus *outError );
-#define _GetAddrInfoNewCmdCreate( OUT_ERROR )						_GetAddrInfoNewCmdCreateEx( 0, false, OUT_ERROR )
-#define _GetAddrInfoNewCmdCreateWithQoS( IN_QOS, OUT_ERROR )		_GetAddrInfoNewCmdCreateEx( IN_QOS, true, OUT_ERROR )
-static OSStatus				_GetAddrInfoNewCmdRun( GetAddrInfoNewCmd *inCmd );
-static void					_GetAddrInfoNewCmdStopF( GetAddrInfoNewCmd *inCmd, const char *inFmt, ... );
-static GetAddrInfoNewCmd *	_GetAddrInfoNewCmdRetain( GetAddrInfoNewCmd *inCmd );
-static void					_GetAddrInfoNewCmdRelease( GetAddrInfoNewCmd *inCmd );
-
-#define _GetAddrInfoNewCmdForget( X )		ForgetCustom( X, _GetAddrInfoNewCmdRelease )
-
-static void	GetAddrInfoNewCommand( void )
-{
-	OSStatus				err;
-	GetAddrInfoNewCmd *		cmd = NULL;
-	
-	if( gGAINew_QoS )
-	{
-		qos_class_t		qos;
-		
-		qos = (qos_class_t) CLIArgToValue( kQoSArgShortName, gGAINew_QoS, &err,
-			kQoSTypeStr_Unspecified,		QOS_CLASS_UNSPECIFIED,
-			kQoSTypeStr_Background,			QOS_CLASS_BACKGROUND,
-			kQoSTypeStr_Utility,			QOS_CLASS_UTILITY,
-			kQoSTypeStr_Default,			QOS_CLASS_DEFAULT,
-			kQoSTypeStr_UserInitiated,		QOS_CLASS_USER_INITIATED,
-			kQoSTypeStr_UserInteractive,	QOS_CLASS_USER_INTERACTIVE,
-			NULL );
-		require_noerr_quiet( err, exit );
-		
-		cmd = _GetAddrInfoNewCmdCreateWithQoS( qos, &err );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		cmd = _GetAddrInfoNewCmdCreate( &err );
-		require_noerr( err, exit );
-	}
-	err = CheckIntegerArgument( gGAINew_TimeLimitSecs, "time limit", 0, INT_MAX );
-	require_noerr_quiet( err, exit );
-	
-	cmd->timeLimitSecs = (unsigned int) gGAINew_TimeLimitSecs;
-	
-	cmd->hostname				= gGAINew_Hostname;
-	cmd->flags					= GetDNSSDFlagsFromOpts();
-	cmd->serviceScheme			= gGAINew_ServiceScheme;
-	cmd->accountID				= gGAINew_AccountID;
-	cmd->needAuthTags			= gGAINew_WantAuthTags			? true : false;
-	cmd->showTracker			= gGAINew_ShowTracker			? true : false;
-	cmd->useFailover			= gGAINew_UseFailover			? true : false;
-	cmd->prohibitEncryptedDNS	= gGAINew_ProhibitEncryptedDNS	? true : false;
-	cmd->oneshot				= gGAINew_OneShot				? true : false;
-	
-	err = InterfaceIndexFromArgString( gInterface, &cmd->ifIndex );
-	require_noerr_quiet( err, exit );
-	
-	cmd->protocols = 0;
-	if( gGAINew_ProtocolIPv4 ) cmd->protocols |= kDNSServiceProtocol_IPv4;
-	if( gGAINew_ProtocolIPv6 ) cmd->protocols |= kDNSServiceProtocol_IPv6;
-	
-	// Get delegate ID.
-	
-	if( gGAINew_DelegatorID )
-	{
-		pid_t		delegatorPID;
-		
-		delegatorPID = _StringToPID( gGAINew_DelegatorID, &err );
-		if( !err )
-		{
-			if( delegatorPID >= 0 )
-			{
-				cmd->delegation.ident.pid	= delegatorPID;
-				cmd->delegation.type		= kDelegationType_PID;
-			}
-			else
-			{
-				delegatorPID = -delegatorPID;
-				if( audit_token_for_pid( delegatorPID, &cmd->delegation.ident.auditToken ) )
-				{
-					cmd->delegation.type = kDelegationType_AuditToken;
-				}
-				else
-				{
-					FPrintF( stderr, "Failed to get audit token for PID: %d\n", delegatorPID );
-					err = kParamErr;
-					goto exit;
-				}
-			}
-		}
-		else
-		{
-			err = uuid_parse( gGAINew_DelegatorID, cmd->delegation.ident.uuid );
-			if( !err )
-			{
-				cmd->delegation.type = kDelegationType_UUID;
-			}
-			else
-			{
-				FPrintF( stderr, "Invalid delegate ID (PID or UUID): %s\n", gGAINew_DelegatorID );
-				err = kParamErr;
-				goto exit;
-			}
-		}
-	}
-	if( gGAINew_ResolverUUID )
-	{
-		uuid_t		uuid;
-		
-		err = uuid_parse( gGAINew_ResolverUUID, uuid );
-		if( err )
-		{
-			FPrintF( stderr, "Invalid resolver UUID: %s\n", gGAINew_ResolverUUID );
-			err = kParamErr;
-			goto exit;
-		}
-		cmd->resolverUUID = (uuid_t *) _memdup( uuid, sizeof( uuid ) );
-		require_action( cmd->resolverUUID, exit, err = kNoMemoryErr );
-	}
-	err = _GetAddrInfoNewCmdRun( cmd );
-	require_noerr( err, exit );
-	
-exit:
-	_GetAddrInfoNewCmdForget( &cmd );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-
-static GetAddrInfoNewCmd *	_GetAddrInfoNewCmdCreateEx( qos_class_t inQoS, Boolean inUseQoS, OSStatus *outError )
-{
-	OSStatus				err;
-	GetAddrInfoNewCmd *		obj;
-	GetAddrInfoNewCmd *		cmd = NULL;
-	
-	obj = (GetAddrInfoNewCmd *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount = 1;
-	if( inUseQoS )
-	{
-		dispatch_queue_attr_t		attr;
-		
-		attr = dispatch_queue_attr_make_with_qos_class( DISPATCH_QUEUE_SERIAL, inQoS, 0 );
-		obj->queue = dispatch_queue_create( "com.apple.dnssdutil.getaddrinfo-new-command", attr );
-		require_action( obj->queue, exit, err = kNoResourcesErr );
-	}
-	else
-	{
-		obj->queue = dispatch_queue_create( "com.apple.dnssdutil.getaddrinfo-new-command", DISPATCH_QUEUE_SERIAL );
-		require_action( obj->queue, exit, err = kNoResourcesErr );
-	}
-	obj->group = dispatch_group_create();
-	require_action( obj->group, exit, err = kNoResourcesErr );
-	
-	cmd = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( outError ) *outError = err;
-	_GetAddrInfoNewCmdForget( &obj );
-	return( cmd );
-}
-
-//===========================================================================================================================
-
-static void	_GetAddrInfoNewCmdStart( void *inCtx );
-
-static OSStatus	_GetAddrInfoNewCmdRun( GetAddrInfoNewCmd *me )
-{
-	dispatch_group_enter( me->group );
-	dispatch_async_f( me->queue, me, _GetAddrInfoNewCmdStart );
-    dispatch_group_wait( me->group, DISPATCH_TIME_FOREVER );
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:   %{du:time}\n", NULL );
-	if( me->stopReason ) FPrintF( stdout, "End reason: %s\n", me->stopReason );
-	return( me->error );
-}
-
-static void	_GetAddrInfoNewCmdStart( void *inCtx )
-{
-	OSStatus						err;
-	GetAddrInfoNewCmd * const		me = (GetAddrInfoNewCmd *) inCtx;
-	char							ifName[ kInterfaceNameBufLen ];
-	
-	me->gai = dnssd_getaddrinfo_create();
-	require_action( me->gai, exit, err = kNoResourcesErr );
-	
-	dnssd_getaddrinfo_set_hostname( me->gai, me->hostname );
-	dnssd_getaddrinfo_set_flags( me->gai, me->flags );
-	dnssd_getaddrinfo_set_interface_index( me->gai, me->ifIndex );
-	dnssd_getaddrinfo_set_protocols( me->gai, me->protocols );
-	dnssd_getaddrinfo_set_need_authenticated_results( me->gai, me->needAuthTags ? true : false );
-	dnssd_getaddrinfo_set_use_failover( me->gai, me->useFailover );
-	if( __builtin_available( macOS 13.0, iOS 16.1, watchOS 9.1, tvOS 16.1, * ) )
-	{
-		dnssd_getaddrinfo_prohibit_encrypted_dns( me->gai, me->prohibitEncryptedDNS );
-	}
-	else
-	{
-		FPrintF( stderr, "dnssd_getaddrinfo_prohibit_encrypted_dns is not available on this OS." );
-		err = kUnsupportedErr;
-		goto exit;
-	}
-	switch( me->delegation.type )
-	{
-		case kDelegationType_PID:
-			dnssd_getaddrinfo_set_delegate_pid( me->gai, me->delegation.ident.pid );
-			break;
-		
-		case kDelegationType_UUID:
-			dnssd_getaddrinfo_set_delegate_uuid( me->gai, me->delegation.ident.uuid );
-			break;
-		
-		case kDelegationType_AuditToken:
-			dnssd_getaddrinfo_set_delegate_audit_token( me->gai, me->delegation.ident.auditToken );
-			break;
-		
-		case kDelegationType_None:
-		default:
-			break;
-	}
-	if( me->serviceScheme )
-	{
-		dnssd_getaddrinfo_set_service_scheme( me->gai, me->serviceScheme );
-	}
-	if( me->accountID )
-	{
-		dnssd_getaddrinfo_set_account_id( me->gai, me->accountID );
-	}
-	if( me->resolverUUID )
-	{
-		dnssd_getaddrinfo_add_resolver_uuid( me->gai, *me->resolverUUID );
-	}
-	dnssd_getaddrinfo_set_queue( me->gai, me->queue );
-	dnssd_getaddrinfo_set_result_handler( me->gai,
-	^( dnssd_getaddrinfo_result_t *inResultArray, size_t inResultCount )
-	{
-		size_t		i;
-		
-		require_return( me->gai );
-		require_return( inResultCount > 0 );
-		
-		for( i = 0; i < inResultCount; ++i )
-		{
-			const dnssd_getaddrinfo_result_t			result	= inResultArray[ i ];
-			const dnssd_getaddrinfo_result_type_t		type	= dnssd_getaddrinfo_result_get_type( result );
-			const char *								typeStr;
-			const char *								cacheStr;
-			
-			if( !me->printedHeader )
-			{
-				FPrintF( stdout, "%-26s  Type C? IF %-30s Address\n", "Timestamp", "Hostname" );
-				me->printedHeader = true;
-			}
-			switch( type )
-			{
-				case dnssd_getaddrinfo_result_type_add:				typeStr = "Add"; break;
-				case dnssd_getaddrinfo_result_type_remove:			typeStr = "Rmv"; break;
-				case dnssd_getaddrinfo_result_type_no_address:		typeStr = "NoA"; break;
-				case dnssd_getaddrinfo_result_type_expired:			typeStr = "Exp"; break;
-				case dnssd_getaddrinfo_result_type_service_binding:	typeStr = "SvB"; break;
-				default:											typeStr = "???"; break;
-			}
-			if( type == dnssd_getaddrinfo_result_type_remove )
-			{
-				cacheStr = "-";
-			}
-			else
-			{
-				cacheStr = dnssd_getaddrinfo_result_is_from_cache( result ) ? "Y" : "N";
-			}
-			FPrintF( stdout, "%{du:time}  %-4s %-2s %2d %-30s %##a",
-				NULL, typeStr, cacheStr, dnssd_getaddrinfo_result_get_interface_index( result ),
-				dnssd_getaddrinfo_result_get_hostname( result ), dnssd_getaddrinfo_result_get_address( result ) );
-			if( type == dnssd_getaddrinfo_result_type_no_address )
-			{
-				FPrintF( stdout, " (%s)",
-					dnssd_negative_reason_to_string( dnssd_getaddrinfo_result_get_negative_reason( result ) ) );
-			}
-			FPrintF( stdout, "\n" );
-			if( me->flags & kDNSServiceFlagsReturnIntermediates )
-			{
-				const dnssd_cname_array_t		cnames = dnssd_getaddrinfo_result_get_cnames( result );
-				size_t							j, n;
-				
-				FPrintF( stdout, "    Canonical Names: [" );
-				n = dnssd_cname_array_get_count( cnames );
-				for( j = 0; j < n; ++j )
-				{
-					FPrintF( stdout, "%s%s", ( j == 0 ) ? "" : ", ", dnssd_cname_array_get_cname( cnames, j ) );
-				}
-				FPrintF( stdout, "]\n" );
-			}
-			if( me->showTracker && ( type != dnssd_getaddrinfo_result_type_remove ) )
-			{
-				const char * const		tracker = dnssd_getaddrinfo_result_get_tracker_hostname( result );
-				
-				if( tracker )
-				{
-					const char * const		owner = dnssd_getaddrinfo_result_get_tracker_owner( result );
-					
-					FPrintF( stdout, "    Tracker: %s", tracker );
-					if( owner ) FPrintF( stdout, ", Owner: %s", owner );
-					FPrintF( stdout, "\n" );
-				}
-				else
-				{
-					FPrintF( stdout, "    (Not a known tracker)\n" );
-				}
-			}
-			if( me->needAuthTags )
-			{
-				if( ( type == dnssd_getaddrinfo_result_type_add ) || ( type == dnssd_getaddrinfo_result_type_expired ) )
-				{
-					const void *		tagPtr;
-					size_t				tagLen;
-					
-					tagPtr = dnssd_getaddrinfo_result_get_authentication_tag( result, &tagLen );
-					FPrintF( stdout, "    Auth Tag: " );
-					if( tagPtr )	FPrintF( stdout, "%.4H (%zu bytes)\n", tagPtr, (int) tagLen, (int) tagLen, tagLen );
-					else			FPrintF( stdout, "<NO AUTH TAG!>\n" );
-				}
-			}
-		}
-		if( me->oneshot ) _GetAddrInfoNewCmdStopF( me, "one-shot done" );
-	} );
-	_GetAddrInfoNewCmdRetain( me );
-	dispatch_group_enter( me->group );
-	dnssd_getaddrinfo_set_event_handler( me->gai,
-	^( dnssd_event_t inEvent, DNSServiceErrorType inError )
-	{
-		switch( inEvent )
-		{
-			case dnssd_event_invalidated:
-				dispatch_group_leave( me->group );
-				_GetAddrInfoNewCmdRelease( me );
-				break;
-			
-			case dnssd_event_error:
-				if( !me->error ) me->error = inError;
-				_GetAddrInfoNewCmdStopF( me, "error %#m", inError );
-				break;
-			
-			default:
-				break;
-		}
-	} );
-	
-	// Set up signal handlers.
-	
-	signal( SIGINT, SIG_IGN );
-	me->sigint = dispatch_source_create( DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t) SIGINT, 0, me->queue );
-	require_action( me->sigint, exit, err = kNoResourcesErr );
-	
-	dispatch_source_set_event_handler( me->sigint, ^{ _GetAddrInfoNewCmdStopF( me, "interrupt signal" ); } );
-	dispatch_activate( me->sigint );
-	
-	signal( SIGTERM, SIG_IGN );
-	me->sigterm = dispatch_source_create( DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t) SIGTERM, 0, me->queue );
-	require_action( me->sigterm, exit, err = kNoResourcesErr );
-	
-	dispatch_source_set_event_handler( me->sigterm, ^{ _GetAddrInfoNewCmdStopF( me, "termination signal" ); } );
-	dispatch_activate( me->sigterm );
-	
-	// Start getaddrinfo operation.
-	
-	InterfaceIndexToName( me->ifIndex, ifName );
-	FPrintF( stdout, "Service Scheme: %s\n", me->serviceScheme );
-	FPrintF( stdout, "Flags:          %#{flags}\n",	me->flags, kDNSServiceFlagsDescriptors );
-	FPrintF( stdout, "Interface:      %d (%s)\n",	(int32_t) me->ifIndex, ifName );
-	FPrintF( stdout, "Protocols:      %#{flags}\n",	me->protocols, kDNSServiceProtocolDescriptors );
-	FPrintF( stdout, "Name:           %s\n",		me->hostname );
-	FPrintF( stdout, "Mode:           %s\n",		me->oneshot ? "one-shot" : "continuous" );
-	if( me->serviceScheme )	FPrintF( stdout, "Service Scheme: %s\n", me->serviceScheme );
-	if( me->accountID )		FPrintF( stdout, "Account ID:     %s\n", me->accountID );
-	FPrintF( stdout, "Time limit:     " );
-	if( me->timeLimitSecs > 0 )	FPrintF( stdout, "%d second%?c\n", me->timeLimitSecs, me->timeLimitSecs != 1, 's' );
-	else						FPrintF( stdout, "∞\n" );
-	FPrintF( stdout, "Start time: %{du:time}\n",	NULL );
-	FPrintF( stdout, "---\n" );
-	
-	if( me->timeLimitSecs > 0 )
-	{
-		me->timer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, me->queue );
-		require_action( me->timer, exit, err = kNoResourcesErr );
-		
-		dispatch_source_set_timer( me->timer, dispatch_time_seconds( me->timeLimitSecs ), DISPATCH_TIME_FOREVER,
-			me->timeLimitSecs * ( UINT64_C_safe( kNanosecondsPerSecond ) / 20 ) );
-		dispatch_source_set_event_handler( me->timer, ^{ _GetAddrInfoNewCmdStopF( me, "time limit" ); } );
-		dispatch_activate( me->timer );
-	}
-	dnssd_getaddrinfo_activate( me->gai );
-	err = kNoErr;
-	
-exit:
-	if( err ) _GetAddrInfoNewCmdStopF( me, "error %#m", err );
-}
-
-//===========================================================================================================================
-
-static void	_GetAddrInfoNewCmdStopF( GetAddrInfoNewCmd *me, const char *inFmt, ... )
-{
-	if( !me->stopped )
-	{
-		me->stopped = true;
-		dnssd_getaddrinfo_forget( &me->gai );
-		dispatch_source_forget( &me->timer );
-		dispatch_source_forget( &me->sigint );
-		dispatch_source_forget( &me->sigterm );
-		if( inFmt )
-		{
-			va_list		args;
-			
-			check( !me->stopReason );
-			va_start( args, inFmt );
-			VASPrintF( &me->stopReason, inFmt, args );
-			va_end( args );
-			check( me->stopReason );
-		}
-		dispatch_group_leave( me->group );
-	}
-}
-
-//===========================================================================================================================
-
-static GetAddrInfoNewCmd *	_GetAddrInfoNewCmdRetain( GetAddrInfoNewCmd *me )
-{
-	atomic_add_32( &me->refCount, 1 );
-	return( me );
-}
-
-//===========================================================================================================================
-
-static void	_GetAddrInfoNewCmdRelease( GetAddrInfoNewCmd *me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		check( !me->gai );
-		check( !me->timer );
-		check( !me->sigint );
-		check( !me->sigterm );
-		dispatch_forget( &me->queue );
-		dispatch_forget( &me->group );
-		ForgetMem( &me->stopReason );
-		ForgetMem( &me->resolverUUID );
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-//	TCPInfoCommand
-//===========================================================================================================================
-
-static void	TCPInfoCommand( void )
-{
-	OSStatus			err;
-	sockaddr_ip			local, remote;
-	struct tcp_info		ti;
-	
-	err = SockAddrFromArgString( gTCPInfo_LocalAddrStr, "local IP address", &local );
-	require_noerr_return( err );
-	
-	err = SockAddrFromArgString( gTCPInfo_RemoteAddrStr, "remote IP address", &remote );
-	require_noerr_return( err );
-	cli_require_return( local.sa.sa_family == remote.sa.sa_family, "error: IP address version mismatch.\n" );
-	
-	FPrintF( stdout, "Local Address:  %##a\n", &local.sa );
-	FPrintF( stdout, "Remote Address: %##a\n", &remote.sa );
-	FPrintF( stdout, "Start time:     %{du:time}\n", NULL );
-	FPrintF( stdout, "---\n" );
-	
-	if( local.sa.sa_family == AF_INET )
-	{
-		err = mdns_tcpinfo_get_ipv4( ntohl( local.v4.sin_addr.s_addr ), ntohs( local.v4.sin_port ),
-			ntohl( remote.v4.sin_addr.s_addr ), ntohs( remote.v4.sin_port ), &ti );
-		cli_require_noerr_return( err, "error: mdns_tcpinfo_get_ipv4: %#m\n", err );
-	}
-	else
-	{
-		err = mdns_tcpinfo_get_ipv6( local.v6.sin6_addr.s6_addr, ntohs( local.v6.sin6_port ),
-			remote.v6.sin6_addr.s6_addr, ntohs( remote.v6.sin6_port ), &ti );
-		cli_require_noerr_return( err, "error: mdns_tcpinfo_get_ipv6: %#m\n", err );
-	}
-#define _TCPInfoPrint( INFO, FIELD )		FPrintF( stdout, "%-28s%llu\n", # FIELD, (unsigned long long)( (INFO)->FIELD ) )
-	_TCPInfoPrint( &ti, tcpi_state );
-	_TCPInfoPrint( &ti, tcpi_options );
-	_TCPInfoPrint( &ti, tcpi_snd_wscale );
-	_TCPInfoPrint( &ti, tcpi_rcv_wscale );
-	_TCPInfoPrint( &ti, tcpi_flags );
-	_TCPInfoPrint( &ti, tcpi_rto );
-	_TCPInfoPrint( &ti, tcpi_snd_mss );
-	_TCPInfoPrint( &ti, tcpi_rcv_mss );
-	_TCPInfoPrint( &ti, tcpi_rttcur );
-	_TCPInfoPrint( &ti, tcpi_srtt );
-	_TCPInfoPrint( &ti, tcpi_rttvar );
-	_TCPInfoPrint( &ti, tcpi_rttbest );
-	_TCPInfoPrint( &ti, tcpi_snd_ssthresh );
-	_TCPInfoPrint( &ti, tcpi_snd_cwnd );
-	_TCPInfoPrint( &ti, tcpi_rcv_space );
-	_TCPInfoPrint( &ti, tcpi_snd_wnd );
-	_TCPInfoPrint( &ti, tcpi_snd_nxt );
-	_TCPInfoPrint( &ti, tcpi_rcv_nxt );
-	_TCPInfoPrint( &ti, tcpi_last_outif );
-	_TCPInfoPrint( &ti, tcpi_snd_sbbytes );
-	_TCPInfoPrint( &ti, tcpi_txpackets );
-	_TCPInfoPrint( &ti, tcpi_txbytes );
-	_TCPInfoPrint( &ti, tcpi_txretransmitbytes );
-	_TCPInfoPrint( &ti, tcpi_txunacked );
-	_TCPInfoPrint( &ti, tcpi_rxpackets );
-	_TCPInfoPrint( &ti, tcpi_rxbytes );
-	_TCPInfoPrint( &ti, tcpi_rxduplicatebytes );
-	_TCPInfoPrint( &ti, tcpi_rxoutoforderbytes );
-	_TCPInfoPrint( &ti, tcpi_snd_bw );
-	_TCPInfoPrint( &ti, tcpi_synrexmits );
-	_TCPInfoPrint( &ti, tcpi_unused1 );
-	_TCPInfoPrint( &ti, tcpi_unused2 );
-	_TCPInfoPrint( &ti, tcpi_cell_rxpackets );
-	_TCPInfoPrint( &ti, tcpi_cell_rxbytes );
-	_TCPInfoPrint( &ti, tcpi_cell_txpackets );
-	_TCPInfoPrint( &ti, tcpi_cell_txbytes );
-	_TCPInfoPrint( &ti, tcpi_wifi_rxpackets );
-	_TCPInfoPrint( &ti, tcpi_wifi_rxbytes );
-	_TCPInfoPrint( &ti, tcpi_wifi_txpackets );
-	_TCPInfoPrint( &ti, tcpi_wifi_txbytes );
-	_TCPInfoPrint( &ti, tcpi_wired_rxpackets );
-	_TCPInfoPrint( &ti, tcpi_wired_rxbytes );
-	_TCPInfoPrint( &ti, tcpi_wired_txpackets );
-	_TCPInfoPrint( &ti, tcpi_wired_txbytes );
-	FPrintF( stdout, "tcpi_connstatus = {\n" );
-	FPrintF( stdout, "    probe_activated         %u\n", ti.tcpi_connstatus.probe_activated );
-	FPrintF( stdout, "    write_probe_failed      %u\n", ti.tcpi_connstatus.write_probe_failed );
-	FPrintF( stdout, "    read_probe_failed       %u\n", ti.tcpi_connstatus.read_probe_failed );
-	FPrintF( stdout, "    conn_probe_failed       %u\n", ti.tcpi_connstatus.conn_probe_failed );
-	FPrintF( stdout, "}\n" );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_req );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_rcv );
-	_TCPInfoPrint( &ti, tcpi_tfo_syn_loss );
-	_TCPInfoPrint( &ti, tcpi_tfo_syn_data_sent );
-	_TCPInfoPrint( &ti, tcpi_tfo_syn_data_acked );
-	_TCPInfoPrint( &ti, tcpi_tfo_syn_data_rcv );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_req_rcv );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_sent );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_invalid );
-	_TCPInfoPrint( &ti, tcpi_tfo_cookie_wrong );
-	_TCPInfoPrint( &ti, tcpi_tfo_no_cookie_rcv );
-	_TCPInfoPrint( &ti, tcpi_tfo_heuristics_disable );
-	_TCPInfoPrint( &ti, tcpi_tfo_send_blackhole );
-	_TCPInfoPrint( &ti, tcpi_tfo_recv_blackhole );
-	_TCPInfoPrint( &ti, tcpi_tfo_onebyte_proxy );
-	_TCPInfoPrint( &ti, tcpi_ecn_client_setup );
-	_TCPInfoPrint( &ti, tcpi_ecn_server_setup );
-	_TCPInfoPrint( &ti, tcpi_ecn_success );
-	_TCPInfoPrint( &ti, tcpi_ecn_lost_syn );
-	_TCPInfoPrint( &ti, tcpi_ecn_lost_synack );
-	_TCPInfoPrint( &ti, tcpi_local_peer );
-	_TCPInfoPrint( &ti, tcpi_if_cell );
-	_TCPInfoPrint( &ti, tcpi_if_wifi );
-	_TCPInfoPrint( &ti, tcpi_if_wired );
-	_TCPInfoPrint( &ti, tcpi_if_wifi_infra );
-	_TCPInfoPrint( &ti, tcpi_if_wifi_awdl );
-	_TCPInfoPrint( &ti, tcpi_snd_background );
-	_TCPInfoPrint( &ti, tcpi_rcv_background );
-	_TCPInfoPrint( &ti, tcpi_ecn_recv_ce );
-	_TCPInfoPrint( &ti, tcpi_ecn_recv_cwr );
-	_TCPInfoPrint( &ti, tcpi_rcvoopack );
-	_TCPInfoPrint( &ti, tcpi_pawsdrop );
-	_TCPInfoPrint( &ti, tcpi_sack_recovery_episode );
-	_TCPInfoPrint( &ti, tcpi_reordered_pkts );
-	_TCPInfoPrint( &ti, tcpi_dsack_sent );
-	_TCPInfoPrint( &ti, tcpi_dsack_recvd );
-	_TCPInfoPrint( &ti, tcpi_flowhash );
-	_TCPInfoPrint( &ti, tcpi_txretransmitpackets );
-#undef _TCPInfoPrint
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:       %{du:time}\n", NULL );
-}
-
-//===========================================================================================================================
-//    XCTestCmd
-//===========================================================================================================================
-
-static void    XCTestCmd( void )
-{
-    int result = 0;
-    setenv(DNSSDUTIL_XCTEST, DNSSDUTIL_XCTEST, 0);
-    if(!run_xctest_named(gXCTest_Classname)) {
-        result = 1;
-    }
-    unsetenv(DNSSDUTIL_XCTEST);
-    exit( result );
-}
-
-//===========================================================================================================================
-//    MultiConnectTestCmd
-//===========================================================================================================================
-
-static void    MultiConnectTestCmd( void )
-{
-    int result = 0;
-	dispatch_group_t group = dispatch_group_create();
-	int count = gMultiConnectTest_ConnectionCount;
-	DNSServiceRef *	refs = calloc( (uint32_t)count, sizeof(DNSServiceRef) );
-
-	// Create count connections on async queue
-	// rdar://problem/59861422
-	__block int goodcount = 0;
-	for ( int i = 0; i < count; i++ ) {
-		char label[256];
-		sprintf( label, "multi-connect queue %d", i+1 );
-		dispatch_group_async( group, dispatch_queue_create( label, DISPATCH_QUEUE_SERIAL ), ^{
-			DNSServiceErrorType err = DNSServiceCreateConnection( &refs[i] );
-			if ( err ) {
-				fprintf( stderr, "%s Failed to create connection # %d err(%d)\n", __FUNCTION__, i, err );
-            } else {
-                goodcount++;
-            }
-		});
-	}
-	dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
-	dispatch_release( group );
-	fprintf( stderr, "%s Created %d connections of %d\n", __FUNCTION__, goodcount, count );
-
-	// Free them
-	goodcount = 0;
-	for ( int i = 0; i < count; i++ ) {
-		if ( refs[i] ) {
-			DNSServiceRefDeallocate( refs[i] );
-			goodcount++;
-		}
-	}
-	fprintf( stderr, "%s Stopped %d connections of %d\n", __FUNCTION__, goodcount, count );
-	result = (goodcount == count) ? 0 : 1;
-    exit( result );
-}
-
-#endif	// MDNSRESPONDER_PROJECT
-
-//===========================================================================================================================
-//	ThreadPFNAT64Command
-//===========================================================================================================================
-
-static void	ThreadPFNAT64Command( void )
-{
-	OSStatus					err;
-	const char *				endPtr;
-	StringToIPAddressFlags		flags;
-	uint32_t					ipv4Addr;
-	int							prefixLen;
-	uint8_t						prefixAddr[ 16 ];
-	
-	FPrintF( stdout, "Setting Thread border router NAT64 PF rules with IPv6 prefix '%s' and IPv4 address '%s'\n",
-		gThreadPFNAT64_IPv6Prefix, gThreadPFNAT64_IPv4Address );
-	
-	flags = kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoScope;
-	err = _StringToIPv6Address( gThreadPFNAT64_IPv6Prefix, flags, prefixAddr, NULL, NULL, &prefixLen, NULL );
-	cli_require_noerr_return( err, "Invalid IPv6 prefix: \"%s\".\n", gThreadPFNAT64_IPv6Prefix );
-	
-	flags = kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoPrefix;
-	err = _StringToIPv4Address( gThreadPFNAT64_IPv4Address, flags, &ipv4Addr, NULL, NULL, NULL, &endPtr );
-	cli_require_return( !err && ( *endPtr == '\0' ), "Invalid IPv4 address: \"%s\".\n", gThreadPFNAT64_IPv4Address );
-	
-	err = mdns_pf_set_thread_nat64_rules( prefixAddr, prefixLen, htonl( ipv4Addr ) );
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	ThreadPFDeleteCommand
-//===========================================================================================================================
-
-static void	ThreadPFDeleteCommand( void )
-{
-	OSStatus		err;
-	
-	FPrintF( stdout, "Deleting Thread border router PF rules.\n" );
-	err = mdns_pf_delete_thread_rules();
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	IPv4FwdEnableCommand
-//===========================================================================================================================
-
-static void	IPv4FwdEnableCommand( void )
-{
-	OSStatus		err;
-	
-	FPrintF( stdout, "Enabling IPv4 forwarding.\n" );
-	err = mdns_system_set_ipv4_forwarding( true );
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	IPv4FwdDisableCommand
-//===========================================================================================================================
-
-static void	IPv4FwdDisableCommand( void )
-{
-	OSStatus		err;
-	
-	FPrintF( stdout, "Disabling IPv4 forwarding.\n" );
-	err = mdns_system_set_ipv4_forwarding( false );
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	IPv6FwdEnableCommand
-//===========================================================================================================================
-
-static void	IPv6FwdEnableCommand( void )
-{
-	OSStatus		err;
-	
-	FPrintF( stdout, "Enabling IPv6 forwarding.\n" );
-	err = mdns_system_set_ipv6_forwarding( true );
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	IPv6FwdDisableCommand
-//===========================================================================================================================
-
-static void	IPv6FwdDisableCommand( void )
-{
-	OSStatus		err;
-	
-	FPrintF( stdout, "Disabling IPv6 forwarding.\n" );
-	err = mdns_system_set_ipv6_forwarding( false );
-	cli_require_noerr_return( err, "error: %#m\n", err );
-}
-
-//===========================================================================================================================
-//	PrintCommand
-//===========================================================================================================================
-
-static void	PrintCommand( void )
-{
-	OSStatus			err;
-	const char *		inputPath;
-	uint8_t *			msgPtr = NULL;
-	size_t				msgLen;
-	char *				msgStr = NULL;
-	
-	inputPath = CLINextArgOrNULL();
-	if( !inputPath || ( strcmp( inputPath, "-" ) == 0 ) )
-	{
-		err = CopyFileDataByFile( stdin, (char **) &msgPtr, &msgLen );
-		require_noerr_action_quiet( err, exit, FPrintF( stderr,
-			"error: Failed to copy DNS message from stdin: %#m\n", err ) );
-	}
-	else
-	{
-		err = CopyFileDataByPath( inputPath, (char **) &msgPtr, &msgLen );
-		require_noerr_action_quiet( err, exit, FPrintF( stderr,
-			"error: Failed to copy DNS message from '%s': %#m\n", inputPath, err ) );
-	}
-	require_action_quiet( msgLen <= UINT16_MAX, exit, err = kSizeErr; FPrintF( stderr,
-		"error: DNS message size is greater than the supported maximum (%zu > %d bytes)\n", msgLen, UINT16_MAX ) );
-	
-	err = DNSMessageToString( msgPtr, msgLen, kDNSMessageToStringFlag_Null, &msgStr );
-	if( !err )
-	{
-		FPrintF( stdout, "%s\n", msgStr );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Failed to pretty print DNS message: %#m\n", err );
-		FPrintF( stdout, "%.1H\n", msgPtr, (int) msgLen, (int) msgLen );
-		err = kNoErr;
-	}
-	
-exit:
-	ForgetMem( &msgPtr );
-	ForgetMem( &msgStr );
-	gExitCode = err ? 1 : 0;
-}
-
-//===========================================================================================================================
-//	DaemonVersionCmd
-//===========================================================================================================================
-
-static void	DaemonVersionCmd( void )
-{
-	OSStatus		err;
-	uint32_t		size, version;
-	char			strBuf[ 16 ];
-	
-	size = (uint32_t) sizeof( version );
-	err = DNSServiceGetProperty( kDNSServiceProperty_DaemonVersion, &version, &size );
-	require_noerr( err, exit );
-	
-	FPrintF( stdout, "Daemon version: %s\n", _DNSSDSourceVersionToCString( version, strBuf, sizeof( strBuf ) ) );
-	
-exit:
-	if( err ) exit( 1 );
-}
-
-//===========================================================================================================================
-//	Exit
-//===========================================================================================================================
-
-static void	Exit( void *inContext )
-{
-	const char * const		reason = (const char *) inContext;
-	
-	FPrintF( stdout, "---\n" );
-	FPrintF( stdout, "End time:   %{du:time}\n", NULL );
-	if( reason ) FPrintF( stdout, "End reason: %s\n", reason );
-	exit( gExitCode );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_Timestamp
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_Timestamp(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	struct timeval				now;
-	const struct timeval *		tv;
-	struct tm *					localTime;
-	size_t						len;
-	int							n;
-	char						dateTimeStr[ 32 ];
-	
-	Unused( inUserContext );
-	
-	tv = va_arg( inArgs->args, const struct timeval * );
-	require_action_quiet( !inFormat->suppress, exit, n = 0 );
-	
-	if( !tv )
-	{
-		gettimeofday( &now, NULL );
-		tv = &now;
-	}
-	localTime = localtime( &tv->tv_sec );
-	len = strftime( dateTimeStr, sizeof( dateTimeStr ), "%Y-%m-%d %H:%M:%S", localTime );
-	if( len == 0 ) dateTimeStr[ 0 ] = '\0';
-	
-	n = PrintFCore( inContext, "%s.%06u", dateTimeStr, (unsigned int) tv->tv_usec );
-	
-exit:
-	return( n );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_DNSMessage
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_DNSMessageCommon(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext,
-		Boolean			inRawRData );
-
-static int
-	_PrintFExtensionHandler_DNSMessage(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	return( _PrintFExtensionHandler_DNSMessageCommon( inContext, inFormat, inArgs, inUserContext, false ) );
-}
-
-static int
-	_PrintFExtensionHandler_DNSMessageCommon(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext,
-		Boolean			inRawRData )
-{
-	OSStatus					err;
-	const void *				msgPtr;
-	size_t						msgLen;
-	char *						msgStr;
-	DNSMessageToStringFlags		flags;
-	int							n;
-	
-	Unused( inUserContext );
-	
-	msgPtr = va_arg( inArgs->args, const void * );
-	msgLen = va_arg( inArgs->args, size_t );
-	require_action_quiet( !inFormat->suppress, exit, n = 0 );
-	
-	flags = kDNSMessageToStringFlags_None;
-	if( inRawRData )				flags |= kDNSMessageToStringFlag_RawRData;
-	if( inFormat->altForm   == 1 )	flags |= kDNSMessageToStringFlag_MDNS;
-	if( inFormat->precision == 1 )	flags |= kDNSMessageToStringFlag_OneLine;
-	err = DNSMessageToString( msgPtr, msgLen, flags, &msgStr );
-	if( !err )
-	{
-		n = PrintFCore( inContext, "%*{text}", inFormat->fieldWidth, msgStr, kSizeCString );
-		free( msgStr );
-	}
-	else
-	{
-		n = PrintFCore( inContext, "%*.1H", inFormat->fieldWidth, msgPtr, (int) msgLen, (int) msgLen );
-	}
-	
-exit:
-	return( n );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_RawDNSMessage
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_RawDNSMessage(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	return( _PrintFExtensionHandler_DNSMessageCommon( inContext, inFormat, inArgs, inUserContext, true ) );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_CallbackFlags
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_CallbackFlags(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	DNSServiceFlags		flags;
-	int					n;
-	char				dnssecResult;
-	
-	Unused( inUserContext );
-	
-	flags = va_arg( inArgs->args, DNSServiceFlags );
-	require_action_quiet( !inFormat->suppress, exit, n = 0 );
-	
-	if(      ( flags & kDNSServiceFlagsValidate ) == 0 )						dnssecResult = ' ';
-	else if( ( flags & kDNSServiceFlagsSecure )   == kDNSServiceFlagsSecure )	dnssecResult = 'S';
-	else if( ( flags & kDNSServiceFlagsInsecure ) == kDNSServiceFlagsInsecure )	dnssecResult = 'I';
-	else																		dnssecResult = 'E';
-	n = PrintFCore( inContext, "%08X %s%c %c%c%c",
-		flags, DNSServiceFlagsToAddRmvStr( flags ),
-		( flags & kDNSServiceFlagsMoreComing )       ? '+' : ' ',
-		( flags & kDNSServiceFlagAnsweredFromCache ) ? 'C' : ' ',
-		( flags & kDNSServiceFlagsExpiredAnswer )    ? '*' : ' ',
-		dnssecResult );
-	
-exit:
-	return( n );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_DNSRecordData
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_DNSRecordData(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	const void *		rdataPtr;
-	int					recordType, n, fieldWidth;
-	unsigned int		rdataLen;
-	
-	Unused( inUserContext );
-	
-	recordType	= va_arg( inArgs->args, int );
-	rdataPtr	= va_arg( inArgs->args, const void * );
-	rdataLen	= va_arg( inArgs->args, unsigned int );
-	require_action_quiet( !inFormat->suppress, exit, n = 0 );
-	
-	check( inFormat->fieldWidth < INT_MAX );
-	fieldWidth = inFormat->leftJustify ? -( (int) inFormat->fieldWidth ) : ( (int) inFormat->fieldWidth );
-	
-	if( rdataLen > 0 )
-	{
-		char *		rdataStr = NULL;
-		
-		DNSRecordDataToString( rdataPtr, rdataLen, recordType, &rdataStr );
-		if( rdataStr )
-		{
-			n = PrintFCore( inContext, "%*s", fieldWidth, rdataStr );
-			free( rdataStr );
-		}
-		else
-		{
-			n = PrintFCore( inContext, "%*H", fieldWidth, rdataPtr, rdataLen, rdataLen );
-		}
-	}
-	else
-	{
-		n = PrintFCore( inContext, "%*s", fieldWidth, "<< ZERO-LENGTH RDATA >>" );
-	}
-	
-exit:
-	return( n );
-}
-
-//===========================================================================================================================
-//	_PrintFExtensionHandler_DomainName
-//===========================================================================================================================
-
-static int
-	_PrintFExtensionHandler_DomainName(
-		PrintFContext *	inContext,
-		PrintFFormat *	inFormat,
-		PrintFVAList *	inArgs,
-		void *			inUserContext )
-{
-	OSStatus			err;
-	const uint8_t *		namePtr;
-	int					n, fieldWidth;
-	char				nameStr[ kDNSServiceMaxDomainName ];
-	
-	Unused( inUserContext );
-	
-	namePtr = va_arg( inArgs->args, const uint8_t * );
-	require_action_quiet( !inFormat->suppress, exit, n = 0 );
-	
-	check( inFormat->fieldWidth < INT_MAX );
-	fieldWidth = inFormat->leftJustify ? -( (int) inFormat->fieldWidth ) : ( (int) inFormat->fieldWidth );
-	
-	err = DomainNameToString( namePtr, NULL, nameStr, NULL );
-	check_noerr( err );
-	if( !err )
-	{
-		n = PrintFCore( inContext, "%*s", fieldWidth, nameStr );
-	}
-	else
-	{
-		n = PrintFCore( inContext, "%*s", fieldWidth, "<< ERROR: domain name conversion failed >>" );
-	}
-	
-exit:
-	return( n );
-}
-
-
-//===========================================================================================================================
-//	GetDNSSDFlagsFromOpts
-//===========================================================================================================================
-
-static DNSServiceFlags	GetDNSSDFlagsFromOpts( void )
-{
-	DNSServiceFlags		flags;
-	
-	flags = (DNSServiceFlags) gDNSSDFlags;
-	if( flags & kDNSServiceFlagsShareConnection )
-	{
-		FPrintF( stderr, "*** Warning: kDNSServiceFlagsShareConnection (0x%X) is explicitly set in flag parameters.\n",
-			kDNSServiceFlagsShareConnection );
-	}
-	
-	if( gDNSSDFlag_AllowExpiredAnswers )	flags |= kDNSServiceFlagsAllowExpiredAnswers;
-	if( gDNSSDFlag_BrowseDomains )			flags |= kDNSServiceFlagsBrowseDomains;
-	if( gDNSSDFlag_DenyCellular )			flags |= kDNSServiceFlagsDenyCellular;
-	if( gDNSSDFlag_DenyConstrained )		flags |= kDNSServiceFlagsDenyConstrained;
-	if( gDNSSDFlag_DenyExpensive )			flags |= kDNSServiceFlagsDenyExpensive;
-	if( gDNSSDFlag_ForceMulticast )			flags |= kDNSServiceFlagsForceMulticast;
-	if( gDNSSDFlag_IncludeAWDL )			flags |= kDNSServiceFlagsIncludeAWDL;
-	if( gDNSSDFlag_KnownUnique )			flags |= kDNSServiceFlagsKnownUnique;
-	if( gDNSSDFlag_NoAutoRename )			flags |= kDNSServiceFlagsNoAutoRename;
-	if( gDNSSDFlag_PathEvaluationDone )		flags |= kDNSServiceFlagsPathEvaluationDone;
-	if( gDNSSDFlag_RegistrationDomains )	flags |= kDNSServiceFlagsRegistrationDomains;
-	if( gDNSSDFlag_ReturnIntermediates )	flags |= kDNSServiceFlagsReturnIntermediates;
-	if( gDNSSDFlag_Shared )					flags |= kDNSServiceFlagsShared;
-	if( gDNSSDFlag_SuppressUnusable )		flags |= kDNSServiceFlagsSuppressUnusable;
-	if( gDNSSDFlag_Timeout )				flags |= kDNSServiceFlagsTimeout;
-	if( gDNSSDFlag_UnicastResponse )		flags |= kDNSServiceFlagsUnicastResponse;
-	if( gDNSSDFlag_Unique )					flags |= kDNSServiceFlagsUnique;
-	if( gDNSSDFlag_WakeOnResolve )			flags |= kDNSServiceFlagsWakeOnResolve;
-	if( gDNSSDFlag_EnableDNSSEC )			flags |= kDNSServiceFlagsEnableDNSSEC;
-	
-	return( flags );
-}
-
-//===========================================================================================================================
-//	CreateConnectionFromArgString
-//===========================================================================================================================
-
-static OSStatus
-	CreateConnectionFromArgString(
-		const char *			inString,
-		dispatch_queue_t		inQueue,
-		DNSServiceRef *			outSDRef,
-		ConnectionDesc *		outDesc )
-{
-	OSStatus			err;
-	DNSServiceRef		sdRef = NULL;
-	ConnectionType		type;
-	int32_t				pid = -1;	// Initializing because the analyzer claims pid may be used uninitialized.
-	uint8_t				uuid[ 16 ];
-	
-	if( strcasecmp( inString, kConnectionArg_Normal ) == 0 )
-	{
-		err = DNSServiceCreateConnection( &sdRef );
-		require_noerr( err, exit );
-		type = kConnectionType_Normal;
-	}
-	else if( stricmp_prefix( inString, kConnectionArgPrefix_PID ) == 0 )
-	{
-		const char * const		pidStr = inString + sizeof_string( kConnectionArgPrefix_PID );
-		
-		err = StringToInt32( pidStr, &pid );
-		if( err )
-		{
-			FPrintF( stderr, "Invalid delegate connection PID value: %s\n", pidStr );
-			err = kParamErr;
-			goto exit;
-		}
-		
-		memset( uuid, 0, sizeof( uuid ) );
-		err = DNSServiceCreateDelegateConnection( &sdRef, pid, uuid );
-		if( err )
-		{
-			FPrintF( stderr, "DNSServiceCreateDelegateConnection() returned %#m for PID %d\n", err, pid );
-			goto exit;
-		}
-		type = kConnectionType_DelegatePID;
-	}
-	else if( stricmp_prefix( inString, kConnectionArgPrefix_UUID ) == 0 )
-	{
-		const char * const		uuidStr = inString + sizeof_string( kConnectionArgPrefix_UUID );
-		
-		check_compile_time_code( sizeof( uuid ) == sizeof( uuid_t ) );
-		
-		err = StringToUUID( uuidStr, kSizeCString, false, uuid );
-		if( err )
-		{
-			FPrintF( stderr, "Invalid delegate connection UUID value: %s\n", uuidStr );
-			err = kParamErr;
-			goto exit;
-		}
-		
-		err = DNSServiceCreateDelegateConnection( &sdRef, 0, uuid );
-		if( err )
-		{
-			FPrintF( stderr, "DNSServiceCreateDelegateConnection() returned %#m for UUID %#U\n", err, uuid );
-			goto exit;
-		}
-		type = kConnectionType_DelegateUUID;
-	}
-	else
-	{
-		FPrintF( stderr, "Unrecognized connection string \"%s\".\n", inString );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	err = DNSServiceSetDispatchQueue( sdRef, inQueue );
-	require_noerr( err, exit );
-	
-	*outSDRef = sdRef;
-	if( outDesc )
-	{
-		outDesc->type = type;
-		if(      type == kConnectionType_DelegatePID )	outDesc->delegate.pid = pid;
-		else if( type == kConnectionType_DelegateUUID )	memcpy( outDesc->delegate.uuid, uuid, 16 );
-	}
-	sdRef = NULL;
-	
-exit:
-	if( sdRef ) DNSServiceRefDeallocate( sdRef );
-	return( err );
-}
-
-//===========================================================================================================================
-//	InterfaceIndexFromArgString
-//===========================================================================================================================
-
-static OSStatus	InterfaceIndexFromArgString( const char *inString, uint32_t *outIndex )
-{
-	OSStatus		err;
-	uint32_t		ifIndex;
-	
-	if( inString )
-	{
-		ifIndex = if_nametoindex( inString );
-		if( ifIndex == 0 )
-		{
-			err = StringToUInt32( inString, &ifIndex );
-			if( err )
-			{
-				FPrintF( stderr, "error: Invalid interface value: %s\n", inString );
-				err = kParamErr;
-				goto exit;
-			}
-		}
-	}
-	else
-	{
-		ifIndex	= 0;
-	}
-	
-	*outIndex = ifIndex;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	RecordDataFromArgString
-//===========================================================================================================================
-
-static OSStatus	RecordDataFromArgString( const char *inString, uint8_t **outDataPtr, size_t *outDataLen )
-{
-	OSStatus		err;
-	uint8_t *		dataPtr = NULL;
-	size_t			dataLen;
-	
-	if( 0 ) {}
-	
-	// Domain name
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_Domain ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_Domain );
-		
-		err = StringToDomainName( str, &dataPtr, &dataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// File path
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_File ) == 0 )
-	{
-		const char * const		path = inString + sizeof_string( kRDataArgPrefix_File );
-		
-		err = CopyFileDataByPath( path, (char **) &dataPtr, &dataLen );
-		require_noerr( err, exit );
-		require_action( dataLen <= kDNSRecordDataLengthMax, exit, err = kSizeErr );
-	}
-	
-	// Hexadecimal string
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_HexString ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_HexString );
-		
-		err = HexToDataCopy( str, kSizeCString, kHexToData_DefaultFlags, &dataPtr, &dataLen, NULL );
-		require_noerr( err, exit );
-		require_action( dataLen <= kDNSRecordDataLengthMax, exit, err = kSizeErr );
-	}
-	
-	// IPv4 address string
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_IPv4 ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_IPv4 );
-		
-		err = StringToARecordData( str, &dataPtr, &dataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// IPv6 address string
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_IPv6 ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_IPv6 );
-		
-		err = StringToAAAARecordData( str, &dataPtr, &dataLen );
-		require_noerr_quiet( err, exit );
-	}
-	
-	// SRV record
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_SRV ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_SRV );
-		
-		err = CreateSRVRecordDataFromString( str, &dataPtr, &dataLen );
-		require_noerr( err, exit );
-	}
-	
-	// String with escaped hex and octal bytes
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_String ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_String );
-		const char * const		end = str + strlen( str );
-		size_t					copiedLen;
-		size_t					totalLen;
-		Boolean					success;
-		
-		if( str < end )
-		{
-			success = _ParseQuotedEscapedString( str, end, "", NULL, 0, NULL, &totalLen, NULL );
-			require_action( success, exit, err = kParamErr );
-			require_action( totalLen <= kDNSRecordDataLengthMax, exit, err = kSizeErr );
-			
-			dataLen = totalLen;
-			dataPtr = (uint8_t *) malloc( dataLen );
-			require_action( dataPtr, exit, err = kNoMemoryErr );
-			
-			success = _ParseQuotedEscapedString( str, end, "", (char *) dataPtr, dataLen, &copiedLen, NULL, NULL );
-			require_action( success, exit, err = kParamErr );
-			check( copiedLen == dataLen );
-		}
-		else
-		{
-			dataPtr = NULL;
-			dataLen = 0;
-		}
-	}
-	
-	// TXT record
-	
-	else if( stricmp_prefix( inString, kRDataArgPrefix_TXT ) == 0 )
-	{
-		const char * const		str = inString + sizeof_string( kRDataArgPrefix_TXT );
-		
-		err = CreateTXTRecordDataFromString( str, ',', &dataPtr, &dataLen );
-		require_noerr( err, exit );
-	}
-	
-	// Unrecognized format
-	
-	else
-	{
-		FPrintF( stderr, "Unrecognized record data string \"%s\".\n", inString );
-		err = kParamErr;
-		goto exit;
-	}
-	
-	err = kNoErr;
-	*outDataLen = dataLen;
-	*outDataPtr = dataPtr;
-	dataPtr = NULL;
-	
-exit:
-	FreeNullSafe( dataPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	RecordTypeFromArgString
-//===========================================================================================================================
-
-static OSStatus	RecordTypeFromArgString( const char *inString, uint16_t *outValue )
-{
-	OSStatus		err;
-	uint16_t		value;
-	
-	value = DNSRecordTypeStringToValue( inString );
-	if( value == 0 )
-	{
-		int32_t		i32;
-		
-		err = StringToInt32( inString, &i32 );
-		require_noerr_quiet( err, exit );
-		require_action_quiet( ( i32 >= 0 ) && ( i32 <= UINT16_MAX ), exit, err = kParamErr );
-		value = (uint16_t) i32;
-	}
-	*outValue = value;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	RecordClassFromArgString
-//===========================================================================================================================
-
-static OSStatus	RecordClassFromArgString( const char *inString, uint16_t *outValue )
-{
-	OSStatus		err;
-	int32_t			i32;
-	
-	if( strcasecmp( inString, "IN" ) == 0 )
-	{
-		*outValue = kDNSServiceClass_IN;
-		err = kNoErr;
-		goto exit;
-	}
-	
-	err = StringToInt32( inString, &i32 );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( ( i32 >= 0 ) && ( i32 <= UINT16_MAX ), exit, err = kParamErr );
-	
-	*outValue = (uint16_t) i32;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	SockAddrFromArgString
-//===========================================================================================================================
-
-static OSStatus	SockAddrFromArgString( const char *inArgStr, const char *inArgName, sockaddr_ip *outSA )
-{
-	OSStatus		err;
-	sockaddr_ip		sip;
-	
-	err = StringToSockAddr( inArgStr, &sip, sizeof( sip ), NULL );
-	if( !err && ( ( sip.sa.sa_family == AF_INET ) || ( sip.sa.sa_family == AF_INET6 ) ) )
-	{
-		if( outSA ) SockAddrCopy( &sip, outSA );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Invalid %s: '%s'\n", inArgName, inArgStr );
-		err = kParamErr;
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	InterfaceIndexToName
-//===========================================================================================================================
-
-static char * InterfaceIndexToName( uint32_t inIfIndex, char inNameBuf[ kInterfaceNameBufLen ] )
-{
-	switch( inIfIndex )
-	{
-		case kDNSServiceInterfaceIndexAny:
-			strlcpy( inNameBuf, "Any", kInterfaceNameBufLen );
-			break;
-		
-		case kDNSServiceInterfaceIndexLocalOnly:
-			strlcpy( inNameBuf, "LocalOnly", kInterfaceNameBufLen );
-			break;
-		
-		case kDNSServiceInterfaceIndexUnicast:
-			strlcpy( inNameBuf, "Unicast", kInterfaceNameBufLen );
-			break;
-		
-		case kDNSServiceInterfaceIndexP2P:
-			strlcpy( inNameBuf, "P2P", kInterfaceNameBufLen );
-			break;
-		
-	#if( defined( kDNSServiceInterfaceIndexBLE ) )
-		case kDNSServiceInterfaceIndexBLE:
-			strlcpy( inNameBuf, "BLE", kInterfaceNameBufLen );
-			break;
-	#endif
-		
-		default:
-		{
-			const char *		name;
-			
-			name = if_indextoname( inIfIndex, inNameBuf );
-			if( !name ) strlcpy( inNameBuf, "NO NAME", kInterfaceNameBufLen );
-			break;
-		}
-	}
-	
-	return( inNameBuf );
-}
-
-//===========================================================================================================================
-//	RecordTypeToString
-//===========================================================================================================================
-
-static const char *	RecordTypeToString( int inValue )
-{
-	const char *		string;
-	
-	string = DNSRecordTypeValueToString( inValue );
-	if( !string ) string = "???";
-	return( string );
-}
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	RecordClassToString
-//===========================================================================================================================
-
-static const char *	RecordClassToString( int inValue )
-{
-	return( ( inValue == kDNSServiceClass_IN ) ? "IN" : "???" );
-}
-#endif
-
-//===========================================================================================================================
-//	WriteDNSQueryMessage
-//===========================================================================================================================
-
-static OSStatus
-	WriteDNSQueryMessage(
-		uint8_t			inMsg[ kDNSQueryMessageMaxLen ],
-		uint16_t		inMsgID,
-		uint16_t		inFlags,
-		const char *	inQName,
-		uint16_t		inQType,
-		uint16_t		inQClass,
-		size_t *		outMsgLen )
-{
-	OSStatus		err;
-	uint8_t			qname[ kDomainNameLengthMax ];
-	
-	err = DomainNameFromString( qname, inQName, NULL );
-	require_noerr_quiet( err, exit );
-	
-	err = DNSMessageWriteQuery( inMsgID, inFlags, qname, inQType, inQClass, inMsg, outMsgLen );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DispatchSignalSourceCreate
-//===========================================================================================================================
-
-static OSStatus
-	DispatchSignalSourceCreate(
-		int					inSignal,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		void *				inContext,
-		dispatch_source_t *	outSource )
-{
-	OSStatus				err;
-	dispatch_source_t		source;
-	
-	source = dispatch_source_create( DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t) inSignal, 0, inQueue );
-	require_action( source, exit, err = kUnknownErr );
-	
-	dispatch_set_context( source, inContext );
-	dispatch_source_set_event_handler_f( source, inEventHandler );
-	
-	*outSource = source;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DispatchSocketSourceCreate
-//===========================================================================================================================
-
-static OSStatus
-	DispatchSocketSourceCreate(
-		SocketRef				inSock,
-		dispatch_source_type_t	inType,
-		dispatch_queue_t		inQueue,
-		DispatchHandler			inEventHandler,
-		DispatchHandler			inCancelHandler,
-		void *					inContext,
-		dispatch_source_t *		outSource )
-{
-	OSStatus				err;
-	dispatch_source_t		source;
-	
-	source = dispatch_source_create( inType, (uintptr_t) inSock, 0, inQueue ? inQueue : dispatch_get_main_queue() );
-	require_action( source, exit, err = kNoResourcesErr );
-	
-	dispatch_set_context( source, inContext );
-	dispatch_source_set_event_handler_f( source, inEventHandler );
-	dispatch_source_set_cancel_handler_f( source, inCancelHandler );
-	
-	*outSource = source;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	DispatchTimerCreate
-//===========================================================================================================================
-
-static OSStatus
-	DispatchTimerCreate(
-		dispatch_time_t		inStart,
-		uint64_t			inIntervalNs,
-		uint64_t			inLeewayNs,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		DispatchHandler		inCancelHandler,
-		void *				inContext,
-		dispatch_source_t *	outTimer )
-{
-	OSStatus				err;
-	dispatch_source_t		timer;
-	
-	timer = dispatch_source_create( DISPATCH_SOURCE_TYPE_TIMER, 0, 0, inQueue ? inQueue : dispatch_get_main_queue() );
-	require_action( timer, exit, err = kNoResourcesErr );
-	
-	dispatch_source_set_timer( timer, inStart, inIntervalNs, inLeewayNs );
-	dispatch_set_context( timer, inContext );
-	dispatch_source_set_event_handler_f( timer, inEventHandler );
-	dispatch_source_set_cancel_handler_f( timer, inCancelHandler );
-	
-	*outTimer = timer;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	DispatchProcessMonitorCreate
-//===========================================================================================================================
-
-static OSStatus
-	DispatchProcessMonitorCreate(
-		pid_t				inPID,
-		unsigned long		inFlags,
-		dispatch_queue_t	inQueue,
-		DispatchHandler		inEventHandler,
-		DispatchHandler		inCancelHandler,
-		void *				inContext,
-		dispatch_source_t *	outMonitor )
-{
-	OSStatus				err;
-	dispatch_source_t		monitor;
-	
-	monitor = dispatch_source_create( DISPATCH_SOURCE_TYPE_PROC, (uintptr_t) inPID, inFlags,
-		inQueue ? inQueue : dispatch_get_main_queue() );
-	require_action( monitor, exit, err = kUnknownErr );
-	
-	dispatch_set_context( monitor, inContext );
-	dispatch_source_set_event_handler_f( monitor, inEventHandler );
-	dispatch_source_set_cancel_handler_f( monitor, inCancelHandler );
-	
-	*outMonitor = monitor;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-#endif
-
-//===========================================================================================================================
-//	ServiceTypeDescription
-//===========================================================================================================================
-
-typedef struct
-{
-	const char *		name;			// Name of the service type in two-label "_service._proto" format.
-	const char *		description;	// Description of the service type.
-	
-}	ServiceType;
-
-// A Non-comprehensive table of DNS-SD service types
-
-static const ServiceType		kServiceTypes[] =
-{
-	{ "_acp-sync._tcp",			"AirPort Base Station Sync" },
-	{ "_adisk._tcp",			"Automatic Disk Discovery" },
-	{ "_afpovertcp._tcp",		"Apple File Sharing" },
-	{ "_airdrop._tcp",			"AirDrop" },
-	{ "_airplay._tcp",			"AirPlay" },
-	{ "_airport._tcp",			"AirPort Base Station" },
-	{ "_daap._tcp",				"Digital Audio Access Protocol (iTunes)" },
-	{ "_eppc._tcp",				"Remote AppleEvents" },
-	{ "_ftp._tcp",				"File Transfer Protocol" },
-	{ "_home-sharing._tcp",		"Home Sharing" },
-	{ "_homekit._tcp",			"HomeKit" },
-	{ "_http._tcp",				"World Wide Web HTML-over-HTTP" },
-	{ "_https._tcp",			"HTTP over SSL/TLS" },
-	{ "_ipp._tcp",				"Internet Printing Protocol" },
-	{ "_ldap._tcp",				"Lightweight Directory Access Protocol" },
-	{ "_mediaremotetv._tcp",	"Media Remote" },
-	{ "_net-assistant._tcp",	"Apple Remote Desktop" },
-	{ "_od-master._tcp",		"OpenDirectory Master" },
-	{ "_nfs._tcp",				"Network File System" },
-	{ "_presence._tcp",			"Peer-to-peer messaging / Link-Local Messaging" },
-	{ "_pdl-datastream._tcp",	"Printer Page Description Language Data Stream" },
-	{ "_raop._tcp",				"Remote Audio Output Protocol" },
-	{ "_rfb._tcp",				"Remote Frame Buffer" },
-	{ "_scanner._tcp",			"Bonjour Scanning" },
-	{ "_smb._tcp",				"Server Message Block over TCP/IP" },
-	{ "_sftp-ssh._tcp",			"Secure File Transfer Protocol over SSH" },
-	{ "_sleep-proxy._udp",		"Sleep Proxy Server" },
-	{ "_ssh._tcp",				"SSH Remote Login Protocol" },
-	{ "_teleport._tcp",			"teleport" },
-	{ "_tftp._tcp",				"Trivial File Transfer Protocol" },
-	{ "_workstation._tcp",		"Workgroup Manager" },
-	{ "_webdav._tcp",			"World Wide Web Distributed Authoring and Versioning (WebDAV)" },
-	{ "_webdavs._tcp",			"WebDAV over SSL/TLS" }
-};
-
-static const char *	ServiceTypeDescription( const char *inName )
-{
-	const ServiceType *				serviceType;
-	const ServiceType * const		end = kServiceTypes + countof( kServiceTypes );
-	
-	for( serviceType = kServiceTypes; serviceType < end; ++serviceType )
-	{
-		if( ( stricmp_prefix( inName, serviceType->name ) == 0 ) )
-		{
-			const char * const		ptr = &inName[ strlen( serviceType->name ) ];
-			
-			if( ( ptr[ 0 ] == '\0' ) || ( ( ptr[ 0 ] == '.' ) && ( ptr[ 1 ] == '\0' ) ) )
-			{
-				return( serviceType->description );
-			}
-		}
-	}
-	return( NULL );
-}
-
-//===========================================================================================================================
-//	SocketContextCreate
-//===========================================================================================================================
-
-static SocketContext *	SocketContextCreate( SocketRef inSock, void *inUserContext, OSStatus *outError )
-{
-	return( SocketContextCreateEx( inSock, inUserContext, NULL, outError ) );
-}
-
-//===========================================================================================================================
-//	SocketContextCreateEx
-//===========================================================================================================================
-
-static SocketContext *
-	SocketContextCreateEx(
-		SocketRef					inSock,
-		void *						inUserContext,
-		SocketContextFinalizer_f	inUserFinalizer,
-		OSStatus *					outError )
-{
-	OSStatus			err;
-	SocketContext *		context;
-	
-	context = (SocketContext *) calloc( 1, sizeof( *context ) );
-	require_action( context, exit, err = kNoMemoryErr );
-	
-	context->refCount		= 1;
-	context->sock			= inSock;
-	context->userContext	= inUserContext;
-	context->userFinalizer	= inUserFinalizer;
-	err = kNoErr;
-	
-exit:
-	if( outError ) *outError = err;
-	return( context );
-}
-
-//===========================================================================================================================
-//	SocketContextRetain
-//===========================================================================================================================
-
-static SocketContext *	SocketContextRetain( SocketContext *inContext )
-{
-	atomic_add_32( &inContext->refCount, 1 );
-	return( inContext );
-}
-
-//===========================================================================================================================
-//	SocketContextRelease
-//===========================================================================================================================
-
-static void	SocketContextRelease( SocketContext *me )
-{
-	if( atomic_add_and_fetch_32( &me->refCount, -1 ) == 0 )
-	{
-		ForgetSocket( &me->sock );
-		if( me->userFinalizer )
-		{
-			me->userFinalizer( me->userContext );
-			me->userFinalizer = NULL;
-		}
-		me->userContext = NULL;
-		free( me );
-	}
-}
-
-//===========================================================================================================================
-//	SocketContextCancelHandler
-//===========================================================================================================================
-
-static void	SocketContextCancelHandler( void *inContext )
-{
-	SocketContextRelease( (SocketContext *) inContext );
-}
-
-//===========================================================================================================================
-//	SocketContextFinalizerCF
-//===========================================================================================================================
-
-static void	SocketContextFinalizerCF( void *inUserCtx )
-{
-	CFRelease( (CFTypeRef) inUserCtx );
-}
-
-//===========================================================================================================================
-//	StringToInt32
-//===========================================================================================================================
-
-static OSStatus	StringToInt32( const char *inString, int32_t *outValue )
-{
-	OSStatus		err;
-	long			value;
-	char *			endPtr;
-	
-	value = strtol( inString, &endPtr, 0 );
-	require_action_quiet( ( *endPtr == '\0' ) && ( endPtr != inString ), exit, err = kParamErr );
-	require_action_quiet( ( value >= INT32_MIN ) && ( value <= INT32_MAX ), exit, err = kRangeErr );
-	
-	*outValue = (int32_t) value;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	StringToUInt32
-//===========================================================================================================================
-
-static OSStatus	StringToUInt32( const char *inString, uint32_t *outValue )
-{
-	OSStatus		err;
-	uint32_t		value;
-	char *			endPtr;
-	
-	value = (uint32_t) strtol( inString, &endPtr, 0 );
-	require_action_quiet( ( *endPtr == '\0' ) && ( endPtr != inString ), exit, err = kParamErr );
-	
-	*outValue = value;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	_StringToInt64
-//===========================================================================================================================
-
-static int64_t	_StringToInt64( const char *inString, OSStatus *outError )
-{
-	OSStatus		err;
-	long long		ll;
-	char *			end;
-	int64_t			i64 = 0;
-	int				errnoVal;
-	
-	set_errno_compat( 0 );
-	ll = strtoll( inString, &end, 0 );
-	errnoVal = errno_compat();
-	require_action_quiet( ( *end == '\0' ) && ( end != inString ), exit, err = kMalformedErr );
-	require_action_quiet( ( ( ll != LLONG_MIN ) && ( ll != LLONG_MAX ) ) || ( errnoVal != ERANGE ), exit, err = kRangeErr );
-	require_action_quiet( ( ll >= INT64_MIN ) && ( ll <= INT64_MAX ), exit, err = kRangeErr );
-	i64 = (int64_t) ll;
-	err = kNoErr;
-	
-exit:
-	if( outError ) *outError = err;
-	return( i64 );
-}
-
-//===========================================================================================================================
-//	_StringToUInt64
-//===========================================================================================================================
-
-static uint64_t	_StringToUInt64( const char *inString, OSStatus *outError )
-{
-	OSStatus				err;
-	unsigned long long		val;
-	char *					end;
-	int						errnoVal;
-	
-	set_errno_compat( 0 );
-	val = strtoull( inString, &end, 0 );
-	errnoVal = errno_compat();
-	
-	require_action_quiet( ( *end == '\0' ) && ( end != inString ), exit, err = kMalformedErr );
-	require_action_quiet( ( val != ULLONG_MAX ) || ( errnoVal != ERANGE ), exit, err = kRangeErr );
-	require_action_quiet( val <= UINT64_MAX, exit, err = kRangeErr );
-	err = kNoErr;
-	
-exit:
-	if( outError ) *outError = err;
-	return( (uint64_t)val );
-}
-
-//===========================================================================================================================
-//	_StringToPID
-//===========================================================================================================================
-
-static pid_t	_StringToPID( const char *inString, OSStatus *outError )
-{
-	OSStatus		err;
-	int64_t			i64;
-	pid_t			pid = 0;
-	
-	i64 = _StringToInt64( inString, &err );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( i64 == (pid_t) i64, exit, err = kRangeErr );
-	pid = (pid_t) i64;
-	err = kNoErr;
-	
-exit:
-	if( outError ) *outError = err;
-	return( pid );
-}
-
-//===========================================================================================================================
-//	_ParseEscapedString
-//	
-//	Note: Similar to ParseEscapedString() from CoreUtils except that _ParseEscapedString() takes an optional C string
-//	containing delimiter characters instead of being limited to one delimiter character. Also, when the function returns
-//	due to a delimiter, the output pointer is set to the delimiter character instead of the character after the delimiter.
-//===========================================================================================================================
-
-static OSStatus
-	_ParseEscapedString(
-		const char *	inSrc,
-		const char *	inEnd,
-		const char *	inDelimiters,
-		char *			inBufPtr,
-		size_t			inBufLen,
-		size_t *		outCopiedLen,
-		size_t *		outActualLen,
-		const char **	outPtr )
-{
-	OSStatus				err;
-	const char *			ptr;
-	char *					dst = inBufPtr;
-	const char * const		lim = ( inBufLen > 0 ) ? &inBufPtr[ inBufLen - 1 ] : inBufPtr;
-	size_t					len;
-	
-	len = 0;
-	ptr = inSrc;
-	if( !inDelimiters ) inDelimiters = "";
-	while( ptr < inEnd )
-	{
-		int					c;
-		const char *		del;
-		
-		c = *ptr;
-		for( del = inDelimiters; ( *del != '\0' ) && ( c != *del ); ++del ) {}
-		if( *del != '\0' ) break;
-		++ptr;
-		if( c == '\\' )
-		{
-			require_action_quiet( ptr < inEnd, exit, err = kUnderrunErr );
-			c = *ptr++;
-		}
-		++len;
-		if( dst < lim ) *dst++ = (char) c;
-	}
-	if( inBufLen > 0 ) *dst = '\0';
-	
-	if( outCopiedLen )	*outCopiedLen	= (size_t)( dst - inBufPtr );
-	if( outActualLen )	*outActualLen	= len;
-	if( outPtr )		*outPtr			= ptr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ParseEscapedStringWithCopy
-//===========================================================================================================================
-
-static OSStatus
-	_ParseEscapedStringWithCopy(
-		const char *	inSrc,
-		const char *	inEnd,
-		const char *	inDelimiters,
-		char *			inBufPtr,
-		size_t			inBufLen,
-		const char **	outString,
-		char **			outMemory,
-		const char **	outPtr )
-{
-	OSStatus		err;
-	size_t			actualLen, bufLen;
-	char *			bufPtr;
-	char *			mem = NULL;
-	
-	err = _ParseEscapedString( inSrc, inEnd, inDelimiters, NULL, 0, NULL, &actualLen, NULL );
-	require_noerr_quiet( err, exit );
-	
-	if( actualLen < inBufLen )
-	{
-		bufPtr = inBufPtr;
-		bufLen = inBufLen;
-	}
-	else
-	{
-		bufLen = actualLen + 1;
-		mem = (char *) malloc( bufLen );
-		require_action( mem, exit, err = kNoMemoryErr );
-		bufPtr = mem;
-	}
-	err = _ParseEscapedString( inSrc, inEnd, inDelimiters, bufPtr, bufLen, NULL, NULL, outPtr );
-	require_noerr_quiet( err, exit );
-	
-	*outString = bufPtr;
-	*outMemory = mem;
-	mem = NULL;
-	
-exit:
-	ForgetMem( &mem );
-	return( err );
-}
-
-#endif
-
-//===========================================================================================================================
-//	StringToARecordData
-//===========================================================================================================================
-
-static OSStatus	StringToARecordData( const char *inString, uint8_t **outPtr, size_t *outLen )
-{
-	OSStatus			err;
-	uint32_t *			addrPtr;
-	const size_t		addrLen = sizeof( *addrPtr );
-	const char *		end;
-	
-	addrPtr = (uint32_t *) malloc( addrLen );
-	require_action( addrPtr, exit, err = kNoMemoryErr );
-	
-	err = _StringToIPv4Address( inString, kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoPrefix, addrPtr,
-		NULL, NULL, NULL, &end );
-	if( !err && ( *end != '\0' ) ) err = kMalformedErr;
-	require_noerr_quiet( err, exit );
-	
-	*addrPtr = HostToBig32( *addrPtr );
-	
-	*outPtr = (uint8_t *) addrPtr;
-	addrPtr = NULL;
-	*outLen = addrLen;
-	
-exit:
-	FreeNullSafe( addrPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	StringToAAAARecordData
-//===========================================================================================================================
-
-static OSStatus	StringToAAAARecordData( const char *inString, uint8_t **outPtr, size_t *outLen )
-{
-	OSStatus			err;
-	uint8_t *			addrPtr;
-	const size_t		addrLen = 16;
-	const char *		end;
-	
-	addrPtr = (uint8_t *) malloc( addrLen );
-	require_action( addrPtr, exit, err = kNoMemoryErr );
-	
-	err = _StringToIPv6Address( inString,
-		kStringToIPAddressFlagsNoPort | kStringToIPAddressFlagsNoPrefix | kStringToIPAddressFlagsNoScope,
-		addrPtr, NULL, NULL, NULL, &end );
-	if( !err && ( *end != '\0' ) ) err = kMalformedErr;
-	require_noerr_quiet( err, exit );
-	
-	*outPtr = addrPtr;
-	addrPtr = NULL;
-	*outLen = addrLen;
-	
-exit:
-	FreeNullSafe( addrPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	StringToDomainName
-//===========================================================================================================================
-
-static OSStatus	StringToDomainName( const char *inString, uint8_t **outPtr, size_t *outLen )
-{
-	OSStatus		err;
-	uint8_t *		namePtr;
-	size_t			nameLen;
-	uint8_t *		end;
-	uint8_t			nameBuf[ kDomainNameLengthMax ];
-	
-	err = DomainNameFromString( nameBuf, inString, &end );
-	require_noerr_quiet( err, exit );
-	
-	nameLen = (size_t)( end - nameBuf );
-	namePtr = _memdup( nameBuf, nameLen );
-	require_action( namePtr, exit, err = kNoMemoryErr );
-	
-	*outPtr = namePtr;
-	namePtr = NULL;
-	if( outLen ) *outLen = nameLen;
-	
-exit:
-	return( err );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	GetDefaultDNSServer
-//===========================================================================================================================
-
-static OSStatus	GetDefaultDNSServer( sockaddr_ip *outAddr )
-{
-	OSStatus				err;
-	dns_config_t *			config;
-	struct sockaddr *		addr;
-	int32_t					i;
-	
-	config = dns_configuration_copy();
-	require_action( config, exit, err = kUnknownErr );
-	
-	addr = NULL;
-	for( i = 0; i < config->n_resolver; ++i )
-	{
-		const dns_resolver_t * const		resolver = config->resolver[ i ];
-		
-		if( !resolver->domain && ( resolver->n_nameserver > 0 ) )
-		{
-			addr = resolver->nameserver[ 0 ];
-			break;
-		}
- 	}
-	require_action_quiet( addr, exit, err = kNotFoundErr );
-	
-	SockAddrCopy( addr, outAddr );
-	err = kNoErr;
-	
-exit:
-	if( config ) dns_configuration_free( config );
-	return( err );
-}
-#endif
-
-//===========================================================================================================================
-//	GetMDNSMulticastAddrV4
-//===========================================================================================================================
-
-static void	_MDNSMulticastAddrV4Init( void *inContext );
-
-static const struct sockaddr *	GetMDNSMulticastAddrV4( void )
-{
-	static struct sockaddr_in		sMDNSMulticastAddrV4;
-	static dispatch_once_t			sMDNSMulticastAddrV4InitOnce = 0;
-	
-	dispatch_once_f( &sMDNSMulticastAddrV4InitOnce, &sMDNSMulticastAddrV4, _MDNSMulticastAddrV4Init );
-	return( (const struct sockaddr *) &sMDNSMulticastAddrV4 );
-}
-
-static void	_MDNSMulticastAddrV4Init( void *inContext )
-{
-	struct sockaddr_in * const		addr = (struct sockaddr_in *) inContext;
-	
-	_SockAddrInitIPv4( addr, UINT32_C( 0xE00000FB ), kMDNSPort );	// The mDNS IPv4 multicast address is 224.0.0.251.
-}
-
-//===========================================================================================================================
-//	GetMDNSMulticastAddrV6
-//===========================================================================================================================
-
-static void	_MDNSMulticastAddrV6Init( void *inContext );
-
-static const struct sockaddr *	GetMDNSMulticastAddrV6( void )
-{
-	static struct sockaddr_in6		sMDNSMulticastAddrV6;
-	static dispatch_once_t			sMDNSMulticastAddrV6InitOnce = 0;
-	
-	dispatch_once_f( &sMDNSMulticastAddrV6InitOnce, &sMDNSMulticastAddrV6, _MDNSMulticastAddrV6Init );
-	return( (const struct sockaddr *) &sMDNSMulticastAddrV6 );
-}
-
-static void	_MDNSMulticastAddrV6Init( void *inContext )
-{
-	struct sockaddr_in6 * const		addr = (struct sockaddr_in6 *) inContext;
-	
-	memset( addr, 0, sizeof( *addr ) );
-	SIN6_LEN_SET( addr );
-	addr->sin6_family	= AF_INET6;
-	addr->sin6_port		= htons( kMDNSPort );
-	addr->sin6_addr.s6_addr[  0 ] = 0xFF;	// The mDNS IPv6 multicast address is FF02::FB.
-	addr->sin6_addr.s6_addr[  1 ] = 0x02;
-	addr->sin6_addr.s6_addr[ 15 ] = 0xFB;
-}
-
-//===========================================================================================================================
-//	CreateMulticastSocket
-//===========================================================================================================================
-
-static OSStatus
-	CreateMulticastSocket(
-		const struct sockaddr *	inAddr,
-		int						inPort,
-		const char *			inIfName,
-		uint32_t				inIfIndex,
-		Boolean					inJoin,
-		int *					outPort,
-		SocketRef *				outSock )
-{
-	OSStatus		err;
-	SocketRef		sock	= kInvalidSocketRef;
-	const int		family	= inAddr->sa_family;
-	int				port;
-	
-	require_action_quiet( ( family == AF_INET ) ||( family == AF_INET6 ), exit, err = kUnsupportedErr );
-	
-	err = ServerSocketOpen( family, SOCK_DGRAM, IPPROTO_UDP, inPort, &port, kSocketBufferSize_DontSet, &sock );
-	require_noerr_quiet( err, exit );
-	
-	err = SocketSetMulticastInterface( sock, inIfName, inIfIndex );
-	require_noerr_quiet( err, exit );
-	
-	if( family == AF_INET )
-	{
-		err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &(uint8_t){ 1 }, (socklen_t) sizeof( uint8_t ) );
-		err = map_socket_noerr_errno( sock, err );
-		require_noerr_quiet( err, exit );
-	}
-	else
-	{
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &(int){ 1 }, (socklen_t) sizeof( int ) );
-		err = map_socket_noerr_errno( sock, err );
-		require_noerr_quiet( err, exit );
-	}
-	
-	if( inJoin )
-	{
-		err = SocketJoinMulticast( sock, inAddr, inIfName, inIfIndex );
-		require_noerr_quiet( err, exit );
-	}
-	
-	if( outPort ) *outPort = port;
-	*outSock = sock;
-	sock = kInvalidSocketRef;
-	
-exit:
-	ForgetSocket( &sock );
-	return( err );
-}
-
-//===========================================================================================================================
-//	DecimalTextToUInt32
-//===========================================================================================================================
-
-static OSStatus	DecimalTextToUInt32( const char *inSrc, const char *inEnd, uint32_t *outValue, const char **outPtr )
-{
-	OSStatus			err;
-	uint64_t			value;
-	const char *		ptr = inSrc;
-	
-	require_action_quiet( ( ptr < inEnd ) && isdigit_safe( *ptr ), exit, err = kMalformedErr );
-	
-	value = (uint64_t)( *ptr++ - '0' );
-	if( value == 0 )
-	{
-		if( ( ptr < inEnd ) && isdigit_safe( *ptr ) )
-		{
-			err = kMalformedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		while( ( ptr < inEnd ) && isdigit_safe( *ptr ) )
-		{
-			value = ( value * 10 ) + (uint64_t)( *ptr++ - '0' );
-			require_action_quiet( value <= UINT32_MAX, exit, err = kRangeErr );
-		}
-	}
-	
-	*outValue = (uint32_t) value;
-	if( outPtr ) *outPtr = ptr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	CheckIntegerArgument
-//===========================================================================================================================
-
-static OSStatus	CheckIntegerArgument( int inArgValue, const char *inArgName, int inMin, int inMax )
-{
-	if( ( inArgValue >= inMin ) && ( inArgValue <= inMax ) ) return( kNoErr );
-	
-	FPrintF( stderr, "error: Invalid %s: %d. Valid range is [%d, %d].\n", inArgName, inArgValue, inMin, inMax );
-	return( kRangeErr );
-}
-
-//===========================================================================================================================
-//	CheckDoubleArgument
-//===========================================================================================================================
-
-static OSStatus	CheckDoubleArgument( double inArgValue, const char *inArgName, double inMin, double inMax )
-{
-	if( ( inArgValue >= inMin ) && ( inArgValue <= inMax ) ) return( kNoErr );
-	
-	FPrintF( stderr, "error: Invalid %s: %.1f. Valid range is [%.1f, %.1f].\n", inArgName, inArgValue, inMin, inMax );
-	return( kRangeErr );
-}
-
-//===========================================================================================================================
-//	CheckRootUser
-//===========================================================================================================================
-
-static OSStatus	CheckRootUser( void )
-{
-	if( geteuid() == 0 ) return( kNoErr );
-	
-	FPrintF( stderr, "error: This command must to be run as root.\n" );
-	return( kPermissionErr );
-}
-
-//===========================================================================================================================
-//	_SpawnCommand
-//===========================================================================================================================
-
-extern char **		environ;
-
-static OSStatus
-	_SpawnCommand(
-		pid_t *			outPID,
-		const char *	inStdOutRedirect,
-		const char *	inStdErrRedirect,
-		const char *	inFormat,
-		... )
-{
-	OSStatus							err;
-	va_list								args;
-	char *								cmdStr		= NULL;
-	size_t								cmdLen;
-	const char *						cmdEnd;
-	char *								bufPtr		= NULL;
-	size_t								bufLen;
-	const char *						bufLim;
-	pid_t								pid;
-	const char *						src;
-	char *								dst;
-	char **								argArray	= NULL;
-	size_t								argCapacity, argCount;
-	posix_spawn_file_actions_t			actions;
-	posix_spawn_file_actions_t *		actionsPtr	= NULL;
-	
-	// Create command string from format string and its arguments.
-	
-	va_start( args, inFormat );
-	VASPrintF( &cmdStr, inFormat, args );
-	va_end( args );
-	require_action( cmdStr, exit, err = kUnknownErr );
-	
-	cmdLen = strlen( cmdStr );
-	cmdEnd = &cmdStr[ cmdLen ];
-	
-	// Allocate buffer for argument strings.
-	// In the worst-case scenario in terms of memory requirements, the only non-escaped white space is one non-escaped
-	// white space character between each pair of adjacent arguments. The amount of required memory is equal to the size
-	// of cmdStr.
-	
-	bufLen = cmdLen + 1; // +1 for NUL terminator.
-	bufPtr = (char *) malloc( bufLen );
-	require_action( bufPtr, exit, err = kNoMemoryErr );
-	bufLim = &bufPtr[ bufLen ];
-	
-	// Allocate initial argument array.
-	
-	argCount	= 0;
-	argCapacity	= 8;
-	argArray = (char **) malloc( ( argCapacity + 1 ) * sizeof( *argArray ) ); // +1 for NULL arg.
-	require_action( argArray, exit, err = kNoMemoryErr );
-	
-	// Extract argument strings from command string.
-	
-	src = cmdStr;
-	dst = bufPtr;
-	for( ;; )
-	{
-		size_t		maxLen, copiedLen, totalLen;
-		Boolean		more;
-		
-		maxLen = (size_t)( bufLim - dst );
-		if( maxLen > 0 ) --maxLen; // -1 for NUL terminator.
-		more = _ParseQuotedEscapedString( src, cmdEnd, kWhiteSpaceCharSet, dst, maxLen, &copiedLen, &totalLen, &src );
-		if( !more ) break;
-		require_fatal( copiedLen == totalLen, "Incorrect assumption about maximum required buffer space." );
-		
-		if( argCount >= argCapacity )
-		{
-			size_t		newCapactiy;
-			char **		newArray;
-			
-			newCapactiy = 2 * argCapacity;
-			newArray = (char **) realloc( argArray, ( newCapactiy + 1 ) * sizeof( *newArray ) ); // +1 for NULL arg.
-			require_action( newArray, exit, err = kNoMemoryErr );
-			
-			argArray	= newArray;
-			argCapacity	= newCapactiy;
-		}
-		argArray[ argCount++ ] = dst;
-		dst += copiedLen;
-		*dst++ = '\0';
-		check( dst <= bufLim );
-	}
-	require_action_quiet( argCount > 0, exit, err = kCommandErr );
-	
-	argArray[ argCount ] = NULL;
-	
-	// Set up stdout and stderr redirections, if any.
-	
-	if( inStdOutRedirect || inStdErrRedirect )
-	{
-		err = posix_spawn_file_actions_init( &actions );
-		require_noerr( err, exit );
-		
-		actionsPtr = &actions;
-		if( inStdOutRedirect )
-		{
-			err = posix_spawn_file_actions_addopen( actionsPtr, STDOUT_FILENO, inStdOutRedirect, O_WRONLY, 0 );
-			require_noerr( err, exit );
-		}
-		if( inStdErrRedirect )
-		{
-			err = posix_spawn_file_actions_addopen( actionsPtr, STDERR_FILENO, inStdErrRedirect, O_WRONLY, 0 );
-			require_noerr( err, exit );
-		}
-	}
-	// Spawn command.
-	
-	err = posix_spawnp( &pid, argArray[ 0 ], actionsPtr, NULL, argArray, environ );
-	require_noerr_quiet( err, exit );
-	
-	if( outPID ) *outPID = pid;
-	
-exit:
-	FreeNullSafe( cmdStr );
-	FreeNullSafe( bufPtr );
-	FreeNullSafe( argArray );
-	if( actionsPtr ) posix_spawn_file_actions_destroy( actionsPtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	OutputFormatFromArgString
-//===========================================================================================================================
-
-static OSStatus	OutputFormatFromArgString( const char *inArgString, OutputFormatType *outFormat )
-{
-	OSStatus				err;
-	OutputFormatType		format;
-	
-	format = (OutputFormatType) CLIArgToValue( "format", inArgString, &err,
-		kOutputFormatStr_JSON,		kOutputFormatType_JSON,
-		kOutputFormatStr_XML,		kOutputFormatType_XML,
-		kOutputFormatStr_Binary,	kOutputFormatType_Binary,
-		NULL );
-	if( outFormat ) *outFormat = format;
-	return( err );
-}
-
-//===========================================================================================================================
-//	OutputPropertyList
-//===========================================================================================================================
-
-static OSStatus	OutputPropertyList( CFPropertyListRef inPList, OutputFormatType inType, const char *inOutputFilePath )
-{
-	OSStatus		err;
-	CFDataRef		results = NULL;
-	FILE *			file	= NULL;
-	
-	// Convert plist to a specific format.
-	
-	switch( inType )
-	{
-		case kOutputFormatType_JSON:
-			results = CFCreateJSONData( inPList, kJSONFlags_None, NULL );
-			require_action( results, exit, err = kUnknownErr );
-			break;
-		
-		case kOutputFormatType_XML:
-			results = CFPropertyListCreateData( NULL, inPList, kCFPropertyListXMLFormat_v1_0, 0, NULL );
-			require_action( results, exit, err = kUnknownErr );
-			break;
-		
-		case kOutputFormatType_Binary:
-			results = CFPropertyListCreateData( NULL, inPList, kCFPropertyListBinaryFormat_v1_0, 0, NULL );
-			require_action( results, exit, err = kUnknownErr );
-			break;
-		
-		default:
-			err = kTypeErr;
-			goto exit;
-	}
-	
-	// Write formatted results to file or stdout.
-	
-	if( inOutputFilePath )
-	{
-		file = fopen( inOutputFilePath, "wb" );
-		err = map_global_value_errno( file, file );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		file = stdout;
-	}
-	
-	err = WriteANSIFile( file, CFDataGetBytePtr( results ), (size_t) CFDataGetLength( results ) );
-	require_noerr_quiet( err, exit );
-	
-	// Write a trailing newline for JSON-formatted results.
-	
-	if( inType == kOutputFormatType_JSON )
-	{
-		err = WriteANSIFile( file, "\n", 1 );
-		require_noerr_quiet( err, exit );
-	}
-	
-exit:
-	if( file && ( file != stdout ) ) fclose( file );
-	CFReleaseNullSafe( results );
-	return( err );
-}
-
-//===========================================================================================================================
-//	CreateSRVRecordDataFromString
-//===========================================================================================================================
-
-static OSStatus	CreateSRVRecordDataFromString( const char *inString, uint8_t **outPtr, size_t *outLen )
-{
-	OSStatus			err;
-	DataBuffer			dataBuf;
-	const char *		ptr;
-	int					i;
-	uint8_t *			end;
-	uint8_t				target[ kDomainNameLengthMax ];
-	
-	DataBuffer_Init( &dataBuf, NULL, 0, ( 3 * 2 ) + kDomainNameLengthMax );
-	
-	// Parse and set the priority, weight, and port values (all three are unsigned 16-bit values).
-	
-	ptr = inString;
-	for( i = 0; i < 3; ++i )
-	{
-		char *		next;
-		long		value;
-		uint8_t		buf[ 2 ];
-		
-		value = strtol( ptr, &next, 0 );
-		require_action_quiet( ( next != ptr ) && ( *next == ',' ), exit, err = kMalformedErr );
-		require_action_quiet( ( value >= 0 ) && ( value <= UINT16_MAX ), exit, err = kRangeErr );
-		ptr = next + 1;
-		
-		WriteBig16Typed( buf, (uint16_t) value );
-		
-		err = DataBuffer_Append( &dataBuf, buf, sizeof( buf ) );
-		require_noerr( err, exit );
-	}
-	
-	// Set the target domain name.
-	
-	err = DomainNameFromString( target, ptr, &end );
-    require_noerr_quiet( err, exit );
-	
-	err = DataBuffer_Append( &dataBuf, target, (size_t)( end - target ) );
-	require_noerr( err, exit );
-	
-	err = DataBuffer_Detach( &dataBuf, outPtr, outLen );
-	require_noerr( err, exit );
-	
-exit:
-	DataBuffer_Free( &dataBuf );
-	return( err );
-}
-
-//===========================================================================================================================
-//	CreateTXTRecordDataFromString
-//===========================================================================================================================
-
-static OSStatus	CreateTXTRecordDataFromString(const char *inString, int inDelimiter, uint8_t **outPtr, size_t *outLen )
-{
-	OSStatus			err;
-	DataBuffer			dataBuf;
-	const char *		src;
-	uint8_t				txtStr[ 256 ];	// Buffer for single TXT string: 1 length byte + up to 255 bytes of data.
-	
-	DataBuffer_Init( &dataBuf, NULL, 0, kDNSRecordDataLengthMax );
-	
-	src = inString;
-	for( ;; )
-	{
-		uint8_t *					dst = &txtStr[ 1 ];
-		const uint8_t * const		lim = &txtStr[ 256 ];
-		int							c;
-		
-		while( *src && ( *src != inDelimiter ) )
-		{
-			if( ( c = *src++ ) == '\\' )
-			{
-				require_action_quiet( *src != '\0', exit, err = kUnderrunErr );
-				c = *src++;
-			}
-			require_action_quiet( dst < lim, exit, err = kOverrunErr );
-			*dst++ = (uint8_t) c;
-		}
-		txtStr[ 0 ] = (uint8_t)( dst - &txtStr[ 1 ] );
-		err = DataBuffer_Append( &dataBuf, txtStr, 1 + txtStr[ 0 ] );
-		require_noerr( err, exit );
-		
-		if( *src == '\0' ) break;
-		++src;
-	}
-	
-	err = DataBuffer_Detach( &dataBuf, outPtr, outLen );
-	require_noerr( err, exit );
-	
-exit:
-	DataBuffer_Free( &dataBuf );
-	return( err );
-}
-
-//===========================================================================================================================
-//	CreateNSECRecordData
-//===========================================================================================================================
-
-DECLARE_QSORT_NUMERIC_COMPARATOR( _QSortCmpUnsigned );
-DEFINE_QSORT_NUMERIC_COMPARATOR( unsigned int, _QSortCmpUnsigned )
-
-#define kNSECBitmapMaxLength		32	// 32 bytes (256 bits). See <https://tools.ietf.org/html/rfc4034#section-4.1.2>.
-
-static OSStatus
-	CreateNSECRecordData(
-		const uint8_t *	inNextDomainName,
-		uint8_t **		outPtr,
-		size_t *		outLen,
-		unsigned int	inTypeCount,
-		... )
-{
-	OSStatus			err;
-	va_list				args;
-	DataBuffer			rdataDB;
-	unsigned int *		array	= NULL;
-	unsigned int		i, type, maxBit, currBlock, bitmapLen;
-	uint8_t				fields[ 2 + kNSECBitmapMaxLength ];
-	uint8_t * const		bitmap	= &fields[ 2 ];
-	
-	va_start( args, inTypeCount );
-	DataBuffer_Init( &rdataDB, NULL, 0, kDNSRecordDataLengthMax );
-	
-	// Append Next Domain Name.
-	
-	err = DataBuffer_Append( &rdataDB, inNextDomainName, DomainNameLength( inNextDomainName ) );
-	require_noerr( err, exit );
-	
-	// Append Type Bit Maps.
-	
-	maxBit = 0;
-	memset( bitmap, 0, kNSECBitmapMaxLength );
-	if( inTypeCount > 0 )
-	{
-		array = (unsigned int *) malloc( inTypeCount * sizeof_element( array ) );
-		require_action( array, exit, err = kNoMemoryErr );
-		
-		for( i = 0; i < inTypeCount; ++i )
-		{
-			type = va_arg( args, unsigned int );
-			require_action_quiet( type <= UINT16_MAX, exit, err = kRangeErr );
-			array[ i ] = type;
-		}
-		qsort( array, inTypeCount, sizeof_element( array ), _QSortCmpUnsigned );
-		
-		currBlock = array[ 0 ] / 256;
-		for( i = 0; i < inTypeCount; ++i )
-		{
-			const unsigned int		block	= array[ i ] / 256;
-			const unsigned int		bit		= array[ i ] % 256;
-			
-			if( block != currBlock )
-			{
-				bitmapLen	= BitArray_MaxBytes( maxBit + 1 );
-				fields[ 0 ] = (uint8_t) currBlock;
-				fields[ 1 ] = (uint8_t) bitmapLen;
-				
-				err = DataBuffer_Append( &rdataDB, fields, 2 + bitmapLen );
-				require_noerr( err, exit );
-				
-				maxBit		= 0;
-				currBlock	= block;
-				memset( bitmap, 0, bitmapLen );
-			}
-			BitArray_SetBit( bitmap, bit );
-			if( bit > maxBit ) maxBit = bit;
-		}
-	}
-	else
-	{
-		currBlock = 0;
-	}
-	
-	bitmapLen	= BitArray_MaxBytes( maxBit + 1 );
-	fields[ 0 ] = (uint8_t) currBlock;
-	fields[ 1 ] = (uint8_t) bitmapLen;
-	
-	err = DataBuffer_Append( &rdataDB, fields, 2 + bitmapLen );
-	require_noerr( err, exit );
-	
-	err = DataBuffer_Detach( &rdataDB, outPtr, outLen );
-	require_noerr( err, exit );
-	
-exit:
-	va_end( args );
-	DataBuffer_Free( &rdataDB );
-	FreeNullSafe( array );
-	return( err );
-}
-
-//===========================================================================================================================
-//	AppendSOARecord
-//===========================================================================================================================
-
-static OSStatus
-	_AppendSOARecordData(
-		DataBuffer *	inDB,
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		size_t *		outLen );
-
-static OSStatus
-	AppendSOARecord(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass,
-		uint32_t		inTTL,
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		size_t *		outLen )
-{
-	OSStatus		err;
-	size_t			rdataLen;
-	size_t			rdlengthOffset = 0;
-	uint8_t *		rdlengthPtr;
-	
-	if( inDB )
-	{
-		err = _DataBuffer_AppendDNSRecord( inDB, inNamePtr, inNameLen, inType, inClass, inTTL, NULL, 0 );
-		require_noerr( err, exit );
-		
-		rdlengthOffset = DataBuffer_GetLen( inDB ) - 2;
-	}
-	
-	err = _AppendSOARecordData( inDB, inMName, inRName, inSerial, inRefresh, inRetry, inExpire, inMinimumTTL, &rdataLen );
-	require_noerr( err, exit );
-	
-	if( inDB )
-	{
-		rdlengthPtr = DataBuffer_GetPtr( inDB ) + rdlengthOffset;
-		WriteBig16Typed( rdlengthPtr, (uint16_t) rdataLen );
-	}
-	
-	if( outLen ) *outLen = inNameLen + sizeof( dns_fixed_fields_record ) + rdataLen;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-static OSStatus
-	_AppendSOARecordData(
-		DataBuffer *	inDB,
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		size_t *		outLen )
-{
-	OSStatus					err;
-	dns_fixed_fields_soa		fields;
-	const size_t				mnameLen = DomainNameLength( inMName );
-	const size_t				rnameLen = DomainNameLength( inRName );
-	
-	if( inDB )
-	{
-		err = DataBuffer_Append( inDB, inMName, mnameLen );
-		require_noerr( err, exit );
-		
-		err = DataBuffer_Append( inDB, inRName, rnameLen );
-		require_noerr( err, exit );
-		
-		dns_fixed_fields_soa_init( &fields, inSerial, inRefresh, inRetry, inExpire, inMinimumTTL );
-		err = DataBuffer_Append( inDB, &fields, sizeof( fields ) );
-		require_noerr( err, exit );
-	}
-	if( outLen ) *outLen = mnameLen + rnameLen + sizeof( fields );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	CreateSOARecordData
-//===========================================================================================================================
-
-static OSStatus
-	CreateSOARecordData(
-		const uint8_t *	inMName,
-		const uint8_t *	inRName,
-		uint32_t		inSerial,
-		uint32_t		inRefresh,
-		uint32_t		inRetry,
-		uint32_t		inExpire,
-		uint32_t		inMinimumTTL,
-		uint8_t **		outPtr,
-		size_t *		outLen )
-{
-	OSStatus		err;
-	DataBuffer		rdataDB;
-	
-	DataBuffer_Init( &rdataDB, NULL, 0, kDNSRecordDataLengthMax );
-	
-	err = _AppendSOARecordData( &rdataDB, inMName, inRName, inSerial, inRefresh, inRetry, inExpire, inMinimumTTL, NULL );
-	require_noerr( err, exit );
-	
-	err = DataBuffer_Detach( &rdataDB, outPtr, outLen );
-	require_noerr( err, exit );
-	
-exit:
-	DataBuffer_Free( &rdataDB );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_DataBuffer_AppendDNSQuestion
-//===========================================================================================================================
-
-static OSStatus
-	_DataBuffer_AppendDNSQuestion(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass )
-{
-	OSStatus						err;
-	dns_fixed_fields_question		fields;
-	
-	err = DataBuffer_Append( inDB, inNamePtr, inNameLen );
-	require_noerr( err, exit );
-	
-	dns_fixed_fields_question_init( &fields, inType, inClass );
-	err = DataBuffer_Append( inDB, &fields, sizeof( fields ) );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_DataBuffer_AppendDNSRecord
-//===========================================================================================================================
-
-static OSStatus
-	_DataBuffer_AppendDNSRecord(
-		DataBuffer *	inDB,
-		const uint8_t *	inNamePtr,
-		size_t			inNameLen,
-		uint16_t		inType,
-		uint16_t		inClass,
-		uint32_t		inTTL,
-		const uint8_t *	inRDataPtr,
-		size_t			inRDataLen )
-{
-	OSStatus					err;
-	dns_fixed_fields_record		fields;
-	
-	require_action_quiet( inRDataLen < kDNSRecordDataLengthMax, exit, err = kSizeErr );
-	
-	err = DataBuffer_Append( inDB, inNamePtr, inNameLen );
-	require_noerr( err, exit );
-	
-	dns_fixed_fields_record_init( &fields, inType, inClass, inTTL, (uint16_t) inRDataLen );
-	err = DataBuffer_Append( inDB, &fields, sizeof( fields ) );
-	require_noerr( err, exit );
-	
-	if( inRDataPtr )
-	{
-		err = DataBuffer_Append( inDB, inRDataPtr, inRDataLen );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_NanoTime64ToTimestamp
-//===========================================================================================================================
-
-static char *	_NanoTime64ToTimestamp( NanoTime64 inTime, char *inBuf, size_t inMaxLen )
-{
-	struct  timeval		tv;
-	
-	NanoTimeToTimeVal( inTime, &tv );
-	return( MakeFractionalDateString( &tv, inBuf, inMaxLen ) );
-}
-
-//===========================================================================================================================
-//	_MDNSInterfaceListCreate
-//===========================================================================================================================
-
-static Boolean	_MDNSInterfaceIsBlacklisted( SocketRef inInfoSock, const char *inIfName );
-
-static OSStatus	_MDNSInterfaceListCreate( MDNSInterfaceSubset inSubset, size_t inItemSize, MDNSInterfaceItem **outList )
-{
-	OSStatus					err;
-	struct ifaddrs *			ifaList;
-	const struct ifaddrs *		ifa;
-	MDNSInterfaceItem *			interfaceList;
-	MDNSInterfaceItem **		ptr;
-	SocketRef					infoSock;
-	
-	ifaList			= NULL;
-	interfaceList	= NULL;
-	infoSock		= kInvalidSocketRef;
-	if( inItemSize == 0 ) inItemSize = sizeof( MDNSInterfaceItem );
-	require_action_quiet( inItemSize >= sizeof( MDNSInterfaceItem ), exit, err = kSizeErr );
-	
-	infoSock = socket( AF_INET, SOCK_DGRAM, 0 );
-	err = map_socket_creation_errno( infoSock );
-	require_noerr( err, exit );
-	
-	err = getifaddrs( &ifaList );
-	err = map_global_noerr_errno( err );
-	require_noerr( err, exit );
-	
-	ptr = &interfaceList;
-	for( ifa = ifaList; ifa; ifa = ifa->ifa_next )
-	{
-		MDNSInterfaceItem *		item;
-		int						family;
-		const unsigned int		flagsMask	= IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT;
-		const unsigned int		flagsNeeded	= IFF_UP | IFF_MULTICAST;
-		
-		if( ( ifa->ifa_flags & flagsMask ) != flagsNeeded )		continue;
-		if( !ifa->ifa_addr || !ifa->ifa_name )					continue;
-		family = ifa->ifa_addr->sa_family;
-		if( ( family != AF_INET ) && ( family != AF_INET6 ) )	continue;
-		
-		for( item = interfaceList; item && ( strcmp( item->ifName, ifa->ifa_name ) != 0 ); item = item->next ) {}
-		if( !item )
-		{
-			NetTransportType		type;
-			uint32_t				ifIndex;
-			const char * const		ifName = ifa->ifa_name;
-			
-			if( _MDNSInterfaceIsBlacklisted( infoSock, ifName ) ) continue;
-			err = SocketGetInterfaceInfo( infoSock, ifName, NULL, &ifIndex, NULL, NULL, NULL, NULL, NULL, &type );
-			require_noerr( err, exit );
-			
-			if( ifIndex == 0 ) continue;
-			if( type == kNetTransportType_AWDL )
-			{
-				if( inSubset == kMDNSInterfaceSubset_NonAWDL ) continue;
-			}
-			else
-			{
-				if( inSubset == kMDNSInterfaceSubset_AWDL ) continue;
-			}
-			item = (MDNSInterfaceItem *) calloc( 1, inItemSize );
-			require_action( item, exit, err = kNoMemoryErr );
-			
-			*ptr =  item;
-			 ptr = &item->next;
-			
-			item->ifName = strdup( ifName );
-			require_action( item->ifName, exit, err = kNoMemoryErr );
-			
-			item->ifIndex = ifIndex;
-			if(      type == kNetTransportType_AWDL ) item->isAWDL = true;
-			else if( type == kNetTransportType_WiFi ) item->isWiFi = true;
-		}
-		if( family == AF_INET )	item->hasIPv4 = true;
-		else					item->hasIPv6 = true;
-	}
-	require_action_quiet( interfaceList, exit, err = kNotFoundErr );
-	
-	if( outList )
-	{
-		*outList = interfaceList;
-		interfaceList = NULL;
-	}
-	
-exit:
-	if( ifaList ) freeifaddrs( ifaList );
-	_MDNSInterfaceListFree( interfaceList );
-	ForgetSocket( &infoSock );
-	return( err );
-}
-
-static Boolean	_MDNSInterfaceIsBlacklisted( SocketRef inInfoSock, const char *inIfName )
-{
-	OSStatus						err;
-	int								i;
-	static const char * const		kMDNSInterfacePrefixBlacklist[] = { "llw", "nan" };
-	struct ifreq					ifr;
-	
-	// Check if the interface name's prefix matches the prefix blacklist.
-	
-	for( i = 0; i < (int) countof( kMDNSInterfacePrefixBlacklist ); ++i )
-	{
-		const char * const		prefix	= kMDNSInterfacePrefixBlacklist[ i ];
-		
-        if( strcmp_prefix( inIfName, prefix ) == 0 )
-		{
-			const char *		ptr = &inIfName[ strlen( prefix ) ];
-			
-			while( isdigit_safe( *ptr ) ) ++ptr;
-			if( *ptr == '\0' ) return( true );
-		}
-	}
-	
-	// Check if the interface is used for inter-(co)processor networking.
-	
-	memset( &ifr, 0, sizeof( ifr ) );
-	strlcpy( ifr.ifr_name, inIfName, sizeof( ifr.ifr_name ) );
-	err = ioctl( inInfoSock, SIOCGIFFUNCTIONALTYPE, &ifr );
-	err = map_global_value_errno( err != -1, err );
-	if( !err && ( ifr.ifr_functional_type == IFRTYPE_FUNCTIONAL_INTCOPROC ) ) return( true );
-	
-	return( false );
-}
-
-//===========================================================================================================================
-//	_MDNSInterfaceListFree
-//===========================================================================================================================
-
-static void	_MDNSInterfaceListFree( MDNSInterfaceItem *inList )
-{
-	MDNSInterfaceItem *		item;
-	
-	while( ( item = inList ) != NULL )
-	{
-		inList = item->next;
-		FreeNullSafe( item->ifName );
-		free( item );
-	}
-}
-
-//===========================================================================================================================
-//	_MDNSInterfaceGetAny
-//===========================================================================================================================
-
-static OSStatus	_MDNSInterfaceGetAny( MDNSInterfaceSubset inSubset, char inNameBuf[ IF_NAMESIZE + 1 ], uint32_t *outIndex )
-{
-	OSStatus						err;
-	MDNSInterfaceItem *				list;
-	const MDNSInterfaceItem *		item;
-	
-	list = NULL;
-	err = _MDNSInterfaceListCreate( inSubset, 0, &list );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( list, exit, err = kNotFoundErr );
-	
-	for( item = list; item; item = item->next )
-	{
-		if( item->hasIPv4 && item->hasIPv6 ) break;
-	}
-	if( !item ) item = list;
-	if( inNameBuf )	strlcpy( inNameBuf, item->ifName, IF_NAMESIZE + 1 );
-	if( outIndex ) *outIndex = item->ifIndex;
-	
-exit:
-	_MDNSInterfaceListFree( list );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SetComputerName
-//===========================================================================================================================
-
-static OSStatus	_SetComputerName( CFStringRef inComputerName, CFStringEncoding inEncoding )
-{
-	OSStatus				err;
-	SCPreferencesRef		prefs;
-	Boolean					ok;
-	
-	prefs = SCPreferencesCreateWithAuthorization( NULL, CFSTR( kDNSSDUtilIdentifier ), NULL, NULL );
-	err = map_scerror( prefs );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesSetComputerName( prefs, inComputerName, inEncoding );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesCommitChanges( prefs );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesApplyChanges( prefs );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	CFReleaseNullSafe( prefs );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SetComputerNameWithUTF8CString
-//===========================================================================================================================
-
-static OSStatus	_SetComputerNameWithUTF8CString( const char *inComputerName )
-{
-	OSStatus		err;
-	CFStringRef		computerName;
-	
-	computerName = CFStringCreateWithCString( NULL, inComputerName, kCFStringEncodingUTF8 );
-	require_action( computerName, exit, err = kNoMemoryErr );
-	
-	err = _SetComputerName( computerName, kCFStringEncodingUTF8 );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	CFReleaseNullSafe( computerName );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SetLocalHostName
-//===========================================================================================================================
-
-static OSStatus	_SetLocalHostName( CFStringRef inLocalHostName )
-{
-	OSStatus				err;
-	SCPreferencesRef		prefs;
-	Boolean					ok;
-	
-	prefs = SCPreferencesCreateWithAuthorization( NULL, CFSTR( kDNSSDUtilIdentifier ), NULL, NULL );
-	err = map_scerror( prefs );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesSetLocalHostName( prefs, inLocalHostName );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesCommitChanges( prefs );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-	ok = SCPreferencesApplyChanges( prefs );
-	err = map_scerror( ok );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	CFReleaseNullSafe( prefs );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SetLocalHostNameWithUTF8CString
-//===========================================================================================================================
-
-static OSStatus	_SetLocalHostNameWithUTF8CString( const char *inLocalHostName )
-{
-	OSStatus		err;
-	CFStringRef		localHostName;
-	
-	localHostName = CFStringCreateWithCString( NULL, inLocalHostName, kCFStringEncodingUTF8 );
-	require_action( localHostName, exit, err = kNoMemoryErr );
-	
-	err = _SetLocalHostName( localHostName );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	CFReleaseNullSafe( localHostName );
-	return( err );
-}
-
-#if( TARGET_OS_DARWIN )
-//===========================================================================================================================
-//	_InterfaceIPv6AddressAdd
-//===========================================================================================================================
-
-static OSStatus	_InterfaceIPv6AddressAdd( const char *inIfName, uint8_t inAddr[ STATIC_PARAM 16 ], int inMaskBitLen )
-{
-	OSStatus					err;
-	SocketRef					infoSock = kInvalidSocketRef;
-	struct in6_aliasreq			ifra;
-	size_t						len;
-	struct sockaddr_in6 *		sin6;
-	int							wholeBytes, remainingBits;
-	
-	require_action_quiet( ( inMaskBitLen >= 0 ) &&  ( inMaskBitLen <= 128 ), exit, err = kSizeErr );
-	
-	infoSock = socket( AF_INET6, SOCK_DGRAM, 0 );
-	err = map_socket_creation_errno( infoSock );
-	require_noerr( err, exit );
-	
-	// Set interface name.
-	
-	memset( &ifra, 0, sizeof( ifra ) );
-	len = strlcpy( ifra.ifra_name, inIfName, sizeof( ifra.ifra_name ) );
-	require_action_quiet( len < sizeof( ifra.ifra_name ), exit, err = kSizeErr );
-	
-	// Set IPv6 address.
-	
-	sin6 = &ifra.ifra_addr;
-	SIN6_LEN_SET( sin6 );
-	sin6->sin6_family = AF_INET6;
-	memcpy( sin6->sin6_addr.s6_addr, inAddr, 16 );
-	
-	// Set prefix mask.
-	
-	sin6 = &ifra.ifra_prefixmask;
-	SIN6_LEN_SET( sin6 );
-	sin6->sin6_family = AF_INET6;
-	wholeBytes = inMaskBitLen / 8;
-	if( wholeBytes > 0 ) memset( sin6->sin6_addr.s6_addr, 0xFF, (size_t) wholeBytes );
-	remainingBits = inMaskBitLen % 8;
-	if( remainingBits > 0 ) sin6->sin6_addr.s6_addr[ wholeBytes ] = ( 0xFFU << ( 8 - remainingBits ) ) & 0xFFU;
-	
-	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
-	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
-	
-	err = ioctl( infoSock, SIOCAIFADDR_IN6, &ifra );
-	err = map_global_value_errno( err != -1, err );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	ForgetSocket( &infoSock );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_InterfaceIPv6AddressRemove
-//===========================================================================================================================
-
-static OSStatus	_InterfaceIPv6AddressRemove( const char *inIfName, const uint8_t inAddr[ STATIC_PARAM 16 ] )
-{
-	OSStatus					err;
-	SocketRef					infoSock = kInvalidSocketRef;
-	struct in6_ifreq			ifr;
-	size_t						len;
-	struct sockaddr_in6 *		sin6;
-	
-	infoSock = socket( AF_INET6, SOCK_DGRAM, 0 );
-	err = map_socket_creation_errno( infoSock );
-	require_noerr( err, exit );
-	
-	memset( &ifr, 0, sizeof( ifr ) );
-	len = strlcpy( ifr.ifr_name, inIfName, sizeof( ifr.ifr_name ) );
-	require_action_quiet( len < sizeof( ifr.ifr_name ), exit, err = kSizeErr );
-	
-	sin6 = &ifr.ifr_ifru.ifru_addr;
-	SIN6_LEN_SET( sin6 );
-	sin6->sin6_family = AF_INET6;
-	memcpy( sin6->sin6_addr.s6_addr, inAddr, 16 );
-	
-	err = ioctl( infoSock, SIOCDIFADDR_IN6, &ifr );
-	err = map_global_value_errno( err != -1, err );
-	require_noerr_quiet( err, exit );
-	
-exit:
-	ForgetSocket( &infoSock );
-	return( err );
-}
-#endif	// TARGET_OS_DARWIN
-
-//===========================================================================================================================
-//	_TicksDiff
-//===========================================================================================================================
-
-static int64_t	_TicksDiff( uint64_t inT1, uint64_t inT2 )
-{
-	return( (int64_t)( inT1 - inT2 ) );
-}
-
-//===========================================================================================================================
-//	_SockAddrInitIPv4
-//===========================================================================================================================
-
-static void	_SockAddrInitIPv4( struct sockaddr_in *inSA, uint32_t inIPv4, uint16_t inPort )
-{
-	memset( inSA, 0, sizeof( *inSA ) );
-	SIN_LEN_SET( inSA );
-	inSA->sin_family		= AF_INET;
-	inSA->sin_port			= htons( inPort );
-	inSA->sin_addr.s_addr	= htonl( inIPv4 );
-}
-
-//===========================================================================================================================
-//	_SockAddrInitIPv6
-//===========================================================================================================================
-
-static void
-	_SockAddrInitIPv6(
-		struct sockaddr_in6 *	inSA,
-		const uint8_t			inIPv6[ STATIC_PARAM 16 ],
-		uint32_t				inScope,
-		uint16_t				inPort )
-{
-	check_compile_time_code( sizeof( inSA->sin6_addr.s6_addr ) == 16 );
-	
-	memset( inSA, 0, sizeof( *inSA ) );
-	SIN6_LEN_SET( inSA );
-	inSA->sin6_family	= AF_INET6;
-	inSA->sin6_port		= htons( inPort );
-	memcpy( inSA->sin6_addr.s6_addr, inIPv6, 16 );
-	inSA->sin6_scope_id	= inScope;
-}
-
-//===========================================================================================================================
-//	_WriteReverseIPv6DomainNameString
-//===========================================================================================================================
-
-static void
-	_WriteReverseIPv6DomainNameString(
-		const uint8_t	inIPv6Addr[ STATIC_PARAM 16 ],
-		char			outBuffer[ STATIC_PARAM kReverseIPv6DomainNameBufLen ] )
-{
-	char *		dst;
-	int			i;
-	
-	dst = outBuffer;
-	for( i = 0; i < 16; ++i )
-	{
-		const unsigned int		octet = inIPv6Addr[ 15 - i ];
-		
-		*dst++ = kHexDigitsLowercase[ octet & 0x0F ];
-		*dst++ = '.';
-		*dst++ = kHexDigitsLowercase[ octet >> 4 ];
-		*dst++ = '.';
-	}
-	memcpy( dst, kIP6ArpaDomainStr, sizeof( kIP6ArpaDomainStr ) );
-	dst += sizeof( kIP6ArpaDomainStr );
-	check( ( dst - outBuffer ) == kReverseIPv6DomainNameBufLen );
-}
-
-//===========================================================================================================================
-//	_WriteReverseIPv4DomainNameString
-//===========================================================================================================================
-
-static void
-	_WriteReverseIPv4DomainNameString(
-		uint32_t	inIPv4Addr,
-		char		outBuffer[ STATIC_PARAM kReverseIPv4DomainNameBufLen ] )
-{
-	SNPrintF( outBuffer, kReverseIPv4DomainNameBufLen, "%u.%u.%u.%u.%s",
-		  inIPv4Addr         & 0xFF,
-		( inIPv4Addr >>  8 ) & 0xFF,
-		( inIPv4Addr >> 16 ) & 0xFF,
-		( inIPv4Addr >> 24 ) & 0xFF, kInAddrArpaDomainStr );
-}
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	_SetDefaultFallbackDNSService
-//===========================================================================================================================
-
-static OSStatus	_SetDefaultFallbackDNSService( const char *inFallbackDNSServiceStr )
-{
-	OSStatus					err;
-	nw_resolver_config_t		resolverConfig;
-	CFDataRef					plistData;
-	
-	if( stricmp_prefix( inFallbackDNSServiceStr, kFallbackDNSServiceArgPrefix_DoH ) == 0 )
-	{
-		nw_endpoint_t			endpoint;
-		const char * const		url = inFallbackDNSServiceStr + sizeof_string( kFallbackDNSServiceArgPrefix_DoH );
-		
-		endpoint = nw_endpoint_create_url( url );
-		require_action( endpoint, exit, err = kUnknownErr );
-		
-		resolverConfig = nw_resolver_config_create_https( endpoint );
-		nw_forget( &endpoint );
-		require_action( resolverConfig, exit, err = kUnknownErr );
-	}
-	else if( stricmp_prefix( inFallbackDNSServiceStr, kFallbackDNSServiceArgPrefix_DoT ) == 0 )
-	{
-		nw_endpoint_t			endpoint;
-		const char * const		hostname = inFallbackDNSServiceStr + sizeof_string( kFallbackDNSServiceArgPrefix_DoT );
-		
-		endpoint = nw_endpoint_create_host( hostname, "0" );
-		require_action( endpoint, exit, err = kUnknownErr );
-		
-		resolverConfig = nw_resolver_config_create_tls( endpoint );
-		nw_forget( &endpoint );
-		require_action( resolverConfig, exit, err = kUnknownErr );
-	}
-	else
-	{
-		FPrintF( stderr, "error: Unrecognized fallback DNS service string: \"%s\"\n", inFallbackDNSServiceStr );
-		err = kParamErr;
-		goto exit;
-	}
-	plistData = nw_resolver_config_copy_plist_data_ref( resolverConfig );
-	require_action( plistData, exit, err = kUnknownErr );
-	
-	err = DNSServiceSetResolverDefaults( CFDataGetBytePtr( plistData ), (size_t) CFDataGetLength( plistData ), true );
-	ForgetCF( &plistData );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-}
-#endif
-
-//===========================================================================================================================
-//	MDNSColliderCreate
-//===========================================================================================================================
-
-typedef enum
-{
-	kMDNSColliderOpCode_Invalid			= 0,
-	kMDNSColliderOpCode_Send			= 1,
-	kMDNSColliderOpCode_Wait			= 2,
-	kMDNSColliderOpCode_SetProbeActions	= 3,
-	kMDNSColliderOpCode_LoopPush		= 4,
-	kMDNSColliderOpCode_LoopPop			= 5,
-	kMDNSColliderOpCode_Exit			= 6
-	
-}	MDNSColliderOpCode;
-
-typedef struct
-{
-	MDNSColliderOpCode		opcode;
-	uint32_t				operand;
-	
-}	MDNSCInstruction;
-
-#define kMaxLoopDepth		16
-
-struct MDNSColliderPrivate
-{
-	CFRuntimeBase					base;							// CF object base.
-	dispatch_queue_t				queue;							// Queue for collider's events.
-	dispatch_source_t				readSourceV4;					// Read dispatch source for IPv4 socket.
-	dispatch_source_t				readSourceV6;					// Read dispatch source for IPv6 socket.
-	SocketRef						sockV4;							// IPv4 UDP socket for mDNS.
-	SocketRef						sockV6;							// IPv6 UDP socket for mDNS.
-	uint8_t *						target;							// Record name being targeted. (malloced)
-	uint8_t *						responsePtr;					// Response message pointer. (malloced)
-	size_t							responseLen;					// Response message length.
-	uint8_t *						probePtr;						// Probe query message pointer. (malloced)
-	size_t							probeLen;						// Probe query message length.
-	unsigned int					probeCount;						// Count of probe queries received for collider's record.
-	uint32_t						probeActionMap;					// Bitmap of actions to take for 
-	MDNSCInstruction *				program;						// Program to execute.
-	uint32_t						pc;								// Program's program counter.
-	uint32_t						loopCounts[ kMaxLoopDepth ];	// Stack of loop counters.
-	uint32_t						loopDepth;						// Current loop depth.
-	dispatch_source_t				waitTimer;						// Timer for program's wait commands.
-	uint32_t						interfaceIndex;					// Interface over which to send and receive mDNS msgs.
-	MDNSColliderStopHandler_f		stopHandler;					// User's stop handler.
-	void *							stopContext;					// User's stop handler context.
-	MDNSColliderProtocols			protocols;						// Protocols to use, i.e., IPv4, IPv6.
-	Boolean							stopped;						// True if the collider has been stopped.
-	uint8_t							msgBuf[ kMDNSMessageSizeMax ];	// mDNS message buffer.
-};
-
-static void		_MDNSColliderStop( MDNSColliderRef inCollider, OSStatus inError );
-static void		_MDNSColliderReadHandler( void *inContext );
-static void		_MDNSColliderExecuteProgram( void *inContext );
-static OSStatus	_MDNSColliderSendResponse( MDNSColliderRef inCollider, SocketRef inSock, const struct sockaddr *inDest );
-static OSStatus	_MDNSColliderSendProbe( MDNSColliderRef inCollider, SocketRef inSock, const struct sockaddr *inDest );
-
-CF_CLASS_DEFINE( MDNSCollider );
-
-ulog_define_ex( kDNSSDUtilIdentifier, MDNSCollider, kLogLevelInfo, kLogFlags_None, "MDNSCollider", NULL );
-#define mc_ulog( LEVEL, ... )		ulog( &log_category_from_name( MDNSCollider ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus	MDNSColliderCreate( dispatch_queue_t inQueue, MDNSColliderRef *outCollider )
-{
-	OSStatus			err;
-	MDNSColliderRef		obj = NULL;
-	
-	CF_OBJECT_CREATE( MDNSCollider, obj, err, exit );
-	
-	ReplaceDispatchQueue( &obj->queue, inQueue );
-	obj->sockV4 = kInvalidSocketRef;
-	obj->sockV6 = kInvalidSocketRef;
-	
-	*outCollider = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSColliderFinalize
-//===========================================================================================================================
-
-static void	_MDNSColliderFinalize( CFTypeRef inObj )
-{
-	MDNSColliderRef const		me = (MDNSColliderRef) inObj;
-	
-	check( !me->waitTimer );
-	check( !me->readSourceV4 );
-	check( !me->readSourceV6 );
-	check( !IsValidSocket( me->sockV4 ) );
-	check( !IsValidSocket( me->sockV6 ) );
-	ForgetMem( &me->target );
-	ForgetMem( &me->responsePtr );
-	ForgetMem( &me->probePtr );
-	ForgetMem( &me->program );
-	dispatch_forget( &me->queue );
-}
-
-//===========================================================================================================================
-//	MDNSColliderStart
-//===========================================================================================================================
-
-static void	_MDNSColliderStart( void *inContext );
-
-static OSStatus	MDNSColliderStart( MDNSColliderRef me )
-{
-	OSStatus		err;
-	
-	require_action_quiet( me->target,         exit, err = kNotPreparedErr );
-	require_action_quiet( me->responsePtr,    exit, err = kNotPreparedErr );
-	require_action_quiet( me->probePtr,       exit, err = kNotPreparedErr );
-	require_action_quiet( me->program,        exit, err = kNotPreparedErr );
-	require_action_quiet( me->interfaceIndex, exit, err = kNotPreparedErr );
-	require_action_quiet( me->protocols,      exit, err = kNotPreparedErr );
-	
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _MDNSColliderStart );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-static void	_MDNSColliderStart( void *inContext )
-{
-	OSStatus					err;
-	MDNSColliderRef const		me		= (MDNSColliderRef) inContext;
-	SocketRef					sock	= kInvalidSocketRef;
-	SocketContext *				sockCtx	= NULL;
-	
-	if( me->protocols & kMDNSColliderProtocol_IPv4 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV4(), kMDNSPort, NULL, me->interfaceIndex, true, NULL, &sock );
-		require_noerr( err, exit );
-		
-		sockCtx = SocketContextCreate( sock, me, &err );
-		require_noerr( err, exit );
-		sock = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, me->queue, _MDNSColliderReadHandler, SocketContextCancelHandler,
-			sockCtx, &me->readSourceV4 );
-		require_noerr( err, exit );
-		me->sockV4 = sockCtx->sock;
-		sockCtx = NULL;
-		
-		dispatch_resume( me->readSourceV4 );
-	}
-	
-	if( me->protocols & kMDNSColliderProtocol_IPv6 )
-	{
-		err = CreateMulticastSocket( GetMDNSMulticastAddrV6(), kMDNSPort, NULL, me->interfaceIndex, true, NULL, &sock );
-		require_noerr( err, exit );
-		
-		sockCtx = SocketContextCreate( sock, me, &err );
-		require_noerr( err, exit );
-		sock = kInvalidSocketRef;
-		
-		err = DispatchReadSourceCreate( sockCtx->sock, me->queue, _MDNSColliderReadHandler, SocketContextCancelHandler,
-			sockCtx, &me->readSourceV6 );
-		require_noerr( err, exit );
-		me->sockV6 = sockCtx->sock;
-		sockCtx = NULL;
-		
-		dispatch_resume( me->readSourceV6 );
-	}
-	
-	_MDNSColliderExecuteProgram( me );
-	err = kNoErr;
-	
-exit:
-	ForgetSocket( &sock );
-	ForgetSocketContext( &sockCtx );
-	if( err ) _MDNSColliderStop( me, err );
-}
-
-//===========================================================================================================================
-//	MDNSColliderStop
-//===========================================================================================================================
-
-static void	_MDNSColliderUserStop( void *inContext );
-
-static void	MDNSColliderStop( MDNSColliderRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _MDNSColliderUserStop );
-}
-
-static void	_MDNSColliderUserStop( void *inContext )
-{
-	MDNSColliderRef const		me = (MDNSColliderRef) inContext;
-	
-	_MDNSColliderStop( me, kCanceledErr );
-	CFRelease( me );
-}
-
-//===========================================================================================================================
-//	MDNSColliderSetProtocols
-//===========================================================================================================================
-
-static void	MDNSColliderSetProtocols( MDNSColliderRef me, MDNSColliderProtocols inProtocols )
-{
-	me->protocols = inProtocols;
-}
-
-//===========================================================================================================================
-//	MDNSColliderSetInterfaceIndex
-//===========================================================================================================================
-
-static void	MDNSColliderSetInterfaceIndex( MDNSColliderRef me, uint32_t inInterfaceIndex )
-{
-	me->interfaceIndex = inInterfaceIndex;
-}
-
-//===========================================================================================================================
-//	MDNSColliderSetProgram
-//===========================================================================================================================
-
-#define kMDNSColliderProgCmd_Done		"done"
-#define kMDNSColliderProgCmd_Loop		"loop"
-#define kMDNSColliderProgCmd_Send		"send"
-#define kMDNSColliderProgCmd_Probes		"probes"
-#define kMDNSColliderProgCmd_Wait		"wait"
-
-typedef uint32_t		MDNSColliderProbeAction;
-
-#define kMDNSColliderProbeAction_None					0
-#define kMDNSColliderProbeAction_Respond				1
-#define kMDNSColliderProbeAction_RespondUnicast			2
-#define kMDNSColliderProbeAction_RespondMulticast		3
-#define kMDNSColliderProbeAction_Probe					4
-#define kMDNSColliderProbeAction_MaxValue				kMDNSColliderProbeAction_Probe
-
-#define kMDNSColliderProbeActionBits_Count			3
-#define kMDNSColliderProbeActionBits_Mask			( ( 1U << kMDNSColliderProbeActionBits_Count ) - 1 )
-#define kMDNSColliderProbeActionMaxProbeCount		( 32 / kMDNSColliderProbeActionBits_Count )
-
-check_compile_time( kMDNSColliderProbeAction_MaxValue <= kMDNSColliderProbeActionBits_Mask );
-
-static OSStatus	_MDNSColliderParseProbeActionString( const char *inString, size_t inLen, uint32_t *outBitmap );
-
-static OSStatus	MDNSColliderSetProgram( MDNSColliderRef me, const char *inProgramStr )
-{
-	OSStatus				err;
-	uint32_t				insCount;
-	unsigned int			loopDepth;
-	const char *			cmd;
-	const char *			end;
-	const char *			next;
-	MDNSCInstruction *		program = NULL;
-	uint32_t				loopStart[ kMaxLoopDepth ];
-	
-	insCount = 0;
-	for( cmd = inProgramStr; *cmd; cmd = next )
-	{
-		for( end = cmd; *end && ( *end != ';' ); ++end ) {}
-		require_action_quiet( end != cmd, exit, err = kMalformedErr );
-		next = ( *end == ';' ) ? ( end + 1 ) : end;
-		++insCount;
-	}
-	
-	program = (MDNSCInstruction *) calloc( insCount + 1, sizeof( *program ) );
-	require_action( program, exit, err = kNoMemoryErr );
-	
-	insCount	= 0;
-	loopDepth	= 0;
-	for( cmd = inProgramStr; *cmd; cmd = next )
-	{
-		size_t							cmdLen;
-		const char *					ptr;
-		const char *					arg;
-		size_t							argLen;
-		uint32_t						value;
-		MDNSCInstruction * const		ins = &program[ insCount ];
-		
-		while( isspace_safe( *cmd ) ) ++cmd;
-		for( end = cmd; *end && ( *end != ';' ); ++end ) {}
-		next = ( *end == ';' ) ? ( end + 1 ) : end;
-		
-		for( ptr = cmd; ( ptr < end ) && !isspace_safe( *ptr ); ++ptr ) {}
-		cmdLen = (size_t)( ptr - cmd );
-		
-		// Done statement
-		
-		if( strnicmpx( cmd, cmdLen, kMDNSColliderProgCmd_Done ) == 0 )
-		{
-			while( ( ptr < end ) && isspace_safe( *ptr ) ) ++ptr;
-			require_action_quiet( ptr == end, exit, err = kMalformedErr );
-			
-			require_action_quiet( loopDepth > 0, exit, err = kMalformedErr );
-			
-			ins->opcode		= kMDNSColliderOpCode_LoopPop;
-			ins->operand	= loopStart[ --loopDepth ];
-		}
-		
-		// Loop command
-		
-		else if( strnicmpx( cmd, cmdLen, kMDNSColliderProgCmd_Loop ) == 0 )
-		{
-			for( arg = ptr; ( arg < end ) && isspace_safe( *arg ); ++arg ) {}
-			err = DecimalTextToUInt32( arg, end, &value, &ptr );
-			require_noerr_quiet( err, exit );
-			require_action_quiet( value > 0, exit, err = kValueErr );
-			
-			while( ( ptr < end ) && isspace_safe( *ptr ) ) ++ptr;
-			require_action_quiet( ptr == end, exit, err = kMalformedErr );
-			
-			ins->opcode 	= kMDNSColliderOpCode_LoopPush;
-			ins->operand	= value;
-			
-			require_action_quiet( loopDepth < kMaxLoopDepth, exit, err = kNoSpaceErr );
-			loopStart[ loopDepth++ ] = insCount + 1;
-		}
-		
-		// Probes command
-		
-		else if( strnicmpx( cmd, cmdLen, kMDNSColliderProgCmd_Probes ) == 0 )
-		{
-			for( arg = ptr; ( arg < end ) &&  isspace_safe( *arg ); ++arg ) {}
-			for( ptr = arg; ( ptr < end ) && !isspace_safe( *ptr ); ++ptr ) {}
-			argLen = (size_t)( ptr - arg );
-			if( argLen > 0 )
-			{
-				err = _MDNSColliderParseProbeActionString( arg, argLen, &value );
-				require_noerr_quiet( err, exit );
-			}
-			else
-			{
-				value = 0;
-			}
-			
-			while( ( ptr < end ) && isspace_safe( *ptr ) ) ++ptr;
-			require_action_quiet( ptr == end, exit, err = kMalformedErr );
-			
-			ins->opcode 	= kMDNSColliderOpCode_SetProbeActions;
-			ins->operand	= value;
-		}
-		
-		// Send command
-		
-		else if( strnicmpx( cmd, cmdLen, kMDNSColliderProgCmd_Send ) == 0 )
-		{
-			while( ( ptr < end ) && isspace_safe( *ptr ) ) ++ptr;
-			require_action_quiet( ptr == end, exit, err = kMalformedErr );
-			
-			ins->opcode = kMDNSColliderOpCode_Send;
-		}
-		
-		// Wait command
-		
-		else if( strnicmpx( cmd, cmdLen, kMDNSColliderProgCmd_Wait ) == 0 )
-		{
-			for( arg = ptr; ( arg < end ) && isspace_safe( *arg ); ++arg ) {}
-			err = DecimalTextToUInt32( arg, end, &value, &ptr );
-			require_noerr_quiet( err, exit );
-			
-			while( ( ptr < end ) && isspace_safe( *ptr ) ) ++ptr;
-			require_action_quiet( ptr == end, exit, err = kMalformedErr );
-			
-			ins->opcode		= kMDNSColliderOpCode_Wait;
-			ins->operand	= value;
-		}
-		
-		// Unrecognized command
-		
-		else
-		{
-			err = kCommandErr;
-			goto exit;
-		}
-		++insCount;
-	}
-	require_action_quiet( loopDepth == 0, exit, err = kMalformedErr );
-	
-	program[ insCount ].opcode = kMDNSColliderOpCode_Exit;
-	
-	FreeNullSafe( me->program );
-	me->program = program;
-	program = NULL;
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( program );
-	return( err );
-}
-
-static OSStatus	_MDNSColliderParseProbeActionString( const char *inString, size_t inLen, uint32_t *outBitmap )
-{
-	OSStatus				err;
-	const char *			ptr;
-	const char * const		end = &inString[ inLen ];
-	uint32_t				bitmap;
-	int						index;
-	
-	bitmap	= 0;
-	index	= 0;
-	ptr		= inString;
-	while( ptr < end )
-	{
-		int							c, count;
-		MDNSColliderProbeAction		action;
-		
-		c = *ptr++;
-		if( isdigit_safe( c ) )
-		{
-			count = 0;
-			do
-			{
-				count = ( count * 10 ) + ( c - '0' );
-				require_action_quiet( count <= ( kMDNSColliderProbeActionMaxProbeCount - index ), exit, err = kCountErr );
-				require_action_quiet( ptr < end, exit, err = kUnderrunErr );
-				c = *ptr++;
-				
-			}	while( isdigit_safe( c ) );
-			require_action_quiet( count > 0, exit, err = kCountErr );
-		}
-		else
-		{
-			require_action_quiet( index < kMDNSColliderProbeActionMaxProbeCount, exit, err = kMalformedErr );
-			count = 1;
-		}
-		
-		switch( c )
-		{
-			case 'n':	action = kMDNSColliderProbeAction_None;				break;
-			case 'r':	action = kMDNSColliderProbeAction_Respond;			break;
-			case 'u':	action = kMDNSColliderProbeAction_RespondUnicast;	break;
-			case 'm':	action = kMDNSColliderProbeAction_RespondMulticast;	break;
-			case 'p':	action = kMDNSColliderProbeAction_Probe;			break;
-			default:	err = kMalformedErr;								goto exit;
-		}
-		if( ptr < end )
-		{
-			c = *ptr++;
-			require_action_quiet( ( c == '-' ) && ( ptr < end ), exit, err = kMalformedErr );
-		}
-		while( count-- > 0 )
-		{
-			bitmap |= ( action << ( index * kMDNSColliderProbeActionBits_Count ) );
-			++index;
-		}
-	}
-	
-	*outBitmap = bitmap;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	MDNSColliderSetStopHandler
-//===========================================================================================================================
-
-static void	MDNSColliderSetStopHandler( MDNSColliderRef me, MDNSColliderStopHandler_f inStopHandler, void *inStopContext )
-{
-	me->stopHandler = inStopHandler;
-	me->stopContext = inStopContext;
-}
-
-//===========================================================================================================================
-//	MDNSColliderSetRecord
-//===========================================================================================================================
-
-#define kMDNSColliderDummyStr			"\x16" "mdnscollider-sent-this" "\x05" "local"
-#define kMDNSColliderDummyName			( (const uint8_t *) kMDNSColliderDummyStr )
-#define kMDNSColliderDummyNameLen		sizeof( kMDNSColliderDummyStr )
-
-static OSStatus
-	MDNSColliderSetRecord(
-		MDNSColliderRef	me,
-		const uint8_t *	inName,
-		uint16_t		inType,
-		const void *	inRDataPtr,
-		size_t			inRDataLen )
-{
-	OSStatus		err;
-	DataBuffer		msgDB;
-	DNSHeader		header;
-	uint8_t *		targetPtr	= NULL;
-	size_t			targetLen;
-	uint8_t *		responsePtr	= NULL;
-	size_t			responseLen;
-	uint8_t *		probePtr	= NULL;
-	size_t			probeLen;
-	
-	DataBuffer_Init( &msgDB, NULL, 0, kMDNSMessageSizeMax );
-	
-	err = DomainNameDup( inName, &targetPtr, &targetLen );
-	require_noerr_quiet( err, exit );
-	
-	// Create response message.
-	
-	memset( &header, 0, sizeof( header ) );
-	DNSHeaderSetFlags( &header, kDNSHeaderFlag_Response | kDNSHeaderFlag_AuthAnswer );
-	DNSHeaderSetAnswerCount( &header, 1 );
-	
-	err = DataBuffer_Append( &msgDB, &header, sizeof( header ) );
-	require_noerr( err, exit );
-	
-	err = _DataBuffer_AppendDNSRecord( &msgDB, targetPtr, targetLen, inType, kDNSServiceClass_IN | kMDNSClassCacheFlushBit,
-		1976, inRDataPtr, inRDataLen );
-	require_noerr( err, exit );
-	
-	err = DataBuffer_Detach( &msgDB, &responsePtr, &responseLen );
-	require_noerr( err, exit );
-	
-	// Create probe message.
-	
-	memset( &header, 0, sizeof( header ) );
-	DNSHeaderSetQuestionCount( &header, 2 );
-	DNSHeaderSetAuthorityCount( &header, 1 );
-	
-	err = DataBuffer_Append( &msgDB, &header, sizeof( header ) );
-	require_noerr( err, exit );
-	
-	err = _DataBuffer_AppendDNSQuestion( &msgDB, targetPtr, targetLen, kDNSServiceType_ANY, kDNSServiceClass_IN );
-	require_noerr( err, exit );
-	
-	err = _DataBuffer_AppendDNSQuestion( &msgDB, kMDNSColliderDummyName, kMDNSColliderDummyNameLen,
-		kDNSServiceType_NULL, kDNSServiceClass_IN );
-	require_noerr( err, exit );
-	
-	err = _DataBuffer_AppendDNSRecord( &msgDB, targetPtr, targetLen, inType, kDNSServiceClass_IN,
-		1976, inRDataPtr, inRDataLen );
-	require_noerr( err, exit );
-	
-	err = DataBuffer_Detach( &msgDB, &probePtr, &probeLen );
-	require_noerr( err, exit );
-	
-	FreeNullSafe( me->target );
-	me->target = targetPtr;
-	targetPtr = NULL;
-	
-	FreeNullSafe( me->responsePtr );
-	me->responsePtr = responsePtr;
-	me->responseLen = responseLen;
-	responsePtr = NULL;
-	
-	FreeNullSafe( me->probePtr );
-	me->probePtr = probePtr;
-	me->probeLen = probeLen;
-	probePtr = NULL;
-	
-exit:
-	DataBuffer_Free( &msgDB );
-	FreeNullSafe( targetPtr );
-	FreeNullSafe( responsePtr );
-	FreeNullSafe( probePtr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSColliderStop
-//===========================================================================================================================
-
-static void	_MDNSColliderStop( MDNSColliderRef me, OSStatus inError )
-{
-	dispatch_source_forget( &me->waitTimer );
-	dispatch_source_forget( &me->readSourceV4 );
-	dispatch_source_forget( &me->readSourceV6 );
-	me->sockV4 = kInvalidSocketRef;
-	me->sockV6 = kInvalidSocketRef;
-	
-	if( !me->stopped )
-	{
-		me->stopped = true;
-		if( me->stopHandler ) me->stopHandler( me->stopContext, inError );
-		CFRelease( me );
-	}
-}
-
-//===========================================================================================================================
-//	_MDNSColliderReadHandler
-//===========================================================================================================================
-
-static MDNSColliderProbeAction	_MDNSColliderGetProbeAction( uint32_t inBitmap, unsigned int inProbeNumber );
-static const char *				_MDNSColliderProbeActionToString( MDNSColliderProbeAction inAction );
-
-static void	_MDNSColliderReadHandler( void *inContext )
-{
-	OSStatus					err;
-	struct timeval				now;
-	SocketContext * const		sockCtx	= (SocketContext *) inContext;
-	MDNSColliderRef const		me		= (MDNSColliderRef) sockCtx->userContext;
-	size_t						msgLen;
-	sockaddr_ip					sender;
-	const DNSHeader *			hdr;
-	const uint8_t *				ptr;
-	const struct sockaddr *		dest;
-	int							probeFound, probeIsQU;
-	unsigned int				qCount, i;
-	MDNSColliderProbeAction		action;
-	
-	gettimeofday( &now, NULL );
-	
-	err = SocketRecvFrom( sockCtx->sock, me->msgBuf, sizeof( me->msgBuf ), &msgLen, &sender, sizeof( sender ),
-		NULL, NULL, NULL, NULL );
-	require_noerr( err, exit );
-	
-	require_quiet( msgLen >= kDNSHeaderLength, exit );
-	hdr = (const DNSHeader *) me->msgBuf;
-	
-	probeFound	= false;
-	probeIsQU	= false;
-	qCount = DNSHeaderGetQuestionCount( hdr );
-	ptr = (const uint8_t *) &hdr[ 1 ];
-	for( i = 0; i < qCount; ++i )
-	{
-		uint16_t		qtype, qclass;
-		uint8_t			qname[ kDomainNameLengthMax ];
-		
-		err = DNSMessageExtractQuestion( me->msgBuf, msgLen, ptr, qname, &qtype, &qclass, &ptr );
-		require_noerr_quiet( err, exit );
-		
-		if( ( qtype == kDNSServiceType_NULL ) && ( qclass == kDNSServiceClass_IN ) &&
-			DomainNameEqual( qname, kMDNSColliderDummyName ) )
-		{
-			probeFound = false;
-			break;
-		}
-		
-		if( qtype != kDNSServiceType_ANY ) continue;
-		if( ( qclass & ~kMDNSClassUnicastResponseBit ) != kDNSServiceClass_IN ) continue;
-		if( !DomainNameEqual( qname, me->target ) ) continue;
-		
-		if( !probeFound )
-		{
-			probeFound	= true;
-			probeIsQU	= ( qclass & kMDNSClassUnicastResponseBit ) ? true : false;
-		}
-	}
-	require_quiet( probeFound, exit );
-	
-	++me->probeCount;
-	action = _MDNSColliderGetProbeAction( me->probeActionMap, me->probeCount );
-	
-	mc_ulog( kLogLevelInfo, "Received probe from %##a at %{du:time} (action: %s) -- %#.1{du:dnsmsg}\n",
-		&sender, &now, _MDNSColliderProbeActionToString( action ), me->msgBuf, msgLen );
-	
-	if( ( action == kMDNSColliderProbeAction_Respond )			||
-		( action == kMDNSColliderProbeAction_RespondUnicast )	||
-		( action == kMDNSColliderProbeAction_RespondMulticast ) )
-	{
-		if( ( ( action == kMDNSColliderProbeAction_Respond ) && probeIsQU ) ||
-			(   action == kMDNSColliderProbeAction_RespondUnicast ) )
-		{
-			dest = &sender.sa;
-		}
-		else if( ( ( action == kMDNSColliderProbeAction_Respond ) && !probeIsQU ) ||
-				 (   action == kMDNSColliderProbeAction_RespondMulticast ) )
-		{
-			dest = ( sender.sa.sa_family == AF_INET ) ? GetMDNSMulticastAddrV4() : GetMDNSMulticastAddrV6();
-		}
-		
-		err = _MDNSColliderSendResponse( me, sockCtx->sock, dest );
-		require_noerr( err, exit );
-	}
-	else if( action == kMDNSColliderProbeAction_Probe )
-	{
-		dest = ( sender.sa.sa_family == AF_INET ) ? GetMDNSMulticastAddrV4() : GetMDNSMulticastAddrV6();
-		
-		err = _MDNSColliderSendProbe( me, sockCtx->sock, dest );
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return;
-}
-
-static MDNSColliderProbeAction	_MDNSColliderGetProbeAction( uint32_t inBitmap, unsigned int inProbeNumber )
-{
-	MDNSColliderProbeAction		action;
-	
-	if( ( inProbeNumber >= 1 ) && ( inProbeNumber <= kMDNSColliderProbeActionMaxProbeCount ) )
-	{
-		action = ( inBitmap >> ( ( inProbeNumber - 1 ) * kMDNSColliderProbeActionBits_Count ) ) &
-			kMDNSColliderProbeActionBits_Mask;
-	}
-	else
-	{
-		action = kMDNSColliderProbeAction_None;
-	}
-	return( action );
-}
-
-static const char *	_MDNSColliderProbeActionToString( MDNSColliderProbeAction inAction )
-{
-	switch( inAction )
-	{
-		case kMDNSColliderProbeAction_None:				return( "None" );
-		case kMDNSColliderProbeAction_Respond:			return( "Respond" );
-		case kMDNSColliderProbeAction_RespondUnicast:	return( "Respond (unicast)" );
-		case kMDNSColliderProbeAction_RespondMulticast:	return( "Respond (multicast)" );
-		case kMDNSColliderProbeAction_Probe:			return( "Probe" );
-		default:										return( "???" );
-	}
-}
-
-//===========================================================================================================================
-//	_MDNSColliderExecuteProgram
-//===========================================================================================================================
-
-static void	_MDNSColliderExecuteProgram( void *inContext )
-{
-	OSStatus					err;
-	MDNSColliderRef const		me = (MDNSColliderRef) inContext;
-	int							stop;
-	
-	dispatch_forget( &me->waitTimer );
-	
-	stop = false;
-	for( ;; )
-	{
-		const MDNSCInstruction * const		ins = &me->program[ me->pc++ ];
-		uint32_t							waitMs;
-		
-		switch( ins->opcode )
-		{
-			case kMDNSColliderOpCode_Send:
-				if( IsValidSocket( me->sockV4 ) )
-				{
-					err = _MDNSColliderSendResponse( me, me->sockV4, GetMDNSMulticastAddrV4() );
-					require_noerr( err, exit );
-				}
-				if( IsValidSocket( me->sockV6 ) )
-				{
-					err = _MDNSColliderSendResponse( me, me->sockV6, GetMDNSMulticastAddrV6() );
-					require_noerr( err, exit );
-				}
-				break;
-			
-			case kMDNSColliderOpCode_Wait:
-				waitMs = ins->operand;
-				if( waitMs > 0 )
-				{
-					err = DispatchTimerOneShotCreate( dispatch_time_milliseconds( waitMs ), 1, me->queue,
-						_MDNSColliderExecuteProgram, me, &me->waitTimer );
-					require_noerr( err, exit );
-					dispatch_resume( me->waitTimer );
-					goto exit;
-				}
-				break;
-			
-			case kMDNSColliderOpCode_SetProbeActions:
-				me->probeCount		= 0;
-				me->probeActionMap	= ins->operand;
-				break;
-			
-			case kMDNSColliderOpCode_LoopPush:
-				check( me->loopDepth < kMaxLoopDepth );
-				me->loopCounts[ me->loopDepth++ ] = ins->operand;
-				break;
-			
-			case kMDNSColliderOpCode_LoopPop:
-				check( me->loopDepth > 0 );
-				if( --me->loopCounts[ me->loopDepth - 1 ] > 0 )
-				{
-					me->pc = ins->operand;
-				}
-				else
-				{
-					--me->loopDepth;
-				}
-				break;
-			
-			case kMDNSColliderOpCode_Exit:
-				stop = true;
-				err	= kNoErr;
-				goto exit;
-			
-			default:
-				dlogassert( "Unhandled opcode %u\n", ins->opcode );
-				err = kCommandErr;
-				goto exit;
-		}
-	}
-	
-exit:
-	if( err || stop ) _MDNSColliderStop( me, err );
-}
-
-//===========================================================================================================================
-//	_MDNSColliderSendResponse
-//===========================================================================================================================
-
-static OSStatus	_MDNSColliderSendResponse( MDNSColliderRef me, SocketRef inSock, const struct sockaddr *inDest )
-{
-	OSStatus		err;
-	ssize_t			n;
-	
-	n = sendto( inSock, (char *) me->responsePtr, me->responseLen, 0, inDest, SockAddrGetSize( inDest ) );
-	err = map_socket_value_errno( inSock, n == (ssize_t) me->responseLen, n );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_MDNSColliderSendProbe
-//===========================================================================================================================
-
-static OSStatus	_MDNSColliderSendProbe( MDNSColliderRef me, SocketRef inSock, const struct sockaddr *inDest )
-{
-	OSStatus		err;
-	ssize_t			n;
-	
-	n = sendto( inSock, (char *) me->probePtr, me->probeLen, 0, inDest, SockAddrGetSize( inDest ) );
-	err = map_socket_value_errno( inSock, n == (ssize_t) me->probeLen, n );
-	return( err );
-}
-
-//===========================================================================================================================
-//	ServiceBrowserCreate
-//===========================================================================================================================
-
-typedef struct SBDomain					SBDomain;
-typedef struct SBServiceType			SBServiceType;
-typedef struct SBServiceBrowse			SBServiceBrowse;
-typedef struct SBServiceInstance		SBServiceInstance;
-typedef struct SBIPAddress				SBIPAddress;
-
-struct ServiceBrowserPrivate
-{
-	CFRuntimeBase					base;				// CF object base.
-	dispatch_queue_t				queue;				// Queue for service browser's events.
-	DNSServiceRef					connection;			// Shared connection for DNS-SD ops.
-	DNSServiceRef					domainsQuery;		// Query for recommended browsing domains.
-	char *							domain;				// If non-null, then browsing is limited to this domain.
-	StringListItem *				serviceTypeList;	// If non-null, then browsing is limited to these service types.
-	ServiceBrowserCallback_f		userCallback;		// User's callback. Called when browsing stops.
-	void *							userContext;		// User's callback context.
-	SBDomain *						domainList;			// List of domains and their browse results.
-	dispatch_source_t				stopTimer;			// Timer to stop browsing after browseTimeSecs.
-	uint32_t						ifIndex;			// If non-zero, then browsing is limited to this interface.
-	unsigned int					browseTimeSecs;		// Amount of time to spend browsing in seconds.
-#if( MDNSRESPONDER_PROJECT )
-	Boolean							useNewGAI;			// Use dnssd_getaddrinfo_* instead of DNSServiceGetAddrInfo().
-#endif
-	Boolean							includeAWDL;		// True if the IncludeAWDL flag should be used for DNS-SD ops that
-														// use the "any" interface.
-	Boolean							validateResults;	// Validate results.
-};
-
-struct SBDomain
-{
-	SBDomain *				next;			// Next domain object in list.
-	ServiceBrowserRef		browser;		// Pointer to parent service browser.
-	char *					name;			// Name of the domain.
-	DNSServiceRef			servicesQuery;	// Query for services (_services._dns-sd._udp.<domain> PTR record) in domain.
-	SBServiceType *			typeList;		// List of service types to browse for in this domain.
-};
-
-struct SBServiceType
-{
-	SBServiceType *			next;		// Next service type object in list.
-	char *					name;		// Name of the service type.
-	SBServiceBrowse *		browseList;	// List of browses for this service type.
-};
-
-struct SBServiceBrowse
-{
-	SBServiceBrowse *		next;			// Next browse object in list.
-	ServiceBrowserRef		browser;		// Pointer to parent service browser.
-	DNSServiceRef			browse;			// Reference to DNSServiceBrowse op.
-	SBServiceInstance *		instanceList;	// List of service instances that were discovered by this browse.
-	uint64_t				startTicks;		// Value of UpTicks() when the browse op began.
-	uint32_t				ifIndex;		// If non-zero, then the browse is limited to this interface.
-};
-
-struct SBServiceInstance
-{
-	SBServiceInstance *		next;				// Next service instance object in list.
-	ServiceBrowserRef		browser;			// Pointer to parent service browser.
-	char *					name;				// Name of the service instance.
-	char *					fqdn;				// Fully qualified domain name of service instance (for logging/debugging).
-	uint32_t				ifIndex;			// Index of interface over which this service instance was discovered.
-	uint64_t				discoverTimeUs;		// Time it took to discover this service instance in microseconds.
-	DNSServiceRef			resolve;			// Reference to DNSServiceResolve op for this service instance.
-	uint64_t				resolveStartTicks;	// Value of UpTicks() when the DNSServiceResolve op began.
-	uint64_t				resolveTimeUs;		// Time it took to resolve this service instance.
-	char *					hostname;			// Service instance's hostname. Result of DNSServiceResolve.
-	uint16_t				port;				// Service instance's port number. Result of DNSServiceResolve.
-	uint8_t *				txtPtr;				// Service instance's TXT record data. Result of DNSServiceResolve.
-	size_t					txtLen;				// Length of service instance's TXT record data.
-	DNSServiceRef			gai;				// Reference to DNSServiceGetAddrInfo op for service instance's hostname.
-#if( MDNSRESPONDER_PROJECT )
-	dnssd_getaddrinfo_t		newGAI;				// Reference to dnssd_getaddrinfo object for service instance's hostname.
-#endif
-	uint64_t				gaiStartTicks;		// Value of UpTicks() when the DNSServiceGetAddrInfo op began.
-	SBIPAddress *			ipaddrList;			// List of IP addresses that the hostname resolved to.
-	int32_t					refCount;			// This object's reference count.
-};
-
-struct SBIPAddress
-{
-	SBIPAddress *		next;			// Next IP address object in list.
-	sockaddr_ip			sip;			// IPv4 or IPv6 address.
-	uint64_t			resolveTimeUs;	// Time it took to resolve this IP address in microseconds.
-	Boolean				validated;		// True if IP address is validated.
-};
-
-typedef struct
-{
-	SBRDomain *		domainList;	// List of domains in which services were found.
-	int32_t			refCount;	// This object's reference count.
-	
-}	ServiceBrowserResultsPrivate;
-
-static void		_ServiceBrowserStop( ServiceBrowserRef me, OSStatus inError );
-static OSStatus	_ServiceBrowserAddDomain( ServiceBrowserRef inBrowser, const char *inDomain );
-static OSStatus	_ServiceBrowserRemoveDomain( ServiceBrowserRef inBrowser, const char *inName );
-static void		_ServiceBrowserTimerHandler( void *inContext );
-static void DNSSD_API
-	_ServiceBrowserDomainsQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void DNSSD_API
-	_ServiceBrowserServicesQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext );
-static void DNSSD_API
-	_ServiceBrowserBrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inRegType,
-		const char *		inDomain,
-		void *				inContext );
-static void DNSSD_API
-	_ServiceBrowserResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext );
-#if( MDNSRESPONDER_PROJECT )
-static void
-	_ServiceBrowserGAIResultHandler(
-		ServiceBrowserRef				inBrowser,
-		SBServiceInstance *				inInstance,
-		dnssd_getaddrinfo_result_t *	inResultArray,
-		size_t							inResultCount );
-#endif
-static void DNSSD_API
-	_ServiceBrowserGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext );
-static OSStatus
-	_ServiceBrowserAddServiceType(
-		ServiceBrowserRef	inBrowser,
-		SBDomain *			inDomain,
-		const char *		inName,
-		uint32_t			inIfIndex );
-static OSStatus
-	_ServiceBrowserRemoveServiceType(
-		ServiceBrowserRef	inBrowser,
-		SBDomain *			inDomain,
-		const char *		inName,
-		uint32_t			inIfIndex );
-static OSStatus
-	_ServiceBrowserAddServiceInstance(
-		ServiceBrowserRef			inBrowser,
-		SBServiceBrowse *			inBrowse,
-		uint32_t					inIfIndex,
-		const char *				inName,
-		const char *				inRegType,
-		const char *				inDomain,
-		uint64_t					inDiscoverTimeUs,
-		const DNSServiceAttribute *	inAttr );
-static OSStatus
-	_ServiceBrowserRemoveServiceInstance(
-		ServiceBrowserRef	inBrowser,
-		SBServiceBrowse *	inBrowse,
-		const char *		inName,
-		uint32_t			inIfIndex );
-static OSStatus
-	_ServiceBrowserAddIPAddress(
-		ServiceBrowserRef		inBrowser,
-		SBServiceInstance *		inInstance,
-		const struct sockaddr *	inSockAddr,
-		uint64_t				inResolveTimeUs,
-		Boolean					inValidated );
-static OSStatus
-	_ServiceBrowserRemoveIPAddress(
-		ServiceBrowserRef		inBrowser,
-		SBServiceInstance *		inInstance,
-		const struct sockaddr *	inSockAddr );
-static OSStatus	_ServiceBrowserCreateResults( ServiceBrowserRef me, ServiceBrowserResults **outResults );
-static OSStatus	_SBDomainCreate( const char *inName, ServiceBrowserRef inBrowser, SBDomain **outDomain );
-static void		_SBDomainFree( SBDomain *inDomain );
-static OSStatus	_SBServiceTypeCreate( const char *inName, SBServiceType **outType );
-static void		_SBServiceTypeFree( SBServiceType *inType );
-static OSStatus	_SBServiceBrowseCreate( uint32_t inIfIndex, ServiceBrowserRef inBrowser, SBServiceBrowse **outBrowse );
-static void		_SBServiceBrowseFree( SBServiceBrowse *inBrowse );
-static OSStatus
-	_SBServiceInstanceCreate(
-		const char *			inName,
-		const char *			inType,
-		const char *			inDomain,
-		uint32_t				inIfIndex,
-		uint64_t				inDiscoverTimeUs,
-		ServiceBrowserRef		inBrowser,
-		SBServiceInstance **	outInstance );
-#if( MDNSRESPONDER_PROJECT )
-static void		_SBServiceInstanceRetain( SBServiceInstance *inInstance );
-#endif
-static void		_SBServiceInstanceStop( SBServiceInstance *inInstance );
-static void		_SBServiceInstanceRelease( SBServiceInstance *inInstance );
-#define _SBServiceInstanceForget( X )		ForgetCustomEx( X, _SBServiceInstanceStop, _SBServiceInstanceRelease )
-static OSStatus
-	_SBIPAddressCreate(
-		const struct sockaddr *	inSockAddr,
-		uint64_t				inResolveTimeUs,
-		Boolean 				inValidated,
-		SBIPAddress **			outIPAddress );
-static void		_SBIPAddressFree( SBIPAddress *inIPAddress );
-static void		_SBIPAddressFreeList( SBIPAddress *inList );
-static OSStatus	_SBRDomainCreate( const char *inName, SBRDomain **outDomain );
-static void		_SBRDomainFree( SBRDomain *inDomain );
-static OSStatus	_SBRServiceTypeCreate( const char *inName, SBRServiceType **outType );
-static void		_SBRServiceTypeFree( SBRServiceType *inType );
-static OSStatus
-	_SBRServiceInstanceCreate(
-		const char *			inName,
-		uint32_t				inInterfaceIndex,
-		const char *			inHostname,
-		uint16_t				inPort,
-		const uint8_t *			inTXTPtr,
-		size_t					inTXTLen,
-		uint64_t				inDiscoverTimeUs,
-		uint64_t				inResolveTimeUs,
-		SBRServiceInstance **	outInstance );
-static void		_SBRServiceInstanceFree( SBRServiceInstance *inInstance );
-static OSStatus
-	_SBRIPAddressCreate(
-		const struct sockaddr *	inSockAddr,
-		uint64_t				inResolveTimeUs,
-		Boolean					inValidated,
-		SBRIPAddress **			outIPAddress );
-static void		_SBRIPAddressFree( SBRIPAddress *inIPAddress );
-
-#define ForgetSBIPAddressList( X )		ForgetCustom( X, _SBIPAddressFreeList )
-
-CF_CLASS_DEFINE( ServiceBrowser );
-
-ulog_define_ex( kDNSSDUtilIdentifier, ServiceBrowser, kLogLevelTrace, kLogFlags_None, "ServiceBrowser", NULL );
-#define sb_ulog( LEVEL, ... )		ulog( &log_category_from_name( ServiceBrowser ), (LEVEL), __VA_ARGS__ )
-
-static OSStatus
-	ServiceBrowserCreate(
-		dispatch_queue_t	inQueue,
-		uint32_t			inInterfaceIndex,
-		const char *		inDomain,
-		unsigned int		inBrowseTimeSecs,
-		Boolean				inIncludeAWDL,
-		ServiceBrowserRef *	outBrowser )
-{
-	OSStatus				err;
-	ServiceBrowserRef		obj;
-	
-	CF_OBJECT_CREATE( ServiceBrowser, obj, err, exit );
-	
-	ReplaceDispatchQueue( &obj->queue, inQueue );
-	obj->ifIndex		= inInterfaceIndex;
-	if( inDomain )
-	{
-		obj->domain = strdup( inDomain );
-		require_action( obj->domain, exit, err = kNoMemoryErr );
-	}
-	obj->browseTimeSecs	= inBrowseTimeSecs;
-	obj->includeAWDL	= inIncludeAWDL;
-	
-	*outBrowser = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	CFReleaseNullSafe( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserFinalize
-//===========================================================================================================================
-
-static void	_ServiceBrowserFinalize( CFTypeRef inObj )
-{
-	ServiceBrowserRef const		me = (ServiceBrowserRef) inObj;
-	StringListItem *			serviceType;
-	
-	dispatch_forget( &me->queue );
-	check( !me->connection );
-	check( !me->domainsQuery );
-	ForgetMem( &me->domain );
-	while( ( serviceType = me->serviceTypeList ) != NULL )
-	{
-		me->serviceTypeList = serviceType->next;
-		ForgetMem( &serviceType->str );
-		free( serviceType );
-	}
-	check( !me->domainList );
-	check( !me->stopTimer );
-}
-
-//===========================================================================================================================
-//	ServiceBrowserSetUseNewGAI
-//===========================================================================================================================
-
-static void	ServiceBrowserSetUseNewGAI( ServiceBrowserRef me, Boolean inUseNewGAI )
-{
-	me->useNewGAI = inUseNewGAI;
-}
-
-//===========================================================================================================================
-//	ServiceBrowserSetValidateResults
-//===========================================================================================================================
-
-static void	ServiceBrowserSetValidateResults( const ServiceBrowserRef me, const Boolean inValidateResults )
-{
-	me->validateResults = inValidateResults;
-}
-
-//===========================================================================================================================
-//	ServiceBrowserStart
-//===========================================================================================================================
-
-static void	_ServiceBrowserStart( void *inContext );
-
-static void	ServiceBrowserStart( ServiceBrowserRef me )
-{
-	CFRetain( me );
-	dispatch_async_f( me->queue, me, _ServiceBrowserStart );
-}
-
-static void	_ServiceBrowserStart( void *inContext )
-{
-	OSStatus					err;
-	ServiceBrowserRef const		me = (ServiceBrowserRef) inContext;
-	
-	err = DNSServiceCreateConnection( &me->connection );
-	require_noerr( err, exit );
-	
-	err = DNSServiceSetDispatchQueue( me->connection, me->queue );
-	require_noerr( err, exit );
-	
-	if( me->domain )
-	{
-		err = _ServiceBrowserAddDomain( me, me->domain );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		DNSServiceRef			sdRef;
-		const char * const		recordName	= "b._dns-sd._udp.local.";
-		const uint32_t			ifIndex		= kDNSServiceInterfaceIndexLocalOnly;
-		
-		// Perform PTR meta-query for "b._dns-sd._udp.local." to enumerate recommended browsing domains.
-		// See <https://tools.ietf.org/html/rfc6763#section-11>.
-		
-		sb_ulog( kLogLevelTrace, "Starting PTR QueryRecord on interface %d for %s", (int32_t) ifIndex, recordName );
-		
-		sdRef = me->connection;
-		err = DNSServiceQueryRecord( &sdRef, kDNSServiceFlagsShareConnection, ifIndex, recordName,
-			kDNSServiceType_PTR, kDNSServiceClass_IN, _ServiceBrowserDomainsQueryCallback, me );
-		require_noerr( err, exit );
-		
-		me->domainsQuery = sdRef;
-	}
-	
-	err = DispatchTimerCreate( dispatch_time_seconds( me->browseTimeSecs ), DISPATCH_TIME_FOREVER,
-		100 * kNanosecondsPerMillisecond, me->queue, _ServiceBrowserTimerHandler, NULL, me, &me->stopTimer );
-	require_noerr( err, exit );
-	dispatch_resume( me->stopTimer );
-	
-exit:
-	if( err ) _ServiceBrowserStop( me, err );
-}
-
-//===========================================================================================================================
-//	ServiceBrowserAddServiceType
-//===========================================================================================================================
-
-static OSStatus	ServiceBrowserAddServiceType( ServiceBrowserRef me, const char *inServiceType )
-{
-	OSStatus				err;
-	StringListItem *		item;
-	StringListItem **		itemPtr;
-	StringListItem *		newItem = NULL;
-	
-	for( itemPtr = &me->serviceTypeList; ( item = *itemPtr ) != NULL; itemPtr = &item->next )
-	{
-		if( strcmp( item->str, inServiceType ) == 0 ) break;
-	}
-	if( !item )
-	{
-		newItem = (StringListItem *) calloc( 1, sizeof( *newItem ) );
-		require_action( newItem, exit, err = kNoMemoryErr );
-		
-		newItem->str = strdup( inServiceType );
-		require_action( newItem->str, exit, err = kNoMemoryErr );
-		
-		*itemPtr = newItem;
-		newItem = NULL;
-	}
-	err = kNoErr;
-	
-exit:
-	FreeNullSafe( newItem );
-	return( err );
-}
-
-//===========================================================================================================================
-//	ServiceBrowserSetCallback
-//===========================================================================================================================
-
-static void	ServiceBrowserSetCallback( ServiceBrowserRef me, ServiceBrowserCallback_f inCallback, void *inContext )
-{
-	me->userCallback	= inCallback;
-	me->userContext		= inContext;
-}
-
-//===========================================================================================================================
-//	ServiceBrowserResultsRetain
-//===========================================================================================================================
-
-static void	ServiceBrowserResultsRetain( ServiceBrowserResults *inResults )
-{
-	ServiceBrowserResultsPrivate * const		results = (ServiceBrowserResultsPrivate *) inResults;
-	
-	atomic_add_32( &results->refCount, 1 );
-}
-
-//===========================================================================================================================
-//	ServiceBrowserResultsRelease
-//===========================================================================================================================
-
-static void	ServiceBrowserResultsRelease( ServiceBrowserResults *inResults )
-{
-	ServiceBrowserResultsPrivate * const		results = (ServiceBrowserResultsPrivate *) inResults;
-	SBRDomain *									domain;
-	
-	if( atomic_add_and_fetch_32( &results->refCount, -1 ) == 0 )
-	{
-		while( ( domain = inResults->domainList ) != NULL )
-		{
-			inResults->domainList = domain->next;
-			_SBRDomainFree( domain );
-		}
-		free( inResults );
-	}
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserStop
-//===========================================================================================================================
-
-static void	_ServiceBrowserStop( ServiceBrowserRef me, OSStatus inError )
-{
-	OSStatus		err;
-	SBDomain *		d;
-	
-	dispatch_source_forget( &me->stopTimer );
-	DNSServiceForget( &me->domainsQuery );
-	for( d = me->domainList; d; d = d->next )
-	{
-		SBServiceType *		t;
-		
-		DNSServiceForget( &d->servicesQuery );
-		for( t = d->typeList; t; t = t->next )
-		{
-			SBServiceBrowse *		b;
-			
-			for( b = t->browseList; b; b = b->next )
-			{
-				SBServiceInstance *		i;
-				
-				DNSServiceForget( &b->browse );
-				for( i = b->instanceList; i; i = i->next )
-				{
-					_SBServiceInstanceStop( i );
-				}
-			}
-		}
-	}
-	DNSServiceForget( &me->connection );
-	
-	if( me->userCallback )
-	{
-		ServiceBrowserResults *		results = NULL;
-		
-		err = _ServiceBrowserCreateResults( me, &results );
-		if( !err ) err = inError;
-		
-		me->userCallback( results, err, me->userContext );
-		me->userCallback	= NULL;
-		me->userContext		= NULL;
-		if( results ) ServiceBrowserResultsRelease( results );
-	}
-	
-	while( ( d = me->domainList ) != NULL )
-	{
-		me->domainList = d->next;
-		_SBDomainFree( d );
-	}
-	CFRelease( me );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserAddDomain
-//===========================================================================================================================
-
-static OSStatus	_ServiceBrowserAddDomain( ServiceBrowserRef me, const char *inDomain )
-{
-	OSStatus		err;
-	SBDomain *		domain;
-	SBDomain **		domainPtr;
-	SBDomain *		newDomain = NULL;
-	
-	for( domainPtr = &me->domainList; ( domain = *domainPtr ) != NULL; domainPtr = &domain->next )
-	{
-		if( strcasecmp( domain->name, inDomain ) == 0 ) break;
-	}
-	require_action_quiet( !domain, exit, err = kDuplicateErr );
-	
-	err = _SBDomainCreate( inDomain, me, &newDomain );
-	require_noerr_quiet( err, exit );
-	
-	if( me->serviceTypeList )
-	{
-		const StringListItem *		item;
-		
-		for( item = me->serviceTypeList; item; item = item->next )
-		{
-			err = _ServiceBrowserAddServiceType( me, newDomain, item->str, me->ifIndex );
-			if( err == kDuplicateErr ) err = kNoErr;
-			require_noerr( err, exit );
-		}
-	}
-	else
-	{
-		char *				recordName;
-		DNSServiceRef		sdRef;
-		DNSServiceFlags		flags;
-		
-		// Perform PTR meta-query for _services._dns-sd._udp.<domain> to enumerate service types in domain.
-		// See <https://tools.ietf.org/html/rfc6763#section-9>.
-		
-		ASPrintF( &recordName, "_services._dns-sd._udp.%s", newDomain->name );
-		require_action( recordName, exit, err = kNoMemoryErr );
-		
-		flags = kDNSServiceFlagsShareConnection;
-		if( ( me->ifIndex == kDNSServiceInterfaceIndexAny ) && me->includeAWDL ) flags |= kDNSServiceFlagsIncludeAWDL;
-		
-		sb_ulog( kLogLevelTrace, "Starting PTR QueryRecord on interface %d for %s", (int32_t) me->ifIndex, recordName );
-		
-		sdRef = newDomain->browser->connection;
-		err = DNSServiceQueryRecord( &sdRef, flags, me->ifIndex, recordName, kDNSServiceType_PTR, kDNSServiceClass_IN,
-			_ServiceBrowserServicesQueryCallback, newDomain );
-		free( recordName );
-		require_noerr( err, exit );
-		
-		newDomain->servicesQuery = sdRef;
-	}
-	
-	*domainPtr	= newDomain;
-	newDomain	= NULL;
-	err = kNoErr;
-	
-exit:
-	if( newDomain ) _SBDomainFree( newDomain );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserRemoveDomain
-//===========================================================================================================================
-
-static OSStatus	_ServiceBrowserRemoveDomain( ServiceBrowserRef me, const char *inName )
-{
-	OSStatus		err;
-	SBDomain *		domain;
-	SBDomain **		domainPtr;
-	
-	for( domainPtr = &me->domainList; ( domain = *domainPtr ) != NULL; domainPtr = &domain->next )
-	{
-		if( strcasecmp( domain->name, inName ) == 0 ) break;
-	}
-	
-	if( domain )
-	{
-		*domainPtr = domain->next;
-		_SBDomainFree( domain );
-		err = kNoErr;
-	}
-	else
-	{
-		err = kNotFoundErr;
-	}
-	
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserTimerHandler
-//===========================================================================================================================
-
-static void	_ServiceBrowserTimerHandler( void *inContext )
-{
-	ServiceBrowserRef const		me = (ServiceBrowserRef) inContext;
-	
-	_ServiceBrowserStop( me, kNoErr );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserDomainsQueryCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ServiceBrowserDomainsQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	ServiceBrowserRef const		me = (ServiceBrowserRef) inContext;
-	OSStatus					err;
-	char						domainStr[ kDNSServiceMaxDomainName ];
-	
-	Unused( inSDRef );
-	Unused( inClass );
-	Unused( inTTL );
-	
-	sb_ulog( kLogLevelTrace, "QueryRecord result: %s on interface %d for %s -> %{du:rdata}%?{end} (error: %#m)",
-		DNSServiceFlagsToAddRmvStr( inFlags ), (int32_t) inInterfaceIndex, inFullName, inType, inRDataPtr, inRDataLen,
-		!inError, inError );
-	
-	require_noerr( inError, exit );
-	
-	err = DomainNameToString( inRDataPtr, ( (const uint8_t *) inRDataPtr ) + inRDataLen, domainStr, NULL );
-	require_noerr( err, exit );
-	
-	if( inFlags & kDNSServiceFlagsAdd )
-	{
-		err = _ServiceBrowserAddDomain( me, domainStr );
-		if( err == kDuplicateErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = _ServiceBrowserRemoveDomain( me, domainStr );
-		if( err == kNotFoundErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserServicesQueryCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ServiceBrowserServicesQueryCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		uint16_t				inType,
-		uint16_t				inClass,
-		uint16_t				inRDataLen,
-		const void *			inRDataPtr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus					err;
-	SBDomain * const			domain	= (SBDomain *) inContext;
-	ServiceBrowserRef const		me		= domain->browser;
-	const uint8_t *				src;
-	const uint8_t *				end;
-	uint8_t *					dst;
-	int							i;
-	uint8_t						serviceType[ 2 * ( 1 + kDomainLabelLengthMax ) + 1 ];
-	char						serviceTypeStr[ kDNSServiceMaxDomainName ];
-	
-	Unused( inSDRef );
-	Unused( inTTL );
-	Unused( inClass );
-	
-	sb_ulog( kLogLevelTrace, "QueryRecord result: %s on interface %d for %s -> %{du:rdata}%?{end} (error: %#m)",
-		DNSServiceFlagsToAddRmvStr( inFlags ), (int32_t) inInterfaceIndex, inFullName, inType, inRDataPtr, inRDataLen,
-		!inError, inError );
-	
-	require_noerr( inError, exit );
-	
-	check( inType  == kDNSServiceType_PTR );
-	check( inClass == kDNSServiceClass_IN );
-	
-	// The first two labels of the domain name in the RDATA describe a service type.
-	// See <https://tools.ietf.org/html/rfc6763#section-9>.
-	
-	src = (const uint8_t *) inRDataPtr;
-	end = src + inRDataLen;
-	dst = serviceType;
-	for( i = 0; i < 2; ++i )
-	{
-		size_t		labelLen;
-		
-		require_action_quiet( ( end - src ) > 0, exit, err = kUnderrunErr );
-		
-		labelLen = *src;
-		require_action_quiet( ( labelLen > 0 ) && ( labelLen <= kDomainLabelLengthMax ), exit, err = kMalformedErr );
-		require_action_quiet( ( (size_t)( end - src ) ) >= ( 1 + labelLen ), exit, err = kUnderrunErr );
-		
-		memcpy( dst, src, 1 + labelLen );
-		src += 1 + labelLen;
-		dst += 1 + labelLen;
-	}
-	*dst = 0;
-	
-	err = DomainNameToString( serviceType, NULL, serviceTypeStr, NULL );
-	require_noerr( err, exit );
-	
-	if( inFlags & kDNSServiceFlagsAdd )
-	{
-		err = _ServiceBrowserAddServiceType( me, domain, serviceTypeStr, inInterfaceIndex );
-		if( err == kDuplicateErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = _ServiceBrowserRemoveServiceType( me, domain, serviceTypeStr, inInterfaceIndex );
-		if( err == kNotFoundErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserBrowseCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ServiceBrowserBrowseCallback(
-		DNSServiceRef		inSDRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inError,
-		const char *		inName,
-		const char *		inRegType,
-		const char *		inDomain,
-		void *				inContext )
-{
-	OSStatus					err;
-	const uint64_t				nowTicks	= UpTicks();
-	SBServiceBrowse * const		browse		= (SBServiceBrowse *) inContext;
-	ServiceBrowserRef const		me			= (ServiceBrowserRef) browse->browser;
-	DNSServiceAttributeRef		attr		= NULL;
-	
-	Unused( inSDRef );
-	
-	sb_ulog( kLogLevelTrace, "Browse result: %s on interface %d for %s.%s%s%?{end} (error: %#m)",
-		DNSServiceFlagsToAddRmvStr( inFlags ), (int32_t) inInterfaceIndex, inName, inRegType, inDomain, !inError, inError );
-	
-	require_noerr( inError, exit );
-	
-	if( inFlags & kDNSServiceFlagsAdd )
-	{
-		if( me->validateResults )
-		{
-			if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-			{
-				const uint8_t *		dataPtr;
-				size_t				dataLen;
-				
-				dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-				sb_ulog( kLogLevelTrace, "Got %zu bytes of validation data for browse result", dataLen );
-				if( dataPtr )
-				{
-					attr = DNSServiceAttributeCreate();
-					require( attr, exit );
-					
-					err = DNSServiceAttrSetValidationData( attr, dataPtr, dataLen );
-					require_noerr( err, exit );
-				}
-			}
-			else
-			{
-				sb_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS\n" );
-			}
-		}
-		err = _ServiceBrowserAddServiceInstance( me, browse, inInterfaceIndex, inName, inRegType, inDomain,
-			UpTicksToMicroseconds( nowTicks - browse->startTicks ), attr );
-		if( err == kDuplicateErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = _ServiceBrowserRemoveServiceInstance( me, browse, inName, inInterfaceIndex );
-		if( err == kNotFoundErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	
-exit:
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserResolveCallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ServiceBrowserResolveCallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inFullName,
-		const char *			inHostname,
-		uint16_t				inPort,
-		uint16_t				inTXTLen,
-		const unsigned char *	inTXTPtr,
-		void *					inContext )
-{
-	OSStatus						err;
-	const uint64_t					nowTicks			= UpTicks();
-	SBServiceInstance * const		instance			= (SBServiceInstance *) inContext;
-	ServiceBrowserRef const			me					= (ServiceBrowserRef) instance->browser;
-	DNSServiceAttributeRef			attr				= NULL;
-	const uint8_t *					validationDataPtr	= NULL;
-	size_t							validationDataLen	= 0;
-	
-	Unused( inSDRef );
-	Unused( inFlags );
-	
-	sb_ulog( kLogLevelTrace, "Resolve result on interface %d for %s -> %s:%u %#{txt}%?{end} (error %#m)",
-		(int32_t) inInterfaceIndex, inFullName, inHostname, inPort, inTXTPtr, (size_t) inTXTLen, !inError, inError );
-	
-	require_noerr( inError, exit );
-	
-	if( !MemEqual( instance->txtPtr, instance->txtLen, inTXTPtr, inTXTLen ) )
-	{
-		FreeNullSafe( instance->txtPtr );
-		instance->txtPtr = _memdup( inTXTPtr, inTXTLen );
-		require_action( instance->txtPtr, exit, err = kNoMemoryErr );
-		
-		instance->txtLen = inTXTLen;
-	}
-	if( me->validateResults )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			const uint8_t *		dataPtr;
-			size_t				dataLen;
-			
-			dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-			sb_ulog( kLogLevelTrace, "Got %zu bytes of validation data for resolve result\n", dataLen );
-			if( dataPtr )
-			{
-				mdns_signed_resolve_result_t		signedResult;
-				
-				signedResult = mdns_signed_resolve_result_create_from_data( dataPtr, dataLen, &err );
-				if( signedResult )
-				{
-					if( mdns_signed_resolve_result_covers_txt_rdata( signedResult, instance->txtPtr, instance->txtLen ) )
-					{
-						sb_ulog( kLogLevelTrace, "Signed resolve result covers TXT record data\n" );
-						validationDataPtr = dataPtr;
-						validationDataLen = dataLen;
-					}
-					else
-					{
-						sb_ulog( kLogLevelError, "Signed resolve result doesn't cover TXT record data\n" );
-					}
-					mdns_forget( &signedResult );
-				}
-				else
-				{
-					sb_ulog( kLogLevelError, "mdns_signed_resolve_result_create_from_data() failed: %#m\n", err );
-				}
-			}
-		}
-		else
-		{
-			sb_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS\n" );
-		}
-	}
-	instance->port = ntohs( inPort );
-	
-	if( !instance->hostname || ( strcasecmp( instance->hostname, inHostname ) != 0 ) )
-	{
-		DNSServiceRef		sdRef;
-		
-		if( !instance->hostname ) instance->resolveTimeUs = UpTicksToMicroseconds( nowTicks - instance->resolveStartTicks );
-		
-		err = ReplaceString( &instance->hostname, NULL, inHostname, kSizeCString );
-		require_noerr( err, exit );
-		
-		sb_ulog( kLogLevelTrace,
-			"Starting GetAddrInfo on interface %d for %s", (int32_t) instance->ifIndex, instance->hostname );
-		
-		ForgetSBIPAddressList( &instance->ipaddrList );
-		
-		if( me->useNewGAI )
-		{
-			dnssd_getaddrinfo_t		gai;
-			
-			dnssd_getaddrinfo_forget( &instance->newGAI );
-			
-			gai = dnssd_getaddrinfo_create();
-			require_action( gai, exit, err = kNoResourcesErr );
-			
-			dnssd_getaddrinfo_set_hostname( gai, instance->hostname );
-			dnssd_getaddrinfo_set_flags( gai, 0 );
-			dnssd_getaddrinfo_set_interface_index( gai, instance->ifIndex );
-			dnssd_getaddrinfo_set_protocols( gai, kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6 );
-			if( validationDataPtr )
-			{
-				if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-				{
-					dnssd_getaddrinfo_set_validation_data( gai, validationDataPtr, validationDataLen );
-				}
-				else
-				{
-					sb_ulog( kLogLevelError, "dnssd_getaddrinfo_set_validation_data is not available on this OS\n" );
-				}
-			}
-			dnssd_getaddrinfo_set_queue( gai, me->queue );
-			_SBServiceInstanceRetain( instance );
-			CFRetain( me );
-			dnssd_getaddrinfo_set_result_handler( gai,
-			^( dnssd_getaddrinfo_result_t * const inResultArray, const size_t inResultCount )
-			{
-				if( instance->newGAI == gai )
-				{
-					_ServiceBrowserGAIResultHandler( me, instance, inResultArray, inResultCount );
-				}
-			} );
-			dnssd_getaddrinfo_set_event_handler( gai,
-			^( dnssd_event_t inEvent, DNSServiceErrorType inGAIError )
-			{
-				switch( inEvent )
-				{
-					case dnssd_event_invalidated:
-						dnssd_release( gai );
-						_SBServiceInstanceRelease( instance );
-						CFRelease( me );
-						break;
-					
-					case dnssd_event_error:
-						if( instance->newGAI == gai )
-						{
-							sb_ulog( kLogLevelError, "dnssd_getaddrinfo error %#m\n", inGAIError );
-							dnssd_getaddrinfo_forget( &instance->newGAI );
-						}
-						break;
-					
-					default:
-						break;
-				}
-			} );
-			instance->newGAI = gai;
-			dnssd_retain( instance->newGAI );
-			dnssd_getaddrinfo_activate( instance->newGAI );
-		}
-		else
-		{
-			DNSServiceForget( &instance->gai );
-			
-			sdRef = me->connection;
-			instance->gaiStartTicks = UpTicks();
-			if( validationDataPtr )
-			{
-				if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-				{
-					attr = DNSServiceAttributeCreate();
-					require( attr, exit );
-					
-					err = DNSServiceAttrSetValidationData( attr, validationDataPtr, validationDataLen );
-					require_noerr( err, exit );
-					
-					err = DNSServiceGetAddrInfoEx( &sdRef, kDNSServiceFlagsShareConnection, instance->ifIndex,
-						kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6, instance->hostname, attr,
-						_ServiceBrowserGAICallback, instance );
-					require_noerr( err, exit );
-				}
-				else
-				{
-					sb_ulog( kLogLevelError, "DNSServiceAttributeCreate is not available on this OS\n" );
-				}
-			}
-			else
-			{
-				err = DNSServiceGetAddrInfo( &sdRef, kDNSServiceFlagsShareConnection, instance->ifIndex,
-					kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6, instance->hostname, _ServiceBrowserGAICallback,
-					instance );
-				require_noerr( err, exit );
-			}
-			instance->gai = sdRef;
-		}
-	}
-	
-exit:
-	if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-	{
-		_DNSServiceAttrForget( &attr );
-	}
-}
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	_ServiceBrowserGAIResultHandler
-//===========================================================================================================================
-
-static void
-	_ServiceBrowserGAIResultHandler(
-		ServiceBrowserRef				me,
-		SBServiceInstance *				inInstance,
-		dnssd_getaddrinfo_result_t *	inResultArray,
-		size_t							inResultCount )
-{
-	OSStatus			err;
-	size_t				i;
-	const uint64_t		nowTicks = UpTicks();
-	
-	for( i = 0; i < inResultCount; ++i )
-	{
-		const dnssd_getaddrinfo_result_t			result	= inResultArray[ i ];
-		const dnssd_getaddrinfo_result_type_t		type	= dnssd_getaddrinfo_result_get_type( result );
-		
-		sb_ulog( kLogLevelTrace, "dnssd_getaddrinfo result: %@\n", result );
-		
-		if( type == dnssd_getaddrinfo_result_type_add )
-		{
-			Boolean		validated = false;
-			
-			if( me->validateResults )
-			{
-				if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-				{
-					const uint8_t *		dataPtr;
-					size_t				dataLen;
-					
-					dataPtr = dnssd_getaddrinfo_result_get_validation_data( result, &dataLen );
-					sb_ulog( kLogLevelTrace, "Got %zu bytes of validation data for dnssd_getaddrinfo result", dataLen );
-					if( dataPtr )
-					{
-						OSStatus							createErr;
-						mdns_signed_hostname_result_t		signedResult;
-						
-						signedResult = mdns_signed_hostname_result_create_from_data( dataPtr, dataLen, &createErr );
-						sb_ulog( kLogLevelTrace, "Signed hostname result: %@", signedResult );
-						if( signedResult )
-						{
-							validated = true;
-							mdns_forget( &signedResult );
-						}
-					}
-				}
-				else
-				{
-					sb_ulog( kLogLevelError, "dnssd_getaddrinfo_result_get_validation_data is not available on this OS." );
-				}
-			}
-			err = _ServiceBrowserAddIPAddress( me, inInstance, dnssd_getaddrinfo_result_get_address( result ),
-				UpTicksToMicroseconds( nowTicks - inInstance->gaiStartTicks ), validated );
-			if( err == kDuplicateErr ) err = kNoErr;
-			require_noerr( err, exit );
-		}
-		else if( type == dnssd_getaddrinfo_result_type_remove )
-		{
-			err = _ServiceBrowserRemoveIPAddress( me, inInstance, dnssd_getaddrinfo_result_get_address( result ) );
-			if( err == kNotFoundErr ) err = kNoErr;
-			require_noerr( err, exit );
-		}
-	}
-	
-exit:
-	return;
-}
-#endif
-
-//===========================================================================================================================
-//	_ServiceBrowserGAICallback
-//===========================================================================================================================
-
-static void DNSSD_API
-	_ServiceBrowserGAICallback(
-		DNSServiceRef			inSDRef,
-		DNSServiceFlags			inFlags,
-		uint32_t				inInterfaceIndex,
-		DNSServiceErrorType		inError,
-		const char *			inHostname,
-		const struct sockaddr *	inSockAddr,
-		uint32_t				inTTL,
-		void *					inContext )
-{
-	OSStatus						err;
-	const uint64_t					nowTicks	= UpTicks();
-	SBServiceInstance * const		instance	= (SBServiceInstance *) inContext;
-	ServiceBrowserRef const			me			= (ServiceBrowserRef) instance->browser;
-	
-	Unused( inSDRef );
-	Unused( inTTL );
-	
-	sb_ulog( kLogLevelTrace, "GetAddrInfo result: %s on interface %d for (%s ->) %s -> %##a%?{end} (error: %#m)",
-		DNSServiceFlagsToAddRmvStr( inFlags ), (int32_t) inInterfaceIndex, instance->fqdn, inHostname, inSockAddr,
-		!inError, inError );
-	
-	require_noerr( inError, exit );
-	
-	if( ( inSockAddr->sa_family != AF_INET ) && ( inSockAddr->sa_family != AF_INET6 ) )
-	{
-		dlogassert( "Unexpected address family: %d", inSockAddr->sa_family );
-		goto exit;
-	}
-	
-	if( inFlags & kDNSServiceFlagsAdd )
-	{
-		Boolean		validated = false;
-		
-		if( me->validateResults )
-		{
-			if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-			{
-				const uint8_t *		dataPtr;
-				size_t				dataLen;
-				
-				dataPtr = DNSServiceGetValidationData( inSDRef, &dataLen );
-				sb_ulog( kLogLevelTrace, "Got %zu bytes of validation data for GetAddrInfo result", dataLen );
-				if( dataPtr )
-				{
-					OSStatus							createErr;
-					mdns_signed_hostname_result_t		signedResult;
-					
-					signedResult = mdns_signed_hostname_result_create_from_data( dataPtr, dataLen, &createErr );
-					sb_ulog( kLogLevelTrace, "Signed hostname result: %@", signedResult );
-					if( signedResult )
-					{
-						validated = true;
-						mdns_forget( &signedResult );
-					}
-				}
-			}
-			else
-			{
-				sb_ulog( kLogLevelError, "DNSServiceGetValidationData is not available on this OS" );
-			}
-		}
-		err = _ServiceBrowserAddIPAddress( me, instance, inSockAddr,
-			UpTicksToMicroseconds( nowTicks - instance->gaiStartTicks ), validated );
-		if( err == kDuplicateErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = _ServiceBrowserRemoveIPAddress( me, instance, inSockAddr );
-		if( err == kNotFoundErr ) err = kNoErr;
-		require_noerr( err, exit );
-	}
-	
-exit:
-	return;
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserAddServiceType
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserAddServiceType(
-		ServiceBrowserRef	me,
-		SBDomain *			inDomain,
-		const char *		inName,
-		uint32_t			inIfIndex )
-{
-	OSStatus				err;
-	SBServiceType *			type;
-	SBServiceType **		typePtr;
-	SBServiceType *			newType		= NULL;
-	SBServiceBrowse *		browse;
-	SBServiceBrowse **		browsePtr;
-	SBServiceBrowse *		newBrowse	= NULL;
-	DNSServiceRef			sdRef;
-	DNSServiceFlags			flags;
-	
-	for( typePtr = &inDomain->typeList; ( type = *typePtr ) != NULL; typePtr = &type->next )
-	{
-		if( strcasecmp( type->name, inName ) == 0 ) break;
-	}
-	if( !type )
-	{
-		err = _SBServiceTypeCreate( inName, &newType );
-		require_noerr_quiet( err, exit );
-		
-		type = newType;
-	}
-	
-	for( browsePtr = &type->browseList; ( browse = *browsePtr ) != NULL; browsePtr = &browse->next )
-	{
-		if( browse->ifIndex == inIfIndex ) break;
-	}
-	require_action_quiet( !browse, exit, err = kDuplicateErr );
-	
-	err = _SBServiceBrowseCreate( inIfIndex, me, &newBrowse );
-	require_noerr_quiet( err, exit );
-	
-	flags = kDNSServiceFlagsShareConnection;
-	if( ( newBrowse->ifIndex == kDNSServiceInterfaceIndexAny ) && me->includeAWDL ) flags |= kDNSServiceFlagsIncludeAWDL;
-	
-	sb_ulog( kLogLevelTrace, "Starting Browse on interface %d for %s%s",
-		(int32_t) newBrowse->ifIndex, type->name, inDomain->name );
-	
-	sdRef = me->connection;
-	newBrowse->startTicks = UpTicks();
-	if( me->validateResults )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			err = DNSServiceBrowseEx( &sdRef, flags, newBrowse->ifIndex, type->name, inDomain->name,
-				&kDNSServiceAttrValidationRequired, _ServiceBrowserBrowseCallback, newBrowse );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			sb_ulog( kLogLevelError, "DNSServiceBrowseEx is not available on this OS." );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = DNSServiceBrowse( &sdRef, flags, newBrowse->ifIndex, type->name, inDomain->name, _ServiceBrowserBrowseCallback,
-			newBrowse );
-		require_noerr( err, exit );
-	}
-	newBrowse->browse = sdRef;
-	*browsePtr	= newBrowse;
-	newBrowse	= NULL;
-	
-	if( newType )
-	{
-		*typePtr	= newType;
-		newType		= NULL;
-	}
-	
-exit:
-	if( newBrowse )	_SBServiceBrowseFree( newBrowse );
-	if( newType )	_SBServiceTypeFree( newType );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserRemoveServiceType
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserRemoveServiceType(
-		ServiceBrowserRef	me,
-		SBDomain *			inDomain,
-		const char *		inName,
-		uint32_t			inIfIndex )
-{
-	OSStatus				err;
-	SBServiceType *			type;
-	SBServiceType **		typePtr;
-	SBServiceBrowse *		browse;
-	SBServiceBrowse **		browsePtr;
-	
-	Unused( me );
-	
-	for( typePtr = &inDomain->typeList; ( type = *typePtr ) != NULL; typePtr = &type->next )
-	{
-		if( strcasecmp( type->name, inName ) == 0 ) break;
-	}
-	require_action_quiet( type, exit, err = kNotFoundErr );
-	
-	for( browsePtr = &type->browseList; ( browse = *browsePtr ) != NULL; browsePtr = &browse->next )
-	{
-		if( browse->ifIndex == inIfIndex ) break;
-	}
-	require_action_quiet( browse, exit, err = kNotFoundErr );
-	
-	*browsePtr = browse->next;
-	_SBServiceBrowseFree( browse );
-	if( !type->browseList )
-	{
-		*typePtr = type->next;
-		_SBServiceTypeFree( type );
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserAddServiceInstance
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserAddServiceInstance(
-		ServiceBrowserRef			me,
-		SBServiceBrowse *			inBrowse,
-		uint32_t					inIfIndex,
-		const char *				inName,
-		const char *				inRegType,
-		const char *				inDomain,
-		uint64_t					inDiscoverTimeUs,
-		const DNSServiceAttribute *	inAttr )
-{
-	OSStatus					err;
-	DNSServiceRef				sdRef;
-	SBServiceInstance *			instance;
-	SBServiceInstance **		instancePtr;
-	SBServiceInstance *			newInstance	= NULL;
-	
-	for( instancePtr = &inBrowse->instanceList; ( instance = *instancePtr ) != NULL; instancePtr = &instance->next )
-	{
-		if( ( instance->ifIndex == inIfIndex ) && ( strcasecmp( instance->name, inName ) == 0 ) ) break;
-	}
-	require_action_quiet( !instance, exit, err = kDuplicateErr );
-	
-	err = _SBServiceInstanceCreate( inName, inRegType, inDomain, inIfIndex, inDiscoverTimeUs, me, &newInstance );
-	require_noerr_quiet( err, exit );
-	
-	sb_ulog( kLogLevelTrace, "Starting Resolve on interface %d for %s.%s%s",
-		(int32_t) newInstance->ifIndex, inName, inRegType, inDomain );
-	
-	sdRef = me->connection;
-	newInstance->resolveStartTicks = UpTicks();
-	if( inAttr )
-	{
-		if( __builtin_available( macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * ) )
-		{
-			err = DNSServiceResolveEx( &sdRef, kDNSServiceFlagsShareConnection, newInstance->ifIndex, inName, inRegType,
-				inDomain, inAttr, _ServiceBrowserResolveCallback, newInstance );
-			require_noerr( err, exit );
-		}
-		else
-		{
-			sb_ulog( kLogLevelError, "DNSServiceResolveEx is not available on this OS." );
-			err = kUnsupportedErr;
-			goto exit;
-		}
-	}
-	else
-	{
-		err = DNSServiceResolve( &sdRef, kDNSServiceFlagsShareConnection, newInstance->ifIndex, inName, inRegType,
-			inDomain, _ServiceBrowserResolveCallback, newInstance );
-		require_noerr( err, exit );
-	}
-	newInstance->resolve = sdRef;
-	*instancePtr	= newInstance;
-	newInstance		= NULL;
-	
-exit:
-	if( newInstance ) _SBServiceInstanceRelease( newInstance );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserRemoveServiceInstance
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserRemoveServiceInstance(
-		ServiceBrowserRef	me,
-		SBServiceBrowse *	inBrowse,
-		const char *		inName,
-		uint32_t			inIfIndex )
-{
-	OSStatus					err;
-	SBServiceInstance *			instance;
-	SBServiceInstance **		ptr;
-	
-	Unused( me );
-	
-	for( ptr = &inBrowse->instanceList; ( instance = *ptr ) != NULL; ptr = &instance->next )
-	{
-		if( ( instance->ifIndex == inIfIndex ) && ( strcasecmp( instance->name, inName ) == 0 ) ) break;
-	}
-	require_action_quiet( instance, exit, err = kNotFoundErr );
-	
-	*ptr = instance->next;
-	_SBServiceInstanceForget( &instance );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserAddIPAddress
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserAddIPAddress(
-		ServiceBrowserRef		me,
-		SBServiceInstance *		inInstance,
-		const struct sockaddr *	inSockAddr,
-		uint64_t				inResolveTimeUs,
-		Boolean					inValidated )
-{
-	OSStatus			err;
-	SBIPAddress *		ipaddr;
-	SBIPAddress **		ipaddrPtr;
-	SBIPAddress *		newIPAddr = NULL;
-	
-	Unused( me );
-	
-	if( ( inSockAddr->sa_family != AF_INET ) && ( inSockAddr->sa_family != AF_INET6 ) )
-	{
-		dlogassert( "Unexpected address family: %d", inSockAddr->sa_family );
-		err = kTypeErr;
-		goto exit;
-	}
-	
-	for( ipaddrPtr = &inInstance->ipaddrList; ( ipaddr = *ipaddrPtr ) != NULL; ipaddrPtr = &ipaddr->next )
-	{
-		if( SockAddrCompareAddr( &ipaddr->sip, inSockAddr ) == 0 ) break;
-	}
-	require_action_quiet( !ipaddr, exit, err = kDuplicateErr );
-	
-	err = _SBIPAddressCreate( inSockAddr, inResolveTimeUs, inValidated, &newIPAddr );
-	require_noerr_quiet( err, exit );
-	
-	*ipaddrPtr = newIPAddr;
-	newIPAddr = NULL;
-	err = kNoErr;
-	
-exit:
-	if( newIPAddr ) _SBIPAddressFree( newIPAddr );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserRemoveIPAddress
-//===========================================================================================================================
-
-static OSStatus
-	_ServiceBrowserRemoveIPAddress(
-		ServiceBrowserRef		me,
-		SBServiceInstance *		inInstance,
-		const struct sockaddr *	inSockAddr )
-{
-	OSStatus			err;
-	SBIPAddress *		ipaddr;
-	SBIPAddress **		ipaddrPtr;
-	
-	Unused( me );
-	
-	for( ipaddrPtr = &inInstance->ipaddrList; ( ipaddr = *ipaddrPtr ) != NULL; ipaddrPtr = &ipaddr->next )
-	{
-		if( SockAddrCompareAddr( &ipaddr->sip.sa, inSockAddr ) == 0 ) break;
-	}
-	require_action_quiet( ipaddr, exit, err = kNotFoundErr );
-	
-	*ipaddrPtr = ipaddr->next;
-	_SBIPAddressFree( ipaddr );
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ServiceBrowserCreateResults
-//===========================================================================================================================
-
-static OSStatus	_ServiceBrowserCreateResults( ServiceBrowserRef me, ServiceBrowserResults **outResults )
-{
-	OSStatus							err;
-	SBDomain *							d;
-	SBServiceType *						t;
-	SBServiceBrowse *					b;
-	SBServiceInstance *					i;
-	SBIPAddress *						a;
-	ServiceBrowserResultsPrivate *		results;
-	SBRDomain **						domainPtr;
-	
-	results = (ServiceBrowserResultsPrivate *) calloc( 1, sizeof( *results ) );
-	require_action( results, exit, err = kNoMemoryErr );
-	
-	results->refCount = 1;
-	
-	domainPtr = &results->domainList;
-	for( d = me->domainList; d; d = d->next )
-	{
-		SBRDomain *				domain;
-		SBRServiceType **		typePtr;
-		
-		err = _SBRDomainCreate( d->name, &domain );
-		require_noerr_quiet( err, exit );
-		*domainPtr = domain;
-		 domainPtr = &domain->next;
-		
-		typePtr = &domain->typeList;
-		for( t = d->typeList; t; t = t->next )
-		{
-			SBRServiceType *			type;
-			SBRServiceInstance **		instancePtr;
-			
-			err = _SBRServiceTypeCreate( t->name, &type );
-			require_noerr_quiet( err, exit );
-			*typePtr = type;
-			 typePtr = &type->next;
-			
-			instancePtr = &type->instanceList;
-			for( b = t->browseList; b; b = b->next )
-			{
-				for( i = b->instanceList; i; i = i->next )
-				{
-					SBRServiceInstance *		instance;
-					SBRIPAddress **				ipaddrPtr;
-					
-					err = _SBRServiceInstanceCreate( i->name, i->ifIndex, i->hostname, i->port, i->txtPtr, i->txtLen,
-						i->discoverTimeUs, i->resolveTimeUs, &instance );
-					require_noerr_quiet( err, exit );
-					*instancePtr = instance;
-					 instancePtr = &instance->next;
-					
-					ipaddrPtr = &instance->ipaddrList;
-					for( a = i->ipaddrList; a; a = a->next )
-					{
-						SBRIPAddress *		ipaddr;
-						
-						err = _SBRIPAddressCreate( &a->sip.sa, a->resolveTimeUs, a->validated, &ipaddr );
-						require_noerr_quiet( err, exit );
-						
-						*ipaddrPtr = ipaddr;
-						 ipaddrPtr = &ipaddr->next;
-					}
-				}
-			}
-		}
-	}
-	
-	*outResults = (ServiceBrowserResults *) results;
-	results = NULL;
-	err = kNoErr;
-	
-exit:
-	if( results ) ServiceBrowserResultsRelease( (ServiceBrowserResults *) results );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBDomainCreate
-//===========================================================================================================================
-
-static OSStatus	_SBDomainCreate( const char *inName, ServiceBrowserRef inBrowser, SBDomain **outDomain )
-{
-	OSStatus		err;
-	SBDomain *		obj;
-	
-	obj = (SBDomain *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	obj->browser = inBrowser;
-	
-	*outDomain = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBDomainFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBDomainFree
-//===========================================================================================================================
-
-static void	_SBDomainFree( SBDomain *inDomain )
-{
-	SBServiceType *		type;
-	
-	ForgetMem( &inDomain->name );
-	DNSServiceForget( &inDomain->servicesQuery );
-	while( ( type = inDomain->typeList ) != NULL )
-	{
-		inDomain->typeList = type->next;
-		_SBServiceTypeFree( type );
-	}
-	free( inDomain );
-}
-
-//===========================================================================================================================
-//	_SBServiceTypeCreate
-//===========================================================================================================================
-
-static OSStatus	_SBServiceTypeCreate( const char *inName, SBServiceType **outType )
-{
-	OSStatus			err;
-	SBServiceType *		obj;
-	
-	obj = (SBServiceType *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	*outType = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBServiceTypeFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBServiceTypeFree
-//===========================================================================================================================
-
-static void	_SBServiceTypeFree( SBServiceType *inType )
-{
-	SBServiceBrowse *		browse;
-	
-	ForgetMem( &inType->name );
-	while( ( browse = inType->browseList ) != NULL )
-	{
-		inType->browseList = browse->next;
-		_SBServiceBrowseFree( browse );
-	}
-	free( inType );
-}
-
-//===========================================================================================================================
-//	_SBServiceBrowseCreate
-//===========================================================================================================================
-
-static OSStatus	_SBServiceBrowseCreate( uint32_t inIfIndex, ServiceBrowserRef inBrowser, SBServiceBrowse **outBrowse )
-{
-	OSStatus				err;
-	SBServiceBrowse *		obj;
-	
-	obj = (SBServiceBrowse *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->ifIndex = inIfIndex;
-	obj->browser = inBrowser;
-	*outBrowse = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBServiceBrowseFree
-//===========================================================================================================================
-
-static void	_SBServiceBrowseFree( SBServiceBrowse *inBrowse )
-{
-	SBServiceInstance *		instance;
-	
-	DNSServiceForget( &inBrowse->browse );
-	while( ( instance = inBrowse->instanceList ) != NULL )
-	{
-		inBrowse->instanceList = instance->next;
-		_SBServiceInstanceForget( &instance );
-	}
-	free( inBrowse );
-}
-
-//===========================================================================================================================
-//	_SBServiceInstanceCreate
-//===========================================================================================================================
-
-static OSStatus
-	_SBServiceInstanceCreate(
-		const char *			inName,
-		const char *			inType,
-		const char *			inDomain,
-		uint32_t				inIfIndex,
-		uint64_t				inDiscoverTimeUs,
-		ServiceBrowserRef		inBrowser,
-		SBServiceInstance **	outInstance )
-{
-	OSStatus				err;
-	SBServiceInstance *		obj;
-	
-	obj = (SBServiceInstance *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->refCount = 1;
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	ASPrintF( &obj->fqdn, "%s.%s%s", obj->name, inType, inDomain );
-	require_action( obj->fqdn, exit, err = kNoMemoryErr );
-	
-	obj->ifIndex		= inIfIndex;
-	obj->discoverTimeUs	= inDiscoverTimeUs;
-	obj->browser		= inBrowser;
-	
-	*outInstance = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBServiceInstanceRelease( obj );
-	return( err );
-}
-
-#if( MDNSRESPONDER_PROJECT )
-//===========================================================================================================================
-//	_SBServiceInstanceRetain
-//===========================================================================================================================
-
-static void	_SBServiceInstanceRetain( SBServiceInstance *inInstance )
-{
-	atomic_add_32( &inInstance->refCount, 1 );
-}
-#endif
-
-//===========================================================================================================================
-//	_SBServiceInstanceStop
-//===========================================================================================================================
-
-static void	_SBServiceInstanceStop( SBServiceInstance *inInstance )
-{
-	DNSServiceForget( &inInstance->resolve );
-	DNSServiceForget( &inInstance->gai );
-#if( MDNSRESPONDER_PROJECT )
-	dnssd_getaddrinfo_forget( &inInstance->newGAI );
-#endif
-}
-
-//===========================================================================================================================
-//	_SBServiceInstanceRelease
-//===========================================================================================================================
-
-static void	_SBServiceInstanceRelease( SBServiceInstance *inInstance )
-{
-	if( atomic_add_and_fetch_32( &inInstance->refCount, -1 ) == 0 )
-	{
-		check( !inInstance->resolve );
-		check( !inInstance->gai );
-	#if( MDNSRESPONDER_PROJECT )
-		check( !inInstance->newGAI );
-	#endif
-		ForgetMem( &inInstance->name );
-		ForgetMem( &inInstance->fqdn );
-		ForgetMem( &inInstance->hostname );
-		ForgetMem( &inInstance->txtPtr );
-		ForgetSBIPAddressList( &inInstance->ipaddrList );
-		free( inInstance );
-	}
-}
-
-//===========================================================================================================================
-//	_SBIPAddressCreate
-//===========================================================================================================================
-
-static OSStatus	_SBIPAddressCreate( const struct sockaddr *inSockAddr, uint64_t inResolveTimeUs, Boolean inValidated,
-	SBIPAddress **outIPAddress )
-{
-	OSStatus			err;
-	SBIPAddress *		obj;
-	
-	obj = (SBIPAddress *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	SockAddrCopy( inSockAddr, &obj->sip );
-	obj->resolveTimeUs	= inResolveTimeUs;
-	obj->validated		= inValidated;
-	
-	*outIPAddress = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBIPAddressFree
-//===========================================================================================================================
-
-static void _SBIPAddressFree( SBIPAddress *inIPAddress )
-{
-	free( inIPAddress );
-}
-
-//===========================================================================================================================
-//	_SBIPAddressFreeList
-//===========================================================================================================================
-
-static void	_SBIPAddressFreeList( SBIPAddress *inList )
-{
-	SBIPAddress *		ipaddr;
-	
-	while( ( ipaddr = inList ) != NULL )
-	{
-		inList = ipaddr->next;
-		_SBIPAddressFree( ipaddr );
-	}
-}
-
-//===========================================================================================================================
-//	_SBRDomainCreate
-//===========================================================================================================================
-
-static OSStatus	_SBRDomainCreate( const char *inName, SBRDomain **outDomain )
-{
-	OSStatus		err;
-	SBRDomain *		obj;
-	
-	obj = (SBRDomain *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	*outDomain = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBRDomainFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBRDomainFree
-//===========================================================================================================================
-
-static void	_SBRDomainFree( SBRDomain *inDomain )
-{
-	SBRServiceType *		type;
-	
-	ForgetMem( &inDomain->name );
-	while( ( type = inDomain->typeList ) != NULL )
-	{
-		inDomain->typeList = type->next;
-		_SBRServiceTypeFree( type );
-	}
-	free( inDomain );
-}
-
-//===========================================================================================================================
-//	_SBRServiceTypeCreate
-//===========================================================================================================================
-
-static OSStatus	_SBRServiceTypeCreate( const char *inName, SBRServiceType **outType )
-{
-	OSStatus				err;
-	SBRServiceType *		obj;
-	
-	obj = (SBRServiceType *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	*outType = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBRServiceTypeFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBRServiceTypeFree
-//===========================================================================================================================
-
-static void	_SBRServiceTypeFree( SBRServiceType *inType )
-{
-	SBRServiceInstance *		instance;
-	
-	ForgetMem( &inType->name );
-	while( ( instance = inType->instanceList ) != NULL )
-	{
-		inType->instanceList = instance->next;
-		_SBRServiceInstanceFree( instance );
-	}
-	free( inType );
-}
-
-//===========================================================================================================================
-//	_SBRServiceInstanceCreate
-//===========================================================================================================================
-
-static OSStatus
-	_SBRServiceInstanceCreate(
-		const char *			inName,
-		uint32_t				inInterfaceIndex,
-		const char *			inHostname,
-		uint16_t				inPort,
-		const uint8_t *			inTXTPtr,
-		size_t					inTXTLen,
-		uint64_t				inDiscoverTimeUs,
-		uint64_t				inResolveTimeUs,
-		SBRServiceInstance **	outInstance )
-{
-	OSStatus					err;
-	SBRServiceInstance *		obj;
-	
-	obj = (SBRServiceInstance *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	obj->name = strdup( inName );
-	require_action( obj->name, exit, err = kNoMemoryErr );
-	
-	if( inHostname )
-	{
-		obj->hostname = strdup( inHostname );
-		require_action( obj->hostname, exit, err = kNoMemoryErr );
-	}
-	if( inTXTLen > 0 )
-	{
-		obj->txtPtr = (uint8_t *) _memdup( inTXTPtr, inTXTLen );
-		require_action( obj->txtPtr, exit, err = kNoMemoryErr );
-		obj->txtLen = inTXTLen;
-	}
-	obj->discoverTimeUs	= inDiscoverTimeUs;
-	obj->resolveTimeUs	= inResolveTimeUs;
-	obj->ifIndex		= inInterfaceIndex;
-	obj->port			= inPort;
-	
-	*outInstance = obj;
-	obj = NULL;
-	err = kNoErr;
-	
-exit:
-	if( obj ) _SBRServiceInstanceFree( obj );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBRServiceInstanceFree
-//===========================================================================================================================
-
-static void	_SBRServiceInstanceFree( SBRServiceInstance *inInstance )
-{
-	SBRIPAddress *		ipaddr;
-	
-	ForgetMem( &inInstance->name );
-	ForgetMem( &inInstance->hostname );
-	ForgetMem( &inInstance->txtPtr );
-	while( ( ipaddr = inInstance->ipaddrList ) != NULL )
-	{
-		inInstance->ipaddrList = ipaddr->next;
-		_SBRIPAddressFree( ipaddr );
-	}
-	free( inInstance );
-}
-
-//===========================================================================================================================
-//	_SBRIPAddressCreate
-//===========================================================================================================================
-
-static OSStatus
-	_SBRIPAddressCreate(
-		const struct sockaddr *	inSockAddr,
-		uint64_t				inResolveTimeUs,
-		Boolean 				inValidated,
-		SBRIPAddress **			outIPAddress )
-{
-	OSStatus			err;
-	SBRIPAddress *		obj;
-	
-	obj = (SBRIPAddress *) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = kNoMemoryErr );
-	
-	SockAddrCopy( inSockAddr, &obj->sip );
-	obj->resolveTimeUs 	= inResolveTimeUs;
-	obj->validated 		= inValidated;
-	
-	*outIPAddress = obj;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_SBRIPAddressFree
-//===========================================================================================================================
-
-static void	_SBRIPAddressFree( SBRIPAddress *inIPAddress )
-{
-	free( inIPAddress );
-}
-
-//===========================================================================================================================
-//	_ParseIPv4Address
-//
-//	Warning: "inBuffer" may be modified even in error cases.
-//
-//	Note: This was copied from CoreUtils because the StringToIPv4Address function is currently not exported in the framework.
-//===========================================================================================================================
-
-static OSStatus	_ParseIPv4Address( const char *inStr, uint8_t inBuffer[ 4 ], const char **outStr )
-{
-	OSStatus		err;
-	uint8_t *		dst;
-	int				segments;
-	int				sawDigit;
-	int				c;
-	int				v;
-	
-	check( inBuffer );
-	check( outStr );
-	
-	dst		 = inBuffer;
-	*dst	 = 0;
-	sawDigit = 0;
-	segments = 0;
-	for( ; ( c = *inStr ) != '\0'; ++inStr )
-	{
-		if( isdigit_safe( c ) )
-		{
-			v = ( *dst * 10 ) + ( c - '0' );
-			require_action_quiet( v <= 255, exit, err = kRangeErr );
-			*dst = (uint8_t) v;
-			if( !sawDigit )
-			{
-				++segments;
-				require_action_quiet( segments <= 4, exit, err = kOverrunErr );
-				sawDigit = 1;
-			}
-		}
-		else if( ( c == '.' ) && sawDigit )
-		{
-			require_action_quiet( segments < 4, exit, err = kMalformedErr );
-			*++dst = 0;
-			sawDigit = 0;
-		}
-		else
-		{
-			break;
-		}
-	}
-	require_action_quiet( segments == 4, exit, err = kUnderrunErr );
-	
-	*outStr = inStr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_StringToIPv4Address
-//
-//	Note: This was copied from CoreUtils because the StringToIPv4Address function is currently not exported in the framework.
-//===========================================================================================================================
-
-static OSStatus
-	_StringToIPv4Address( 
-		const char *			inStr, 
-		StringToIPAddressFlags	inFlags, 
-		uint32_t *				outIP, 
-		int *					outPort, 
-		uint32_t *				outSubnet, 
-		uint32_t *				outRouter, 
-		const char **			outStr )
-{
-	OSStatus			err;
-	uint8_t				buf[ 4 ];
-	int					c;
-	uint32_t			ip;
-	int					hasPort;
-	int					port;
-	int					hasPrefix;
-	int					prefix;
-	uint32_t			subnetMask;
-	uint32_t			router;
-	
-	require_action( inStr, exit, err = kParamErr );
-	
-	// Parse the address-only part of the address (e.g. "1.2.3.4").
-	
-	err = _ParseIPv4Address( inStr, buf, &inStr );
-	require_noerr_quiet( err, exit );
-	ip = (uint32_t)( ( buf[ 0 ] << 24 ) | ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ] );
-	c = *inStr;
-	
-	// Parse the port (if any).
-	
-	hasPort = 0;
-	port    = 0;
-	if( c == ':' )
-	{
-		require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPort ), exit, err = kUnexpectedErr );
-		while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) port = ( port * 10 ) + ( c - '0' );
-		require_action_quiet( port <= 65535, exit, err = kRangeErr );
-		hasPort = 1;
-	}
-	
-	// Parse the prefix length (if any).
-	
-	hasPrefix  = 0;
-	prefix     = 0;
-	subnetMask = 0;
-	router     = 0;
-	if( c == '/' )
-	{
-		require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPrefix ), exit, err = kUnexpectedErr );
-		while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) prefix = ( prefix * 10 ) + ( c - '0' );
-		require_action_quiet( ( prefix >= 0 ) && ( prefix <= 32 ), exit, err = kRangeErr );
-		hasPrefix = 1;
-		
-		subnetMask = ( prefix > 0 ) ? ( UINT32_C( 0xFFFFFFFF ) << ( 32 - prefix ) ) : 0;
-		router	   = ( ip & subnetMask ) | 1;
-	}
-	
-	// Return the results. Only fill in port/prefix/router results if the info was found to allow for defaults.
-	
-	if( outIP )					 *outIP		= ip;
-	if( outPort   && hasPort )	 *outPort	= port;
-	if( outSubnet && hasPrefix ) *outSubnet	= subnetMask;
-	if( outRouter && hasPrefix ) *outRouter	= router;
-	if( outStr )				 *outStr	= inStr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ParseIPv6Address
-//
-//	Note: Parsed according to the rules specified in RFC 3513.
-//	Warning: "inBuffer" may be modified even in error cases.
-//
-//	Note: This was copied from CoreUtils because the StringToIPv6Address function is currently not exported in the framework.
-//===========================================================================================================================
-
-static OSStatus	_ParseIPv6Address( const char *inStr, int inAllowV4Mapped, uint8_t inBuffer[ 16 ], const char **outStr )
-{
-													// Table to map uppercase hex characters - '0' to their numeric values.
-													// 0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?  @  A   B   C   D   E   F
-	static const uint8_t		kASCIItoHexTable[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 };
-	OSStatus					err;
-	const char *				ptr;
-	uint8_t *					dst;
-	uint8_t *					lim;
-	uint8_t *					colonPtr;
-	int							c;
-	int							sawDigit;
-	unsigned int				v;
-	int							i;
-	int							n;
-	
-	// Pre-zero the address to simplify handling of compressed addresses (e.g. "::1").
-	
-	for( i = 0; i < 16; ++i ) inBuffer[ i ] = 0;
-	
-	// Special case leading :: (e.g. "::1") to simplify processing later.
-	
-	if( *inStr == ':' )
-	{
-		++inStr;
-		require_action_quiet( *inStr == ':', exit, err = kMalformedErr );
-	}
-	
-	// Parse the address.
-	
-	ptr		 = inStr;
-	dst		 = inBuffer;
-	lim		 = dst + 16;
-	colonPtr = NULL;
-	sawDigit = 0;
-	v		 = 0;
-	while( ( ( c = *inStr++ ) != '\0' ) && ( c != '%' ) && ( c != '/' ) && ( c != ']' ) )
-	{
-		if(   ( c >= 'a' ) && ( c <= 'f' ) ) c -= ( 'a' - 'A' );
-		if( ( ( c >= '0' ) && ( c <= '9' ) ) || ( ( c >= 'A' ) && ( c <= 'F' ) ) )
-		{
-			c -= '0';
-			check( c < (int) countof( kASCIItoHexTable ) );
-			v = ( v << 4 ) | kASCIItoHexTable[ c ];
-			require_action_quiet( v <= 0xFFFF, exit, err = kRangeErr );
-			sawDigit = 1;
-			continue;
-		}
-		if( c == ':' )
-		{
-			ptr = inStr;
-			if( !sawDigit )
-			{
-				require_action_quiet( !colonPtr, exit, err = kMalformedErr );
-				colonPtr = dst;
-				continue;
-			}
-			require_action_quiet( *inStr != '\0', exit, err = kUnderrunErr );
-			require_action_quiet( ( dst + 2 ) <= lim, exit, err = kOverrunErr );
-			*dst++ = (uint8_t)( ( v >> 8 ) & 0xFF );
-			*dst++ = (uint8_t)(   v        & 0xFF );
-			sawDigit = 0;
-			v = 0;
-			continue;
-		}
-		
-		// Handle IPv4-mapped/compatible addresses (e.g. ::FFFF:1.2.3.4).
-		
-		if( inAllowV4Mapped && ( c == '.' ) && ( ( dst + 4 ) <= lim ) )
-		{
-			err = _ParseIPv4Address( ptr, dst, &inStr );
-			require_noerr_quiet( err, exit );
-			dst += 4;
-			sawDigit = 0;
-			++inStr; // Increment because the code below expects the end to be at "inStr - 1".
-		}
-		break;
-	}
-	if( sawDigit )
-	{
-		require_action_quiet( ( dst + 2 ) <= lim, exit, err = kOverrunErr );
-		*dst++ = (uint8_t)( ( v >> 8 ) & 0xFF );
-		*dst++ = (uint8_t)(   v        & 0xFF );
-	}
-	check( dst <= lim );
-	if( colonPtr )
-	{
-		require_action_quiet( dst < lim, exit, err = kOverrunErr );
-		n = (int)( dst - colonPtr );
-		for( i = 1; i <= n; ++i )
-		{
-			lim[ -i ] = colonPtr[ n - i ];
-			colonPtr[ n - i ] = 0;
-		}
-		dst = lim;
-	}
-	require_action_quiet( dst == lim, exit, err = kUnderrunErr );
-	
-	*outStr = inStr - 1;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ParseIPv6Scope
-//
-//	Note: This was copied from CoreUtils because the StringToIPv6Address function is currently not exported in the framework.
-//===========================================================================================================================
-
-static OSStatus	_ParseIPv6Scope( const char *inStr, uint32_t *outScope, const char **outStr )
-{
-#if( TARGET_OS_POSIX )
-	OSStatus			err;
-	char				scopeStr[ 64 ];
-	char *				dst;
-	char *				lim;
-	int					c;
-	uint32_t			scope;
-	const char *		ptr;
-	
-	// Copy into a local NULL-terminated string since that is what if_nametoindex expects.
-	
-	dst = scopeStr;
-	lim = dst + ( countof( scopeStr ) - 1 );
-	while( ( ( c = *inStr ) != '\0' ) && ( c != ':' ) && ( c != '/' ) && ( c != ']' ) && ( dst < lim ) )
-	{
-		*dst++ = *inStr++;
-	}
-	*dst = '\0';
-	check( dst <= lim );
-	
-	// First try to map as a name and if that fails, treat it as a numeric scope.
-	
-	scope = if_nametoindex( scopeStr );
-	if( scope == 0 )
-	{
-		for( ptr = scopeStr; ( ( c = *ptr ) >= '0' ) && ( c <= '9' ); ++ptr )
-		{
-			scope = ( scope * 10 ) + ( ( (uint8_t) c ) - '0' );
-		}
-		require_action_quiet( c == '\0', exit, err = kMalformedErr );
-		require_action_quiet( ( ptr != scopeStr ) && ( ( (int)( ptr - scopeStr ) ) <= 10 ), exit, err = kMalformedErr );
-	}
-	
-	*outScope = scope;
-	*outStr   = inStr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-#else
-	OSStatus			err;
-	uint32_t			scope;
-	const char *		start;
-	int					c;
-	
-	scope = 0;
-	for( start = inStr; ( ( c = *inStr ) >= '0' ) && ( c <= '9' ); ++inStr )
-	{
-		scope = ( scope * 10 ) + ( c - '0' );
-	}
-	require_action_quiet( ( inStr != start ) && ( ( (int)( inStr - start ) ) <= 10 ), exit, err = kMalformedErr );
-	
-	*outScope = scope;
-	*outStr   = inStr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-#endif
-}
-
-//===========================================================================================================================
-//	_StringToIPv6Address
-//
-//	Note: This was copied from CoreUtils because the StringToIPv6Address function is currently not exported in the framework.
-//===========================================================================================================================
-
-static OSStatus
-	_StringToIPv6Address( 
-		const char *			inStr, 
-		StringToIPAddressFlags	inFlags, 
-		uint8_t					outIPv6[ 16 ], 
-		uint32_t *				outScope, 
-		int *					outPort, 
-		int *					outPrefix, 
-		const char **			outStr )
-{
-	OSStatus		err;
-	uint8_t			ipv6[ 16 ];
-	int				c;
-	int				hasScope;
-	uint32_t		scope;
-	int				hasPort;
-	int				port;
-	int				hasPrefix;
-	int				prefix;
-	int				hasBracket;
-	int				i;
-	
-	require_action( inStr, exit, err = kParamErr );
-	
-	if( *inStr == '[' ) ++inStr; // Skip a leading bracket for []-wrapped addresses (e.g. "[::1]:80").
-	
-	// Parse the address-only part of the address (e.g. "1::1").
-	
-	err = _ParseIPv6Address( inStr, !( inFlags & kStringToIPAddressFlagsNoIPv4Mapped ), ipv6, &inStr );
-	require_noerr_quiet( err, exit );
-	c = *inStr;
-	
-	// Parse the scope, port, or prefix length.
-	
-	hasScope	= 0;
-	scope		= 0;
-	hasPort		= 0;
-	port		= 0;
-	hasPrefix	= 0;
-	prefix		= 0;
-	hasBracket	= 0;
-	for( ;; )
-	{
-		if( c == '%' )		// Scope (e.g. "%en0" or "%5")
-		{
-			require_action_quiet( !hasScope, exit, err = kMalformedErr );
-			require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoScope ), exit, err = kUnexpectedErr );
-			++inStr;
-			err = _ParseIPv6Scope( inStr, &scope, &inStr );
-			require_noerr_quiet( err, exit );
-			hasScope = 1;
-			c = *inStr;
-		}
-		else if( c == ':' )	// Port (e.g. ":80")
-		{
-			require_action_quiet( !hasPort, exit, err = kMalformedErr );
-			require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPort ), exit, err = kUnexpectedErr );
-			while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) port = ( port * 10 ) + ( c - '0' );
-			require_action_quiet( port <= 65535, exit, err = kRangeErr );
-			hasPort = 1;
-		}
-		else if( c == '/' )	// Prefix Length (e.g. "/64")
-		{
-			require_action_quiet( !hasPrefix, exit, err = kMalformedErr );
-			require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPrefix ), exit, err = kUnexpectedErr );
-			while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) prefix = ( prefix * 10 ) + ( c - '0' );
-			require_action_quiet( ( prefix >= 0 ) && ( prefix <= 128 ), exit, err = kRangeErr );
-			hasPrefix = 1;
-		}
-		else if( c == ']' )
-		{
-			require_action_quiet( !hasBracket, exit, err = kMalformedErr );
-			hasBracket = 1;
-			c = *( ++inStr );
-		}
-		else
-		{
-			break;
-		}
-	}
-	
-	// Return the results. Only fill in scope/port/prefix results if the info was found to allow for defaults.
-	
-	if( outIPv6 )				 for( i = 0; i < 16; ++i ) outIPv6[ i ] = ipv6[ i ];
-	if( outScope  && hasScope )  *outScope	= scope;
-	if( outPort   && hasPort )   *outPort	= port;
-	if( outPrefix && hasPrefix ) *outPrefix	= prefix;
-	if( outStr )				 *outStr	= inStr;
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	_ParseQuotedEscapedString
-//
-//	Note: This was copied from CoreUtils because it's currently not exported in the framework.
-//===========================================================================================================================
-
-static Boolean
-	_ParseQuotedEscapedString( 
-		const char *	inSrc, 
-		const char *	inEnd, 
-		const char *	inDelimiters, 
-		char *			inBuf, 
-		size_t			inMaxLen, 
-		size_t *		outCopiedLen, 
-		size_t *		outTotalLen, 
-		const char **	outSrc )
-{
-	const unsigned char *		src;
-	const unsigned char *		end;
-	unsigned char *				dst;
-	unsigned char *				lim;
-	unsigned char				c;
-	unsigned char				c2;
-	size_t						totalLen;
-	Boolean						singleQuote;
-	Boolean						doubleQuote;
-	
-	if( inEnd == NULL ) inEnd = inSrc + strlen( inSrc );
-	src = (const unsigned char *) inSrc;
-	end = (const unsigned char *) inEnd;
-	dst = (unsigned char *) inBuf;
-	lim = dst + inMaxLen;
-	while( ( src < end ) && isspace_safe( *src ) ) ++src; // Skip leading spaces.
-	if( src >= end ) return( false );
-	
-	// Parse each argument from the string.
-	//
-	// See <http://resources.mpi-inf.mpg.de/departments/rg1/teaching/unixffb-ss98/quoting-guide.html> for details.
-	
-	totalLen = 0;
-	singleQuote = false;
-	doubleQuote = false;
-	while( src < end )
-	{
-		c = *src++;
-		if( singleQuote )
-		{
-			// Single quotes protect everything (even backslashes, newlines, etc.) except single quotes.
-			
-			if( c == '\'' )
-			{
-				singleQuote = false;
-				continue;
-			}
-		}
-		else if( doubleQuote )
-		{
-			// Double quotes protect everything except double quotes and backslashes. A backslash can be 
-			// used to protect " or \ within double quotes. A backslash-newline pair disappears completely.
-			// A backslash followed by x or X and 2 hex digits (e.g. "\x1f") is stored as that hex byte.
-			// A backslash followed by 3 octal digits (e.g. "\377") is stored as that octal byte.
-			// A backslash that does not precede ", \, x, X, or a newline is taken literally.
-			
-			if( c == '"' )
-			{
-				doubleQuote = false;
-				continue;
-			}
-			else if( c == '\\' )
-			{
-				if( src < end )
-				{
-					c2 = *src;
-					if( ( c2 == '"' ) || ( c2 == '\\' ) )
-					{
-						++src;
-						c = c2;
-					}
-					else if( c2 == '\n' )
-					{
-						++src;
-						continue;
-					}
-					else if( ( c2 == 'x' ) || ( c2 == 'X' ) )
-					{
-						++src;
-						c = c2;
-						if( ( ( end - src ) >= 2 ) && IsHexPair( src ) )
-						{
-							c = HexPairToByte( src );
-							src += 2;
-						}
-					}
-					else if( isoctal_safe( c2 ) )
-					{
-						if( ( ( end - src ) >= 3 ) && IsOctalTriple( src ) )
-						{
-							c = OctalTripleToByte( src );
-							src += 3;
-						}
-					}
-				}
-			}
-		}
-		else if( strchr( inDelimiters, c ) )
-		{
-			break;
-		}
-		else if( c == '\\' )
-		{
-			// A backslash protects the next character, except a newline, x, X and 2 hex bytes or 3 octal bytes. 
-			// A backslash followed by a newline disappears completely.
-			// A backslash followed by x or X and 2 hex digits (e.g. "\x1f") is stored as that hex byte.
-			// A backslash followed by 3 octal digits (e.g. "\377") is stored as that octal byte.
-			
-			if( src < end )
-			{
-				c = *src;
-				if( c == '\n' )
-				{
-					++src;
-					continue;
-				}
-				else if( ( c == 'x' ) || ( c == 'X' ) )
-				{
-					++src;
-					if( ( ( end - src ) >= 2 ) && IsHexPair( src ) )
-					{
-						c = HexPairToByte( src );
-						src += 2;
-					}
-				}
-				else if( isoctal_safe( c ) )
-				{
-					if( ( ( end - src ) >= 3 ) && IsOctalTriple( src ) )
-					{
-						c = OctalTripleToByte( src );
-						src += 3;
-					}
-					else
-					{
-						++src;
-					}
-				}
-				else
-				{
-					++src;
-				}
-			}
-		}
-		else if( c == '\'' )
-		{
-			singleQuote = true;
-			continue;
-		}
-		else if( c == '"' )
-		{
-			doubleQuote = true;
-			continue;
-		}
-		
-		if( dst < lim )
-		{
-			if( inBuf ) *dst = c;
-			++dst;
-		}
-		++totalLen;
-	}
-	
-	if( outCopiedLen )	*outCopiedLen	= (size_t)( dst - ( (unsigned char *) inBuf ) );
-	if( outTotalLen )	*outTotalLen	= totalLen;
-	if( outSrc )		*outSrc			= (const char *) src;
-	return( true );
-}
-
-//===========================================================================================================================
-//	_ServerSocketOpenEx2
-//
-//	Note: Based on ServerSocketOpenEx() from CoreUtils. Added parameter to not use SO_REUSEPORT.
-//===========================================================================================================================
-
-static OSStatus
-	_ServerSocketOpenEx2( 
-		int				inFamily, 
-		int				inType, 
-		int				inProtocol, 
-		const void *	inAddr, 
-		int				inPort, 
-		int *			outPort, 
-		int				inRcvBufSize, 
-		Boolean			inNoPortReuse,
-		SocketRef *		outSock )
-{
-	OSStatus		err;
-	int				port;
-	SocketRef		sock;
-	int				name;
-	int				option;
-	sockaddr_ip		sip;
-	socklen_t		len;
-	
-	port = ( inPort < 0 ) ? -inPort : inPort; // Negated port number means "try this port, but allow dynamic".
-	
-	sock = socket( inFamily, inType, inProtocol );
-	err = map_socket_creation_errno( sock );
-	require_noerr_quiet( err, exit );
-	
-#if( defined( SO_NOSIGPIPE ) )
-	setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, (socklen_t) sizeof( int ) );
-#endif
-	
-	err = SocketMakeNonBlocking( sock );
-	require_noerr( err, exit );
-	
-	// Set receive buffer size. This has to be done on the listening socket *before* listen is called because
-	// accept does not return until after the window scale option is exchanged during the 3-way handshake. 
-	// Since accept returns a new socket, the only way to use a larger window scale option is to set the buffer
-	// size on the listening socket since SO_RCVBUF is inherited by the accepted socket. See UNPv1e3 Section 7.5.
-	
-	err = SocketSetBufferSize( sock, SO_RCVBUF, inRcvBufSize );
-	check_noerr( err );
-	
-	// Allow port or address reuse because we may bind separate IPv4 and IPv6 sockets to the same port.
-	
-	if( ( inType != SOCK_DGRAM ) || !inNoPortReuse )
-	{
-		option = 1;
-		name = ( inType == SOCK_DGRAM ) ? SO_REUSEPORT : SO_REUSEADDR;
-		err = setsockopt( sock, SOL_SOCKET, name, (char *) &option, (socklen_t) sizeof( option ) );
-		err = map_socket_noerr_errno( sock, err );
-		require_noerr( err, exit );
-	}
-	
-	if( inFamily == AF_INET )
-	{
-		// Bind to the port. If it fails, retry with a dynamic port.
-		
-		memset( &sip.v4, 0, sizeof( sip.v4 ) );
-		SIN_LEN_SET( &sip.v4 );
-		sip.v4.sin_family		= AF_INET;
-		sip.v4.sin_port			= htons( (uint16_t) port );
-		sip.v4.sin_addr.s_addr	= inAddr ? *( (const uint32_t *) inAddr ) : htonl( INADDR_ANY );
-		err = bind( sock, &sip.sa, (socklen_t) sizeof( sip.v4 ) );
-		err = map_socket_noerr_errno( sock, err );
-		if( err && ( inPort < 0 ) )
-		{
-			sip.v4.sin_port = 0;
-			err = bind( sock, &sip.sa, (socklen_t) sizeof( sip.v4 ) );
-			err = map_socket_noerr_errno( sock, err );
-		}
-		require_noerr( err, exit );
-	}
-#if( defined( AF_INET6 ) )
-	else if( inFamily == AF_INET6 )
-	{
-		// Restrict this socket to IPv6 only because we're going to use a separate socket for IPv4.
-		
-		option = 1;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, (socklen_t) sizeof( option ) );
-		err = map_socket_noerr_errno( sock, err );
-		require_noerr( err, exit );
-		
-		// Bind to the port. If it fails, retry with a dynamic port.
-		
-		memset( &sip.v6, 0, sizeof( sip.v6 ) );
-		SIN6_LEN_SET( &sip.v6 );
-		sip.v6.sin6_family	= AF_INET6;
-		sip.v6.sin6_port	= htons( (uint16_t) port );
-		sip.v6.sin6_addr	= inAddr ? *( (const struct in6_addr *) inAddr ) : in6addr_any;	
-		err = bind( sock, &sip.sa, (socklen_t) sizeof( sip.v6 ) );
-		err = map_socket_noerr_errno( sock, err );
-		if( err && ( inPort < 0 ) )
-		{
-			sip.v6.sin6_port = 0;
-			err = bind( sock, &sip.sa, (socklen_t) sizeof( sip.v6 ) );
-			err = map_socket_noerr_errno( sock, err );
-		}
-		require_noerr( err, exit );
-	}
-#endif
-	else
-	{
-		dlogassert( "Unsupported family: %d", inFamily );
-		err = kUnsupportedErr;
-		goto exit;
-	}
-	
-	if( inType == SOCK_STREAM )
-	{
-		err = listen( sock, SOMAXCONN );
-		err = map_socket_noerr_errno( sock, err );
-		if( err )
-		{
-			err = listen( sock, 5 );
-			err = map_socket_noerr_errno( sock, err );
-			require_noerr( err, exit );
-		}
-	}
-	
-	if( outPort )
-	{
-		len = (socklen_t) sizeof( sip );
-		err = getsockname( sock, &sip.sa, &len );
-		err = map_socket_noerr_errno( sock, err );
-		require_noerr( err, exit );
-		
-		*outPort = SockAddrGetPort( &sip );
-	}
-	*outSock = sock;
-	sock = kInvalidSocketRef;
-	
-exit:
-	ForgetSocket( &sock );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_memdup
-//
-//	Note: This was copied from CoreUtils because it's currently not exported in the framework.
-//===========================================================================================================================
-
-static void *	_memdup( const void *inPtr, size_t inLen )
-{
-	void *		mem;
-	
-	mem = malloc( ( inLen > 0 ) ? inLen : 1 ); // If inLen is 0, use 1 since malloc( 0 ) is not well defined.
-	require( mem, exit );
-	if( inLen > 0 ) memcpy( mem, inPtr, inLen );
-	
-exit:
-	return( mem );
-}
-
-//===========================================================================================================================
-//	_memicmp
-//
-//	Note: This was copied from CoreUtils because it's currently not exported in the framework.
-//===========================================================================================================================
-
-static int	_memicmp( const void *inP1, const void *inP2, size_t inLen )
-{
-	const unsigned char *		p1;
-	const unsigned char *		e1;
-	const unsigned char *		p2;
-	int							c1;
-	int							c2;
-	
-	p1 = (const unsigned char *) inP1;
-	e1 = p1 + inLen;
-	p2 = (const unsigned char *) inP2;
-	while( p1 < e1 )
-	{
-		c1 = *p1++;
-		c2 = *p2++;
-		c1 = tolower( c1 );
-		c2 = tolower( c2 );
-		if( c1 < c2 ) return( -1 );
-		if( c1 > c2 ) return(  1 );
-	}
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	_FNV1
-//
-//	Note: This was copied from CoreUtils because it's currently not exported in the framework.
-//===========================================================================================================================
-
-static uint32_t	_FNV1( const void *inData, size_t inSize )
-{
-	const uint8_t *				src = (const uint8_t *) inData;
-	const uint8_t * const		end = src + inSize;
-	uint32_t					hash;
-	
-	hash = 0x811c9dc5U;
-	while( src != end )
-	{
-		hash *= 0x01000193;
-		hash ^= *src++;
-	}
-	return( hash );
-}
-
-//===========================================================================================================================
-//	_UIint32FromArgString
-//===========================================================================================================================
-
-static OSStatus	_UInt32FromArgString( const char * const inArgStr, const char * const inArgName, uint32_t * const outValue )
-{
-	OSStatus		err;
-	int64_t			i64;
-	
-	i64 = _StringToInt64( inArgStr, &err );
-	require_noerr_quiet( err, exit );
-	require_action_quiet( ( i64 >= 0 ) && ( i64 <= UINT32_MAX ), exit, err = kRangeErr );
-	
-	*outValue = (uint32_t) i64;
-	
-exit:
-	if( err ) FPrintF( stderr, "error: Invalid %s '%s'. Valid range is [0, %u].\n", inArgName, inArgStr, UINT32_MAX );
-	return( err );
-}
-
-//===========================================================================================================================
-//	_UnixTimeToDateAndTimeString
-//===========================================================================================================================
-
-static char *	_UnixTimeToDateAndTimeString( const int64_t inTimeSecs, char * const inBufPtr, const size_t inBufLen )
-{
-	OSStatus		err;
-	
-	// If the number of seconds is representable as a time_t value, then use the standard library functions to create a
-	// local date and time string. If not (e.g., time_t may be a 32-bit signed integer type), then try to create a UTC
-	// date and time string with CoreUtils as a fallback.
-	
-	if( ( (time_t) inTimeSecs ) == inTimeSecs )
-	{
-		struct tm			tm;
-		struct tm *			tmPtr;
-		size_t				len;
-		const time_t		timeSecs = (time_t) inTimeSecs;
-		
-		tmPtr = localtime_r( &timeSecs, &tm );
-		require_action( tmPtr, exit, err = kUnknownErr );
-		
-		// Local date and time in ISO 8601 date, hours, minutes, seconds, and time zone format.
-		
-		len = strftime( inBufPtr, inBufLen, "%Y-%m-%dT%H:%M:%S%z", tmPtr );
-		require_action_quiet( len > 0, exit, err = kUnknownErr );
-	}
-	else
-	{
-		const int64_t		epochSecs	= INT64_C_safe( kDaysToUnixEpoch ) * kSecondsPerDay;
-		const int64_t		year10KSecs	= ( YearToDays( 10000 ) - INT64_C_safe( kDaysToUnixEpoch ) ) * kSecondsPerDay;
-		int					year, month, day, hour, minute, second;
-		
-		// Ensure that the time's year is representable by four digits, i.e., before 10,000 A.D.
-		
-		require_action_quiet( inTimeSecs >= -epochSecs, exit, err = kNotHandledErr );
-		require_action_quiet( inTimeSecs < year10KSecs, exit, err = kNotHandledErr );
-		
-		// UTC date and time in ISO 8601 date, hours, minutes, and seconds format.
-		
-		SecondsToYMD_HMS( epochSecs + inTimeSecs, &year, &month, &day, &hour, &minute, &second );
-		SNPrintF( inBufPtr, inBufLen, "%04d-%02d-%02dT%02d:%02d:%02dZ", year, month, day, hour, minute, second );
-	}
-	err = kNoErr;
-	
-exit:
-	if( err && ( inBufLen > 0 ) ) inBufPtr[ 0 ] = '\0';
-	return( err ? NULL : inBufPtr );
-}
-
-//===========================================================================================================================
-//	_DNSSDSourceVersionToCString
-//===========================================================================================================================
-
-static char *	_DNSSDSourceVersionToCString( const uint32_t inVersion, char * const inBufPtr, const size_t inBufLen )
-{
-	uint32_t		x, y, z;
-	
-	// Version strings are of the form x[.y[.z]].
-	// Newer version strings are encoded as (x * 1000000) + (y * 1000) + z, where 0 ≤ y,z ≤ 999.
-	// Older version strings were encoded as (x * 10000) + (y * 100) + z, where 0 ≤ y,z ≤ 99.
-	
-	if( inVersion > DNS_SD_ORIGINAL_ENCODING_VERSION_NUMBER_MAX )
-	{
-		x =   inVersion / 1000000;
-		y = ( inVersion /    1000 ) % 1000;
-		z =   inVersion             % 1000;
-	}
-	else
-	{
-		x =   inVersion / 10000;
-		y = ( inVersion /   100 ) % 100;
-		z =   inVersion           % 100;
-	}
-	if( z > 0 )			SNPrintF( inBufPtr, inBufLen, "%u.%u.%u", x, y, z );
-	else if( y > 0 )	SNPrintF( inBufPtr, inBufLen, "%u.%u", x, y );
-	else				SNPrintF( inBufPtr, inBufLen, "%u", x );
-	return( inBufPtr );
-}
-
-//===========================================================================================================================
-//	_StdOutIsTTY
-//===========================================================================================================================
-
-static Boolean	_StdOutIsTTY( void )
-{
-	static dispatch_once_t		sOnce	= 0;
-	static Boolean				sIsTTY	= false;
-	
-	dispatch_once( &sOnce,
-	^{
-		sIsTTY = isatty( STDOUT_FILENO ) ? true : false;
-	});
-	return( sIsTTY );
-}
-
-#if( TARGET_OS_IOS )
-//===========================================================================================================================
-//	_StdErrIsTTY
-//===========================================================================================================================
-
-static Boolean	_StdErrIsTTY( void )
-{
-	static dispatch_once_t		sOnce	= 0;
-	static Boolean				sIsTTY	= false;
-	
-	dispatch_once( &sOnce,
-	^{
-		sIsTTY = isatty( STDERR_FILENO ) ? true : false;
-	});
-	return( sIsTTY );
-}
-#endif
-
-//===========================================================================================================================
-//	_PrintValidatedToStdOut
-//===========================================================================================================================
-
-static void	_PrintValidatedToStdOut( const char * const inPrefix, const Boolean inValidated, const char * const inSuffix )
-{
-	FPrintF_safe( stdout, "%s%s%svalidated%s%s",
-		inPrefix,
-		_StdOutIsTTY() ? ( inValidated ? kANSIGreen : kANSIRed ) : "",
-		inValidated ? "" : "not ",
-		_StdOutIsTTY() ? kANSINormal : "",
-		inSuffix );
-}
-
-//===========================================================================================================================
-//	_DNSProtocolIsSecure
-//===========================================================================================================================
-
-static Boolean	_DNSProtocolIsSecure( const DNSProtocol inProtocol )
-{
-	switch( inProtocol )
-	{
-		case kDNSProtocol_Do53:	return( false );
-		case kDNSProtocol_DoT:	return( true );
-		case kDNSProtocol_DoH:	return( true );
-	}
-	return( false );
-}
-
-//===========================================================================================================================
-//	_DNSProtocolToString
-//===========================================================================================================================
-
-static const char *	_DNSProtocolToString( const DNSProtocol inProtocol )
-{
-	switch( inProtocol )
-	{
-		case kDNSProtocol_Do53:	return( kDNSProtocolStr_Do53 );
-		case kDNSProtocol_DoT:	return( kDNSProtocolStr_DoT );
-		case kDNSProtocol_DoH:	return( kDNSProtocolStr_DoH );
-	}
-	return( NULL );
-}
diff --git a/Clients/mDNSNetMonitor.VisualStudio/resource.h b/Clients/mDNSNetMonitor.VisualStudio/resource.h
deleted file mode 100644
index 31ad9f0..0000000
--- a/Clients/mDNSNetMonitor.VisualStudio/resource.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by mDNSNetMonitor.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/Clients/srputil/srputil.c b/Clients/srputil/srputil.c
deleted file mode 100644
index de2595f..0000000
--- a/Clients/srputil/srputil.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/* srputil.c
- *
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * SRP Advertising Proxy utility program, allows:
- *   start/stop advertising proxy
- *   get/track list of service types
- *   get/track list of services of a particular type
- *   get/track list of hosts
- *   get/track information about a particular host
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dns_sd.h>
-#include <net/if.h>
-#include <inttypes.h>
-
-void *main_queue = NULL;
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "advertising_proxy_services.h"
-
-
-static void
-flushed_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("flushed: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after flushing.
-    exit(0);
-}
-
-static void
-block_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("blocked: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after blocking.
-    exit(0);
-}
-
-static void
-unblock_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("unblocked: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after unblocking.
-    exit(0);
-}
-
-static void
-regenerate_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("regenerated ula: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after unblocking.
-    exit(0);
-}
-
-static void
-prefix_advertise_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("advertise prefix: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after advertising prefix.
-    exit(0);
-}
-
-static void
-add_prefix_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("add prefix: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after advertising prefix.
-    exit(0);
-}
-
-static void
-remove_prefix_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("remove prefix: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after advertising prefix.
-    exit(0);
-}
-
-static void
-stop_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("stopped: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after stopping.
-    exit(0);
-}
-
-static const char *
-print_address(advertising_proxy_host_address_t *address, char *addrbuf, size_t addrbuf_size)
-{
-    if (address->rrtype == 0) {
-        return (char *)address->rdata;
-    } else if (address->rrtype == dns_rrtype_a && address->rdlen == 4) {
-        inet_ntop(AF_INET, address->rdata, addrbuf, (socklen_t)addrbuf_size);
-        return addrbuf;
-    } else if (address->rrtype == dns_rrtype_aaaa && address->rdlen == 16) {
-        inet_ntop(AF_INET6, address->rdata, addrbuf, (socklen_t)addrbuf_size);
-        return addrbuf;
-    } else {
-        sprintf(addrbuf, "Family-%d", address->rrtype);
-        return addrbuf;
-    }
-}
-
-static void
-services_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    int i;
-    int64_t lease, hours, minutes, seconds;
-    advertising_proxy_host_t *host = result;
-    const char *address = "<no address>";
-    char *addrbuf = NULL;
-    size_t addrbuflen;
-    uint64_t ula;
-
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        INFO("services: cref %p  response %p   err %d.", cref, result, err);
-        exit(1);
-    }
-    if (result == NULL) {
-        INFO("services: cref %p  response %p   err %d.", cref, result, err);
-        exit(0);
-    }
-
-    if (host->num_instances == 0) {
-        i = -1;
-    } else {
-        i = 0;
-    }
-    for (; i < host->num_instances; i++) {
-        const char *instance_name, *service_type;
-        char port[6]; // uint16_t as ascii
-
-        if (i == -1 || host->instances[i].instance_name == NULL) {
-            instance_name = "<no instances>";
-            service_type = "";
-            port[0] = 0;
-        } else {
-            instance_name = host->instances[i].instance_name;
-            service_type = host->instances[i].service_type;
-            snprintf(port, sizeof(port), "%u", host->instances[i].port);
-        }
-
-        if (host->num_addresses > 0) {
-            addrbuflen = host->num_addresses * (INET6_ADDRSTRLEN + 1);
-            addrbuf = malloc(addrbuflen);
-            if (addrbuf == NULL) {
-                address = "<no memory for address buffer>";
-            } else {
-                char *ap = addrbuf;
-                for (int j = 0; j < host->num_addresses; j++) {
-                    *ap++ = ' ';
-                    address = print_address(&host->addresses[j], ap, addrbuflen - (ap - addrbuf));
-                    size_t len = strlen(address);
-                    if (address != ap) {
-                        if (len + ap + 1 > addrbuf + addrbuflen) {
-                            len = addrbuflen - (ap - addrbuf) - 1;
-                        }
-                        memcpy(ap, address, len + 1); // Includes NUL
-                    }
-                    ap += len;
-                }
-                address = addrbuf;
-            }
-        }
-        lease = host->lease_time;
-        hours = lease / 3600 / 1000;
-        lease -= hours * 3600 * 1000;
-        minutes = lease / 60 / 1000;
-        lease -= minutes * 60 * 1000;
-        seconds = lease / 1000;
-        lease -= seconds * 1000;
-
-        // Our implementation of the stable server ID uses the server ULA, so just copy out those 48 bits,
-        // which are in network byte order.
-        ula = 0;
-        for (int j = 1; j < 6; j++) {
-            ula = ula << 8 | (((uint8_t *)&host->server_id)[j]);
-        }
-        printf("\"%s\" \"%s\" %s %s %s %" PRIu64 ":%" PRIu64 ":%" PRIu64 ".%" PRIu64 " \"%s\" %s %" PRIx64 "\n",
-               host->regname, instance_name, service_type, port,
-               address == NULL ? "" : address, hours, minutes, seconds, lease, host->hostname, host->removed ? "invalid" : "valid",
-               ula);
-        if (addrbuf != NULL) {
-            free(addrbuf);
-        }
-    }
-}
-
-static void
-ula_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("get_ula: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        fprintf(stderr, "ULA get failed: %d\n", err);
-        exit(1);
-    }
-    uint64_t ula = *((uint64_t *)result);
-    printf("ULA: %" PRIx64 "\n", ula);
-    exit(0);
-}
-
-static void
-disable_srp_replication_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("disable_srp_replication: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    // We don't need to wait around after SRP replication disabled.
-    exit(0);
-}
-
-static void
-drop_srpl_connection_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("drop_srpl_connection: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    exit(0);
-}
-
-static void
-undrop_srpl_connection_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("undrop_srpl_connection: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    exit(0);
-}
-
-static void
-drop_srpl_advertisement_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("drop_srpl_advertisement: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    exit(0);
-}
-
-static void
-undrop_srpl_advertisement_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("undrop_srpl_advertisement: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    exit(0);
-}
-
-static void
-start_dropping_push_connections_callback(advertising_proxy_conn_ref cref, void *result, advertising_proxy_error_type err)
-{
-    INFO("start_dropping_push_connections: cref %p  response %p   err %d.", cref, result, err);
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-    exit(0);
-}
-
-static comm_t *tcp_connection;
-bool do_tcp_zero_test = false;
-bool do_tcp_fin_length = false;
-bool do_tcp_fin_payload = false;
-
-static void
-tcp_datagram_callback(comm_t *NONNULL comm, message_t *NONNULL message, void *NULLABLE context)
-{
-    (void)comm;
-    (void)context;
-    fprintf(stderr, "tcp datagram received, length %d", message->length);
-}
-
-static void
-tcp_connect_callback(comm_t *NONNULL connection, void *NULLABLE context)
-{
-    fprintf(stderr, "tcp connection succeeded...\n");
-    uint8_t length[2];
-    struct iovec iov[2];
-    char databuf[128];
-    memset(databuf, 0, sizeof(databuf));
-    memset(iov, 0, sizeof(iov));
-
-    (void)context;
-
-    if (do_tcp_zero_test) {
-        memset(length, 0, sizeof(length));
-        iov[0].iov_len = 2;
-        iov[0].iov_base = length;
-        ioloop_send_data(connection, NULL, iov, 1);
-    } else if (do_tcp_fin_length) {
-        memset(length, 0, sizeof(length));
-        iov[0].iov_len = 1;
-        iov[0].iov_base = &length;
-        ioloop_send_final_data(connection, NULL, iov, 1);
-    } else if (do_tcp_fin_payload) {
-        length[0] = 0;
-        length[1] = 255;
-        iov[0].iov_len = 2;
-        iov[0].iov_base = length;
-        iov[1].iov_len = 128;
-        iov[1].iov_base = databuf;
-        ioloop_send_final_data(connection, NULL, iov, 2);
-    }
-}
-
-static void
-tcp_disconnect_callback(comm_t *NONNULL comm, void *NULLABLE context, int error)
-{
-    (void)comm;
-    (void)context;
-    (void)error;
-    fprintf(stderr, "tcp remote close.\n");
-    exit(0);
-}
-
-static int
-start_tcp_test(void)
-{
-    addr_t address;
-    memset(&address, 0, sizeof(address));
-    address.sa.sa_family = AF_INET;
-    address.sin.sin_addr.s_addr = htonl(0x7f000001);
-    address.sin.sin_port = htons(53);
-#ifndef NOT_HAVE_SA_LEN
-    address.sin.sin_len = sizeof(address.sin);
-#endif
-    tcp_connection = ioloop_connection_create(&address, false, true, false, false, tcp_datagram_callback,
-                                              tcp_connect_callback, tcp_disconnect_callback, NULL, NULL);
-    if (tcp_connection == NULL) {
-        return kDNSSDAdvertisingProxyStatus_NoMemory;
-    }
-    return kDNSSDAdvertisingProxyStatus_NoError;
-}
-
-static void
-usage(void)
-{
-    fprintf(stderr, "srputil start                     -- start the SRP MDNS Proxy through launchd\n");
-    fprintf(stderr,
-            "        tcp-zero                  -- connect to port 53, send a DNS message that's got a zero-length payload\n");
-    fprintf(stderr,
-            "        tcp-fin-length            -- connect to port 53, send a DNS message that ends before length is complete\n");
-    fprintf(stderr,
-            "        tcp-fin-payload           -- connect to port 53, send a DNS message that ends before payload is complete\n");
-    fprintf(stderr, "        services                  -- get the list of services currently being advertised\n");
-    fprintf(stderr, "        block                     -- block the SRP listener\n");
-    fprintf(stderr, "        unblock                   -- unblock the SRP listener\n");
-    fprintf(stderr, "        regenerate-ula            -- generate a new ULA and restart the network\n");
-    fprintf(stderr, "        adv-prefix                -- advertise prefix to thread network\n");
-    fprintf(stderr, "        stop                      -- stop advertising as SRP server\n");
-    fprintf(stderr, "        get-ula                   -- fetch the current ULA prefix configured on the SRP server\n");
-    fprintf(stderr, "        disable-srpl              -- disable SRP replication\n");
-    fprintf(stderr, "        add-prefix <ipv6 prefix>     -- add an OMR prefix\n");
-    fprintf(stderr, "        remove-prefix <ipv6 prefix>  -- remove an OMR prefix\n");
-    fprintf(stderr, "        drop-srpl-connection      -- drop existing srp replication connections\n");
-    fprintf(stderr, "        undrop-srpl-connection    -- restart srp replication connections that were dropped \n");
-    fprintf(stderr, "        drop-srpl-advertisement   -- stop advertising srpl service (but keep it around)\n");
-    fprintf(stderr, "        undrop-srpl-advertisement -- resume advertising srpl service\n");
-    fprintf(stderr, "        start-dropping-push       -- start repeatedly dropping any active push connections after 90 seconds\n");
-#ifdef NOTYET
-    fprintf(stderr, "        flush                     -- flush all entries from the SRP proxy (for testing only)\n");
-#endif
-}
-
-bool start_proxy = false;
-bool flush_entries = false;
-bool list_services = false;
-bool block = false;
-bool unblock = false;
-bool regenerate_ula = false;
-bool adv_prefix = false;
-bool stop_proxy = false;
-bool dump_stdin = false;
-bool get_ula = false;
-bool disable_srp_replication = false;
-bool dso_test = false;
-bool drop_srpl_connection;
-bool undrop_srpl_connection;
-bool drop_srpl_advertisement;
-bool undrop_srpl_advertisement;
-bool start_dropping_push_connections;
-bool add_thread_prefix = false;
-bool remove_thread_prefix = false;
-uint8_t prefix_buf[16];
-#ifdef NOTYET
-bool watch = false;
-bool get = false;
-#endif
-
-static void
-start_activities(void *context)
-{
-    advertising_proxy_error_type err = kDNSSDAdvertisingProxyStatus_NoError;;
-    advertising_proxy_conn_ref cref = NULL;
-    (void)context;
-
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && flush_entries) {
-        err = advertising_proxy_flush_entries(&cref, main_queue, flushed_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && (do_tcp_zero_test ||
-                                                        do_tcp_fin_length || do_tcp_fin_payload)) {
-        err = start_tcp_test();
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && list_services) {
-        err = advertising_proxy_get_service_list(&cref, main_queue, services_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && block) {
-        err = advertising_proxy_block_service(&cref, main_queue, block_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && unblock) {
-        err = advertising_proxy_unblock_service(&cref, main_queue, unblock_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && regenerate_ula) {
-        err = advertising_proxy_regenerate_ula(&cref, main_queue, regenerate_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && adv_prefix) {
-        err = advertising_proxy_advertise_prefix(&cref, main_queue, prefix_advertise_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && stop_proxy) {
-        err = advertising_proxy_stop(&cref, main_queue, stop_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && get_ula) {
-        err = advertising_proxy_get_ula(&cref, main_queue, ula_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && disable_srp_replication) {
-        err = advertising_proxy_disable_srp_replication(&cref, main_queue, disable_srp_replication_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && add_thread_prefix) {
-        err = advertising_proxy_add_prefix(&cref, main_queue, add_prefix_callback, prefix_buf, sizeof(prefix_buf));
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && remove_thread_prefix) {
-        err = advertising_proxy_remove_prefix(&cref, main_queue, remove_prefix_callback, prefix_buf, sizeof(prefix_buf));
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && drop_srpl_connection) {
-        err = advertising_proxy_drop_srpl_connection(&cref, main_queue, drop_srpl_connection_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && undrop_srpl_connection) {
-        err = advertising_proxy_undrop_srpl_connection(&cref, main_queue, undrop_srpl_connection_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && drop_srpl_advertisement) {
-        err = advertising_proxy_drop_srpl_advertisement(&cref, main_queue, drop_srpl_advertisement_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && undrop_srpl_advertisement) {
-        err = advertising_proxy_undrop_srpl_advertisement(&cref, main_queue, undrop_srpl_advertisement_callback);
-    }
-    if (err == kDNSSDAdvertisingProxyStatus_NoError && start_dropping_push_connections) {
-        err = advertising_proxy_start_dropping_push_connections(&cref, main_queue, start_dropping_push_connections_callback);
-    }
-    if (err != kDNSSDAdvertisingProxyStatus_NoError) {
-        exit(1);
-    }
-}
-
-static void
-dump_packet(void)
-{
-    ssize_t len;
-    dns_message_t *message = NULL;
-    dns_wire_t wire;
-
-    len = read(0, &wire, sizeof(wire));
-    if (len < 0) {
-        ERROR("stdin: %s", strerror(errno));
-        return;
-    }
-    if (len < DNS_HEADER_SIZE) {
-        ERROR("stdin: too short: %zd bytes", len);
-        return;
-    }
-    if (!dns_wire_parse(&message, &wire, (unsigned)len, true)) {
-        fprintf(stderr, "DNS message parse failed\n");
-        return;
-    }
-}
-
-int
-main(int argc, char **argv)
-{
-    int i;
-    bool something = false;
-    bool log_stderr = false;
-
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "start")) {
-			start_proxy = true;
-            something = true;
-        } else if (!strcmp(argv[i], "tcp-zero")) {
-            do_tcp_zero_test = true;
-            something = true;
-        } else if (!strcmp(argv[i], "tcp-fin-length")) {
-            do_tcp_fin_length = true;
-            something = true;
-        } else if (!strcmp(argv[i], "tcp-fin-payload")) {
-            do_tcp_fin_payload = true;
-            something = true;
-		} else if (!strcmp(argv[i], "flush")) {
-            flush_entries = true;
-            something = true;
-		} else if (!strcmp(argv[i], "services")) {
-            list_services = true;
-            something = true;
-		} else if (!strcmp(argv[i], "block")) {
-            block = true;
-            something = true;
-		} else if (!strcmp(argv[i], "unblock")) {
-            unblock = true;
-            something = true;
-		} else if (!strcmp(argv[i], "regenerate-ula")) {
-            regenerate_ula = true;
-            something = true;
-        } else if (!strcmp(argv[i], "adv-prefix")) {
-            adv_prefix = true;
-            something = true;
-        } else if (!strcmp(argv[i], "stop")) {
-            stop_proxy = true;
-            something = true;
-        } else if (!strcmp(argv[i], "dump")) {
-            dump_packet();
-            exit(0);
-        } else if (!strcmp(argv[i], "get-ula")) {
-            get_ula = true;
-            something = true;
-        } else if (!strcmp(argv[i], "disable-srpl")) {
-            disable_srp_replication = true;
-            something = true;
-        } else if (!strcmp(argv[i], "add-prefix")) {
-            if (inet_pton(AF_INET6, argv[i + 1], prefix_buf) < 1) {
-                fprintf(stderr, "Wrong ipv6 prefix.\n");
-            } else {
-                add_thread_prefix = true;
-                something = true;
-                i++;
-            }
-        } else if (!strcmp(argv[i], "remove-prefix")) {
-            if (inet_pton(AF_INET6, argv[i + 1], prefix_buf) < 1) {
-                fprintf(stderr, "Wrong ipv6 prefix.\n");
-            } else {
-                remove_thread_prefix = true;
-                something = true;
-                i++;
-            }
-        } else if (!strcmp(argv[i], "drop-srpl-connection")) {
-            drop_srpl_connection = true;
-            something = true;
-        } else if (!strcmp(argv[i], "undrop-srpl-connection")) {
-            undrop_srpl_connection = true;
-            something = true;
-        } else if (!strcmp(argv[i], "drop-srpl-advertisement")) {
-            drop_srpl_advertisement = true;
-            something = true;
-        } else if (!strcmp(argv[i], "undrop-srpl-advertisement")) {
-            undrop_srpl_advertisement = true;
-            something = true;
-        } else if (!strcmp(argv[i], "start-dropping-push")) {
-            start_dropping_push_connections = true;
-            something = true;
-#ifdef NOTYET
-		} else if (!strcmp(argv[i], "watch")) {
-            fprintf(stderr, "Watching not implemented yet.\n");
-            exit(1);
-		} else if (!strcmp(argv[i], "get")) {
-            fprintf(stderr, "Getting not implemented yet.\n");
-            exit(1);
-#endif
-        } else if (!strcmp(argv[i], "--debug")) {
-            OPENLOG("srputil", true);
-            log_stderr = true;
-        } else {
-            usage();
-            exit(1);
-        }
-    }
-
-    if (!something) {
-        usage();
-        exit(1);
-    }
-
-    if (log_stderr == false) {
-        OPENLOG("srputil", log_stderr);
-    }
-
-    ioloop_init();
-    // Start the queue, //then// do the work
-    ioloop_run_async(start_activities, NULL);
-    ioloop();
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/DSO/dso-transport.c b/DSO/dso-transport.c
deleted file mode 100644
index 765dded..0000000
--- a/DSO/dso-transport.c
+++ /dev/null
@@ -1,1695 +0,0 @@
-/* dso-transport.c
- *
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- *
- */
-
-//*************************************************************************************************************
-// Headers
-
-#include <stdio.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <string.h>
-#include <assert.h>
-
-#include <netdb.h>              // For gethostbyname().
-#include <sys/socket.h>         // For AF_INET, AF_INET6, etc.
-#include <net/if.h>             // For IF_NAMESIZE.
-#include <netinet/in.h>         // For INADDR_NONE.
-#include <arpa/inet.h>          // For inet_addr().
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "dns_sd.h"
-#include "DNSCommon.h"
-#include "mDNSEmbeddedAPI.h"
-#include "dso.h"
-#include "dso-transport.h"
-#include "mdns_strict.h"
-#include "DebugServices.h"      // For check_compile_time_code().
-#include "mDNSDebug.h"
-#include "misc_utilities.h"     // For mDNSAddr_from_sockaddr().
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-#include "tls-keychain.h"       // For evaluate_tls_cert().
-#endif
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-// Network Framework only works on MacOS X at the moment, and we need the locking primitives for
-// MacOSX.
-#include "mDNSMacOSX.h"
-#endif
-
-extern mDNS mDNSStorage;
-
-static dso_connect_state_t *dso_connect_states; // DSO connect states that exist.
-static dso_transport_t *dso_transport_states; // DSO transport states that exist.
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-static dispatch_queue_t dso_dispatch_queue;
-#else
-static void dso_read_callback(TCPSocket *sock, void *context, mDNSBool connection_established,
-                       mStatus err);
-#endif
-
-static void dso_connect_state_process_address_port_change(const mDNSAddr *addr_changed, mDNSIPPort port,
-                                                          bool add, dso_connect_state_t *const cs);
-static void dso_connect_internal(dso_connect_state_t *cs, mDNSBool reconnecting);
-
-void
-dso_transport_init(void)
-{
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    // It's conceivable that we might want a separate queue, but we don't know yet, so for
-    // now we just use the main dispatch queue, which should be on the main dispatch thread,
-    // which is _NOT_ the kevent thread.   So whenever we are doing anything on the dispatch
-    // queue (any completion functions for NW framework) we need to acquire the lock before
-    // we even look at any variables that could be changed by the other thread.
-    dso_dispatch_queue = dispatch_get_main_queue();
-#endif
-}
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-static dso_connect_state_t *
-dso_connect_state_find(uint32_t serial)
-{
-    dso_connect_state_t *csp;
-    for (csp = dso_connect_states; csp; csp = csp->next) {
-        if (csp->serial ==  serial) {
-            return csp;
-        }
-    }
-    return NULL;
-}
-#endif
-
-static void
-dso_transport_finalize(dso_transport_t *transport, const char *whence)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u->DSOT%u] dso_transport_t finalizing for " PUB_S " - "
-              "transport: %p.", transport->dso != NULL ? transport->dso->serial : DSO_STATE_INVALID_SERIAL,
-              transport->serial, whence, transport);
-
-    dso_transport_t **tp = &dso_transport_states;
-    for (; *tp != NULL && *tp != transport; tp = &((*tp)->next))
-        ;
-    if (*tp != NULL) {
-        *tp = (*tp)->next;
-    } else {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "dso_transport_t is not in the dso_transport_states list -"
-            " transport: %p.", transport);
-    }
-
-    if (transport->connection != NULL) {
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-        nw_release(transport->connection);
-#else
-        mDNSPlatformTCPCloseConnection(transport->connection);
-#endif
-        transport->connection = NULL;
-    } else {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "Finalizing a dso_transport_t with no corresponding underlying connection - transport: %p.", transport);
-    }
-
-    mdns_free(transport);
-}
-
-// dso_connect_state_t objects that have been canceled but aren't yet freed.
-static dso_connect_state_t *dso_connect_state_needing_clean_up = NULL;
-
-// We do all of the finalization for the dso state object and any objects it depends on here in the
-// dso_idle function because it avoids the possibility that some code on the way out to the event loop
-// _after_ the DSO connection has been dropped might still write to the DSO structure or one of the
-// dependent structures and corrupt the heap, or indeed in the unlikely event that this memory was
-// freed and then reallocated before the exit to the event loop, there could be a bad pointer
-// dereference.
-//
-// If there is a finalize function, that function MUST either free its own state that references the
-// DSO state, or else must NULL out the pointer to the DSO state.
-int32_t dso_transport_idle(void *context, int32_t now_in, int32_t next_timer_event)
-{
-    dso_connect_state_t *cs, *cnext;
-    mDNS *m = context;
-    mDNSs32 now = now_in;
-    mDNSs32 next_event = next_timer_event;
-
-    // Clean any remaining dso_connect_state_t objects that have been canceled.
-    for (cs = dso_connect_state_needing_clean_up; cs != NULL; cs = cnext) {
-        cnext = cs->next;
-        if (cs->lookup != NULL) {
-            DNSServiceRef ref = cs->lookup;
-            cs->lookup = NULL;
-            // dso_transport_idle runs under KQueueLoop() which holds a mDNS_Lock already, so directly call
-            // DNSServiceRefDeallocate() will grab the lock again. Given that:
-            // 1. dso_transport_idle runs under KQueueLoop() that does not traverse any existing mDNSCore structure.
-            // 2. The work we do here is cleaning up, not starting a new request.
-            // It is "relatively" safe and reasonable to temporarily unlock the mDNSCore lock here.
-            mDNS_DropLockBeforeCallback();
-            MDNS_DISPOSE_DNS_SERVICE_REF(ref);
-            mDNS_ReclaimLockAfterCallback();
-        }
-
-        // Remove any remaining unused addresses.
-        for (dso_transport_address_t **addrs = &cs->addrs; *addrs != NULL; ) {
-            dso_transport_address_t *addr = *addrs;
-            *addrs = addr->next;
-            mdns_free(addr);
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] dso_connect_state_t finalizing - "
-            "dso_connect: %p, hostname: " PRI_S ", dso_connect->context: %p.", cs->serial, cs, cs->hostname,
-            cs->context);
-        if (cs->dso_connect_context_callback != NULL) {
-            cs->dso_connect_context_callback(dso_connect_life_cycle_free, cs->context, cs);
-        }
-        mDNSPlatformMemFree(cs);
-    }
-    dso_connect_state_needing_clean_up = NULL;
-
-    // Notice if a DSO connection state is active but hasn't seen activity in a while.
-    for (cs = dso_connect_states; cs != NULL; cs = cnext) {
-        cnext = cs->next;
-        if (!cs->connecting && cs->last_event != 0) {
-            mDNSs32 expiry = cs->last_event + 90 * mDNSPlatformOneSecond;
-            if (now - expiry > 0) {
-                cs->last_event = 0;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] dso_transport_idle: expiry has happened "
-                          ": %p, hostname: " PRI_S ", dso_connect->context: %p; now %d expiry %d last_event %d",
-                          cs->serial, cs, cs->hostname, cs->context, now, expiry, cs->last_event);
-                cs->callback(cs->context, NULL, cs->dso, kDSOEventType_ConnectFailed);
-                // Should not touch the current dso_connect_state_t after we deliver kDSOEventType_ConnectFailed event,
-                // because it is possible that the current dso_connect_state_t has been canceled in the callback.
-                // Any status update for the canceled dso_connect_state_t will not work as expected.
-                continue;
-            } else {
-                if (next_timer_event - expiry > 0) {
-                    next_timer_event = expiry;
-                }
-            }
-        } else if (!cs->connecting && cs->reconnect_time != 0) {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] reconnect time %d "
-                      "hostname: " PRI_S ", dso_connect->context: %p.",
-                      cs->serial, now - cs->reconnect_time, cs->hostname, cs->context);
-            if (now - cs->reconnect_time > 0) {
-                cs->reconnect_time = 0; // Don't try to immediately reconnect if it fails.
-                // If cs->dso->transport is non-null, we're already connected.
-                if (cs->dso && cs->dso->transport == NULL) {
-                    cs->callback(cs->context, NULL, cs->dso, kDSOEventType_ShouldReconnect);
-                }
-                // Should not touch the current dso_connect_state_t after we deliver kDSOEventType_ShouldReconnect event,
-                // because it is possible that the current dso_connect_state_t has been canceled in the callback.
-                // Any status update for the canceled dso_connect_state_t will not work as expected.
-                continue;
-            }
-        }
-        if (cs->reconnect_time != 0 && next_event - cs->reconnect_time > 0) {
-            next_event = cs->reconnect_time;
-        }
-    }
-
-    return next_event;
-}
-
-void dso_reconnect(dso_connect_state_t *cs, dso_state_t *dso)
-{
-    cs->dso = dso;
-    dso_connect_internal(cs, mDNStrue);
-}
-
-// Call to schedule a reconnect at a later time.
-void dso_schedule_reconnect(mDNS *m, dso_connect_state_t *cs, mDNSs32 when)
-{
-    cs->reconnect_time = when * mDNSPlatformOneSecond + m->timenow;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] scheduling reconnect in %d (%d %d) seconds, "
-              "hostname: " PRI_S ", dso_connect->context: %p.", cs->serial, when,
-              m->timenow, cs->reconnect_time, cs->hostname, cs->context);
-}
-
-// If a DSO was created by an incoming connection, the creator of the listener can use this function
-// to supply context and a callback for future events.
-void dso_set_callback(dso_state_t *dso, void *context, dso_event_callback_t cb)
-{
-    dso->cb = cb;
-    dso->context = context;
-}
-
-// This is called before writing a DSO message to the output buffer.  length is the length of the message.
-// Returns true if we have successfully selected for write (which means that we're under TCP_NOTSENT_LOWAT).
-// Otherwise returns false.   It is valid to write even if it returns false, but there is a risk that
-// the write will return EWOULDBLOCK, at which point we'd have to blow away the connection.   It is also
-// valid to give up at this point and not write a message; as long as dso_write_finish isn't called, a later
-// call to dso_write_start will overwrite the length that was stored by the previous invocation.
-//
-// The circumstance in which this would occur is that we have filled the kernel's TCP output buffer for this
-// connection all the way up to TCP_NOTSENT_LOWAT, and then we get a query from the Discovery Proxy to which we
-// need to respond.  Because TCP_NOTSENT_LOWAT is fairly low, there should be a lot of room in the TCP output
-// buffer for small responses; it would need to be the case that we are getting requests from the proxy at a
-// high rate for us to fill the output buffer to the point where a write of a 12-byte response returns
-// EWOULDBLOCK; in that case, things are so dysfunctional that killing the connection isn't any worse than
-// allowing it to continue.
-
-// An additional note about the motivation for this code: the idea originally was that we'd do scatter/gather
-// I/O here: this lets us write everything out in a single sendmsg() call.   This isn't used with the mDNSPlatformTCP
-// code because it doesn't support scatter/gather.   Network Framework does, however, and in principle we could
-// write to the descriptor directly if that were really needed.
-
-bool dso_write_start(dso_transport_t *transport, size_t in_length)
-{
-    // The transport doesn't support messages outside of this range.
-    if (in_length < 12 || in_length > 65535) {
-        return false;
-    }
-
-    const uint16_t length = (uint16_t)in_length;
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    uint8_t lenbuf[2];
-
-    if (transport->to_write != NULL) {
-        nw_release(transport->to_write);
-        transport->to_write = NULL;
-    }
-    lenbuf[0] = length >> 8;
-    lenbuf[1] = length & 255;
-    transport->to_write = dispatch_data_create(lenbuf, 2, dso_dispatch_queue,
-                                               DISPATCH_DATA_DESTRUCTOR_DEFAULT);
-    if (transport->to_write == NULL) {
-        transport->write_failed = true;
-        return false;
-    }
-    transport->bytes_to_write = length + 2;
-
-    // We don't have access to TCP_NOTSENT_LOWAT, so for now we track how many bytes we've written
-    // versus how many bytes that we've written have completed, and if that creeps above MAX_UNSENT_BYTES,
-    // we return false here to indicate that there is congestion.
-    if (transport->unsent_bytes > MAX_UNSENT_BYTES) {
-        return false;
-    } else {
-        return true;
-    }
-#else
-    transport->lenbuf[0] = length >> 8;
-    transport->lenbuf[1] = length & 255;
-
-    transport->to_write[0] = transport->lenbuf;
-    transport->write_lengths[0] = 2;
-    transport->num_to_write = 1;
-
-    return mDNSPlatformTCPWritable(transport->connection);
-#endif // DSO_USES_NETWORK_FRAMEWORK
-}
-
-// Called to finish a write (dso_write_start .. dso_write .. [ dso_write ... ] dso_write_finish).  The
-// write must completely finish--if we get a partial write, this means that the connection is stalled, and
-// so we cancel it.  Since this can call dso_state_cancel, the caller must not reference the DSO state object
-// after this call if the return value is false.
-bool dso_write_finish(dso_transport_t *transport)
-{
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    const uint32_t serial = transport->dso->serial;
-    const size_t bytes_to_write = transport->bytes_to_write;
-    transport->bytes_to_write = 0;
-    if (transport->write_failed) {
-        dso_state_cancel(transport->dso);
-        return false;
-    }
-    transport->unsent_bytes += bytes_to_write;
-    nw_connection_send(transport->connection, transport->to_write, NW_CONNECTION_DEFAULT_STREAM_CONTEXT, true,
-        ^(nw_error_t  _Nullable error)
-    {
-        KQueueLock();
-        dso_state_t *const dso = dso_find_by_serial(serial);
-        if (error != NULL) {
-            const nw_error_t tmp = error;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u] dso_write_finish: write failed - "
-                "error: " PUB_S ".", serial, strerror(nw_error_get_error_code(tmp)));
-            if (dso != NULL) {
-                dso_state_cancel(dso);
-            }
-        } else {
-            if (dso != NULL && dso->transport != NULL) {
-                dso->transport->unsent_bytes -= bytes_to_write;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u] dso_write_finish: completed - "
-                    "bytes written: %zu, bytes outstanding: %zu.", serial, bytes_to_write,
-                    dso->transport->unsent_bytes);
-            } else {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING,
-                    "[DSO%u] dso_write_finish: completed but the corresponding dso_state_t has been canceled - "
-                    "bytes written: %zu.", serial, bytes_to_write);
-            }
-        }
-        KQueueUnlock("dso_write_finish completion routine");
-    });
-    nw_release(transport->to_write);
-    transport->to_write = NULL;
-    return true;
-#else
-    ssize_t result, total = 0;
-    int i;
-
-   if (transport->num_to_write > MAX_WRITE_HUNKS) {
-        LogMsg("dso_write_finish: fatal internal programming error: called %d times (more than limit of %d)",
-               transport->num_to_write, MAX_WRITE_HUNKS);
-        dso_state_cancel(transport->dso);
-        return false;
-    }
-
-    // This is our ersatz scatter/gather I/O.
-    for (i = 0; i < transport->num_to_write; i++) {
-        result = mDNSPlatformWriteTCP(transport->connection, (const char *)transport->to_write[i], transport->write_lengths[i]);
-        if (result != transport->write_lengths[i]) {
-            if (result < 0) {
-                LogMsg("dso_write_finish: fatal: mDNSPlatformWrite on %s returned %d", transport->dso->remote_name, errno);
-            } else {
-                LogMsg("dso_write_finish: fatal: mDNSPlatformWrite: short write on %s: %ld < %ld",
-                       transport->dso->remote_name, (long)result, (long)total);
-            }
-            dso_state_cancel(transport->dso);
-            return false;
-        }
-    }
-#endif
-    return true;
-}
-
-// This function may only be called after a previous call to dso_write_start; it records the length of and
-// pointer to the write buffer.  These buffers must remain valid until dso_write_finish() is called.  The
-// caller is responsible for managing the memory they contain.  The expected control flow for writing is:
-// dso_write_start(); dso_write(); dso_write(); dso_write(); dso_write_finished(); There should be one or
-// more calls to dso_write; these will ideally be translated into a single scatter/gather sendmsg call (or
-// equivalent) to the kernel.
-void dso_write(dso_transport_t *transport, const uint8_t *buf, size_t length)
-{
-    if (length == 0) {
-        return;
-    }
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    if (transport->write_failed) {
-        return;
-    }
-    dispatch_data_t dpd = dispatch_data_create(buf, length, dso_dispatch_queue,
-                                               DISPATCH_DATA_DESTRUCTOR_DEFAULT);
-    if (dpd == NULL) {
-        transport->write_failed = true;
-        return;
-    }
-    if (transport->to_write != NULL) {
-        dispatch_data_t dpc = dispatch_data_create_concat(transport->to_write, dpd);
-        MDNS_DISPOSE_DISPATCH(dpd);
-        MDNS_DISPOSE_DISPATCH(transport->to_write);
-        if (dpc == NULL) {
-            transport->to_write = NULL;
-            transport->write_failed = true;
-            return;
-        }
-        transport->to_write = dpc;
-    }
-#else
-    // We'll report this in dso_write_finish();
-    if (transport->num_to_write >= MAX_WRITE_HUNKS) {
-        transport->num_to_write++;
-        return;
-    }
-
-    transport->to_write[transport->num_to_write] = buf;
-    transport->write_lengths[transport->num_to_write] = length;
-    transport->num_to_write++;
-#endif
-}
-
-// Write a DSO message
-int dso_message_write(dso_state_t *dso, dso_message_t *msg, bool disregard_low_water)
-{
-    dso_transport_t *transport = dso->transport;
-    if (transport == NULL || transport->dso == NULL) {
-        return mStatus_BadStateErr;
-    }
-    if (transport->connection != NULL) {
-        if (dso_write_start(transport, dso_message_length(msg)) || disregard_low_water) {
-            dso_write(transport, msg->buf, msg->no_copy_bytes_offset);
-            dso_write(transport, msg->no_copy_bytes, msg->no_copy_bytes_len);
-            dso_write(transport, &msg->buf[msg->no_copy_bytes_offset], msg->cur - msg->no_copy_bytes_offset);
-            return dso_write_finish(transport);
-        }
-    }
-    return mStatus_NoMemoryErr;
-}
-
-// Replies to some message we were sent with a response code and no data.
-// This is a convenience function for replies that do not require that a new
-// packet be constructed.   It takes advantage of the fact that the message
-// to which this is a reply is still in the input buffer, and modifies that
-// message in place to turn it into a response.
-
-bool dso_send_simple_response(dso_state_t *dso, int rcode, const DNSMessageHeader *header, const char *pres)
-{
-    dso_transport_t *transport = dso->transport;
-    (void)pres; // might want this later.
-    DNSMessageHeader response = *header;
-
-    // The OPCODE is a 4-bit value in DNS message
-    if (rcode < 0 || rcode > 15) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "[DSO%u]: rcode[%d] is out of range", dso->serial, rcode);
-        return false;
-    }
-    // Just return the message, with no questions, answers, etc.
-    response.flags.b[1] = (response.flags.b[1] & ~kDNSFlag1_RC_Mask) | (uint8_t)rcode;
-    response.flags.b[0] |= kDNSFlag0_QR_Response;
-    response.numQuestions = 0;
-    response.numAnswers = 0;
-    response.numAuthorities = 0;
-    response.numAdditionals = 0;
-
-    // Buffered write back to discovery proxy
-    (void)dso_write_start(transport, 12);
-    dso_write(transport, (uint8_t *)&response, 12);
-    if (!dso_write_finish(transport)) {
-        return false;
-    }
-    return true;
-}
-
-// DSO Message we received has a primary TLV that's not implemented.
-// XXX is this what we're supposed to do here? check draft.
-bool dso_send_not_implemented(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_DSOTypeNI, header, "DSOTYPENI");
-}
-
-// Non-DSO message we received is refused.
-bool dso_send_refused(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_Refused, header, "REFUSED");
-}
-
-bool dso_send_formerr(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_FormErr, header, "FORMERR");
-}
-
-bool dso_send_servfail(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_ServFail, header, "SERVFAIL");
-}
-
-bool dso_send_name_error(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_NXDomain, header, "NXDOMAIN");
-}
-
-bool dso_send_no_error(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    return dso_send_simple_response(dso, kDNSFlag1_RC_NoErr, header, "NOERROR");
-}
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-static void dso_read_message(dso_transport_t *transport, uint32_t length);
-
-static void dso_read_message_length(dso_transport_t *transport)
-{
-    if (transport == NULL) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "dso_read_message_length: dso_transport_t is NULL while reading message");
-        return;
-    }
-
-    if (transport->dso == NULL) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "dso_read_message_length: transport->dso is NULL while reading message");
-        return;
-    }
-
-    const uint32_t serial = transport->dso->serial;
-    if (transport->connection == NULL) {
-        LogMsg("dso_read_message_length called with null connection.");
-        return;
-    }
-    nw_connection_receive(transport->connection, 2, 2,
-                          ^(dispatch_data_t content, nw_content_context_t __unused context,
-                            bool __unused is_complete, nw_error_t error) {
-                              dso_state_t *dso;
-                              // Don't touch anything or look at anything until we have the lock.
-                              KQueueLock();
-                              dso = dso_find_by_serial(serial);
-                              if (error != NULL) {
-                                  LogMsg("dso_read_message_length: read failed: %s",
-                                         strerror(nw_error_get_error_code(error)));
-                              fail:
-                                  if (dso != NULL) {
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso_state_cancel(dso);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  }
-                              } else if (content == NULL) {
-                                  dso_disconnect_context_t disconnect_context;
-                                  if (dso != NULL && transport->dso == dso && transport->dso->cb != NULL) {
-                                      LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                                                "dso_read_message_length: remote end closed connection: "
-                                                "passing disconnect event to callback.");
-                                      memset(&disconnect_context, 0, sizeof disconnect_context);
-                                      disconnect_context.reconnect_delay = 1; // reconnect in 1s
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso->transport = NULL;
-                                      nw_connection_cancel(transport->connection);
-                                      transport->dso->cb(transport->dso->context, &disconnect_context, transport->dso,
-                                                         kDSOEventType_Disconnected);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  } else if (dso != NULL) {
-                                      LogMsg("dso_read_message_length: remote end closed connection: "
-                                             "no callback to notify.");
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso_state_cancel(dso);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  }
-                              } else if (dso != NULL) {
-                                  uint32_t length;
-                                  size_t length_length;
-                                  const uint8_t *lenbuf;
-                                  dispatch_data_t map = dispatch_data_create_map(content, (const void **)&lenbuf,
-                                                                                 &length_length);
-                                  if (map == NULL) {
-                                      LogMsg("dso_read_message_length: map create failed");
-                                      goto fail;
-                                  } else if (length_length != 2) {
-                                      LogMsg("dso_read_message_length: invalid length = %d", length_length);
-                                      MDNS_DISPOSE_DISPATCH(map);
-                                      goto fail;
-                                  }
-                                  length = ((unsigned)(lenbuf[0]) << 8) | ((unsigned)lenbuf[1]);
-                                  MDNS_DISPOSE_DISPATCH(map);
-                                  dso_read_message(transport, length);
-                              } else {
-                                  LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING,
-                                      "[DSO%u] dso_read_message_length: the corresponding dso_state_t has been canceled.",
-                                      serial);
-                              }
-                              KQueueUnlock("dso_read_message_length completion routine");
-                          });
-}
-
-void dso_read_message(dso_transport_t *transport, uint32_t length)
-{
-    if (transport == NULL) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "dso_read_message: dso_transport_t is NULL while reading message");
-        return;
-    }
-    if (transport->dso == NULL) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "dso_read_message: transport->dso is NULL while reading message");
-        return;
-    }
-
-    const uint32_t serial = transport->dso->serial;
-    if (transport->connection == NULL) {
-        LogMsg("dso_read_message called with null connection.");
-        return;
-    }
-    nw_connection_receive(transport->connection, length, length,
-                          ^(dispatch_data_t content, nw_content_context_t __unused context,
-                            bool __unused is_complete, nw_error_t error) {
-                              dso_state_t *dso;
-                              // Don't touch anything or look at anything until we have the lock.
-                              KQueueLock();
-                              dso = dso_find_by_serial(serial);
-                              if (error != NULL) {
-                                  LogMsg("dso_read_message: read failed: %s", strerror(nw_error_get_error_code(error)));
-                              fail:
-                                  if (dso != NULL) {
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso_state_cancel(dso);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  }
-                              } else if (content == NULL) {
-                                  dso_disconnect_context_t disconnect_context;
-                                  if (dso != NULL && transport->dso == dso && transport->dso->cb != NULL) {
-                                      LogMsg("dso_read_message: remote end closed connection: "
-                                             "passing disconnect event to callback.");
-                                      memset(&disconnect_context, 0, sizeof disconnect_context);
-                                      disconnect_context.reconnect_delay = 1; // reconnect in 1s
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso->transport = NULL;
-                                      nw_connection_cancel(transport->connection);
-                                      transport->dso->cb(transport->dso->context, &disconnect_context, transport->dso,
-                                                         kDSOEventType_Disconnected);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  } else if (dso != NULL) {
-                                      LogMsg("dso_read_message: remote end closed connection: "
-                                             "no callback to notify.");
-                                      mDNS_Lock(&mDNSStorage);
-                                      dso_state_cancel(dso);
-                                      mDNS_Unlock(&mDNSStorage);
-                                  }
-                              } else if (dso != NULL) {
-                                  dso_message_payload_t message;
-                                  dispatch_data_t map = dispatch_data_create_map(content,
-                                                                                 (const void **)&message.message, &message.length);
-                                  if (map == NULL) {
-                                      LogMsg("dso_read_message_length: map create failed");
-                                      goto fail;
-                                  } else if (message.length != length) {
-                                      LogMsg("dso_read_message_length: only %d of %d bytes read", message.length, length);
-                                      MDNS_DISPOSE_DISPATCH(map);
-                                      goto fail;
-                                  }
-                                  // Process the message.
-                                  mDNS_Lock(&mDNSStorage);
-                                  dns_message_received(dso, message.message, message.length, &message);
-                                  mDNS_Unlock(&mDNSStorage);
-
-                                  // Release the map object now that we no longer need its buffers.
-                                  MDNS_DISPOSE_DISPATCH(map);
-
-                                  // Now read the next message length.
-                                  dso_read_message_length(transport);
-                              } else {
-                                  LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING,
-                                      "[DSO%u] dso_read_message: the corresponding dso_state_t has been canceled.",
-                                      serial);
-                              }
-                              KQueueUnlock("dso_read_message completion routine");
-                          });
-}
-#else
-// Called whenever there's data available on a DSO connection
-void dso_read_callback(TCPSocket *sock, void *context, mDNSBool connection_established, int err)
-{
-    dso_transport_t *transport = context;
-    dso_state_t *dso;
-    mDNSBool closed = mDNSfalse;
-
-    mDNS_Lock(&mDNSStorage);
-    dso = transport->dso;
-
-    // This shouldn't ever happen.
-    if (err) {
-        LogMsg("dso_read_callback: error %d", err);
-        dso_state_cancel(dso);
-        goto out;
-    }
-
-    // Connection is already established by the time we set this up.
-    if (connection_established) {
-        goto out;
-    }
-
-    // This will be true either if we have never read a message or
-    // if the last thing we did was to finish reading a message and
-    // process it.
-    if (transport->message_length == 0) {
-        transport->need_length = true;
-        transport->inbufp = transport->inbuf;
-        transport->bytes_needed = 2;
-    }
-
-    // Read up to bytes_needed bytes.
-    ssize_t count = mDNSPlatformReadTCP(sock, transport->inbufp, transport->bytes_needed, &closed);
-    // LogMsg("read(%d, %p:%p, %d) -> %d", fd, dso->inbuf, dso->inbufp, dso->bytes_needed, count);
-    if (count < 0) {
-        LogMsg("dso_read_callback: read from %s returned %d", dso->remote_name, errno);
-        dso_state_cancel(dso);
-        goto out;
-    }
-
-    // If we get selected for read and there's nothing to read, the remote end has closed the
-    // connection.
-    if (closed) {
-        LogMsg("dso_read_callback: remote %s closed", dso->remote_name);
-        dso_state_cancel(dso);
-        goto out;
-    }
-
-    transport->inbufp += count;
-    transport->bytes_needed -= count;
-
-    // If we read all the bytes we wanted, do what's next.
-    if (transport->bytes_needed == 0) {
-        // We just finished reading the complete length of a DNS-over-TCP message.
-        if (transport->need_length) {
-            // Get the number of bytes in this DNS message
-            size_t bytes_needed = (((size_t)transport->inbuf[0]) << 8) | transport->inbuf[1];
-
-            // Under no circumstances can length be zero.
-            if (bytes_needed == 0) {
-                LogMsg("dso_read_callback: %s sent zero-length message.", dso->remote_name);
-                dso_state_cancel(dso);
-                goto out;
-            }
-
-            // The input buffer size is AbsoluteMaxDNSMessageData, which is around 9000 bytes on
-            // big platforms and around 1500 bytes on smaller ones.   If the remote end has sent
-            // something larger than that, it's an error from which we can't recover.
-            if (bytes_needed > transport->inbuf_size - 2) {
-                LogMsg("dso_read_callback: fatal: Proxy at %s sent a too-long (%zd bytes) message",
-                       dso->remote_name, bytes_needed);
-                dso_state_cancel(dso);
-                goto out;
-            }
-
-            transport->message_length = bytes_needed;
-            transport->bytes_needed = bytes_needed;
-            transport->inbufp = transport->inbuf + 2;
-            transport->need_length = false;
-
-        // We just finished reading a complete DNS-over-TCP message.
-        } else {
-            dso_message_payload_t message = { &transport->inbuf[2], transport->message_length };
-            dns_message_received(dso, message.message, message.length, &message);
-            transport->message_length = 0;
-        }
-    }
-out:
-    mDNS_Unlock(&mDNSStorage);
-}
-#endif // DSO_USES_NETWORK_FRAMEWORK
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-static dso_transport_t *dso_transport_create(nw_connection_t connection, bool is_server, void *context,
-    const dso_life_cycle_context_callback_t context_callback, int max_outstanding_queries, size_t outbuf_size_in,
-    const char *remote_name, dso_event_callback_t cb, dso_state_t *dso)
-{
-    dso_transport_t *transport;
-    uint8_t *transp;
-    const size_t outbuf_size = outbuf_size_in + 256; // Space for additional TLVs
-
-    // We allocate everything in a single hunk so that we can free it together as well.
-    transp = mallocL("dso_transport_create", (sizeof *transport) + outbuf_size);
-    if (transp == NULL) {
-        transport = NULL;
-        goto out;
-    }
-    // Don't clear the buffers.
-    mDNSPlatformMemZero(transp, sizeof (*transport));
-
-    transport = (dso_transport_t *)transp;
-    transp += sizeof *transport;
-
-    transport->outbuf = transp;
-    transport->outbuf_size = outbuf_size;
-
-    if (dso == NULL) {
-        transport->dso = dso_state_create(is_server, max_outstanding_queries, remote_name, cb, context, context_callback,
-                                          transport);
-        if (transport->dso == NULL) {
-            mDNSPlatformMemFree(transport);
-            transport = NULL;
-            goto out;
-        }
-    } else {
-        transport->dso = dso;
-    }
-    transport->connection = connection;
-    nw_retain(transport->connection);
-
-    // Used to uniquely mark dso_transport_t objects, incremented once for each dso_transport_t created.
-    // DSO_TRANSPORT_INVALID_SERIAL(0) is used to identify the invalid dso_transport_t.
-    static uint32_t dso_transport_serial = DSO_TRANSPORT_INVALID_SERIAL + 1;
-    transport->serial = dso_transport_serial++;
-
-    transport->dso->transport = transport;
-    transport->dso->transport_finalize = dso_transport_finalize;
-    transport->next = dso_transport_states;
-    dso_transport_states = transport;
-
-    // Start looking for messages...
-    dso_read_message_length(transport);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u->DSOT%u] New dso_transport_t created - "
-        "transport: %p, remote_name: " PRI_S ".", transport->dso->serial, transport->serial, transport, remote_name);
-out:
-    return transport;
-}
-#else
-// Create a dso_transport_t structure
-static dso_transport_t *dso_transport_create(TCPSocket *sock, bool is_server, void *context,
-    const dso_life_cycle_context_callback_t context_callback, int max_outstanding_queries, size_t inbuf_size_in,
-    size_t outbuf_size_in, const char *remote_name, dso_event_callback_t cb, dso_state_t *dso)
-{
-    dso_transport_t *transport;
-    size_t outbuf_size;
-    size_t inbuf_size;
-    uint8_t *transp;
-    int status;
-
-    // There's no point in a DSO that doesn't have a callback.
-    if (!cb) {
-        return NULL;
-    }
-
-    outbuf_size = outbuf_size_in + 256; // Space for additional TLVs
-    inbuf_size = inbuf_size_in + 2;   // Space for length
-
-    // We allocate everything in a single hunk so that we can free it together as well.
-    transp = mallocL("dso_transport_create", (sizeof *transport) + inbuf_size + outbuf_size);
-    if (transp == NULL) {
-        transport = NULL;
-        goto out;
-    }
-    // Don't clear the buffers.
-    mDNSPlatformMemZero(transp, sizeof (*transport));
-
-    transport = (dso_transport_t *)transp;
-    transp += sizeof *transport;
-
-    transport->inbuf = transp;
-    transport->inbuf_size = inbuf_size;
-    transp += inbuf_size;
-
-    transport->outbuf = transp;
-    transport->outbuf_size = outbuf_size;
-
-    if (dso == NULL) {
-        transport->dso = dso_state_create(is_server, max_outstanding_queries, remote_name, cb, context, context_callback,
-                                          transport);
-        if (transport->dso == NULL) {
-            mDNSPlatformMemFree(transport);
-            transport = NULL;
-            goto out;
-        }
-    } else {
-        transport->dso = dso;
-    }
-    transport->connection = sock;
-
-    // Used to uniquely mark dso_transport_t objects, incremented once for each dso_transport_t created.
-    // DSO_TRANSPORT_INVALID_SERIAL(0) is used to identify the invalid dso_transport_t.
-    static uint32_t dso_transport_serial = DSO_TRANSPORT_INVALID_SERIAL + 1;
-    transport->serial = dso_transport_serial++;
-
-    status = mDNSPlatformTCPSocketSetCallback(sock, dso_read_callback, transport);
-    if (status != mStatus_NoError) {
-        LogMsg("dso_state_create: unable to set callback: %d", status);
-        dso_state_cancel(transport->dso);
-        goto out;
-    }
-
-    transport->dso->transport = transport;
-    transport->dso->transport_finalize = dso_transport_finalize;
-    transport->next = dso_transport_states;
-    dso_transport_states = transport;
-out:
-    return transport;
-}
-#endif // DSO_USES_NETWORK_FRAMEWORK
-
-// This should all be replaced with Network Framework connection setup.
-dso_connect_state_t *dso_connect_state_create(
-    const char *hostname, mDNSAddr *addr, mDNSIPPort port,
-    int max_outstanding_queries, size_t inbuf_size, size_t outbuf_size,
-    dso_event_callback_t callback,
-    dso_state_t *dso, void *context,
-    const dso_life_cycle_context_callback_t dso_context_callback,
-    const dso_connect_life_cycle_context_callback_t dso_connect_context_callback,
-    const char *detail)
-{
-    size_t detlen = strlen(detail) + 1;
-    size_t hostlen = hostname == NULL ? 0 : strlen(hostname) + 1;
-    size_t len;
-    dso_connect_state_t *cs = NULL;
-    dso_connect_state_t *cs_to_return = NULL;
-    char *csp;
-    char nbuf[INET6_ADDRSTRLEN + 1];
-    dso_connect_state_t **states;
-
-    // Enforce Some Minimums (Xxx these are a bit arbitrary, maybe not worth doing?)
-    if (inbuf_size < MaximumRDSize || outbuf_size < 128 || max_outstanding_queries < 1) {
-        goto exit;
-    }
-
-    // If we didn't get a hostname, make a presentation form of the IP address to use instead.
-    if (!hostlen) {
-        if (addr != NULL) {
-            if (addr->type == mDNSAddrType_IPv4) {
-                hostname = inet_ntop(AF_INET, &addr->ip.v4, nbuf, sizeof nbuf);
-            } else {
-                hostname = inet_ntop(AF_INET6, &addr->ip.v6, nbuf, sizeof nbuf);
-            }
-            if (hostname != NULL) {
-                hostlen = strlen(nbuf);
-            }
-        }
-    }
-    // If we don't have a printable name, we won't proceed, because this means we don't know
-    // what to connect to.
-    if (!hostlen) {
-        goto exit;
-    }
-
-    len = (sizeof *cs) + detlen + hostlen;
-    csp = mdns_malloc(len);
-    if (!csp) {
-        goto exit;
-    }
-    cs = (dso_connect_state_t *)csp;
-    memset(cs, 0, sizeof *cs);
-    csp += sizeof *cs;
-
-    cs->detail = csp;
-    memcpy(cs->detail, detail, detlen);
-    csp += detlen;
-    cs->hostname = csp;
-    memcpy(cs->hostname, hostname, hostlen);
-
-    // Used to uniquely mark dso_connect_state_t objects, incremented once for each dso_connect_state_t created.
-    // DSO_CONNECT_STATE_INVALID_SERIAL(0) is used to identify the invalid dso_connect_state_t.
-    static uint32_t dso_connect_state_serial = DSO_CONNECT_STATE_INVALID_SERIAL + 1;
-    cs->serial = dso_connect_state_serial++;
-
-    cs->config_port = port;
-    cs->max_outstanding_queries = max_outstanding_queries;
-    cs->outbuf_size = outbuf_size;
-    if (context) {
-        cs->context = context;
-    } // else cs->context = NULL because of memset call above.
-    if (dso_context_callback != NULL) {
-        cs->dso_context_callback = dso_context_callback;
-    }
-    if (dso_connect_context_callback != NULL) {
-        cs->dso_connect_context_callback = dso_connect_context_callback;
-        dso_connect_context_callback(dso_connect_life_cycle_create, context, cs);
-    }
-    cs->callback = callback;
-    cs->connect_port.NotAnInteger = 0;
-    cs->dso = dso;
-#ifndef DSO_USES_NETWORK_FRAMEWORK
-    cs->inbuf_size = inbuf_size;
-#endif
-
-    if (addr != NULL) {
-        dso_connect_state_process_address_port_change(addr, port, mDNStrue, cs);
-        if (cs->addrs == NULL) {
-            goto exit;
-        }
-    }
-
-    // cs->canceled must be set to false here, because we use it to determine if the current dso_connect_state_t is
-    // still valid. We do not need to set it explicitly because the memset(cs, 0, sizeof *cs); above will initialize it
-    // to 0(false).
-    // cs->canceled = mDNSfalse;
-
-    for (states = &dso_connect_states; *states != NULL; states = &(*states)->next)
-        ;
-    *states = cs;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u->DSOC%u] New dso_connect_state_t created - "
-        "dso_connect: %p, hostname: " PUB_S ", context: %p.", dso->serial, cs->serial, cs, hostname, context);
-
-    cs_to_return = cs;
-    cs = NULL;
-
-exit:
-    if (cs != NULL) {
-        mdns_free(cs->addrs);
-    }
-    mdns_free(cs);
-    return cs_to_return;
-}
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-void dso_connect_state_use_tls(dso_connect_state_t *cs)
-{
-    cs->tls_enabled = true;
-}
-#endif
-
-void
-dso_connect_state_cancel(dso_connect_state_t *const cs)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] Canceling dso_connect_state_t.", cs->serial);
-
-    // Remove the dso_connect_state_t from the main dso_connect_states list.
-    dso_connect_state_t **cs_pp;
-    for (cs_pp = &dso_connect_states; *cs_pp != NULL && *cs_pp != cs; cs_pp = &(*cs_pp)->next)
-        ;
-    if (*cs_pp != NULL) {
-        *cs_pp = cs->next;
-    } else {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[DSOC%u] Canceling a dso_connect_state_t that is not in the dso_connect_states list - host name: " PRI_S
-            ", detail: " PUB_S ".", cs->serial, cs->hostname, cs->detail);
-    }
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    // Cancel the underlying nw_connection_t.
-    if (cs->connection != NULL) {
-        nw_connection_cancel(cs->connection);
-    }
-    if (cs->transport != NULL && cs->transport->connection != NULL) {
-        nw_connection_cancel(cs->transport->connection);
-    }
-#endif
-
-    // We cannot call `DNSServiceRefDeallocate(cs->lookup);` directly to cancel the address lookup, because we are
-    // holding the mDNS_Lock when calling the function. And it is also possible that we are traversing some mDNSCore
-    // data structures while calling it, so use mDNS_DropLockBeforeCallback is not correct either.
-
-    if (cs->dso_connect_context_callback != NULL) {
-        cs->dso_connect_context_callback(dso_connect_life_cycle_cancel, cs->context, cs);
-    }
-
-    // Invalidate this dso_connect_state_t object, so that when we get a callback for dso_inaddr_callback(), we can skip
-    // the callback for the canceled dso_connect_state_t object.
-    cs->canceled = mDNStrue;
-
-    // We leave cs and cs->lookup to be freed by dso_transport_idle.
-    cs->next = dso_connect_state_needing_clean_up;
-    dso_connect_state_needing_clean_up = cs;
-}
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-static void
-dso_connection_succeeded(dso_connect_state_t *cs)
-{
-    // We got a connection.
-    dso_transport_t *transport =
-        dso_transport_create(cs->connection, false, cs->context, cs->dso_context_callback,
-            cs->max_outstanding_queries, cs->outbuf_size, cs->hostname, cs->callback, cs->dso);
-    nw_release(cs->connection);
-    cs->connection = NULL;
-    if (transport == NULL) {
-        // If dso_transport_create fails, there's no point in continuing to try to connect to new
-        // addresses
-        LogMsg("dso_connection_succeeded: dso_state_create failed");
-        // XXX we didn't retain the connection, so we're done when it goes out of scope, right?
-    } else {
-        // Call the "we're connected" callback, which will start things up.
-        transport->dso->cb(cs->context, NULL, transport->dso, kDSOEventType_Connected);
-    }
-
-    cs->last_event = 0;
-    // Remember the transport on the connect state so that we can cancel it when needed.
-    cs->transport = transport;
-    return;
-}
-
-static bool tls_cert_verify(const sec_protocol_metadata_t metadata, const sec_trust_t trust_ref,
-                            const uint32_t cs_serial)
-{
-    bool valid;
-
-    // When iCloud keychain is enabled, it is possible that the TLS certificate that DNS push server
-    // uses has been synced to the client device, so we do the evaluation here.
-    const tls_keychain_context_t context = {metadata, trust_ref};
-    valid = tls_cert_evaluate(&context);
-    if (valid) {
-        // If the evaluation succeeds, it means that the DNS push server that mDNSResponder is
-        // talking to, is registered under the same iCloud account. Therefore, it is trustworthy.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[DSOC%u] TLS certificate evaluation SUCCEEDS, the DNS push server is trustworthy.",
-                  cs_serial);
-    } else {
-        // If the evaluation fails, it means that, the DNS push server that mDNSResponder is
-        // talking to, is not registered under the same iCloud account or the user does not enable iCloud Keychain.
-        // Case 1: The DNS push server is not owned by the user making the request. For example,
-        // a user goes to other's home and trying to discover the services there.
-        // Case 2: The DNS push server is owned by the client, but does not enable iCloud Keychain.
-        // Case 3: The DNS push server is a malicious server.
-        // Case 4: The user does not enable iCloud Keychain, thus the TLS certificate on the client may be out of date,
-        // or not available due to no certificate syncing.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[DSOC%u] TLS certificate evaluation FAILS, the DNS push server is not trustworthy.",
-                  cs_serial);
-    }
-
-    // Ideally, We should support case 1 and case 2, case 4, but avoid case 3.
-    // However, given that:
-    // 1. mDNSResponder only connects to the DNS push server on the same local subnet, which
-    //    means the malicious DNS push server has to be present in the local network (at home,
-    //    , at office), the probability of this scenario is relatively small.
-    // 2. Service discovery via multicast DNS or unicast DNS has no security protection.
-    // It is OK for now to blindly trust the TLS certificate from the DNS push server, which means we
-    // will not avoid case 3, just like service discovery via multicast DNS or unicast DNS.
-    valid = true;
-
-    return valid;
-}
-
-static void dso_connect_internal(dso_connect_state_t *cs, mDNSBool reconnecting)
-{
-    uint32_t serial = cs->serial;
-    nw_endpoint_t endpoint = NULL;
-    nw_parameters_t parameters = NULL;
-    nw_connection_t connection = NULL;
-
-    cs->last_event = mDNSStorage.timenow;
-
-    // If we do not have more address to connect.
-    if (cs->next_addr == NULL) {
-        if (reconnecting) {
-            if (cs->addrs != NULL) {
-                dso_disconnect_context_t context;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[DSOC%u] At end of address list, delaying retry - "
-                          "server name: " PRI_S ".", cs->serial, cs->hostname);
-                cs->last_event = 0;
-                context.reconnect_delay = 60; // Wait one minute before attempting to reconnect.
-                cs->callback(cs->context, &context, cs->dso, kDSOEventType_Disconnected);
-                cs->next_addr = cs->addrs;
-            } else {
-                // Otherwise, we will get more callbacks when outstanding queries either fail or succeed.
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[DSOC%u] Waiting for newly resolved address to connect - server name: " PRI_S ".",
-                          cs->serial, cs->hostname);
-            }
-        } else {
-            // The expectation is that if we are connecting to a DSO server, we really should succeed. If we
-            // don't succeed in connecting to any of the advertised servers, it's a good assumption that it's
-            // not working, so we should give up, rather than continuing forever to try.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[DSOC%u] No more addresses to try - "
-                      "server name: " PRI_S ".", cs->serial, cs->hostname);
-            cs->last_event = 0;
-            cs->callback(cs->context, NULL, cs->dso, kDSOEventType_ConnectFailed);
-        }
-        goto exit;
-    }
-
-    // Always use the first address in the list to set up the connection.
-    const dso_transport_address_t *dest_addr = cs->next_addr;
-
-    const mDNSAddr addr = dest_addr->address;
-    const mDNSIPPort port = dest_addr->port;
-
-    char addrbuf[INET6_ADDRSTRLEN + 1];
-    char portbuf[6];
-    get_address_string_from_mDNSAddr(&addr, addrbuf);
-    snprintf(portbuf, sizeof(portbuf), "%u", mDNSVal16(port));
-
-    endpoint = nw_endpoint_create_host(addrbuf, portbuf);
-    if (endpoint == NULL) {
-        goto exit;
-    }
-
-    nw_parameters_configure_protocol_block_t configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL;
-    if (cs->tls_enabled) {
-        const uint32_t cs_serial = cs->serial;
-        configure_tls = ^(nw_protocol_options_t tls_options) {
-            sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
-            sec_protocol_options_set_verify_block(sec_options,
-                ^(sec_protocol_metadata_t metadata, sec_trust_t trust_ref, sec_protocol_verify_complete_t complete)
-                {
-                    const bool valid = tls_cert_verify(metadata, trust_ref, cs_serial);
-                    complete(valid);
-                },
-                dso_dispatch_queue);
-            sec_release(sec_options);
-        };
-    }
-    parameters = nw_parameters_create_secure_tcp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION);
-    if (parameters == NULL) {
-        goto exit;
-    }
-    connection = nw_connection_create(endpoint, parameters);
-    if (connection == NULL) {
-        goto exit;
-    }
-
-    const uint64_t nw_connection_id = nw_connection_get_id(connection);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u->C%" PRIu64 "] Connecting to the server - "
-        "server: " PRI_IP_ADDR ":%u.", cs->serial, nw_connection_id, &addr, mDNSVal16(port));
-
-    nw_connection_set_queue(connection, dso_dispatch_queue);
-    nw_connection_set_state_changed_handler(
-        connection, ^(nw_connection_state_t state, nw_error_t error) {
-            dso_connect_state_t *ncs;
-            KQueueLock();
-            ncs = dso_connect_state_find(serial); // Might have been canceled.
-            if (ncs == NULL) {
-                // If we cannot find dso_connect_state_t in the system's list, it means that we have already canceled it
-                // in dso_connect_state_cancel() including the corresponding nw_connection_t. Therefore, there is no
-                // need to cancel the nw_connection_t again.
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "[DSOC%u->C%" PRIu64
-                          "] No connect state found - nw_connection_state_t: " PUB_S ".",
-                          serial, nw_connection_id, nw_connection_state_to_string(state));
-            } else {
-                if (state == nw_connection_state_waiting) {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[DSOC%u->C%" PRIu64 "] Connection to server: " PRI_IP_ADDR ":%u waiting.",
-                              serial, nw_connection_id, &addr, mDNSVal16(port));
-
-                    // XXX the right way to do this is to just let NW Framework wait until we get a connection,
-                    // but there are a bunch of problems with that right now.   First, will we get "waiting" on
-                    // every connection we try?   We aren't relying on NW Framework for DNS lookups, so we are
-                    // connecting to an IP address, not a host, which means in principle that a later IP address
-                    // might be reachable.   So we have to stop trying on this one to try that one.   Oops.
-                    // Once we get NW Framework to use internal calls to resolve names, we can fix this.
-                    // Second, maybe we want to switch to polling if this happens.   Probably not, but we need
-                    // to think this through.   So right now we're just using the semantics of regular sockets,
-                    // which we /have/ thought through.   So in the future we should do this think-through and
-                    // try to use NW Framework as it's intended to work rather than as if it were just sockets.
-                    nw_connection_cancel(connection);
-                } else if (state == nw_connection_state_failed) {
-                    // We tried to connect, but didn't succeed.
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[DSOC%u->C%" PRIu64 "] Connection to server: " PRI_IP_ADDR ":%u failed, error:"
-                              PUB_S ", detail: " PUB_S ".", serial, nw_connection_id,
-                              &addr, mDNSVal16(port), strerror(nw_error_get_error_code(error)), ncs->detail);
-                    nw_connection_cancel(connection);
-                } else if (state == nw_connection_state_ready) {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "[DSOC%u->C%" PRIu64 "] Connection to server: " PRI_IP_ADDR ":%u ready.",
-                        serial, nw_connection_id, &addr, mDNSVal16(port));
-                    ncs->connecting = mDNSfalse;
-                    mDNS_Lock(&mDNSStorage);
-                    dso_connection_succeeded(ncs);
-                    mDNS_Unlock(&mDNSStorage);
-                } else if (state == nw_connection_state_cancelled) {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "[DSOC%u->C%" PRIu64 "] Connection to server: " PRI_IP_ADDR ":%u canceled.",
-                        serial, nw_connection_id, &addr, mDNSVal16(port));
-                    if (ncs->transport) {
-                        if (ncs->transport->connection) {
-                            nw_release(ncs->transport->connection);
-                            ncs->transport->connection = NULL;
-                        }
-                        // If there is a dso state on the connect state and it is referencing this transport,
-                        // remove the reference.
-                        if (ncs->dso != NULL && ncs->dso->transport == ncs->transport) {
-                            ncs->dso->transport = NULL;
-                        }
-                        // If the dso_state_t is still referencing this transport, remove the reference.
-                        if (ncs->transport->dso != NULL && ncs->transport->dso->transport == ncs->transport) {
-                            ncs->transport->dso->transport = NULL;
-                        }
-                        dso_transport_finalize(ncs->transport, "dso_connect_internal");
-                        ncs->transport = NULL;
-                    }
-                    if (ncs->connection) {
-                        nw_release(ncs->connection);
-                    }
-                    ncs->connection = NULL;
-                    if (ncs->connecting) {
-                        ncs->connecting = mDNSfalse;
-                        // If we get here and cs exists, we are still trying to connect.   So do the next step.
-                        mDNS_Lock(&mDNSStorage);
-                        dso_connect_internal(ncs, reconnecting);
-                        mDNS_Unlock(&mDNSStorage);
-                    }
-                }
-
-                // Except for the state nw_connection_state_ready, all the other states mean that the nw_connection is
-                // not ready for use. Therefore, it is no longer correct to say that we have an established session.
-                // In which case, set has_session to false.
-                if (state != nw_connection_state_ready) {
-                    if (ncs->dso != NULL) {
-                        ncs->dso->has_session = false;
-                    }
-                }
-            }
-            KQueueUnlock("dso_connect_internal state change handler");
-        });
-    nw_connection_start(connection);
-    cs->connecting = mDNStrue;
-    cs->connection = connection;
-    connection = NULL;
-
-    // We finished setting up the connection with the first address in the list, so remove it from the list.
-    cs->next_addr = dest_addr->next;
-    dest_addr = NULL;
-exit:
-    MDNS_DISPOSE_NW(endpoint);
-    MDNS_DISPOSE_NW(parameters);
-    MDNS_DISPOSE_NW(connection);
-}
-
-#else
-static void dso_connect_callback(TCPSocket *sock, void *context, mDNSBool connected, int err)
-{
-    dso_connect_state_t *cs = context;
-    char *detail;
-    int status;
-    dso_transport_t *transport;
-    mDNS *m = &mDNSStorage;
-
-    (void)connected;
-    mDNS_Lock(m);
-    detail = cs->detail;
-
-    // If we had a socket open but the connect failed, close it and try the next address, if we have
-    // a next address.
-    if (sock != NULL) {
-        cs->last_event = m->timenow;
-
-        cs->connecting = mDNSfalse;
-        if (err != mStatus_NoError) {
-            mDNSPlatformTCPCloseConnection(sock);
-            LogMsg("dso_connect_callback: connect %p failed (%d)", cs, err);
-        } else {
-        success:
-            // We got a connection.
-            transport = dso_transport_create(sock, false, cs->context, cs->dso_context_callback,
-                cs->max_outstanding_queries, cs->inbuf_size, cs->outbuf_size, cs->hostname, cs->callback, cs->dso);
-            if (transport == NULL) {
-                // If dso_state_create fails, there's no point in continuing to try to connect to new
-                // addresses
-            fail:
-                LogMsg("dso_connect_callback: dso_state_create failed");
-                mDNSPlatformTCPCloseConnection(sock);
-            } else {
-                // Call the "we're connected" callback, which will start things up.
-                transport->dso->cb(cs->context, NULL, transport->dso, kDSOEventType_Connected);
-            }
-
-            cs->last_event = 0;
-
-            // When the connection has succeeded, stop asking questions.
-            if (cs->lookup != NULL) {
-                DNSServiceRef ref = cs->lookup;
-                cs->lookup = NULL;
-                mDNS_DropLockBeforeCallback();
-                DNSServiceRefDeallocate(ref);
-                mDNS_ReclaimLockAfterCallback();
-            }
-            mDNS_Unlock(m);
-            return;
-        }
-    }
-
-    // If there are no addresses to connect to, and there are no queries running, then we can give
-    // up.  Otherwise, we wait for one of the queries to deliver an answer.
-    if (cs->next_addr == NULL) {
-        // We may get more callbacks when outstanding queries either fail or succeed, at which point we can try to
-        // connect to those addresses, or give up.
-        mDNS_Unlock(m);
-        return;
-    }
-
-    const mDNSAddr addr = cs->next_addr->address;
-    const mDNSIPPort port = cs->next_addr->port;
-
-    sock = mDNSPlatformTCPSocket(kTCPSocketFlags_Zero, addr.type, NULL, NULL, mDNSfalse);
-    if (sock == NULL) {
-        LogMsg("drConnectCallback: couldn't get a socket for %s: %s%s",
-               cs->hostname, strerror(errno), detail);
-        goto fail;
-    }
-
-    LogMsg("dso_connect_callback: Attempting to connect to %#a%%%d", &addr, mDNSVal16(port));
-
-    status = mDNSPlatformTCPConnect(sock, &addr, port, NULL, dso_connect_callback, cs);
-    // We finished setting up the connection with the first address in the list, so remove it from the list.
-    cs->next_addr = cs->next_addr->next;
-
-    if (status == mStatus_NoError || status == mStatus_ConnEstablished) {
-        // This can't happen in practice on MacOS; we don't know about all other operating systems,
-        // so we handle it just in case.
-        LogMsg("dso_connect_callback: synchronous connect to %s", cs->hostname);
-        goto success;
-    } else if (status == mStatus_ConnPending) {
-        LogMsg("dso_connect_callback: asynchronous connect to %s", cs->hostname);
-        cs->connecting = mDNStrue;
-        // We should get called back when the connection succeeds or fails.
-        mDNS_Unlock(m);
-        return;
-    }
-    LogMsg("dso_connect_callback: failed to connect to %s on %#a%d: %s%s",
-           cs->hostname, &addr, mDNSVal16(port), strerror(errno), detail);
-    mDNS_Unlock(m);
-}
-
-static void dso_connect_internal(dso_connect_state_t *cs, mDNSBool reconnecting)
-{
-    (void)reconnecting;
-    dso_connect_callback(NULL, cs, false, mStatus_NoError);
-}
-#endif // DSO_USES_NETWORK_FRAMEWORK
-
-static void dso_connect_state_process_address_port_change(const mDNSAddr *addr_changed, mDNSIPPort port,
-                                                          bool add, dso_connect_state_t *const cs)
-{
-    bool succeeded;
-    dso_transport_address_t **addrs = &cs->addrs;
-
-    if (add) {
-        // Always add the new address to the tail, so the order of using the address to connect is the same as the order
-        // of the address being added.
-        while (*addrs != NULL) {
-            addrs = &(*addrs)->next;
-        }
-        dso_transport_address_t *new_addr = mdns_calloc(1, sizeof(*new_addr));
-        if (new_addr == NULL) {
-            succeeded = false;
-            goto exit;
-        }
-        memcpy(&new_addr->address, addr_changed, sizeof (*addr_changed));
-        new_addr->port = port;
-        *addrs = new_addr;
-        if (cs->next_addr == NULL) {
-            cs->next_addr = new_addr;
-        }
-    } else {
-        // Remove address that has been previously added, so that mDNSResponder will not even try the removed address in
-        // the future when reconnecting.
-        bool removed = mDNSfalse;
-        while (*addrs != NULL) {
-            dso_transport_address_t *addr = *addrs;
-            if (((addr->address.type == mDNSAddrType_IPv4 && !memcmp(&addr->address.ip.v4, &addr_changed->ip.v4,
-                                                                     sizeof(addr->address.ip.v4))) ||
-                 (addr->address.type == mDNSAddrType_IPv6 && !memcmp(&addr->address.ip.v6, &addr_changed->ip.v6,
-                                                                     sizeof(addr->address.ip.v4)))) &&
-                addr->port.NotAnInteger == port.NotAnInteger)
-            {
-                if (cs->next_addr == addr) {
-                    cs->next_addr = addr->next;
-                }
-                *addrs = addr->next;
-                mdns_free(addr);
-                removed = mDNStrue;
-                break;
-            }
-            addrs = &addr->next;
-        }
-
-        if (!removed) {
-            // If the address being removed is not in the list, it indicates the following two scenarios:
-            // 1. The address has been traversed when dso_connect_state_t tries to connect to the server address.
-            // 2. The address is the server address that dso_transport_t currently connects to, for efficiency, it is
-            // not terminated immediately. If the address is removed because of the network changes, dso_transport_t
-            // will notice that and terminate the connection by itself.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[DSOC%u] The address being removed has been tried for the connection or is being used right now - "
-                "address: " PRI_IP_ADDR ":%u.", cs->serial, &addr_changed, mDNSVal16(cs->config_port));
-        }
-    }
-
-    if (!cs->connecting && !cs->transport) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] Starting a new connection.", cs->serial);
-        dso_connect_internal(cs, mDNSfalse);
-    } else {
-        if (cs->connecting) {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "[DSOC%u] Connection in progress, deferring new connection until it fails.", cs->serial);
-        } else {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "[DSOC%u] Already connected, retained new address for later need.", cs->serial);
-        }
-    }
-
-    succeeded = true;
-exit:
-    if (!succeeded) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                  "[DSOC%u] Failed to process address changes for dso_connect_state_t.", cs->serial);
-    }
-}
-
-static void dso_connect_state_process_address_change(const mDNSAddr *addr_changed, const bool add,
-                                                     dso_connect_state_t *const cs)
-{
-    dso_connect_state_process_address_port_change(addr_changed, cs->config_port, add, cs);
-}
-
-static void dso_inaddr_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
-                                DNSServiceErrorType errorCode, const char *fullname, const struct sockaddr *sa,
-                                uint32_t ttl, void *context)
-{
-    (void)sdRef;
-    dso_connect_state_t *cs = context;
-    mDNS *const m = &mDNSStorage;
-
-    // Do not proceed if we find that the dso_connect_state_t has been canceled previously.
-    if (cs->canceled) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[DSOC%u] The current dso_connect_state_t has been canceled - hostname: " PRI_S ".", cs->serial,
-            cs->hostname);
-        goto exit;
-    }
-
-    cs->last_event = mDNSStorage.timenow;
-
-    // It is possible that the network does not support IPv4 or IPv6, in which case we will get the
-    // kDNSServiceErr_NoSuchRecord error for the corresponding unsupported address type. This is a valid case.
-    if (errorCode == kDNSServiceErr_NoSuchRecord) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] No usable IP address for the DNS push server - "
-            "host name: " PRI_S ", address type: " PUB_S ".", cs->serial, fullname,
-            sa->sa_family == AF_INET ? "A" : "AAAA");
-        goto exit;
-    }
-
-    // All the other error cases other than kDNSServiceErr_NoSuchRecord and kDNSServiceErr_NoError are invalid. They
-    // should be reported as FAULT.
-    if (errorCode != kDNSServiceErr_NoError) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "[DSOC%u] Unexpected dso_inaddr_callback call - "
-            "flags: %x, error: %d.", cs->serial, flags, errorCode);
-        goto exit;
-    }
-
-    const mDNSAddr addr_changed = mDNSAddr_from_sockaddr(sa);
-    const mDNSBool addr_add = (flags & kDNSServiceFlagsAdd) != 0;
-
-    // mDNSPlatformInterfaceIDfromInterfaceIndex() should be called without holding mDNS lock, because the function itself
-    // may need to grab mDNS lock.
-    const mDNSInterfaceID if_id = mDNSPlatformInterfaceIDfromInterfaceIndex(m, interfaceIndex);
-    mDNS_Lock(m);
-    const char *const if_name = InterfaceNameForID(m, if_id);
-    const mDNSBool on_the_local_subnet = mDNS_AddressIsLocalSubnet(m, if_id, &addr_changed);
-    mDNS_Unlock(m);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] dso_inaddr_callback - address " PUB_ADD_RMV
-        ", resolved name: " PRI_S ", flags: %x, interface name: " PUB_S "(%u), erorr: %d, full name: " PRI_S
-        ", addr: " PRI_IP_ADDR ":%u, ttl: %u, on the local subnet: " PUB_BOOL ".", cs->serial, ADD_RMV_PARAM(addr_add),
-        fullname, flags, if_name, interfaceIndex, errorCode, fullname, &addr_changed, mDNSVal16(cs->config_port), ttl,
-        BOOL_PARAM(on_the_local_subnet));
-
-    // Currently, mDNSResponder only trusts DNS push server on the local subnet.
-    if (!on_the_local_subnet) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[DSOC%u] Ignoring the DNS push server address that is not on the local subnet.", cs->serial);
-         goto exit;
-    }
-
-    dso_connect_state_process_address_change(&addr_changed, addr_add, cs);
-
-exit:
-    return;
-}
-
-bool dso_connect(dso_connect_state_t *cs)
-{
-    struct in_addr in;
-    struct in6_addr in6;
-
-    if (cs->next_addr != NULL) {
-        // If the connection state was created with an address, use that rather than hostname,
-        dso_connect_internal(cs, mDNSfalse);
-
-    } else if (inet_pton(AF_INET, cs->hostname, &in)) {
-        // else allow an IPv4 address literal string,
-        const mDNSAddr v4 = mDNSAddr_from_in_addr(&in);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[DSOC%u] Add and connecting to an IPv4 address literal string directly - address: " PRI_IP_ADDR ":%u.",
-            cs->serial, &v4, mDNSVal16(cs->config_port));
-
-        dso_connect_state_process_address_change(&v4, true, cs);
-
-    } else if (inet_pton(AF_INET6, cs->hostname, &in6)) {
-        // or an IPv6 address literal string,
-        const mDNSAddr v6 = mDNSAddr_from_in6_addr(&in6);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[DSOC%u] Add and connecting to an IPv6 address literal string directly - address: " PRI_IP_ADDR ":%u.",
-            cs->serial, &v6, mDNSVal16(cs->config_port));
-
-        dso_connect_state_process_address_change(&v6, true, cs);
-
-    } else {
-        // else look it up.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSOC%u] Resolving server name to start a new connection - "
-            "server: " PRI_S ".", cs->serial, cs->hostname);
-        mDNS *m = &mDNSStorage;
-        mDNS_DropLockBeforeCallback();
-        const DNSServiceErrorType err = DNSServiceGetAddrInfo(&cs->lookup, kDNSServiceFlagsReturnIntermediates,
-            kDNSServiceInterfaceIndexAny, 0, cs->hostname, dso_inaddr_callback, cs);
-
-        mDNS_ReclaimLockAfterCallback();
-        if (err != mStatus_NoError) {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "[DSOC%u] Name resolving failed for the server to connect - server: " PRI_S ", error: %d.",
-                cs->serial, cs->hostname, err);
-            return false;
-        }
-    }
-    return true;
-}
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-// We don't need this for DNS Push, so it is being left as future work.
-int dso_listen(dso_connect_state_t * __unused listen_context)
-{
-    return mStatus_UnsupportedErr;
-}
-
-#else
-
-// Called whenever we get a connection on the DNS TCP socket
-static void dso_listen_callback(TCPSocket *sock, mDNSAddr *addr, mDNSIPPort *port,
-                                const char *remote_name, void *context)
-{
-    dso_connect_state_t *lc = context;
-    dso_transport_t *transport;
-
-    mDNS_Lock(&mDNSStorage);
-    transport = dso_transport_create(sock, mDNStrue, lc->context, lc->dso_context_callback, lc->max_outstanding_queries,
-                                     lc->inbuf_size, lc->outbuf_size, remote_name, lc->callback, NULL);
-    if (transport == NULL) {
-        mDNSPlatformTCPCloseConnection(sock);
-        LogMsg("No memory for new DSO connection from %s", remote_name);
-        goto out;
-    }
-
-    transport->remote_addr = *addr;
-    transport->remote_port = ntohs(port->NotAnInteger);
-    if (transport->dso->cb) {
-        transport->dso->cb(lc->context, 0, transport->dso, kDSOEventType_Connected);
-    }
-    LogMsg("DSO connection from %s", remote_name);
-out:
-    mDNS_Unlock(&mDNSStorage);
-}
-
-// Listen for connections; each time we get a connection, make a new dso_state_t object with the specified
-// parameters and call the callback.   Port can be zero to leave it unspecified.
-
-int dso_listen(dso_connect_state_t *listen_context)
-{
-    mDNSIPPort port;
-    mDNSBool reuseAddr = mDNSfalse;
-
-    if (listen_context->config_port.NotAnInteger) {
-        port = listen_context->config_port;
-        reuseAddr = mDNStrue;
-    }
-    listen_context->listener = mDNSPlatformTCPListen(mDNSAddrType_None, &port, NULL, kTCPSocketFlags_Zero,
-                                                     reuseAddr, 5, dso_listen_callback, listen_context);
-    if (!listen_context->listener) {
-        return mStatus_UnknownErr;
-    }
-    listen_context->connect_port = port;
-
-    LogMsg("DSOListen: Listening on <any>%%%d", mDNSVal16(port));
-    return mStatus_NoError;
-}
-#endif // DSO_USES_NETWORK_FRAMEWORK
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/DSO/dso-transport.h b/DSO/dso-transport.h
deleted file mode 100644
index ff4edb3..0000000
--- a/DSO/dso-transport.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/* dso-transport.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- */
-
-#ifndef __DSO_TRANSPORT_H
-#define __DSO_TRANSPORT_H
-
-#include "mdns_addr_tailq.h"   // For mdns_addr_tailq_t.
-
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-#include <Network/Network.h>
-#endif
-
-// Maximum number of IP addresses that we'll deal with as a result of looking up a name
-// to which to connect.
-#define MAX_DSO_CONNECT_ADDRS 16
-
-// Threshold above which we indicate that a DSO connection isn't writable.   This is advisory,
-// but e.g. for a Discovery Relay, if the remote proxy isn't consuming what we are sending, we
-// should start dropping packets on the floor rather than just queueing more and more packets.
-// 60k may actually be too much.   This is used when we're using NW Framework, because it doesn't
-// allow us to use TCP_NOTSENT_LOWAT directly.
-#define MAX_UNSENT_BYTES 60000
-
-// Use 0 to represent an invalid ID for the object dso_connect_state_t and dso_transport_t.
-#define DSO_CONNECT_STATE_INVALID_SERIAL 0
-#define DSO_TRANSPORT_INVALID_SERIAL 0
-
-struct dso_transport {
-    dso_state_t *dso;              // DSO state for which this is the transport
-    struct dso_transport *next;    // Transport is on list of transports.
-    void *event_context;           // I/O event context
-    mDNSAddr remote_addr;          // The IP address to which we have connected
-    int remote_port;               // The port to which we have connected
-
-    uint32_t serial;               // Serial number for locating possibly freed dso_transport_t structs.
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    nw_connection_t connection;
-    dispatch_data_t to_write;
-    size_t bytes_to_write;
-    size_t unsent_bytes;
-    bool write_failed;             // This is set if any of the parts of the dso_write process fail
-#else
-    TCPSocket *connection;         // Socket connected to Discovery Proxy
-    size_t bytes_needed;
-    size_t message_length;         // Length of message we are currently accumulating, if known
-    uint8_t *inbuf;                // Buffer for incoming messages.
-    size_t inbuf_size;
-    uint8_t *inbufp;               // Current read pointer (may not be in inbuf)
-    bool need_length;              // True if we need a 2-byte length
-
-    uint8_t lenbuf[2];             // Buffer for storing the length in a DNS TCP message
-
-#define MAX_WRITE_HUNKS 4          // When writing a DSO message, we need this many separate hunks.
-    const uint8_t *to_write[MAX_WRITE_HUNKS];
-    ssize_t write_lengths[MAX_WRITE_HUNKS];
-    int num_to_write;
-#endif // DSO_USES_NETWORK_FRAMEWORK
-
-    uint8_t *outbuf;               // Output buffer for building and sending DSO messages
-    size_t outbuf_size;
-};
-
-typedef struct dso_lookup dso_lookup_t;
-struct dso_lookup {
-    dso_lookup_t *next;
-    DNSServiceRef sdref;
-};
-
-typedef struct dso_connect_state dso_connect_state_t;
-
-typedef enum {
-    // When the object is created and holds a reference to the context, the callback(see below) is called with
-    // dso_connect_life_cycle_create.
-    dso_connect_life_cycle_create,
-    // When the object is canceled, the callback(see below) is called with dso_connect_life_cycle_cancel to provide a
-    // chance for the context to do the corresponding cleaning work(cancel or release/free).
-    dso_connect_life_cycle_cancel,
-    // When the object is freed, the callback(see below) is called with dso_connect_life_cycle_free to provide a chance
-    // for the context to clean anything remains allocated.
-    dso_connect_life_cycle_free
-} dso_connect_life_cycle_t;
-
-typedef bool (*dso_connect_life_cycle_context_callback_t)(const dso_connect_life_cycle_t life_cycle,
-     void *const context, dso_connect_state_t *const dso_connect);
-
-typedef struct dso_transport_address dso_transport_address_t;
-struct dso_transport_address {
-    dso_transport_address_t *next;
-    mDNSAddr address;
-    mDNSIPPort port;
-};
-
-struct dso_connect_state {
-    dso_connect_state_t *next;
-    dso_event_callback_t callback;
-    dso_state_t *dso;
-    char *detail;
-    void *context;
-
-    // The callback gets called when dso_state_t is created, canceled or finalized to do some status maintaining
-    // operation for the context. This is passed into dso_state_create(), when dso_connect_state_t uses the context to
-    // create a new dso_state_t in dso_connection_succeeded().
-    dso_life_cycle_context_callback_t dso_context_callback;
-    // The callback gets called when dso_connect_t is created, canceled or finalized to do some status maintaining
-    // operation for the context.
-    dso_connect_life_cycle_context_callback_t dso_connect_context_callback;
-    TCPListener *listener;
-
-    uint32_t serial; // Serial number that identifies a specific dso_connect_state_t.
-    char *hostname;
-
-    // A list of addresses that we've discovered, and the next address to try.
-    dso_transport_address_t *addrs, *next_addr;
-    DNSServiceRef lookup;
-    mDNSBool canceled; // Indicates if the dso_connect_state_t has been canceled and should be ignored for processing.
-
-    mDNSBool connecting;
-    mDNSIPPort config_port, connect_port;
-    dso_transport_t *transport;
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-    nw_connection_t connection;
-    bool tls_enabled;
-#else
-    size_t inbuf_size;
-#endif
-    size_t outbuf_size;
-    int max_outstanding_queries;
-    mDNSs32 last_event;
-    mDNSs32 reconnect_time;
-};
-
-typedef struct {
-	TCPListener *listener;
-    dso_event_callback_t callback;
-	void *context;
-} dso_listen_context_t;
-
-typedef struct {
-    const uint8_t *message;
-    size_t length;
-} dso_message_payload_t;
-
-void dso_transport_init(void);
-mStatus dso_set_connection(dso_state_t *dso, TCPSocket *socket);
-void dso_schedule_reconnect(mDNS *m, dso_connect_state_t *cs, mDNSs32 when);
-void dso_set_callback(dso_state_t *dso, void *context, dso_event_callback_t cb);
-mStatus dso_message_write(dso_state_t *dso, dso_message_t *msg, bool disregard_low_water);
-dso_connect_state_t *dso_connect_state_create(
-    const char *hostname, mDNSAddr *addr, mDNSIPPort port,
-    int max_outstanding_queries, size_t inbuf_size, size_t outbuf_size,
-    dso_event_callback_t callback,
-    dso_state_t *dso, void *context,
-    const dso_life_cycle_context_callback_t dso_context_callback,
-    const dso_connect_life_cycle_context_callback_t dso_connect_context_callback,
-    const char *detail);
-#ifdef DSO_USES_NETWORK_FRAMEWORK
-void dso_connect_state_use_tls(dso_connect_state_t *cs);
-#endif
-void dso_connect_state_cancel(dso_connect_state_t *const cs);
-bool dso_connect(dso_connect_state_t *connect_state);
-void dso_reconnect(dso_connect_state_t *cs, dso_state_t *dso);
-mStatus dso_listen(dso_connect_state_t *listen_context);
-bool dso_write_start(dso_transport_t *transport, size_t length);
-bool dso_write_finish(dso_transport_t *transport);
-void dso_write(dso_transport_t *transport, const uint8_t *buf, size_t length);
-#endif // __DSO_TRANSPORT_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/DSO/dso.c b/DSO/dso.c
deleted file mode 100644
index d2a6d16..0000000
--- a/DSO/dso.c
+++ /dev/null
@@ -1,926 +0,0 @@
-/* dso.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- */
-
-//*************************************************************************************************************
-// Headers
-
-#include <stdio.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <assert.h>
-
-#include <netdb.h>           // For gethostbyname()
-#include <sys/socket.h>      // For AF_INET, AF_INET6, etc.
-#include <net/if.h>          // For IF_NAMESIZE
-#include <netinet/in.h>      // For INADDR_NONE
-#include <netinet/tcp.h>     // For SOL_TCP, TCP_NOTSENT_LOWAT
-#include <arpa/inet.h>       // For inet_addr()
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "DNSCommon.h"
-#include "mDNSEmbeddedAPI.h"
-#include "mdns_strict.h"
-#include "dso.h"
-#include "DebugServices.h"   // For check_compile_time
-
-#ifdef STANDALONE
-#undef LogMsg
-#define LogMsg INFO
-
-#include "srp-log.h"
-extern uint16_t srp_random16(void);
-#define mDNSRandom(x) srp_random16()
-#define mDNSPlatformMemAllocateClear(length) mdns_calloc(1, length)
-#else // STANDALONE
-
-// This is only a temporary fix to let the code in this file print unredacted logs.
-
-#include "srp-log.h"
-#undef FAULT
-#undef INFO
-        #define FAULT(fmt, ...)
-        #define INFO(fmt, ...)
-
-#endif // STANDALONE
-
-//*************************************************************************************************************
-// Remaining work TODO
-
-// - Add keepalive/inactivity timeout support
-// - Notice if it takes a long time to get a response when establishing a session, and treat that
-//   as "DSO not supported."
-// - TLS support
-// - Actually use Network Framework
-
-
-//*************************************************************************************************************
-// Globals
-
-// List of dso connection states that are active. Added when dso_connect_state_create() is called, removed
-// when dso_state_cancel() is called. Removals are moved to dso_connections_needing_cleanup for cleanup during
-// the idle loop.
-// The list of connection states is not declared static so that the discovery proxy can access it as part of
-// the "start-dropping-push" test.
-dso_state_t *dso_connections;
-static dso_state_t *dso_connections_needing_cleanup; // DSO connections that have been shut down but aren't yet freed.
-
-dso_state_t *dso_find_by_serial(uint32_t serial)
-{
-    dso_state_t *dsop;
-
-    for (dsop = dso_connections; dsop; dsop = dsop->next) {
-        if (dsop->serial == serial) {
-            return dsop;
-        }
-    }
-    return NULL;
-}
-
-// This function is called either when an error has occurred requiring the a DSO connection be
-// canceled, or else when a connection to a DSO endpoint has been cleanly closed and is ready to be
-// canceled for that reason.
-
-void dso_state_cancel(dso_state_t *dso)
-{
-    dso_state_t **dsop = &dso_connections;
-    bool status = true;
-
-    // Find dso on the list of connections.
-    while (*dsop != NULL && *dsop != dso) {
-        dsop = &(*dsop)->next;
-    }
-
-    // If we get to the end of the list without finding dso, it means that it's already
-    // been dropped.
-    if (*dsop == NULL) {
-        return;
-    }
-
-    // When the dso_state_t is canceled, its context may also need to be canceled/released/freed, so we give context a
-    // callback to do the cleaning work with dso_life_cycle_cancel state.
-    if (dso->context_callback != NULL) {
-        status = dso->context_callback(dso_life_cycle_cancel, dso->context, dso);
-    }
-
-    // If the callback returns a status of true, then we want to free the dso object in the idle loop.
-    if (status) {
-        // Remove dso from the list of active dso objects.
-        *dsop = dso->next;
-
-        // Add it to the list of dso objects needing cleanup.
-        dso->next = dso_connections_needing_cleanup;
-        dso_connections_needing_cleanup = dso;
-    }
-}
-
-int32_t dso_idle(void *context, int32_t now, int32_t next_timer_event)
-{
-    dso_state_t *dso, *dnext;
-    dso_activity_t *ap, *anext;
-
-    for (dso = dso_connections_needing_cleanup; dso; dso = dnext) {
-        dnext = dso->next;
-        // Finalize and then free any activities.
-        for (ap = dso->activities; ap; ap = anext) {
-            anext = ap->next;
-            if (ap->finalize) {
-                ap->finalize(ap);
-            }
-            mdns_free(ap);
-        }
-        if (dso->transport != NULL && dso->transport_finalize != NULL) {
-            dso->transport_finalize(dso->transport, "dso_idle");
-            dso->transport = NULL;
-        }
-        LogMsg("[DSO%u] dso_state_t finalizing - "
-               "dso: %p, remote name: %s, dso->context: %p", dso->serial, dso, dso->remote_name, dso->context);
-        if (dso->cb) {
-            // Because dso->context is the DNSPushServer that uses the current dso_state_t *dso
-            // (server->connection) and the server has been canceled by CancelDNSPushServer(), the
-            // current dso is not used and cannot be recovered (or reconnected). The only thing we can do is to finalize
-            // it.
-            dso->cb(dso->context, NULL, dso, kDSOEventType_Finalize);
-        } else {
-            mdns_free(dso);
-        }
-        // Do not touch dso after this point, because it has been freed.
-    }
-    dso_connections_needing_cleanup = NULL;
-
-    // Do keepalives.
-    for (dso = dso_connections; dso; dso = dnext) {
-        dnext = dso->next;
-        if (dso->inactivity_due == 0) {
-            if (dso->inactivity_timeout != 0) {
-                dso->inactivity_due = NonZeroTime(now + (event_time_t)MIN(dso->inactivity_timeout, INT32_MAX));
-                if (next_timer_event - dso->inactivity_due > 0) {
-                    next_timer_event = dso->inactivity_due;
-                }
-            }
-        } else if (now - dso->inactivity_due > 0 && dso->cb != NULL) {
-            dso->cb(dso->context, 0, dso, kDSOEventType_Inactive);
-            // Should not touch the current dso_state_t after we deliver kDSOEventType_Inactive event, because it is
-            // possible that the current dso_state_t has been canceled in the callback. Doing any operation to update
-            // its status will not work as expected.
-            continue;
-        }
-        if (dso->keepalive_due != 0 && dso->keepalive_due - now < 0 && dso->cb != NULL) {
-            dso_keepalive_context_t kc;
-            memset(&kc, 0, sizeof kc);
-            dso->cb(dso->context, &kc, dso, kDSOEventType_Keepalive);
-            dso->keepalive_due = NonZeroTime(now + (event_time_t)MIN(dso->keepalive_interval, INT32_MAX));
-            if (next_timer_event - dso->keepalive_due > 0) {
-                next_timer_event = dso->keepalive_due;
-            }
-        }
-    }
-    return dso_transport_idle(context, now, next_timer_event);
-}
-
-void dso_set_event_context(dso_state_t *dso, void *context)
-{
-    dso->context = context;
-}
-
-void dso_set_event_callback(dso_state_t *dso, dso_event_callback_t callback)
-{
-    dso->cb = callback;
-}
-
-// Called when something happens that establishes a DSO session.
-static void dso_session_established(dso_state_t *dso)
-{
-    LogMsg("[DSO%u] DSO session established - dso: %p, remote name: %s.", dso->serial, dso, dso->remote_name);
-    dso->has_session = true;
-    // Set up inactivity timer and keepalive timer...
-}
-
-// Create a dso_state_t structure
-dso_state_t *dso_state_create(bool is_server, int max_outstanding_queries, const char *remote_name,
-                              dso_event_callback_t callback, void *const context,
-                              const dso_life_cycle_context_callback_t context_callback,
-                              dso_transport_t *transport)
-{
-    dso_state_t *dso;
-    size_t namelen = strlen(remote_name);
-    size_t namespace = namelen + 1;
-    const size_t outsize = (sizeof (dso_outstanding_query_state_t)) + (size_t)max_outstanding_queries * sizeof (dso_outstanding_query_t);
-
-    if ((sizeof (*dso) + outsize + namespace) > UINT_MAX) {
-        FAULT("Fatal: sizeof (*dso)[%zd], outsize[%zd], "
-                  "namespace[%zd]", sizeof (*dso), outsize, namespace);
-        dso = NULL;
-        goto out;
-    }
-    // We allocate everything in a single hunk so that we can free it together as well.
-    dso = (dso_state_t *) mDNSPlatformMemAllocateClear((uint32_t)((sizeof (*dso)) + outsize + namespace));
-    if (dso == NULL) {
-        goto out;
-    }
-    dso->outstanding_queries = (dso_outstanding_query_state_t *)(dso + 1);
-    dso->outstanding_queries->max_outstanding_queries = max_outstanding_queries;
-
-    dso->remote_name = ((char *)dso->outstanding_queries) + outsize;
-    memcpy(dso->remote_name, remote_name, namelen);
-    dso->remote_name[namelen] = 0;
-
-    dso->cb = callback;
-    if (context != NULL) {
-        dso->context = context;
-    }
-    if (context_callback != NULL) {
-        dso->context_callback = context_callback;
-        // When dso_state_t is created, the context it holds may need to be reference counted, for example, to retain
-        // the context. Here we give the context a callback with dso_life_cycle_create state.
-        context_callback(dso_life_cycle_create, context, dso);
-    }
-    dso->transport = transport;
-    dso->is_server = is_server;
-
-    // Used to uniquely mark dso_state_t objects, incremented once for each dso_state_t created.
-    // DSO_STATE_INVALID_SERIAL(0) is used to identify invalid dso_state_t.
-    static uint32_t dso_state_serial = DSO_STATE_INVALID_SERIAL + 1;
-    dso->serial = dso_state_serial++;
-
-    dso->next = dso_connections;
-    dso_connections = dso;
-
-    LogMsg("[DSO%u] New dso_state_t created - dso: %p, remote name: %s, context: %p",
-           dso->serial, dso, remote_name, context);
-out:
-    return dso;
-}
-
-// Start building a TLV in an outgoing dso message.
-void dso_start_tlv(dso_message_t *state, int opcode)
-{
-    // Make sure there's room for the length and the TLV opcode.
-    if (state->cur + 4 >= state->max) {
-        LogMsg("dso_start_tlv called when no space in output buffer!");
-        assert(0);
-    }
-
-    // We need to not yet have a TLV.
-    if (state->building_tlv) {
-        LogMsg("dso_start_tlv called while already building a TLV!");
-        assert(0);
-    }
-    state->building_tlv = true;
-    state->tlv_len = 0;
-
-    // Set up the TLV header.
-    state->buf[state->cur] = (uint8_t)(opcode >> 8);
-    state->buf[state->cur + 1] = opcode & 255;
-    state->tlv_len_offset = state->cur + 2;
-    state->cur += 4;
-}
-
-// Add some bytes to a TLV that's being built, but don't copy them--just remember the
-// pointer to the buffer.   This is used so that when we have a message to forward, we
-// don't copy it into the output buffer--we just use scatter/gather I/O.
-void dso_add_tlv_bytes_no_copy(dso_message_t *state, const uint8_t *bytes, size_t len)
-{
-    if (!state->building_tlv) {
-        LogMsg("add_tlv_bytes called when not building a TLV!");
-        assert(0);
-    }
-    if (state->no_copy_bytes_len) {
-        LogMsg("add_tlv_bytesNoCopy called twice on the same DSO message.");
-        assert(0);
-    }
-    state->no_copy_bytes_len = len;
-    state->no_copy_bytes = bytes;
-    state->no_copy_bytes_offset = state->cur;
-    state->tlv_len += len;
-}
-
-// Add some bytes to a TLV that's being built.
-void dso_add_tlv_bytes(dso_message_t *state, const uint8_t *bytes, size_t len)
-{
-    if (!state->building_tlv) {
-        LogMsg("add_tlv_bytes called when not building a TLV!");
-        assert(0);
-    }
-    if (state->cur + len > state->max) {
-        LogMsg("add_tlv_bytes called with no room in output buffer.");
-        assert(0);
-    }
-    memcpy(&state->buf[state->cur], bytes, len);
-    state->cur += len;
-    state->tlv_len += len;
-}
-
-// Add a single byte to a TLV that's being built.
-void dso_add_tlv_byte(dso_message_t *state, uint8_t byte)
-{
-    if (!state->building_tlv) {
-        LogMsg("dso_add_tlv_byte called when not building a TLV!");
-        assert(0);
-    }
-    if (state->cur + 1 > state->max) {
-        LogMsg("dso_add_tlv_byte called with no room in output buffer.");
-        assert(0);
-    }
-    state->buf[state->cur++] = byte;
-    state->tlv_len++;
-}
-
-// Add an uint16_t to a TLV that's being built.
-void dso_add_tlv_u16(dso_message_t *state, uint16_t u16)
-{
-    if (!state->building_tlv) {
-        LogMsg("dso_add_tlv_u16 called when not building a TLV!");
-        assert(0);
-    }
-    if ((state->cur + sizeof u16) > state->max) {
-        LogMsg("dso_add_tlv_u16 called with no room in output buffer.");
-        assert(0);
-    }
-    state->buf[state->cur++] = u16 >> 8;
-    state->buf[state->cur++] = u16 & 255;
-    state->tlv_len += 2;
-}
-
-// Add an uint32_t to a TLV that's being built.
-void dso_add_tlv_u32(dso_message_t *state, uint32_t u32)
-{
-    if (!state->building_tlv) {
-        LogMsg("dso_add_tlv_u32 called when not building a TLV!");
-        assert(0);
-    }
-    if ((state->cur + sizeof u32) > state->max) {
-        LogMsg("dso_add_tlv_u32 called with no room in output buffer.");
-        assert(0);
-    }
-    state->buf[state->cur++] = u32 >> 24;
-    state->buf[state->cur++] = (u32 >> 16) & 255;
-    state->buf[state->cur++] = (u32 >> 8) & 255;
-    state->buf[state->cur++] = u32 & 255;
-    state->tlv_len += 4;
-}
-
-// Finish building a TLV.
-void dso_finish_tlv(dso_message_t *state)
-{
-    if (!state->building_tlv) {
-        LogMsg("dso_finish_tlv called when not building a TLV!");
-        assert(0);
-    }
-
-    // A TLV can't be longer than this.
-    if (state->tlv_len > 65535) {
-        LogMsg("dso_finish_tlv was given more than 65535 bytes of TLV payload!");
-        assert(0);
-    }
-    state->buf[state->tlv_len_offset] = (uint8_t)(state->tlv_len >> 8);
-    state->buf[state->tlv_len_offset + 1] = state->tlv_len & 255;
-    state->tlv_len = 0;
-    state->building_tlv = false;
-}
-
-dso_activity_t *NULLABLE dso_find_activity(dso_state_t *const NONNULL dso, const char *const NULLABLE name,
-                                  const char *const NONNULL activity_type, void *const NULLABLE context)
-{
-    dso_activity_t *activity;
-
-    // If we haven't been given something to search for, don't search.
-    if (name == NULL && context == NULL) {
-        FAULT("[DSO%u] Cannot search for activity with name and context both equal to NULL - "
-              "activity_type: " PUB_S_SRP ".", dso->serial, activity_type);
-        activity = NULL;
-        goto exit;
-    }
-
-    for (activity = dso->activities; activity != NULL; activity = activity->next) {
-        if (activity->activity_type != activity_type) {
-            continue;
-        }
-
-        if (name != NULL) {
-            // If name is specified, always use the name to search for the corresponding activity, even if context is
-            // also specified.
-            if (activity->name == NULL) {
-                continue;
-            }
-            if (strcmp(name, activity->name) != 0) {
-                continue;
-            }
-            // If the name matches, the corresponding context should also match if the context is not NULL.
-            if (context != NULL && activity->context != context) {
-                FAULT("[DSO%u] The activity specified by the name does not have the expected context - "
-                    "name: " PRI_S_SRP ", activity_type: " PUB_S_SRP ", context: %p.", dso->serial, name, activity_type,
-                    context);
-            }
-        } else {
-            // name == NULL && context != NULL
-            // If name is not specified, use context to search for the activity.
-            if (context != activity->context) {
-                continue;
-            }
-        }
-
-        break;
-    }
-
-exit:
-    return activity;
-}
-
-// Make an activity structure to hang off the DSO.
-dso_activity_t *dso_add_activity(dso_state_t *dso, const char *name, const char *activity_type,
-                                 void *context, void (*finalize)(dso_activity_t *))
-{
-    size_t namelen = name ? strlen(name) + 1 : 0;
-    size_t len;
-    dso_activity_t *activity;
-    void *ap;
-
-    // Shouldn't add an activity that's already been added.
-    activity = dso_find_activity(dso, name, activity_type, context);
-    if (activity != NULL) {
-        FAULT("[DSO%u] Trying to add a duplicate activity - activity name: " PRI_S_SRP ", activity type: " PUB_S_SRP
-            ", activity context: %p.", dso->serial, name, activity_type, context);
-        return NULL;
-    }
-
-    len = namelen + sizeof *activity;
-    ap = mDNSPlatformMemAllocateClear((mDNSu32)len);
-    if (ap == NULL) {
-        return NULL;
-    }
-    activity = (dso_activity_t *)ap;
-    ap = (char *)ap + sizeof *activity;
-
-    // Activities can be identified either by name or by context
-    if (namelen) {
-        activity->name = ap;
-        memcpy(activity->name, name, namelen);
-    } else {
-        activity->name = NULL;
-    }
-    activity->context = context;
-
-    // Activity type is expected to be a string constant; all activities of the same type must
-    // reference the same constant, not different constants with the same contents.
-    activity->activity_type = activity_type;
-    activity->finalize = finalize;
-
-    INFO("[DSO%u] Adding a DSO activity - activity name: " PRI_S_SRP ", activity type: " PUB_S_SRP
-        ", activity context: %p.", dso->serial, activity->name, activity->activity_type, activity->context);
-
-    // Retain this activity on the list.
-    activity->next = dso->activities;
-    dso->activities = activity;
-
-    return activity;
-}
-
-void dso_drop_activity(dso_state_t *dso, dso_activity_t *activity)
-{
-    dso_activity_t **app = &dso->activities;
-    bool matched = false;
-
-    // Remove this activity from the list.
-    while (*app) {
-        if (*app == activity) {
-            *app = activity->next;
-            matched = true;
-            break;
-        } else {
-            app = &((*app)->next);
-        }
-    }
-
-    // If an activity that's not on the DSO list is passed here, it's an internal consistency
-    // error that probably indicates something is corrupted.
-    if (!matched) {
-        FAULT("[DSO%u] Trying to remove an activity that is not in the list - "
-            "activity name: " PRI_S_SRP ", activity type: " PUB_S_SRP ", activity context: %p.",
-            dso->serial, activity->name, activity->activity_type, activity->context);
-    }
-    INFO("[DSO%u] Removing a DSO activity - activity name: " PRI_S_SRP ", activity type: " PUB_S_SRP
-        ", activity context: %p.", dso->serial, activity->name, activity->activity_type, activity->context);
-
-    if (activity->finalize != NULL) {
-        activity->finalize(activity);
-    }
-    mdns_free(activity);
-}
-
-uint32_t dso_ignore_further_responses(dso_state_t *dso, void *context)
-{
-    dso_outstanding_query_state_t *midState = dso->outstanding_queries;
-    int i;
-    uint32_t disassociated_count = 0;
-    for (i = 0; i < midState->max_outstanding_queries; i++) {
-        // The query is still be outstanding, and we want to know it when it comes back, but we forget the context,
-        // which presumably is a reference to something that's going away.
-        if (midState->queries[i].context == context) {
-            midState->queries[i].context = NULL;
-            INFO("[DSO%u] Disassociate the outstanding dso query with the context - query id: 0x%x, context: %p.",
-                 dso->serial, midState->queries[i].id, context);
-            disassociated_count++;
-        }
-    }
-
-    return disassociated_count;
-}
-
-bool dso_make_message(dso_message_t *state, uint8_t *outbuf, size_t outbuf_size, dso_state_t *dso,
-                      bool unidirectional, bool response, uint16_t xid, int rcode, void *callback_state)
-{
-    DNSMessageHeader *msg_header;
-    dso_outstanding_query_state_t *midState = dso->outstanding_queries;
-
-    memset(state, 0, sizeof *state);
-    state->buf = outbuf;
-    state->max = outbuf_size;
-
-    // We need space for the TCP message length plus the DNS header.
-    if (state->max < sizeof *msg_header) {
-        LogMsg("dso_make_message: called without enough buffer space to store a DNS header!");
-        assert(0);
-    }
-
-    // This buffer should be 16-bit aligned.
-    msg_header = (DNSMessageHeader *)state->buf;
-
-    // The DNS header for a DSO message is mostly zeroes
-    memset(msg_header, 0, sizeof *msg_header);
-    msg_header->flags.b[0] = (response ? kDNSFlag0_QR_Response : kDNSFlag0_QR_Query) | kDNSFlag0_OP_DSO;
-
-    // Servers can't send DSO messages until there's a DSO session.
-    if (dso->is_server && !dso->has_session) {
-        LogMsg("dso_make_message: FATAL: server attempting to make a DSO message with no session!");
-        assert(0);
-    }
-
-    // Response-requiring messages need to have a message ID. Replies take the message ID from the message to which
-    // they are a reply, and also need an rcode.
-    if (response) {
-        msg_header->flags.b[1] = (uint8_t)rcode;
-        msg_header->id.NotAnInteger = xid;
-    } else if (!unidirectional) {
-        bool msg_id_ok = true;
-        uint16_t message_id;
-        int looping = 0;
-        int i, avail = -1;
-
-        // If we don't have room for another outstanding message, the caller should try
-        // again later.
-        if (midState->outstanding_query_count == midState->max_outstanding_queries) {
-            return false;
-        }
-        // Generate a random message ID.   This doesn't really need to be cryptographically sound
-        // (right?) because we're encrypting the whole data stream in TLS.
-        do {
-            // This would be a surprising fluke, but let's not get killed by it.
-            if (looping++ > 1000) {
-                return false;
-            }
-            message_id = (uint16_t)mDNSRandom(UINT16_MAX);
-            msg_id_ok = true;
-            if (message_id == 0) {
-                msg_id_ok = false;
-            } else {
-                for (i = 0; i < midState->max_outstanding_queries; i++) {
-                    if (midState->queries[i].id == 0 && avail == -1) {
-                        avail = i;
-                    } else if (midState->queries[i].id == message_id) {
-                        msg_id_ok = false;
-                    }
-                }
-            }
-        } while (!msg_id_ok);
-        midState->queries[avail].id = message_id;
-        midState->queries[avail].context = callback_state;
-        midState->outstanding_query_count++;
-        msg_header->id.NotAnInteger = message_id;
-        state->outstanding_query_number = avail;
-    } else {
-        // Clients aren't allowed to send unidirectional messages until there's a session.
-        if (!dso->has_session) {
-            LogMsg("dso_make_message: FATAL: client making a DSO unidirectional message with no session!");
-            assert(0);
-        }
-        state->outstanding_query_number = -1;
-    }
-
-    state->cur = sizeof *msg_header;
-    return true;
-}
-
-size_t dso_message_length(dso_message_t *state)
-{
-    return state->cur + state->no_copy_bytes_len;
-}
-
-void dso_retry_delay(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    dso_disconnect_context_t context;
-    if (dso->cb) {
-        memset(&context, 0, sizeof context);
-        if (dso->primary.length != 4) {
-            LogMsg("Invalid DSO Retry Delay length %d from %s", dso->primary.length, dso->remote_name);
-            dso_send_formerr(dso, header);
-            return;
-        }
-        memcpy(&context, dso->primary.payload, dso->primary.length);
-        context.reconnect_delay = ntohl(context.reconnect_delay);
-        dso->cb(dso->context, &context, dso, kDSOEventType_RetryDelay);
-    }
-}
-
-void dso_keepalive(dso_state_t *dso, const DNSMessageHeader *header)
-{
-    dso_keepalive_context_t context;
-    memset(&context, 0, sizeof context);
-    if (dso->primary.length != 8) {
-        LogMsg("Invalid DSO Keepalive length %d from %s", dso->primary.length, dso->remote_name);
-        if (dso->is_server) {
-            dso_send_formerr(dso, header);
-        }
-        return;
-    }
-    memcpy(&context, dso->primary.payload, dso->primary.length);
-    context.inactivity_timeout = ntohl(context.inactivity_timeout);
-    context.keepalive_interval = ntohl(context.keepalive_interval);
-    if (context.inactivity_timeout > FutureTime || context.keepalive_interval > FutureTime) {
-        LogMsg("[DSO%u] inactivity_timeoutl[%u] keepalive_interva[%u] is unreasonably large.",
-               dso->serial, context.inactivity_timeout, context.keepalive_interval);
-        if (dso->is_server) {
-            dso_send_formerr(dso, header);
-        }
-        return;
-    }
-    if (dso->is_server) {
-        if (dso->cb) {
-            if (dso->keepalive_interval < context.keepalive_interval) {
-                context.keepalive_interval = dso->keepalive_interval;
-            }
-            if (dso->inactivity_timeout < context.inactivity_timeout) {
-                context.inactivity_timeout = dso->inactivity_timeout;
-            }
-            dso->cb(dso->context, &context, dso, kDSOEventType_KeepaliveRcvd);
-        }
-        dso_send_simple_response(dso, kDNSFlag1_RC_NoErr, header, "No Error");
-    } else {
-        if (dso->keepalive_interval > context.keepalive_interval) {
-            dso->keepalive_interval = context.keepalive_interval;
-        }
-        if (dso->inactivity_timeout > context.inactivity_timeout) {
-            dso->inactivity_timeout = context.inactivity_timeout;
-        }
-        // Client does not send response.
-    }
-}
-
-// We received a DSO message; validate it, parse it and, if implemented, dispatch it.
-void dso_message_received(dso_state_t *dso, const uint8_t *message, size_t message_length, void *context)
-{
-    int i;
-    size_t offset;
-    const DNSMessageHeader *header = (const DNSMessageHeader *)message;
-    int response = (header->flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Response;
-    dso_query_receive_context_t qcontext;
-
-    if (message_length < 12) {
-        LogMsg("dso_message_received: response too short: %ld bytes", (long)message_length);
-        dso_state_cancel(dso);
-        goto out;
-    }
-
-    // See if we have sent a message for which a response is expected.
-    if (response) {
-        bool expected = false;
-
-        // A zero ID on a response is not permitted.
-        if (header->id.NotAnInteger == 0) {
-            LogMsg("dso_message_received: response with id==0 received from %s", dso->remote_name);
-            dso_state_cancel(dso);
-            goto out;
-        }
-        // It's possible for a DSO response to contain no TLVs, but if that's the case, the length
-        // should always be twelve.
-        if (message_length < 16 && message_length != 12) {
-            LogMsg("dso_message_received: response with bogus length==%ld received from %s", (long)message_length, dso->remote_name);
-            dso_state_cancel(dso);
-            goto out;
-        }
-        for (i = 0; i < dso->outstanding_queries->max_outstanding_queries; i++) {
-            if (dso->outstanding_queries->queries[i].id == header->id.NotAnInteger) {
-                qcontext.query_context = dso->outstanding_queries->queries[i].context;
-                qcontext.rcode = header->flags.b[1] & kDNSFlag1_RC_Mask;
-                qcontext.message_context = context;
-
-                // If we are a client, and we just got an acknowledgment, a session has been established.
-                if (!dso->is_server && !dso->has_session && (header->flags.b[1] & kDNSFlag1_RC_Mask) == kDNSFlag1_RC_NoErr) {
-                    dso_session_established(dso);
-                }
-                dso->outstanding_queries->queries[i].id = 0;
-                dso->outstanding_queries->queries[i].context = 0;
-                dso->outstanding_queries->outstanding_query_count--;
-                if (dso->outstanding_queries->outstanding_query_count < 0) {
-                    LogMsg("dso_message_receive: programming error: outstanding_query_count went negative.");
-                    assert(0);
-                }
-                // If there were no TLVs, we don't need to parse them.
-                expected = true;
-                if (message_length == 12) {
-                    dso->primary.opcode = 0;
-                    dso->primary.length = 0;
-                    dso->num_additls = 0;
-                }
-                break;
-            }
-        }
-
-        // This is fatal because we've received a response to a message we didn't send, so
-        // it's not just that we don't understand what was sent.
-        if (!expected) {
-            LogMsg("dso_message_received: fatal: %s sent %ld byte message, QR=1, xid=%02x%02x", dso->remote_name,
-                   (long)message_length, header->id.b[0], header->id.b[1]);
-            dso_state_cancel(dso);
-            goto out;
-        }
-    }
-
-    // Make sure that the DNS header is okay (QDCOUNT, ANCOUNT, NSCOUNT and ARCOUNT are all zero)
-    for (i = 0; i < 4; i++) {
-        if (message[4 + i * 2] != 0 || message[4 + i * 2 + 1] != 0) {
-            LogMsg("dso_message_received: fatal: %s sent %ld byte DSO message, %s is nonzero",
-                   dso->remote_name, (long)message_length,
-                   (i == 0 ? "QDCOUNT" : (i == 1 ? "ANCOUNT" : ( i == 2 ? "NSCOUNT" : "ARCOUNT"))));
-            dso_state_cancel(dso);
-            goto out;
-        }
-    }
-
-    // Check that there is space for there to be a primary TLV
-    if (message_length < 16 && message_length != 12) {
-        LogMsg("dso_message_received: fatal: %s sent short (%ld byte) DSO message",
-               dso->remote_name, (long)message_length);
-
-        // Short messages are a fatal error. XXX check DSO document
-        dso_state_cancel(dso);
-        goto out;
-    }
-
-    // If we are a server, and we don't have a session, and this is a message, then we have now established a session.
-    if (!dso->has_session && dso->is_server && !response) {
-        dso_session_established(dso);
-    }
-
-    // If a DSO session isn't yet established, make sure the message is a request (if is_server) or a
-    // response (if not).
-    if (!dso->has_session && ((dso->is_server && response) || (!dso->is_server && !response))) {
-        LogMsg("dso_message_received: received a %s with no established session from %s",
-               response ? "response" : "request", dso->remote_name);
-        dso_state_cancel(dso);
-    }
-
-    // Get the primary TLV and count how many TLVs there are in total
-    offset = 12;
-    while (offset < message_length) {
-        // Get the TLV opcode
-        const uint16_t opcode = (uint16_t)(((uint16_t)message[offset]) << 8) + message[offset + 1];
-        // And the length
-        const uint16_t length = (uint16_t)(((uint16_t)message[offset + 2]) << 8) + message[offset + 3];
-
-        // Is there room for the contents of this TLV?
-        if (length + offset > message_length) {
-            LogMsg("dso_message_received: fatal: %s: TLV (%d %ld) extends past end (%ld)",
-                   dso->remote_name, opcode, (long)length, (long)message_length);
-
-            // Short messages are a fatal error. XXX check DSO document
-            dso_state_cancel(dso);
-            goto out;
-        }
-
-        // Is this the primary TLV?
-        if (offset == 12) {
-            dso->primary.opcode = opcode;
-            dso->primary.length = length;
-            dso->primary.payload = &message[offset + 4];
-            dso->num_additls = 0;
-        } else {
-            if (dso->num_additls < MAX_ADDITLS) {
-                dso->additl[dso->num_additls].opcode = opcode;
-                dso->additl[dso->num_additls].length = length;
-                dso->additl[dso->num_additls].payload = &message[offset + 4];
-                dso->num_additls++;
-            } else {
-                // XXX MAX_ADDITLS should be enough for all possible additional TLVs, so this
-                // XXX should never happen; if it does, maybe it's a fatal error.
-                LogMsg("dso_message_received: %s: ignoring additional TLV (%d %ld) in excess of %d",
-                       dso->remote_name, opcode, (long)length, MAX_ADDITLS);
-            }
-        }
-        offset += 4 + length;
-    }
-
-    // Call the callback with the message or response
-    if (dso->cb) {
-        if (message_length != 12 && dso->primary.opcode == kDSOType_Keepalive) {
-            dso_keepalive(dso, header);
-        } else if (message_length != 12 && dso->primary.opcode == kDSOType_RetryDelay) {
-            dso_retry_delay(dso, header);
-        } else {
-            if (response) {
-                dso->cb(dso->context, &qcontext, dso, kDSOEventType_DSOResponse);
-            } else {
-                dso->cb(dso->context, context, dso, kDSOEventType_DSOMessage);
-            }
-        }
-    }
-out:
-    ;
-}
-
-// This code is currently assuming that we won't get a DNS message, but that's not true.   Fix.
-void dns_message_received(dso_state_t *dso, const uint8_t *message, size_t message_length, void *context)
-{
-    const DNSMessageHeader *header;
-    int opcode, response;
-
-    // We can safely assume that the header is 16-bit aligned.
-    header = (const DNSMessageHeader *)message;
-    opcode = header->flags.b[0] & kDNSFlag0_OP_Mask;
-    response = (header->flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Response;
-
-    // Validate the length of the DNS message.
-    if (message_length < 12) {
-        LogMsg("dns_message_received: fatal: %s sent short (%ld byte) message",
-               dso->remote_name, (long)message_length);
-
-        // Short messages are a fatal error.
-        dso_state_cancel(dso);
-        return;
-    }
-
-    // This is not correct for the general case.
-    if (opcode != kDNSFlag0_OP_DSO) {
-        LogMsg("dns_message_received: %s sent %ld byte %s, QTYPE=%d",
-               dso->remote_name, (long)message_length, (response ? "response" : "request"), opcode);
-        if (dso->cb) {
-            dso->cb(dso->context, context, dso,
-                    response ? kDSOEventType_DNSMessage : kDSOEventType_DNSResponse);
-        }
-    } else {
-        dso_message_received(dso, message, message_length, context);
-    }
-}
-
-const char *dso_event_type_to_string(const dso_event_type_t dso_event_type)
-{
-#define CASE_TO_STR(s) case kDSOEventType_ ## s: return (#s)
-    switch(dso_event_type)
-    {
-        CASE_TO_STR(DNSMessage);
-        CASE_TO_STR(DNSResponse);
-        CASE_TO_STR(DSOMessage);
-        CASE_TO_STR(Finalize);
-        CASE_TO_STR(DSOResponse);
-        CASE_TO_STR(Connected);
-        CASE_TO_STR(ConnectFailed);
-        CASE_TO_STR(Disconnected);
-        CASE_TO_STR(ShouldReconnect);
-        CASE_TO_STR(Inactive);
-        CASE_TO_STR(Keepalive);
-        CASE_TO_STR(KeepaliveRcvd);
-        CASE_TO_STR(RetryDelay);
-    }
-#undef CASE_TO_STR
-    LogMsg("Invalid dso_event_type - dso_event_type: %d.", dso_event_type);
-    return "<INVALID dso_event_type>";
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/DSO/dso.h b/DSO/dso.h
deleted file mode 100644
index dc47d04..0000000
--- a/DSO/dso.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/* dso.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- */
-
-#ifndef __DSO_H
-#define __DSO_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "nullability.h"
-
-// Maximum number of additional TLVs we support in a DSO message.
-#define MAX_ADDITLS           10
-
-// Use 0 to represent an invalid ID for the object dso_connect_t.
-#define DSO_STATE_INVALID_SERIAL 0
-
-typedef enum {
-    // When we get a DSO query or response with no primary TLV, the TLV type will be "No Primary TLV," which is not
-    // otherwise a valid DSO TLV type.
-    kDSOType_NoPrimaryTLV = 0,
-    // Standard DSO Types from RFC 8490
-    kDSOType_Keepalive = 1,
-    kDSOType_RetryDelay = 2,
-    kDSOType_EncryptionPadding = 3,
-
-    // Standard DSO Types from RFC 8765
-    kDSOType_DNSPushSubscribe = 0x40,
-    kDSOType_DNSPushUpdate = 0x41,
-    kDSOType_DNSPushUnsubscribe = 0x42,
-    kDSOType_DNSPushReconfirm = 0x43,
-
-    // Experimental types, taken from the experimental number space, for the discovery relay.
-    kDSOType_mDNSLinkRequest = 0xF901,
-    kDSOType_mDNSLinkDiscontinue = 0xF902,
-    kDSOType_mDNSMessage = 0xF903,
-    kDSOType_LinkIdentifier = 0xF904,
-    kDSOType_L2SourceAddress = 0xF905,
-    kDSOType_IPSourceAddress = 0xF906,
-    kDSOType_mDNSReportLinkChanges = 0xF907,
-    kDSOType_mDNSStopLinkChanges = 0xF908,
-    kDSOType_mDNSLinkAvailable = 0xF900,
-    kDSOType_mDNSLinkUnavailable = 0xF90a,
-    kDSOType_LinkPrefix = 0xF90b,
-
-    // Experimental types, taken from the experimental number space, for SRP Replication.
-    kDSOType_SRPLSession = 0xF90c,
-    kDSOType_SRPLSendCandidates = 0xF90d,
-    kDSOType_SRPLCandidate = 0xF90e,
-    kDSOType_SRPLHost = 0xF90f,
-    kDSOType_SRPLServerID = 0xF910,
-    kDSOType_SRPLCandidateYes = 0xF911,
-    kDSOType_SRPLCandidateNo = 0xF912,
-    kDSOType_SRPLConflict = 0xF913,
-    kDSOType_SRPLHostname = 0xF914,
-    kDSOType_SRPLHostMessage = 0xF915,
-    kDSOType_SRPLTimeOffset = 0xF916,
-    kDSOType_SRPLKeyID = 0xF917,
-    kDSOType_SRPLServerStableID = 0xF918,
-} dso_message_types_t;
-
-// When a DSO message arrives, or one that was sent is acknowledged, or the state of the DSO connection
-// changes, we need to call the user of the DSO connection.
-typedef enum {
-    kDSOEventType_DNSMessage,      // A DNS message that is not a DSO message
-    kDSOEventType_DNSResponse,     // A DNS response that is not a DSO response
-    kDSOEventType_DSOMessage,      // DSOState.primary and DSOState.additl will contain the message TLVs;
-                                   // header will contain the DNS header
-    kDSOEventType_Finalize,        // The DSO connection to the other DSO endpoint has terminated and we are
-                                   // in the idle loop.
-    kDSOEventType_DSOResponse,     // DSOState.primary and DSOState.additl contain any TLVs in the response;
-                                   // header contains the DNS header
-    kDSOEventType_Connected,       // We succeeded in making a connection
-    kDSOEventType_ConnectFailed,   // We failed to get a connection
-    kDSOEventType_Disconnected,    // We were connected, but have disconnected or been disconnected
-    kDSOEventType_ShouldReconnect, // We are disconnected, and a scheduled reconnect timer has gone off.
-    							   // Recipient is responsible for reconnecting, or deciding not to.
-    kDSOEventType_Inactive,		   // We went inactive and the inactivity timeout expired, so it's time to drop the connection.
-    kDSOEventType_Keepalive,       // It's time to send a keepalive message, here are the values to send
-    kDSOEventType_KeepaliveRcvd,   // We just received a keepalive from a client, here are the values.
-    kDSOEventType_RetryDelay       // We got a RetryDelay from the server.   Have to shut down.
-} dso_event_type_t;
-
-typedef struct dso_outstanding_query {
-    uint16_t id;
-    void *context;
-} dso_outstanding_query_t;
-
-typedef struct dso_outstanding_query_state {
-    int outstanding_query_count;
-    int max_outstanding_queries;
-    dso_outstanding_query_t queries[0];
-} dso_outstanding_query_state_t;
-
-typedef struct dso_query_receive_context {
-    void *query_context;
-    void *message_context;
-    uint16_t rcode;
-} dso_query_receive_context_t;
-
-typedef struct dso_disconnect_context {
-    uint32_t reconnect_delay;
-} dso_disconnect_context_t;
-
-typedef struct dso_keepalive_context {
-    uint32_t inactivity_timeout;
-    uint32_t keepalive_interval;
-} dso_keepalive_context_t;
-
-// Structure to represent received DSO TLVs
-typedef struct dsotlv {
-    uint16_t opcode;
-    uint16_t length;
-    const uint8_t *payload;
-} dso_tlv_t;
-
-// DSO message under construction
-typedef struct dso_message {
-    uint8_t *buf;                 // The buffer in which we are constructing the message
-    size_t max;                   // Size of the buffer
-    size_t cur;                   // Current position in the buffer
-    bool building_tlv;            // True if we have started and not finished building a TLV
-    int outstanding_query_number; // Number of the outstanding query state entry for this message, or -1
-    size_t tlv_len;               // Current length of the TLV we are building.
-    size_t tlv_len_offset;        // Where to store the length of the current TLV when finished.
-    const uint8_t *no_copy_bytes; // One TLV can have data that isn't copied into the buffer
-    size_t no_copy_bytes_len;     // Length of that data, if any.
-    size_t no_copy_bytes_offset;  // Where in the buffer the data should be interposed.
-} dso_message_t;
-
-// Record of ongoing activity
-typedef struct dso_activity dso_activity_t;
-struct dso_activity {
-    dso_activity_t *next;
-    void (*finalize)(dso_activity_t *activity);
-    const char *activity_type;  // Name of the activity type, must be the same pointer for all activities of a type.
-    void *context;              // Activity implementation's context (if any).
-    char *name;                 // Name of the individual activity.
-};
-
-typedef struct dso_transport dso_transport_t;
-typedef struct dso_state dso_state_t;
-typedef int32_t event_time_t;
-
-typedef void (*dso_event_callback_t)(void *context, void *header,
-                                     dso_state_t *dso, dso_event_type_t eventType);
-typedef void (*dso_transport_finalize_t)(dso_transport_t *transport, const char *whence);
-
-typedef enum {
-    // When the object is created and holds a reference to the context, the callback(see below) is called with
-    // dso_life_cycle_create.
-    dso_life_cycle_create,
-    // When the object is canceled, the callback(see below) is called with dso_life_cycle_cancel to provide a chance
-    // for the context to do the corresponding cleaning work(cancel or release/free).
-    dso_life_cycle_cancel,
-    // When the object is freed, the callback(see below) is called with dso_life_cycle_free to provide a chance for the
-    // context to clean anything remains allocated.
-    dso_life_cycle_free
-} dso_life_cycle_t;
-
-typedef bool (*dso_life_cycle_context_callback_t)(const dso_life_cycle_t life_cycle, void *const context,
-                                                  dso_state_t *const dso);
-
-// DNS Stateless Operations state
-struct dso_state {
-    dso_state_t *next;
-    void *context;                   // The context of the next layer up (e.g., a Discovery Proxy)
-    // The callback gets called when dso_state_t is created, canceled or freed.
-    dso_life_cycle_context_callback_t context_callback;
-    dso_event_callback_t cb;         // Called when an event happens
-
-    // Transport state; handled separately for reusability
-    dso_transport_t *transport;		 // The transport (e.g., dso-transport.c or other).
-    dso_transport_finalize_t transport_finalize;
-
-    uint32_t serial;                 // Unique serial number which can be used after the DSO has been dropped.
-    bool is_server;                  // True if the endpoint represented by this DSO state is a server
-                                     // (according to the DSO spec)
-    bool has_session;                // True if DSO session establishment has happened for this DSO endpoint
-    event_time_t response_awaited;   // If we are waiting for a session-establishing response, when it's
-                                     // expected; otherwise zero.
-    uint32_t keepalive_interval;     // Time between keepalives (to be sent, on client, expected, on server)
-    uint32_t inactivity_timeout;     // Session can't be inactive more than this amount of time.
-    event_time_t keepalive_due;      // When the next keepalive is due (to be received or sent)
-    event_time_t inactivity_due;     // When next activity has to happen for connection to remain active
-    dso_activity_t *activities;      // Outstanding DSO activities.
-
-    dso_tlv_t primary;               // Primary TLV for current message
-    dso_tlv_t additl[MAX_ADDITLS];   // Additional TLVs
-    int num_additls;                 // Number of additional TLVs in this message
-
-    char *remote_name;
-
-    dso_outstanding_query_state_t *outstanding_queries;
-};
-
-// Provided by dso.c
-dso_state_t *dso_state_create(bool is_server, int max_outstanding_queries, const char *remote_name,
-                        dso_event_callback_t callback, void *const context,
-                        const dso_life_cycle_context_callback_t context_callback,
-                        dso_transport_t *transport);
-dso_state_t *dso_find_by_serial(uint32_t serial);
-void dso_state_cancel(dso_state_t *dso);
-int32_t dso_idle(void *context, int32_t now, int32_t next_timer_event);
-void dso_set_event_context(dso_state_t *dso, void *context);
-void dso_set_event_callback(dso_state_t *dso, dso_event_callback_t callback);
-void dso_start_tlv(dso_message_t *state, int opcode);
-void dso_add_tlv_bytes(dso_message_t *state, const uint8_t *bytes, size_t len);
-void dso_add_tlv_bytes_no_copy(dso_message_t *state, const uint8_t *bytes, size_t len);
-void dso_add_tlv_byte(dso_message_t *state, uint8_t byte);
-void dso_add_tlv_u16(dso_message_t *state, uint16_t u16);
-void dso_add_tlv_u32(dso_message_t *state, uint32_t u32);
-void dso_finish_tlv(dso_message_t *state);
-dso_activity_t *dso_find_activity(dso_state_t *dso, const char *name, const char *activity_type, void *context);
-dso_activity_t *dso_add_activity(dso_state_t *dso, const char *name, const char *activity_type,
-                                            void *context, void (*finalize)(dso_activity_t *));
-void dso_drop_activity(dso_state_t *dso, dso_activity_t *activity);
-uint32_t dso_ignore_further_responses(dso_state_t *dso, void *context);
-bool dso_make_message(dso_message_t *state, uint8_t *outbuf, size_t outbuf_size, dso_state_t *dso,
-                      bool unidirectional, bool response, uint16_t xid, int rcode, void *callback_state);
-size_t dso_message_length(dso_message_t *state);
-void dso_retry_delay(dso_state_t *dso, const DNSMessageHeader *header);
-void dso_keepalive(dso_state_t *dso, const DNSMessageHeader *header);
-void dso_message_received(dso_state_t *dso, const uint8_t *message, size_t message_length, void *context);
-void dns_message_received(dso_state_t *dso, const uint8_t *message, size_t message_length, void *context);
-
-const char *dso_event_type_to_string(dso_event_type_t dso_event_type);
-
-// Provided by DSO transport implementation for use by dso.c:
-int32_t dso_transport_idle(void *context, int32_t now, int32_t next_timer_event);
-bool dso_send_simple_response(dso_state_t *dso, int rcode, const DNSMessageHeader *header, const char *pres);
-bool dso_send_not_implemented(dso_state_t *dso, const DNSMessageHeader *header);
-bool dso_send_refused(dso_state_t *dso, const DNSMessageHeader *header);
-bool dso_send_formerr(dso_state_t *dso, const DNSMessageHeader *header);
-bool dso_send_servfail(dso_state_t *dso, const DNSMessageHeader *header);
-bool dso_send_name_error(dso_state_t *dso, const DNSMessageHeader *header);
-bool dso_send_no_error(dso_state_t *dso, const DNSMessageHeader *header);
-#endif // !defined(__DSO_H)
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/Makefile b/ServiceRegistration/Makefile
index e75b927..719d09b 100644
--- a/ServiceRegistration/Makefile
+++ b/ServiceRegistration/Makefile
@@ -104,13 +104,13 @@
 $(BUILDDIR)/dnssd-proxy:  $(OBJDIR)/dnssd-proxy.o $(SIMPLEOBJS) $(DSOOBJS) $(MDNSOBJS) $(FROMWIREOBJS) $(IOOBJS) $(CFOBJS) $(OBJDIR)/srp-log.o
 	$(CC) -o $@ $+ $(SRPLDOPTS)
 
-$(BUILDDIR)/srp-client:	$(OBJDIR)/srp-ioloop.o $(OBJDIR)/srp-client.o $(OBJDIR)/dnssd_clientlib.o $(CTIOBJS) $(SIMPLEOBJS) $(IOWOTLSOBJS) $(CFOBJS)
+$(BUILDDIR)/srp-client:	$(OBJDIR)/srp-ioloop.o $(OBJDIR)/srp-client.o $(OBJDIR)/dnssd_clientlib.o $(CTIOBJS) $(SIMPLEOBJS) $(IOWOTLSOBJS) $(CFOBJS) $(DSOOBJS) $(FROMWIREOBJS)
 	$(CC) -o $@ $+ $(SRPLDOPTS)
 
 $(BUILDDIR)/srp-dns-proxy:	$(OBJDIR)/srp-dns-proxy.o $(OBJDIR)/srp-parse.o $(SIMPLEOBJS) $(FROMWIREOBJS) $(IOOBJS) $(HMACOBJS) $(CFOBJS)
 	$(CC) -o $@ $+ $(SRPLDOPTS)
 
-$(BUILDDIR)/srp-mdns-proxy:	$(OBJDIR)/srp-mdns-proxy.o $(OBJDIR)/srp-parse.o $(OBJDIR)/route.o $(OBJDIR)/adv-ctl-server.o $(OBJDIR)/combined-dnssd-proxy.o $(OBJDIR)/srp-replication.o $(OBJDIR)/srp-log.o $(CTIOBJS) $(MDNSOBJS) $(SIMPLEOBJS) $(DSOOBJS) $(FROMWIREOBJS) $(IOOBJS) $(HMACOBJS) $(CFOBJS)
+$(BUILDDIR)/srp-mdns-proxy:	$(OBJDIR)/srp-mdns-proxy.o $(OBJDIR)/srp-parse.o $(OBJDIR)/route.o $(OBJDIR)/omr-watcher.o $(OBJDIR)/adv-ctl-server.o $(OBJDIR)/combined-dnssd-proxy.o $(OBJDIR)/srp-replication.o $(OBJDIR)/srp-log.o $(CTIOBJS) $(MDNSOBJS) $(SIMPLEOBJS) $(DSOOBJS) $(FROMWIREOBJS) $(IOOBJS) $(HMACOBJS) $(CFOBJS)
 	$(CC) -o $@ $+ $(SRPLDOPTS)
 
 $(BUILDDIR)/keydump:	$(OBJDIR)/keydump.o $(MDNSOBJS) $(SIMPLEOBJS) $(FROMWIREOBJS) $(IOOBJS)
diff --git a/ServiceRegistration/adv-ctl-common.h b/ServiceRegistration/adv-ctl-common.h
deleted file mode 100644
index 4e64b6c..0000000
--- a/ServiceRegistration/adv-ctl-common.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* adv-ctl-common.h
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains Macros shared by service registration code.
- */
-
-
-#ifndef XPC_CLIENT_ADVERTISING_PROXY_H
-#define XPC_CLIENT_ADVERTISING_PROXY_H
-
-#define kDNSSDAdvertisingProxyResponse                     0
-#define kDNSSDAdvertisingProxyEnable                       1
-#define kDNSSDAdvertisingProxyListServiceTypes             2
-#define kDNSSDAdvertisingProxyListServices                 3
-#define kDNSSDAdvertisingProxyListHosts                    4
-#define kDNSSDAdvertisingProxyGetHost                      5
-#define kDNSSDAdvertisingProxyFlushEntries                 6
-#define kDNSSDAdvertisingProxyBlockService                 7
-#define kDNSSDAdvertisingProxyUnblockService               8
-#define kDNSSDAdvertisingProxyRegenerateULA                9
-#define kDNSSDAdvertisingProxyAdvertisePrefix              10
-#define kDNSSDAdvertisingProxyStop                         11
-#define kDNSSDAdvertisingProxyGetULA                       12
-#define kDNSSDAdvertisingProxyDisableReplication           13
-#define kDNSSDAdvertisingProxyDropSrplConnection           14
-#define kDNSSDAdvertisingProxyUndropSrplConnection         15
-#define kDNSSDAdvertisingProxyDropSrplAdvertisement        16
-#define kDNSSDAdvertisingProxyUndropSrplAdvertisement      17
-#define kDNSSDAdvertisingProxyAddPrefix                    18
-#define kDNSSDAdvertisingProxyRemovePrefix                 19
-#define kDNSSDAdvertisingProxyStartDroppingPushConnections 20
-
-#endif /* XPC_CLIENT_ADVERTISING_PROXY_H */
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/adv-ctl-server.c b/ServiceRegistration/adv-ctl-server.c
deleted file mode 100644
index bea9f4d..0000000
--- a/ServiceRegistration/adv-ctl-server.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/* adv-ctl-proxy.c
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains the SRP Advertising Proxy control interface, which allows clients to control the advertising proxy
- * and discover information about its internal state. This is largely used for testing.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dns_sd.h>
-#include <net/if.h>
-#include <inttypes.h>
-#include <sys/resource.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "cti-services.h"
-#include "route.h"
-#include "adv-ctl-server.h"
-#include "srp-replication.h"
-#include "dnssd-proxy.h"
-
-#include "cti-proto.h"
-#include "adv-ctl-common.h"
-#include "advertising_proxy_services.h"
-
-
-static int
-adv_ctl_block_service(bool enable, void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-#if THREAD_BORDER_ROUTER
-    srp_server_t *server_state = context;
-    if (enable) {
-        if (server_state->route_state->srp_listener != NULL) {
-            srp_proxy_listener_cancel(server_state->route_state->srp_listener);
-            server_state->route_state->srp_listener = NULL;
-        } else {
-            status = kDNSSDAdvertisingProxyStatus_UnknownErr;
-        }
-    } else {
-        if (server_state->route_state->srp_listener == NULL) {
-            partition_start_srp_listener(server_state->route_state);
-        } else {
-            status = kDNSSDAdvertisingProxyStatus_UnknownErr;
-        }
-    }
-#else
-    (void)enable;
-    (void)context;
-#endif // THREAD_BORDER_ROUTER
-    return status;
-}
-
-static bool
-adv_ctl_regenerate_ula(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-    srp_server_t *server_state = context;
-
-#if THREAD_BORDER_ROUTER
-    partition_stop_advertising_pref_id(server_state->route_state);
-    infrastructure_network_shutdown(server_state->route_state);
-    route_ula_generate(server_state->route_state);
-    infrastructure_network_startup(server_state->route_state);
-#endif
-    return status;
-}
-
-static int
-adv_ctl_advertise_prefix(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-    srp_server_t *server_state = context;
-
-#if THREAD_BORDER_ROUTER
-    partition_publish_my_prefix(server_state->route_state);
-#endif
-    return status;
-}
-
-static int
-adv_ctl_prefix_add_remove(void *context, xpc_object_t request, bool add)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-    srp_server_t *server_state = context;
-    const uint8_t *data;
-    size_t data_len;
-
-    data = xpc_dictionary_get_data(request, "data", &data_len);
-    if (data != NULL && data_len == 16) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(data, prefix_buf);
-        INFO("got prefix " PRI_SEGMENTED_IPv6_ADDR_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(data, prefix_buf));
-#if THREAD_BORDER_ROUTER
-        if (add) {
-            adv_ctl_add_prefix(server_state->route_state, data);
-        } else {
-            adv_ctl_remove_prefix(server_state->route_state, data);
-        }
-#endif
-    } else {
-        ERROR("invalid request, data[%p], data_len[%ld]", data, data_len);
-        status = kDNSSDAdvertisingProxyStatus_BadParam;
-    }
-    return status;
-}
-
-static int
-adv_ctl_stop_advertising_service(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-    srp_server_t *server_state = context;
-
-#if THREAD_BORDER_ROUTER
-    partition_discontinue_srp_service(server_state->route_state);
-#endif
-    return status;
-}
-
-static int
-adv_ctl_disable_replication(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-
-#if SRP_FEATURE_REPLICATION
-    srp_server_t *server_state = context;
-    srpl_disable(server_state);
-#else
-    (void)context;
-#endif
-    return status;
-}
-
-static int
-adv_ctl_drop_srpl_connection(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-
-#if SRP_FEATURE_REPLICATION
-    srp_server_t *server_state = context;
-    srpl_drop_srpl_connection(server_state);
-#else
-    (void)context;
-#endif
-    return status;
-}
-
-static int
-adv_ctl_undrop_srpl_connection(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-
-#if SRP_FEATURE_REPLICATION
-    srp_server_t *server_state = context;
-    srpl_undrop_srpl_connection(server_state);
-#else
-    (void)context;
-#endif
-    return status;
-}
-
-static int
-adv_ctl_drop_srpl_advertisement(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-
-#if SRP_FEATURE_REPLICATION
-    srp_server_t *server_state = context;
-    srpl_drop_srpl_advertisement(server_state);
-#else
-    (void)context;
-#endif
-    return status;
-}
-
-static int
-adv_ctl_undrop_srpl_advertisement(void *context)
-{
-    int status = kDNSSDAdvertisingProxyStatus_NoError;
-
-#if SRP_FEATURE_REPLICATION
-    srp_server_t *server_state = context;
-    srpl_undrop_srpl_advertisement(server_state);
-#else
-    (void)context;
-#endif
-    return status;
-}
-
-
-static void
-adv_ctl_fd_finalize(void *context)
-{
-    advertising_proxy_conn_ref connection = context;
-    connection->io_context = NULL;
-    RELEASE_HERE(connection, cti_connection_finalize);
-}
-
-static bool
-adv_ctl_list_services(advertising_proxy_conn_ref connection, void *context)
-{
-    srp_server_t *server_state = context;
-    adv_host_t *host;
-    int i;
-    int64_t now = ioloop_timenow();
-	int num_hosts = 0;
-
-	for (host = hosts; host != NULL; host = host->next) {
-		num_hosts++;
-	}
-	if (!cti_connection_message_create(connection, kDNSSDAdvertisingProxyResponse, 200) ||
-		!cti_connection_u32_put(connection, (uint32_t)kDNSSDAdvertisingProxyStatus_NoError) ||
-		!cti_connection_u32_put(connection, num_hosts))
-	{
-		ERROR("adv_ctl_list_services: error starting response");
-		cti_connection_close(connection);
-		return false;
-	}
-	for (host = server_state->hosts; host != NULL; host = host->next) {
-		int num_addresses = 0;
-		int num_instances = 0;
-		if (!cti_connection_string_put(connection, host->name) ||
-			!cti_connection_string_put(connection, host->registered_name) ||
-			!cti_connection_u32_put(connection, host->lease_expiry >= now ? host->lease_expiry - now : 0) ||
-			!cti_connection_bool_put(connection, host->removed) ||
-			!cti_connection_u64_put(connection, host->update_server_id))
-		{
-			ERROR("adv_ctl_list_services: unable to write host info for host %s", host->name);
-			cti_connection_close(connection);
-			return false;
-		}
-
-        cti_connection_u64_put(connection, host->server_stable_id);
-
-        if (host->addresses != NULL) {
-            for (i = 0; i < host->addresses->num; i++) {
-                if (host->addresses->vec[i] != NULL) {
-                    num_addresses++;
-                }
-            }
-        }
-		cti_connection_u16_put(connection, num_addresses);
-        if (host->addresses != NULL) {
-            for (i = 0; i < host->addresses->num; i++) {
-                if (host->addresses->vec[i] != NULL) {
-                    if (!cti_connection_u16_put(connection, host->addresses->vec[i]->rrtype) ||
-                        !cti_connection_data_put(connection, host->addresses->vec[i]->rdata, host->addresses->vec[i]->rdlen))
-                    {
-                        ERROR("adv_ctl_list_services: unable to write address %d for host %s", i, host->name);
-                        cti_connection_close(connection);
-                        return false;
-                    }
-                }
-            }
-        }
-        if (host->instances != NULL) {
-            for (i = 0; i < host->instances->num; i++) {
-                if (host->instances->vec[i] != NULL) {
-                    num_instances++;
-                }
-            }
-        }
-		cti_connection_u16_put(connection, num_instances);
-        if (host->instances != NULL) {
-            for (i = 0; i < host->instances->num; i++) {
-                adv_instance_t *instance = host->instances->vec[i];
-                if (instance != NULL) {
-                    if (!cti_connection_string_put(connection, instance->instance_name) ||
-                        !cti_connection_string_put(connection, instance->service_type) ||
-                        !cti_connection_u16_put(connection, instance->port) ||
-                        !cti_connection_data_put(connection, instance->txt_data, instance->txt_length))
-                    {
-                        ERROR("adv_ctl_list_services: unable to write address %d for host %s", i, host->name);
-                        cti_connection_close(connection);
-                        return false;
-                    }
-                }
-			}
-		}
-    }
-	return cti_connection_message_send(connection);
-}
-
-static bool
-adv_ctl_get_ula(advertising_proxy_conn_ref connection, void *context)
-{
-    srp_server_t *server_state = context;
-
-    if (!cti_connection_message_create(connection, kDNSSDAdvertisingProxyResponse, 200) ||
-        !cti_connection_u32_put(connection, (uint32_t)kDNSSDAdvertisingProxyStatus_NoError))
-    {
-        ERROR("error starting response");
-        cti_connection_close(connection);
-        return false;
-    }
-    // Copy out just the global ID part of the ULA prefix.
-    uint64_t ula = 0;
-    for (int j = 1; j < 6; j++) {
-        ula = ula << 8 | (((uint8_t *)&server_state->ula_prefix)[j]);
-    }
-    if (!cti_connection_u64_put(connection, ula)) {
-        ERROR("error sending ula");
-        cti_connection_close(connection);
-        return false;
-    }
-    return cti_connection_message_send(connection);
-}
-
-static void
-adv_ctl_message_parse(advertising_proxy_conn_ref connection, void *context)
-{
-	int status = kDNSSDAdvertisingProxyStatus_NoError;
-	cti_connection_parse_start(connection);
-	if (!cti_connection_u16_parse(connection, &connection->message_type)) {
-		return;
-	}
-	switch(connection->message_type) {
-    case kDNSSDAdvertisingProxyEnable:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyEnable request.",
-			 connection->uid, connection->gid);
-		break;
-	case kDNSSDAdvertisingProxyListServiceTypes:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyListServiceTypes request.",
-			 connection->uid, connection->gid);
-		break;
-	case kDNSSDAdvertisingProxyListServices:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyListServices request.",
-			 connection->uid, connection->gid);
-        adv_ctl_list_services(connection, context);
-		return;
-	case kDNSSDAdvertisingProxyListHosts:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyListHosts request.",
-			 connection->uid, connection->gid);
-		break;
-	case kDNSSDAdvertisingProxyGetHost:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyGetHost request.",
-			 connection->uid, connection->gid);
-		break;
-	case kDNSSDAdvertisingProxyFlushEntries:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyFlushEntries request.",
-			 connection->uid, connection->gid);
-        srp_mdns_flush(context);
-		break;
-	case kDNSSDAdvertisingProxyBlockService:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyBlockService request.",
-			 connection->uid, connection->gid);
-        adv_ctl_block_service(true, context);
-		break;
-	case kDNSSDAdvertisingProxyUnblockService:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyUnblockService request.",
-			 connection->uid, connection->gid);
-        adv_ctl_block_service(false, context);
-		break;
-	case kDNSSDAdvertisingProxyRegenerateULA:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyRegenerateULA request.",
-			 connection->uid, connection->gid);
-        adv_ctl_regenerate_ula(context);
-		break;
-    case kDNSSDAdvertisingProxyAdvertisePrefix:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyAdvertisePrefix request.",
-             connection->uid, connection->gid);
-        adv_ctl_advertise_prefix(context);
-        break;
-    case kDNSSDAdvertisingProxyAddPrefix:
-        void *data = NULL;
-        uint16_t data_len;
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyAddPrefix request.",
-             connection->uid, connection->gid);
-        if (!cti_connection_data_parse(connection, &data, &data_len)) {
-            ERROR("faile to parse data for kDNSSDAdvertisingProxyAddPrefix request.");
-            status = kDNSSDAdvertisingProxyStatus_BadParam;
-        } else {
-            if (data != NULL && data_len == 16) {
-                SEGMENTED_IPv6_ADDR_GEN_SRP(data, prefix_buf);
-                INFO("got prefix " PRI_SEGMENTED_IPv6_ADDR_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(data, prefix_buf));
-                status = adv_ctl_add_prefix(context, data);
-            } else {
-                ERROR("invalid add prefix request, data[%p], data_len[%ld]", data, data_len);
-                status = kDNSSDAdvertisingProxyStatus_BadParam;
-            }
-        }
-        break;
-    case kDNSSDAdvertisingProxyRemovePrefix:
-        void *data = NULL;
-        uint16_t data_len;
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyRemovePrefix request.",
-             connection->uid, connection->gid);
-        if (!cti_connection_data_parse(connection, &data, &data_len)) {
-            ERROR("faile to parse data for kDNSSDAdvertisingProxyRemovePrefix request.");
-            status = kDNSSDAdvertisingProxyStatus_BadParam;
-        } else {
-            if (data != NULL && data_len == 16) {
-                SEGMENTED_IPv6_ADDR_GEN_SRP(data, prefix_buf);
-                INFO("got prefix " PRI_SEGMENTED_IPv6_ADDR_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(data, prefix_buf));
-                status = adv_ctl_add_prefix(context, data);
-            } else {
-                ERROR("invalid add prefix request, data[%p], data_len[%ld]", data, data_len);
-                status = kDNSSDAdvertisingProxyStatus_BadParam;
-            }
-        }
-        break;
-    case kDNSSDAdvertisingProxyStop:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyStop request.",
-             connection->uid, connection->gid);
-        adv_ctl_stop_advertising_service(context);
-        break;
-    case kDNSSDAdvertisingProxyGetULA:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyULA request.",
-             connection->uid, connection->gid);
-        adv_ctl_get_ula(connection, context);
-        break;
-    case kDNSSDAdvertisingProxyDisableReplication:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyDisableReplication request.",
-             connection->uid, connection->gid);
-        adv_ctl_disable_replication(context);
-        break;
-    case kDNSSDAdvertisingProxyDropSrplConnection:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyDropSrplConnection request.",
-             connection->uid, connection->gid);
-        adv_ctl_drop_srpl_connection(context);
-        break;
-    case kDNSSDAdvertisingProxyUndropSrplConnection:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyUndropSrplConnection request.",
-             connection->uid, connection->gid);
-        adv_ctl_undrop_srpl_connection(context);
-        break;
-    case kDNSSDAdvertisingProxyDropSrplAdvertisement:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyDropSrplAdvertisement request.",
-             connection->uid, connection->gid);
-        adv_ctl_drop_srpl_advertisement(context);
-        break;
-    case kDNSSDAdvertisingProxyUndropSrplAdvertisement:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyUndropSrplAdvertisement request.",
-             connection->uid, connection->gid);
-        adv_ctl_undrop_srpl_advertisement(context);
-        break;
-
-    case kDNSSDAdvertisingProxyStartDroppingPushConnections:
-        INFO("Client uid %d pid %d sent a kDNSSDAdvertisingProxyStartDroppingPushConnections request.",
-             connection->uid, connection->gid);
-        dp_start_smashing();
-        break;
-
-	default:
-        ERROR("Client uid %d pid %d sent a request with unknown message type %d.",
-			  connection->uid, connection->gid, connection->message_type);
-        status = kDNSSDAdvertisingProxyStatus_Invalid;
-		break;
-	}
-	cti_send_response(connection, status);
-	cti_connection_close(connection);
-}
-
-static void
-adv_ctl_read_callback(io_t *UNUSED io, void *context)
-{
-    advertising_proxy_conn_ref connection = context;
-
-    cti_read(connection, adv_ctl_message_parse);
-}
-
-static void
-adv_ctl_listen_callback(io_t *UNUSED io, void *context)
-{
-    srp_server_t *server_state = context;
-	uid_t uid;
-	gid_t gid;
-	pid_t pid;
-
-	int fd = cti_accept(server_state->adv_ctl_listener->fd, &uid, &gid, &pid);
-	if (fd < 0) {
-		return;
-	}
-
-    advertising_proxy_conn_ref connection = cti_connection_allocate(500);
-    if (connection == NULL) {
-        ERROR("cti_listen_callback: no memory for connection.");
-		close(fd);
-        return;
-    }
-    RETAIN_HERE(connection);
-
-    connection->fd = fd;
-	connection->uid = uid;
-	connection->gid = gid;
-	connection->pid = pid;
-    connection->io_context = ioloop_file_descriptor_create(connection->fd, connection, adv_ctl_fd_finalize);
-    if (connection->io_context == NULL) {
-        ERROR("cti_listen_callback: no memory for io context.");
-		close(fd);
-		RELEASE_HERE(connection, cti_connection_finalize);
-        return;
-    }
-    ioloop_add_reader(connection->io_context, adv_ctl_read_callback);
-    connection->context = context;
-    connection->callback.callback = NULL;
-    connection->internal_callback = NULL;
-    return;
-}
-
-static int
-adv_ctl_listen(srp_server_t *server_state)
-{
-    int fd = cti_make_unix_socket(ADV_CTL_SERVER_SOCKET_NAME, sizeof(ADV_CTL_SERVER_SOCKET_NAME), true);
-    if (fd < 0) {
-        int ret = (errno == ECONNREFUSED
-				   ? kDNSSDAdvertisingProxyStatus_DaemonNotRunning
-				   : errno == EPERM ? kDNSSDAdvertisingProxyStatus_NotPermitted : kDNSSDAdvertisingProxyStatus_UnknownErr);
-        ERROR("adv_ctl_listener: socket: %s", strerror(errno));
-        return ret;
-    }
-
-    server_state->adv_ctl_listener = ioloop_file_descriptor_create(fd, server_state, NULL);
-    if (server_state->listener == NULL) {
-        ERROR("adv_ctl_listener: no memory for io_t object.");
-		close(fd);
-        return kDNSSDAdvertisingProxyStatus_NoMemory;
-    }
-    RETAIN_HERE(server_state->adv_ctl_listener);
-
-    ioloop_add_reader(server_state->adv_ctl_listener, adv_ctl_listen_callback);
-    return kDNSSDAdvertisingProxyStatus_NoError;
-}
-
-bool
-adv_ctl_init(void *context)
-{
-    srp_server_t *server_state = context;
-	return adv_ctl_listen(server_state);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/adv-ctl-server.h b/ServiceRegistration/adv-ctl-server.h
deleted file mode 100644
index 8b6fe20..0000000
--- a/ServiceRegistration/adv-ctl-server.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* adv-ctl-server.h
- *
- * Copyright (c) 2020 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface for Thread Border router control.
- */
-
-#ifndef __ADV_CTL_SERVER_H__
-#define __ADV_CTL_SERVER_H__
-bool adv_ctl_init(void *NULLABLE context);
-#endif /* __ADV_CTL_SERVER_H__ */
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/advertising_proxy_services.c b/ServiceRegistration/advertising_proxy_services.c
deleted file mode 100644
index 0d9a2e2..0000000
--- a/ServiceRegistration/advertising_proxy_services.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/* advertising_proxy_services.h
- *
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains the implementation of the SRP Advertising Proxy management
- * API on MacOS, which is private API used to control and manage the advertising
- * proxy.
- */
-
-
-
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "cti-proto.h"
-
-#include "adv-ctl-common.h"
-#include "advertising_proxy_services.h"
-
-static void
-adv_host_finalize(advertising_proxy_host_t *host)
-{
-    int i;
-
-    free(host->hostname);
-    free(host->regname);
-
-    if (host->addresses != NULL) {
-        for (i = 0; i < host->num_addresses; i++) {
-            free(host->addresses[i].rdata);
-        }
-        free(host->addresses);
-    }
-    if (host->instances != NULL) {
-        for (i = 0; i < host->num_instances; i++) {
-            free(host->instances[i].instance_name);
-            free(host->instances[i].service_type);
-            free(host->instances[i].txt_data);
-        }
-    }
-    free(host);
-}
-
-#define adv_host_allocate() adv_host_allocate_(__FILE__, __LINE__)
-static advertising_proxy_host_t *
-adv_host_allocate_(const char *file, int line)
-{
-    advertising_proxy_host_t *host = calloc(1, sizeof(*host));
-    if (host == NULL) {
-        return host;
-    }
-    RETAIN(host);
-    return host;
-}
-
-
-
-static void
-adv_fd_finalize(void *context)
-{
-    advertising_proxy_conn_ref connection = context;
-    connection->io_context = NULL;
-    RELEASE_HERE(connection, cti_connection_finalize);
-}
-
-void
-advertising_proxy_ref_dealloc(advertising_proxy_conn_ref conn_ref)
-{
-    if (conn_ref == NULL) {
-        ERROR("advertising_proxy_ref_dealloc called with NULL advertising_proxy_conn_ref");
-        return;
-    }
-    conn_ref->callback.callback = NULL;
-    cti_connection_close(conn_ref);
-
-    // This is releasing the caller's reference. We may still have an internal reference.
-    RELEASE_HERE(conn_ref, cti_connection_finalize);
-    ERROR("advertising_proxy_ref_dealloc successfully released conn_ref");
-}
-
-static void
-adv_message_parse(cti_connection_t connection)
-{
-    int err = kDNSSDAdvertisingProxyStatus_NoError;
-    int32_t status;
-
-    cti_connection_parse_start(connection);
-    if (!cti_connection_u16_parse(connection, &connection->message_type)) {
-        err = kDNSSDAdvertisingProxyStatus_Disconnected;
-        goto out;
-    }
-    if (connection->message_type != kDNSSDAdvertisingProxyResponse) {
-        syslog(LOG_ERR, "adv_message_parse: unexpected message type %d", connection->message_type);
-        err = kDNSSDAdvertisingProxyStatus_Disconnected;
-        goto out;
-    }
-    if (!cti_connection_u32_parse(connection, (uint32_t *)&status)) {
-        err = kDNSSDAdvertisingProxyStatus_Disconnected;
-        goto out;
-    }
-    if (status != kDNSSDAdvertisingProxyStatus_NoError) {
-        goto out;
-    }
-    if (connection->internal_callback != NULL) {
-        (*connection->internal_callback)(connection, NULL, status);
-    } else {
-        if (!cti_connection_parse_done(connection)) {
-            err = kDNSSDAdvertisingProxyStatus_Disconnected;
-            goto out;
-        }
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, NULL, status);
-        }
-    }
-    return;
-out:
-    cti_connection_close(connection);
-    if (connection->callback.reply != NULL) {
-        connection->callback.reply(connection, NULL, err);
-    }
-    return;
-}
-
-static void
-adv_read_callback(io_t *UNUSED io, void *context)
-{
-    cti_connection_t connection = context;
-
-    cti_read(connection, adv_message_parse);
-}
-
-static void
-adv_service_list_callback(cti_connection_t connection, void *UNUSED object, cti_status_t UNUSED status)
-{
-    int i;
-    advertising_proxy_host_t *host = NULL;
-    uint32_t num_hosts;
-
-	if (!cti_connection_u32_parse(connection, &num_hosts)) {
-		ERROR("adv_ctl_list_callback: error parsing host count");
-        goto fail;
-	}
-	for (i = 0; i < num_hosts; i++) {
-        host = adv_host_allocate();
-        if (host == NULL) {
-            ERROR("adv_ctl_list_callback: no memory for host object");
-            cti_connection_close(connection);
-            goto fail;
-        }
-		if (!cti_connection_string_parse(connection, &host->hostname) ||
-			!cti_connection_string_parse(connection, &host->regname) ||
-			!cti_connection_u32_parse(connection, &host->lease_time) ||
-            !cti_connection_bool_parse(connection, &host->removed) ||
-            !cti_connection_u64_parse(connection, &host->server_id))
-		{
-			ERROR("adv_ctl_list_callback: unable to parse host info for host %d", i);
-			cti_connection_close(connection);
-            goto fail;
-		}
-
-		if (!cti_connection_u16_parse(connection, &host->num_addresses)) {
-			ERROR("adv_ctl_list_callback: unable to parse host address count for host %s", host->hostname);
-			cti_connection_close(connection);
-            goto fail;
-        }
-        if (host->num_addresses > 0) {
-            host->addresses = calloc(host->num_addresses, sizeof(advertising_proxy_host_address_t));
-            if (host->addresses == NULL) {
-					ERROR("adv_ctl_list_callback: no memory for addresses for host %s", host->hostname);
-                    goto fail;
-            }
-        }
-		for (i = 0; i < host->num_addresses; i++) {
-            if (!cti_connection_u16_parse(connection, &host->addresses[i].rrtype) ||
-                !cti_connection_data_parse(connection, (void **)&host->addresses[i].rdata, &host->addresses[i].rdlen))
-            {
-                ERROR("adv_ctl_list_callback: unable to parse address %d for host %s", i, host->hostname);
-                goto fail;
-            }
-		}
-
-        if (!cti_connection_u64_parse(connection, &host->server_id)) {
-            ERROR("adv_ctl_list_callback: unable to parse stable server ID for host %s", host->hostname);
-            goto fail;
-        }
-
-        if (!cti_connection_u16_parse(connection, &host->num_instances)) {
-			ERROR("adv_ctl_list_callback: unable to parse host address count for host %s", host->hostname);
-			cti_connection_close(connection);
-            goto fail;
-        }
-        if (host->num_instances > 0) {
-            host->instances = calloc(host->num_instances, sizeof(advertising_proxy_instance_t));
-            if (host->instances == NULL) {
-                ERROR("adv_ctl_list_callback: no memory for instances for host %s", host->hostname);
-                    goto fail;
-            }
-        }
-		for (i = 0; i < host->num_instances; i++) {
-            if (!cti_connection_string_parse(connection, &host->instances[i].instance_name) ||
-                !cti_connection_string_parse(connection, &host->instances[i].service_type) ||
-                !cti_connection_u16_parse(connection, &host->instances[i].port) ||
-                !cti_connection_data_parse(connection, (void **)&host->instances[i].txt_data, &host->instances[i].txt_len))
-            {
-                ERROR("adv_ctl_list_callback: unable to write address %d for host %s", i, host->hostname);
-                goto fail;
-            }
-		}
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, host, kDNSSDAdvertisingProxyStatus_NoError);
-        }
-        RELEASE_HERE(host, adv_host_finalize);
-        host = NULL;
-    }
-
-    if (!cti_connection_parse_done(connection)) {
-    fail:
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, NULL, kDNSSDAdvertisingProxyStatus_Disconnected);
-        }
-    } else {
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, NULL, kDNSSDAdvertisingProxyStatus_NoError);
-        }
-    }
-    if (host != NULL) {
-        RELEASE_HERE(host, adv_host_finalize);
-    }
-}
-
-static void
-adv_ula_callback(cti_connection_t connection, void *UNUSED object, cti_status_t UNUSED status)
-{
-    uint64_t ula_prefix;
-
-	if (!cti_connection_u64_parse(connection, &ula_prefix)) {
-		ERROR("error parsing ula prefix");
-        goto fail;
-	}
-
-    if (!cti_connection_parse_done(connection)) {
-    fail:
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, NULL, kDNSSDAdvertisingProxyStatus_Disconnected);
-        }
-    } else {
-        if (connection->callback.reply != NULL) {
-            connection->callback.reply(connection, &ula_prefix, kDNSSDAdvertisingProxyStatus_NoError);
-        }
-    }
-}
-
-#define adv_send_command(ref, client_queue, command_name, command, app_callback, internal_callback, allocation)  \
-    adv_send_command_(ref, client_queue, command_name, command, app_callback, internal_callback, allocation, __FILE__, __LINE__)
-static advertising_proxy_error_type
-adv_send_command_(advertising_proxy_conn_ref *ref, run_context_t client_queue, const char *command_name, int command,
-                  advertising_proxy_reply app_callback, cti_internal_callback_t internal_callback, size_t allocation,
-                  const char *file, int line)
-{
-    int fd;
-    cti_connection_t connection;
-
-    fd = cti_make_unix_socket(ADV_CTL_SERVER_SOCKET_NAME, sizeof(ADV_CTL_SERVER_SOCKET_NAME), false);
-    if (fd < 0) {
-        return kDNSSDAdvertisingProxyStatus_DaemonNotRunning;
-    }
-    connection = cti_connection_allocate(allocation);
-    if (connection == NULL) {
-        close(fd);
-        return kDNSSDAdvertisingProxyStatus_NoMemory;
-    }
-    connection->fd = fd;
-    RETAIN(connection);
-
-    connection->io_context = ioloop_file_descriptor_create(connection->fd, connection, adv_fd_finalize);
-    if (connection->io_context == NULL) {
-        ERROR("cti_listen_callback: no memory for io context.");
-		close(fd);
-		RELEASE_HERE(connection, cti_connection_finalize);
-        return kDNSSDAdvertisingProxyStatus_NoMemory;
-    }
-    ioloop_add_reader(connection->io_context, adv_read_callback);
-    connection->callback.reply = app_callback;
-    connection->internal_callback = internal_callback;
-    cti_connection_message_create(connection, command, 2);
-    cti_connection_message_send(connection);
-    *ref = connection;
-    return kDNSSDAdvertisingProxyStatus_NoError;
-}
-
-
-advertising_proxy_error_type
-advertising_proxy_flush_entries(advertising_proxy_conn_ref *conn_ref,
-                                run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_flush_entries",
-                            kDNSSDAdvertisingProxyFlushEntries, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_get_service_list(advertising_proxy_conn_ref *conn_ref,
-                                   run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_get_service_list",
-                            kDNSSDAdvertisingProxyListServices, callback, adv_service_list_callback, 4096);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_block_service(advertising_proxy_conn_ref *conn_ref,
-                                run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_block_service",
-                            kDNSSDAdvertisingProxyBlockService, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_unblock_service(advertising_proxy_conn_ref *conn_ref,
-                                  run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_unblock_service",
-                            kDNSSDAdvertisingProxyUnblockService, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_regenerate_ula(advertising_proxy_conn_ref *conn_ref,
-                                 run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_regenerate_ula",
-                            kDNSSDAdvertisingProxyRegenerateULA, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_advertise_prefix(advertising_proxy_conn_ref *conn_ref,
-                                   run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_advertise_prefix",
-                            kDNSSDAdvertisingProxyAdvertisePrefix, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_add_prefix(advertising_proxy_conn_ref *conn_ref, run_context_t client_queue,
-                             advertising_proxy_reply callback, const uint8_t *prefix_buf, size_t buf_len)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command_with_data(conn_ref, client_queue, "advertising_proxy_add_prefix",
-                                      kDNSSDAdvertisingProxyAddPrefix, callback, NULL, 0,
-                                      prefix_buf, buf_len);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_remove_prefix(advertising_proxy_conn_ref *conn_ref, run_context_t client_queue,
-                                advertising_proxy_reply callback, const uint8_t *prefix_buf, size_t buf_len)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command_with_data(conn_ref, client_queue, "advertising_proxy_remove_prefix",
-                                      kDNSSDAdvertisingProxyRemovePrefix, callback, NULL, 0,
-                                      prefix_buf, buf_len);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_stop(advertising_proxy_conn_ref *conn_ref,
-                       run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_stop",
-                            kDNSSDAdvertisingProxyStop, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_get_ula(advertising_proxy_conn_ref *conn_ref,
-                          run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_get_ula",
-                            kDNSSDAdvertisingProxyGetULA, callback, adv_ula_callback, 128);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_disable_srp_replication(advertising_proxy_conn_ref *conn_ref,
-                                          run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_disable_srp_replication",
-                            kDNSSDAdvertisingProxyDisableReplication, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_drop_srpl_connection(advertising_proxy_conn_ref *conn_ref,
-                                       run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_drop_srpl_connection",
-                            kDNSSDAdvertisingProxyDropSrplConnection, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_undrop_srpl_connection(advertising_proxy_conn_ref *conn_ref,
-                                         run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_undrop_srpl_connection",
-                            kDNSSDAdvertisingProxyUndropSrplConnection, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_drop_srpl_advertisement(advertising_proxy_conn_ref *conn_ref,
-                                          run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_drop_srpl_advertisement",
-                            kDNSSDAdvertisingProxyDropSrplAdvertisement, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_undrop_srpl_advertisement(advertising_proxy_conn_ref *conn_ref,
-                                            run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_disable_undrop_srpl_advertisement",
-                            kDNSSDAdvertisingProxyUndropSrplAdvertisement, callback, NULL, 0);
-    return errx;
-}
-
-advertising_proxy_error_type
-advertising_proxy_start_dropping_push_connections(advertising_proxy_conn_ref *conn_ref,
-                                                  run_context_t client_queue, advertising_proxy_reply callback)
-{
-    advertising_proxy_error_type errx;
-    errx = adv_send_command(conn_ref, client_queue, "advertising_proxy_disable_start_dropping_push_connections",
-                            kDNSSDAdvertisingProxyStartDroppingPushConnections, callback, NULL, 0);
-    return errx;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/advertising_proxy_services.h b/ServiceRegistration/advertising_proxy_services.h
deleted file mode 100644
index fa7b3c0..0000000
--- a/ServiceRegistration/advertising_proxy_services.h
+++ /dev/null
@@ -1,633 +0,0 @@
-/* advertising_proxy_services.h
- *
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains definitions for the SRP Advertising Proxy management
- * API on MacOS, which is private API used to control and manage the advertising
- * proxy.
- */
-
-#ifndef DNSSD_PROXY_SERVICES_H
-#define DNSSD_PROXY_SERVICES_H
-
-typedef void *run_context_t;
-typedef struct _cti_connection_t *advertising_proxy_conn_ref;
-#define ADV_CTL_SERVER_SOCKET_NAME "/var/run/adv-ctl-server-socket"
-#define RCHAR char
-#define RUCHAR uint8_t
-
-typedef struct advertising_proxy_host_address {
-    uint16_t rrtype;
-    RUCHAR *NULLABLE rdata;
-    uint16_t rdlen;
-} advertising_proxy_host_address_t;
-
-typedef struct advertising_proxy_instance {
-    RCHAR *NULLABLE instance_name;
-    RCHAR *NULLABLE service_type;
-    uint16_t port;
-    RUCHAR *NULLABLE txt_data;
-    uint16_t txt_len;
-} advertising_proxy_instance_t;
-
-typedef struct advertising_proxy_host {
-    int ref_count;
-    RCHAR *NULLABLE hostname;
-    RCHAR *NULLABLE regname;
-    uint16_t num_addresses;
-    uint32_t lease_time;
-    advertising_proxy_host_address_t *NULLABLE addresses;
-    uint16_t num_instances;
-    advertising_proxy_instance_t *NULLABLE instances;
-    bool removed;
-    uint64_t server_id;
-} advertising_proxy_host_t;
-
-#if (defined(__GNUC__) && (__GNUC__ >= 4))
-#define DNS_SERVICES_EXPORT __attribute__((visibility("default")))
-#else
-#define DNS_SERVICES_EXPORT
-#endif
-
-typedef enum
-{
-    kDNSSDAdvertisingProxyStatus_NoError                   =  0,
-    kDNSSDAdvertisingProxyStatus_UnknownErr                = -65537,   /* 0xFFFE FFFF */
-    kDNSSDAdvertisingProxyStatus_NoMemory                  = -65539,   /* No Memory   */
-    kDNSSDAdvertisingProxyStatus_BadParam                  = -65540,   /* Client passed invalid arg */
-    kDNSSDAdvertisingProxyStatus_Invalid                   = -65549,   /* Invalid message */
-    kDNSSDAdvertisingProxyStatus_DaemonNotRunning          = -65563,   /* Daemon not running */
-    kDNSSDAdvertisingProxyStatus_Disconnected              = -65569,   /* Daemon disconnected */
-    kDNSSDAdvertisingProxyStatus_NotPermitted              = -65571
-} advertising_proxy_error_type;
-
-/*********************************************************************************************
- *
- *  DNSSD Advertising Proxy control/management library functions
- *
- *********************************************************************************************/
-
-/* advertising_proxy_reply: Callback from all DNSSD Advertising proxy library functions
- *
- * advertising_proxy_reply() parameters:
- *
- * conn_ref:                   The advertising_proxy_conn_ref initialized by the library function.
- *
- * errCode:                    Will be kDNSSDAdvertisingProxy_NoError on success, otherwise will indicate the
- *                             failure that occurred.
- *
- */
-
-typedef void (*advertising_proxy_reply)
-(
-    advertising_proxy_conn_ref NULLABLE conn_ref,
-    void *                     NULLABLE data,
-    advertising_proxy_error_type        errCode
-);
-
-
-/* advertising_proxy_flush_entries
- *
- * Flushes any host entries that have been registered with the advertising proxy.   For testing only:
- * this is never the right thing to do in production.
- *
- * advertising_proxy_flush_entries() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  CallBack function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that DNSSD Advertising Proxy host
- *                            table was successfully flushed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_flush_entries
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_get_service_list
- *
- * Returns a list of registered services on the advertising proxy.
- *
- * advertising_proxy_get_service_list() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  CallBack function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that DNSSD Advertising Proxy host
- *                            table was successfully flushed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_get_service_list
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_block_service
- *
- * For testing, block advertisement of SRP service on the thread network.
- *
- * advertising_proxy_block_service() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  CallBack function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that DNSSD Advertising Proxy host
- *                            table was successfully flushed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_block_service
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_unblock_service
- *
- * For testing, unblock advertisement of SRP service on the thread network.
- *
- * advertising_proxy_unblock_service() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  CallBack function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that DNSSD Advertising Proxy host
- *                            table was successfully flushed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_unblock_service
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_regenerate_ula
- *
- * For testing, generate a new ULA prefix
- *
- * advertising_proxy_regenerate_ula() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  CallBack function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that DNSSD Advertising Proxy host
- *                            table was successfully flushed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_regenerate_ula
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_advertise_prefix
- *
- * For testing, advertise it's own prefix to thread network
- *
- * advertising_proxy_advertise_prefix() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that the prefix advertising
- *                            was successful. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_advertise_prefix
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_add_prefix
- *
- * For testing, stop advertising service
- *
- * advertising_proxy_add_prefix() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL).
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * prefix_buf:                 Prefix to be added.
- *
- * buf_len:                    Length of the prefixbuf.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that the service advertising
- *                            was stopped successfully. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning).
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_add_prefix
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback,
-    const uint8_t                       *NONNULL prefix_buf,
-    size_t                                       buf_len
-);
-
-/* advertising_proxy_remove_prefix
- *
- * For testing, stop advertising service
- *
- * advertising_proxy_remove_prefix() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL).
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * prefix_buf:                Prefix to be added.
- *
- * buf_len:                   Length of the prefixbuf.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that the service advertising
- *                            was stopped successfully. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning).
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_remove_prefix
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback,
-    const uint8_t                       *NONNULL prefix_buf,
-    size_t                                       buf_len
-);
-
-/* advertising_proxy_stop
- *
- * For testing, stop advertising service
- *
- * advertising_proxy_stop() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL).
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that the service advertising
- *                            was stopped successfully. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning).
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_stop
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_get_ula
- *
- * For testing, advertise it's own prefix to thread network
- *
- * advertising_proxy_get_ula() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *                            The response object in the callback is a pointer to a uint64_t containing the
- *                            prefix in host byte order.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that the prefix advertising
- *                            was successful. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_get_ula
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_disable_srp_replication
- *
- * For testing, disable SRP replication.
- *
- * advertising_proxy_disable_srp_replication() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication was disabled
- *                            successfully. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_disable_srp_replication
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_undrop_srpl_advertisement
- *
- * For testing, undrop_srpl_advertisement
- *
- * advertising_proxy_undrop_srpl_advertisement() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication advertisements
- *                            were successfully resumed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_undrop_srpl_advertisement
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_undrop_srpl_connection
- *
- * For testing, restart all dropped srpl connections
- *
- * advertising_proxy_undrop_srpl_connection() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication connections
- *                            were successfully resumed. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_undrop_srpl_connection
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_drop_srpl_advertisement
- *
- * For testing, drop all srpl advertisements
- *
- * advertising_proxy_drop_srpl_advertisement() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication advertisements
- *                            were successfully discontinued. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_drop_srpl_advertisement
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_drop_srpl_connection
- *
- * For testing, drop all srpl connections
- *
- * advertising_proxy_drop_srpl_connection() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication connections
- *                            were successfully dropped. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_drop_srpl_connection
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_start_dropping_push_connections
- *
- * For testing, start dropping DNS Push connections every 90 seconds.
- *
- * advertising_proxy_start_dropping_push_connections() Parameters:
- *
- * conn_ref:                  A pointer to advertising_proxy_conn_ref that is initialized to NULL.
- *                            If the call succeeds it will be initialized to a non-NULL value.
- *                            The same conn_ref can be used for more than one call.
- *
- * clientq:                   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:                  Callback function for the client that indicates success or failure.
- *                            Callback is not called until either the command has failed, or has completed.
- *
- * return value:              Returns kDNSSDAdvertisingProxy_NoError when no error otherwise returns an
- *                            error code indicating the error that occurred. Note: A return value of
- *                            kDNSSDAdvertisingProxy_NoError does not mean that srp replication connections
- *                            were successfully dropped. The callback may asynchronously return an
- *                            error (such as kDNSSDAdvertisingProxy_DaemonNotRunning)
- *
- */
-
-DNS_SERVICES_EXPORT
-advertising_proxy_error_type advertising_proxy_start_dropping_push_connections
-(
-    advertising_proxy_conn_ref NONNULL *NULLABLE conn_ref,
-    run_context_t                        NONNULL clientq,
-    advertising_proxy_reply             NULLABLE callback
-);
-
-/* advertising_proxy_ref_dealloc()
- *
- * Terminate a connection with the daemon and free memory associated with the advertising_proxy_conn_ref.
- * When used on a advertising_proxy_conn_ref returned by advertising_proxy_enable, terminates the advertising
- * proxy.  When used on a call that subscribes to notifications about objects managed by the advertising proxy,
- * discontinues those notifications.
- *
- * conn_ref:        A advertising_proxy_conn_ref initialized by any of the advertising_proxy_*() calls.
- *
- */
-DNS_SERVICES_EXPORT
-void advertising_proxy_ref_dealloc(advertising_proxy_conn_ref NONNULL conn_ref);
-#endif /* DNSSD_PROXY_SERVICES_H */
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/config-parse.c b/ServiceRegistration/config-parse.c
deleted file mode 100644
index 4864159..0000000
--- a/ServiceRegistration/config-parse.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108 -*-
- *
- * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2018 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.
- *
- */
-
-//*************************************************************************************************************
-//
-// General purpose stupid little parser, currently used by dnssd-proxy for its configuration file
-//
-//*************************************************************************************************************
-// Headers
-
-#include <stdio.h>          // For printf()
-#include <stdlib.h>         // For malloc()
-#include <string.h>         // For strrchr(), strcmp()
-#include <time.h>           // For "struct tm" etc.
-#include <signal.h>         // For SIGINT, SIGTERM
-#include <assert.h>
-#include <netdb.h>           // For gethostbyname()
-#include <sys/socket.h>      // For AF_INET, AF_INET6, etc.
-#include <net/if.h>          // For IF_NAMESIZE
-#include <netinet/in.h>      // For INADDR_NONE
-#include <netinet/tcp.h>     // For SOL_TCP, TCP_NOTSENT_LOWAT
-#include <arpa/inet.h>       // For inet_addr()
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-
-#include "srp.h"
-#include "config-parse.h"
-
-#ifdef STANDALONE
-#undef LogMsg
-#define LogMsg(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
-#endif // STANDALONE
-
-// Parse one line of a config file.
-// A line consists of a verb followed by one or more hunks of text.
-// We parse the verb first, then that tells us how many hunks of text to expect.
-// Each hunk is space-delineated; the last hunk can contain spaces.
-static bool config_parse_line(void *context, const char *filename, char *line, int lineno,
-							  config_file_verb_t *verbs, int num_verbs)
-{
-	char *sp;
-#define MAXCFHUNKS 10
-	char *hunks[MAXCFHUNKS];
-	int num_hunks = 0;
-	config_file_verb_t *config_file_verb = NULL;
-	int i;
-
-	sp = line;
-	do {
-		// Skip leading spaces.
-		while (*sp && (*sp == ' ' || *sp == '\t'))
-			sp++;
-		if (num_hunks == 0) {
-			// If this is a blank line with spaces on it or a comment line, we ignore it.
-			if (!*sp || *sp == '#')
-				return true;
-		}
-		hunks[num_hunks++] = sp;
-		// Find EOL or hunk
-		while (*sp && (*sp != ' ' && *sp != '\t')) {
-			sp++;
-		}
-		if (*sp) {
-			*sp++ = 0;
-		}
-		if (num_hunks == 1) {
-			for (i = 0; i < num_verbs; i++) {
-				// If the verb name matches, or the verb name is NULL (meaning whatever doesn't
-				// match a preceding verb), we've found our verb.
-				if (verbs[i].name == NULL || !strcmp(verbs[i].name, hunks[0])) {
-					config_file_verb = &verbs[i];
-					break;
-				}
-			}
-			if (config_file_verb == NULL) {
-				INFO("unknown verb %s at line %d", hunks[0], lineno);
-				return false;
-			}
-		}				
-	} while (*sp && num_hunks < MAXCFHUNKS && config_file_verb->max_hunks > num_hunks);
-	
-	// If we didn't get the hunks we needed, bail.
-	if (config_file_verb->min_hunks > num_hunks) {
-		INFO("error: verb %s requires between %d and %d modifiers; %d given at line %d",
-			 hunks[0], config_file_verb->min_hunks, config_file_verb->max_hunks, num_hunks, lineno);
-		return false;
-	}
-
-	return config_file_verb->handler(context, filename, hunks, num_hunks, lineno);
-}
-
-// Parse a configuration file
-bool config_parse(void *context, const char *filename, config_file_verb_t *verbs, int num_verbs)
-{
-	int file;
-	char *buf, *line, *eof, *eol, *nextCR, *nextNL;
-	off_t flen, have;
-    ssize_t len;
-    int lineno;
-	bool success = true;
-
-	file = open(filename, O_RDONLY);
-	if (file < 0) {
-		INFO("fatal: %s: %s", filename, strerror(errno));
-		return false;
-	}
-
-	// Get the length of the file.
-	flen = lseek(file, 0, SEEK_END);
-	lseek(file, 0, SEEK_SET);
-	buf = malloc(flen + 1);
-	if (buf == NULL) {
-		INFO("fatal: not enough memory for %s", filename);
-		goto outclose;
-	}
-	
-	// Just in case we have a read() syscall that doesn't always read the whole file at once
-	have = 0;
-	while (have < flen) {
-		len = read(file, &buf[have], flen - have);
-		if (len < 0) {
-			INFO("fatal: read of %s at %lld len %lld: %s",
-				 filename, (long long)have, (long long)(flen - have), strerror(errno));
-			goto outfree;
-		}
-		if (len == 0) {
-			INFO("fatal: read of %s at %lld len %lld: zero bytes read",
-				 filename, (long long)have, (long long)(flen - have));
-		outfree:
-			free(buf);
-		outclose:
-			close(file);
-			return false;
-		}
-		have += len;
-	}
-	close(file);
-	buf[flen] = 0; // NUL terminate.
-	eof = buf + flen;
-	
-	// Parse through the file line by line.
-	line = buf;
-	lineno = 1;
-	while (line < eof) { // < because NUL at eof could be last eol.
-		nextCR = strchr(line, '\r');
-		nextNL = strchr(line, '\n');
-
-		// Added complexity for CR/LF agnostic line endings.   Necessary?
-		if (nextNL != NULL) {
-			if (nextCR != NULL && nextCR < nextNL)
-				eol = nextCR;
-			else
-				eol = nextNL;
-		} else {
-			if (nextCR != NULL)
-				eol = nextCR;
-			else
-				eol = buf + flen;
-		}
-
-		// If this isn't a blank line or a comment line, parse it.
-		if (eol - line != 1 && line[0] != '#') {
-			*eol = 0;
-			// If we get a bad config line, we're going to return failure later, but continue parsing now.
-			if (!config_parse_line(context, filename, line, lineno, verbs, num_verbs))
-				success = false;
-        }
-        line = eol + 1;
-        lineno++;
-	}		
-	free(buf);
-	return success;
-}
-
diff --git a/ServiceRegistration/config-parse.h b/ServiceRegistration/config-parse.h
deleted file mode 100644
index 69161df..0000000
--- a/ServiceRegistration/config-parse.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108 -*-
- *
- * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2018 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.
- *
- */
-
-#ifndef __CONFIG_PARSE_H
-#define __CONFIG_PARSE_H
-
-// Structure of a configuration file verb
-typedef struct {
-	char *name;
-	int min_hunks, max_hunks;
-	bool (*handler)(void *context, const char *config_file_name, char **hunks, int num_hunks, int lineno);
-} config_file_verb_t;
-
-// Provided by RelayParse.c
-bool config_parse(void *context, const char *config_file_name, config_file_verb_t *verbs, int num_verbs);
-
-#endif // __CONFIG_PARSE_H
diff --git a/ServiceRegistration/cti-common.h b/ServiceRegistration/cti-common.h
deleted file mode 100644
index 1d007ba..0000000
--- a/ServiceRegistration/cti-common.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* cti-common.h
- *
- * Copyright (c) 2020 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface for Thread Border router control.
- */
-
-#ifndef __CTI_COMMON_H__
-#define __CTI_COMMON_H__
-
-#if OPENTHREAD_PLATFORM_POSIX
-#define NO_IOLOOP 1
-#endif
-
-typedef struct _cti_connection_t *cti_connection_t;
-
-#ifndef GCCATTR
-#ifdef __clang__
-#define GCCATTR(x)
-#else
-#define GCCATTR(x) __attribute__(x)
-#endif
-#endif
-
-#ifndef NONNULL
-#ifdef __clang__
-#define NONNULL _Nonnull
-#else
-#define NONNULL
-#endif
-#endif
-
-#ifndef NULLABLE
-#ifdef __clang__
-#define NULLABLE _Nullable
-#else
-#define NULLABLE
-#endif
-#endif
-
-#ifndef UNUSED
-#ifdef __clang__
-#define UNUSED __unused
-#else
-#define UNUSED  __attribute__((unused))
-#endif
-#endif
-
-#ifndef ND6_INFINITE_LIFETIME
-#define ND6_INFINITE_LIFETIME 0xffffffff
-#endif
-
-#define kCTIMessageType_Response                0
-#define kCTIMessageType_AddService              1
-#define kCTIMessageType_RemoveService           2
-#define kCTIMessageType_AddPrefix               3
-#define kCTIMessageType_RemovePrefix            4
-#define kCTIMessageType_GetTunnelName           5
-#define kCTIMessageType_TunnelNameResponse      6
-#define kCTIMessageType_RequestStateEvents      7
-#define kCTIMessageType_StateEvent              8
-#define kCTIMessageType_RequestUInt64PropEvents 9
-#define kCTIMessageType_UInt64PropEvent        10
-#define kCTIMessageType_RequestRoleEvents      11
-#define kCTIMessageType_RoleEvent              12
-#define kCTIMessageType_RequestServiceEvents   13
-#define kCTIMessageType_ServiceEvent           14
-#define kCTIMessageType_RequestPrefixEvents    15
-#define kCTIMessageType_PrefixEvent            16
-
-#if defined(POSIX_BUILD) || OPENTHREAD_PLATFORM_POSIX
-#define kCTIPropertyPartitionID                 1
-#define kCTIPropertyExtendedPANID               2
-#else
-#define kCTIPropertyPartitionID                 "Network:PartitionID"
-#define kCTIPropertyExtendedPANID               "Network:XPANID"
-#endif // POSIX_BUILD
-
-typedef enum
-{
-    kCTIStatus_NoError                   =  0,
-    kCTIStatus_UnknownError              = -65537,
-    kCTIStatus_NoMemory                  = -65539,   // No Memory
-    kCTIStatus_BadParam                  = -65540,   // Client passed invalid arg
-    kCTIStatus_Invalid                   = -65549,   // Invalid CTI message
-    kCTIStatus_DaemonNotRunning          = -65563,   // Daemon not running: unable to connect
-    kCTIStatus_Disconnected              = -65569,   // Server disconnected after successful connection
-    kCTIStatus_NotPermitted              = -65571    // Unable to open the daemon socket, or connection not permitted.
-} cti_status_t;
-
-// Enum values for kWPANTUNDStateXXX (see wpan-properties.h)
-typedef enum {
-    kCTI_NCPState_Uninitialized,
-    kCTI_NCPState_Fault,
-    kCTI_NCPState_Upgrading,
-    kCTI_NCPState_DeepSleep,
-    kCTI_NCPState_Offline,
-    kCTI_NCPState_Commissioned,
-    kCTI_NCPState_Associating,
-    kCTI_NCPState_CredentialsNeeded,
-    kCTI_NCPState_Associated,
-    kCTI_NCPState_Isolated,
-    kCTI_NCPState_NetWake_Asleep,
-    kCTI_NCPState_NetWake_Waking,
-    kCTI_NCPState_Unknown
-} cti_network_state_t;
-
-typedef enum {
-    kCTI_NetworkNodeType_Unknown,
-    kCTI_NetworkNodeType_Router,
-    kCTI_NetworkNodeType_EndDevice,
-    kCTI_NetworkNodeType_SleepyEndDevice,
-    kCTI_NetworkNodeType_NestLurker,
-    kCTI_NetworkNodeType_Commissioner,
-    kCTI_NetworkNodeType_Leader,
-} cti_network_node_type_t;
-
-#define kCTIRoleDisabled 0
-#define kCTIRoleDetached 1
-#define kCTIRoleChild    2
-#define kCTIRoleRouter   3
-#define kCTIRoleLeader   4
-
-// CTI flags.
-#define kCTIFlag_Stable                1
-#define kCTIFlag_NCP                   2
-
-#endif // _CTI_COMMON_H__
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-openthread.c b/ServiceRegistration/cti-openthread.c
deleted file mode 100644
index 8436043..0000000
--- a/ServiceRegistration/cti-openthread.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/* cti-openthread.c
- *
- * Copyright (c) 2020 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface implementation
- */
-
-#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <syslog.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include "cti-proto.h"
-#include "cti-server.h"
-#include "cti-openthread.h"
-
-#include <syslog.h>
-#include <openthread/config.h>
-#include <openthread/server.h>
-#include <openthread/border_router.h>
-#include <openthread/instance.h>
-#include <openthread/thread.h>
-#include <openthread/platform/misc.h>
-#include <openthread/openthread-system.h>
-
-static otInstance* cti_instance = NULL;
-void handleThreadStateChanged(uint32_t flags, void UNUSED *context);
-
-#define SuccessOrFailure(eval)                      \
-    do                                              \
-    {                                               \
-        if (!(eval))                                \
-        {                                           \
-            return kCTIStatus_UnknownError;         \
-        }                                           \
-    } while (false)
-
-// OT accessorys and mutators
-//    Implementions of the getters and setters called by cti-server
-int ctiAddService( uint32_t enterprise_number,
-                   const uint8_t* service_data,
-                   size_t service_data_length,
-                   const uint8_t* server_data,
-                   size_t server_data_length) {
-
-    otError error = OT_ERROR_NONE;
-    otServiceConfig serviceCfg;
-
-    if ( !cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-
-    if (service_data_length > sizeof(serviceCfg.mServiceData) ||
-        server_data_length > sizeof(serviceCfg.mServerConfig.mServerData)) {
-        return kCTIStatus_BadParam;
-    }
-
-    serviceCfg.mEnterpriseNumber = enterprise_number;
-    memcpy(serviceCfg.mServiceData, service_data, service_data_length);
-    serviceCfg.mServiceDataLength = service_data_length;
-    memcpy(serviceCfg.mServerConfig.mServerData, server_data, server_data_length);
-    serviceCfg.mServerConfig.mServerDataLength = server_data_length;
-    serviceCfg.mServerConfig.mStable = true;
-
-    error = otServerAddService(cti_instance, &serviceCfg);
-
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to add service: %d", error);
-        return kCTIStatus_UnknownError;
-    }
-    error = otBorderRouterRegister(cti_instance);
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to push service: %d", error);
-        return kCTIStatus_UnknownError;
-    }
-
-    return kCTIStatus_NoError;
-}
-
-int ctiRemoveService( uint32_t enterprise_number,
-                      const uint8_t *service_data,
-                      size_t service_data_length) {
-
-    if ( !cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-
-    otError error = otServerRemoveService(cti_instance,
-                                          enterprise_number,
-                                          service_data,
-                                          service_data_length);
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to remove service %d", enterprise_number);
-        return kCTIStatus_UnknownError;
-    }
-    error = otBorderRouterRegister(cti_instance);
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to push service: %d", error);
-        return kCTIStatus_UnknownError;
-    }
-    return kCTIStatus_NoError;
-}
-
-int ctiRetrieveServiceList(cti_connection_t connection, int UNUSED event)
-{
-    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-    otServiceConfig config;
-    if ( !cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-
-    uint16_t numServices = 0;
-    uint16_t totalSize = 0;
-    // Walk through the list and calculate the number and size of services
-    while (otNetDataGetNextService(cti_instance, &iterator, &config) == OT_ERROR_NONE) {
-        numServices++;
-
-        // We will send the data back in this order:
-        totalSize += sizeof(config.mEnterpriseNumber);   // Enterprise Num
-        totalSize += sizeof(config.mServiceDataLength);  // Size of the service data
-        totalSize += config.mServiceDataLength;         // The actual service data bytes
-        totalSize += sizeof(config.mServerConfig.mServerDataLength);  // Size of the server data
-        totalSize += config.mServerConfig.mServerDataLength;         // The actual server data bytes
-    }
-
-    totalSize += sizeof(numServices);
-
-    // Message:
-    // Num Services in List
-    //    For each Service:
-    //      Enterprise number
-    //      Service Data Length
-    //      Service Data
-    //      Server Data Length
-    //      Server Data
-    SuccessOrFailure( cti_connection_message_create(connection, kCTIMessageType_ServiceEvent, totalSize) );
-
-    // Indicate the number of services in the vector
-    SuccessOrFailure(cti_connection_u8_put(connection, numServices));
-
-    iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-
-    int i = 0;
-    while ((otNetDataGetNextService(cti_instance, &iterator, &config) == OT_ERROR_NONE) && i < numServices) {
-        SuccessOrFailure(cti_connection_u32_put(connection, config.mEnterpriseNumber));
-        SuccessOrFailure(cti_connection_data_put(connection, config.mServiceData, config.mServiceDataLength));
-        SuccessOrFailure(cti_connection_data_put(connection,
-                                                 config.mServerConfig.mServerData,
-                                                 config.mServerConfig.mServerDataLength));
-    }
-
-    SuccessOrFailure( cti_connection_message_send(connection) );
-
-    return kCTIStatus_NoError;
-}
-
-int ctiAddMeshPrefix(struct in6_addr *prefix, size_t prefix_length, bool on_mesh, bool preferred, bool slaac, bool stable)
-{
-    otError error = OT_ERROR_NONE;
-    if ( !cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-    otBorderRouterConfig borderRouterConfig;
-    memset(&borderRouterConfig, 0, sizeof(borderRouterConfig));
-
-    if ( prefix_length > 64) {
-        return kCTIStatus_BadParam;
-    }
-    memcpy(borderRouterConfig.mPrefix.mPrefix.mFields.m8, prefix, sizeof(*prefix));
-
-    borderRouterConfig.mPrefix.mLength = prefix_length;
-    borderRouterConfig.mStable = stable;
-    borderRouterConfig.mPreference = OT_ROUTE_PREFERENCE_MED; // Can also be high or low.
-    borderRouterConfig.mPreferred = preferred;
-    borderRouterConfig.mSlaac = slaac;
-    borderRouterConfig.mOnMesh = on_mesh;
-    borderRouterConfig.mStable = stable;
-    borderRouterConfig.mConfigure = false;
-    borderRouterConfig.mDefaultRoute = true;
-    borderRouterConfig.mDhcp = false;
-
-    error = otBorderRouterAddOnMeshPrefix(cti_instance, &borderRouterConfig);
-    if (error != OT_ERROR_NONE) {
-        return kCTIStatus_UnknownError;
-    }
-    error = otBorderRouterRegister(cti_instance);
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to push service: %d", error);
-        return kCTIStatus_UnknownError;
-    }
-
-    return kCTIStatus_NoError;
-}
-
-int ctiRemoveMeshPrefix(struct in6_addr *prefix, size_t prefix_length) {
-
-    if (!cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-
-    otIp6Prefix ip6Prefix;
-    memset(&ip6Prefix, 0, sizeof(ip6Prefix));
-
-    if (prefix_length > 64) {
-        return kCTIStatus_BadParam;
-    }
-    memcpy(ip6Prefix.mPrefix.mFields.m8, prefix, sizeof(*prefix));
-    ip6Prefix.mLength = prefix_length;
-    otError error = otBorderRouterRemoveOnMeshPrefix(cti_instance, &ip6Prefix);
-    if (error != OT_ERROR_NONE && error != OT_ERROR_NOT_FOUND) {
-        return kCTIStatus_UnknownError;
-    }
-    error = otBorderRouterRegister(cti_instance);
-    if (error != OT_ERROR_NONE) {
-        syslog(LOG_INFO, "Failed to push service: %d", error);
-        return kCTIStatus_UnknownError;
-    }
-    return kCTIStatus_NoError;
-}
-
-int ctiRetrievePrefixList(cti_connection_t connection, int UNUSED event)
-{
-    if (!cti_instance) {
-        return kCTIStatus_UnknownError;
-    }
-    otBorderRouterConfig config;
-    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-
-    uint16_t numPrefixes = 0;
-    int totalSize = 0;
-    do {
-        int error = otNetDataGetNextOnMeshPrefix(cti_instance, &iterator, &config);
-        if (error != OT_ERROR_NONE) {
-            if (error != OT_ERROR_NOT_FOUND) {
-                syslog(LOG_ERR, "ctiRetrievePrefixList: otBorderRouterGetNextRoute: %d", error);
-                return kCTIStatus_UnknownError;
-            }
-            break;
-        }
-        numPrefixes++;
-        totalSize += 1;  // 1 byte stability / source flag.
-        totalSize += sizeof (config.mPrefix.mLength);
-        totalSize +=  config.mPrefix.mLength; // size of the prefix
-    } while (1);
-
-    // Message:
-    // Num prefixes in List
-    //    For each prefix:
-    //      flags
-    //      prefix length
-    //      prefix
-    SuccessOrFailure( cti_connection_message_create(connection, kCTIMessageType_PrefixEvent, totalSize) );
-
-    // Indicate the number of services in the vector
-    SuccessOrFailure(cti_connection_u16_put(connection, numPrefixes));
-
-    iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-
-    int i = 0;
-    while (i < numPrefixes)
-    {
-        int error = otNetDataGetNextOnMeshPrefix(cti_instance, &iterator, &config);
-        if (error != OT_ERROR_NONE) {
-            if (error != OT_ERROR_NOT_FOUND) {
-                syslog(LOG_ERR, "ctiRetrievePrefixList: otBorderRouterGetNextRoute: %d", error);
-            }
-            break;
-        }
-        // DJC Note:  Shouldn't be possible for the items in the Thread Network data to have changed
-        // between above count and now, but I'm paranoid and assumptions rot over time.
-        uint16_t flags = 0;
-        flags |= config.mDefaultRoute ? 0 : kCTIFlag_NCP;
-        flags |= config.mStable ? kCTIFlag_Stable : 0;
-
-        SuccessOrFailure(cti_connection_u16_put(connection, flags));
-        SuccessOrFailure(cti_connection_u8_put(connection, config.mPrefix.mLength));
-        SuccessOrFailure(cti_connection_data_put(connection, config.mPrefix.mPrefix.mFields.m8, 8));
-    }
-
-    SuccessOrFailure( cti_connection_message_send(connection) );
-    return kCTIStatus_NoError;
-}
-
-int ctiRetrievePartitionId(cti_connection_t connection, int UNUSED event)
-{
-    uint32_t partitionId = otThreadGetPartitionId(cti_instance);
-    SuccessOrFailure(cti_connection_message_create(connection, kCTIMessageType_UInt64PropEvent,
-                                                   sizeof(partitionId) + sizeof(uint32_t)));
-    SuccessOrFailure(cti_connection_u32_put(connection, kCTIPropertyPartitionID));
-    SuccessOrFailure(cti_connection_u64_put(connection, partitionId));
-    SuccessOrFailure(cti_connection_message_send(connection));
-    return kCTIStatus_NoError;
-}
-
-int ctiRetrieveXPANID(cti_connection_t connection, int UNUSED event)
-{
-    const otExtendedPanId *panid_buf = otThreadGetExtendedPanId(cti_instance);
-    uint64_t xpanid = 0;
-    for (int i = 7; i >= 0; i--) {
-        xpanid = (xpanid << 8) | panid_buf->m8[i];
-    }
-    SuccessOrFailure(cti_connection_message_create(connection, kCTIMessageType_UInt64PropEvent,
-                                                   sizeof(xpanid) + sizeof(uint32_t)));
-    SuccessOrFailure(cti_connection_u32_put(connection, kCTIPropertyExtendedPANID));
-    SuccessOrFailure(cti_connection_u64_put(connection, xpanid));
-    SuccessOrFailure(cti_connection_message_send(connection));
-    return kCTIStatus_NoError;
-}
-
-int ctiRetrieveTunnel(cti_connection_t connection) {
-    const char *interfaceName = "wpan0";
-    uint32_t interfaceIndex = 0;
-#if defined(OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE) && OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
-    otError error = otPlatGetNetif(cti_instance, &interfaceName, &interfaceIndex);
-    if (error != OT_ERROR_NONE) {
-        return kCTIStatus_UnknownError;
-    }
-#endif
-    (void)interfaceIndex;
-    SuccessOrFailure(cti_connection_message_create(connection,
-                                                   kCTIMessageType_TunnelNameResponse,
-                                                   2 + strlen(interfaceName)));
-    SuccessOrFailure(cti_connection_string_put(connection, interfaceName));
-    SuccessOrFailure(cti_connection_message_send(connection));
-    return kCTIStatus_NoError;
-}
-
-/*  This will return one of the following:
- *      OT_DEVICE_ROLE_DISABLED = 0, ///< The Thread stack is disabled.
- *      OT_DEVICE_ROLE_DETACHED = 1, ///< Not currently participating in a Thread network/partition.
- *      OT_DEVICE_ROLE_CHILD    = 2, ///< The Thread Child role.
- *      OT_DEVICE_ROLE_ROUTER   = 3, ///< The Thread Router role.
- *      OT_DEVICE_ROLE_LEADER   = 4, ///< The Thread Leader role.
- * Note:  Disabled = "OFF", Detached = "Associating", Others = "Associated"
- */
-int
-ctiRetrieveNodeType(cti_connection_t connection, int event)
-{
-    otDeviceRole role = otThreadGetDeviceRole(cti_instance);
-    uint8_t datum;
-    int event_type;
-
-    if (event == CTI_EVENT_ROLE) {
-        event_type = kCTIMessageType_RoleEvent;
-        switch(role) {
-        default:
-        case OT_DEVICE_ROLE_DISABLED:
-        case OT_DEVICE_ROLE_DETACHED:
-            datum = kCTI_NetworkNodeType_Unknown;
-            break;
-        case OT_DEVICE_ROLE_CHILD:
-            datum = kCTI_NetworkNodeType_EndDevice;
-            break;
-        case OT_DEVICE_ROLE_ROUTER:
-            datum = kCTI_NetworkNodeType_Router;
-            break;
-        case OT_DEVICE_ROLE_LEADER:
-            datum = kCTI_NetworkNodeType_Leader;
-            break;
-        }
-    } else {
-        event_type = kCTIMessageType_StateEvent;
-        switch(role) {
-        default:
-        case OT_DEVICE_ROLE_DISABLED:
-            datum = kCTI_NCPState_Offline;
-            break;
-        case OT_DEVICE_ROLE_DETACHED:
-            datum = kCTI_NCPState_Associating;
-            break;
-        case OT_DEVICE_ROLE_CHILD:
-        case OT_DEVICE_ROLE_ROUTER:
-        case OT_DEVICE_ROLE_LEADER:
-            datum = kCTI_NCPState_Associated;
-            break;
-        }
-    }
-    if (cti_connection_message_create(connection, event_type, 1) &&
-        cti_connection_u8_put(connection, datum) &&
-        cti_connection_message_send(connection)) {
-    }
-    return 0;
-}
-
-void
-handleThreadStateChanged(uint32_t flags, void UNUSED *context)
-{
-    syslog(LOG_INFO, "handleThreadStateChanged: flags = %" PRIx32, flags);
-
-    if ( !cti_instance) {
-        return;
-    }
-
-    syslog(LOG_INFO, "Thread state changed, flag: %d", flags );
-    if ( flags & OT_CHANGED_THREAD_ROLE)
-    {
-        syslog(LOG_INFO, "    Thread Role changed.  Notify registered clients" );
-        cti_notify_event(CTI_EVENT_ROLE, ctiRetrieveNodeType);
-        cti_notify_event(CTI_EVENT_STATE, ctiRetrieveNodeType);
-    }
-    if ( flags & OT_CHANGED_THREAD_NETDATA)
-    {
-        syslog(LOG_INFO, "    Thread Netdata changed.  Notify registered clients" );
-        cti_notify_event(CTI_EVENT_SERVICE, ctiRetrieveServiceList);
-        cti_notify_event(CTI_EVENT_PREFIX, ctiRetrievePrefixList);
-
-    }
-    if ( flags & OT_CHANGED_THREAD_PARTITION_ID)
-    {
-        syslog(LOG_INFO, "    Thread Partition ID changed.  Notify registered clients" );
-        cti_notify_event(CTI_EVENT_PARTITION_ID, ctiRetrievePartitionId);
-    }
-    if ( flags & OT_CHANGED_THREAD_EXT_PANID)
-    {
-        syslog(LOG_INFO, "    Thread Partition ID changed.  Notify registered clients" );
-        cti_notify_event(CTI_EVENT_XPANID, ctiRetrievePartitionId);
-    }
-
-}
-
-// Functions to be called by ot-daemon's main:
-// Called from main after InitInstance()
-void otCtiServerInit(otInstance*  aInstance) {
-    cti_instance = aInstance;
-    otError error = otSetStateChangedCallback(cti_instance, handleThreadStateChanged, NULL);
-    if(error != OT_ERROR_NONE && error != OT_ERROR_ALREADY) {
-        syslog(LOG_INFO, "otCtiServerInit: otSetStateChangedCallback: Unable to register: %d", error);
-    }
-
-    cti_init();
-}
-
-// Called in main's idle loop after FD Prep.
-void otCtiServerUpdate(otInstance* aInstance, otSysMainloopContext *aMainloop) {
-    int nfds = 0;
-    cti_instance = aInstance;
-    // Note:  This will not compile as it requires a change to cti_fd_init's arg list since
-    // ot-daemon's make does not allow unused arguments.
-    cti_fd_init(&nfds, &aMainloop->mReadFdSet);
-    if (aMainloop->mMaxFd < nfds) {
-        aMainloop->mMaxFd = nfds;
-    }
-}
-
-// Called in main loop after a successful otSysMainloopPoll
-void otCtiServerProcess(otInstance* aInstance, otSysMainloopContext *aMainloop) {
-    cti_instance = aInstance;
-    // Note: this will not compile as it is as it removes unused args in cti_fd_process
-    cti_fd_process(&aMainloop->mReadFdSet);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-openthread.h b/ServiceRegistration/cti-openthread.h
deleted file mode 100644
index 053dcbf..0000000
--- a/ServiceRegistration/cti-openthread.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* cti-openthread.h
- *
- * Copyright (c) 2020 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.
- *
- * External function signatures for CTI entry points used by OpenThread main loop.
- */
-
-#ifndef __CTI_SERVER_H__
-#define __CTI_SERVER_H__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "cti-server.h"
-#include "cti-common.h"
-#include <openthread/instance.h>
-#include <openthread/openthread-system.h>
-
-
-void otCtiServerInit(otInstance *NONNULL aInstance);
-void otCtiServerUpdate(otInstance *NONNULL aInstance, otSysMainloopContext *NONNULL aMainloop);
-void otCtiServerProcess(otInstance* aInstance, otSysMainloopContext *aMainloop);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __CTI_SERVER_H__
diff --git a/ServiceRegistration/cti-proto.c b/ServiceRegistration/cti-proto.c
deleted file mode 100644
index 5051d40..0000000
--- a/ServiceRegistration/cti-proto.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/* cti-proto.c
- *
- * Copyright (c) 2020 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.
- *
- * CTI protocol communication primitives
- */
-
-#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <stdint.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/signal.h>
-
-#ifdef OPENTHREAD_PLATFORM_POSIX
-#include "cti-server.h"
-#include "cti-proto.h"
-#else
-#include "cti-proto.h"
-#include "cti-common.h"
-#endif
-
-
-void
-cti_connection_finalize(cti_connection_t connection)
-{
-	if (connection->input.buffer) {
-		free(connection->input.buffer);
-	}
-	if (connection->output.buffer) {
-		free(connection->output.buffer);
-	}
-	free(connection);
-}
-
-void
-dump_to_hex(uint8_t *data, size_t length, char *buffer, int len)
-{
-	char *s = buffer;
-	unsigned int i;
-	for (i = 0; i < length; i++) {
-		size_t avail = len - (s - buffer);
-		if (i == 0) {
-			snprintf(s, avail, "%02x", data[i]);
-		} else {
-			snprintf(s, avail, ":%02x", data[i]);
-		}
-		s += strlen(s);
-	}
-}
-
-bool
-cti_make_space(cti_buffer_t *buf, size_t space)
-{
-	if (buf->buffer == NULL) {
-		buf->current = 0;
-		buf->size = space;
-		buf->buffer = malloc(space);
-		if (buf->buffer == NULL) {
-			syslog(LOG_ERR, "cti_make_space: no memory for %zd bytes.", space);
-			return false;
-		}
-	}
-	if (buf->current + space > buf->size) {
-		size_t next_increment = buf->size * 2;
-		if (next_increment + space > buf->size) {
-			next_increment += space;
-		}
-		void *new_buf = malloc(next_increment);
-		if (new_buf == NULL) {
-			syslog(LOG_ERR, "cti_make_space: no memory for %zd bytes.", next_increment);
-			return false;
-		}
-		memcpy(new_buf, buf->buffer, buf->current);
-		free(buf->buffer);
-		buf->buffer = new_buf;
-        buf->size = next_increment;
-	}
-	return true;
-}
-
-static bool
-cti_put(cti_connection_t connection, const void *data, size_t length)
-{
-	if (!cti_make_space(&connection->output, length)) {
-		cti_connection_close(connection);
-		return false;
-	}
-
-	memcpy(connection->output.buffer + connection->output.current, data, length);
-	connection->output.current += length;
-	return true;
-}
-
-bool
-cti_connection_u64_put(cti_connection_t connection, uint64_t val)
-{
-	uint32_t rvals[2];
-    rvals[0] = htonl((val >> 32));
-    rvals[1] = htonl((val & 0xffffffffL));
-	return cti_put(connection, &rvals, sizeof(rvals));
-}
-
-bool
-cti_connection_u32_put(cti_connection_t connection, uint32_t val)
-{
-	uint32_t rval = htonl(val);
-	return cti_put(connection, &rval, sizeof(rval));
-}
-
-bool
-cti_connection_i32_put(cti_connection_t connection, int32_t val)
-{
-	uint32_t uval = htonl((uint32_t)val);
-	return cti_connection_u32_put(connection, uval);
-}
-
-bool
-cti_connection_u16_put(cti_connection_t connection, uint16_t val)
-{
-	uint16_t rval = htons(val);
-	return cti_put(connection, &rval, sizeof(rval));
-}
-
-bool
-cti_connection_u8_put(cti_connection_t connection, uint8_t val)
-{
-	uint8_t rval = val;
-	return cti_put(connection, &rval, sizeof(rval));
-}
-
-bool
-cti_connection_bool_put(cti_connection_t connection, bool val)
-{
-	uint8_t rval = val ? 1 : 0;
-	return cti_put(connection, &rval, sizeof(rval));
-}
-
-bool
-cti_connection_data_put(cti_connection_t connection, const void *data, uint16_t length)
-{
-	return (cti_connection_u16_put(connection, length) && cti_put(connection, data, length));
-}
-
-bool
-cti_connection_string_put(cti_connection_t connection, const char *string)
-{
-	uint16_t len;
-    if (string == NULL) {
-        return cti_connection_u16_put(connection, 0xffff);
-    }
-    len = strlen(string);
-    return (cti_connection_u16_put(connection, len) && cti_put(connection, string, len));
-}
-
-bool
-cti_parse(cti_connection_t connection, void *buffer, uint16_t length)
-{
-	if (length > connection->message_length - connection->input.current) {
-		syslog(LOG_ERR, "cti_parse: bogus data element length %d exceeds available space %zd",
-			   length, connection->message_length - connection->input.current);
-		cti_connection_close(connection);
-		return false;
-	}
-
-	memcpy(buffer, connection->input.buffer + connection->input.current, length);
-	connection->input.current += length;
-	return true;
-}
-
-bool
-cti_connection_u64_parse(cti_connection_t connection, uint64_t *val)
-{
-	uint32_t rvals[2];
-	if (!cti_parse(connection, &rvals, sizeof(rvals))) {
-		return false;
-	}
-	*val = ((uint64_t)(ntohl(rvals[0])) << 32) | ntohl(rvals[1]);
-	return true;
-}
-
-bool
-cti_connection_u32_parse(cti_connection_t connection, uint32_t *val)
-{
-	uint32_t rval;
-	if (!cti_parse(connection, &rval, sizeof(rval))) {
-		return false;
-	}
-	*val = ntohl(rval);
-	return true;
-}
-
-bool
-cti_connection_i32_parse(cti_connection_t connection, int32_t *val)
-{
-	uint32_t uval;
-	if (!cti_parse(connection, &uval, sizeof(uval))) {
-		return false;
-	}
-	*val = (int32_t)ntohl(uval);
-	return true;
-}
-
-bool
-cti_connection_u16_parse(cti_connection_t connection, uint16_t *val)
-{
-	uint16_t rval;
-	if (!cti_parse(connection, &rval, sizeof(rval))) {
-		return false;
-	}
-	*val = ntohs(rval);
-	return true;
-}
-
-bool
-cti_connection_u8_parse(cti_connection_t connection, uint8_t *val)
-{
-    uint8_t rval;
-	if (cti_parse(connection, &rval, sizeof(rval))) {
-        *val = rval;
-        return true;
-    }
-    return false;
-}
-
-bool
-cti_connection_bool_parse(cti_connection_t connection, bool *val)
-{
-	uint8_t rval;
-	if (!cti_parse(connection, &rval, sizeof(rval))) {
-		return false;
-	}
-	*val = rval == 0 ? false : true;
-	return true;
-}
-
-bool
-cti_connection_data_parse(cti_connection_t connection, void **data, uint16_t *length)
-{
-	uint16_t len;
-	void *ret;
-	if (!cti_connection_u16_parse(connection, &len)) {
-		return false;
-	}
-	if (len > connection->message_length - connection->input.current) {
-		syslog(LOG_ERR, "cti_connection_data_parse: bogus data element length %d exceeds available space %zd",
-			   len, connection->message_length - connection->input.current);
-		cti_connection_close(connection);
-		return false;
-	}
-	ret = malloc(len);
-	if (ret == NULL) {
-		syslog(LOG_ERR, "cti_connection_data_parse: out of memory for %d byte data element", len);
-		cti_connection_close(connection);
-		return false;
-	}
-	if (!cti_parse(connection, ret, len)) {
-		free(ret);
-		return false;
-	}
-    *length = len;
-	*data = ret;
-	return true;
-}
-
-bool
-cti_connection_string_parse(cti_connection_t connection, char **string)
-{
-	uint16_t len;
-	char *ret;
-	if (!cti_connection_u16_parse(connection, &len)) {
-		return false;
-	}
-    if (len == 0xffff) {
-        *string = NULL;
-        return true;
-    }
-	if (len > connection->message_length - connection->input.current) {
-		syslog(LOG_ERR, "cti_connection_string_parse: bogus data element length %d exceeds available space %zd",
-			   len, connection->message_length - connection->input.current);
-		cti_connection_close(connection);
-		return false;
-	}
-	ret = malloc(len + 1);
-	if (ret == NULL) {
-		syslog(LOG_ERR, "cti_connection_string_parse: out of memory for %d byte string", len);
-		cti_connection_close(connection);
-		return false;
-	}
-	if (!cti_parse(connection, ret, len)) {
-		free(ret);
-		return false;
-	}
-    ret[len] = 0;
-	*string = ret;
-	return true;
-}
-
-void
-cti_connection_parse_start(cti_connection_t connection)
-{
-	connection->input.current = 0;
-}
-
-bool
-cti_connection_parse_done(cti_connection_t connection)
-{
-	if (connection->input.current != connection->message_length) {
-		syslog(LOG_ERR, "cti_connection_parse_done: %zd bytes of junk at end of message",
-			   connection->message_length - connection->input.current);
-		return false;
-	}
-	return true;
-}
-
-bool
-cti_connection_message_create(cti_connection_t connection, int message_type, uint16_t space)
-{
-	connection->output.current = 0;
-	if (connection->output.buffer != NULL) {
-		if (connection->output.size < space) {
-			free(connection->output.buffer);
-			connection->output.buffer = NULL;
-		}
-	}
-    // +4 for the length and the message type, which the caller isn't expected to track.
-	if (!cti_make_space(&connection->output, space + 4)) {
-		cti_connection_close(connection);
-		return false;
-	}
-	// Space for length, which is stored last.
-	connection->output.current = 2;
-	return cti_connection_u16_put(connection, message_type);
-}
-
-bool
-cti_connection_message_send(cti_connection_t connection)
-{
-	size_t offset = connection->output.current;
-    uint16_t len;
-	ssize_t result;
-	connection->output.current = 0;
-	if (offset > UINT16_MAX) {
-		syslog(LOG_ERR, "cti_connection_send: too big (%zd)", offset);
-	out:
-		cti_connection_close(connection);
-		return false;
-	}
-    len = (uint16_t)offset - 2;
-	if (!cti_connection_u16_put(connection, len)) {
-		return false;
-	}
-	result = write(connection->fd, connection->output.buffer, offset);
-	if (result < 0) {
-		syslog(LOG_ERR, "cti_connection_send: write: %s", strerror(errno));
-		goto out;
-	}
-	if ((size_t)result != offset) {
-		syslog(LOG_ERR, "cti_connection_send: short write: %zd instead of %zd", result, offset);
-		goto out;
-	}
-	return true;
-}
-
-bool
-cti_send_response(cti_connection_t connection, int status)
-{
-	if (cti_connection_message_create(connection, kCTIMessageType_Response, 10) &&
-		cti_connection_u16_put(connection, connection->message_type) &&
-		cti_connection_u32_put(connection, status))
-	{
-		return cti_connection_message_send(connection);
-	}
-	return false;
-}
-
-void
-cti_read(cti_connection_t connection, cti_datagram_callback_t datagram_callback)
-{
-	size_t needed = connection->input.expected - connection->input.current;
-	if (needed > 0) {
-		if (!cti_make_space(&connection->input, needed)) {
-			cti_connection_close(connection);
-			return;
-		}
-		ssize_t result = read(connection->fd, connection->input.buffer + connection->input.current, needed);
-		if (result < 0) {
-			syslog(LOG_INFO, "cti_read_callback: read: %s", strerror(errno));
-			cti_connection_close(connection);
-			return;
-		}
-        if (result == 0) {
-            syslog(LOG_INFO, "cti_read_callback: remote close");
-            cti_connection_close(connection);
-            return;
-        }
-		connection->input.current += result;
-		if ((size_t)result < needed) {
-			return;
-		}
-	}
-	// We have finished reading the length of the next message.
-	if (connection->message_length == 0) {
-		if (connection->input.expected != 2) {
-			syslog(LOG_ERR, "cti_read_callback: invalid expected length: %zd", connection->input.expected);
-			cti_connection_close(connection);
-			return;
-		}
-		connection->message_length = ((size_t)connection->input.buffer[0] << 8) + connection->input.buffer[1];
-		connection->input.current = 0;
-		connection->input.expected = connection->message_length;
-		return;
-	}
-	// We have finished reading a message.
-	datagram_callback(connection);
-
-	// Read the next one.
-	connection->input.expected = 2;
-	connection->message_length = 0;
-	connection->input.current = 0;
-}
-
-cti_connection_t
-cti_connection_allocate(uint16_t expected_size)
-{
-	cti_connection_t connection = calloc(1, sizeof(*connection));
-	if (connection == NULL) {
-		syslog(LOG_ERR, "cti_accept: no memory for connection structure.");
-		return NULL;
-	}
-	if (!cti_make_space(&connection->input, expected_size)) {
-		cti_connection_finalize(connection);
-		return NULL;
-	}
-	connection->input.expected = 2;
-	return connection;
-}
-
-int
-cti_make_unix_socket(const char *sockname, size_t name_size, bool is_listener)
-{
-    struct sockaddr_un addr;
-    int fd;
-
-    if (is_listener && (unlink(sockname) < 0 && errno != ENOENT)) {
-        syslog(LOG_ERR, "cti_make_unix_socket: unlink(%s: %s", sockname, strerror(errno));
-        return -1;
-    }
-
-    addr.sun_family = AF_LOCAL;
-    if (name_size > sizeof(addr.sun_path)) {
-        syslog(LOG_ERR, "cti_make_unix_socket: no space for unix socket named %s.", sockname);
-        return -1;
-    }
-    strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
-#ifndef NOT_HAVE_SA_LEN
-    addr.sun_len = strlen(addr.sun_path) + 1 + sizeof(addr.sun_len) + sizeof(addr.sun_family);
-#endif
-
-    fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (fd < 0) {
-        syslog(LOG_ERR, "cti_make_unix_socket: socket: %s", strerror(errno));
-        return -1;
-    }
-
-    if (is_listener) {
-        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-            syslog(LOG_ERR, "cti_make_unix_socket: %s", strerror(errno));
-            goto out;
-        }
-
-        if (listen(fd, 1) < 0) {
-            syslog(LOG_ERR, "cti_make_unix_socket: listen: %s", strerror(errno));
-            goto out;
-        }
-    } else {
-        if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-            syslog(LOG_ERR, "cti_make_unix_socket: connect: %s", strerror(errno));
-            goto out;
-        }
-
-#ifdef SO_NOSIGPIPE
-        int one = 1;
-        if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof one) < 0) {
-            syslog(LOG_ERR, "cti_make_unix_socket: SO_NOSIGPIPE failed: %s", strerror(errno));
-            goto out;
-        }
-#endif
-        if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-            syslog(LOG_ERR, "cti_make_unix_socket: can't set O_NONBLOCK: %s", strerror(errno));
-        out:
-            close(fd);
-            return -1;
-        }
-    }
-    return fd;
-}
-
-int
-cti_accept(int listen_fd, uid_t *p_uid, gid_t *p_gid, pid_t *p_pid)
-{
-    struct sockaddr_un addr;
-    socklen_t socksize = sizeof(addr);
-    int fd = accept(listen_fd, (struct sockaddr *)&addr, &socksize);
-
-    if (fd < 0) {
-        syslog(LOG_ERR, "cti_accept: accept: %s", strerror(errno));
-        return -1;
-    }
-
-#if defined(LINUX) || OPENTHREAD_PLATFORM_POSIX
-    struct ucred ucred;
-    socklen_t len = sizeof(struct ucred);
-    if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
-        syslog(LOG_ERR, "cti_accept: unable to get peer credentials for incoming connection: %s", strerror(errno));
-        goto out;
-    }
-
-    if (ucred.uid != 0) {
-        char **s;
-        struct group *group = getgrnam("cti-clients");
-        if (group == NULL) {
-            syslog(LOG_ERR, "cti_accept: connecting user %d is not root and there is no cti-clients group.", ucred.uid);
-            goto out;
-        } else if (group->gr_gid == ucred.gid) {
-        } else {
-            struct passwd *passwd = getpwuid(ucred.uid);
-            if (passwd == NULL || passwd->pw_name == NULL) {
-                syslog(LOG_ERR, "cti_accept: connecting user %d is not root and has no username.", ucred.uid);
-                goto out;
-            } else if (group->gr_mem == NULL || *group->gr_mem == NULL) {
-                syslog(LOG_ERR, "cti_accept: connecting user %s is not a member of cti-clients group.", passwd->pw_name);
-                goto out;
-            } else {
-                for (s = group->gr_mem; s != NULL && *s != NULL; s++) {
-                    if (!strcmp(*s, passwd->pw_name)) {
-                        break;
-                    }
-                }
-                if (*s == NULL) {
-                    syslog(LOG_ERR, "cti_accept: connecting user %s is not a member of cti-clients group.", passwd->pw_name);
-                    goto out;
-                }
-            }
-        }
-    }
-#else
-    syslog(LOG_ERR, "cti_accept: no way to validate user credentials.");
-#endif
-
-#ifdef SO_NOSIGPIPE
-    int one = 1;
-    if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof one) < 0) {
-        syslog(LOG_ERR, "SO_NOSIGPIPE failed: %s", strerror(errno));
-    }
-#endif
-    if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-        syslog(LOG_ERR, "cti_accept: can't set O_NONBLOCK: %s", strerror(errno));
-        goto out;
-    }
-
-#if defined(LINUX) || OPENTHREAD_PLATFORM_POSIX
-    if (p_uid != NULL) {
-        *p_uid = ucred.uid;
-    }
-    if (p_gid != NULL) {
-        *p_gid = ucred.gid;
-    }
-    if (p_pid != NULL) {
-        *p_pid = ucred.pid;
-    }
-    syslog(LOG_INFO, "cti_accept: connection from user %d accepted", ucred.uid);
-#else
-    syslog(LOG_INFO, "cti_accept: connection from unknown user accepted");
-#endif
-    goto done;
-
-out:
-    close(fd);
-    fd = -1;
-done:
-    return fd;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-proto.h b/ServiceRegistration/cti-proto.h
deleted file mode 100644
index e9038bf..0000000
--- a/ServiceRegistration/cti-proto.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* cti-proto.h
- *
- * Copyright (c) 2020 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.
- *
- * CTI protocol definitions
- */
-
-#ifndef __CTI_PROTO_H__
-#define __CTI_PROTO_H__
-#define CTI_SERVER_SOCKET_NAME "/var/run/cti-server-socket"
-
-#include <stdbool.h>
-#include "cti-common.h"
-
-typedef struct cti_buffer cti_buffer_t;
-struct cti_buffer {
-	size_t expected;
-	size_t current;
-	size_t size;
-	uint8_t *NULLABLE buffer;
-};
-
-#ifndef NO_IOLOOP
-#ifndef __CTI_SERVICES_H__
-typedef union {
-	void (*NONNULL callback)(void);
-	void (*NONNULL reply)(cti_connection_t NONNULL connection, void *NULLABLE result, int status);
-} cti_callback_t;
-#endif
-typedef void (*cti_internal_callback_t)(cti_connection_t NONNULL conn_ref, void *NULLABLE object, cti_status_t status);
-#endif
-
-struct _cti_connection_t {
-#ifdef NO_IOLOOP
-	cti_connection_t NULLABLE next;
-    uint16_t registered_event_flags;
-#else
-	void *NULLABLE io_context;
-	void *NULLABLE context;
-	int ref_count;
-	cti_callback_t callback;
-	cti_internal_callback_t NULLABLE internal_callback;
-	uid_t uid;
-	gid_t gid;
-	pid_t pid;
-#endif
-	int fd;
-	cti_buffer_t input, output;
-	size_t message_length;
-	uint16_t message_type;
-	bool message_valid;
-};
-
-typedef void (*cti_datagram_callback_t)(cti_connection_t NONNULL connection);
-void cti_connection_finalize(cti_connection_t NONNULL connection);
-void cti_connection_close(cti_connection_t NONNULL connection);
-#define cti_connection_release(connection) cti_connection_release_(connection, __FILE__, __LINE__)
-void cti_connection_release_(cti_connection_t NONNULL connection, const char *NONNULL file, int line);
-void dump_to_hex(uint8_t *NONNULL data, size_t length, char *NONNULL buffer, int len);
-bool cti_make_space(cti_buffer_t *NONNULL buf, size_t space);
-bool cti_connection_begin(cti_connection_t NONNULL connection, size_t space);
-bool cti_connection_u64_put(cti_connection_t NONNULL connection, uint64_t val);
-bool cti_connection_i32_put(cti_connection_t NONNULL connection, int32_t val);
-bool cti_connection_u32_put(cti_connection_t NONNULL connection, uint32_t val);
-bool cti_connection_u16_put(cti_connection_t NONNULL connection, uint16_t val);
-bool cti_connection_u8_put(cti_connection_t NONNULL connection, uint8_t val);
-bool cti_connection_bool_put(cti_connection_t NONNULL connection, bool val);
-bool cti_connection_u64_parse(cti_connection_t NONNULL connection, uint64_t *NONNULL val);
-bool cti_connection_i32_parse(cti_connection_t NONNULL connection, int32_t *NONNULL val);
-bool cti_connection_u32_parse(cti_connection_t NONNULL connection, uint32_t *NONNULL val);
-bool cti_connection_u16_parse(cti_connection_t NONNULL connection, uint16_t *NONNULL val);
-bool cti_connection_u8_parse(cti_connection_t NONNULL connection, uint8_t *NONNULL val);
-bool cti_connection_bool_parse(cti_connection_t NONNULL connection, bool *NONNULL val);
-bool cti_connection_data_put(cti_connection_t NONNULL connection, const void *NONNULL data, uint16_t length);
-bool cti_connection_string_put(cti_connection_t NONNULL connection, const char *NONNULL data);
-bool cti_connection_data_parse(cti_connection_t NONNULL connection,
-							   void *NONNULL *NULLABLE data, uint16_t *NONNULL length);
-bool cti_connection_string_parse(cti_connection_t NONNULL connection, char *NONNULL *NULLABLE string);
-void cti_connection_parse_start(cti_connection_t NONNULL connection);
-bool cti_connection_parse_done(cti_connection_t NONNULL connection);
-bool cti_connection_message_create(cti_connection_t NONNULL connection, int message_type, uint16_t space);
-bool cti_connection_message_send(cti_connection_t NONNULL connection);
-bool cti_send_response(cti_connection_t NONNULL connection, int status);
-void cti_read(cti_connection_t NONNULL connection, cti_datagram_callback_t NONNULL datagram_callback);
-cti_connection_t NULLABLE cti_connection_allocate(uint16_t expected_size);
-int cti_make_unix_socket(const char *NONNULL sockname, size_t name_size, bool is_listener);
-int cti_accept(int listen_fd, uid_t *NULLABLE p_uid, gid_t *NULLABLE p_gid, pid_t *NULLABLE p_pid);
-#endif // __CTI_PROTO_H__
diff --git a/ServiceRegistration/cti-server.c b/ServiceRegistration/cti-server.c
deleted file mode 100644
index 79612f3..0000000
--- a/ServiceRegistration/cti-server.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/* cti-server.c
- *
- * Copyright (c) 2020 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface Server
- */
-
-#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <syslog.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/signal.h>
-#include "cti-server.h"
-#include "cti-proto.h"
-
-#include <syslog.h>
-
-int cti_listener_fd;
-cti_connection_t connections;
-
-void
-cti_connection_close(cti_connection_t connection)
-{
-	if (connection->fd != -1) {
-		close(connection->fd);
-		connection->fd = -1;
-	}
-}
-
-static void
-cti_service_add_parse(cti_connection_t connection)
-{
-    uint32_t enterprise_id;
-    uint16_t service_data_length;
-    uint16_t server_data_length;
-    int status = kCTIStatus_NoError;
-    void *service_data;
-    void *server_data;
-    char service_data_buf[13], server_data_buf[55];
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u32_parse(connection, &enterprise_id) &&
-        cti_connection_data_parse(connection, &service_data, &service_data_length) &&
-        cti_connection_data_parse(connection, &server_data, &server_data_length) &&
-        cti_connection_parse_done(connection))
-    {
-        dump_to_hex(service_data, service_data_length, service_data_buf, sizeof(service_data_buf));
-        dump_to_hex(server_data, server_data_length, server_data_buf, sizeof(server_data_buf));
-        syslog(LOG_INFO, "cti_service_add_parse: %" PRIu32 " %" PRIu16 "[ %s ] %" PRIu16 "[ %s ]",
-               enterprise_id, service_data_length, service_data_buf, server_data_length, server_data_buf);
-
-#ifndef POSIX_BUILD
-        status = ctiAddService(enterprise_id,
-                               service_data,
-                               service_data_length,
-                               server_data,
-                               server_data_length);
-
-#else
-        status = kCTIStatus_NoError;
-#endif
-        cti_send_response(connection, status);
-    }
-}
-
-static void
-cti_service_remove_parse(cti_connection_t connection)
-{
-    uint32_t enterprise_id;
-    uint16_t service_data_length;
-    int status = kCTIStatus_NoError;
-    void *service_data;
-    char service_data_buf[13];
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u32_parse(connection, &enterprise_id) &&
-        cti_connection_data_parse(connection, &service_data, &service_data_length) &&
-        cti_connection_parse_done(connection))
-    {
-        dump_to_hex(service_data, service_data_length, service_data_buf, sizeof(service_data_buf));
-        syslog(LOG_INFO, "cti_service_add_parse: %" PRIu32 " %" PRIu16 "[ %s ]", enterprise_id, service_data_length, service_data_buf);
-
-#ifndef POSIX_BUILD
-        status = ctiRemoveService(enterprise_id,
-                                  service_data,
-                                  service_data_length);
-#else
-        status = kCTIStatus_NoError;
-#endif
-        cti_send_response(connection, status);
-    }
-}
-
-static void
-cti_prefix_add_parse(cti_connection_t connection)
-{
-    uint32_t preferred, valid;
-    uint8_t prefix_length;
-    struct in6_addr prefix;
-    void *prefix_data = NULL;
-    uint16_t prefix_data_length;
-    bool slaac, on_mesh, stable;
-    if (cti_connection_u32_parse(connection, &preferred) &&
-        cti_connection_u32_parse(connection, &valid) &&
-        cti_connection_data_parse(connection, &prefix_data, &prefix_data_length) &&
-        cti_connection_u8_parse(connection, &prefix_length) &&
-        cti_connection_bool_parse(connection, &slaac) &&
-        cti_connection_bool_parse(connection, &on_mesh) &&
-        cti_connection_bool_parse(connection, &stable) &&
-        cti_connection_parse_done(connection))
-    {
-        int status = kCTIStatus_NoError;
-        if (prefix_data_length != 8) {
-            status = kCTIStatus_Invalid;
-        } else {
-            memset(((char *)&prefix) + 8, 0, sizeof(prefix) - 8);
-            memcpy(&prefix, prefix_data, prefix_data_length);
-#ifndef POSIX_BUILD
-            status = ctiAddMeshPrefix(&prefix, prefix_length, on_mesh, true, slaac, stable);
-#endif
-        }
-        cti_send_response(connection, status);
-    }
-    if (prefix_data != NULL) {
-        free(prefix_data);
-    }
-}
-
-static void
-cti_prefix_remove_parse(cti_connection_t connection)
-{
-    uint8_t prefix_length;
-    struct in6_addr prefix;
-    void *prefix_data = NULL;
-    uint16_t prefix_data_length;
-    if (cti_connection_data_parse(connection, &prefix_data, &prefix_data_length) &&
-        cti_connection_u8_parse(connection, &prefix_length) &&
-        cti_connection_parse_done(connection))
-    {
-        int status = kCTIStatus_NoError;
-        if (prefix_data_length != 8) {
-            status = kCTIStatus_Invalid;
-        } else {
-            memset(((char *)&prefix) + 8, 0, sizeof(prefix) - 8);
-            memcpy(&prefix, prefix_data, prefix_data_length);
-#ifndef POSIX_BUILD
-            status = ctiRemoveMeshPrefix(&prefix, prefix_length);
-#endif
-            cti_send_response(connection, status);
-        }
-    }
-    if (prefix_data != NULL) {
-        free(prefix_data);
-    }
-}
-
-static void
-cti_get_tunnel_name_parse(cti_connection_t connection)
-{
-    if (cti_connection_parse_done(connection)) {
-#ifndef POSIX_BUILD
-        ctiRetrieveTunnel(connection);
-#endif
-    }
-}
-
-static void
-cti_message_parse(cti_connection_t connection)
-{
-    uint32_t propertyName;
-
-    cti_connection_parse_start(connection);
-    if (!cti_connection_u16_parse(connection, &connection->message_type)) {
-        return;
-    }
-    switch(connection->message_type) {
-    case kCTIMessageType_AddService:
-        cti_service_add_parse(connection);
-        break;
-    case kCTIMessageType_RemoveService:
-        cti_service_remove_parse(connection);
-        break;
-    case kCTIMessageType_AddPrefix:
-        cti_prefix_add_parse(connection);
-        break;
-    case kCTIMessageType_RemovePrefix:
-        cti_prefix_remove_parse(connection);
-        break;
-    case kCTIMessageType_GetTunnelName:
-        cti_get_tunnel_name_parse(connection);
-        break;
-    case kCTIMessageType_RequestStateEvents:
-        if (cti_connection_parse_done(connection)) {
-            connection->registered_event_flags |= CTI_EVENT_STATE;
-            cti_send_response(connection, kCTIStatus_NoError);
-#ifndef POSIX_BUILD
-            ctiRetrieveNodeType(connection, CTI_EVENT_STATE);
-
-#endif
-        }
-        break;
-    case kCTIMessageType_RequestUInt64PropEvents:
-        if (cti_connection_u32_parse(connection, &propertyName) && cti_connection_parse_done(connection)) {
-            cti_send_response(connection, kCTIStatus_NoError);
-#ifndef POSIX_BUILD
-            switch(propertyName) {
-            case kCTIPropertyPartitionID:
-                connection->registered_event_flags |= CTI_EVENT_PARTITION_ID;
-                ctiRetrievePartitionId(connection, CTI_EVENT_PARTITION_ID);
-                break;
-            case kCTIPropertyExtendedPANID:
-                connection->registered_event_flags |= CTI_EVENT_XPANID;
-                ctiRetrieveXPANID(connection, CTI_EVENT_XPANID);
-                break;
-            default:
-                cti_connection_close(connection);
-                break;
-            }
-#endif
-        }
-        break;
-    case kCTIMessageType_RequestRoleEvents:
-        if (cti_connection_parse_done(connection)) {
-            connection->registered_event_flags |= CTI_EVENT_ROLE;
-            cti_send_response(connection, kCTIStatus_NoError);
-#ifndef POSIX_BUILD
-            ctiRetrieveNodeType(connection, CTI_EVENT_ROLE);
-#endif
-        }
-        break;
-    case kCTIMessageType_RequestServiceEvents:
-        if (cti_connection_parse_done(connection)) {
-            connection->registered_event_flags |= CTI_EVENT_SERVICE;
-            cti_send_response(connection, kCTIStatus_NoError);
-#ifndef POSIX_BUILD
-            ctiRetrieveServiceList(connection, CTI_EVENT_SERVICE);
-#endif
-        }
-        break;
-    case kCTIMessageType_RequestPrefixEvents:
-        if (cti_connection_parse_done(connection)) {
-            connection->registered_event_flags |= CTI_EVENT_PREFIX;
-            cti_send_response(connection, kCTIStatus_NoError);
-#ifndef POSIX_BUILD
-            ctiRetrievePrefixList(connection, CTI_EVENT_PREFIX);
-#endif
-        }
-        break;
-    default:
-        cti_send_response(connection, kCTIStatus_Invalid);
-
-    }
-}
-
-static void
-cti_listen_callback(void)
-
-{
-    cti_connection_t connection;
-    int fd;
-    uid_t uid;
-    pid_t pid;
-
-    fd = cti_accept(cti_listener_fd, &uid, NULL, &pid);
-
-    // User is authenticated.
-    connection = cti_connection_allocate(100);
-    if (connection == NULL) {
-        close(fd);
-        return;
-    }
-    connection->fd = fd;
-    connection->next = connections;
-    connections = connection;
-    syslog(LOG_INFO, "cti_accept: connection from user %d, pid %d accepted", uid, pid);
-}
-
-int
-cti_init(void)
-{
-    cti_listener_fd = cti_make_unix_socket(CTI_SERVER_SOCKET_NAME, sizeof(CTI_SERVER_SOCKET_NAME), true);
-    if (cti_listener_fd == -1) {
-        return -1;
-    }
-    return 0;
-}
-
-void
-cti_fd_init(int *p_nfds, fd_set *r)
-{
-    int nfds = *p_nfds;
-    cti_connection_t connection, *p_connection;
-
-    if (cti_listener_fd >= nfds) {
-        nfds = cti_listener_fd + 1;
-    }
-    FD_SET(cti_listener_fd, r);
-
-    // GC any closed connections.
-    for (p_connection = &connections; *p_connection; ) {
-        connection = *p_connection;
-        if (connection->fd == -1) {
-            *p_connection = connection->next;
-            cti_connection_finalize(connection);
-        } else {
-            p_connection = &connection->next;
-        }
-    }
-
-    // Now process input on any connections that are still around.
-    for (connection = connections; connection; connection = connection->next) {
-        if (connection->fd >= nfds) {
-            nfds = connection->fd + 1;
-        }
-        FD_SET(connection->fd, r);
-    }
-    *p_nfds = nfds;
-}
-
-void
-cti_fd_process(fd_set *r)
-{
-    cti_connection_t connection;
-
-    if (FD_ISSET(cti_listener_fd, r)) {
-        cti_listen_callback();
-    }
-
-    for (connection = connections; connection; connection = connection->next) {
-        if (connection->fd != -1 && FD_ISSET(connection->fd, r)) {
-            cti_read(connection, cti_message_parse);
-        }
-    }
-}
-
-void
-cti_notify_event(unsigned int evt, send_event_t evt_handler)
-{
-    // Walk through connections and see if have registered for this particular event.
-    cti_connection_t connection = connections;
-    while (connection) {
-        if (evt & connection->registered_event_flags) {
-            evt_handler(connection, evt);
-        }
-        connection = connection->next;
-    }
-}
-
-#ifdef POSIX_BUILD
-int
-main(int argc, char **argv)
-{
-    fd_set fd_r, fd_w, fd_x;
-    int nfds = 0;
-
-    openlog("cti-server", LOG_PERROR, LOG_DAEMON);
-    signal(SIGPIPE, SIG_IGN); // because why ever?
-    cti_init();
-
-    do {
-        FD_ZERO(&fd_r);
-        FD_ZERO(&fd_w);
-        FD_ZERO(&fd_x);
-
-        cti_fd_init(&nfds, &fd_r);
-        syslog(LOG_INFO, "selecting: %d descriptors.", nfds);
-        if (select(nfds, &fd_r, &fd_w, &fd_x, NULL) < 0) {
-            syslog(LOG_ERR, "select: %s", strerror(errno));
-            exit(1);
-        }
-
-        cti_fd_process(&fd_r);
-    } while (1);
-}
-#endif
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-server.h b/ServiceRegistration/cti-server.h
deleted file mode 100644
index ec9b44b..0000000
--- a/ServiceRegistration/cti-server.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* cti-server.h
- *
- * Copyright (c) 2020 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.
- *
- * External function signatures for cti-server
- */
-
-#ifndef __CTI_SERVER_H__
-#define __CTI_SERVER_H__
-
-#include <stdbool.h>
-
-#define CTI_EVENT_SERVICE      (1 << 1)
-#define CTI_EVENT_PREFIX       (1 << 2)
-#define CTI_EVENT_ROLE         (1 << 3)
-#define CTI_EVENT_PARTITION_ID (1 << 4)
-#define CTI_EVENT_STATE        (1 << 5)
-#define CTI_EVENT_XPANID       (1 << 6)
-
-#ifndef NO_IOLOOP
-#define NO_IOLOOP 1
-#endif
-
-#ifndef NOT_HAVE_SA_LEN
-#define NOT_HAVE_SA_LEN 1
-#endif
-
-#include "cti-common.h"
-
-int cti_init(void);
-void cti_fd_init(int *NONNULL p_nfds, fd_set *NONNULL r) GCCATTR((nonnull (1,2)));
-void cti_fd_process(fd_set *NONNULL r) GCCATTR((nonnull (1)));
-
-typedef int (*send_event_t)(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-void cti_notify_event(unsigned int evt, send_event_t NONNULL evt_handler) GCCATTR((nonnull (2)));
-
-int ctiAddService(uint32_t enterprise_number, const uint8_t *NONNULL service_data,
-				  size_t service_data_length, const uint8_t *NONNULL server_data, size_t server_data_length)
-    GCCATTR((nonnull (2, 4)));
-int ctiRemoveService(uint32_t enterprise_number,
-					 const uint8_t *service_data, size_t service_data_length) GCCATTR((nonnull (2)));
-int ctiRetrieveServiceList(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-int ctiAddMeshPrefix(struct in6_addr *NONNULL prefix,
-					 size_t prefix_length, bool on_mesh, bool preferred, bool slaac, bool stable) GCCATTR((nonnull (1)));
-int ctiRemoveMeshPrefix(struct in6_addr *NONNULL prefix, size_t prefix_length) GCCATTR((nonnull (1)));
-int ctiRetrievePrefixList(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-int ctiRetrievePartitionId(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-int ctiRetrieveXPANID(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-int ctiRetrieveTunnel(cti_connection_t NONNULL connection) GCCATTR((nonnull (1)));
-int ctiRetrieveNodeType(cti_connection_t NONNULL connection, int event) GCCATTR((nonnull (1)));
-
-#endif // __CTI_SERVER_H__
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-services.c b/ServiceRegistration/cti-services.c
deleted file mode 100644
index 6c64a45..0000000
--- a/ServiceRegistration/cti-services.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/* cti-services.c
- *
- * Copyright (c) 2020-2021 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface for Thread Border router control.
- */
-
-
-#include <netinet/in.h>
-#include <string.h>
-#include <stdlib.h>
-
-
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "cti-services.h"
-
-static void cti_message_parse(cti_connection_t connection);
-
-
-//*************************************************************************************************************
-// Globals
-
-#include "cti-common.h"
-
-#include "cti-proto.h"
-
-
-// For configuration comments, we return success/failure.
-static void
-cti_internal_reply_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_reply_t callback;
-    INFO("conn_ref = %p", conn_ref);
-    callback = conn_ref->callback.reply;
-    if (callback != NULL) {
-        callback(conn_ref->context, status);
-        // We only ever call this callback once.
-        conn_ref->callback.reply = NULL;
-    }
-    cti_connection_close(conn_ref);
-}
-
-static void
-cti_fd_finalize(void *context)
-{
-    cti_connection_t connection = context;
-    connection->io_context = NULL;
-    if (connection->callback.reply != NULL && connection->internal_callback != NULL) {
-        connection->internal_callback(connection, NULL, kCTIStatus_Disconnected);
-    }
-    RELEASE_HERE(connection, cti_connection_finalize);
-}
-
-void
-cti_connection_close(cti_connection_t connection)
-{
-    // The reason we test for NULL here is to save some typing: when a connection is closed remotely, we have call the
-    // internal event handler for the event; this event handler closes the connection when we've just received a
-    // successful reply. However, when the remote end closes the connection without that reply having been processed, we
-    // get to the internal callback with connection->io_context set to NULL. Rather than checking in every event handler,
-    // it's easier to check here.
-    if (connection->io_context != NULL) {
-        ioloop_close(connection->io_context);
-        ioloop_file_descriptor_release(connection->io_context);
-        connection->io_context = NULL;
-    }
-}
-
-static void
-cti_response_parse(cti_connection_t connection)
-{
-    uint16_t responding_to;
-    int32_t status;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u16_parse(connection, &responding_to) &&
-        cti_connection_i32_parse(connection, &status) &&
-        cti_connection_parse_done(connection))
-    {
-        INFO("%d %d", responding_to, status);
-        connection->internal_callback(connection, NULL, status);
-    }
-}
-
-static void
-cti_tunnel_response_parse(cti_connection_t connection)
-{
-    char *tunnel_name = NULL;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_string_parse(connection, &tunnel_name) &&
-        cti_connection_parse_done(connection))
-    {
-        INFO("%s", tunnel_name);
-        connection->internal_callback(connection, tunnel_name, kCTIStatus_NoError);
-    }
-    if (tunnel_name != NULL) {
-        free(tunnel_name);
-    }
-}
-
-static void
-cti_connection_read_callback(io_t *UNUSED io, void *context)
-{
-    cti_connection_t connection = context;
-
-    cti_read(connection, cti_message_parse);
-}
-
-void
-cti_connection_release_(cti_connection_t connection, const char *file, int line)
-{
-    RELEASE(connection, cti_connection_finalize);
-}
-
-static int
-cti_connection_create(void *context, cti_callback_t callback,
-                      cti_internal_callback_t internal_callback, cti_connection_t *retcon)
-{
-    cti_connection_t connection = cti_connection_allocate(500);
-    if (connection == NULL) {
-        ERROR("cti_connection_create: no memory for connection.");
-        return kCTIStatus_NoMemory;
-    }
-    RETAIN_HERE(connection);
-
-    connection->fd = cti_make_unix_socket(CTI_SERVER_SOCKET_NAME, sizeof(CTI_SERVER_SOCKET_NAME), false);
-    if (connection->fd < 0) {
-        int ret = errno == ECONNREFUSED ? kCTIStatus_DaemonNotRunning : EPERM ? kCTIStatus_NotPermitted : kCTIStatus_UnknownError;
-        ERROR("cti_connection_create: socket: %s", strerror(errno));
-        cti_connection_release(connection);
-        return ret;
-    }
-
-    connection->io_context = ioloop_file_descriptor_create(connection->fd, connection, cti_fd_finalize);
-    if (connection->io_context == NULL) {
-        ERROR("cti_connection_create: can't create file descriptor object.");
-        close(connection->fd);
-        cti_connection_release(connection);
-        return kCTIStatus_NoMemory;
-    }
-    ioloop_add_reader(connection->io_context, cti_connection_read_callback);
-    connection->context = context;
-    connection->callback = callback;
-    connection->internal_callback = internal_callback;
-    *retcon = connection;
-    return kCTIStatus_NoError;
-}
-
-cti_status_t
-cti_add_service_(void *context, cti_reply_t callback, run_context_t client_queue,
-                 uint32_t enterprise_number, const uint8_t *NONNULL service_data, size_t service_data_length,
-                 const uint8_t *NONNULL server_data, size_t server_data_length, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_reply_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        conn_ref->callback.reply = callback;
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_AddService,
-                                          // sizeof(u32) + sizeof(length) + sizeof(length) = 8
-                                          8 + service_data_length + server_data_length) &&
-            cti_connection_u32_put(conn_ref, enterprise_number) &&
-            cti_connection_data_put(conn_ref, service_data, service_data_length) &&
-            cti_connection_data_put(conn_ref, server_data, server_data_length))
-        {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-cti_status_t
-cti_remove_service_(void *context, cti_reply_t callback, run_context_t client_queue,
-                    uint32_t enterprise_number, const uint8_t *NONNULL service_data, size_t service_data_length,
-                    const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_reply_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RemoveService,
-                                          // sizeof(u32) + sizeof(length) = 6
-                                          6 + service_data_length) &&
-            cti_connection_u32_put(conn_ref, enterprise_number) &&
-            cti_connection_data_put(conn_ref, service_data, service_data_length))
-        {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-
-cti_status_t
-cti_add_prefix_(void *context, cti_reply_t callback, run_context_t client_queue,
-                struct in6_addr *prefix, int prefix_length, bool on_mesh, bool preferred, bool slaac, bool stable,
-                const char *file, int line)
-{
-    cti_callback_t app_callback;
-    int ret;
-    cti_connection_t conn_ref;
-    app_callback.reply = callback;
-    ret = cti_connection_create(context, app_callback, cti_internal_reply_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_AddPrefix,
-                                          // sizeof(u32) * 2 + sizeof(prefix) (8) + sizeof(u8) + 3 * sizeof(bool) = 20
-                                          20) &&
-            cti_connection_u32_put(conn_ref, ND6_INFINITE_LIFETIME) &&
-            cti_connection_u32_put(conn_ref, ND6_INFINITE_LIFETIME) &&
-            cti_connection_data_put(conn_ref, prefix, 8) &&
-            cti_connection_u8_put(conn_ref, prefix_length) &&
-            cti_connection_bool_put(conn_ref, slaac) &&
-            cti_connection_bool_put(conn_ref, on_mesh) &&
-            cti_connection_bool_put(conn_ref, stable))
-        {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-cti_status_t
-cti_remove_prefix_(void *NULLABLE context, cti_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                   struct in6_addr *NONNULL prefix, int prefix_length, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    int ret;
-    cti_connection_t conn_ref;
-    app_callback.reply = callback;
-    ret = cti_connection_create(context, app_callback, cti_internal_reply_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RemovePrefix,
-                                          // sizeof(prefix) (8) + sizeof(u8) = 9
-                                          9) &&
-            cti_connection_data_put(conn_ref, prefix, 8) &&
-            cti_connection_u8_put(conn_ref, prefix_length))
-        {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-// For configuration comments, we return success/failure.
-static void
-cti_internal_tunnel_reply_callback(cti_connection_t conn_ref, void *tunnel_name, cti_status_t status)
-{
-    cti_tunnel_reply_t callback;
-    INFO("conn_ref = %p name = %s", conn_ref,
-         tunnel_name == NULL ? "<NULL>" : (char *)tunnel_name);
-    callback = conn_ref->callback.tunnel_reply;
-    if (callback != NULL) {
-        callback(conn_ref->context, tunnel_name, status);
-        conn_ref->callback.reply = NULL;
-    }
-    cti_connection_close(conn_ref);
-}
-
-cti_status_t
-cti_get_tunnel_name_(void *NULLABLE context, cti_tunnel_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                     const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.tunnel_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_tunnel_reply_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_GetTunnelName, 0))
-        {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-// For event comamnds, we return failure and close; on success, we just wait for events to flow and return those.
-static void
-cti_internal_state_event_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_state_reply_t callback;
-    INFO("conn_ref = %p", conn_ref);
-    if (status != kCTIStatus_NoError) {
-        callback = conn_ref->callback.state_reply;
-        if (callback != NULL) {
-            callback(conn_ref->context, 0, status);
-            // Only one error callback ever.
-            conn_ref->callback.reply = NULL;
-        }
-        cti_connection_close(conn_ref);
-    }
-}
-
-cti_status_t
-cti_get_state_(cti_connection_t *ref, void *NULLABLE context, cti_state_reply_t NONNULL callback,
-               run_context_t NULLABLE client_queue, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.state_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_state_event_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RequestStateEvents, 4)) {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-typedef uint32_t cti_property_name_t;
-
-// For event commands, we return failure and close; on success, we just wait for events to flow and return those.
-static void
-cti_internal_uint64_property_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_uint64_property_reply_t callback = conn_ref->callback.uint64_property_reply;
-    INFO("conn_ref = %p", conn_ref);
-    if (status != kCTIStatus_NoError) {
-        if (callback != NULL) {
-            callback(conn_ref->context, 0, status);
-            // Only one error callback ever.
-            conn_ref->callback.reply = NULL;
-        }
-        cti_connection_close(conn_ref);
-    }
-}
-
-static cti_status_t
-cti_get_uint64_property(cti_connection_t *ref, void *NULLABLE context, cti_uint64_property_reply_t NONNULL callback,
-                        run_context_t NULLABLE client_queue, cti_property_name_t property_name, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.uint64_property_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_uint64_property_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RequestUInt64PropEvents, 4)) {
-            if (!cti_connection_u32_put(conn_ref, property_name) || !cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-cti_status_t
-cti_get_partition_id_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context,
-                      cti_uint64_property_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                      const char *NONNULL file, int line)
-{
-    return cti_get_uint64_property(ref, context, callback, client_queue, kCTIPropertyPartitionID, file, line);
-}
-
-cti_status_t
-cti_get_extended_pan_id_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context,
-                         cti_uint64_property_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                         const char *NONNULL file, int line)
-{
-    return cti_get_uint64_property(ref, context, callback, client_queue, kCTIPropertyExtendedPANID, file, line);
-}
-
-// For event commands, we return failure and close; on success, we just wait for events to flow and return those.
-static void
-cti_internal_node_type_event_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_network_node_type_reply_t callback;
-    INFO("conn_ref = %p", conn_ref);
-    if (status != kCTIStatus_NoError) {
-        callback = conn_ref->callback.network_node_type_reply;
-        if (callback != NULL) {
-            callback(conn_ref->context, 0, status);
-            // Only one error callback ever.
-            conn_ref->callback.reply = NULL;
-        }
-        cti_connection_close(conn_ref);
-    }
-}
-
-cti_status_t
-cti_get_network_node_type_(cti_connection_t *ref, void *NULLABLE context, cti_network_node_type_reply_t NONNULL callback,
-                           run_context_t NULLABLE client_queue, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.network_node_type_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_node_type_event_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RequestRoleEvents, 4)) {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-static void
-cti_service_finalize(cti_service_t *service)
-{
-    if (service->server != NULL) {
-        free(service->server);
-    }
-    free(service);
-}
-
-static void
-cti_service_vec_finalize(cti_service_vec_t *services)
-{
-    size_t i;
-
-    if (services->services != NULL) {
-        for (i = 0; i < services->num; i++) {
-            if (services->services[i] != NULL) {
-                RELEASE_HERE(services->services[i], cti_service_finalize);
-            }
-        }
-        free(services->services);
-    }
-    free(services);
-}
-
-cti_service_vec_t *
-cti_service_vec_create_(size_t num_services, const char *file, int line)
-{
-    cti_service_vec_t *services = calloc(1, sizeof(*services));
-    if (services != NULL) {
-        if (num_services != 0) {
-            services->services = calloc(num_services, sizeof(cti_service_t *));
-            if (services->services == NULL) {
-                free(services);
-                return NULL;
-            }
-        }
-        services->num = num_services;
-        RETAIN(services);
-    }
-    return services;
-}
-
-void
-cti_service_vec_release_(cti_service_vec_t *services, const char *file, int line)
-{
-    RELEASE(services, cti_service_vec_finalize);
-}
-
-cti_service_t *
-cti_service_create_(uint64_t enterprise_number, uint16_t service_type, uint16_t service_version,
-                    uint8_t *server, size_t server_length, int flags, const char *file, int line)
-{
-    cti_service_t *service = calloc(1, sizeof(*service));
-    if (service != NULL) {
-        service->enterprise_number = enterprise_number;
-        service->service_type = service_type;
-        service->service_version = service_version;
-        service->server = server;
-        service->server_length = server_length;
-        service->flags = flags;
-        RETAIN(service);
-    }
-    return service;
-}
-
-void
-cti_service_release_(cti_service_t *service, const char *file, int line)
-{
-    RELEASE(service, cti_service_finalize);
-}
-
-// For event comamnds, we return failure and close; on success, we just wait for events to flow and return those.
-static void
-cti_internal_service_event_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_service_reply_t callback;
-    INFO("conn_ref = %p", conn_ref);
-    if (status != kCTIStatus_NoError) {
-        callback = conn_ref->callback.service_reply;
-        if (callback != NULL) {
-            callback(conn_ref->context, 0, status);
-            // Only one error callback ever.
-            conn_ref->callback.reply = NULL;
-        }
-        cti_connection_close(conn_ref);
-    }
-}
-
-cti_status_t
-cti_get_service_list_(cti_connection_t *ref, void *NULLABLE context, cti_service_reply_t NONNULL callback,
-                      run_context_t NULLABLE client_queue, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.service_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_service_event_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RequestServiceEvents, 4)) {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-static void
-cti_prefix_finalize(cti_prefix_t *prefix)
-{
-    free(prefix);
-}
-
-static void
-cti_prefix_vec_finalize(cti_prefix_vec_t *prefixes)
-{
-    size_t i;
-
-    if (prefixes->prefixes != NULL) {
-        for (i = 0; i < prefixes->num; i++) {
-            if (prefixes->prefixes[i] != NULL) {
-                RELEASE_HERE(prefixes->prefixes[i], cti_prefix_finalize);
-            }
-        }
-        free(prefixes->prefixes);
-    }
-    free(prefixes);
-}
-
-cti_prefix_vec_t *
-cti_prefix_vec_create_(size_t num_prefixes, const char *file, int line)
-{
-    cti_prefix_vec_t *prefixes = calloc(1, sizeof(*prefixes));
-    if (prefixes != NULL) {
-        if (num_prefixes != 0) {
-            prefixes->prefixes = calloc(num_prefixes, sizeof(cti_prefix_t *));
-            if (prefixes->prefixes == NULL) {
-                free(prefixes);
-                return NULL;
-            }
-        }
-        prefixes->num = num_prefixes;
-        RETAIN(prefixes);
-    }
-    return prefixes;
-}
-
-void
-cti_prefix_vec_release_(cti_prefix_vec_t *prefixes, const char *file, int line)
-{
-    RELEASE(prefixes, cti_prefix_vec_finalize);
-}
-
-cti_prefix_t *
-cti_prefix_create_(struct in6_addr *prefix, int prefix_length, int metric, int flags, const char *file, int line)
-{
-    cti_prefix_t *prefix_ret = calloc(1, sizeof(*prefix_ret));
-    if (prefix != NULL) {
-        prefix_ret->prefix = *prefix;
-        prefix_ret->prefix_length = prefix_length;
-        prefix_ret->metric = metric;
-        prefix_ret->flags = flags;
-        RETAIN(prefix_ret);
-    }
-    return prefix_ret;
-}
-
-void
-cti_prefix_release_(cti_prefix_t *prefix, const char *file, int line)
-{
-    RELEASE(prefix, cti_prefix_finalize);
-}
-
-// For event comamnds, we return failure and close; on success, we just wait for events to flow and return those.
-static void
-cti_internal_prefix_event_callback(cti_connection_t conn_ref, void *UNUSED object, cti_status_t status)
-{
-    cti_prefix_reply_t callback;
-    INFO("conn_ref = %p", conn_ref);
-    if (status != kCTIStatus_NoError) {
-        callback = conn_ref->callback.prefix_reply;
-        if (callback != NULL && conn_ref->context != NULL) {
-            callback(conn_ref->context, 0, status);
-            // Only one error callback ever.
-            conn_ref->callback.reply = NULL;
-        }
-        cti_connection_close(conn_ref);
-    }
-}
-
-cti_status_t
-cti_get_prefix_list_(cti_connection_t *ref, void *NULLABLE context, cti_prefix_reply_t NONNULL callback,
-                     run_context_t NULLABLE client_queue, const char *file, int line)
-{
-    cti_callback_t app_callback;
-    app_callback.prefix_reply = callback;
-    int ret;
-    cti_connection_t conn_ref;
-    ret = cti_connection_create(context, app_callback, cti_internal_prefix_event_callback, &conn_ref);
-    if (ret == kCTIStatus_NoError) {
-        if (cti_connection_message_create(conn_ref, kCTIMessageType_RequestPrefixEvents, 4)) {
-            if (!cti_connection_message_send(conn_ref)) {
-                ret = kCTIStatus_Disconnected;
-            }
-        } else {
-            ret = kCTIStatus_NoMemory;
-        }
-        if (ret != kCTIStatus_NoError) {
-            cti_connection_close(conn_ref);
-        }
-    }
-    return ret;
-}
-
-cti_status_t
-cti_events_discontinue(cti_connection_t connection)
-{
-    if (connection->io_context != NULL) {
-        cti_connection_close(connection);
-    }
-    cti_connection_release(connection);
-    return kCTIStatus_NoError;
-}
-static void
-cti_role_event_parse(cti_connection_t connection)
-{
-    uint8_t role;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u8_parse(connection, &role) &&
-        cti_connection_parse_done(connection))
-    {
-        INFO("%d", role);
-        connection->callback.network_node_type_reply(connection, role, kCTIStatus_NoError);
-    }
-}
-
-static void
-cti_state_event_parse(cti_connection_t connection)
-{
-    uint8_t state;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u8_parse(connection, &state) &&
-        cti_connection_parse_done(connection))
-    {
-        INFO("%d", state);
-        connection->callback.state_reply(connection, state, kCTIStatus_NoError);
-    }
-}
-
-static void
-cti_uint64_property_event_parse(cti_connection_t connection)
-{
-    uint64_t property_value;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u64_parse(connection, &property_value) &&
-        cti_connection_parse_done(connection))
-    {
-        INFO("%" PRIx64, property_value);
-        connection->callback.uint64_property_reply(connection, property_value, kCTIStatus_NoError);
-    }
-}
-
-static void
-cti_service_event_parse(cti_connection_t connection)
-{
-    uint8_t service_count, i;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u8_parse(connection, &service_count)) {
-        cti_service_vec_t *vec = cti_service_vec_create(service_count);
-        if (vec == NULL) {
-            ERROR("cti_service_event_parse: no memory for service vector.");
-            return;
-        }
-        vec->num = 0;
-        for (i = 0; i < service_count; i++) {
-            uint32_t enterprise_number;
-            void *service_data = NULL;
-            uint16_t service_data_length;
-            void *server_data = NULL;
-            uint16_t server_data_length;
-            if (!cti_connection_u32_parse(connection, &enterprise_number) ||
-                !cti_connection_data_parse(connection, &service_data, &service_data_length) ||
-                !cti_connection_data_parse(connection, &server_data, &server_data_length))
-            {
-                if (service_data != NULL) {
-                    free(service_data);
-                }
-                cti_service_vec_release(vec);
-                return;
-            }
-            char service_data_buf[13], server_data_buf[55];
-            cti_service_t *service = NULL;
-            dump_to_hex(service_data, service_data_length, service_data_buf, sizeof(service_data_buf));
-            dump_to_hex(server_data, server_data_length, server_data_buf, sizeof(server_data_buf));
-            INFO("%" PRIu32 " %" PRIu16 "[ %s ] %" PRIu16 "[ %s ]",
-                 enterprise_number, service_data_length, service_data_buf, server_data_length, server_data_buf);
-            if (enterprise_number == THREAD_ENTERPRISE_NUMBER) {
-                if (service_data_length == 1) {
-                    service = cti_service_create(enterprise_number,
-                                                 ((uint8_t *)service_data)[0], 1, server_data, server_data_length, 0);
-                }
-            }
-            if (service == NULL) {
-                free(service_data);
-                free(server_data);
-            } else {
-                vec->services[vec->num++] = service;
-            }
-        }
-
-        if (!cti_connection_parse_done(connection)) {
-            cti_service_vec_release(vec);
-            return;
-        }
-
-        INFO("%zd", vec->num);
-        connection->callback.service_reply(connection, vec, kCTIStatus_NoError);
-    }
-}
-
-static void
-cti_prefix_event_parse(cti_connection_t connection)
-{
-    uint16_t prefix_count, i;
-
-    // And statement will fail as soon as anything fails to parse.
-    if (cti_connection_u16_parse(connection, &prefix_count)) {
-        if (prefix_count > 200) {
-            ERROR("cti_prefix_event_parse: bogus number of prefixes returned: %d", prefix_count);
-            cti_connection_close(connection);
-            return;
-        }
-        cti_prefix_vec_t *vec = cti_prefix_vec_create(prefix_count);
-        if (vec == NULL) {
-            ERROR("cti_prefix_event_parse: no memory for prefix vector.");
-            return;
-        }
-        vec->num = 0;
-        for (i = 0; i < prefix_count; i++) {
-            uint16_t flags;
-            uint8_t prefix_length;
-            void *prefix_data = NULL;
-            uint16_t prefix_data_length;
-            struct in6_addr *prefix_addr;
-            if (!cti_connection_u16_parse(connection, &flags) ||
-                !cti_connection_u8_parse(connection, &prefix_length) ||
-                !cti_connection_data_parse(connection, &prefix_data, &prefix_data_length))
-            {
-                cti_prefix_vec_release(vec);
-                return;
-            }
-            if (prefix_data_length != 8) {
-                ERROR("cti_prefix_event_parse: wrong prefix length: %d", prefix_data_length);
-                cti_prefix_vec_release(vec);
-                return;
-            }
-            prefix_addr = calloc(1, sizeof(*prefix_addr));
-            if (prefix_addr == NULL) {
-                ERROR("cti_prefix_event_parse: no memory for prefix data.");
-                cti_prefix_vec_release(vec);
-                return;
-            }
-            memcpy(prefix_addr, prefix_data, prefix_data_length);
-            free(prefix_data);
-            cti_prefix_t *prefix = cti_prefix_create(prefix_addr, prefix_length, 0, flags);
-            if (prefix == NULL) {
-                ERROR("cti_prefix_event_parse: no memory for prefix object.");
-                cti_prefix_vec_release(vec);
-                return;
-            }
-            vec->prefixes[vec->num++] = prefix;
-        }
-
-        if (!cti_connection_parse_done(connection)) {
-            cti_prefix_vec_release(vec);
-            return;
-        }
-
-        INFO("%zd", vec->num);
-        connection->callback.prefix_reply(connection, vec, kCTIStatus_NoError);
-    }
-}
-
-static void
-cti_message_parse(cti_connection_t connection)
-{
-    cti_connection_parse_start(connection);
-    if (!cti_connection_u16_parse(connection, &connection->message_type)) {
-        return;
-    }
-    switch(connection->message_type) {
-    case kCTIMessageType_Response:
-        cti_response_parse(connection);
-        break;
-    case kCTIMessageType_TunnelNameResponse:
-        cti_tunnel_response_parse(connection);
-        break;
-    case kCTIMessageType_StateEvent:
-        cti_state_event_parse(connection);
-        break;
-    case kCTIMessageType_UInt64PropEvent:
-        cti_uint64_property_event_parse(connection);
-        break;
-    case kCTIMessageType_RoleEvent:
-        cti_role_event_parse(connection);
-        break;
-    case kCTIMessageType_ServiceEvent:
-        cti_service_event_parse(connection);
-        break;
-    case kCTIMessageType_PrefixEvent:
-        cti_prefix_event_parse(connection);
-        break;
-    }
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/cti-services.h b/ServiceRegistration/cti-services.h
deleted file mode 100644
index 145d786..0000000
--- a/ServiceRegistration/cti-services.h
+++ /dev/null
@@ -1,778 +0,0 @@
-/* cti-services.h
- *
- * Copyright (c) 2020 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Concise Thread Interface for Thread Border router control.
- */
-
-#ifndef __CTI_SERVICES_H__
-#define __CTI_SERVICES_H__
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-typedef void *run_context_t;
-#include "srp.h"
-
-#if (defined(__GNUC__) && (__GNUC__ >= 4))
-#define DNS_SERVICES_EXPORT __attribute__((visibility("default")))
-#else
-#define DNS_SERVICES_EXPORT
-#endif
-
-#include "cti-common.h"
-
-typedef struct _cti_service {
-    uint64_t enterprise_number;
-    uint16_t service_type;
-    uint16_t service_version;
-    uint8_t *NONNULL server;
-    size_t server_length;
-    int ref_count;
-    int flags;      // E.g., kCTIFlag_NCP
-} cti_service_t;
-
-typedef struct _cti_service_vec {
-    size_t num;
-    int ref_count;
-    cti_service_t *NULLABLE *NONNULL services;
-} cti_service_vec_t;
-
-typedef struct _cti_prefix {
-    struct in6_addr prefix;
-    int prefix_length;
-    int metric;
-    int flags;
-    int ref_count;
-} cti_prefix_t;
-
-typedef struct _cti_prefix_vec {
-    size_t num;
-    int ref_count;
-    cti_prefix_t *NULLABLE *NONNULL prefixes;
-} cti_prefix_vec_t;
-
-/* cti_reply:
- *
- * A general reply mechanism to indicate success or failure for a cti call that doesn't
- * return any data.
- *
- * cti_reply parameters:
- *
- * context:    The context that was passed to the cti service call to which this is a callback.
- *
- * status:	   Will be kCTIStatus_NoError on success, otherwise will indicate the
- * 			   failure that occurred.
- *
- */
-
-typedef void
-(*cti_reply_t)(void *NULLABLE context, cti_status_t status);
-
-/* cti_tunnel_reply: Callback for cti_get_tunnel_name()
- *
- * Called exactly once in response to a cti_get_tunnel_name() call, either with an error or with
- * the name of the tunnel that wpantund is using as the Thread network interface.   The invoking
- * program is responsible for releasing the connection state either during or after the callback.
- *
- * cti_reply parameters:
- *
- * context:       The context that was passed to the cti service call to which this is a callback.
- *
- * tunnel_name:   If error is kCTIStatus_NoError, this dictionary contains either the response to
- * 			      a request, or else the content of a CTI event if this is an event callback.
- *
- * status:	      Will be kCTIStatus_NoError on success, otherwise will indicate the
- * 			      failure that occurred.
- *
- */
-
-typedef void
-(*cti_tunnel_reply_t)(void *NULLABLE context, const char *NONNULL tunnel_name,
-                      cti_status_t status);
-
-/* cti_get_tunnel_name
- *
- * Get the name of the tunnel that wpantund is presenting as the Thread network interface.
- * The tunnel name is passed to the reply callback if the request succeeds; otherwise an error
- * is either returned immediately or returned to the callback.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- *
- * client_queueq:  Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating the
- *                 error that occurred. Note: A return value of kCTIStatus_NoError does not mean that the
- *                 request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_tunnel_name(context, callback, client_queue) \
-    cti_get_tunnel_name_(context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_tunnel_name_(void *NULLABLE context, cti_tunnel_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                     const char *NONNULL file, int line);
-
-/*
- * cti_service_vec_create
- *
- * creates a service array vector of specified length
- *
- * num_services:     Number of service slots available in the service vector.
- *
- * return value:     NULL, if the call failed; otherwise a service vector capable of containing the requested number of
- *                   services.
- */
-cti_service_vec_t *NULLABLE
-cti_service_vec_create_(size_t num_services, const char *NONNULL file, int line);
-#define cti_service_vec_create(num_services) cti_service_vec_create_(num_services, __FILE__, __LINE__)
-
-/*
- * cti_service_vec_release
- *
- * decrements the reference count on the provided service vector and, if it reaches zero, finalizes the service vector,
- * which calls cti_service_release on each service in the vector, potentially also finalizing them.
- *
- * num_services:     Number of service slots available in the service vector.
- *
- * return value:     NULL, if the call failed; otherwise a service vector capable of containing the requested number of
- *                   services.
- */
-
-void
-cti_service_vec_release_(cti_service_vec_t *NONNULL services, const char *NONNULL file, int line);
-#define cti_service_vec_release(services) cti_service_vec_release_(services, __FILE__, __LINE__)
-
-/*
- * cti_service_create
- *
- * Creates a service containing the specified information.   service and server are retained, and will be
- * freed using free() when the service object is finalized.   Caller must not retain or free these values, and
- * they must be allocated on the malloc heap.
- *
- * enterprise_number: The enterprise number for this service.
- *
- * service_type:      The service type, from the service data.
- *
- * service_version:   The service version, from the service data.
- *
- * server:            Server information for this service, stored in network byte order.   Format depends on service type.
- *
- * server_length:     Length of server information in bytes.
- *
- * flags:             Thread network status flags, e.g. NCP versue User
- *
- * return value:     NULL, if the call failed; otherwise a service object containing the specified state.
- */
-
-cti_service_t *NULLABLE
-cti_service_create_(uint64_t enterprise_number, uint16_t service_type, uint16_t service_version,
-                    uint8_t *NONNULL server, size_t server_length, int flags,
-                    const char *NONNULL file, int line);
-#define cti_service_create(enterprise_number, service_type, service_version, server, server_length, flags) \
-    cti_service_create_(enterprise_number, service_type, service_version, server, server_length, flags, \
-                        __FILE__, __LINE__)
-
-/*
- * cti_service_vec_release
- *
- * decrements the reference count on the provided service vector and, if it reaches zero, finalizes the service vector,
- * which calls cti_service_release on each service in the vector, potentially also finalizing them.
- *
- * services:         The service vector to release
- *
- * return value:     NULL, if the call failed; otherwise a service vector capable of containing the requested number of
- *                   services.
- */
-
-void
-cti_service_release_(cti_service_t *NONNULL service, const char *NONNULL file, int line);
-#define cti_service_release(services) cti_service_release(service, __FILE__, __LINE__)
-
-/* cti_service_reply: Callback from cti_get_service_list()
- *
- * Called when an error occurs during processing of the cti_get_service_list call, or when data
- * is available in response to the call.
- *
- * In the case of an error, the callback will not be called again, and the caller is responsible for
- * releasing the connection state and restarting if needed.
- *
- * The callback will be called once immediately upon success, and once again each time the service list
- * is updated.   If the callback wishes to retain either the cti_service_vec_t or any of the elements
- * of that vector, the appropriate retain function should be called; when the object is no longer needed,
- * the corresponding release call must be called.
- *
- * cti_reply parameters:
- *
- * context:           The context that was passed to the cti service call to which this is a callback.
- *
- * services:          If status is kCTIStatus_NoError, a cti_service_vec_t containing the list of services
- *                    provided in the update.
- *
- * status:	          Will be kCTIStatus_NoError if the service list request is successful, or
- *                    will indicate the failure that occurred.
- *
- */
-
-typedef void
-(*cti_service_reply_t)(void *NULLABLE context, cti_service_vec_t *NULLABLE services, cti_status_t status);
-
-/* cti_get_service_list
- *
- * Requests wpantund to immediately send the current list of services published in the Thread network data.
- * Whenever the service list is updated, the callback will be called again with the new information.  A
- * return value of kCTIStatus_NoError means that the caller can expect the reply callback to be called at least
- * once.  Any other error status means that the request could not be sent, and the callback will never be
- * called.
- *
- * To discontinue receiving service add/remove callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to get_service_list();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- *
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *                 If the get_services call fails, response will be NULL and status
- *                 will indicate what went wrong.  No further callbacks can be expected
- *                 after this.   If the request succeeds, then the callback will be called
- *                 once immediately with the current service list, and then again whenever
- *                 the service list is updated.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_service_list(ref, context, callback, client_queue) \
-    cti_get_service_list_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_service_list_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context, cti_service_reply_t NONNULL callback,
-                      run_context_t NULLABLE client_queue, const char *NONNULL file, int line);
-
-/*
- * cti_service_vec_create
- *
- * creates a service array vector of specified length
- *
- * num_prefixes:     Number of prefix slots available in the prefix vector.
- *
- * return value:     NULL, if the call failed; otherwise a prefix vector capable of containing the requested number of
- *                   prefixes.
- */
-cti_prefix_vec_t *NULLABLE
-cti_prefix_vec_create_(size_t num_prefixes, const char *NONNULL file, int line);
-#define cti_prefix_vec_create(num_prefixes) cti_prefix_vec_create_(num_prefixes, __FILE__, __LINE__)
-
-/*
- * cti_prefix_vec_release
- *
- * decrements the reference count on the provided prefix vector and, if it reaches zero, finalizes the prefix vector,
- * which calls cti_prefix_release on each prefix in the vector, potentially also finalizing them.
- *
- * num_prefixes:     Number of prefix slots available in the prefix vector.
- *
- * return value:     NULL, if the call failed; otherwise a prefix vector capable of containing the requested number of
- *                   prefixes.
- */
-
-void
-cti_prefix_vec_release_(cti_prefix_vec_t *NONNULL prefixes, const char *NONNULL file, int line);
-#define cti_prefix_vec_release(prefixes) cti_prefix_vec_release_(prefixes, __FILE__, __LINE__)
-
-/*
- * cti_prefix_create
- *
- * Creates a prefix containing the specified information.   prefix and server are retained, and will be
- * freed using free() when the prefix object is finalized.   Caller must not retain or free these values, and
- * they must be allocated on the malloc heap.
- *
- * enterprise_number: The enterprise number for this prefix.
- *
- * prefix_type:      The prefix type, from the prefix data.
- *
- * prefix_version:   The prefix version, from the prefix data.
- *
- * server:            Server information for this prefix, stored in network byte order.   Format depends on prefix type.
- *
- * server_length:     Length of server information in bytes.
- *
- * flags:             Thread network status flags, e.g. NCP versue User
- *
- * return value:     NULL, if the call failed; otherwise a prefix object containing the specified state.
- */
-
-cti_prefix_t *NULLABLE
-cti_prefix_create_(struct in6_addr *NONNULL prefix, int prefix_length, int metric, int flags,
-                   const char *NONNULL file, int line);
-#define cti_prefix_create(prefix, prefix_length, metric, flags) \
-    cti_prefix_create_(prefix, prefix_length, metric, flags, __FILE__, __LINE__)
-
-/*
- * cti_prefix_vec_release
- *
- * decrements the reference count on the provided prefix vector and, if it reaches zero, finalizes the prefix vector,
- * which calls cti_prefix_release on each prefix in the vector, potentially also finalizing them.
- *
- * prefixes:         The prefix vector to release.
- *
- * return value:     NULL, if the call failed; otherwise a prefix vector capable of containing the requested number of
- *                   prefixes.
- */
-
-void
-cti_prefix_release_(cti_prefix_t *NONNULL prefix, const char *NONNULL file, int line);
-#define cti_prefix_release(prefixes) cti_prefix_release(prefix, __FILE__, __LINE__)
-
-/* cti_prefix_reply: Callback from cti_get_prefix_list()
- *
- * Called when an error occurs during processing of the cti_get_prefix_list call, or when a prefix
- * is added or removed.
- *
- * In the case of an error, the callback will not be called again, and the caller is responsible for
- * releasing the connection state and restarting if needed.
- *
- * The callback will be called once for each prefix present on the Thread network at the time
- * get_prefix_list() is first called, and then again whenever a prefix is added or removed.
- *
- * cti_reply parameters:
- *
- * context:           The context that was passed to the cti prefix call to which this is a callback.
- *
- * prefix_vec:        If status is kCTIStatus_NoError, a vector containing all of the prefixes that were reported in
- *                    this event.
- *
- * status:	          Will be kCTIStatus_NoError if the prefix list request is successful, or
- *                    will indicate the failure that occurred.
- *
- */
-
-typedef void
-(*cti_prefix_reply_t)(void *NULLABLE context, cti_prefix_vec_t *NULLABLE prefixes, cti_status_t status);
-
-/* cti_get_prefix_list
- *
- * Requests wpantund to immediately send the current list of off-mesh prefixes configured in the Thread
- * network data.  Whenever the prefix list is updated, the callback will be called again with the new
- * information.  A return value of kCTIStatus_NoError means that the caller can expect the reply callback to be
- * called at least once.  Any other error means that the request could not be sent, and the callback will
- * never be called.
- *
- * To discontinue receiving prefix add/remove callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to get_prefix_list();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- *
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_prefix_list(ref, context, callback, client_queue) \
-    cti_get_prefix_list_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_prefix_list_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context, cti_prefix_reply_t NONNULL callback,
-                     run_context_t NULLABLE client_queue, const char *NONNULL file, int line);
-
-/* cti_state_reply: Callback from cti_get_state()
- *
- * Called when an error occurs during processing of the cti_get_state call, or when network state
- * information is available.
- *
- * In the case of an error, the callback will not be called again, and the caller is responsible for
- * releasing the connection state and restarting if needed.
- *
- * The callback will be called initially to report the network state, and subsequently whenever the
- * network state changes.
- *
- * cti_reply parameters:
- *
- * context:           The context that was passed to the cti state call to which this is a callback.
- *
- * state:             The network state.
- *
- * status:	          Will be kCTIStatus_NoError if the prefix list request is successful, or
- *                    will indicate the failure that occurred.
- *
- */
-
-typedef void
-(*cti_state_reply_t)(void *NULLABLE context, cti_network_state_t state, cti_status_t status);
-
-/* cti_get_state
- *
- * Requests wpantund to immediately send the current state of the thread network.  Whenever the thread
- * network state changes, the callback will be called again with the new state.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called at least once.  Any
- * other error means that the request could not be sent, and the callback will never be called.
- *
- * To discontinue receiving state change callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to cti_get_state();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_state(ref, context, callback, client_queue) \
-    cti_get_state_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_state_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context, cti_state_reply_t NONNULL callback,
-               run_context_t NULLABLE client_queue, const char *NONNULL file, int line);
-
-/* cti_uint64_property_reply: Callback from cti_get_partition_id() or cti_get_xpanid()
- *
- * Called when an error occurs during processing of the cti_get_* call, or when a new value for the requested property
- * is available.
- *
- * In the case of an error, the callback will not be called again, and the caller is responsible for
- * releasing the connection and restarting if needed.
- *
- * The callback will be called initially to report the current value for the property, and subsequently whenever the
- * property changes.
- *
- * cti_uint64_property_reply parameters:
- *
- * context:           The context that was passed to the cti prefix call to which this is a callback.
- *
- * property_value     The value of the property (only valid if status is kCTIStatus_NoError).
- *
- * status:	          Will be kCTIStatus_NoError if the partition ID request is successful, or will indicate the failure
- *                    that occurred.
- *
- */
-
-typedef void
-(*cti_uint64_property_reply_t)(void *NULLABLE context, uint64_t property_value, cti_status_t status);
-
-/* cti_get_partition_id
- *
- * Requests wpantund to immediately send the current partition_id of the thread network.  Whenever the thread
- * network partition_id changes, the callback will be called again with the new partition_id.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called at least once.  Any
- * other error means that the request could not be sent, and the callback will never be called.
- *
- * To discontinue receiving partition_id change callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to cti_get_partition_id();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_partition_id(ref, context, callback, client_queue) \
-    cti_get_partition_id_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_partition_id_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context,
-                      cti_uint64_property_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                      const char *NONNULL file, int line);
-
-/* cti_get_extended_pan_id
- *
- * Requests wpantund to immediately send the current extended_pan_id of the thread network.  Whenever the thread
- * network extended_pan_id changes, the callback will be called again with the new extended_pan_id.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called at least once.  Any
- * other error means that the request could not be sent, and the callback will never be called.
- *
- * To discontinue receiving extended_pan_id change callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to cti_get_extended_pan_id();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_extended_pan_id(ref, context, callback, client_queue) \
-    cti_get_extended_pan_id_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_extended_pan_id_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context,
-                         cti_uint64_property_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                         const char *NONNULL file, int line);
-
-/* cti_network_node_type_reply: Callback from cti_get_network_node_type()
- *
- * Called when an error occurs during processing of the cti_get_network_node_type call, or when network partition ID
- * information is available.
- *
- * In the case of an error, the callback will not be called again, and the caller is responsible for releasing the
- * connection network_node_type and restarting if needed.
- *
- * The callback will be called initially to report the network partition ID, and subsequently whenever the network
- * partition ID changes.
- *
- * cti_reply parameters:
- *
- * context:           The context that was passed to the cti prefix call to which this is a callback.
- *
- * network_node_type: The network node type, kCTI_NetworkNodeType_Unknown if it is not known.
- *
- * status:	          Will be kCTIStatus_NoError if the partition ID request is successful, or will indicate the failure
- *                    that occurred.
- *
- */
-
-typedef void
-(*cti_network_node_type_reply_t)(void *NULLABLE context, cti_network_node_type_t network_node_type, cti_status_t status);
-
-/* cti_get_network_node_type
- *
- * Requests wpantund to immediately send the current network_node_type of the thread network.  Whenever the thread
- * network network_node_type changes, the callback will be called again with the new network_node_type.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called at least once.  Any
- * other error means that the request could not be sent, and the callback will never be called.
- *
- * To discontinue receiving network_node_type change callbacks, the calling program should call
- * cti_connection_ref_deallocate on the conn_ref returned by a successful call to cti_get_network_node_type();
- *
- * ref:            A pointer to a reference to the connection is stored through ref if ref is not NULL.
- *                 When events are no longer needed, call cti_discontinue_events() on the returned pointer.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_get_network_node_type(ref, context, callback, client_queue) \
-    cti_get_network_node_type_(ref, context, callback, client_queue, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_get_network_node_type_(cti_connection_t NULLABLE *NULLABLE ref, void *NULLABLE context,
-                           cti_network_node_type_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                           const char *NONNULL file, int line);
-
-/* cti_add_service
- *
- * Requests wpantund to add the specified service to the thread network data.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called with a success or fail
- * status exactly one time.  Any other error means that the request could not be sent, and the callback will
- * never be called.
- *
- * context:           An anonymous pointer that will be passed along to the callback when
- *                    an event occurs.
- *
- * client_queue:      Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * callback:          CallBack function for the client that indicates success or failure.
- *
- * enterprise_number: Contains the enterprise number of the service.
- *
- * service_data:      Typically four bytes, in network byte order, the first two bytes indicate
- *                    the type of service within the enterprise' number space, and the second
- *                    two bytes indicate the version number.
- *
- * service_data_len:  The length of the service data in bytes.
- *
- * server_data:       Typically four bytes, in network byte order, the first two bytes indicate
- *                    the type of service within the enterprise' number space, and the second
- *                    two bytes indicate the version number.
- *
- * server_data_len:   The length of the service data in bytes.
- *
- * return value:      Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                    the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                    that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_add_service(context, callback, client_queue, \
-                        enterprise_number, service_data, service_data_length, server_data, server_data_length) \
-    cti_add_service_(context, callback, client_queue, enterprise_number, \
-                     service_data, service_data_length, server_data, server_data_length, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_add_service_(void *NULLABLE context, cti_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                 uint32_t enterprise_number, const uint8_t *NONNULL service_data, size_t service_data_length,
-                 const uint8_t *NONNULL server_data, size_t server_data_length,
-                 const char *NONNULL file, int line);
-
-/* cti_remove_service
- *
- * Requests wpantund to remove the specified service from the thread network data.  A return value of
- * kCTIStatus_NoError means that the caller can expect the reply callback to be called with a success or fail
- * status exactly one time.  Any other error means that the request could not be sent, and the callback will
- * never be called.
- *
- * context:           An anonymous pointer that will be passed along to the callback when
- *                    an event occurs.
- *
- * client_queue:      Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * enterprise_number: Contains the enterprise number of the service.
- *
- * service_data:      Typically four bytes, in network byte order, the first two bytes indicate
- *                    the type of service within the enterprise' number space, and the second
- *                    two bytes indicate the version number.
- *
- * service_data_len:  The length of the service data in bytes.
- *
- * callback:          callback function for the client that indicates success or failure.
- *
- * return value:      Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                    the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                    that the request succeeded, merely that it was successfully started.
- */
-
-#define cti_remove_service(context, callback, client_queue, \
-                           enterprise_number, service_data, service_data_length) \
-    cti_remove_service_(context, callback, client_queue,            \
-                        enterprise_number, service_data, service_data_length, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_remove_service_(void *NULLABLE context, cti_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                    uint32_t enterprise_number, const uint8_t *NONNULL service_data,
-                    size_t service_data_length, const char *NONNULL file, int line);
-
-/* cti_add_prefix
- *
- * Requests wpantund to add the specified prefix to the set of off-mesh prefixes configured on the thread
- * network.  A return value of kCTIStatus_NoError means that the caller can expect the reply callback to be
- * called with a success or fail status exactly one time.  Any other error means that the request could not
- * be sent, and the callback will never be called.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * prefix:         A pointer to a struct in6_addr.  Must not be reatained by the callback.
- *
- * prefix_len:     The length of the prefix in bits.
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_add_prefix(context, callback, client_queue, \
-                       prefix, prefix_length, on_mesh, preferred, slaac, stable) \
-    cti_add_prefix_(context, callback, client_queue, prefix, prefix_length, \
-                    on_mesh, preferred, slaac, stable, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_add_prefix_(void *NULLABLE context, cti_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                struct in6_addr *NONNULL prefix, int prefix_length, bool on_mesh, bool preferred, bool slaac,
-                bool stable, const char *NONNULL file, int line);
-
-/* cti_remove_prefix
- *
- * Requests wpantund to remove the specified prefix from the set of off-mesh prefixes configured on the thread network.
- * A return value of kCTIStatus_NoError means that the caller can expect the reply callback to be called with a success
- * or fail status exactly one time.  Any other error means that the request could not be sent, and the callback will
- * never be called.
- *
- * context:        An anonymous pointer that will be passed along to the callback when
- *                 an event occurs.
- *
- * client_queue:   Queue the client wants to schedule the callback on (Note: Must not be NULL)
- *
- * prefix:         A pointer to a struct in6_addr.  Must not be reatained by the callback.
- *
- * prefix_len:     The length of the prefix in bits.
- *
- * callback:       CallBack function for the client that indicates success or failure.
- *
- * return value:   Returns kCTIStatus_NoError when no error otherwise returns an error code indicating
- *                 the error that occurred. Note: A return value of kCTIStatus_NoError does not mean
- *                 that the request succeeded, merely that it was successfully started.
- *
- */
-
-#define cti_remove_prefix(context, callback, client_queue, prefix, prefix_length) \
-    cti_remove_prefix_(context, callback, client_queue, prefix, prefix_length, __FILE__, __LINE__)
-DNS_SERVICES_EXPORT cti_status_t
-cti_remove_prefix_(void *NULLABLE context, cti_reply_t NONNULL callback, run_context_t NULLABLE client_queue,
-                   struct in6_addr *NONNULL prefix, int prefix_length, const char *NONNULL file, int line);
-
-/* cti_events_discontinue
- *
- * Requests that the CTI library stop delivering events on the specified connection.   The connection will have
- * been returned by a CTI library call that subscribes to events.
- */
-DNS_SERVICES_EXPORT cti_status_t
-cti_events_discontinue(cti_connection_t NONNULL ref);
-
-typedef union cti_callback {
-    cti_reply_t NULLABLE reply;
-    cti_tunnel_reply_t NONNULL tunnel_reply;
-    cti_service_reply_t NONNULL service_reply;
-    cti_prefix_reply_t NONNULL prefix_reply;
-    cti_state_reply_t NONNULL state_reply;
-    cti_uint64_property_reply_t NONNULL uint64_property_reply;
-    cti_network_node_type_reply_t NONNULL network_node_type_reply;
-} cti_callback_t;
-
-#endif /* __CTI_SERVICES_H__ */
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/dns-msg.h b/ServiceRegistration/dns-msg.h
deleted file mode 100644
index 6535a6b..0000000
--- a/ServiceRegistration/dns-msg.h
+++ /dev/null
@@ -1,563 +0,0 @@
-/* dns-msg.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * Lightweight framework for generating, sending, and unpacking DNS messages.
- * Definitions...
- */
-
-#ifndef __DNS_MSG_H
-#define __DNS_MSG_H
-
-#include "srp.h"
-
-#ifndef DNS_MAX_UDP_PAYLOAD
-#define DNS_MAX_UDP_PAYLOAD 1410
-#endif
-
-#define DNS_HEADER_SIZE            12
-#define DNS_DATA_SIZE              (DNS_MAX_UDP_PAYLOAD - DNS_HEADER_SIZE)
-#define DNS_MAX_POINTER            ((2 << 14) - 1)
-#define DNS_MAX_LABEL_SIZE         63
-#define DNS_MAX_LABEL_SIZE_ESCAPED 252
-#define DNS_MAX_NAME_SIZE          255
-#define DNS_MAX_NAME_SIZE_ESCAPED  1009
-#define DNS_MAX_LABELS             128
-
-typedef struct message message_t;
-
-typedef struct dns_wire dns_wire_t;
-struct dns_wire {
-    uint16_t id;
-    uint16_t bitfield;
-    uint16_t qdcount;
-    uint16_t ancount;
-    uint16_t nscount;
-    uint16_t arcount;
-    uint8_t data[DNS_DATA_SIZE];
-};
-
-typedef struct dns_name_pointer dns_name_pointer_t;
-struct dns_name_pointer {
-    dns_name_pointer_t *NULLABLE next;
-    uint8_t *NONNULL message_start;
-    uint8_t *NONNULL name_start;
-    int num_labels;
-    int length;
-};
-
-typedef struct dns_towire_state dns_towire_state_t;
-struct dns_towire_state {
-    dns_wire_t *NULLABLE message;
-    uint8_t *NONNULL p;
-    uint8_t *NONNULL lim;
-    uint8_t *NULLABLE p_rdlength;
-    uint8_t *NULLABLE p_opt;
-    int line, outer_line;
-    bool truncated : 1;
-    unsigned int error : 31;
-};
-
-typedef struct dns_transaction dns_transaction_t;
-struct dns_transaction {
-    dns_transaction_t *NULLABLE next;
-    dns_towire_state_t towire;
-    dns_wire_t *NULLABLE response;
-    int response_length;
-    int sock;
-};
-
-typedef void (*dns_response_callback_t)(dns_transaction_t *NONNULL txn);
-
-typedef struct dns_label dns_label_t;
-typedef dns_label_t dns_name_t;
-struct dns_label {
-    dns_label_t *NULLABLE next;
-    uint8_t len;
-    char data[DNS_MAX_LABEL_SIZE];
-};
-
-typedef struct dns_rdata_txt dns_rdata_txt_t;
-struct dns_rdata_txt {
-    uint8_t len;
-    char *NONNULL data;
-};
-
-typedef struct dns_rdata_unparsed dns_rdata_unparsed_t;
-struct dns_rdata_unparsed {
-    uint8_t *NULLABLE data;
-    uint16_t len;
-};
-
-typedef struct dns_rdata_single_name dns_rdata_ptr_t;
-typedef struct dns_rdata_single_name dns_rdata_ns_t;
-typedef struct dns_rdata_single_name dns_rdata_cname_t;
-struct dns_rdata_single_name {
-    dns_label_t *NONNULL name;
-};
-
-typedef struct dns_rdata_srv dns_rdata_srv_t;
-struct dns_rdata_srv {
-    dns_label_t *NONNULL name;
-    uint16_t priority;
-    uint16_t weight;
-    uint16_t port;
-};
-
-typedef struct dns_rdata_sig dns_rdata_sig_t;
-struct dns_rdata_sig {
-    uint16_t type;
-    uint8_t algorithm;
-    uint8_t label;
-    uint32_t rrttl;
-    uint32_t expiry;
-    uint32_t inception;
-    uint16_t key_tag;
-    dns_label_t *NONNULL signer;
-    unsigned start;
-    unsigned len;
-    uint8_t *NONNULL signature;
-};
-
-typedef struct dns_rdata_key dns_rdata_key_t;
-struct dns_rdata_key {
-    uint16_t flags;
-    uint8_t protocol;
-    uint8_t algorithm;
-    unsigned len;
-    uint8_t *NONNULL key;
-};
-
-typedef struct dns_rr dns_rr_t;
-struct dns_rr {
-    dns_label_t *NONNULL name;
-    uint16_t type;
-    uint16_t qclass;
-    uint32_t ttl;
-    union {
-        dns_rdata_unparsed_t unparsed;
-        dns_rdata_ptr_t ptr;
-        dns_rdata_cname_t cname;
-        dns_rdata_ns_t ns;
-        struct in_addr a;
-        struct in6_addr aaaa;
-        dns_rdata_srv_t srv;
-        dns_rdata_txt_t txt;
-        dns_rdata_sig_t sig;
-        dns_rdata_key_t key;
-    } data;
-};
-
-typedef struct dns_edns0 dns_edns0_t;
-struct dns_edns0 {
-    dns_edns0_t *NULLABLE next;
-    uint16_t length;
-    uint16_t type;
-    uint8_t data[0];
-};
-
-typedef struct dns_message dns_message_t;
-struct dns_message {
-    int ref_count;
-    unsigned qdcount, ancount, nscount, arcount;
-    dns_rr_t *NULLABLE questions;
-    dns_rr_t *NULLABLE answers;
-    dns_rr_t *NULLABLE authority;
-    dns_rr_t *NULLABLE additional;
-    dns_edns0_t *NULLABLE edns0;
-};
-
-// Masks for bitfield data
-#define dns_qr_mask     0x8000
-#define dns_opcode_mask 0x7800
-#define dns_flags_mask  0x07f0
-#define dns_rcode_mask  0x000f
-
-// Shifts for bitfield data
-#define dns_qr_shift     15
-#define dns_opcode_shift 11
-#define dns_rcode_shift  0
-
-// Booleans
-#define dns_flags_aa 0x0400
-#define dns_flags_tc 0x0200
-#define dns_flags_rd 0x0100
-#define dns_flags_ra 0x0080
-#define dns_flags_ad 0x0020
-#define dns_flags_cd 0x0010
-
-// Getters
-#define dns_qr_get(w)     ((ntohs((w)->bitfield) & dns_qr_mask) >> dns_qr_shift)
-#define dns_opcode_get(w) ((ntohs((w)->bitfield) & dns_opcode_mask) >> dns_opcode_shift)
-#define dns_rcode_get(w)  ((ntohs((w)->bitfield) & dns_rcode_mask) >> dns_rcode_shift)
-
-// Setters
-#define dns_qr_set(w, value) \
-    ((w)->bitfield = htons(((ntohs((w)->bitfield) & ~dns_qr_mask) | ((value) << dns_qr_shift))))
-#define dns_opcode_set(w, value) \
-    ((w)->bitfield = htons(((ntohs((w)->bitfield) & ~dns_opcode_mask) | ((value) << dns_opcode_shift))))
-#define dns_rcode_set(w, value) \
-    ((w)->bitfield = htons(((ntohs((w)->bitfield) & ~dns_rcode_mask) | ((value) << dns_rcode_shift))))
-
-// Query/Response
-#define dns_qr_query           0
-#define dns_qr_response        1
-
-// Opcodes
-#define dns_opcode_query       0
-#define dns_opcode_iquery      1
-#define dns_opcode_status      2
-#define dns_opcode_notify      4
-#define dns_opcode_update      5
-#define dns_opcode_dso         6
-
-// Response Codes
-#define dns_rcode_noerror      0 // [RFC1035] No Error
-#define dns_rcode_formerr      1 // [RFC1035] Format Error
-#define dns_rcode_servfail     2 // [RFC1035] Server Failure
-#define dns_rcode_nxdomain     3 // [RFC1035] Non-Existent Domain
-#define dns_rcode_notimp       4 // [RFC1035] Not Implemented
-#define dns_rcode_refused      5 // [RFC1035] Query Refused
-#define dns_rcode_yxdomain     6 // [RFC2136][RFC6672] Name Exists when it should not
-#define dns_rcode_yxrrset      7 // [RFC2136] RR Set Exists when it should not
-#define dns_rcode_nxrrset      8 // [RFC2136] RR Set that should exist does not
-#define dns_rcode_notauth      9 // [RFC2136] Server Not Authoritative for zone, or [RFC2845] Not Authorized
-#define dns_rcode_notzone     10 // [RFC2136] Name not contained in zone
-#define dns_rcode_dsotypeni   11 // [RFCTBD draft-ietf-dnsop-session-signal] DSO-Type Not Implemented
-#define dns_rcode_badvers     16 // [RFC6891] Bad OPT Version, or [RFC2845] TSIG Signature Failure
-#define dns_rcode_badkey      17 // [RFC2845] Key not recognized
-#define dns_rcode_badtime     18 // [RFC2845] Signature out of time window
-#define dns_rcode_badmode     19 // [RFC2930] Bad TKEY Mode
-#define dns_rcode_badname     20 // [RFC2930] Duplicate key name
-#define dns_rcode_badalg      21 // [RFC2930] Algorithm not supported
-#define dns_rcode_badtrunc    22 // [RFC4635] Bad Truncation
-#define dns_rcode_badcookie   23 // [RFC7873] Bad/missing Server Cookie
-
-#define dns_qclass_in          1 // [RFC1035] Internet (IN)
-#define dns_qclass_chaos       3 // [D. Moon, "Chaosnet"] Chaosnet (MIT)
-#define dns_qclass_hesiod      4 // [MIT Project Athena Technical Plan] Hesiod service
-#define dns_qclass_none      254 // [RFC2136] NONE (delete, or not in use)
-#define dns_qclass_any       255 // [RFC1035] ANY (wildcard)
-
-#define dns_rrtype_a           1 // [RFC1035] a host address
-#define dns_rrtype_ns          2 // [RFC1035] an authoritative name server
-#define dns_rrtype_md          3 // [RFC1035] a mail destination (OBSOLETE - use MX)
-#define dns_rrtype_mf          4 // [RFC1035] a mail forwarder (OBSOLETE - use MX)
-#define dns_rrtype_cname       5 // [RFC1035] the canonical name for an alias
-#define dns_rrtype_soa         6 // [RFC1035] marks the start of a zone of authority
-#define dns_rrtype_mb          7 // [RFC1035] a mailbox domain name (EXPERIMENTAL)
-#define dns_rrtype_mg          8 // [RFC1035] a mail group member (EXPERIMENTAL)
-#define dns_rrtype_mr          9 // [RFC1035] a mail rename domain name (EXPERIMENTAL)
-#define dns_rrtype_null       10 // [RFC1035]    a null RR (EXPERIMENTAL)
-#define dns_rrtype_wks        11 // [RFC1035]    a well known service description
-#define dns_rrtype_ptr        12 // [RFC1035]    a domain name pointer
-#define dns_rrtype_hinfo      13 // [RFC1035]    host information
-#define dns_rrtype_minfo      14 // [RFC1035]    mailbox or mail list information
-#define dns_rrtype_mx         15 // [RFC1035]    mail exchange
-#define dns_rrtype_txt        16 // [RFC1035] text strings
-#define dns_rrtype_rp         17 // [RFC1183] for Responsible Person
-#define dns_rrtype_afsdb      18 // [RFC1183,RFC5864] for AFS Data Base location
-#define dns_rrtype_x25        19 // [RFC1183] for X.25 PSDN address
-#define dns_rrtype_isdn       20 // [RFC1183] for ISDN address
-#define dns_rrtype_rt         21 // [RFC1183] for Route Through
-#define dns_rrtype_nsap       22 // [RFC1706] for NSAP address, NSAP style A record
-#define dns_rrtype_nsap_ptr   23 // [RFC1348,RFC1637,RFC1706] for domain name pointer, NSAP style
-#define dns_rrtype_sig        24 // [RFC4034,RFC3755,RFC2535,RFC2536,RFC2537,RFC2931,RFC3110,RFC3008]
-#define dns_rrtype_key        25 // [RFC4034,RFC3755,RFC2535,RFC2536,RFC2537,RFC2539,RFC3008,RFC3110]
-#define dns_rrtype_px         26 // [RFC2163] X.400 mail mapping information
-#define dns_rrtype_gpos       27 // [RFC1712] Geographical Position
-#define dns_rrtype_aaaa       28 // [RFC3596] IP6 Address
-#define dns_rrtype_loc        29 // [RFC1876] Location Information
-#define dns_rrtype_nxt        30 // [RFC3755] [RFC2535] Next Domain (OBSOLETE)
-#define dns_rrtype_eid        31 // [http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] Endpoint Identifier
-#define dns_rrtype_nimloc     32 // [http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] Nimrod Locator
-#define dns_rrtype_srv        33 // [RFC2782] Server Selection
-#define dns_rrtype_atma       34 // ["ATM Name System, V2.0"] ATM Address
-#define dns_rrtype_naptr      35 // [RFC2915] [RFC2168] [RFC3403] Naming Authority Pointer
-#define dns_rrtype_kx         36 // [RFC2230] Key Exchanger
-#define dns_rrtype_cert       37 // [RFC4398] CERT
-#define dns_rrtype_a6         38 // [RFC3226] [RFC2874] [RFC6563]    A6 (OBSOLETE - use AAAA)
-#define dns_rrtype_dname      39 // [RFC6672]
-#define dns_rrtype_sink       40 // [http://tools.ietf.org/html/draft-eastlake-kitchen-sink]
-#define dns_rrtype_opt        41 // [RFC6891] [RFC3225]
-#define dns_rrtype_apl        42 // [RFC3123]
-#define dns_rrtype_ds         43 // [RFC4034] [RFC3658] Delegation Signer
-#define dns_rrtype_sshfp      44 // [RFC4255] SSH Key Fingerprint
-#define dns_rrtype_ipseckey   45 // [RFC4025]
-#define dns_rrtype_rrsig      46 // [RFC4034] [RFC3755]
-#define dns_rrtype_nsec       47 // [RFC4034] [RFC3755]
-#define dns_rrtype_dnskey     48 // [RFC4034] [RFC3755]
-#define dns_rrtype_dhcid      49 // [RFC4701] DHCID
-#define dns_rrtype_nsec3      50 // [RFC5155] NSEC3
-#define dns_rrtype_nsec3param 51 // [RFC5155] NSEC3PARAM
-#define dns_rrtype_tlsa       52 // [RFC6698] TLSA
-#define dns_rrtype_smimea     53 // [RFC8162] S/MIME cert association
-#define dns_rrtype_hip        55 // Host Identity Protocol
-#define dns_rrtype_ninfo      56 // [Jim_Reid] NINFO/ninfo-completed-template
-#define dns_rrtype_rkey       57 // [Jim_Reid] RKEY/rkey-completed-template
-#define dns_rrtype_talink     58 // [Wouter_Wijngaards] Trust Anchor LINK
-#define dns_rrtype_cds        59 // [RFC7344] Child DS
-#define dns_rrtype_cdnskey    60 // [RFC7344]   DNSKEY(s) the Child wants reflected in DS
-#define dns_rrtype_openpgpkey 61 // [RFC7929]   OpenPGP Key
-#define dns_rrtype_csync      62 // [RFC7477] Child-To-Parent Synchronization
-#define dns_rrtype_zonemd     63 // [RFC8976]
-#define dns_rrtype_svcb       64 // [draft-ietf-dnsop-svcb-https-10]
-#define dns_rrtype_https      65 // [draft-ietf-dnsop-svcb-https-10]
-#define dns_rrtype_spf        99 // [RFC7208]
-#define dns_rrtype_uinfo     100 // [IANA-Reserved]
-#define dns_rrtype_uid       101 // [IANA-Reserved]
-#define dns_rrtype_gid       102 // [IANA-Reserved]
-#define dns_rrtype_unspec    103 // [IANA-Reserved]
-#define dns_rrtype_nid       104 // [RFC6742]
-#define dns_rrtype_l32       105 // [RFC6742]
-#define dns_rrtype_l64       106 // [RFC6742]
-#define dns_rrtype_lp        107 // [RFC6742]
-#define dns_rrtype_eui48     108 // an EUI-48 address [RFC7043]
-#define dns_rrtype_eui64     109 // an EUI-64 address [RFC7043]
-#define dns_rrtype_tkey      249 // Transaction Key [RFC2930]
-#define dns_rrtype_tsig      250 // Transaction Signature [RFC2845]
-#define dns_rrtype_ixfr      251 // incremental transfer    [RFC1995]
-#define dns_rrtype_axfr      252 // transfer of an entire zone [RFC1035][RFC5936]
-#define dns_rrtype_mailb     253 // mailbox-related RRs (MB, MG or MR) [RFC1035]
-#define dns_rrtype_maila     254 // mail agent RRs (OBSOLETE - see MX) [RFC1035]
-#define dns_rrtype_any       255 // A request for some or all records the server has available
-#define dns_rrtype_uri       256 // URI [RFC7553]   URI/uri-completed-template
-#define dns_rrtype_caa       257 // Certification Authority Restriction [RFC6844]
-#define dns_rrtype_avc       258 // Application Visibility and Control [Wolfgang_Riedel]
-#define dns_rrtype_doa       259 // Digital Object Architecture [draft-durand-doa-over-dns]
-#define dns_rrtype_amtrelay  260 // [RFC8777]
-#define dns_rrtype_ta      32768 // Trust authorities [Sam Weiler]
-#define dns_rrtype_dlv     32769 // [RFC8749]
-
-#define dns_opt_llq            1 // On-hold [http://files.dns-sd.org/draft-sekar-dns-llq.txt]
-#define dns_opt_update_lease   2 // On-hold [http://files.dns-sd.org/draft-sekar-dns-ul.txt]
-#define dns_opt_nsid           3 // [RFC5001]
-#define dns_opt_owner          4 // [draft-cheshire-edns0-owner-option]
-#define dns_opt_dau            5 // [RFC6975]
-#define dns_opt_dhu            6 // [RFC6975]
-#define dns_opt_n3u            7 // [RFC6975]
-#define dns_opt_client_subnet  8 // [RFC7871]
-#define dns_opt_expire         9 // [RFC7314]
-#define dns_opt_cookie        10 // [RFC7873]
-#define dns_opt_keepalive     11 // [RFC7828]
-#define dns_opt_padding       12 // [RFC7830]
-#define dns_opt_chain         13 // [RFC7901]
-#define dns_opt_key_tag       14 // [RFC8145]
-#define dns_opt_srp_serial 65186 // ???
-
-// towire.c:
-
-uint16_t srp_random16(void);
-void dns_name_to_wire_(dns_name_pointer_t *NULLABLE r_pointer,
-                       dns_towire_state_t *NONNULL txn,
-                       const char *NONNULL name, int line);
-#define dns_name_to_wire(r_pointer, txn, name) dns_name_to_wire_(r_pointer, txn, name, __LINE__)
-
-void dns_full_name_to_wire_(dns_name_pointer_t *NULLABLE r_pointer,
-                            dns_towire_state_t *NONNULL txn,
-                            const char *NONNULL name, int line);
-#define dns_full_name_to_wire(r_pointer, txn, name) dns_full_name_to_wire_(r_pointer, txn, name, __LINE__)
-
-void dns_pointer_to_wire_(dns_name_pointer_t *NULLABLE r_pointer,
-                          dns_towire_state_t *NONNULL txn,
-                          dns_name_pointer_t *NONNULL pointer, int line);
-#define dns_pointer_to_wire(r_pointer, txn, pointer) dns_pointer_to_wire_(r_pointer, txn, pointer, __LINE__)
-
-void dns_u8_to_wire_(dns_towire_state_t *NONNULL txn, uint8_t val, int line);
-#define dns_u8_to_wire(txn, val) dns_u8_to_wire_(txn, val, __LINE__)
-
-void dns_u16_to_wire_(dns_towire_state_t *NONNULL txn, uint16_t val, int line);
-#define dns_u16_to_wire(txn, val) dns_u16_to_wire_(txn, val, __LINE__)
-
-void dns_u32_to_wire_(dns_towire_state_t *NONNULL txn, uint32_t val, int line);
-#define dns_u32_to_wire(txn, val) dns_u32_to_wire_(txn, val, __LINE__)
-
-void dns_u64_to_wire_(dns_towire_state_t *NONNULL txn, uint64_t val, int line);
-#define dns_u64_to_wire(txn, val) dns_u64_to_wire_(txn, val, __LINE__)
-
-void dns_ttl_to_wire_(dns_towire_state_t *NONNULL txn, int32_t val, int line);
-#define dns_ttl_to_wire(txn, val) dns_ttl_to_wire_(txn, val, __LINE__)
-
-void dns_rdlength_begin_(dns_towire_state_t *NONNULL txn, int line);
-#define dns_rdlength_begin(txn) dns_rdlength_begin_(txn, __LINE__)
-
-void dns_rdlength_end_(dns_towire_state_t *NONNULL txn, int line);
-#define dns_rdlength_end(txn) dns_rdlength_end_(txn, __LINE__)
-
-void dns_rdata_a_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL ip_address, int line);
-#define dns_rdata_a_to_wire(txn, ip_address) dns_rdata_a_to_wire_(txn, ip_address, __LINE__)
-
-void dns_rdata_aaaa_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL ip_address, int line);
-#define dns_rdata_aaaa_to_wire(txn, ip_address) dns_rdata_aaaa_to_wire_(txn, ip_address, __LINE__)
-
-uint16_t dns_rdata_key_to_wire_(dns_towire_state_t *NONNULL txn,
-                                unsigned key_type,
-                                unsigned name_type,
-                                uint8_t signatory,
-                                srp_key_t *NONNULL key, int line);
-#define dns_rdata_key_to_wire(txn, key_type, name_type, signatory, key) \
-    dns_rdata_key_to_wire_(txn, key_type, name_type, signatory, key, __LINE__)
-
-void dns_rdata_txt_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL txt_record, int line);
-#define dns_rdata_txt_to_wire(txn, txt_record) dns_rdata_txt_to_wire_(txn, txt_record, __LINE__)
-
-void dns_rdata_raw_data_to_wire_(dns_towire_state_t *NONNULL txn,
-                                 const void *NONNULL raw_data, size_t length, int line);
-#define dns_rdata_raw_data_to_wire(txn, raw_data, length) dns_rdata_raw_data_to_wire_(txn, raw_data, length, __LINE__)
-
-void dns_edns0_header_to_wire_(dns_towire_state_t *NONNULL txn,
-                               uint16_t mtu, uint8_t xrcode, uint8_t version, bool DO, int line);
-#define dns_edns0_header_to_wire(txn, mtu, xrcode, version, DO) \
-    dns_edns0_header_to_wire_(txn, mtu, xrcode, version, DO, __LINE__)
-
-void dns_edns0_option_begin_(dns_towire_state_t *NONNULL txn, int line);
-#define dns_edns0_option_begin(txn) dns_edns0_option_begin_(txn, __LINE__)
-
-void dns_edns0_option_end_(dns_towire_state_t *NONNULL txn, int line);
-#define dns_edns0_option_end(txn) dns_edns0_option_end_(txn, __LINE__)
-
-void dns_sig0_signature_to_wire_(dns_towire_state_t *NONNULL txn,
-                                 srp_key_t *NONNULL key, uint16_t key_tag,
-                                 dns_name_pointer_t *NONNULL signer, const char *NONNULL signer_hostname,
-                                 const char *NONNULL signer_domain, int line);
-#define dns_sig0_signature_to_wire(txn, key, key_tag, signer, signer_hostname, signer_domain) \
-    dns_sig0_signature_to_wire_(txn, key, key_tag, signer, signer_hostname, signer_domain, __LINE__)
-
-int dns_send_to_server(dns_transaction_t *NONNULL txn,
-                       const char *NONNULL anycast_address, uint16_t port,
-                       dns_response_callback_t NONNULL callback);
-
-// fromwire.c:
-#define dns_label_parse(buf, mlen, offp) dns_label_parse_(buf, mlen, offp, __FILE__, __LINE__)
-dns_label_t *NULLABLE dns_label_parse_(const uint8_t *NONNULL buf, unsigned mlen, unsigned *NONNULL offp,
-                                       const char *NONNULL file, int line);
-bool dns_opt_parse(dns_edns0_t *NONNULL *NULLABLE ret, dns_rr_t *NONNULL rrset);
-#define dns_name_parse(ret, buf, len, offp, base) dns_name_parse_(ret, buf, len, offp, base, __FILE__, __LINE__)
-bool dns_name_parse_(dns_label_t *NONNULL *NULLABLE ret, const uint8_t *NONNULL buf, unsigned len,
-                     unsigned *NONNULL offp, unsigned base, const char *NONNULL file, int line);
-bool dns_u8_parse(const uint8_t *NONNULL buf, unsigned len, unsigned *NONNULL offp, uint8_t *NONNULL ret);
-bool dns_u16_parse(const uint8_t *NONNULL buf, unsigned len, unsigned *NONNULL offp, uint16_t *NONNULL ret);
-bool dns_u32_parse(const uint8_t *NONNULL buf, unsigned len, unsigned *NONNULL offp, uint32_t *NONNULL ret);
-bool dns_u64_parse(const uint8_t *NONNULL buf, unsigned len, unsigned *NONNULL offp, uint64_t *NONNULL ret);
-#define dns_rdata_parse_data(rr, buf, offp, target, rdlen, rrstart) \
-    dns_rdata_parse_data_(rr, buf, offp, target, rdlen, rrstart, __FILE__, __LINE__)
-bool dns_rdata_parse_data_(dns_rr_t *NONNULL rr, const uint8_t *NONNULL buf, unsigned *NONNULL offp,
-                           unsigned target, uint16_t rdlen, unsigned rrstart, const char *NONNULL file, int line);
-#define dns_rr_parse(rrset, buf, len, offp, rrdata_permitted, dump_to_stderr) \
-    dns_rr_parse_(rrset, buf, len, offp, rrdata_permitted, dump_to_stderr, __FILE__, __LINE__)
-bool dns_rr_parse_(dns_rr_t *NONNULL rrset, const uint8_t *NONNULL buf, unsigned len, unsigned *NONNULL offp,
-                   bool rrdata_permitted, bool dump_to_stderr, const char *NONNULL file, int line);
-void dns_name_free(dns_label_t *NONNULL name);
-void dns_rrdata_free(dns_rr_t *NONNULL rr);
-void dns_message_free(dns_message_t *NONNULL message);
-#define dns_wire_parse(ret, message, len, dump_to_stderr) \
-    dns_wire_parse_(ret, message, len, dump_to_stderr, __FILE__, __LINE__)
-bool dns_wire_parse_(dns_message_t *NONNULL *NULLABLE ret, dns_wire_t *NONNULL message, unsigned len,
-                     bool dump_to_stderr, const char *NONNULL FILE, int line);
-bool dns_names_equal(dns_label_t *NONNULL name1, dns_label_t *NONNULL name2);
-
-// wireutils.c
-dns_name_t *NULLABLE dns_name_copy(dns_name_t *NONNULL original);
-void dns_u48_to_wire_(dns_towire_state_t *NONNULL txn, uint64_t val, int line);
-#define dns_u48_to_wire(txn, val) dns_u48_to_wire_(txn, val, __LINE__)
-
-void dns_concatenate_name_to_wire_(dns_towire_state_t *NONNULL towire,
-                                   dns_name_t *NULLABLE labels_prefix,
-                                   const char *NULLABLE prefix, const char *NULLABLE suffix, int line);
-#define dns_concatenate_name_to_wire(txn, labels_prefix, prefix, suffix) \
-    dns_concatenate_name_to_wire_(txn, labels_prefix, prefix, suffix, __LINE__)
-
-const char *NONNULL dns_name_print_to_limit(dns_name_t *NONNULL name, dns_name_t *NULLABLE limit, char *NULLABLE buf,
-                                            size_t bufmax);
-const char *NONNULL dns_name_print(dns_name_t *NONNULL name, char *NONNULL buf, size_t bufmax);
-bool dns_labels_equal(const char *NONNULL label1, const char *NONNULL label2, size_t len);
-bool dns_names_equal_text(dns_label_t *NONNULL name1, const char *NONNULL name2);
-size_t dns_name_wire_length(dns_label_t *NONNULL name);
-size_t dns_name_to_wire_canonical(uint8_t *NONNULL buf, size_t max, dns_label_t *NONNULL name);
-dns_name_t *NULLABLE dns_pres_name_parse(const char *NONNULL pname);
-dns_name_t *NULLABLE dns_name_subdomain_of(dns_name_t *NONNULL name, dns_name_t *NONNULL domain);
-const char *NONNULL dns_rcode_name(int rcode);
-bool dns_keys_rdata_equal(dns_rr_t *NONNULL key1, dns_rr_t *NONNULL key2);
-
-/*!
- *  @brief
- *      Check if the IPv4 address represented by a 4-byte array is a link-local address.
- *
- *  @param bytes
- *      A bytes array whose length is 4, which represents an IPv4 address in the network byte order.
- *
- *  @result
- *      True if the IPv4 address is a link-local address, otherwise, false.
- */
-static inline bool is_ipv4_bytes_link_local(const uint8_t bytes[static const 4])
-{
-    return bytes[0] == 169 && bytes[1] == 254;
-}
-
-/*!
- *  @brief
- *      Check if the IPv4 address represented by a 4-byte array is a loopback address.
- *
- *  @param bytes
- *      A bytes array whose length is 4, which represents an IPv4 address in the network byte order.
- *
- *  @result
- *      True if the IPv4 address is a loopback address, otherwise, false.
- */
-static inline bool is_ipv4_bytes_loopback(const uint8_t bytes[static const 4])
-{
-    return bytes[0] == 127;
-}
-
-/*!
- *  @brief
- *      Check if the IPv4 address represented by a pointer to struct in_addr is a link-local address.
- *
- *  @param addr
- *      A pointer to struct in_addr structure.
- *
- *  @result
- *      True if the IPv4 address is a link-local address, otherwise, false.
- */
-static inline bool is_in_addr_link_local(const struct in_addr *const NONNULL addr)
-{
-    return is_ipv4_bytes_link_local((const uint8_t *)&addr->s_addr);
-}
-
-/*!
- *  @brief
- *      Check if the IPv4 address represented by a pointer to struct in_addr is a loopback address.
- *
- *  @param addr
- *      A pointer to struct in_addr structure.
- *
- *  @result
- *      True if the IPv4 address is a loopback address, otherwise, false.
- */
-static inline bool is_in_addr_loopback(const struct in_addr *const NONNULL addr)
-{
-    return is_ipv4_bytes_loopback((const uint8_t *)&addr->s_addr);
-}
-
-#endif // _DNS_MSG_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/dnssd-proxy.c b/ServiceRegistration/dnssd-proxy.c
deleted file mode 100644
index b15e9ab..0000000
--- a/ServiceRegistration/dnssd-proxy.c
+++ /dev/null
@@ -1,4634 +0,0 @@
-/* dnssd-proxy.c
- *
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- *
- * This is a Discovery Proxy module for the SRP gateway.
- *
- * The motivation here is that it makes sense to co-locate the SRP relay and the Discovery Proxy because
- * these functions are likely to co-exist on the same node, listening on the same port.  For homenet-style
- * name resolution, we need a DNS proxy that implements DNSSD Discovery Proxy for local queries, but
- * forwards other queries to an ISP resolver.  The SRP gateway is already expecting to do this.
- * This module implements the functions required to allow the SRP gateway to also do Discovery Relay.
- *
- * The Discovery Proxy relies on Apple's DNS-SD library and the mDNSResponder DNSSD server, which is included
- * in Apple's open source mDNSResponder package, available here:
- *
- *            https://opensource.apple.com/tarballs/mDNSResponder/
- */
-
-#ifndef __APPLE_USE_RFC_3542
-    #define __APPLE_USE_RFC_3542
-#endif // #ifndef __APPLE_USE_RFC_3542
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <stdarg.h>
-#ifdef IOLOOP_MACOS
-#include <AssertMacros.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#endif // #ifdef IOLOOP_MACOS
-
-#include "dns_sd.h"
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dso-utils.h"
-#include "dso.h"
-#include "srp-tls.h"
-#include "config-parse.h"
-#include "dnssd-proxy.h"
-#include "srp-tls.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "cti-services.h"
-#include "route.h"
-#include "srp-replication.h"
-#if SRP_FEATURE_NAT64
-#include "dns_sd_private.h"
-#include "nat64-macos.h"
-#endif
-
-#define RESPONSE_WINDOW 6 // in seconds.
-
-extern route_state_t *route_states;
-
-// When do we build dnssd-proxy?
-// 1. When we are integrating dnssd-proxy into srp-mdns-proxy: SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY == 1
-// 2. When we are building standalone dnssd-proxy: !defined(BUILD_SRP_MDNS_PROXY) || (BUILD_SRP_MDNS_PROXY == 0)
-// When do we not build dnssd-proxy?
-// 3. When we are building srp-mdns-proxy without dnssd-proxy: other than the two cases above.
-#if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY) || (!defined(BUILD_SRP_MDNS_PROXY) || (BUILD_SRP_MDNS_PROXY == 0))
-
-// Enumerate the list of interfaces, map them to interface indexes, give each one a name
-// Have a tree of subdomains for matching
-
-// Structures
-
-typedef struct interface_addr interface_addr_t;
-struct interface_addr {
-    interface_addr_t *next;
-    addr_t addr, mask;
-};
-
-typedef struct dp_interface dp_interface_t;
-struct dp_interface {
-    int ifindex;                            // The interface index (for use with sendmsg() and recvmsg().
-    bool no_push;                           // If true, don't set up DNS Push for this domain
-    char *NONNULL name;                     // The name of the interface
-    interface_addr_t *NULLABLE addresses;   // Addresses on this interface.
-};
-
-typedef struct hardwired hardwired_t;
-struct hardwired {
-    hardwired_t *NULLABLE next;
-    uint16_t type;
-    char *NONNULL name;
-    char *NONNULL fullname;
-    uint8_t *NULLABLE rdata;
-    uint16_t rdlen;
-};
-
-typedef struct question question_t;
-typedef struct answer answer_t;
-typedef struct served_domain served_domain_t;
-struct served_domain {
-    served_domain_t *NULLABLE next;             // Active configurations, used for identifying a domain that matches
-    char *NONNULL domain;                       // The domain name of the interface, represented as a text string.
-    char *NONNULL domain_ld;                    // The same name, with a leading dot (if_domain_lp == if_domain + 1)
-    dns_name_t *NONNULL domain_name;            // The domain name, parsed into labels.
-    hardwired_t *NULLABLE hardwired_responses;  // Hardwired responses for this interface.
-    dp_interface_t *NULLABLE interface;         // Interface to which this domain applies (may be NULL).
-    question_t *NULLABLE questions;             // Questions that have been asked in the served domain.
-};
-
-// Questions that aren't in a served domain
-question_t *NULLABLE questions_without_domain;
-
-// There are two ways that a dnssd_query_t can be created. One is that a DNS datagram comes in that's a DNS
-// query.  In this case, we create the query, ask the question, generate a single DNS response, send it, and
-// the dnssd query is finished. We could optimize retransmissions, but currently do not. UDP queries can
-// happen either over a TCP connection or a UDP connection--the behavior is the same in either case.  The
-// other way is that it can be a DNS Push subscribe. A DNS Push subscribe query is finished either when the
-// connection dies, or when we get a corresponding unsubscribe.
-
-// For DNS Push queries, there is an "activity" object which tracks a particular subscription. Each activity
-// can hold a reference to the comm_t. A disconnect from the comm_t should cancel all activities. Otherwise,
-// the lifecycle of activities should not affect the comm_t.
-
-// For DNS queries, a disconnect should cancel every query associated with the connection. This is complicated
-// by the fact that we are not tracking outstanding queries--the query survives because the dnssd_txn_t object
-// holds a reference to it; when the txn_t goes away, the connection will have no remaining references.
-
-// In order to make this work, dnssd_query_t objects are tracked per connection. Dnssd_query_t objects do not
-// hold a reference to their comm_t, but rather to their tracker.
-
-// When a connection drops, the tracker object gets a disconnect callback, which triggers it to cancel out any
-// remaining DNS transactions, and to cancel the associated DSO object. Cancelling the DSO object cancels all
-// of the activities on that object; each activity is a dnssd_query_t object. Consequently, the tracker does
-// not directly track DSO activities.
-
-// In order to follow RFC 7766, the tracker keeps an idle timer going. If no DNS messages have been received
-// on a connection for that amount of time, the tracker closes the connection; when the disconnect event arrives,
-// the tracker is collected. If there is a DSO object on the tracker, the tracker is not responsible for tracking
-// idle state.
-
-typedef struct dnssd_query dnssd_query_t;
-typedef struct dp_tracker {
-    int ref_count;
-    comm_t *connection;
-    dnssd_query_t *dns_queries;
-    dso_state_t *dso;
-    wakeup_t *idle_timeout;
-} dp_tracker_t;
-
-struct answer {
-    answer_t *next;                 // List of answers to a question.
-    char *fullname;                 // Name returned in callback.
-    uint8_t *rdata;                 // Rdata returned in callback (wire format).
-    uint32_t interface_index;       // Interface index returned in callback.
-    uint32_t ttl;                   // Time-to-live returned in callback (probably not useful for LLQ).
-    uint16_t rrtype;                // Resource record type returned in callback.
-    uint16_t rrclass;               // Resource record class returned in callback.
-    uint16_t rdlen;                 // Length of resource record data returned in callback.
-};
-
-struct question {
-    question_t *next;               // List of questions that are being asked.
-    served_domain_t *served_domain;
-    dnssd_query_t *queries;         // dnssd queries that are asking this question.
-    dnssd_txn_t *txn;
-    char *name;                     // The name we are looking up.
-    answer_t *answers;              // Answers this question has received.
-    int64_t start_time;             // When this question was started.
-    int ref_count;                  // Reference count.
-    uint32_t interface_index;       // Which interface the query should use.
-    uint16_t type;                  // The type.
-    uint16_t qclass;                // The class.
-    bool no_data;                   // True if "no such record" is received or all data gets removed
-};
-
-struct dnssd_query {
-    int ref_count;
-    dp_tracker_t *tracker;          // Tracks the connection that delivered this query.
-    dnssd_query_t *next;            // For DNS queries, tracks other queries on the same connection, if any.
-    wakeup_t *wakeup;
-    dns_name_pointer_t enclosing_domain_pointer;
-
-    message_t *question;
-    dso_state_t *dso;               // If this is a DNS Push query, the DSO state associated with it.
-    dso_activity_t *activity;
-    int serviceFlags;               // Service flags to use with this query.
-    bool is_edns0;
-    dns_towire_state_t towire;
-    uint8_t *p_dso_length;          // Where to store the DSO length just before we write out a push notification.
-    dns_wire_t *response;
-    size_t data_size;               // Size of the data payload of the response.
-    dnssd_query_t *question_next;   // Linked list of queries on the question this query is subscribed to.
-    question_t *question_asked;     // Question asked by this query pointing to a cache entry.
-};
-
-// Structure that is used to setup the mDNS discovery for dnssd-proxy.
-typedef struct dnssd_proxy_advertisements dnssd_proxy_advertisements_t;
-struct dnssd_proxy_advertisements {
-    wakeup_t *wakeup_timer;         // Used to setup a timer to advertise records repeatedly until it succeeds.
-    dnssd_txn_t *txn;               // Contains event loop.
-    DNSServiceRef service_ref;      // Shared DNSServiceRef for all registering operation.
-    DNSRecordRef ns_record_ref;     // Used to update the advertised NS record.
-    DNSRecordRef ptr_record_ref;    // Used to update the advertised PTR record.
-    char *domain_to_advertise;      // The domain to be advertised in NS and PTR records.
-};
-
-// Configuration file settings
-
-uint16_t udp_port;
-uint16_t tcp_port;
-uint16_t tls_port;
-const char *my_name = "discoveryproxy.home.arpa.";
-char *listen_addrs[MAX_ADDRS];
-int num_listen_addrs;
-char *publish_addrs[MAX_ADDRS];
-int num_publish_addrs;
-char *tls_cacert_filename;
-char *tls_cert_filename = "/etc/dnssd-proxy/server.crt";
-char *tls_key_filename = "/etc/dnssd-proxy/server.key";
-
-comm_t *listener[4 + MAX_ADDRS];
-int num_listeners;
-served_domain_t *served_domains;
-int num_dso_connections; // Number of connections from DNS Push clients
-
-static dnssd_proxy_advertisements_t advertisements;
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static CFStringRef sc_dynamic_store_key_host_name;
-static char my_name_buf[DNS_MAX_NAME_SIZE + 1];
-#endif // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-static char local_host_name[DNS_MAX_NAME_SIZE + 1];
-static char local_host_name_dot_local[DNS_MAX_NAME_SIZE + 1];
-
-#if THREAD_BORDER_ROUTER && SRP_FEATURE_SRP_COMBINED_DNSSD_PROXY
-extern char *thread_interface_name;
-#endif // THREAD_BORDER_ROUTER && SRP_FEATURE_COMBINED_DNSSD_PROXY
-
-// Globals
-
-const char push_subscription_activity_type[] = "push subscription";
-
-static const char local_suffix[] = ".local.";
-
-bool tls_fail = false; // Command line argument, for testing.
-
-// Macros
-
-#define LOCAL_ONLY_PSEUDO_INTERFACE "local only pseudo interface"
-#define ALL_LOCALS_PSEUDO_INTERFACE "all locally-discoverable services pseudo interface"
-#define THREAD_DOMAIN "thread.home.arpa."
-// "openthread." will change in the future once we have a way to get thread network ID
-#define THREAD_DOMAIN_WITH_ID "openthread." THREAD_DOMAIN
-#define DEFAULT_SERVICE_ARPA_DOMAIN "default.service.arpa."
-#define HOME_NET_DOMAIN "home.arpa."
-#define DOT_HOME_NET_DOMAIN ".home.arpa."
-#define LOCAL "local."
-#define DOT_LOCAL ".local."
-#define IPV4_REVERSE_LOOKUP_DOMAIN "in-addr.arpa."
-#define IPV6_REVERSE_LOOKUP_DOMAIN "ip6.arpa."
-#define SRV_TYPE_FOR_AUTOMATIC_BROWSING_DOMAIN "lb._dns-sd._udp"
-#define TOWIRE_CHECK(note, towire, func) { func; if ((towire)->error != 0 && failnote == NULL) failnote = (note); }
-#define BUSY_RETRY_DELAY_MS (5 * 60 * 1000) // Five minutes.
-#define MAX_DSO_CONNECTIONS 15 // Should be enough for a typical home network, assuming more hosts -> more BRs
-
-#define VALIDATE_TRACKER_CONNECTION_NON_NULL()                      \
-    do {                                                            \
-        if (query->tracker == NULL) {                               \
-            ERROR("query->tracker unexpectedly NULL!");             \
-            return;                                                 \
-        }                                                           \
-        if (query->tracker->connection == NULL) {                   \
-            ERROR("query->tracker->connection unexpectedly NULL!"); \
-            return;                                                 \
-        }                                                           \
-    } while (false)
-
-// Forward references
-
-static served_domain_t *NULLABLE
-new_served_domain(dp_interface_t *const NULLABLE interface, const char * NONNULL domain);
-
-static served_domain_t *NULLABLE
-find_served_domain(const char *const NONNULL domain);
-
-static bool
-string_ends_with(const char *const NONNULL str, const char *const NONNULL suffix);
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static served_domain_t *NONNULL
-add_new_served_domain_with_interface(const char *const NONNULL name,
-    const addr_t *const NULLABLE address, const addr_t *const NULLABLE mask);;
-
-static bool
-dnssd_hardwired_add_or_remove_address_in_domain(const char *const NONNULL name,
-    const char *const NONNULL domain_to_change, const addr_t *const NONNULL address, const bool add);
-
-static bool
-dnssd_hardwired_setup_dns_push_for_domain(served_domain_t *const NONNULL served_domain);
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-static bool
-start_timer_to_advertise(dnssd_proxy_advertisements_t *const NONNULL context,
-    const char *const NULLABLE domain_to_advertise, const uint32_t interval);
-
-static bool
-interface_process_addr_change(dp_interface_t *const NONNULL interface, const addr_t *const NONNULL address,
-                              const addr_t *const NONNULL mask, const enum interface_address_change event_type);
-
-// Functions
-
-// For debugging
-static wakeup_t *connection_dropper;
-extern dso_state_t *dso_connections;
-static void dp_drop_connections(void *UNUSED context);
-static void dns_push_callback(void *context, void *event_context, dso_state_t *dso, dso_event_type_t eventType);
-
-void
-dp_start_dropping(void)
-{
-    if (connection_dropper == NULL) {
-        connection_dropper = ioloop_wakeup_create();
-        if (connection_dropper == NULL) {
-            ERROR("can't create connection dropper.");
-            return;
-        }
-    }
-    ioloop_add_wake_event(connection_dropper, NULL, dp_drop_connections, NULL, 90 * 1000);
-}
-
-static void
-dp_drop_connections(void *UNUSED context)
-{
-    for (dso_state_t *dso = dso_connections; dso != NULL; dso = dso->next) {
-        if (dso->cb == dns_push_callback) {
-            dp_tracker_t *tracker = dso->context;
-            INFO("dropping connection for " PRI_S_SRP ".", dso->remote_name);
-            if (tracker->connection != NULL) {
-                ioloop_comm_cancel(tracker->connection);
-            }
-        }
-    }
-    dp_start_dropping();
-}
-
-static void
-dp_tracker_finalize(dp_tracker_t *tracker)
-{
-    // At this point tracker should have nothing attached to it that we need to get rid of, except maybe the
-    // wakeup timer.
-    if (tracker->idle_timeout != NULL) {
-        ioloop_wakeup_release(tracker->idle_timeout);
-    }
-    // The only case where tracker->connection should still exist at this point is when the connection turned
-    // out to be an srp replication connection.
-    if (tracker->connection) {
-        ioloop_comm_release(tracker->connection);
-    }
-    free(tracker);
-}
-
-// The answer_finalize function frees name, answer data structure and rdata
-static void
-answer_free(answer_t *answer)
-{
-    if (answer != NULL) {
-        free(answer->fullname);
-        free(answer);
-    }
-}
-
-static void
-question_free(question_t *question)
-{
-    if (question != NULL) {
-        free(question->name);
-        free(question);
-    }
-}
-
-// The finalize function will deallocate answers associated with the question,
-// remove question from the question list and deallocate the question.
-static void
-dp_question_finalize(question_t *question)
-{
-    INFO("dp_question_finalize on type %d class %d " PRI_S_SRP,
-         question->type, question->qclass, question->name);
-    // De-allocate answers
-    answer_t *answer = question->answers;
-    answer_t *next;
-    while (answer != NULL) {
-        next = answer->next;
-        answer_free(answer);
-        answer = next;
-    }
-    question->answers = NULL;
-    if (question->txn != NULL) {
-        ioloop_dnssd_txn_cancel(question->txn);
-        ioloop_dnssd_txn_release(question->txn);
-        question->txn = NULL;
-    }
-    // De-allocate question and de-link from cache
-    question_t **questions, *q_cur;
-    if (question->served_domain != NULL) {
-        questions = &question->served_domain->questions;
-    } else {
-        questions = &questions_without_domain;
-    }
-    while (*questions != NULL ) {
-        q_cur = *questions;
-        if (q_cur == question) {
-            *questions = q_cur->next;
-            question_free(q_cur);
-            break;
-        } else {
-            questions = &q_cur->next;
-        }
-    }
-}
-
-// De-link the query from the question cache
-// the query will be freed in the caller
-static void
-dp_question_cache_remove_query(dnssd_query_t *query)
-{
-    question_t *question = query->question_asked;
-    dnssd_query_t **pptr = &(question->queries);
-    dnssd_query_t *cquery;
-    while (*pptr != NULL) {
-        cquery = *pptr;
-        if (cquery == query) {
-            *pptr = cquery->question_next;
-            RELEASE_HERE(query->question_asked, dp_question_finalize);
-            query->question_asked = NULL;
-            return;
-        } else {
-            pptr = &cquery->question_next;
-        }
-    }
-}
-
-// Called when the last reference on the query has been released.
-static void
-dnssd_query_finalize(void *context)
-{
-    dnssd_query_t *query = context;
-    INFO("dnssd_query_finalize on " PRI_S_SRP PUB_S_SRP,
-         query->question_asked == NULL ? "<null>" : query->question_asked->name,
-         query->question_asked == NULL ? "" : ((query->question_asked->served_domain
-         ? (query->question_asked->served_domain->interface ? DOT_LOCAL : query->question_asked->served_domain->domain_ld)
-         : "")));
-    if (query->tracker != NULL) {
-        RELEASE_HERE(query->tracker, dp_tracker_finalize);
-    }
-    if (query->question != NULL) {
-        ioloop_message_release(query->question);
-    }
-    if (query->wakeup != NULL) {
-        ioloop_wakeup_release(query->wakeup);
-    }
-    if (query->response != NULL) {
-        free(query->response);
-    }
-
-    // remove query from the list of queries that have asked this question
-    dp_question_cache_remove_query(query);
-    query->question_asked = NULL;
-
-    free(query);
-}
-
-static void
-dp_tracker_context_release(void *context)
-{
-    dp_tracker_t *tracker = context;
-    RELEASE_HERE(tracker, dp_tracker_finalize);
-}
-
-static void
-dp_tracker_idle(void *context)
-{
-    dp_tracker_t *tracker = context;
-    // Shouldn't be NULL.
-    if (tracker->connection != NULL) {
-        comm_t *connection = tracker->connection;
-        INFO("tracker for connection " PRI_S_SRP " has gone idle.", tracker->connection->name);
-
-        // If the connection is already disconnected, it's already released its reference to the tracker. If not,
-        // the release below will release tracker as a side effect. So in case tracker survives, clear the
-        // connection pointer.
-        tracker->connection = NULL;
-        // The POSIX ioloop just hands us the "listener", which we do not want to cancel.
-        if (!connection->is_listener) {
-            ioloop_comm_cancel(connection);
-        }
-        ioloop_comm_release(connection);
-    }
-}
-
-static void
-dp_tracker_idle_after(dp_tracker_t *tracker, int seconds, dnssd_query_t *query)
-{
-    if (tracker->connection != NULL && !tracker->connection->is_listener &&
-        tracker->dso == NULL && (query == NULL ||
-                                 (tracker->dns_queries == NULL ||
-                                  (tracker->dns_queries == query && query->next == NULL))))
-    {
-        if (tracker->idle_timeout == NULL) {
-            tracker->idle_timeout = ioloop_wakeup_create();
-        }
-        if (tracker->idle_timeout == NULL) {
-            ERROR("no memory for idle timeout");
-        } else {
-            ioloop_add_wake_event(tracker->idle_timeout, tracker, dp_tracker_idle, NULL, seconds * MSEC_PER_SEC);
-        }
-    }
-}
-
-// Called at any time (prior to release!) to cancel a query.
-static void
-dnssd_query_cancel(dnssd_query_t *query)
-{
-    if (query->wakeup != NULL) {
-        ioloop_wakeup_release(query->wakeup);
-        query->wakeup = NULL;
-    }
-    if (query->tracker != NULL) {
-        dp_tracker_t *tracker = query->tracker;
-
-        // If we have a connection, and we've become idle, we need to set an idle timer and disconnect when
-        // it goes off. If tracker->dso is not null, the DSO engine handles idle timeouts. If tracker is
-        // tracking more queries than this one, we don't need an idle timeout, because we're not
-        // idle. Otherwise, set up an idle timeout. This doesn't apply to POSIX udp listeners.
-        dp_tracker_idle_after(tracker, 15, query);
-
-        if (query->dso == NULL) {
-            dnssd_query_t **qp = &tracker->dns_queries;
-            bool matched = false;
-            while (*qp != NULL) {
-                if (*qp == query) {
-                    *qp = query->next;
-                    matched = true;
-                    break;
-                } else {
-                    qp = &(*qp)->next;
-                }
-            }
-            // Release this query's reference to the tracker
-            RELEASE_HERE(tracker, dp_tracker_finalize);
-            query->tracker = NULL;
-
-            if (matched) {
-                // The tracker was holding a reference to the query.
-                RELEASE_HERE(query, dnssd_query_finalize);
-            }
-            // Query is now potentially invalid.
-        } else {
-            // Query is holding a reference to the tracker, but the tracker isn't holding a reference to the
-            // query--the activity is. So dropping the activity may or may not finalize the query, but I think
-            // in practice will always finalize it. Just in case, though, null out the tracker now, since we
-            // can't safely null it out later.
-            query->tracker = NULL;
-
-            // For DNS Push queries, drop the activity, which will release the query.
-            if (query->activity != NULL && query->dso != NULL) {
-                dso_activity_t *activity = query->activity;
-                dso_state_t *dso = query->dso;
-                query->activity = NULL;
-                dso_drop_activity(dso, activity);
-            }
-            // Now release the reference the query had on the tracker, which may or may not finalize the tracker,
-            // depending on whether the connection is still alive.
-            RELEASE_HERE(tracker, dp_tracker_finalize);
-        }
-    }
-    // We can't touch query or tracker here, just in case.
-}
-
-static void
-dp_query_track(dp_tracker_t *tracker, dnssd_query_t *query)
-{
-    dnssd_query_t **qp = &tracker->dns_queries;
-
-    while (*qp != NULL) {
-        if (*qp == query) {
-            ERROR("query is already being tracked.");
-            return;
-        }
-        qp = &(*qp)->next;
-    }
-    *qp = query;
-    RETAIN_HERE(query);
-}
-
-static void
-dp_tracker_disconnected(comm_t *UNUSED connection, void *context, int UNUSED error)
-{
-    dp_tracker_t *tracker = context;
-    dnssd_query_t *dns_queries = tracker->dns_queries, **qp, *query;
-    comm_t *tracker_connection = tracker->connection;
-    tracker->connection = NULL;
-    tracker->dns_queries = NULL;
-
-    INFO("tracker %p queries %p dso %p comm %p", tracker, dns_queries, tracker->dso, tracker_connection);
-
-    // If there is a DSO state outstanding on the tracker, cancel any activities connected to it.
-    if (tracker->dso != NULL) {
-        dso_activity_t *activity = tracker->dso->activities;
-        while (activity != NULL) {
-            dso_drop_activity(tracker->dso, tracker->dso->activities);
-            // Failsafe in case dso_drop_activity for some reason doesn't drop the activity.
-            if (tracker->dso->activities == activity) {
-                break;
-            }
-            activity = tracker->dso->activities;
-        }
-        dso_state_cancel(tracker->dso);
-        // Reduce the number of outstanding connections (should never go below zero).
-        if (--num_dso_connections < 0) {
-            FAULT("dso connection count went negative");
-            num_dso_connections = 0;
-        } else {
-            INFO("dso connection count dropped: %d", num_dso_connections);
-        }
-        tracker->dso = NULL;
-    }
-
-    // We probably still have the connection object at this point, so we should release it, which could
-    // in turn finalize the tracker.
-    if (tracker_connection != NULL) {
-        ioloop_comm_release(tracker_connection);
-    }
-
-    // If dns_queries is non-null, tracker still exists, but it might go away when we cancel the last
-    // query.
-    qp = &dns_queries;
-    while (*qp != NULL) {
-        query = *qp;
-        *qp = query->next;
-        RELEASE_HERE(query, dnssd_query_finalize);
-    }
-}
-
-static void
-dnssd_question_close_callback(void *context, int status)
-{
-    question_t *question = context;
-
-    ERROR("DNSServiceProcessResult on %s%s returned %d",
-          question->name, (question->served_domain != NULL
-          ? (question->served_domain->interface != NULL ? DOT_LOCAL : question->served_domain->domain_ld)
-          : ""), status);
-    dnssd_query_t *next, *query = question->queries;
-    while (query != NULL) {
-        next = query->question_next;
-        dnssd_query_cancel(query);
-        query = next;
-    }
-
-    if (question->txn != NULL) {
-        ioloop_dnssd_txn_cancel(question->txn);
-        ioloop_dnssd_txn_release(question->txn);
-        question->txn = NULL;
-    }
-}
-
-static void
-dns_push_cancel(dso_activity_t *activity)
-{
-    dnssd_query_t *query = (dnssd_query_t *)activity->context;
-    INFO(PUB_S_SRP, activity->name);
-    // We can either get here because the dso object is being finalized, or because the activity is being dropped.
-    // In the former case, we need to cancel the query. In the latter case, we've been called as a result of
-    // dnssd_query_cancel calling dso_drop_activity. dnssd_query_cancel sets query->activity to NULL before dropping
-    // it, so we mustn't call back in to dnssd_query_cancel.
-    if (query->activity != NULL) {
-        query->activity = NULL;
-        dnssd_query_cancel(query);
-    }
-    // The activity held a reference to the query.
-    RELEASE_HERE(query, dnssd_query_finalize);
-}
-
-static void
-dp_tracker_not_idle(dp_tracker_t *tracker)
-{
-    if (tracker->idle_timeout) {
-        ioloop_cancel_wake_event(tracker->idle_timeout);
-    }
-}
-
-static served_domain_t *
-dp_served(dns_name_t *name, char *buf, size_t bufsize)
-{
-    served_domain_t *sdt;
-    dns_label_t *lim;
-
-    for (sdt = served_domains; sdt; sdt = sdt->next) {
-        if ((lim = dns_name_subdomain_of(name, sdt->domain_name))) {
-            dns_name_print_to_limit(name, lim, buf, bufsize);
-            return sdt;
-        }
-    }
-    return NULL;
-}
-
-static bool
-is_in_local_domain(const dns_name_t *const NONNULL name)
-{
-    const dns_label_t *prev_root_label;
-    const dns_label_t *root_label;
-
-    for (prev_root_label = NULL, root_label = name;
-         root_label->next != NULL;
-         prev_root_label = root_label, root_label = root_label->next)
-        ;
-
-    if (prev_root_label == NULL) {
-        return false;
-    }
-
-#define LOCAL_DOMAIN_LABEL "local"
-    if (prev_root_label->len != strlen(LOCAL_DOMAIN_LABEL)) {
-        return false;
-    }
-
-    if (!dns_labels_equal(prev_root_label->data, LOCAL_DOMAIN_LABEL, strlen(LOCAL_DOMAIN_LABEL))) {
-        return false;
-    }
-#undef LOCAL_DOMAIN_LABEL
-
-    return true;
-}
-
-// Utility function to find "local" on the end of a string of labels.
-static bool
-truncate_local(dns_name_t *name)
-{
-    dns_label_t *lp, *prev, *prevprev;
-
-    prevprev = prev = NULL;
-    // Find the root label.
-    for (lp = name; lp && lp->len; lp = lp->next) {
-        prevprev = prev;
-        prev = lp;
-    }
-    if (lp && prev && prevprev) {
-        if (prev->len == 5 && dns_labels_equal(prev->data, "local", 5)) {
-            dns_name_free(prev);
-            prevprev->next = NULL;
-            return true;
-        }
-    }
-    return false;
-}
-
-static bool
-dp_query_add_data_to_response(dnssd_query_t *query, const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                              uint16_t rdlen, const void *rdata, int32_t ttl, const bool hardwired_response)
-{
-    bool record_added;
-    dns_towire_state_t *towire = &query->towire;
-    const char *failnote = NULL;
-    const uint8_t *rd = rdata;
-    char pbuf[DNS_MAX_NAME_SIZE + 1];
-    char rbuf[DNS_MAX_NAME_SIZE + 1];
-    uint8_t *revert = query->towire.p; // Remember where we were in case there's no room.
-
-    // Only do the translation if:
-    // 1. We serve the domain.
-    // 2. The response we will add does not come from our hardwired response set.
-    const bool translate = (query->question_asked->served_domain != NULL) && (!hardwired_response);
-
-    if (rdlen == 0) {
-        INFO("Eliding zero-length response for " PRI_S_SRP " %d %d", fullname, rrtype, rrclass);
-        record_added = false;
-        goto exit;
-    }
-    // Don't send A records for 127.* nor AAAA records for ::1
-    if (rrtype == dns_rrtype_a && rdlen == 4) {
-        // Should use IN_LINKLOCAL and IN_LOOPBACK macros here, but for some reason they are not present on
-        // OpenWRT.
-        if (rd[0] == 127) {
-            IPv4_ADDR_GEN_SRP(rd, rd_buf);
-            INFO("Eliding localhost response for " PRI_S_SRP ": " PRI_IPv4_ADDR_SRP, fullname,
-                  IPv4_ADDR_PARAM_SRP(rd, rd_buf));
-            record_added = false;
-            goto exit;
-        }
-        if (rd[0] == 169 && rd[1] == 254) {
-            IPv4_ADDR_GEN_SRP(rd, rd_buf);
-            INFO("Eliding link-local response for " PRI_S_SRP ": " PRI_IPv4_ADDR_SRP, fullname,
-                 IPv4_ADDR_PARAM_SRP(rd, rd_buf));
-            record_added = false;
-            goto exit;
-        }
-    } else if (rrtype == dns_rrtype_aaaa && rdlen == 16) {
-        struct in6_addr addr = *(struct in6_addr *)rdata;
-        if (IN6_IS_ADDR_LOOPBACK(&addr)) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(rdata, rdata_buf);
-            INFO("Eliding localhost response for " PRI_S_SRP ": " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 fullname, SEGMENTED_IPv6_ADDR_PARAM_SRP(rdata, rdata_buf));
-            record_added = false;
-            goto exit;
-        }
-        if (IN6_IS_ADDR_LINKLOCAL(&addr)) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(rdata, rdata_buf);
-            INFO("Eliding link-local response for " PRI_S_SRP ": " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 fullname, SEGMENTED_IPv6_ADDR_PARAM_SRP(rdata, rdata_buf));
-            record_added = false;
-            goto exit;
-        }
-    }
-    INFO("survived for rrtype %d rdlen %d", rrtype, rdlen);
-
-    // Rewrite the domain if it's .local.
-    if (query->question_asked->served_domain != NULL) {
-        TOWIRE_CHECK("concatenate_name_to_wire", towire,
-                     dns_concatenate_name_to_wire(towire, NULL, query->question_asked->name, query->question_asked->served_domain->domain));
-        INFO(PUB_S_SRP " answer:  type %02d class %02d " PRI_S_SRP "." PRI_S_SRP, query->dso != NULL ? "PUSH" : "DNS ",
-             rrtype, rrclass, query->question_asked->name, query->question_asked->served_domain->domain);
-    } else {
-        TOWIRE_CHECK("compress_name_to_wire", towire, dns_concatenate_name_to_wire(towire, NULL, NULL, query->question_asked->name));
-        INFO(PUB_S_SRP " answer:  type %02d class %02d " PRI_S_SRP " (p)",
-             query->dso != NULL ? "push" : " dns", rrtype, rrclass, query->question_asked->name);
-    }
-    TOWIRE_CHECK("rrtype", towire, dns_u16_to_wire(towire, rrtype));
-    TOWIRE_CHECK("rrclass", towire, dns_u16_to_wire(towire, rrclass));
-    TOWIRE_CHECK("ttl", towire, dns_ttl_to_wire(towire, ttl));
-
-    // If necessary, correct domain names inside of rrdata.
-    dns_rr_t answer;
-    dns_name_t *name;
-    unsigned offp = 0;
-
-    answer.type = rrtype;
-    answer.qclass = rrclass;
-    if (dns_rdata_parse_data(&answer, rdata, &offp, rdlen, rdlen, 0)) {
-        switch(rrtype) {
-            case dns_rrtype_cname:
-            case dns_rrtype_ptr:
-            case dns_rrtype_ns:
-            case dns_rrtype_md:
-            case dns_rrtype_mf:
-            case dns_rrtype_mb:
-            case dns_rrtype_mg:
-            case dns_rrtype_mr:
-            case dns_rrtype_nsap_ptr:
-            case dns_rrtype_dname:
-                name = answer.data.ptr.name;
-                TOWIRE_CHECK("rdlength begin", towire, dns_rdlength_begin(towire));
-                break;
-            case dns_rrtype_srv:
-                name = answer.data.srv.name;
-                TOWIRE_CHECK("rdlength begin", towire, dns_rdlength_begin(towire));
-                TOWIRE_CHECK("answer.data.srv.priority", towire, dns_u16_to_wire(towire, answer.data.srv.priority));
-                TOWIRE_CHECK("answer.data.srv.weight", towire, dns_u16_to_wire(towire, answer.data.srv.weight));
-                TOWIRE_CHECK("answer.data.srv.port", towire, dns_u16_to_wire(towire, answer.data.srv.port));
-                break;
-            default:
-                INFO("record type %d not translated", rrtype);
-                dns_rrdata_free(&answer);
-                goto raw;
-        }
-
-        dns_name_print(name, rbuf, sizeof rbuf);
-
-        if (translate && is_in_local_domain(name)) {
-            // If the response requires the translation from <served domain> to ".local." and the response ends in
-            // ".local.", truncate it.
-            truncate_local(name);
-            dns_name_print(name, pbuf, sizeof pbuf);
-            TOWIRE_CHECK("concatenate_name_to_wire 2", towire,
-                         dns_concatenate_name_to_wire(towire, name, NULL, query->question_asked->served_domain->domain));
-            INFO("translating " PRI_S_SRP " to " PRI_S_SRP " . " PRI_S_SRP, rbuf, pbuf, query->question_asked->served_domain->domain);
-        } else {
-            TOWIRE_CHECK("concatenate_name_to_wire 2", towire,
-                         dns_concatenate_name_to_wire(towire, name, NULL, NULL));
-            INFO("compressing " PRI_S_SRP, rbuf);
-        }
-
-        dns_name_free(name);
-        dns_rdlength_end(towire);
-    } else {
-        ERROR("dp_query_add_data_to_response: rdata from mDNSResponder didn't parse!!");
-    raw:
-        TOWIRE_CHECK("rdlen", towire, dns_u16_to_wire(towire, rdlen));
-        TOWIRE_CHECK("rdata", towire, dns_rdata_raw_data_to_wire(towire, rdata, rdlen));
-    }
-
-    if (towire->truncated || failnote) {
-        ERROR("RR ADD FAIL: dp_query_add_data_to_response: " PUB_S_SRP, failnote);
-        query->towire.p = revert;
-        record_added = false;
-        goto exit;
-    }
-
-    record_added = true;
-exit:
-    return record_added;
-}
-
-static void
-dnssd_hardwired_add(served_domain_t *sdt,
-                    const char *name, const char *domain, size_t rdlen, const uint8_t *rdata, uint16_t type)
-{
-    hardwired_t *hp, **hrp;
-    size_t namelen = strlen(name);
-    size_t domainlen = strlen(domain);
-    size_t total = sizeof *hp;
-    uint8_t *trailer;
-    total += rdlen; // Space for RDATA
-    total += namelen; // Space for name
-    total += 1; // NUL
-    total += namelen;// space for FQDN
-    total += domainlen;
-    total += 1; // NUL
-
-    hp = calloc(1, total + 4);
-    if (hp == NULL) {
-        ERROR("no memory for %s %s", name, domain);
-        return;
-    }
-    trailer = ((uint8_t *)hp) + total;
-    memcpy(trailer, "abcd", 4);
-    hp->rdata = (uint8_t *)(hp + 1);
-    hp->rdlen = rdlen;
-    memcpy(hp->rdata, rdata, rdlen);
-    hp->name = (char *)hp->rdata + rdlen;
-    memcpy(hp->name, name, namelen);
-    hp->name[namelen] = '\0';
-    hp->fullname = hp->name + namelen + 1;
-    if (namelen != 0) {
-        snprintf(hp->fullname, namelen + domainlen + 1, "%s%s", name, domain);
-    } else {
-        memcpy(hp->fullname, domain, domainlen);
-        hp->fullname[domainlen] = '\0';
-    }
-    if (hp->fullname + strlen(hp->fullname) + 1 != (char *)hp + total) {
-        ERROR("%p != %p", hp->fullname + strlen(hp->fullname) + 1, ((char *)hp) + total);
-        return;
-    }
-    if (memcmp(trailer, "abcd", 4)) {
-        ERROR("ran off the end.");
-        return;
-    }
-    hp->type = type;
-    hp->next = NULL;
-
-    // Store this new hardwired_t at the end of the list unless a hardwired_t with the same name
-    // is already on the list.   If it is, splice it in.
-    for (hrp = &sdt->hardwired_responses; *hrp != NULL; hrp = &(*hrp)->next) {
-        hardwired_t *old = *hrp;
-        if (old->type != hp->type) {
-            continue;
-        }
-        if (strcasecmp(old->fullname, hp->fullname) != 0) {
-            continue;
-        }
-        // The same name and type
-        bool superseded;
-        switch (type) {
-            case dns_rrtype_a:
-            case dns_rrtype_aaaa:
-            case dns_rrtype_ns:
-            case dns_rrtype_ptr:
-                superseded = false;
-                break;
-            default:
-                // dns_rrtype_soa
-                // dns_rrtype_srv
-                superseded = true;
-                break;
-        }
-
-        if (superseded) {
-            INFO("superseding " PRI_S_SRP " name " PRI_S_SRP " type %d rdlen %d", old->fullname,
-                 old->name, old->type, old->rdlen);
-            hp->next = old->next;
-            free(old);
-        } else {
-            INFO("inserting before " PRI_S_SRP " name " PRI_S_SRP " type %d rdlen %d", old->fullname,
-                 old->name, old->type, old->rdlen);
-            hp->next = old;
-        }
-        break;
-    }
-    *hrp = hp;
-
-    INFO("fullname " PRI_S_SRP " name " PRI_S_SRP " type %d rdlen %d",
-         hp->fullname, hp->name, hp->type, hp->rdlen);
-}
-
-static bool
-dnssd_hardwired_remove_record(served_domain_t *const NONNULL sdt, const char *const NONNULL name, const char *const NONNULL domain, size_t rdlen,
-    const void *const NULLABLE rdata, uint16_t type)
-{
-    bool removed;
-    hardwired_t *prev = NULL;
-    hardwired_t *current;
-    char full_name[DNS_MAX_NAME_SIZE + 1];
-
-    int bytes_written = snprintf(full_name, sizeof(full_name), "%s%s", name, domain);
-    require_action_quiet(bytes_written > 0 && (size_t)bytes_written < sizeof(full_name), exit, removed = false;
-        ERROR("snprintf truncates the string - name length: %zu, domain length: %zu, buffer length: %zu",
-            strlen(name), strlen(domain), sizeof(full_name))
-    );
-
-    for (current = sdt->hardwired_responses; current != NULL; prev = current, current = current->next) {
-        if (current->type != type) {
-            continue;
-        }
-        if (rdata != NULL && current->rdlen != rdlen) {
-            continue;
-        }
-        if (strcasecmp(current->fullname, full_name) != 0) {
-            continue;
-        }
-        if (rdata != NULL && memcmp(current->rdata, rdata, rdlen) != 0) {
-            continue;
-        }
-        // record found
-        break;
-    }
-    require_action_quiet(current != NULL, exit, removed = false;
-        ERROR("no matching hardwired_t found - record name: " PUB_S_SRP ", record type: %d", full_name, type));
-
-    if (prev != NULL) {
-        prev->next = current->next;
-    } else {
-        sdt->hardwired_responses = current->next;
-    }
-    free(current);
-
-    removed = true;
-exit:
-    return removed;
-}
-
-static bool
-dnssd_hardwired_add_or_remove_addr_record(served_domain_t *const NONNULL sdt, const addr_t *const NONNULL addr,
-    const char *const NONNULL name, bool add)
-{
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-    bool succeeded;
-
-    memset(&towire, 0, sizeof towire);
-    towire.message = &wire;
-    towire.p = wire.data;
-    towire.lim = towire.p + sizeof wire.data;
-
-    const void *rdata_ptr;
-    size_t addr_len;
-    uint16_t addr_type;
-    if (addr->sa.sa_family == AF_INET) {
-        rdata_ptr = &addr->sin.sin_addr;
-        addr_len = sizeof(addr->sin.sin_addr);
-        addr_type = dns_rrtype_a;
-    } else { // addr.sa.sa_family == AF_INET6
-        rdata_ptr = &addr->sin6.sin6_addr;
-        addr_len = sizeof(addr->sin6.sin6_addr);
-        addr_type = dns_rrtype_aaaa;
-    }
-    dns_rdata_raw_data_to_wire(&towire, rdata_ptr, addr_len);
-
-    if (add) {
-        dnssd_hardwired_add(sdt, name, name[0] == '\0' ? sdt->domain : sdt->domain_ld, towire.p - wire.data, wire.data,
-            addr_type);
-        succeeded = true;
-    } else {
-        succeeded = dnssd_hardwired_remove_record(sdt, name,  name[0] == '\0' ? sdt->domain : sdt->domain_ld,
-            towire.p - wire.data, wire.data, addr_type);
-    }
-
-    return succeeded;
-}
-
-static bool
-dnssd_hardwired_add_or_remove_address_in_domain(const char *const NONNULL name,
-    const char *const NONNULL domain_to_change, const addr_t *const NONNULL address, const bool add)
-{
-    bool succeeded;
-
-    served_domain_t *served_domain = find_served_domain(domain_to_change);
-    require_action_quiet(served_domain != NULL, exit, succeeded = false;
-        ERROR("could not find served domain with the specified domain name - domain name: " PRI_S_SRP, domain_to_change)
-    );
-
-    succeeded = dnssd_hardwired_add_or_remove_addr_record(served_domain, address, name, add);
-    require_action_quiet(succeeded, exit, succeeded = false;
-        ERROR("failed to " PUB_S_SRP " address record - domain name: " PRI_S_SRP,
-            domain_to_change, add ? "add" : "remove")
-    );
-
-exit:
-    return succeeded;
-}
-
-static bool
-dnssd_hardwired_generate_ptr_name(const addr_t *const NONNULL addr, const addr_t *const NONNULL mask,
-                                  char *name_buf, size_t buf_size)
-{
-    char *name_ptr = name_buf;
-    const char *const name_limit = name_ptr + buf_size;
-    int bytes_written;
-    bool succeeded;
-
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    bytes_written = snprintf(name_ptr, name_limit - name_ptr, SRV_TYPE_FOR_AUTOMATIC_BROWSING_DOMAIN);
-    require_action_quiet(bytes_written > 0 && bytes_written < name_limit - name_ptr, exit, succeeded = false;
-        ERROR("snprintf truncates the string - bytes_written: %d, limit: %zd", bytes_written, name_limit - name_ptr));
-    name_ptr += bytes_written;
-
-
-    if (addr->sa.sa_family == AF_INET) {
-        const uint32_t subnet = (ntohl(addr->sin.sin_addr.s_addr) & ntohl(mask->sin.sin_addr.s_addr));
-        bytes_written = snprintf(name_ptr, name_limit - name_ptr, ".%u.%u.%u.%u",
-            subnet & 0xFFU, (subnet >> 8) & 0xFFU, (subnet >> 16) & 0xFFU, (subnet >> 24) & 0xFFU);
-        require_action(bytes_written > 0 && bytes_written < name_limit - name_ptr, exit, succeeded = false);
-        // Remember to increase the name_ptr by bytes_written bytes if name_ptr is used later.
-
-    } else if (addr->sa.sa_family == AF_INET6) {
-        const uint8_t *const addr_bytes = addr->sin6.sin6_addr.s6_addr;
-        const uint8_t *const mask_bytes = mask->sin6.sin6_addr.s6_addr;
-        for (int i = 15; i >= 0; i--) {
-            for (int shift = 0; shift < 8; shift += 4) {
-                bytes_written = snprintf(name_ptr, name_limit - name_ptr, ".%x",
-                    (addr_bytes[i] >> shift) & (mask_bytes[i] >> shift) & 15);
-                require_action_quiet(bytes_written > 0 && bytes_written < name_limit - name_ptr, exit, succeeded = false;
-                    ERROR("snprintf truncates the string - bytes_written: %d, limit: %zd",
-                        bytes_written, name_limit - name_ptr)
-                );
-                name_ptr += bytes_written;
-            }
-        }
-
-    } else {
-        FAULT("skipping address type other than IPv4/IPv6 - type: %u", addr->sa.sa_family);
-        succeeded = false;
-        goto exit;
-    }
-
-    succeeded = true;
-exit:
-    return succeeded;
-}
-
-static bool
-dnssd_hardwired_add_or_remove_ptr_record(served_domain_t *const NONNULL sdt, const addr_t *const NONNULL addr,
-    const addr_t *const NONNULL mask, bool add)
-{
-    char name[DNS_MAX_NAME_SIZE + 1];
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-    bool succeeded;
-
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    succeeded = dnssd_hardwired_generate_ptr_name(addr, mask, name, sizeof(name));
-    if (!succeeded) {
-        INFO("address is not eligible to construct PTR record");
-        goto exit;
-    }
-
-    for (served_domain_t *if_domain = served_domains; if_domain != NULL; if_domain = if_domain->next) {
-        if (if_domain->interface == NULL || if_domain->interface->ifindex == 0) {
-            continue;
-        }
-        RESET;
-        INFO(PUB_S_SRP " PTR from " PRI_S_SRP " to " PRI_S_SRP, add ? "Adding" : "Removing", name, if_domain->domain);
-        dns_full_name_to_wire(NULL, &towire, if_domain->domain);
-
-        if (add) {
-            dnssd_hardwired_add(sdt, name, sdt->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_ptr);
-            succeeded = true;
-        } else {
-            succeeded = dnssd_hardwired_remove_record(sdt, name, sdt->domain_ld, towire.p - wire.data, wire.data,
-                dns_rrtype_ptr);
-        }
-    }
-
-exit:
-    return succeeded;
-}
-
-static bool
-dnssd_hardwired_add_or_remove_ptr_in_domain(const char *const NONNULL domain_to_change,
-    const addr_t *const NONNULL address, const addr_t *const NONNULL mask, const bool add)
-{
-    bool succeeded;
-
-    served_domain_t *served_domain = find_served_domain(domain_to_change);
-    require_action_quiet(served_domain != NULL, exit, succeeded = false;
-        ERROR("could not find served domain with the specified domain name - domain name: " PRI_S_SRP, domain_to_change)
-    );
-
-    succeeded = dnssd_hardwired_add_or_remove_ptr_record(served_domain, address, mask, add);
-    require_action_quiet(succeeded, exit, succeeded = false;
-        ERROR("failed to " PUB_S_SRP " address record - domain name: " PRI_S_SRP,
-            add ? "adding" : "removing", domain_to_change)
-    );
-
-exit:
-    return succeeded;
-}
-
-static bool
-is_valid_address_to_publish(const addr_t *const NONNULL address)
-{
-    bool is_valid = true;
-
-    if (address->sa.sa_family == AF_INET) {
-        const struct in_addr *const ipv4_address = &(address->sin.sin_addr);
-        const bool is_linklocal = is_in_addr_link_local(ipv4_address);
-        const bool is_loopback = is_in_addr_loopback(ipv4_address);
-
-        if (is_linklocal || is_loopback) {
-            IPv4_ADDR_GEN_SRP(&ipv4_address, ipv4_address_buf);
-            INFO("ignoring the address for interface - address: " PRI_IPv4_ADDR_SRP ", address type: " PUB_S_SRP ".",
-                IPv4_ADDR_PARAM_SRP(&ipv4_address, ipv4_address_buf), is_linklocal ? "link local" : "loopback");
-            is_valid = false;
-        }
-
-    } else if (address->sa.sa_family == AF_INET6) {
-        const struct in6_addr *const ipv6_address = &(address->sin6.sin6_addr);
-        const bool is_linklocal = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
-        const bool is_loopback = IN6_IS_ADDR_LOOPBACK(ipv6_address);
-
-        if (is_linklocal || is_loopback) {
-            IPv6_ADDR_GEN_SRP(ipv6_address->s6_addr, ipv6_address_buf);
-            INFO("ignoring the address for interface - address: " PRI_IPv6_ADDR_SRP ", address type: " PUB_S_SRP ".",
-                IPv6_ADDR_PARAM_SRP(ipv6_address->s6_addr, ipv6_address_buf), is_linklocal ? "link local" : "loopback");
-            is_valid = false;
-        }
-
-    } else {
-        // It is possible that MAC address is added for the interface, so ignore it.
-        INFO("Non IPv4/IPv6 address added for the interface - sa_family: %u", address->sa.sa_family);
-        is_valid = false;
-    }
-
-    return is_valid;
-}
-
-static bool
-dnssd_hardwired_process_addr_change(const addr_t *const NONNULL addr, const addr_t *const NONNULL mask, const bool add)
-{
-    bool succeeded;
-
-    if (!is_valid_address_to_publish(addr)) {
-        succeeded = true;
-        goto exit;
-    }
-
-    // Update the <local host name>.home.arpa. address mapping.
-    succeeded = dnssd_hardwired_add_or_remove_address_in_domain("", my_name, addr, add);
-    if (!succeeded) {
-        ERROR("failed to update address record for domain - domain: " PRI_S_SRP, my_name);
-        goto exit;
-    }
-
-    // Update the <local host name>.<Thread ID>.thread.home.arpa. address mapping.
-    succeeded = dnssd_hardwired_add_or_remove_address_in_domain(local_host_name, THREAD_DOMAIN_WITH_ID, addr, add);
-    if (!succeeded) {
-        ERROR("failed to update address record for domain - domain: " PUB_S_SRP, THREAD_DOMAIN_WITH_ID);
-        goto exit;
-    }
-
-    // Update the default.service.arpa. address mapping.
-    succeeded = dnssd_hardwired_add_or_remove_address_in_domain(local_host_name, DEFAULT_SERVICE_ARPA_DOMAIN, addr, add);
-    if (!succeeded) {
-        ERROR("failed to update address record for domain - domain: " PUB_S_SRP, DEFAULT_SERVICE_ARPA_DOMAIN);
-        goto exit;
-    }
-
-    // Setup the "_lb.dns-sd"
-    // Update the "reverse mapping from address to browsing domain" for each eligible served domain under IPv6 or IPv4
-    // reverse lookup domain.
-    if (addr->sa.sa_family == AF_INET6) {
-        succeeded = dnssd_hardwired_add_or_remove_ptr_in_domain(IPV6_REVERSE_LOOKUP_DOMAIN, addr, mask, add);
-    } else if (addr->sa.sa_family == AF_INET) {
-        succeeded = dnssd_hardwired_add_or_remove_ptr_in_domain(IPV4_REVERSE_LOOKUP_DOMAIN, addr, mask, add);
-    } else {
-        char buf[INET6_ADDRSTRLEN];
-        IOLOOP_NTOP(addr, buf);
-        INFO("Skipping non IPv6/IPv4 address - addr:" PRI_S_SRP, buf);
-        succeeded = true;
-    }
-
-exit:
-    return succeeded;
-}
-
-static void
-dnssd_hardwired_lbdomains_setup(void)
-{
-    served_domain_t *ipv6, *ipv4;
-#if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-    // When dnssd-proxy is combined with srp-mdns-proxy, IPv4 and IPv6 reverse look up domain is set from the begining.
-    ipv4 = find_served_domain(IPV4_REVERSE_LOOKUP_DOMAIN);
-    ipv6 = find_served_domain(IPV6_REVERSE_LOOKUP_DOMAIN);
-#else // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-    ipv4 = new_served_domain(NULL, IPV4_REVERSE_LOOKUP_DOMAIN);
-    ipv6 = new_served_domain(NULL, IPV6_REVERSE_LOOKUP_DOMAIN);
-#endif // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-    require_action_quiet(ipv4 != NULL && ipv6 != NULL, exit, ERROR("cannot find/create new served domain"));
-
-    for (served_domain_t *addr_domain = served_domains; addr_domain; addr_domain = addr_domain->next) {
-        dp_interface_t *interface = addr_domain->interface;
-        interface_addr_t *ifaddr;
-        if (interface == NULL) {
-            INFO("Domain " PRI_S_SRP " has no interface", addr_domain->domain);
-            continue;
-        }
-        INFO("Interface " PUB_S_SRP, interface->name);
-        // Add lb domain support for link domain
-        for (ifaddr = interface->addresses; ifaddr != NULL; ifaddr = ifaddr->next) {
-            // Do not publish link-local or loopback address
-            if (!is_valid_address_to_publish(&ifaddr->addr)) {
-                continue;
-            }
-
-            if (ifaddr->addr.sa.sa_family == AF_INET) {
-                dnssd_hardwired_add_or_remove_ptr_record(ipv4, &ifaddr->addr, &ifaddr->mask, true);
-            } else if (ifaddr->addr.sa.sa_family == AF_INET6) {
-                dnssd_hardwired_add_or_remove_ptr_record(ipv6, &ifaddr->addr, &ifaddr->mask, true);
-            } else {
-                char buf[INET6_ADDRSTRLEN];
-                IOLOOP_NTOP(&ifaddr->addr, buf);
-                INFO("Skipping " PRI_S_SRP, buf);
-            }
-        }
-    }
-exit:
-    return;
-}
-
-static void
-dnssd_hardwired_setup(void)
-{
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-    served_domain_t *sdt;
-    int i;
-    dns_name_t *my_name_parsed = my_name == NULL ? NULL : dns_pres_name_parse(my_name);
-    char namebuf[DNS_MAX_NAME_SIZE + 1];
-    const char *local_name;
-    addr_t addr;
-
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    // For each interface, set up the hardwired names.
-    for (sdt = served_domains; sdt; sdt = sdt->next) {
-        if (sdt->interface == NULL) {
-            continue;
-        }
-
-        // SRV
-        // _dns-llq._udp
-        // _dns-llq-tls._tcp
-        // _dns-update._udp
-        // _dns-update-tls._udp
-        // We deny the presence of support for LLQ, because we only support DNS Push
-        RESET;
-        dnssd_hardwired_add(sdt, "_dns-llq._udp", sdt->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-        dnssd_hardwired_add(sdt, "_dns-llq-tls._tcp", sdt->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-
-        // We deny the presence of support for DNS Update, because a Discovery Proxy zone is stateless.
-        dnssd_hardwired_add(sdt, "_dns-update._udp", sdt->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-        dnssd_hardwired_add(sdt, "_dns-update-tls._tcp", sdt->domain_ld, towire.p - wire.data, wire.data,
-                            dns_rrtype_srv);
-
-        // Until we set up the DNS Push listener, we deny its existence.   If TLS is ready to go, this will be
-        // overwritten immediately; otherwise it will be overwritten when the TLS key has been generated and signed.
-        dnssd_hardwired_add(sdt, "_dns-push-tls._tcp", sdt->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-
-        // If my_name wasn't set, or if my_name is in this interface's domain, we need to answer
-        // for it when queried.
-        if (my_name == NULL || my_name_parsed != NULL) {
-            const char *local_domain = NULL;
-            if (my_name == NULL) {
-                local_name = "ns";
-                local_domain = sdt->domain_ld;
-            } else {
-                dns_name_t *lim;
-                local_name = NULL;
-
-                // See if my_name is a subdomain of this interface's domain
-                if ((lim = dns_name_subdomain_of(my_name_parsed, sdt->domain_name)) != NULL) {
-                    dns_name_print_to_limit(my_name_parsed, lim, namebuf, sizeof namebuf);
-                    local_name = namebuf;
-                    dns_name_free(my_name_parsed);
-                    my_name_parsed = NULL;
-                    if (local_name[0] == '\0') {
-                        local_domain = sdt->domain;
-                    } else {
-                        local_domain = sdt->domain_ld;
-                    }
-                }
-            }
-            if (local_name != NULL) {
-                for (i = 0; i < num_publish_addrs; i++) {
-                    RESET;
-                    memset(&addr, 0, sizeof addr);
-                    getipaddr(&addr, publish_addrs[i]);
-                    if (addr.sa.sa_family == AF_INET) {
-                        // A
-                        // ns
-                        dns_rdata_raw_data_to_wire(&towire, &addr.sin.sin_addr, sizeof addr.sin.sin_addr);
-                        dnssd_hardwired_add(sdt, local_name, local_domain, towire.p - wire.data, wire.data,
-                                            dns_rrtype_a);
-                    } else {
-                        // AAAA
-                        RESET;
-                        dns_rdata_raw_data_to_wire(&towire, &addr.sin6.sin6_addr, sizeof addr.sin6.sin6_addr);
-                        dnssd_hardwired_add(sdt, local_name, local_domain, towire.p - wire.data, wire.data,
-                                            dns_rrtype_aaaa);
-                    }
-                }
-            }
-        }
-
-        // NS
-        RESET;
-        if (string_ends_with(sdt->domain, THREAD_DOMAIN)) {
-            // For served domain in the THREAD_DOMAIN, set the NS record to the local host name:
-            // For example, openthread.thread.home.arpa. NS Office.local.
-            require_quiet(local_host_name_dot_local[0] != 0, exit);
-            dns_full_name_to_wire(NULL, &towire, local_host_name_dot_local);
-        } else if (my_name != NULL) {
-            dns_full_name_to_wire(NULL, &towire, my_name);
-        } else {
-            dns_name_to_wire(NULL, &towire, "ns");
-            dns_full_name_to_wire(NULL, &towire, sdt->domain);
-        }
-        dnssd_hardwired_add(sdt, "", sdt->domain, towire.p - wire.data, wire.data, dns_rrtype_ns);
-
-        // SOA (piggybacking on what we already did for NS, which starts the same.
-        dns_name_to_wire(NULL, &towire, "postmaster");
-        dns_full_name_to_wire(NULL, &towire, sdt->domain);
-        dns_u32_to_wire(&towire, 0);     // serial
-        dns_ttl_to_wire(&towire, 7200);  // refresh
-        dns_ttl_to_wire(&towire, 3600);  // retry
-        dns_ttl_to_wire(&towire, 86400); // expire
-        dns_ttl_to_wire(&towire, 120);    // minimum
-        dnssd_hardwired_add(sdt, "", sdt->domain, towire.p - wire.data, wire.data, dns_rrtype_soa);
-    }
-
-    // Setup hardwired response A/AAAA record for <local host name>.home.arpa.
-#if SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-    // When dnssd-proxy is combined with srp-mdns-proxy, we get the address from the interface address list not from the
-    // config file, so we search through the served domains for all available address.
-    if (my_name_parsed != NULL) {
-        dns_name_free(my_name_parsed);
-        my_name_parsed = NULL;
-    }
-
-    require_action_quiet(my_name != NULL, exit, ERROR("Failed to get my_name and unable to set hardwired response"));
-    served_domain_t *const my_name_served_domain = find_served_domain(my_name);
-    require_action_quiet(my_name_served_domain != NULL, exit,
-        ERROR("Failed to find my_name domain - my_name: " PRI_S_SRP, my_name));
-
-    served_domain_t *const thread_served_domain = find_served_domain(THREAD_DOMAIN_WITH_ID);
-    require_action(thread_served_domain != NULL, exit,
-        ERROR("Failed to find thread domain - domain: " PUB_S_SRP, THREAD_DOMAIN_WITH_ID));
-
-    served_domain_t *const default_service_arpa_domain = find_served_domain(THREAD_DOMAIN_WITH_ID);
-    require_action(default_service_arpa_domain != NULL, exit,
-        ERROR("Failed to find thread domain - domain: " PUB_S_SRP, THREAD_DOMAIN_WITH_ID));
-
-    for (const served_domain_t *domain = served_domains; domain != NULL; domain = domain->next) {
-        if (domain->interface == NULL) {
-            continue;
-        }
-        for (const interface_addr_t *if_addrs = domain->interface->addresses; if_addrs != NULL;
-             if_addrs = if_addrs->next) {
-            const addr_t *const if_addr = &if_addrs->addr;
-            // Only publish routable IP address.
-            if (!is_valid_address_to_publish(if_addr)) {
-                continue;
-            }
-
-            RESET;
-            uint16_t rr_type;
-            if (if_addr->sa.sa_family == AF_INET) {
-                dns_rdata_raw_data_to_wire(&towire, &if_addr->sin.sin_addr, sizeof(if_addr->sin.sin_addr));
-                rr_type = dns_rrtype_a;
-            } else if (if_addr->sa.sa_family == AF_INET6) {
-                dns_rdata_raw_data_to_wire(&towire, &if_addr->sin6.sin6_addr, sizeof(if_addr->sin6.sin6_addr));
-                rr_type = dns_rrtype_aaaa;
-            } else {
-                ERROR("Non IPv4/IPv6 address in interface addresses - sa_family: %u", if_addr->sa.sa_family);
-                continue;
-            }
-
-            // <local host name>.home.arpa. A/AAAA <IP address>
-            dnssd_hardwired_add(my_name_served_domain, "", my_name_served_domain->domain, towire.p - wire.data,
-                wire.data, rr_type);
-
-            // <local host name>.openthread.thread.home.arpa. A/AAAA <IP address>
-            dnssd_hardwired_add(thread_served_domain, local_host_name, thread_served_domain->domain_ld,
-                towire.p - wire.data, wire.data, rr_type);
-
-            // <local host name>.default.service.arpa. A/AAAA <IP address>
-            dnssd_hardwired_add(default_service_arpa_domain, local_host_name, default_service_arpa_domain->domain_ld,
-                towire.p - wire.data, wire.data, rr_type);
-        }
-    }
-#else // SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-    if (my_name_parsed != NULL) {
-        dns_name_free(my_name_parsed);
-        my_name_parsed = NULL;
-
-        sdt = new_served_domain(NULL, my_name);
-        if (sdt == NULL) {
-            ERROR("Unable to allocate domain for %s", my_name);
-        } else {
-            for (i = 0; i < num_publish_addrs; i++) {
-                // AAAA
-                // A
-                RESET;
-                memset(&addr, 0, sizeof addr);
-                getipaddr(&addr, publish_addrs[i]);
-                if (addr.sa.sa_family == AF_INET) {
-                    dns_rdata_raw_data_to_wire(&towire, &addr.sin.sin_addr, sizeof addr.sin.sin_addr);
-                    dnssd_hardwired_add(sdt, "", sdt->domain, towire.p - wire.data, wire.data, dns_rrtype_a);
-                } else {
-                    dns_rdata_raw_data_to_wire(&towire, &addr.sin6.sin6_addr, sizeof addr.sin6.sin6_addr);
-                    dnssd_hardwired_add(sdt, "", sdt->domain, towire.p - wire.data, wire.data, dns_rrtype_aaaa);
-                }
-            }
-        }
-    }
-#endif // SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-
-    // Setup _lb._udp.<reversed IP address> PTR record for the domain we are advertising, for example:
-    // _lb._udp.0.0.168.192.in-addr.arpa. PTR my-discovery-proxy-en0.home.arpa.
-    dnssd_hardwired_lbdomains_setup();
-
-exit:
-    return;
-}
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static void
-dnssd_hardwired_clear(void)
-{
-    INFO("Clearing all hardwired response");
-    for (served_domain_t *domain = served_domains; domain != NULL; domain = domain->next) {
-        hardwired_t *hardwired_responses = domain->hardwired_responses;
-        if (hardwired_responses == NULL) {
-            continue;
-        }
-
-        domain->hardwired_responses = NULL;
-        hardwired_t *next_response;
-        for (hardwired_t *response = hardwired_responses; response != NULL; response = next_response) {
-            next_response = response->next;
-            free(response);
-        }
-    }
-}
-
-static void
-dnssd_hardwired_push_setup(void)
-{
-    // For each interface, set up the hardwired names.
-    for (served_domain_t *sdt = served_domains; sdt; sdt = sdt->next) {
-        if (sdt->interface == NULL) {
-            continue;
-        }
-
-        if (!sdt->interface->no_push) {
-            // SRV
-            // _dns-push-tls._tcp
-            // _dns-query-tls._udp
-            dnssd_hardwired_setup_dns_push_for_domain(sdt);
-        }
-    }
-}
-
-static void
-dnssd_hardwired_deny_service_existence_for_served_domain(served_domain_t *const NONNULL served_domain)
-{
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    RESET;
-    // We deny the presence of support for LLQ, because we only support DNS Push.
-    dnssd_hardwired_add(served_domain, "_dns-llq._udp", served_domain->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-    dnssd_hardwired_add(served_domain, "_dns-llq-tls._tcp", served_domain->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-
-    // We deny the presence of support for DNS Update, because a Discovery Proxy zone is stateless.
-    dnssd_hardwired_add(served_domain, "_dns-update._udp", served_domain->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-    dnssd_hardwired_add(served_domain, "_dns-update-tls._tcp", served_domain->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-
-    // We deny the presence of support for UDP with TLS, because we have not implemented DTLS (datagram TLS).
-    dnssd_hardwired_add(served_domain, "_dns-query-tls._udp", served_domain->domain_ld, towire.p - wire.data, wire.data, dns_rrtype_srv);
-
-    // We deny the presence of "lb._dns-sd._udp" for the served domain, to avoid the response like:
-    // lb._dns-sd._udp.openthread.thread.home.arpa. PTR openthread.thread.home.arpa.
-    dnssd_hardwired_add(served_domain, SRV_TYPE_FOR_AUTOMATIC_BROWSING_DOMAIN, served_domain->domain_ld,
-        towire.p - wire.data, wire.data, dns_rrtype_ptr);
-    dnssd_hardwired_add(served_domain, "b._dns-sd._udp", served_domain->domain_ld,
-        towire.p - wire.data, wire.data, dns_rrtype_ptr);
-    dnssd_hardwired_add(served_domain, "db._dns-sd._udp", served_domain->domain_ld,
-        towire.p - wire.data, wire.data, dns_rrtype_ptr);
-}
-
-static bool
-dnssd_hardwired_setup_for_served_domain(served_domain_t *const NONNULL served_domain)
-{
-    bool succeeded;
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-    dns_name_t *my_name_parsed = NULL;
-
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    require_action_quiet(served_domain->interface != NULL, exit, succeeded = false;
-        ERROR("only domain with usable interface can setup hardwired response - domain name: " PRI_S_SRP,
-            served_domain->domain)
-    );
-
-    // deny the existence of the following services:
-    // _dns-llq._udp
-    // _dns-llq-tls._tcp
-    // _dns-update._udp
-    dnssd_hardwired_deny_service_existence_for_served_domain(served_domain);
-
-    // Setup NS record for this served domain.
-    RESET;
-    if (string_ends_with(served_domain->domain, THREAD_DOMAIN)) {
-        // If the response requires the translation from <served domain> to ".local." and the response ends in
-        // ".local.", truncate it.
-        require_action_quiet(local_host_name_dot_local[0] != 0, exit, succeeded = false);
-        dns_full_name_to_wire(NULL, &towire, local_host_name_dot_local);
-    } else if (my_name != NULL) {
-        dns_full_name_to_wire(NULL, &towire, my_name);
-    } else {
-        dns_name_to_wire(NULL, &towire, "ns");
-        dns_full_name_to_wire(NULL, &towire, served_domain->domain);
-    }
-    dnssd_hardwired_add(served_domain, "", served_domain->domain, towire.p - wire.data, wire.data, dns_rrtype_ns);
-
-    // Setup SOA record for this served domain. (piggybacking on what we already did for NS, which starts the same.)
-    dns_name_to_wire(NULL, &towire, "postmaster");
-    dns_full_name_to_wire(NULL, &towire, served_domain->domain);
-    dns_u32_to_wire(&towire, 0);     // serial
-    dns_ttl_to_wire(&towire, 7200);  // refresh
-    dns_ttl_to_wire(&towire, 3600);  // retry
-    dns_ttl_to_wire(&towire, 86400); // expire
-    dns_ttl_to_wire(&towire, 120);    // minimum
-    dnssd_hardwired_add(served_domain, "", served_domain->domain, towire.p - wire.data, wire.data, dns_rrtype_soa);
-
-    // Setup DNS push
-    succeeded = dnssd_hardwired_setup_dns_push_for_domain(served_domain);
-    require_action_quiet(succeeded, exit,
-        ERROR("failed to setup DNS push service for hardwired response - domain: " PRI_S_SRP, served_domain->domain));
-
-exit:
-    if (my_name_parsed != NULL) {
-        dns_name_free(my_name_parsed);
-    }
-    return succeeded;
-}
-
-static bool
-dnssd_hardwired_setup_dns_push_for_domain(served_domain_t *const NONNULL served_domain)
-{
-    bool succeeded;
-
-    require_action_quiet(served_domain->interface != NULL && !served_domain->interface->no_push, exit, succeeded = false;
-        ERROR("the associated interface does not enable DNS push - domain: " PRI_S_SRP, served_domain->domain));
-
-    require_action_quiet(my_name != NULL, exit, succeeded = false; ERROR("my_name is not set"));
-
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-#define RESET \
-    memset(&towire, 0, sizeof towire); \
-    towire.message = &wire; \
-    towire.p = wire.data; \
-    towire.lim = towire.p + sizeof wire.data
-
-    RESET;
-    dns_u16_to_wire(&towire, 0); // priority
-    dns_u16_to_wire(&towire, 0); // weight
-    dns_u16_to_wire(&towire, 853); // port
-
-    if (string_ends_with(served_domain->domain, THREAD_DOMAIN)) {
-        // If the served domain is subdomain of "thread.home.arpa.", use name <local host name>.local for the DNS push
-        // service. Currently we only support DNS push in "thread.home.arpa." domain in local subnet, so DNS push
-        // service for "thread.home.arpa." will be registered with a name in ".local.".
-        require_action_quiet(local_host_name_dot_local[0] != 0, exit, succeeded = false);
-        dns_full_name_to_wire(NULL, &towire, local_host_name_dot_local);
-    } else if (my_name != NULL) {
-        // Use name <local host name>.home.arpa.
-        dns_full_name_to_wire(NULL, &towire, my_name);
-    } else { // my_name == NULL
-        // Use name ns.<served domain>.
-        dns_name_to_wire(NULL, &towire, "ns");
-        dns_full_name_to_wire(NULL, &towire, served_domain->domain);
-    }
-
-    dnssd_hardwired_add(served_domain, "_dns-push-tls._tcp", served_domain->domain_ld, towire.p - wire.data, wire.data,
-        dns_rrtype_srv);
-
-    succeeded = true;
-exit:
-    return succeeded;
-}
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-static bool
-embiggen(dnssd_query_t *query)
-{
-    dns_wire_t *nr = malloc(query->data_size + sizeof *nr); // increments wire size by DNS_DATA_SIZE
-    if (nr == NULL) {
-        return false;
-    }
-    memcpy(nr, query->response, DNS_HEADER_SIZE + query->data_size);
-    query->data_size += DNS_DATA_SIZE;
-#define RELOCATE(x) (x) = &nr->data[0] + ((x) - &query->response->data[0])
-    RELOCATE(query->towire.p);
-    query->towire.lim = &nr->data[0] + query->data_size;
-    query->towire.p_rdlength = NULL;
-    query->towire.p_opt = NULL;
-    query->towire.message = nr;
-    free(query->response);
-    query->response = nr;
-    return true;
-}
-
-static void
-dp_query_send_dns_response(dnssd_query_t *query)
-{
-    struct iovec iov;
-    dns_towire_state_t *towire = &query->towire;
-    const char *failnote = NULL;
-    uint8_t *revert = towire->p;
-    uint16_t tc = towire->truncated ? dns_flags_tc : 0;
-    uint16_t bitfield = ntohs(query->response->bitfield);
-    uint16_t mask = 0;
-
-    VALIDATE_TRACKER_CONNECTION_NON_NULL();
-
-    // Send an SOA record if it's a .local query.
-    if (query->question_asked->served_domain != NULL && query->question_asked->served_domain->interface != NULL && !towire->truncated) {
-    redo:
-        // DNSSD Hybrid, Section 6.1.
-        TOWIRE_CHECK("&query->enclosing_domain_pointer 1", towire,
-                     dns_pointer_to_wire(NULL, towire, &query->enclosing_domain_pointer));
-        TOWIRE_CHECK("dns_rrtype_soa", towire,
-                     dns_u16_to_wire(towire, dns_rrtype_soa));
-        TOWIRE_CHECK("dns_qclass_in", towire,
-                     dns_u16_to_wire(towire, dns_qclass_in));
-        TOWIRE_CHECK("ttl", towire, dns_ttl_to_wire(towire, 3600));
-        TOWIRE_CHECK("rdlength_begin ", towire, dns_rdlength_begin(towire));
-        if (my_name != NULL) {
-            TOWIRE_CHECK(my_name, towire, dns_full_name_to_wire(NULL, towire, my_name));
-        } else {
-            TOWIRE_CHECK("\"ns\"", towire, dns_name_to_wire(NULL, towire, "ns"));
-            TOWIRE_CHECK("&query->enclosing_domain_pointer 2", towire,
-                         dns_pointer_to_wire(NULL, towire, &query->enclosing_domain_pointer));
-        }
-        TOWIRE_CHECK("\"postmaster\"", towire,
-                     dns_name_to_wire(NULL, towire, "postmaster"));
-        TOWIRE_CHECK("&query->enclosing_domain_pointer 3", towire,
-                     dns_pointer_to_wire(NULL, towire, &query->enclosing_domain_pointer));
-        TOWIRE_CHECK("serial", towire,dns_u32_to_wire(towire, 0));     // serial
-        TOWIRE_CHECK("refresh", towire, dns_ttl_to_wire(towire, 7200));  // refresh
-        TOWIRE_CHECK("retry", towire, dns_ttl_to_wire(towire, 3600));  // retry
-        TOWIRE_CHECK("expire", towire, dns_ttl_to_wire(towire, 86400)); // expire
-        TOWIRE_CHECK("minimum", towire, dns_ttl_to_wire(towire, 120));    // minimum
-        dns_rdlength_end(towire);
-        if (towire->truncated) {
-            query->towire.p = revert;
-            if (query->tracker->connection->tcp_stream) {
-                if (embiggen(query)) {
-                    query->towire.error = 0;
-                    towire->truncated = false;
-                    goto redo;
-                }
-            } else {
-                tc = dns_flags_tc;
-            }
-        } else {
-            query->response->nscount = htons(1);
-        }
-
-        // Response is authoritative and not recursive.
-        mask = ~dns_flags_ra;
-        bitfield = bitfield | dns_flags_aa | tc;
-        bitfield = bitfield & mask;
-    } else {
-        // Response is recursive and not authoritative.
-        mask = ~dns_flags_aa;
-        bitfield = bitfield | dns_flags_ra | tc;
-        bitfield = bitfield & mask;
-    }
-    // Not authentic, checking not disabled.
-    mask = ~(dns_flags_rd | dns_flags_ad | dns_flags_cd);
-    bitfield = bitfield & mask;
-    query->response->bitfield = htons(bitfield);
-
-    // This is a response
-    dns_qr_set(query->response, dns_qr_response);
-
-    // Send an OPT RR if we got one
-    // XXX reserve space so we can always send an OPT RR?
-    if (query->is_edns0) {
-    redo_edns0:
-        TOWIRE_CHECK("Root label", towire, dns_u8_to_wire(towire, 0));     // Root label
-        TOWIRE_CHECK("dns_rrtype_opt", towire, dns_u16_to_wire(towire, dns_rrtype_opt));
-        TOWIRE_CHECK("UDP Payload size", towire, dns_u16_to_wire(towire, 4096)); // UDP Payload size
-        TOWIRE_CHECK("extended-rcode", towire, dns_u8_to_wire(towire, 0));     // extended-rcode
-        TOWIRE_CHECK("EDNS version 0", towire, dns_u8_to_wire(towire, 0));     // EDNS version 0
-        TOWIRE_CHECK("No extended flags", towire, dns_u16_to_wire(towire, 0));    // No extended flags
-        TOWIRE_CHECK("No payload", towire, dns_u16_to_wire(towire, 0));    // No payload
-        if (towire->truncated) {
-            query->towire.p = revert;
-            if (query->tracker->connection->tcp_stream) {
-                if (embiggen(query)) {
-                    query->towire.error = false;
-                    query->towire.truncated = false;
-                    goto redo_edns0;
-                }
-            }
-        } else {
-#if SRP_FEATURE_NAT64
-            query->response->arcount = htons(ntohs(query->response->arcount) + 1);
-#else
-            query->response->arcount = htons(1);
-#endif
-        }
-    }
-
-    if (towire->error) {
-        ERROR("dp_query_send_dns_response failed on %s", failnote);
-        if (tc == dns_flags_tc) {
-            dns_rcode_set(query->response, dns_rcode_noerror);
-        } else {
-            dns_rcode_set(query->response, dns_rcode_servfail);
-        }
-    } else {
-        // No error.
-        dns_rcode_set(query->response, dns_rcode_noerror);
-    }
-
-    iov.iov_len = (query->towire.p - (uint8_t *)query->response);
-    iov.iov_base = query->response;
-    INFO("" PRI_S_SRP " (len %zd)", query->question_asked->name, iov.iov_len);
-
-    ioloop_send_message(query->tracker->connection, query->question, &iov, 1);
-
-    // Cancel the query.
-    dnssd_query_cancel(query);
-}
-
-static void
-dp_query_towire_reset(dnssd_query_t *query)
-{
-    query->towire.p = &query->response->data[0];  // We start storing RR data here.
-    query->towire.lim = &query->response->data[0] + query->data_size; // This is the limit to how much we can store.
-    query->towire.message = query->response;
-    query->towire.p_rdlength = NULL;
-    query->towire.p_opt = NULL;
-    query->p_dso_length = NULL;
-}
-
-static void
-dns_push_start(dnssd_query_t *query)
-{
-    const char *failnote = NULL;
-
-    // If we don't have a dso header yet, start one.
-    if (query->p_dso_length == NULL) {
-        memset(query->response, 0, (sizeof *query->response) - DNS_DATA_SIZE);
-        dns_opcode_set(query->response, dns_opcode_dso);
-        // This is a unidirectional DSO message, which is marked as a query
-        dns_qr_set(query->response, dns_qr_query);
-        // No error cuz not a response.
-        dns_rcode_set(query->response, dns_rcode_noerror);
-
-        TOWIRE_CHECK("kDSOType_DNSPushUpdate", &query->towire,
-                     dns_u16_to_wire(&query->towire, kDSOType_DNSPushUpdate));
-        if (query->towire.p + 2 > query->towire.lim) {
-            ERROR("No room for dso length in DNS Push notification message.");
-            dp_query_towire_reset(query);
-            return;
-        }
-        query->p_dso_length = query->towire.p;
-        query->towire.p += 2;
-    }
-    if (failnote != NULL) {
-        ERROR("couldn't start update: %s", failnote);
-    }
-}
-
-static void
-dp_push_response(dnssd_query_t *query)
-{
-    struct iovec iov;
-
-    VALIDATE_TRACKER_CONNECTION_NON_NULL();
-
-    if (query->p_dso_length != NULL) {
-        int16_t dso_length = query->towire.p - query->p_dso_length - 2;
-        iov.iov_len = (query->towire.p - (uint8_t *)query->response);
-        iov.iov_base = query->response;
-        INFO("" PRI_S_SRP " (len %zd)", query->question_asked->name, iov.iov_len);
-
-        query->towire.p = query->p_dso_length;
-        dns_u16_to_wire(&query->towire, dso_length);
-        ioloop_send_message(query->tracker->connection, query->question, &iov, 1);
-        dp_query_towire_reset(query);
-    }
-}
-
-static bool
-dnssd_hardwired_response(dnssd_query_t *query, DNSServiceQueryRecordReply UNUSED callback)
-{
-    hardwired_t *hp;
-    bool got_response = false;
-
-    for (hp = query->question_asked->served_domain->hardwired_responses; hp; hp = hp->next) {
-        if ((query->question_asked->type == hp->type || query->question_asked->type == dns_rrtype_any) &&
-            query->question_asked->qclass == dns_qclass_in && !strcasecmp(hp->name, query->question_asked->name)) {
-            if (query->dso != NULL) {
-                dns_push_start(query);
-                // Since hardwired response is set by the dnssd-proxy itself, do not do ".local" translation.
-                dp_query_add_data_to_response(query, hp->fullname, hp->type, dns_qclass_in, hp->rdlen, hp->rdata, 3600, true);
-            } else {
-                // Store the response
-                if (!query->towire.truncated) {
-                    // Since hardwired response is set by the dnssd-proxy itself, do not do ".local" translation.
-                    bool record_added = dp_query_add_data_to_response(query, hp->fullname, hp->type, dns_qclass_in,
-                        hp->rdlen, hp->rdata, 3600, true);
-                    if (!query->towire.truncated) {
-                        query->response->ancount = htons(ntohs(query->response->ancount) + (record_added ? 1 : 0));
-                    }
-                }
-            }
-            got_response = true;
-        }
-    }
-    if (got_response) {
-        if (query->dso != NULL) {
-            dp_push_response(query);
-        } else {
-            // Send the answer(s).
-            dp_query_send_dns_response(query);
-        }
-        return true;
-    }
-    return false;
-}
-
-#if SRP_FEATURE_NAT64
-static void
-dp_query_append_nat64_prefix_records(dnssd_query_t *query)
-{
-    // 192.0.0.170 and 192.0.0.171 are reserved IPv4 addresses for ipv4only.arpa.
-    // See <https://tools.ietf.org/html/rfc7050#section-8.2>.
-    const uint8_t ipv4_addrs[2][4] = {
-        {192, 0, 0, 170},
-        {192, 0, 0, 171}
-    };
-    uint8_t rdata[16] = {0};
-
-    VALIDATE_TRACKER_CONNECTION_NON_NULL();
-
-    const struct in6_addr *prefix = nat64_get_ipv6_prefix();
-    memcpy(rdata, prefix->s6_addr, sizeof(rdata));
-    for (size_t i = 0; i < countof(ipv4_addrs);) {
-        memcpy(&rdata[12], ipv4_addrs[i], 4);
-        const bool added = dp_query_add_data_to_response(query, "ipv4only.arpa.", dns_rrtype_aaaa, query->question_asked->qclass,
-                                                         (uint16_t)sizeof(rdata), rdata, 10, true);
-        if (query->towire.truncated) {
-            if (query->tracker->connection->tcp_stream) {
-                if (embiggen(query)) {
-                    query->towire.truncated = false;
-                    query->towire.error = false;
-                    continue;
-                } else {
-                    dns_rcode_set(query->response, dns_rcode_servfail);
-                }
-            }
-            return;
-        }
-        if (added) {
-            query->response->arcount = htons(ntohs(query->response->arcount) + 1);
-        }
-        i++;
-    }
-}
-#endif // SRP_FEATURE_NAT64
-
-static void
-dns_query_answer_process(DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                         const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                         uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
-{
-    dnssd_query_t *query = context;
-    bool record_added;
-
-    INFO(PRI_S_SRP " %d %d %x %d", fullname, rrtype, rrclass, rdlen, errorCode);
-
-    VALIDATE_TRACKER_CONNECTION_NON_NULL();
-
-    if (errorCode == kDNSServiceErr_NoError) {
-#if SRP_FEATURE_NAT64
-        const bool aaaa_query_got_a_record = (query->question_asked->type == dns_rrtype_aaaa) && (rrtype == dns_rrtype_a);
-        if (route_states->srp_server->srp_nat64_enabled && (ntohs(query->response->arcount) != 0) && !aaaa_query_got_a_record) {
-            return;
-        }
-#endif
-    re_add:
-        record_added = dp_query_add_data_to_response(query, fullname, rrtype, rrclass, rdlen, rdata,
-            ttl > 10 ? 10 : ttl, false); // Per dnssd-hybrid 5.5.1, limit ttl to 10 seconds
-        if (query->towire.truncated) {
-            if (query->tracker->connection->tcp_stream) {
-                if (embiggen(query)) {
-                    query->towire.truncated = false;
-                    query->towire.error = false;
-                    goto re_add;
-                } else {
-                    dns_rcode_set(query->response, dns_rcode_servfail);
-                    dp_query_send_dns_response(query);
-                    return;
-                }
-            }
-        } else {
-#if SRP_FEATURE_NAT64
-            if (record_added) {
-                if (route_states->srp_server->srp_nat64_enabled && aaaa_query_got_a_record) {
-                    query->response->arcount = htons(ntohs(query->response->arcount) + 1);
-                } else {
-                    query->response->ancount = htons(ntohs(query->response->ancount) + 1);
-                }
-            }
-#else
-            query->response->ancount = htons(ntohs(query->response->ancount) + (record_added ? 1 : 0));
-#endif
-        }
-        // If there isn't more coming, send the response now
-        if (!(flags & kDNSServiceFlagsMoreComing) || query->towire.truncated) {
-            // When we get a CNAME response, we may not get the record it points to with the MoreComing
-            // flag set, so don't respond yet.
-            if (query->question_asked->type != dns_rrtype_cname && rrtype == dns_rrtype_cname) {
-            } else {
-#if SRP_FEATURE_NAT64
-                if (route_states->srp_server->srp_nat64_enabled && (ntohs(query->response->arcount) != 0)) {
-                    dp_query_append_nat64_prefix_records(query);
-                }
-#endif
-                dp_query_send_dns_response(query);
-            }
-        }
-    } else if (errorCode == kDNSServiceErr_NoSuchRecord) {
-        // If we get "no such record," we can't really do much except return the answer.
-        dp_query_send_dns_response(query);
-    } else {
-        dns_rcode_set(query->response, dns_rcode_servfail);
-        dp_query_send_dns_response(query);
-    }
-}
-
-// answer_match is to decide if an answer matches the one requested to be removed.
-// Based on rfc8765
-// Remove all RRsets from a name in all classes:
-//      TTL = 0xFFFFFFFE, RDLEN = 0, CLASS = 255 (ANY).
-// Remove all RRsets from a name in given class:
-//      TTL = 0xFFFFFFFE, RDLEN = 0, CLASS gives class, TYPE = 255 (ANY).
-// Remove specified RRset from a name in given class:
-//      TTL = 0xFFFFFFFE, RDLEN = 0,
-//      CLASS and TYPE specify the RRset being removed.
-// Remove an individual RR from a name:
-//      TTL = 0xFFFFFFFF,
-//      CLASS, TYPE, RDLEN, and RDATA specify the RR being removed.
-static bool
-answer_match(const answer_t *answer, uint32_t rdlen, const char *fullname, uint16_t rrtype, uint16_t rrclass, const void *rdata)
-{
-    return (((rrclass == dns_qclass_any) || (rrclass == answer->rrclass)) &&
-            ((rrtype == dns_rrtype_any) || (rrtype == answer->rrtype)) &&
-            ((rdlen == 0) || ((rdlen == answer->rdlen) && (memcmp(answer->rdata, rdata, rdlen) == 0))) &&
-            (!strcmp(answer->fullname, fullname))
-            );
-}
-
-static void
-dns_push_query_answer_process(DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                              const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                              uint16_t rdlen, const void *rdata, uint32_t ttl, void *context);
-
-// This is the callback for both dns query and dns push query results.
-static void
-dns_question_callback(DNSServiceRef UNUSED sdRef, DNSServiceFlags flags, uint32_t UNUSED interfaceIndex,
-                      DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                      uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
-{
-    question_t *q = context;
-    dnssd_query_t *query, *next;
-
-    // For dns push query,  insert or remove answer from the question cache depending on the flags
-    // For dns query (dso==NULL), add answer when receiving callback to the question
-    if (errorCode == kDNSServiceErr_NoError) {
-        if (flags & kDNSServiceFlagsAdd) {
-            // Add
-            // the extra space rdlen stores rdata at the end
-            answer_t *answer = calloc(1, sizeof(*answer) + rdlen);
-            if (answer == NULL) {
-                ERROR("unable to allocate memory for answer - "
-                      "name: " PRI_S_SRP ", rrtype: " PUB_S_SRP ", rrclass: " PUB_S_SRP ", rdlen: %u.",
-                      fullname, dns_rrtype_to_string(rrtype), dns_qclass_to_string(rrclass), rdlen);
-                return;
-            }
-            answer->fullname = strdup(fullname);
-            if (answer->fullname == NULL) {
-                ERROR("strdup failed to copy the answer name: " PRI_S_SRP, fullname);
-                free(answer);
-                return;
-            }
-            answer->interface_index = interfaceIndex;
-            answer->ttl = ttl;
-            answer->rrtype = rrtype;
-            answer->rrclass = rrclass;
-            answer->rdlen = rdlen;
-            answer->rdata = (uint8_t *)(answer + 1);
-            memcpy(answer->rdata, rdata, rdlen);
-            answer->next = NULL;
-            // Insert answer at the tail
-            answer_t **tail = &(q->answers);
-            while (*tail != NULL) {
-                tail = &((*tail)->next);
-            }
-            *tail = answer;
-            // Received data; reset no_data flag.
-            q->no_data = false;
-            INFO("add answer to cache - "
-                 "name: " PRI_S_SRP ", rrtype: " PUB_S_SRP ", rrclass: " PUB_S_SRP ", rdlen: %u.",
-                 fullname, dns_rrtype_to_string(rrtype), dns_qclass_to_string(rrclass), rdlen);
-        } else {
-            // Remove
-            answer_t **answer = &(q->answers);
-            answer_t *cur = NULL;
-            while (*answer != NULL) {
-                cur = *answer;
-                if (answer_match(cur, rdlen, fullname, rrtype, rrclass, rdata)) {
-                    INFO("remove answer from cache - "
-                         "name: " PRI_S_SRP ", rrtype: " PUB_S_SRP ", rrclass: " PUB_S_SRP ", rdlen: %u.",
-                         fullname, dns_rrtype_to_string(rrtype), dns_qclass_to_string(rrclass), rdlen);
-                    *answer = cur->next;
-                    answer_free(cur);
-                    // If individual RR to be removed, get out of the loop once the RR has been removed
-                    if (rdlen != 0) {
-                        break;
-                    }
-                } else {
-                    answer = &cur->next;
-                }
-            }
-            if (*answer == NULL) {
-                // All the answers get removed; set no_data flag.
-                q->no_data = true;
-            }
-        }
-    } else if (errorCode == kDNSServiceErr_NoSuchRecord) {
-        q->no_data = true;
-    }
-    query = q->queries;
-    while(query != NULL) {
-        next = query->question_next;
-        if (query->dso != NULL) {
-            dns_push_query_answer_process(flags, errorCode, fullname, rrtype, rrclass,
-                                          rdlen, rdata, ttl, (void *)query);
-        } else {
-            dns_query_answer_process(flags, errorCode, fullname, rrtype, rrclass,
-                                     rdlen, rdata, ttl, (void *)query);
-        }
-        query = next;
-    }
-}
-
-static void
-dp_query_wakeup(void *context)
-{
-    dnssd_query_t *query = context;
-    char name[DNS_MAX_NAME_SIZE + 1];
-    size_t namelen = strlen(query->question_asked->name);
-
-    // Should never happen.
-    if (namelen + (query->question_asked->served_domain
-                   ? (query->question_asked->served_domain->interface != NULL
-                      ? sizeof local_suffix
-                      // XXX why are we checking this but not copying in the served domain name below?
-                      : strlen(query->question_asked->served_domain->domain_ld) + 1)
-                   : 0) > sizeof name) {
-        ERROR("db_query_wakeup: no space to construct name.");
-        dnssd_query_cancel(query);
-    }
-
-    memcpy(name, query->question_asked->name, namelen + 1);
-    if (query->question_asked->served_domain != NULL) {
-        memcpy(name + namelen, local_suffix, sizeof(local_suffix));
-    }
-    dp_query_send_dns_response(query);
-}
-
-// Search asked question in the cache; if not existing, create one.
-static question_t *
-dp_query_question_cache_copy(dns_rr_t *search_term, bool *new)
-{
-    char name[DNS_MAX_NAME_SIZE + 1];
-    served_domain_t *sdt = dp_served(search_term->name, name, sizeof(name));
-
-    if (sdt == NULL) {
-        dns_name_print(search_term->name, name, sizeof name);
-    }
-    question_t **questions, *question;
-    question_t *new_question = NULL;
-    // if the query is in served domain, lookup in served_domain->questions
-    // otherwise lookup in the out-of-domain question cache
-    if (sdt != NULL) {
-        questions = &sdt->questions;
-    } else {
-        questions = &questions_without_domain;
-    }
-    *new = false;
-    question = *questions;
-    while (question != NULL) {
-        if (search_term->type == question->type &&
-            search_term->qclass == question->qclass &&
-            !strcmp(name, question->name))
-        {
-            // Find the entry, retain it
-            RETAIN_HERE(question);
-            break;
-        }
-        question = question->next;
-    }
-
-    // If no cache entry was found, create one
-    if (question == NULL) {
-        new_question = calloc(1, sizeof(*new_question));
-        require_action_quiet(new_question != NULL, exit,
-                             ERROR("Unable to allocate memory for question entry on " PRI_S_SRP, name));
-        RETAIN_HERE(new_question);
-        new_question->name = strdup(name);
-        require_action_quiet(new_question->name != NULL, exit,
-                             ERROR("unable to allocate memory for question name on " PRI_S_SRP, name));
-        new_question->type = search_term->type;
-        new_question->qclass = search_term->qclass;
-        new_question->start_time = (int64_t)time(NULL);
-        new_question->answers = NULL;
-        new_question->served_domain = sdt;
-        new_question->queries = NULL;
-        new_question->no_data = false;
-        if (sdt != NULL && sdt->interface != NULL) {
-            new_question->interface_index = sdt->interface->ifindex;
-        } else {
-            new_question->interface_index = kDNSServiceInterfaceIndexAny;
-        }
-
-        // Link the new_question to the question list.
-        new_question->next = *questions;
-        *questions = new_question;
-
-        // Successfully created a new question, which will be the returned question.
-        question = new_question;
-        new_question = NULL;
-        *new = true;
-    }
-exit:
-    if (new_question != NULL) {
-        RELEASE_HERE(new_question, dp_question_finalize);
-    }
-    return question;
-}
-
-// Look for answers in the cache for the current query
-static void
-dp_query_reply_from_cache(question_t *question, dnssd_query_t *query)
-{
-    // For dns query, if no_data is flagged or it's been six seconds since the question
-    // was started and there is still no answer yet, we should also respond immediately.
-    // [DNS Discovery Proxy RFC, RFC 8766, Section 5.6]
-    if (query->dso == NULL &&
-        (question->no_data == true ||
-        (question->answers == NULL &&
-        time(NULL) - question->start_time > RESPONSE_WINDOW)))
-    {
-        INFO("no data for question - type %d class %d " PRI_S_SRP,
-             question->type, question->qclass, question->name);
-        dns_query_answer_process(0, kDNSServiceErr_NoSuchRecord, question->name,
-                                 question->type, question->qclass, 0,
-                                 NULL, 0, query);
-        return;
-    }
-    // answers are available for the question being asked
-    if (question->answers != NULL) {
-        INFO("reply from cache for question - type %d class %d " PRI_S_SRP,
-             question->type, question->qclass, question->name);
-        DNSServiceFlags flags;
-        answer_t *answer = question->answers;
-        while (answer != NULL) {
-            flags = kDNSServiceFlagsAdd;
-            if (answer->next != NULL) {
-                flags |= kDNSServiceFlagsMoreComing;
-            }
-            if (query->dso == NULL) {
-                dns_query_answer_process(flags, kDNSServiceErr_NoError, answer->fullname,
-                                         answer->rrtype, answer->rrclass, answer->rdlen,
-                                         answer->rdata, answer->ttl, query);
-            } else {
-                dns_push_query_answer_process(flags, kDNSServiceErr_NoError, answer->fullname,
-                                              answer->rrtype, answer->rrclass, answer->rdlen,
-                                              answer->rdata, answer->ttl, query);
-            }
-            answer = answer->next;
-        }
-    }
-}
-
-static bool
-dp_query_start(dnssd_query_t *query, int *rcode, bool dns64)
-{
-    char name[DNS_MAX_NAME_SIZE + 1];
-    char *np;
-    bool local = false;
-    size_t len;
-    DNSServiceRef sdref;
-    int err;
-    question_t *question = query->question_asked;
-
-    // If a query has a served domain, query->question_asked->name is the subdomain of the served domain that is
-    // being queried; otherwise query->question_asked->name is the whole name.
-    if (question->served_domain != NULL) {
-        if (dnssd_hardwired_response(query, dns_question_callback)) {
-            *rcode = dns_rcode_noerror;
-            return true;
-        }
-        len = strlen(question->name);
-        if (question->served_domain->interface != NULL) {
-            if (len + sizeof local_suffix > sizeof name) {
-                *rcode = dns_rcode_servfail;
-                ERROR("question name %s is too long for .local.", name);
-                return false;
-            }
-            memcpy(name, question->name, len);
-            memcpy(&name[len], local_suffix, sizeof local_suffix);
-        } else {
-            size_t dlen = strlen(question->served_domain->domain_ld) + 1;
-            if (len + dlen > sizeof name) {
-                *rcode = dns_rcode_servfail;
-                ERROR("question name %s is too long for %s.", name, query->question_asked->served_domain->domain);
-                return false;
-            }
-            memcpy(name, question->name, len);
-            memcpy(&name[len], question->served_domain->domain_ld, dlen);
-        }
-        np = name;
-        local = true;
-    } else {
-        np = question->name;
-    }
-
-    // If we get an SOA query for record that's under a zone cut we're authoritative for, which
-    // is the case of query->served_domain->interface != NULL, then answer with a negative response that includes
-    // our authority records, rather than waiting for the query to time out.
-    if (question->served_domain != NULL && question->served_domain->interface != NULL &&
-        (question->type == dns_rrtype_soa ||
-         question->type == dns_rrtype_ns ||
-         question->type == dns_rrtype_ds) && question->qclass == dns_qclass_in && query->dso == NULL) {
-        dp_query_send_dns_response(query);
-        return true;
-    }
-
-    // Check if DNSServiceQueryRecord call needs to be made
-    if (question->txn != NULL) {
-        return true;
-    }
-
-    // Issue a DNSServiceQueryRecord call
-    if(__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, * )) {
-#if SRP_FEATURE_NAT64
-        const DNSServiceAttribute *attr = NULL;
-        if (dns64 && (question->type == dns_rrtype_aaaa) && (question->qclass == dns_qclass_in)) {
-            attr = &kDNSServiceAttributeAAAAFallback;
-        }
-        err = DNSServiceQueryRecordWithAttribute(&sdref, query->serviceFlags, question->interface_index, np, question->type,
-                                                 question->qclass, attr, dns_question_callback, question);
-#else
-        (void)dns64;
-        err = DNSServiceQueryRecord(&sdref, query->serviceFlags, question->interface_index, np, question->type, question->qclass,
-                                    dns_question_callback, question);
-#endif
-    } else {
-        (void)dns64;
-        err = DNSServiceQueryRecord(&sdref, query->serviceFlags, question->interface_index, np, question->type, question->qclass,
-                                    dns_question_callback, question);
-    }
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("dp_query_start: DNSServiceQueryRecord failed for '%s': %d", np, err);
-        *rcode = dns_rcode_servfail;
-        return false;
-    } else {
-        question->txn = ioloop_dnssd_txn_add(sdref, question, NULL, dnssd_question_close_callback);
-        if (question->txn == NULL) {
-            return false;
-        }
-#if SRP_FEATURE_NAT64
-        INFO("DNSServiceQueryRecordWithAttribute started for '" PRI_S_SRP "': %d", np, err);
-#else
-        INFO("DNSServiceQueryRecord started for '" PRI_S_SRP "': %d", np, err);
-#endif // SRP_FEATURE_NAT64
-    }
-
-    // If this isn't a DNS Push subscription, we need to respond quickly with as much data as we have.  It
-    // turns out that dig gives us a second, but also that responses seem to come back in on the order of a
-    // millisecond, so we'll wait 100ms.
-    if (query->dso == NULL && local) {
-        // [DNS Discovery Proxy RFC, RFC 8766, Section 5.6, Answer Aggregation]
-        if (query->wakeup == NULL) {
-            query->wakeup = ioloop_wakeup_create();
-            if (query->wakeup == NULL) {
-                *rcode = dns_rcode_servfail;
-                return false;
-            }
-        }
-        ioloop_add_wake_event(query->wakeup, query, dp_query_wakeup, NULL, IOLOOP_SECOND * 6);
-    }
-
-    return true;
-}
-
-static dnssd_query_t *
-dp_query_create(dp_tracker_t *tracker, dns_rr_t *question, message_t *message, dso_state_t *dso, int *rcode)
-{
-    char name[DNS_MAX_NAME_SIZE + 1];
-    served_domain_t *sdt = dp_served(question->name, name, sizeof name);
-
-    // If it's a query for a name served by the local discovery proxy, do an mDNS lookup.
-    if (sdt) {
-        INFO(PUB_S_SRP " question: type %d class %d " PRI_S_SRP "." PRI_S_SRP " -> " PRI_S_SRP DOT_LOCAL,
-             dso != NULL ? "push" : " dns", question->type, question->qclass, name, sdt->domain, name);
-    } else {
-        dns_name_print(question->name, name, sizeof name);
-        INFO(PUB_S_SRP " question: type %d class %d " PRI_S_SRP,
-             dso != NULL ? "push" : " dns", question->type, question->qclass, name);
-    }
-
-    dnssd_query_t *query = calloc(1,sizeof *query);
-    require_action_quiet(query != NULL, exit, *rcode = dns_rcode_servfail;
-        ERROR("Unable to allocate memory for query on " PRI_S_SRP, name));
-    RETAIN_HERE(query);
-
-    query->response = malloc(sizeof *query->response);
-    require_action_quiet(query->response != NULL, exit, *rcode = dns_rcode_servfail;
-        ERROR("Unable to allocate memory for query response on " PRI_S_SRP, name));
-
-    query->data_size = DNS_DATA_SIZE;
-
-    // Zero out the DNS header, but not the data.
-    memset(query->response, 0, DNS_HEADER_SIZE);
-
-    query->serviceFlags = 0;
-
-    // If this is a local query, add ".local" to the end of the name and require multicast.
-    if (sdt != NULL && sdt->interface) {
-        query->serviceFlags |= kDNSServiceFlagsForceMulticast;
-    } else {
-        query->serviceFlags |= kDNSServiceFlagsReturnIntermediates;
-    }
-    // Name now contains the name we want mDNSResponder to look up.
-
-    // The only thing holding a reference to query is its tracker.
-    query->tracker = tracker;
-    RETAIN_HERE(query->tracker);
-
-    // Remember whether this is a long-lived query.
-    query->dso = dso;
-
-    // Retain the question, as we will need it to send a response.
-    if (message != NULL) {
-        query->question = message;
-        ioloop_message_retain(query->question);
-    }
-
-    // Start writing the response
-    dp_query_towire_reset(query);
-
-    bool new_entry;
-    question_t *question_asked = dp_query_question_cache_copy(question, &new_entry);
-    require_action_quiet(question_asked != NULL, exit, *rcode = dns_rcode_servfail);
-    query->question_asked = question_asked;
-    // Ownership has been transferred to query->question_asked; NULL question_asked.
-    question_asked = NULL;
-
-    // add the query to the list of queries that are asking this question.
-    dnssd_query_t **qr = &(query->question_asked->queries);
-    while (*qr != NULL) {
-        qr = &(*qr)->question_next;
-    }
-    *qr = query;
-    INFO(PUB_S_SRP " cache entry for question: type %d class %d " PRI_S_SRP,
-         new_entry ? "new" : " existing", question->type, question->qclass, name);
-    *rcode = dns_rcode_noerror;
-
-exit:
-    if (*rcode != dns_rcode_noerror && query != NULL) {
-        RELEASE_HERE(query, dnssd_query_finalize);
-        query = NULL;
-    }
-    return query;
-}
-
-
-static void
-dns_push_query_answer_process(DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                              const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                              uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
-{
-    dnssd_query_t *query = context;
-    uint8_t *revert = query->towire.p;
-
-    VALIDATE_TRACKER_CONNECTION_NON_NULL();
-
-    // From DNSSD-Hybrid, for mDNS queries:
-    // If we have cached answers, respond immediately, because we probably have all the answers.
-    // If we don't have cached answers, respond as soon as we get an answer (presumably more-coming will be false).
-
-    // The spec says to not query if we have cached answers.   We trust the DNSServiceQueryRecord call to handle this.
-
-    // If we switch to using a single connection to mDNSResponder, we could have !more-coming trigger a flush of
-    // all outstanding queries that aren't waiting on a time trigger.   This is because more-coming isn't
-    // query-specific
-
-    INFO("PUSH " PRI_S_SRP " %d %d %x %d", fullname, rrtype, rrclass, rdlen, errorCode);
-
-    // query_state_waiting means that we're answering a regular DNS question
-    if (errorCode == kDNSServiceErr_NoError) {
-        dns_push_start(query);
-
-        const void *rdata_to_send;
-        uint32_t ttl_to_send;
-        // If kDNSServiceFlagsAdd is set, it's an add, otherwise a delete.
-    re_add:
-        if (flags & kDNSServiceFlagsAdd) {
-            rdata_to_send = rdata;
-            ttl_to_send = ttl;
-            INFO("DNS Push adding record - "
-                 "name: " PRI_S_SRP ", rrtype: " PUB_S_SRP ", rrclass: " PUB_S_SRP ", rdlen: %u, ttl: %u.",
-                 fullname, dns_rrtype_to_string(rrtype), dns_qclass_to_string(rrclass), rdlen, ttl_to_send);
-        } else {
-            // See <https://tools.ietf.org/html/rfc8765#section-6.3.1>.
-        #define TTL_TO_REMOVE_INDIVIDUAL_RECORDS    0xFFFFFFFF
-        #define TTL_TO_REMOVE_MULTIPLE_RECORDS      0xFFFFFFFE
-            if (rdlen == 0) {
-                // Remove specified RRset from a name in given class:
-                // TTL = 0xFFFFFFFE, RDLEN = 0,
-                // CLASS and TYPE specify the RRset being removed.
-                rdata_to_send = NULL;
-                ttl_to_send = TTL_TO_REMOVE_MULTIPLE_RECORDS;
-            } else {
-                // Remove an individual RR from a name:
-                // TTL = 0xFFFFFFFF,
-                // CLASS, TYPE, RDLEN, and RDATA specify the RR being removed.
-                rdata_to_send = rdata;
-                ttl_to_send = TTL_TO_REMOVE_INDIVIDUAL_RECORDS;
-            }
-            INFO("DNS Push removing record - "
-                 "name: " PRI_S_SRP ", rrtype: " PUB_S_SRP ", rrclass: " PUB_S_SRP ", rdlen: %u, ttl: 0x%X.",
-                 fullname, dns_rrtype_to_string(rrtype), dns_qclass_to_string(rrclass), rdlen, ttl_to_send);
-        }
-
-        // Do the update.
-        dp_query_add_data_to_response(query, fullname, rrtype, rrclass, rdlen, rdata_to_send, ttl_to_send, false);
-
-        if (query->towire.truncated) {
-            query->towire.truncated = false;
-            query->towire.p = revert;
-            query->towire.error = 0;
-            dp_push_response(query);
-            dns_push_start(query);
-            goto re_add;
-        }
-
-        // If there isn't more coming, send a DNS Push notification now.
-        // XXX If enough comes to fill the response, send the message.
-        if (!(flags & kDNSServiceFlagsMoreComing)) {
-            dp_push_response(query);
-        }
-    } else if (errorCode != kDNSServiceErr_NoSuchRecord) { // Do nothing if kDNSServiceErr_NoSuchRecord is received.
-        ERROR("unexpected error code %d", errorCode);
-        dnssd_query_cancel(query);
-    }
-}
-
-static void
-dns_push_subscribe(dp_tracker_t *tracker, const dns_wire_t *header, dso_state_t *dso, dns_rr_t *question,
-                   const char *activity_name, const char * UNUSED opcode_name)
-{
-    int rcode;
-    dnssd_query_t *query = dp_query_create(tracker, question, NULL, dso, &rcode);
-
-    if (!query) {
-        dso_simple_response(tracker->connection, NULL, header, rcode);
-        return;
-    }
-
-    dso_activity_t *activity = dso_add_activity(dso, activity_name, push_subscription_activity_type, query,
-                                                dns_push_cancel);
-    RETAIN_HERE(query); // The activity holds a reference to the query.
-    query->activity = activity;
-    bool dns64 = false;
-#if SRP_FEATURE_NAT64
-    if (route_states->srp_server->srp_nat64_enabled) {
-        dns64 = nat64_is_active() && !srp_adv_host_is_homekit_accessory(route_states->srp_server, &tracker->connection->address);
-    }
-#endif
-    if (!dp_query_start(query, &rcode, dns64)) {
-        dso_simple_response(tracker->connection, NULL, header, rcode);
-        dnssd_query_cancel(query);
-    } else {
-        dso_simple_response(tracker->connection, NULL, header, dns_rcode_noerror);
-        dp_query_reply_from_cache(query->question_asked, query);
-    }
-    // dp_query_create() returned the query retained; when we added the query to the activity, we retained it again;
-    // if something went wrong, the second retain was released, but whether or not something went wrong, we can now
-    // safely release the initial retain.
-    RELEASE_HERE(query, dnssd_query_finalize);
-}
-
-static void
-dns_push_reconfirm(comm_t *comm, const dns_wire_t *header, dso_state_t *dso)
-{
-    dns_rr_t question;
-    char name[DNS_MAX_NAME_SIZE + 1];
-    uint16_t rdlen;
-    memset(&question, 0, sizeof(question));
-
-    // The TLV offset should always be pointing into the message.
-    unsigned offp = (unsigned)(dso->primary.payload - &header->data[0]);
-    unsigned len = offp + dso->primary.length;
-
-    // Parse the name, rrtype and class.   We say there's no rdata even though there is
-    // because there's no ttl and also we want the raw rdata, not parsed rdata.
-    if (!dns_rr_parse(&question, header->data, len, &offp, false, false) ||
-        !dns_u16_parse(header->data, len, &offp, &rdlen))
-    {
-        dso_simple_response(comm, NULL, header, dns_rcode_formerr);
-        ERROR("dns_push_reconfirm: RR parse from %s failed", dso->remote_name);
-        goto out;
-    }
-    if (rdlen + offp != len) {
-        dso_simple_response(comm, NULL, header, dns_rcode_formerr);
-        ERROR("dns_push_reconfirm: RRdata parse from %s failed: length mismatch (%d != %d)",
-              dso->remote_name, rdlen + offp, len);
-        goto out;
-    }
-
-    if ((dp_served(question.name, name, sizeof name))) {
-        size_t name_len = strlen(name);
-        if (name_len + sizeof local_suffix > sizeof name) {
-            dso_simple_response(comm, NULL, header, dns_rcode_formerr);
-            ERROR("dns_push_reconfirm: name is too long for .local suffix: %s", name);
-            goto out;
-        }
-        memcpy(&name[name_len], local_suffix, sizeof local_suffix);
-    } else {
-        dns_name_print(question.name, &name[8], sizeof name - 8);
-    }
-    // transmogrify name.
-    DNSServiceReconfirmRecord(0, kDNSServiceInterfaceIndexAny, name,
-                              question.type, question.qclass, rdlen, &header->data[offp]);
-    dso_simple_response(comm, NULL, header, dns_rcode_noerror);
-out:
-    dns_rrdata_free(&question);
-    dns_name_free(question.name);
-}
-
-static void
-dns_push_unsubscribe(dso_activity_t *activity)
-{
-    dnssd_query_t *query = activity->context;
-    dnssd_query_cancel(query);
-    // No response, unsubscribe is unidirectional.
-}
-
-static void
-dns_push_subscription_change(const char *opcode_name, dp_tracker_t *tracker, const dns_wire_t *header, dso_state_t *dso)
-{
-    // type-in-hex/class-in-hex/name-to-subscribe
-    char activity_name[DNS_MAX_NAME_SIZE_ESCAPED + 3 + 4 + 4];
-    dso_activity_t *activity;
-
-    // The TLV offset should always be pointing into the message.
-    unsigned offp = (unsigned)(dso->primary.payload - &header->data[0]);
-    // Get the question
-    dns_rr_t question;
-
-    memset(&question, 0, sizeof(question));
-    if (!dns_rr_parse(&question, header->data, offp + dso->primary.length, &offp, false, false)) {
-        // Unsubscribes are unidirectional, so no response can be sent
-        if (dso->primary.opcode != kDSOType_DNSPushUnsubscribe) {
-            dso_simple_response(tracker->connection, NULL, header, dns_rcode_formerr);
-        }
-        ERROR("RR parse for %s from %s failed", dso->remote_name, opcode_name);
-        goto out;
-    }
-
-    // Concoct an activity name.
-    snprintf(activity_name, sizeof activity_name, "%04x%04x", question.type, question.qclass);
-    if ((dp_served(question.name, &activity_name[8], (sizeof activity_name) - 8))) {
-        size_t len = strlen(activity_name);
-        if (len + sizeof local_suffix + 8 > sizeof (activity_name)) {
-            ERROR("activity name overflow for %s", activity_name);
-            goto out;
-        }
-        const int lslen = sizeof local_suffix;
-        strncpy(&activity_name[len], local_suffix, lslen);
-    } else {
-        dns_name_print(question.name, &activity_name[8], (sizeof activity_name) - 8);
-    }
-
-    activity = dso_find_activity(dso, activity_name, push_subscription_activity_type, NULL);
-    if (activity == NULL) {
-        // Unsubscribe with no activity means no work to do; just return noerror.
-        if (dso->primary.opcode != kDSOType_DNSPushSubscribe) {
-            ERROR("dso_message: %s for %s when no subscription exists.", opcode_name, activity_name);
-            if (dso->primary.opcode == kDSOType_DNSPushReconfirm) {
-                dso_simple_response(tracker->connection, NULL, header, dns_rcode_noerror);
-            }
-        } else {
-            // In this case we have a push subscribe for which no subscription exists, which means we can do it.
-            dns_push_subscribe(tracker, header, dso, &question, activity_name, opcode_name);
-        }
-    } else {
-        // Subscribe with a matching activity means no work to do; just return noerror.
-        if (dso->primary.opcode == kDSOType_DNSPushSubscribe) {
-            dso_simple_response(tracker->connection, NULL, header, dns_rcode_noerror);
-        }
-        // Otherwise cancel the subscription.
-        else {
-            dns_push_unsubscribe(activity);
-        }
-    }
-out:
-    dns_rrdata_free(&question);
-    dns_name_free(question.name);
-}
-
-static void dso_message(dp_tracker_t *tracker, message_t *message, dso_state_t *dso)
-{
-    switch(dso->primary.opcode) {
-    case kDSOType_DNSPushSubscribe:
-        dns_push_subscription_change("DNS Push Subscribe", tracker, &message->wire, dso);
-        break;
-    case kDSOType_DNSPushUnsubscribe:
-        dns_push_subscription_change("DNS Push Unsubscribe", tracker, &message->wire, dso);
-        break;
-
-    case kDSOType_DNSPushReconfirm:
-        dns_push_reconfirm(tracker->connection, &message->wire, dso);
-        break;
-
-    case kDSOType_DNSPushUpdate:
-        INFO("bogus push update message %d", dso->primary.opcode);
-        dso_state_cancel(dso);
-        break;
-
-#if SRP_FEATURE_REPLICATION
-    case kDSOType_SRPLSession:
-        if (dso->activities != NULL) {
-            dso_state_cancel(dso);
-            ERROR(PRI_S_SRP ": SRP Replication session start received on a connection that is already doing DNS Push.",
-                  tracker->connection->name);
-            return;
-        }
-        srpl_dso_server_message(tracker->connection, message, dso, route_states->srp_server);
-        break;
-#endif
-
-    default:
-        INFO("unexpected primary TLV %d", dso->primary.opcode);
-        dso_simple_response(tracker->connection, NULL, &message->wire, dns_rcode_dsotypeni);
-        break;
-    }
-    // XXX free the message if we didn't consume it.
-}
-
-static void dns_push_callback(void *context, void *event_context,
-                              dso_state_t *dso, dso_event_type_t eventType)
-{
-    message_t *message;
-    switch(eventType)
-    {
-    case kDSOEventType_DNSMessage:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Message (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DNSResponse:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Response (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DSOMessage:
-        INFO("DSO Message (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        message = event_context;
-        dso_message((dp_tracker_t *)context, message, dso);
-        break;
-    case kDSOEventType_DSOResponse:
-        INFO("DSO Response (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        break;
-
-    case kDSOEventType_Finalize:
-        INFO("Finalize");
-        break;
-
-    case kDSOEventType_Connected:
-        INFO("Connected to " PRI_S_SRP, dso->remote_name);
-        break;
-
-    case kDSOEventType_ConnectFailed:
-        INFO("Connection to " PRI_S_SRP " failed", dso->remote_name);
-        break;
-
-    case kDSOEventType_Disconnected:
-        INFO("Connection to " PRI_S_SRP " disconnected", dso->remote_name);
-        break;
-    case kDSOEventType_ShouldReconnect:
-        INFO("Connection to " PRI_S_SRP " should reconnect (not for a server)", dso->remote_name);
-        break;
-    case kDSOEventType_Inactive:
-        INFO("Inactivity timer went off, closing connection.");
-        break;
-    case kDSOEventType_Keepalive:
-        INFO("should send a keepalive now.");
-        break;
-    case kDSOEventType_KeepaliveRcvd:
-        INFO("keepalive received.");
-        break;
-    case kDSOEventType_RetryDelay:
-        INFO("keepalive received.");
-        break;
-    }
-}
-
-static void
-dp_dns_query(dp_tracker_t *tracker, message_t *message, dns_rr_t *question)
-{
-    int rcode;
-
-    // We do not support queries in the ".local" domain
-    if (is_in_local_domain(question->name)) {
-        dso_simple_response(tracker->connection, message, &message->wire, dns_rcode_refused);
-        return;
-    }
-
-    dnssd_query_t *query = dp_query_create(tracker, question, message, NULL, &rcode);
-    const char *failnote = NULL;
-    if (!query) {
-        dso_simple_response(tracker->connection, message, &message->wire, rcode);
-        return;
-    }
-    dns_rcode_set(query->response, dns_rcode_noerror);
-
-    // For DNS queries, we need to return the question.
-    query->response->qdcount = htons(1);
-    if (query->question_asked->served_domain != NULL) {
-        TOWIRE_CHECK("name", &query->towire, dns_name_to_wire(NULL, &query->towire, query->question_asked->name));
-        TOWIRE_CHECK("enclosing_domain", &query->towire,
-                     dns_full_name_to_wire(&query->enclosing_domain_pointer,
-                                           &query->towire, query->question_asked->served_domain->domain));
-    } else {
-        TOWIRE_CHECK("full name", &query->towire, dns_full_name_to_wire(NULL, &query->towire, query->question_asked->name));
-    }
-    TOWIRE_CHECK("TYPE", &query->towire, dns_u16_to_wire(&query->towire, question->type));    // TYPE
-    TOWIRE_CHECK("CLASS", &query->towire, dns_u16_to_wire(&query->towire, question->qclass));  // CLASS
-    if (failnote != NULL) {
-        ERROR("dp_dns_query: failure encoding question: %s", failnote);
-        goto fail;
-    }
-
-    // Set message ID.
-    query->towire.message->id = message->wire.id;
-
-    // We should check for OPT RR, but for now assume it's there.
-    query->is_edns0 = true;
-
-    bool dns64 = false;
-#if SRP_FEATURE_NAT64
-    if (route_states->srp_server->srp_nat64_enabled) {
-        dns64 = nat64_is_active() && !srp_adv_host_is_homekit_accessory(route_states->srp_server, &tracker->connection->address);
-    }
-#endif
-    if (dp_query_start(query, &rcode, dns64)) {
-        dp_query_track(tracker, query);
-        dp_query_reply_from_cache(query->question_asked, query);
-    } else {
-    fail:
-        dso_simple_response(tracker->connection, message, &message->wire, rcode);
-    }
-    // Query is returned retained, and dp_query_track retains it, so we always need to release the reference here.
-    RELEASE_HERE(query, dnssd_query_finalize);
-}
-
-static void
-dso_transport_finalize(comm_t *comm, const char *whence)
-{
-    dso_state_t *dso = comm->dso;
-    INFO(PRI_S_SRP " (" PUB_S_SRP ")", dso->remote_name, whence);
-    if (comm) {
-        ioloop_comm_cancel(comm);
-    }
-    free(dso);
-    comm->dso = NULL;
-}
-
-static void
-dnssd_proxy_dns_evaluate(comm_t *comm, message_t *message, dp_tracker_t *tracker)
-{
-    dns_rr_t question;
-    unsigned offset = 0;
-
-    if (tracker == NULL) {
-        tracker = calloc(1, sizeof(*tracker));
-        if (tracker == NULL) {
-            ERROR(PRI_S_SRP ": no memory for a connection tracker object!", comm->name);
-            return;
-        }
-        tracker->connection = comm;
-        ioloop_comm_retain(tracker->connection);
-        ioloop_comm_context_set(comm, tracker, dp_tracker_context_release);
-        RETAIN_HERE(tracker); // connection has a reference.
-        if (!comm->is_listener) {
-            ioloop_comm_disconnect_callback_set(comm, dp_tracker_disconnected);
-        }
-    }
-
-    // Drop incoming responses--we're a server, so we only accept queries.
-    if (dns_qr_get(&message->wire) == dns_qr_response) {
-        INFO("dropping unexpected response");
-        return;
-    }
-
-    // If this is a DSO message, see if we have a session yet.
-    switch(dns_opcode_get(&message->wire)) {
-    case dns_opcode_dso:
-        if (!comm->tcp_stream) {
-            ERROR("DSO message received on non-tcp socket %s", comm->name);
-            dso_simple_response(comm, message, &message->wire, dns_rcode_notimp);
-            return;
-        }
-
-        if (!tracker->dso) {
-            if (num_dso_connections == MAX_DSO_CONNECTIONS) {
-                // We are too busy. Return a retry-delay response.
-                INFO("no more DSO connections allowed--sending retry-delay: %d", num_dso_connections);
-                dso_retry_delay_response(comm, message, &message->wire, dns_rcode_servfail, BUSY_RETRY_DELAY_MS);
-
-                // Cancel the connection after five seconds
-                dp_tracker_idle_after(tracker, 5, NULL);
-                return;
-            }
-            tracker->dso = dso_state_create(true, 2, comm->name, dns_push_callback, tracker, NULL, comm);
-            if (!tracker->dso) {
-                ERROR("Unable to create a dso context for %s", comm->name);
-                dso_simple_response(comm, message, &message->wire, dns_rcode_servfail);
-                ioloop_comm_cancel(comm);
-                return;
-            }
-            tracker->dso->transport_finalize = dso_transport_finalize;
-            comm->dso = tracker->dso;
-
-            // Count this as a DSO connection.
-            num_dso_connections++;
-            INFO("new dso connection, count is now %d", num_dso_connections);
-        }
-        dp_tracker_not_idle(tracker);
-        dso_message_received(comm->dso, (uint8_t *)&message->wire, message->length, message);
-        break;
-
-    case dns_opcode_query:
-        // In theory this is permitted but it can't really be implemented because there's no way
-        // to say "here's the answer for this, and here's why that failed.
-        if (ntohs(message->wire.qdcount) != 1) {
-            dso_simple_response(comm, message, &message->wire, dns_rcode_formerr);
-            return;
-        }
-        memset(&question, 0, sizeof(question));
-        if (!dns_rr_parse(&question, message->wire.data, message->length, &offset, false, false)) {
-            dso_simple_response(comm, message, &message->wire, dns_rcode_formerr);
-            return;
-        }
-        dp_tracker_not_idle(tracker);
-        dp_dns_query(tracker, message, &question);
-        dns_rrdata_free(&question);
-        dns_name_free(question.name);
-        break;
-
-        // No support for other opcodes yet.
-    default:
-        dso_simple_response(comm, message, &message->wire, dns_rcode_notimp);
-        break;
-    }
-}
-
-static void
-dns_proxy_input(comm_t *comm, message_t *message, void *context)
-{
-    char buf[INET6_ADDRSTRLEN];
-    IOLOOP_NTOP(&comm->address, buf);
-    INFO("[QID0x%x] Received a new DNS message - src: " PRI_S_SRP ", message length: %ubytes.",
-         ntohs(message->wire.id), buf, message->length);
-
-    dnssd_proxy_dns_evaluate(comm, message, context);
-}
-
-// usage is only called when we are building standalone dnssd-proxy, not the combined one.
-#if (!SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-static int
-usage(const char *progname)
-{
-    ERROR("usage: %s", progname);
-    ERROR("ex: dnssd-proxy");
-    return 1;
-}
-#endif // #if (!SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-
-// Called whenever we get a connection.
-static void UNUSED
-connected(comm_t *comm)
-{
-    INFO("connection from " PRI_S_SRP, comm->name);
-    return;
-}
-
-static served_domain_t *NULLABLE
-new_served_domain(dp_interface_t *const NULLABLE interface, const char *const NONNULL domain)
-{
-    served_domain_t *sdt = calloc(1, sizeof *sdt);
-    if (sdt == NULL) {
-        ERROR("Unable to allocate served domain %s", domain);
-        return NULL;
-    }
-    size_t domain_len = strlen(domain);
-    sdt->domain_ld = malloc(domain_len + 2);
-    if (sdt->domain_ld == NULL) {
-        ERROR("Unable to allocate served domain name %s", domain);
-        free(sdt);
-        return NULL;
-    }
-    sdt->domain_ld[0] = '.';
-    sdt->domain = sdt->domain_ld + 1;
-    memcpy(sdt->domain, domain, domain_len + 1);
-    sdt->domain_name = dns_pres_name_parse(sdt->domain);
-    sdt->interface = interface;
-    if (sdt->domain_name == NULL) {
-        if (interface != NULL) {
-            ERROR("invalid domain name for interface %s: %s", interface->name, sdt->domain);
-        } else {
-            ERROR("invalid domain name: %s", sdt->domain);
-        }
-        free(sdt);
-        return NULL;
-    }
-    sdt->next = served_domains;
-    served_domains = sdt;
-
-    INFO("new served domain created - domain name: " PRI_S_SRP, sdt->domain);
-    return sdt;
-}
-
-static served_domain_t *NULLABLE
-find_served_domain(const char *const NONNULL domain)
-{
-    served_domain_t *current;
-    for (current = served_domains; current != NULL; current = current->next) {
-        if (strcasecmp(domain, current->domain) == 0) {
-            break;
-        }
-    }
-
-    return current;
-}
-
-// served domain can only go away when combined with srp-mdns-proxy and interface going up and down.
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static void
-delete_served_domain(served_domain_t *const served_domain)
-{
-    INFO("served domain removed - domain name: " PRI_S_SRP, served_domain->domain);
-
-    // free struct interface *NULLABLE interface
-    if (served_domain->interface != NULL) {
-        interface_addr_t *current = served_domain->interface->addresses;
-        interface_addr_t *next;
-        for (;current != NULL; current = next) {
-            next = current->next;
-            free(current);
-        }
-        if (served_domain->interface->name != NULL) {
-            free(served_domain->interface->name);
-        }
-        free(served_domain->interface);
-    }
-
-    // free hardwired_t *NULLABLE hardwired_responses
-    if (served_domain->hardwired_responses != NULL) {
-        hardwired_t *current = served_domain->hardwired_responses;
-        hardwired_t *next;
-        for (; current != NULL; current = next) {
-            next = current->next;
-            free(current);
-        }
-    }
-
-    // free dns_name_t *NONNULL domain_name;
-    if (served_domain->domain_name != NULL) {
-        dns_name_free(served_domain->domain_name);
-    }
-
-    // free char *NONNULL domain_ld;
-    free(served_domain->domain_ld);
-
-    // free served_domain_t *
-    free(served_domain);
-}
-
-bool
-delete_served_domain_by_interface_name(const char *const NONNULL interface_name)
-{
-    bool deleted = false;
-
-    served_domain_t *current;
-    served_domain_t *prev = NULL;
-    for(current= served_domains; current != NULL; prev = current, current = current->next) {
-        if (current->interface == NULL) {
-            continue;
-        }
-        if (strcmp(interface_name, current->interface->name) != 0) {
-            continue;
-        }
-
-        INFO("served domain deleted with interface - "
-            "domain: " PRI_S_SRP ", interface name: " PUB_S_SRP, current->domain, interface_name);
-
-        // Since we are removing the entire served domain and the interface, the addresses that are associated with
-        // this interface will also be removed. Therefore, any hardwired response that contains these addresses should
-        // also be removed.
-        for (interface_addr_t *address = current->interface->addresses; address != NULL; address = address->next) {
-            dnssd_hardwired_process_addr_change(&address->addr, &address->mask, false);
-        }
-
-        if (prev == NULL) {
-            served_domains = current->next;
-        } else {
-            prev->next = current->next;
-        }
-
-        delete_served_domain(current);
-        deleted = true;
-        break;
-    }
-
-    return deleted;
-}
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-// Dynamic interface detection...
-// This is called whenever a new interface address is encountered.
-
-void
-dnssd_proxy_ifaddr_callback(void *UNUSED context, const char *name, const addr_t *address, const addr_t *mask,
-    uint32_t UNUSED flags, enum interface_address_change event_type)
-{
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-    bool is_new_interface = true;
-#endif
-    bool succeeded;
-    const char *const action = (event_type == interface_address_added ? "Adding" : "Removing");
-
-    if (event_type == interface_address_unchanged) {
-        goto exit;
-    }
-
-    int interface_index = if_nametoindex(name);
-    if (address->sa.sa_family == AF_INET) {
-        IPv4_ADDR_GEN_SRP((const uint8_t *)&address->sin.sin_addr, addr_buf);
-        IPv4_ADDR_GEN_SRP((const uint8_t *)&mask->sin.sin_addr, mask_buf);
-        INFO("Interface " PUB_S_SRP " address " PRI_IPv4_ADDR_SRP " mask " PRI_IPv4_ADDR_SRP " index %d " PUB_S_SRP,
-             name, IPv4_ADDR_PARAM_SRP((const uint8_t *)&address->sin.sin_addr, addr_buf),
-             IPv4_ADDR_PARAM_SRP((const uint8_t *)&mask->sin.sin_addr, mask_buf), interface_index,
-             event_type == interface_address_added ? "added" : "removed");
-    } else if (address->sa.sa_family == AF_INET6) {
-        IPv6_ADDR_GEN_SRP((const uint8_t *)&address->sin6.sin6_addr, addr_buf);
-        IPv6_ADDR_GEN_SRP((const uint8_t *)&mask->sin6.sin6_addr, mask_buf);
-        INFO("Interface " PUB_S_SRP " address " PRI_IPv6_ADDR_SRP " mask " PRI_IPv6_ADDR_SRP " index %d " PUB_S_SRP,
-             name, IPv6_ADDR_PARAM_SRP((const uint8_t *)&address->sin6.sin6_addr, addr_buf),
-             IPv6_ADDR_PARAM_SRP((const uint8_t *)&mask->sin6.sin6_addr, mask_buf), interface_index,
-             event_type == interface_address_added ? "added" : "removed");
-    } else {
-        INFO("Interface " PUB_S_SRP " address type %d index %d " PUB_S_SRP, name, address->sa.sa_family, interface_index,
-             event_type == interface_address_added ? "added" : "removed");
-        INFO("ignoring non IP address");
-        goto exit;
-    }
-
-#if THREAD_BORDER_ROUTER && SRP_FEATURE_COMBINED_DNSSD_PROXY
-    // Ignore Thread interface
-    bool is_valid_address = thread_interface_name == NULL || strcmp(thread_interface_name, name) != 0;
-    if (!is_valid_address) {
-        INFO("skipping thread interface address");
-        goto exit;
-    }
-#endif
-
-    // Add/remove the address from the corresponding served domain.
-    served_domain_t **sp = &served_domains;
-    while (*sp != NULL) {
-        served_domain_t *current = *sp;
-        // Only change the served domain that owns the current interface and address.
-        if (current->interface == NULL || current->interface->ifindex == 0 ||
-            strcmp(current->interface->name, name) != 0) {
-            goto again;
-        }
-
-        INFO(PUB_S_SRP " address from the served domain - domain: " PRI_S_SRP, action, current->domain);
-        succeeded = interface_process_addr_change(current->interface, address, mask, event_type);
-        require_action_quiet(succeeded, exit, ERROR("failed to " PUB_S_SRP " new interface address", action));
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-        is_new_interface = false;
-
-        // if interface loses all usable IP addresses, the interface has gone, remove this interface and the
-        // corresponding served domain.
-        if (event_type == interface_address_deleted) {
-            if (current->interface->addresses == NULL) {
-                INFO("Removing served domain with 0 address - domain: " PRI_S_SRP ", interface name: " PUB_S_SRP,
-                    current->domain, current->interface->name);
-                *sp = current->next;
-                delete_served_domain(current);
-                continue;
-            }
-        }
-#else // SRP_FEATURE_DYNAMIC_CONFIGURATION
-        if (current->interface->addresses == NULL) {
-            current->interface->ifindex = 0;
-        }
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-    again:
-        sp = &(*sp)->next;
-    }
-
-    // We will only create new served domain from dnssd_proxy_ifaddr_callback if the callback gets called from
-    // srp-mdns-proxy.
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-    if (event_type == interface_address_added && is_new_interface) {
-        served_domain_t *const new_served_domain = add_new_served_domain_with_interface(name, address, mask);
-        verify_action(new_served_domain != NULL,
-            ERROR("failed to add new served domain ""- interface name: " PUB_S_SRP, name));
-
-        bool hardwired_set = dnssd_hardwired_setup_for_served_domain(new_served_domain);
-        if (!hardwired_set) {
-            ERROR("failed to setup hardwired response for newly created served domain - domain: " PRI_S_SRP, name);
-            delete_served_domain(new_served_domain);
-        }
-        INFO("New served domain created and hardwired response created - domain: " PRI_S_SRP,
-            new_served_domain->domain);
-    }
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-    // Added or removed address will possibly need hardwired response to be updated.
-    dnssd_hardwired_process_addr_change(address, mask, event_type == interface_address_added);
-
-exit:
-    return;
-}
-
-#if !SRP_FEATURE_DYNAMIC_CONFIGURATION
-// Config file parsing...
-static bool
-interface_handler(void * UNUSED context, const char * UNUSED filename, char **hunks, int UNUSED num_hunks,
-                  int UNUSED lineno)
-{
-    dp_interface_t *interface = calloc(1, sizeof *interface);
-    if (interface == NULL) {
-        ERROR("Unable to allocate interface %s", hunks[1]);
-        return false;
-    }
-
-    interface->name = strdup(hunks[1]);
-    if (interface->name == NULL) {
-        ERROR("Unable to allocate interface name %s", hunks[1]);
-        free(interface);
-        return false;
-    }
-
-    if (!strcmp(hunks[0], "nopush")) {
-        interface->no_push = true;
-    }
-
-    if (new_served_domain(interface, hunks[2]) == NULL) {
-        free(interface->name);
-        free(interface);
-        return false;
-    }
-    return true;
-}
-
-static bool
-port_handler(void * UNUSED context, const char * UNUSED filename, char **hunks, int UNUSED num_hunks, int UNUSED lineno)
-{
-    char *ep = NULL;
-    long port = strtol(hunks[1], &ep, 10);
-    if (port < 0 || port > 65535 || *ep != 0) {
-        ERROR("Invalid port number: %s", hunks[1]);
-        return false;
-    }
-    if (!strcmp(hunks[0], "udp-port")) {
-        udp_port = port;
-    } else if (!strcmp(hunks[0], "tcp-port")) {
-        tcp_port = port;
-    } else if (!strcmp(hunks[0], "tls-port")) {
-        tls_port = port;
-    }
-    return true;
-}
-
-static bool
-config_string_handler(char **ret, const char * UNUSED filename, const char *string, int UNUSED lineno, bool tdot,
-                                  bool ldot)
-{
-    char *s;
-    int add_trailing_dot = 0;
-    int add_leading_dot = ldot ? 1 : 0;
-    size_t len = strlen(string);
-
-    // Space for NUL and leading dot.
-    if (tdot && len > 0 && string[len - 1] != '.') {
-        add_trailing_dot = 1;
-    }
-    s = malloc(strlen(string) + add_leading_dot + add_trailing_dot + 1);
-    if (s == NULL) {
-        ERROR("Unable to allocate domain name %s", string);
-        return false;
-    }
-    *ret = s;
-    if (ldot) {
-        *s++ = '.';
-    }
-    memcpy(s, string, len + add_leading_dot + add_trailing_dot + 1);
-    if (add_trailing_dot) {
-        s[len] = '.';
-        s[len + 1] = 0;
-    }
-    return true;
-}
-
-static bool
-my_name_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    static char *new_name = NULL;
-    if (new_name != NULL) {
-        free(new_name);
-        my_name = NULL;
-        new_name = NULL;
-    }
-    if (!config_string_handler(&new_name, filename, hunks[1], lineno, false, false)) {
-        return false;
-    }
-    my_name = new_name;
-    size_t len = strlen(my_name);
-    size_t bigger = sizeof(DOT_HOME_NET_DOMAIN) > sizeof(DOT_LOCAL) ? sizeof(DOT_HOME_NET_DOMAIN) : sizeof(DOT_LOCAL);
-    if (len >= sizeof(local_host_name) - bigger) {
-        ERROR("truncating local hostname %s", my_name);
-        return false;
-    }
-
-    // Set up existing local host name with .local. suffix
-    snprintf(local_host_name_dot_local, sizeof(local_host_name_dot_local), "%s" DOT_LOCAL, my_name);
-
-    // Set up existing local host name with .home.net. suffix
-    snprintf(local_host_name, sizeof(local_host_name), "%s" DOT_HOME_NET_DOMAIN, my_name);
-    return true;
-}
-
-static bool
-listen_addr_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    if (num_listen_addrs == MAX_ADDRS) {
-        ERROR("Only %d IPv4 listen addresses can be configured.", MAX_ADDRS);
-        return false;
-    }
-    return config_string_handler(&listen_addrs[num_listen_addrs++], filename, hunks[1], lineno, false, false);
-}
-
-static bool
-publish_addr_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    if (num_publish_addrs == MAX_ADDRS) {
-        ERROR("Only %d addresses can be published.", MAX_ADDRS);
-        return false;
-    }
-    return config_string_handler(&publish_addrs[num_publish_addrs++], filename, hunks[1], lineno, false, false);
-}
-
-static bool
-tls_key_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    return config_string_handler(&tls_key_filename, filename, hunks[1], lineno, false, false);
-}
-
-static bool
-tls_cert_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    return config_string_handler(&tls_cert_filename, filename, hunks[1], lineno, false, false);
-}
-
-static bool
-tls_cacert_handler(void * UNUSED context, const char *filename, char **hunks, int UNUSED num_hunks, int lineno)
-{
-    return config_string_handler(&tls_cacert_filename, filename, hunks[1], lineno, false, false);
-}
-
-config_file_verb_t dp_verbs[] = {
-    { "interface",    3, 3, interface_handler },    // interface <name> <domain>
-    { "nopush",       3, 3, interface_handler },    // nopush <name> <domain>
-    { "udp-port",     2, 2, port_handler },         // udp-port <number>
-    { "tcp-port",     2, 2, port_handler },         // tcp-port <number>
-    { "tls-port",     2, 2, port_handler },         // tls-port <number>
-    { "my-name",      2, 2, my_name_handler },      // my-name <domain name>
-    { "tls-key",      2, 2, tls_key_handler },      // tls-key <filename>
-    { "tls-cert",     2, 2, tls_cert_handler },     // tls-cert <filename>
-    { "tls-cacert",   2, 2, tls_cacert_handler },   // tls-cacert <filename>
-    { "listen-addr",  2, 2, listen_addr_handler },  // listen-addr <IP address>
-    { "publish-addr", 2, 2, publish_addr_handler }  // publish-addr <IP address>
-};
-#define NUMCFVERBS ((sizeof dp_verbs) / sizeof (config_file_verb_t))
-#endif // !SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-static wakeup_t *tls_listener_wakeup;
-static int tls_listener_index;
-static void dnssd_tls_listener_restart(void *NULLABLE context);
-
-static void dnssd_tls_listener_listen(void *UNUSED context)
-{
-    addr_t addr;
-    INFO("starting DoT listener");
-    memset(&addr, 0, sizeof(addr));
-    addr.sa.sa_family = AF_UNSPEC;
-#ifndef NOT_HAVE_SA_LEN
-    addr.sa.sa_len = sizeof(addr.sin6);
-#endif
-    addr.sin6.sin6_port = htons(tls_port);
-#ifndef EXCLUDE_TLS
-    listener[tls_listener_index] = ioloop_listener_create(true, true, NULL, 0, &addr, NULL, "DNS Push Listener",
-                                                          dns_proxy_input, NULL, dnssd_tls_listener_restart, NULL,
-                                                          NULL, srp_tls_configure, NULL);
-#else
-    listener[tls_listener_index] = ioloop_listener_create(true, true, NULL, 0, &addr, NULL, "DNS Push Listener",
-                                                          dns_proxy_input, NULL, dnssd_tls_listener_restart, NULL,
-                                                          NULL, NULL, NULL);
-#endif
-    if (listener[tls_listener_index] == NULL) {
-        ERROR("DNS Push listener: fail.");
-        goto exit;
-    }
-
-    // Schedule a wake up timer to rotate the expired TLS certificate.
-    schedule_tls_certificate_rotation(&tls_listener_wakeup, listener[tls_listener_index]);
-exit:
-    return;
-}
-
-static void
-dnssd_tls_listener_restart(void *const NULLABLE context)
-{
-    const bool doing_rotation = listener[tls_listener_index]->tls_rotation_ready;
-    ioloop_listener_release(listener[tls_listener_index]);
-    listener[tls_listener_index] = NULL;
-
-    if (doing_rotation) {
-        const bool succeeded = srp_tls_init();
-        if (!succeeded) {
-            FAULT("srp_tls_init failed.");
-            return;
-        }
-
-        dnssd_tls_listener_listen(context);
-    } else {
-        INFO("Creation of TLS listener failed; reattempting in 10s.");
-
-        if (tls_listener_wakeup == NULL) {
-            tls_listener_wakeup = ioloop_wakeup_create();
-            if (tls_listener_wakeup == NULL) {
-                ERROR("Unable to allocate wakeup in order to re-attempt TLS listener creation.");
-                return;
-            }
-        }
-        ioloop_add_wake_event(tls_listener_wakeup, NULL, dnssd_tls_listener_listen, NULL, 10 * MSEC_PER_SEC);
-    }
-}
-
-static void
-dnssd_push_setup(void)
-{
-    tls_listener_index = num_listeners++;
-    dnssd_tls_listener_listen(NULL);
-
-    // Only set hardwired response when dynamic configuration is enabled.  Dynamic configuration
-    // sets up hardwired response when new address of the interface is added.
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION // not set hardwired response for now
-    dnssd_hardwired_push_setup();
-#endif // !SRP_FEATURE_DYNAMIC_CONFIGURATION
-}
-
-#if (!SRP_FEATURE_CAN_GENERATE_TLS_CERT)
-
-// Start a key generation or cert signing program.   Arguments are key=value pairs.
-// Arguments that can be constant should be <"key=value", NULL>.   Arguments that
-// have a variable component should be <"key", value">.  References to arguments
-// will be held, except that if the rhs of the pair is variable, memory is allocated
-// to store the key=value pair, so the neither the key nor the value is retained.
-// The callback is called when the program exits.
-
-static void
-keyprogram_start(const char *program, subproc_callback_t callback, ...)
-{
-#define MAX_SUBPROC_VARS 3
-    size_t lens[MAX_SUBPROC_VARS];
-    char *vars[MAX_SUBPROC_VARS];
-    int num_vars = 0;
-    char *argv[MAX_SUBPROC_ARGS + 1];
-    int argc = 0;
-    va_list vl;
-    int i;
-    subproc_t *subproc = NULL;
-
-    va_start(vl, callback);
-    while (true) {
-        char *vname, *value;
-        char *arg;
-
-        vname = va_arg(vl, char *);
-        if (vname == NULL) {
-            break;
-        }
-        value = va_arg(vl, char *);
-
-        if (argc >= MAX_SUBPROC_ARGS) {
-            ERROR("keyprogram_start: too many arguments.");
-        }
-
-        if (value == NULL) {
-            arg = vname;
-        } else {
-            if (num_vars >= MAX_SUBPROC_VARS) {
-                ERROR("Too many variable args: %s %s", vname, value);
-                goto out;
-            }
-            lens[num_vars] = strlen(vname) + strlen(value) + 2;
-            vars[num_vars] = malloc(lens[num_vars]);
-            if (vars[num_vars] == NULL) {
-                ERROR("No memory for variable key=value %s %s", vname, value);
-                goto out;
-            }
-            snprintf(vars[num_vars], lens[num_vars], "%s=%s", vname, value);
-            arg = vars[num_vars];
-            num_vars++;
-        }
-        argv[argc++] = arg;
-    }
-    argv[argc] = NULL;
-    subproc = ioloop_subproc(program, argv, argc, callback, NULL, NULL);
-    if (subproc != NULL) {
-        ioloop_subproc_run_sync(subproc);
-        ioloop_subproc_release(subproc);
-    }
-out:
-    for (i = 0; i < num_vars; i++) {
-        free(vars[i]);
-    }
-}
-
-static bool
-finished_okay(const char *context, int status, const char *error)
-{
-    // If we get an error, something failed before the program had been successfully started.
-    if (error != NULL) {
-        ERROR("%s failed on startup: %s", context, error);
-    }
-
-    // The key file generation process completed
-    else if (WIFEXITED(status)) {
-        if (WEXITSTATUS(status) != 0) {
-            ERROR("%s program exited with status %d", context, status);
-            // And that means we don't have DNS Push--sorry!
-        } else {
-            return true;
-        }
-    } else if (WIFSIGNALED(status)) {
-        ERROR("%s program exited on signal %d", context, WTERMSIG(status));
-        // And that means we don't have DNS Push--sorry!
-    } else if (WIFSTOPPED(status)) {
-        ERROR("%s program stopped on signal %d", context, WSTOPSIG(status));
-        // And that means we don't have DNS Push--sorry!
-    } else {
-        ERROR("%s program exit status unknown: %d", context, status);
-        // And that means we don't have DNS Push--sorry!
-    }
-    return false;
-}
-
-// Called after the cert has been generated.
-static void
-certfile_finished_callback(void *NULLABLE context, int status, const char *error)
-{
-    (void)context;
-
-    // If we were able to generate a cert, we can start DNS Push service and start advertising it.
-    if (finished_okay("Certificate signing", status, error)) {
-        int i = num_listeners;
-
-        dnssd_push_setup();
-
-        for (; i < num_listeners; i++) {
-            INFO("Started " PUB_S_SRP, listener[i]->name);
-        }
-    }
-}
-
-// Called after the key has been generated.
-static void
-keyfile_finished_callback(void *context, int status, const char *error)
-{
-    (void)context;
-    if (finished_okay("Keyfile generation", status, error)) {
-        INFO("Keyfile generation completed.");
-
-    // XXX dates need to not be constant!!!
-    keyprogram_start(CERTWRITE_PROGRAM, certfile_finished_callback,
-                     "selfsign=1", NULL, "issuer_key", tls_key_filename, "issuer_name=CN", my_name,
-                     "not_before=20210825000000", NULL, "not_after=20230824235959", NULL, "is_ca=1", NULL,
-                     "max_pathlen=0", NULL, "output_file", tls_cert_filename, NULL);
-    }
-
-}
-#endif // #if (SRP_FEATURE_CAN_GENERATE_TLS_CERT)
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static served_domain_t *NONNULL
-add_new_served_domain_with_interface(const char *const NONNULL name,
-                                     const addr_t *const NULLABLE address, const addr_t *const NULLABLE mask)
-{
-    dp_interface_t *new_interface = NULL;
-    served_domain_t *served_domain = NULL;
-    bool local_only_interface = !strcmp(LOCAL_ONLY_PSEUDO_INTERFACE, name);
-    bool locally_served_interface = !strcmp(ALL_LOCALS_PSEUDO_INTERFACE, name);
-    bool succeeded;
-
-    new_interface = calloc(1, sizeof(*new_interface));
-    require_action_quiet(new_interface != NULL, exit, succeeded = false;
-        ERROR("calloc failed - name: " PRI_S_SRP ", allocate size: %lu", name, sizeof(*new_interface)));
-
-    new_interface->name = strdup(name);
-    require_action_quiet(new_interface->name != NULL, exit, succeeded = false;
-        ERROR("strdup failed to copy interface name - interface name: " PRI_S_SRP, name));
-
-    if (local_only_interface) {
-        new_interface->ifindex = kDNSServiceInterfaceIndexLocalOnly;
-    } else if (locally_served_interface) {
-        new_interface->ifindex = kDNSServiceInterfaceIndexAny;
-    } else {
-        new_interface->ifindex = if_nametoindex(name);
-    }
-
-    // Enable DNS push by default.
-    new_interface->no_push = false;
-
-    if (address != NULL) {
-        require_action_quiet(mask != NULL, exit, succeeded = false);
-
-        new_interface->addresses = calloc(1, sizeof(*new_interface->addresses));
-        require_action_quiet(new_interface->addresses != NULL, exit, succeeded = false;
-            ERROR("calloc failed - allocated size: %lu", sizeof(*new_interface->addresses)));
-        new_interface->addresses->addr = *address;
-        new_interface->addresses->mask = *mask;
-    }
-
-    char *per_interface_served_domain;
-    char served_domain_buffer[DNS_MAX_NAME_SIZE];
-    if (local_only_interface) {
-        // All queries sent to <Thread ID>.thread.home.arpa. will only be proxied to local only interface.
-        per_interface_served_domain = THREAD_DOMAIN_WITH_ID;
-    } else if (locally_served_interface) {
-        per_interface_served_domain = DEFAULT_SERVICE_ARPA_DOMAIN;
-    } else {
-        int bytes_written = snprintf(served_domain_buffer, sizeof(served_domain_buffer),
-            "%s-%s." HOME_NET_DOMAIN, local_host_name, name);
-        require_action_quiet(bytes_written > 0 && (size_t)bytes_written < sizeof(served_domain_buffer), exit,
-            succeeded = false;
-            ERROR("snprintf failed - local host name: " PRI_S_SRP ", interface name: " PUB_S_SRP
-                ", name buffer size: %lu", my_name, name, sizeof(served_domain_buffer))
-        );
-        per_interface_served_domain = served_domain_buffer;
-    }
-
-    served_domain = new_served_domain(new_interface, per_interface_served_domain);
-    require_action_quiet(served_domain != NULL, exit, succeeded = false;
-        ERROR("new_served_domain failed - interface name: " PUB_S_SRP ", served domain: " PRI_S_SRP,
-            name, per_interface_served_domain)
-    );
-
-    succeeded = true;
-    INFO("new served domain added with interface - served domain: " PUB_S_SRP ", interface name: " PUB_S_SRP,
-        per_interface_served_domain, name);
-exit:
-    if (!succeeded) {
-        if (new_interface != NULL) {
-            if (new_interface->addresses != NULL) {
-                verify_action(new_interface->addresses->next == NULL,
-                    ERROR("multiple addresses added for this new interface"));
-                free(new_interface->addresses);
-            }
-            if (new_interface->name != NULL) {
-                free(new_interface->name);
-            }
-        }
-        if (new_interface != NULL) {
-            free(new_interface);
-        }
-    }
-
-    return served_domain;
-}
-#endif // !SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-static bool
-interface_addr_t_equal(const interface_addr_t *const NONNULL a, const interface_addr_t *const NONNULL b)
-{
-    bool equal;
-    const addr_t *const a_addr = &a->addr;
-    const addr_t *const a_mask = &a->mask;
-    const addr_t *const b_addr = &b->addr;
-    const addr_t *const b_mask = &b->mask;
-
-    if (a_addr->sa.sa_family != b_addr->sa.sa_family) {
-        equal = false;
-        goto exit;
-    }
-
-    require_action_quiet(a_addr->sa.sa_family == a_mask->sa.sa_family, exit, equal = false;
-        ERROR("A address and mask are not in the same sa_family - address family: %d, mask family: %d",
-            a_addr->sa.sa_family, a_mask->sa.sa_family)
-    );
-
-    require_action_quiet(b_addr->sa.sa_family == b_mask->sa.sa_family, exit, equal = false;
-        ERROR("B address and mask are no in the same sa_family - address family: %d, mask family: %d",
-            b_addr->sa.sa_family, b_mask->sa.sa_family)
-    );
-
-    if (a_addr->sa.sa_family == AF_INET) {
-        if (a_addr->sin.sin_addr.s_addr != b_addr->sin.sin_addr.s_addr) {
-            equal = false;
-            goto exit;
-        }
-
-        if (a_mask->sin.sin_addr.s_addr != b_mask->sin.sin_addr.s_addr) {
-            equal = false;
-            goto exit;
-        }
-    } else { // a_addr->sa.sa_family == AF_INET6
-        if (memcmp(&a_addr->sin6.sin6_addr, &b_addr->sin6.sin6_addr, sizeof(a_addr->sin6.sin6_addr)) != 0) {
-            equal = false;
-            goto exit;
-        }
-
-        if (memcmp(&a_mask->sin6.sin6_addr, &b_mask->sin6.sin6_addr, sizeof(a_mask->sin6.sin6_addr)) != 0) {
-            equal = false;
-            goto exit;
-        }
-    }
-
-    equal = true;
-exit:
-    return equal;
-}
-
-static bool
-interface_add_new_address(dp_interface_t *const NONNULL interface, const addr_t *const NONNULL address,
-                          const addr_t *const NONNULL mask)
-{
-    bool succeeded;
-
-    interface_addr_t *new_if_addr = calloc(1, sizeof(*new_if_addr));
-    require_action_quiet(new_if_addr != NULL, exit, succeeded = false;
-        ERROR("calloc failed - allocated size: %zu", sizeof(*new_if_addr)));
-    new_if_addr->addr = *address;
-    new_if_addr->mask = *mask;
-    new_if_addr->next = NULL;
-
-    interface_addr_t *prev;
-    interface_addr_t *current;
-
-    for (prev = NULL, current = interface->addresses; current != NULL; prev = current, current = current->next)
-        ;
-
-    if (prev != NULL) {
-        prev->next = new_if_addr;
-    } else {
-        interface->addresses = new_if_addr;
-    }
-
-    succeeded = true;;
-exit:
-    return succeeded;
-}
-
-static bool
-interface_remove_old_address(dp_interface_t *const NONNULL interface, const addr_t *const NONNULL address,
-                             const addr_t *const NONNULL mask)
-{
-    bool succeeded;
-    interface_addr_t addr_to_remove = {NULL, *address, *mask};
-    interface_addr_t *prev;
-    interface_addr_t *current;
-
-    for (prev = NULL, current = interface->addresses; current != NULL; prev = current, current = current->next) {
-        if (interface_addr_t_equal(current, &addr_to_remove)) {
-            break;
-        }
-    }
-    if (current == NULL) {
-        INFO("address not found in the interface address list - interface name: " PUB_S_SRP, interface->name);
-        succeeded = false;
-        goto exit;
-    }
-
-    if (prev != NULL) {
-        prev->next = current->next;
-    } else {
-        interface->addresses = NULL;
-    }
-    free(current);
-
-    succeeded = true;
-exit:
-    return succeeded;
-}
-
-static bool
-interface_process_addr_change(dp_interface_t *const NONNULL interface, const addr_t *const NONNULL address,
-                              const addr_t *const NONNULL mask, const enum interface_address_change event_type)
-{
-    bool succeeded;
-
-    require_action_quiet(event_type != interface_address_unchanged, exit, succeeded = false;
-        INFO("no address change event happens"));
-
-    if (event_type == interface_address_added) {
-        succeeded = interface_add_new_address(interface, address, mask);
-    } else { // event_type == interface_address_removed
-        succeeded = interface_remove_old_address(interface, address, mask);
-    }
-
-    INFO("address added/removed successfully - event: " PUB_S_SRP,
-        event_type == interface_address_added ? "added" : "removed");
-
-exit:
-    return succeeded;
-}
-
-static void
-towire_init(dns_wire_t * const NONNULL wire_ptr, dns_towire_state_t * const NONNULL towire_ptr)
-{
-    memset(wire_ptr, 0, sizeof(*wire_ptr));
-    memset(towire_ptr, 0, sizeof(*towire_ptr));
-    towire_ptr->message = wire_ptr;
-    towire_ptr->lim = &wire_ptr->data[DNS_DATA_SIZE];
-    towire_ptr->p = wire_ptr->data;
-}
-
-static bool
-string_ends_with(const char *const NONNULL str, const char *const NONNULL suffix)
-{
-    size_t str_len = strlen(str);
-    size_t suffix_len = strlen(suffix);
-    bool ret;
-
-    if (str_len < suffix_len) {
-        ret = false;
-        goto exit;
-    }
-
-    if (strcmp(str + (str_len-suffix_len), suffix) != 0) {
-        ret = false;
-        goto exit;
-    }
-
-    ret = true;
-exit:
-    return ret;
-}
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static bool
-served_domain_change_domain_name(void)
-{
-    bool succeeded = true;
-
-    served_domain_t *next;
-    for (served_domain_t *current = served_domains; current != NULL; current = next) {
-        next = current->next;
-        if (!string_ends_with(current->domain, HOME_NET_DOMAIN)) {
-            continue;
-        }
-        // Skip local only interface because only served domain <Thread ID>.thread.home.arpa. does not contain domain
-        // string.
-        if (current->interface != NULL && strcmp(LOCAL_ONLY_PSEUDO_INTERFACE, current->interface->name) == 0) {
-            continue;
-        }
-
-        // Constructs new served domain name.
-        char *new_served_domain_name;
-        char new_served_domain_buff[DNS_MAX_NAME_SIZE];
-
-        if (current->interface != NULL) { // <local host name>-<interface name>.home.arpa.
-            const dp_interface_t *const interface = current->interface;
-            int bytes_written = snprintf(new_served_domain_buff, sizeof(new_served_domain_buff),
-                "%s-%s." HOME_NET_DOMAIN, local_host_name, interface->name);
-            require_action_quiet(bytes_written > 0 && (size_t)bytes_written < sizeof(new_served_domain_buff), exit,
-                succeeded = false; ERROR("snprintf failed"));
-            new_served_domain_name = new_served_domain_buff;
-
-        } else { // <local host name>.home.arpa.
-            int bytes_written = snprintf(new_served_domain_buff, sizeof(new_served_domain_buff),
-                "%s." HOME_NET_DOMAIN, local_host_name);
-            require_action_quiet(bytes_written > 0 && (size_t)bytes_written < sizeof(new_served_domain_buff), exit,
-                succeeded = false; ERROR("snprintf failed"));
-            new_served_domain_name = new_served_domain_buff;
-        }
-
-        INFO("Updating served domain from " PRI_S_SRP " to " PRI_S_SRP, current->domain, new_served_domain_name);
-
-        // Free the old served domain name.
-        free(current->domain_ld);
-        dns_name_free(current->domain_name);
-
-        // Set the new served domain name.
-        size_t domain_len = strlen(new_served_domain_name);
-        current->domain_ld = malloc(domain_len + 2);
-        require_action_quiet(current->domain_ld != NULL, for_loop_exit, succeeded = false;
-            ERROR("malloc failed - allocated length: %zu", domain_len + 2));
-        current->domain_ld[0] = '.';
-        current->domain = current->domain_ld + 1;
-        memcpy(current->domain, new_served_domain_name, domain_len);
-        current->domain[domain_len] = '\0';
-
-        current->domain_name = dns_pres_name_parse(current->domain);
-        require_action_quiet(current->domain_name != NULL, for_loop_exit, succeeded = false;
-            ERROR("failed to create parsed DNS name - domain name to be parsed: " PRI_S_SRP, current->domain)
-        );
-
-    for_loop_exit:
-        if (!succeeded) {
-            delete_served_domain(current);
-        }
-    }
-
-exit:
-    return succeeded;
-}
-
-static bool
-served_domain_process_name_change(void)
-{
-    bool succeeded;
-
-    // Deletes all hardwired response set in the served domain.
-    dnssd_hardwired_clear();
-
-    // Since local host name changes, we need to reflect the change in the served domain name.
-    succeeded = served_domain_change_domain_name();
-    require_action_quiet(succeeded, exit, ERROR("served_domain_change_domain_name failed"));
-
-    // Re-set the hardwired response
-    dnssd_hardwired_setup();
-
-    // Re-set the DNS push hardwired response
-    dnssd_hardwired_push_setup();
-
-    succeeded = true;
-exit:
-    return succeeded;
-}
-
-static bool
-update_my_name(CFStringRef local_host_name_cfstr)
-{
-    bool succeeded;
-    size_t name_length;
-
-    // local host name to c string.
-    succeeded = CFStringGetCString(local_host_name_cfstr, local_host_name, sizeof(local_host_name),
-        kCFStringEncodingUTF8);
-    require_action_quiet(succeeded, exit, succeeded = false;
-        ERROR("CFStringGetCString failed - local host name: " PRI_S_SRP,
-            CFStringGetCStringPtr(local_host_name_cfstr, kCFStringEncodingUTF8))
-    );
-    name_length = strlen(local_host_name);
-
-    // Validate the local host name.
-    for (size_t i = 0; i < name_length; i++) {
-        char ch = local_host_name[i];
-        bool is_valid_char = isalnum(ch) || (ch == '-');
-        require_action_quiet(is_valid_char, exit, succeeded = false;
-            ERROR("invalid DNS name - name: " PUB_S_SRP, local_host_name));
-    }
-
-    require_action_quiet(name_length + sizeof(DOT_HOME_NET_DOMAIN) <= sizeof(my_name_buf),
-                         exit,
-                         succeeded = false;
-                         ERROR("generated name too long: " PUB_S_SRP DOT_HOME_NET_DOMAIN, local_host_name));
-
-    // Update existing local host name in my_name.
-    memcpy(my_name_buf, local_host_name, name_length);
-    memcpy(my_name_buf + name_length, DOT_HOME_NET_DOMAIN, sizeof(DOT_HOME_NET_DOMAIN));
-
-    // Update existing local host name with .local suffix.
-    int bytes_written = snprintf(local_host_name_dot_local, sizeof(local_host_name_dot_local), "%s" DOT_LOCAL, local_host_name);
-    if (bytes_written < 0 || (size_t) bytes_written > sizeof(local_host_name_dot_local)) {
-        ERROR("snprintf failed - name length: %lu, max: %lu", strlen(local_host_name) + sizeof(DOT_LOCAL),
-            sizeof(local_host_name_dot_local));
-        succeeded = false;
-        goto exit;
-    }
-
-    my_name = my_name_buf;
-
-    succeeded = true;
-    INFO(PUB_S_SRP " my_name: " PRI_S_SRP ", local host name: " PRI_S_SRP, my_name == NULL ? "initialized" : "updated",
-         my_name, local_host_name_dot_local);
-
-exit:
-    return succeeded;
-}
-
-// Gets called when name change event happens
-static void
-monitor_name_changes_callback(SCDynamicStoreRef store, CFArrayRef changed_keys, void UNUSED *context)
-{
-    bool succeeded;
-    CFStringRef local_host_name_cfstring = NULL;
-
-    // Check if name changes.
-    CFRange range = {0, CFArrayGetCount(changed_keys)};
-    const bool host_name_changed = CFArrayContainsValue(changed_keys, range, sc_dynamic_store_key_host_name);
-    if (!host_name_changed) {
-        goto exit;
-    }
-
-    // Get the new local host name.
-    local_host_name_cfstring = SCDynamicStoreCopyLocalHostName(store);
-    require_action_quiet(local_host_name_cfstring != NULL, exit, ERROR("failed to get updated local host name"));
-
-    // Update the old my_name
-    succeeded = update_my_name(local_host_name_cfstring);
-    require_action_quiet(succeeded, exit, ERROR("failed to update my name"));
-
-    // With the new local host name, update the served domains and hardwired response.
-    succeeded = served_domain_process_name_change();
-    require_action_quiet(succeeded, exit, ERROR("failed to process name change for served domains"));
-
-    if (advertisements.txn != NULL) {
-        dns_wire_t wire;
-        dns_towire_state_t towire;
-        towire_init(&wire, &towire);
-        dns_full_name_to_wire(NULL, &towire, local_host_name_dot_local);
-
-        DNSServiceErrorType err = DNSServiceUpdateRecord(advertisements.service_ref, advertisements.ns_record_ref, 0,
-            towire.p - wire.data, wire.data, 0);
-        if (err != kDNSServiceErr_NoError) {
-            ERROR("DNSServiceUpdateRecord failed to update NS record to new name - name: " PRI_S_SRP,
-                local_host_name_dot_local);
-        }
-
-        INFO("Updating record - new NS record rdata: " PRI_S_SRP, local_host_name_dot_local);
-    }
-
-exit:
-    if (local_host_name_cfstring != NULL) {
-        CFRelease(local_host_name_cfstring);
-    }
-    return;
-}
-
-static bool
-monitor_name_changes(void)
-{
-    bool succeeded;
-    SCDynamicStoreRef store = NULL;
-    const void *monitored_keys[1];
-    CFArrayRef monitored_keys_array = NULL;
-
-    // Set the callback function for name change event.
-    store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("dnssd-proxy:watch for name change events"),
-        monitor_name_changes_callback, NULL);
-    require_action_quiet(store != NULL, exit, succeeded = false; ERROR("failed to create SCDynamicStoreRef"));
-
-    // Set the key to be monitored, which is host name
-    sc_dynamic_store_key_host_name = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault);
-    require_action_quiet(sc_dynamic_store_key_host_name != NULL, exit, succeeded = false;
-        ERROR("failed to create SCDynamicStoreKey for host name"));
-
-    monitored_keys[0] = sc_dynamic_store_key_host_name;
-    monitored_keys_array = CFArrayCreate(kCFAllocatorDefault, monitored_keys, countof(monitored_keys),
-        &kCFTypeArrayCallBacks);
-    require_action_quiet(monitored_keys_array != NULL, exit, succeeded = false;
-        ERROR("failed to create CFArrayRef for monitored keys"));
-
-    succeeded = SCDynamicStoreSetNotificationKeys(store, monitored_keys_array, NULL);
-    require_action_quiet(succeeded, exit, ERROR("SCDynamicStoreSetNotificationKeys failed"));
-
-    succeeded = SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue());
-    require_action_quiet(succeeded, exit, ERROR("SCDynamicStoreSetDispatchQueue failed"));
-
-    succeeded = true;
-    INFO("Start to monitor local host name changes");
-exit:
-    if (!succeeded) {
-        if (store != NULL) {
-            CFRelease(store);
-        }
-    }
-    if (monitored_keys_array != NULL) {
-        CFRelease(monitored_keys_array);
-    }
-    return succeeded;
-}
-
-static bool
-initialize_my_name_and_monitoring(void)
-{
-    bool succeeded;
-    CFStringRef local_host_name_cfstring = NULL;
-
-    // Set notification from configd
-    succeeded = monitor_name_changes();
-    require_action_quiet(succeeded, exit, ERROR("failed to monitor name changes"));
-
-    // Get the initial local host name
-    local_host_name_cfstring = SCDynamicStoreCopyLocalHostName(NULL);
-    require_action_quiet(local_host_name != NULL, exit, succeeded = false; ERROR("failed to get local host name"));
-
-    succeeded = update_my_name(local_host_name_cfstring);
-    require_action_quiet(succeeded, exit, ERROR("failed to update myname"));
-
-exit:
-    if (local_host_name_cfstring != NULL) {
-        CFRelease(local_host_name_cfstring);
-    }
-    return succeeded;
-}
-
-static bool
-configure_dnssd_proxy(void)
-{
-    bool succeeded;
-
-    udp_port= 53;
-    tcp_port = 53;
-    tls_port = 853;
-
-    succeeded = true;
-    return succeeded;
-}
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-static bool
-start_dnssd_proxy_listener(void)
-{
-    bool succeeded;
-    addr_t addr;
-
-#ifndef NOT_HAVE_SA_LEN
-#  define SA_LEN_INIT addr.sa.sa_len = sizeof(addr.sin6)
-#else
-#  define SA_LEN_INIT
-#endif // NOT_HAVE_SA_LEN
-#define INIT_ADDR_T(PORT)                       \
-        do {                                    \
-            memset(&addr, 0, sizeof(addr));     \
-            addr.sa.sa_family = AF_UNSPEC;      \
-            addr.sin6.sin6_port = htons(PORT);  \
-            SA_LEN_INIT;                        \
-        } while (false)
-
-    INIT_ADDR_T(udp_port);
-    listener[num_listeners] = ioloop_listener_create(false, false, NULL, 0, &addr, NULL, "DNS UDP Listener",
-                                                     dns_proxy_input, NULL, NULL, NULL, NULL, NULL, NULL);
-    require_action_quiet(listener[num_listeners] != NULL, exit, succeeded = false;
-        ERROR("start_dnssd_proxy_listener: failed to start UDP listener - listerner index: %d", num_listeners));
-    num_listeners++;
-
-    INIT_ADDR_T(tcp_port);
-    listener[num_listeners] = ioloop_listener_create(true, false, NULL, 0, &addr, NULL, "TCP DNS Listener",
-                                                     dns_proxy_input, NULL, NULL, NULL, NULL, NULL, NULL);
-    require_action_quiet(listener[num_listeners] != NULL, exit, succeeded = false;
-        ERROR("start_dnssd_proxy_listener: failed to start TCP listener - listerner index: %d", num_listeners));
-    num_listeners++;
-
-    for (int i = 0; i < num_listeners; i++) {
-        INFO("listener started - name: " PUB_S_SRP, listener[i]->name);
-    }
-
-    dnssd_push_setup();
-
-    succeeded = true;
-exit:
-    return succeeded;
-}
-
-#define ADVERTISEMENT_RETRY_TIMER 10 * MSEC_PER_SEC
-
-static void
-advertisements_finalize(void *context)
-{
-    dnssd_proxy_advertisements_t * const advertisements_context = context;
-    advertisements_context->txn = NULL;
-}
-
-static void
-advertisements_failed(void *UNUSED context, int status)
-{
-    ERROR("%d", status);
-}
-
-static void
-advertisements_callback(DNSServiceRef sd_ref, DNSRecordRef record_ref, DNSServiceFlags UNUSED flags,
-                     DNSServiceErrorType error, void *context)
-{
-    dnssd_proxy_advertisements_t * const advertisements_context = context;
-
-    if (error == kDNSServiceErr_NoError) {
-        const char * const description = record_ref == advertisements_context->ns_record_ref ? "NS" : "PTR";
-        INFO("record registered successfully - registered: " PUB_S_SRP, description);
-    } else if (error == kDNSServiceErr_ServiceNotRunning) {
-        // The record is not being advertised because mDNSResponder stopped running for some reason (like crashes),
-        // in which case, we will stop the previous DNSService operation and start a new one 10s later.
-
-        // Release the previous DNSServiceRef.
-        if (advertisements_context->service_ref != sd_ref) {
-            ERROR("Invalid DNSServiceRef - context->service_ref: %p, sd_ref: %p", advertisements_context->service_ref,
-                sd_ref);
-        }
-        DNSServiceRefDeallocate(advertisements_context->service_ref);
-        advertisements_context->service_ref = NULL;
-
-        // Restart the advertisement.
-        bool succeeded = start_timer_to_advertise(advertisements_context, NULL, ADVERTISEMENT_RETRY_TIMER);
-        if (!succeeded) {
-            ERROR("start_timer_to_advertise failed");
-        } else {
-            INFO("mDNSResponder stopped running, preparing to re-advertise the PTR and NS records");
-        }
-    } else {
-        ERROR("record not registered - error: %d", error);
-    }
-}
-
-static void
-advertise_dnssd_proxy_callback(void *NONNULL context)
-{
-    DNSServiceErrorType err;
-    bool succeeded;
-    bool dns_service_initialized = false;
-    dns_wire_t wire;
-    dns_towire_state_t towire;
-    dnssd_proxy_advertisements_t *advertisement_context = context;
-    const char *const domain_to_advertise = advertisement_context->domain_to_advertise;
-
-    INFO("Start advertising lb._dns-sd._udp.local. PTR and openthread.thread.home.arpa.local NS records");
-
-    // Create DNSServiceRef
-    err = DNSServiceCreateConnection(&advertisement_context->service_ref);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("DNSServiceCreateConnection failed");
-        succeeded = false;
-        goto exit;
-    }
-    dns_service_initialized = true;
-
-    // Setup lb._dns-sd._udp.local. PTR openthread.thread.home.arpa.
-    towire_init(&wire, &towire);
-    dns_full_name_to_wire(NULL, &towire, domain_to_advertise);
-
-    err = DNSServiceRegisterRecord(advertisement_context->service_ref, &advertisement_context->ptr_record_ref,
-        kDNSServiceFlagsShared, 0, AUTOMATIC_BROWSING_DOMAIN, kDNSServiceType_PTR, kDNSServiceClass_IN,
-        towire.p - wire.data, wire.data, 0, advertisements_callback, &advertisements);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("DNSServiceRegisterRecord failed - record: " PUB_S_SRP " PTR " PRI_S_SRP, AUTOMATIC_BROWSING_DOMAIN,
-              domain_to_advertise);
-        succeeded = false;
-        goto exit;
-    }
-
-    // Setup openthread.thread.home.arpa. NS <local host name>.local.
-    towire_init(&wire, &towire);
-    dns_full_name_to_wire(NULL, &towire, local_host_name_dot_local);
-
-    err = DNSServiceRegisterRecord(advertisement_context->service_ref, &advertisement_context->ns_record_ref,
-        kDNSServiceFlagsShared | kDNSServiceFlagsForceMulticast, 0, domain_to_advertise, kDNSServiceType_NS,
-        kDNSServiceClass_IN, towire.p - wire.data, wire.data, 0, advertisements_callback, &advertisements);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("DNSServiceRegisterRecord failed - record: " PUB_S_SRP " NS " PRI_S_SRP, domain_to_advertise,
-            local_host_name_dot_local);
-        succeeded = false;
-        goto exit;
-    }
-
-    // Start the running loop
-    advertisement_context->txn = ioloop_dnssd_txn_add(advertisement_context->service_ref, &advertisements,
-        advertisements_finalize, advertisements_failed);
-    if (advertisement_context->txn == NULL) {
-        ERROR("ioloop_dnssd_txn_add failed");
-        succeeded = false;
-        goto exit;
-    }
-
-    INFO("Advertising records - " PUB_S_SRP " PTR " PRI_S_SRP ", " PRI_S_SRP " NS " PRI_S_SRP,
-         AUTOMATIC_BROWSING_DOMAIN, domain_to_advertise, domain_to_advertise, local_host_name_dot_local);
-    succeeded = true;
-exit:
-    if (!succeeded) {
-        if (dns_service_initialized) {
-            DNSServiceRefDeallocate(advertisement_context->service_ref);
-            advertisement_context->service_ref = NULL;
-        }
-        if (err == kDNSServiceErr_ServiceNotRunning) {
-            ERROR("mDNSResponder is not running yet when trying to advertise PTR and NS records, try again 10s later");
-            // advertise_dnssd_proxy_callback will be called again 10s later, since we did not cancel the timer.
-        } else {
-            // Other kDNSServiceErr, should be impossible. If it happens, give up advertising the records.
-            ioloop_cancel_wake_event(advertisement_context->wakeup_timer);
-        }
-    } else {
-        // Since we registered successfully, there is no need to trigger another timer to set the records.
-        // Stop the timer.
-        ioloop_cancel_wake_event(advertisement_context->wakeup_timer);
-    }
-}
-
-static bool
-start_timer_to_advertise(dnssd_proxy_advertisements_t *const NONNULL context,
-    const char *const NULLABLE domain_to_advertise, const uint32_t interval)
-{
-    bool succeeded;
-
-    // Only create timer once.
-    if (context->wakeup_timer == NULL) {
-        context->wakeup_timer = ioloop_wakeup_create();
-        if (context->wakeup_timer == NULL) {
-            succeeded = false;
-            goto exit;
-        }
-    }
-
-    // Only copy advertised domain once.
-    if (context->domain_to_advertise == NULL) {
-        if (domain_to_advertise == NULL) {
-            succeeded = false;
-            goto exit;
-        }
-
-        context->domain_to_advertise = strdup(domain_to_advertise);
-        if (context->domain_to_advertise == NULL) {
-            succeeded = false;
-            goto exit;
-        }
-    }
-
-    // Start the timer, finalize callback is not necessary here because the context should always be available.
-    succeeded = ioloop_add_wake_event(context->wakeup_timer, context, advertise_dnssd_proxy_callback, NULL, interval);
-    if (!succeeded) {
-        goto exit;
-    }
-
-    succeeded = true;
-exit:
-    if (!succeeded) {
-        if (context->domain_to_advertise != NULL) {
-            free(context->domain_to_advertise);
-            context->domain_to_advertise = NULL;
-        }
-        if (context->wakeup_timer != NULL) {
-            ioloop_wakeup_release(context->wakeup_timer);
-            context->wakeup_timer = NULL;
-        }
-    }
-    return succeeded;
-}
-
-static bool
-advertise_dnssd_proxy(const char *const NONNULL domain_to_advertise)
-{
-    // Start advertisement (wait for ADVERTISEMENT_RETRY_TIMER to allow mDNSResponder to start).
-    return start_timer_to_advertise(&advertisements, domain_to_advertise, ADVERTISEMENT_RETRY_TIMER);
-}
-
-#if SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-#  if SRP_FEATURE_DYNAMIC_CONFIGURATION
-static bool
-served_domain_init(void)
-{
-    bool succeeded;
-    served_domain_t *my_name_served_domain = NULL;
-    served_domain_t *ipv6 = NULL;
-    served_domain_t *ipv4 = NULL;
-    served_domain_t *thread_served_domain = NULL;
-    served_domain_t *default_service_arpa_domain = NULL;
-
-    // <local host name>.home.arpa.
-    my_name_served_domain = new_served_domain(NULL, my_name);
-    require_action_quiet(my_name_served_domain != NULL, exit, succeeded = false;
-        ERROR("failed to create new served domain - domain name: " PUB_S_SRP, my_name));
-
-    // ip6.arpa.
-    // in-addr.arpa.
-    ipv6 = new_served_domain(NULL, IPV6_REVERSE_LOOKUP_DOMAIN);
-    ipv4 = new_served_domain(NULL, IPV4_REVERSE_LOOKUP_DOMAIN);
-    require_action_quiet(ipv6 != NULL && ipv4 != NULL, exit, succeeded = false;
-        ERROR("failed to create new served domain for reverse look up -  domain name: " PUB_S_SRP ", " PUB_S_SRP,
-            IPV6_REVERSE_LOOKUP_DOMAIN, IPV4_REVERSE_LOOKUP_DOMAIN)
-    );
-
-    // THREAD_BROWSING_DOMAIN
-    // It will be served by kDNSServiceInterfaceIndexLocalOnly, which is a pseudo interface.
-    thread_served_domain = add_new_served_domain_with_interface(LOCAL_ONLY_PSEUDO_INTERFACE, NULL, NULL);
-    require_action_quiet(thread_served_domain != NULL, exit, succeeded = false);
-    bool hardwired_set = dnssd_hardwired_setup_for_served_domain(thread_served_domain);
-    require_action_quiet(hardwired_set, exit, succeeded = false);
-
-    // default.service.arpa
-    // For Thread 1.3.0, default.service.arpa has to return all locally-discoverable services
-    default_service_arpa_domain = add_new_served_domain_with_interface(ALL_LOCALS_PSEUDO_INTERFACE, NULL, NULL);
-    require_action_quiet(default_service_arpa_domain != NULL, exit, succeeded = false);
-    hardwired_set = dnssd_hardwired_setup_for_served_domain(default_service_arpa_domain);
-    require_action_quiet(hardwired_set, exit, succeeded = false);
-
-    succeeded = true;
-exit:
-    if (!succeeded) {
-        if (thread_served_domain != NULL) {
-            delete_served_domain(thread_served_domain);
-        }
-        if (default_service_arpa_domain != NULL) {
-            delete_served_domain(default_service_arpa_domain);
-        }
-        if (ipv4 != NULL) {
-            delete_served_domain(ipv4);
-        }
-        if (ipv6 != NULL) {
-            delete_served_domain(ipv6);
-        }
-        if (my_name_served_domain != NULL) {
-            delete_served_domain(my_name_served_domain);
-        }
-    }
-    return succeeded;
-}
-#  endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-#endif // SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-
-bool
-init_dnssd_proxy(void)
-{
-    bool succeeded;
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-    succeeded = configure_dnssd_proxy();
-    require_action_quiet(succeeded, exit, ERROR("configure_dnssd_proxy failed"));
-
-    succeeded = initialize_my_name_and_monitoring();
-    require_action_quiet(succeeded, exit, ERROR("initialize_my_name_and_monitoring failed"));
-#else // SRP_FEATURE_DYNAMIC_CONFIGURATION
-    // Read the config file
-    succeeded = config_parse(NULL, "/etc/dnssd-proxy.cf", dp_verbs, NUMCFVERBS);
-    require_action_quiet(succeeded,
-                         exit,);
-
-    // Insist that we have at least one address we're listening on.
-    succeeded = !(num_listen_addrs == 0 && num_publish_addrs == 0);
-    require_action_quiet(succeeded,
-                         exit,
-                         ERROR("Please configure at least one my-ipv4-addr and/or one my-ipv6-addr."));
-
-    ioloop_map_interface_addresses(NULL, &served_domains, dnssd_proxy_ifaddr_callback);
-
-    // Set up hardwired answers
-    dnssd_hardwired_setup();
-#endif // SRP_FEATURE_DYNAMIC_CONFIGURATION
-
-    succeeded = srp_tls_init();
-    require_action_quiet(succeeded, exit, ERROR("srp_tls_init failed."));
-
-#if !SRP_FEATURE_CAN_GENERATE_TLS_CERT
-    // The tls_fail flag allows us to run the proxy in such a way that TLS connections will fail.
-    // This is never what you want in production, but is useful for testing.
-    if (!tls_fail) {
-        if (access(tls_key_filename, R_OK) < 0) {
-            keyprogram_start(GENKEY_PROGRAM, keyfile_finished_callback,
-                             "type=rsa", NULL, "rsa_keysize=4096", NULL, "filename", tls_key_filename, NULL);
-        } else if (access(tls_cert_filename, R_OK) < 0) {
-            keyfile_finished_callback(NULL, 0, NULL);
-        }
-        require_action_quiet(access(tls_key_filename, R_OK) >= 0, exit, ERROR("failed to create tls listener key."));
-        require_action_quiet(access(tls_cert_filename, R_OK) >= 0, exit, ERROR("failed to create tls listener cert."));
-
-        require_action_quiet(srp_tls_server_init(NULL, tls_cert_filename, tls_key_filename),
-                             exit, ERROR("srp_tls_server_init failed."));
-        require_action_quiet(srp_tls_client_init(), exit, ERROR("srp_tls_client_init failed."));
-    }
-#endif
-
-    succeeded = start_dnssd_proxy_listener();
-    require_action_quiet(succeeded, exit, ERROR("start_dnssd_proxy_listener failed"));
-
-    succeeded = advertise_dnssd_proxy(THREAD_BROWSING_DOMAIN);
-    require_action_quiet(succeeded, exit, ERROR("advertise_dnssd_proxy failed"));
-
-#if SRP_FEATURE_DYNAMIC_CONFIGURATION
-    succeeded = served_domain_init();
-#endif
-
-exit:
-    return succeeded;
-}
-
-#if !SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-int
-main(int argc, char **argv)
-{
-    int i;
-    bool log_stderr = false;
-
-    udp_port = tcp_port = 53;
-    tls_port = 853;
-
-    // Parse command line arguments
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "--tls-fail")) {
-            tls_fail = true;
-        } else if (!strcmp(argv[i], "--log-stderr")) {
-            log_stderr = true;
-        } else {
-            return usage(argv[0]);
-        }
-    }
-
-    OPENLOG("dnssd-proxy", log_stderr);
-
-    if (!ioloop_init()) {
-        return 1;
-    }
-
-    init_dnssd_proxy();
-
-    ioloop();
-}
-#endif // #if !SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-
-#endif // (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY) || (!defined(BUILD_SRP_MDNS_PROXY) || (BUILD_SRP_MDNS_PROXY == 0))
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/dnssd-proxy.h b/ServiceRegistration/dnssd-proxy.h
deleted file mode 100644
index 1addc7a..0000000
--- a/ServiceRegistration/dnssd-proxy.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* dnssd-proxy.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * Discovery Proxy globals.
- */
-
-#ifndef __DNSSD_PROXY_H__
-#define __DNSSD_PROXY_H__
-
-#include "srp-features.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-
-//======================================================================================================================
-// MARK: - Macros
-
-#define MAX_ADDRS 10
-
-#if (!SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-    // FIXME: set CERTWRITE_PROGRAM and GENKEY_PROGRAM to correct one.
-    #ifndef CERTWRITE_PROGRAM
-        #define CERTWRITE_PROGRAM "/bin/echo"
-    #endif
-    #ifndef GENKEY_PROGRAM
-        #define GENKEY_PROGRAM "/bin/echo"
-    #endif
-#endif // #if (!SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-
-#define AUTOMATIC_BROWSING_DOMAIN "lb._dns-sd._udp.local."
-#define THREAD_NETWORK_NAME "openthread"
-#define THREAD_BROWSING_DOMAIN THREAD_NETWORK_NAME ".thread.home.arpa."
-
-//======================================================================================================================
-// MARK: - Functions
-
-// We can only initialize dnssd-proxy in srp-mdns-proxy if we combined it with srp-mdns-proxy.
-#if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-bool init_dnssd_proxy(void);
-bool delete_served_domain_by_interface_name(const char *const NONNULL interface_name);
-#endif // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-
-void dnssd_proxy_ifaddr_callback(void *NULLABLE context, const char *NONNULL name, const addr_t *NONNULL address,
-								 const addr_t *NONNULL mask, uint32_t UNUSED flags, enum interface_address_change event_type);
-void dp_start_dropping(void);
-#endif // #ifndef __DNSSD_PROXY_H__
diff --git a/ServiceRegistration/dnssd-relay.c b/ServiceRegistration/dnssd-relay.c
deleted file mode 100644
index 7048d1f..0000000
--- a/ServiceRegistration/dnssd-relay.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/* dnssd-relay.c
- *
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- *
- * This is a Discovery Proxy module for the SRP gateway.
- *
- * The motivation here is that it makes sense to co-locate the SRP relay and the Discovery Proxy because
- * these functions are likely to co-exist on the same node, listening on the same port.  For homenet-style
- * name resolution, we need a DNS proxy that implements DNSSD Discovery Proxy for local queries, but
- * forwards other queries to an ISP resolver.  The SRP gateway is already expecting to do this.
- * This module implements the functions required to allow the SRP gateway to also do Discovery Relay.
- *
- * The Discovery Proxy relies on Apple's DNS-SD library and the mDNSResponder DNSSD server, which is included
- * in Apple's open source mDNSResponder package, available here:
- *
- *            https://opensource.apple.com/tarballs/mDNSResponder/
- */
-
-#define __APPLE_USE_RFC_3542
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-
-#include "dns_sd.h"
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#define DNSMessageHeader dns_wire_t
-#include "dso.h"
-#include "ioloop.h"
-#include "srp-tls.h"
-#include "config-parse.h"
-
-// Enumerate the list of interfaces, map them to interface indexes, give each one a name
-// Have a tree of subdomains for matching
-
-// Configuration file settings
-uint16_t udp_port;
-uint16_t tcp_port;
-uint16_t tls_port;
-#define MAX_ADDRS 10
-char *listen_addrs[MAX_ADDRS];
-int num_listen_addrs = 0;
-char *publish_addrs[MAX_ADDRS];
-int num_publish_addrs = 0;
-char *tls_cacert_filename = NULL;
-char *tls_cert_filename = "/etc/dnssd-relay/server.crt";
-char *tls_key_filename = "/etc/dnssd-relay/server.key";
-
-// Code
-
-int64_t dso_transport_idle(void *context, int64_t now, int64_t next_event)
-{
-    return next_event;
-}
-
-void
-dp_simple_response(comm_t *comm, int rcode)
-{
-    if (comm->send_response) {
-        struct iovec iov;
-        dns_wire_t response;
-        memset(&response, 0, DNS_HEADER_SIZE);
-
-        // We take the ID and the opcode from the incoming message, because if the
-        // header has been mangled, we (a) wouldn't have gotten here and (b) don't
-        // have any better choice anyway.
-        response.id = comm->message->wire.id;
-        dns_qr_set(&response, dns_qr_response);
-        dns_opcode_set(&response, dns_opcode_get(&comm->message->wire));
-        dns_rcode_set(&response, rcode);
-        iov.iov_base = &response;
-        iov.iov_len = DNS_HEADER_SIZE; // No RRs
-        comm->send_response(comm, comm->message, &iov, 1);
-    }
-}
-
-bool
-dso_send_formerr(dso_state_t *dso, const dns_wire_t *header)
-{
-    comm_t *transport = dso->transport;
-    (void)header;
-    dp_simple_response(transport, dns_rcode_formerr);
-    return true;
-}
-
-static void dso_message(comm_t *comm, const dns_wire_t *header, dso_state_t *dso)
-{
-    switch(dso->primary.opcode) {
-    case kDSOType_DNSPushSubscribe:
-        dns_push_subscription_change("DNS Push Subscribe", comm, header, dso);
-        break;
-    case kDSOType_DNSPushUnsubscribe:
-        dns_push_subscription_change("DNS Push Unsubscribe", comm, header, dso);
-        break;
-
-    case kDSOType_DNSPushReconfirm:
-        dns_push_reconfirm(comm, header, dso);
-        break;
-
-    case kDSOType_DNSPushUpdate:
-        INFO("bogus push update message %d", dso->primary.opcode);
-        dso_drop(dso);
-        break;
-
-    default:
-        INFO("unexpected primary TLV %d", dso->primary.opcode);
-        dp_simple_response(comm, dns_rcode_dsotypeni);
-        break;
-    }
-    // XXX free the message if we didn't consume it.
-}
-
-static void dns_push_callback(void *context, const void *event_context,
-                              dso_state_t *dso, dso_event_type_t eventType)
-{
-    const dns_wire_t *message;
-    switch(eventType)
-    {
-    case kDSOEventType_DNSMessage:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Message (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(message),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DNSResponse:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Response (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(message),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DSOMessage:
-        INFO("DSO Message (Primary TLV=%d) received from " PRI_S_SRP,
-             dso->primary.opcode, dso->remote_name);
-        message = event_context;
-        dso_message((comm_t *)context, message, dso);
-        break;
-    case kDSOEventType_DSOResponse:
-        INFO("DSO Response (Primary TLV=%d) received from " PRI_S_SRP,
-             dso->primary.opcode, dso->remote_name);
-        break;
-
-    case kDSOEventType_Finalize:
-        INFO("Finalize");
-        break;
-
-    case kDSOEventType_Connected:
-        INFO("Connected to " PRI_S_SRP, dso->remote_name);
-        break;
-
-    case kDSOEventType_ConnectFailed:
-        INFO("Connection to " PRI_S_SRP " failed", dso->remote_name);
-        break;
-
-    case kDSOEventType_Disconnected:
-        INFO("Connection to " PRI_S_SRP " disconnected", dso->remote_name);
-        break;
-    case kDSOEventType_ShouldReconnect:
-        INFO("Connection to " PRI_S_SRP " should reconnect (not for a server)", dso->remote_name);
-        break;
-    case kDSOEventType_Inactive:
-        INFO("Inactivity timer went off, closing connection.");
-        // XXX
-        break;
-    case kDSOEventType_Keepalive:
-        INFO("should send a keepalive now.");
-        break;
-    case kDSOEventType_KeepaliveRcvd:
-        INFO("keepalive received.");
-        break;
-    case kDSOEventType_RetryDelay:
-        INFO("keepalive received.");
-        break;
-    }
-}
-
-void
-dp_dns_query(comm_t *comm, dns_rr_t *question)
-{
-    int rcode;
-    dnssd_query_t *query = dp_query_generate(comm, question, false, &rcode);
-    const char *failnote = NULL;
-    if (!query) {
-        dp_simple_response(comm, rcode);
-        return;
-    }
-
-    // For regular DNS queries, copy the ID, etc.
-    query->response->id = comm->message->wire.id;
-    query->response->bitfield = comm->message->wire.bitfield;
-    dns_rcode_set(query->response, dns_rcode_noerror);
-
-    // For DNS queries, we need to return the question.
-    query->response->qdcount = htons(1);
-    if (query->iface != NULL) {
-        TOWIRE_CHECK("name", &query->towire, dns_name_to_wire(NULL, &query->towire, query->name));
-        TOWIRE_CHECK("enclosing_domain", &query->towire,
-                     dns_full_name_to_wire(&query->enclosing_domain_pointer,
-                                           &query->towire, query->iface->domain));
-    } else {
-        TOWIRE_CHECK("full name", &query->towire, dns_full_name_to_wire(NULL, &query->towire, query->name));
-    }
-    TOWIRE_CHECK("TYPE", &query->towire, dns_u16_to_wire(&query->towire, question->type));    // TYPE
-    TOWIRE_CHECK("CLASS", &query->towire, dns_u16_to_wire(&query->towire, question->qclass));  // CLASS
-    if (failnote != NULL) {
-        ERROR("dp_dns_query: failure encoding question: " PUB_S_SRP, failnote);
-        goto fail;
-    }
-
-    // We should check for OPT RR, but for now assume it's there.
-    query->is_edns0 = true;
-
-    if (!dp_query_start(comm, query, &rcode, dns_query_callback)) {
-    fail:
-        dp_simple_response(comm, rcode);
-        free(query->name);
-        free(query);
-        return;
-    }
-
-    // XXX make sure that finalize frees this.
-    if (comm->message) {
-        query->question = comm->message;
-        comm->message = NULL;
-    }
-}
-
-void dso_transport_finalize(comm_t *comm)
-{
-    dso_state_t *dso = comm->dso;
-    INFO(PRI_S_SRP, dso->remote_name);
-    if (comm) {
-        ioloop_close(&comm->io);
-    }
-    free(dso);
-    comm->dso = NULL;
-}
-
-void dns_evaluate(comm_t *comm)
-{
-    dns_rr_t question;
-    unsigned offset = 0;
-
-    // Drop incoming responses--we're a server, so we only accept queries.
-    if (dns_qr_get(&comm->message->wire) == dns_qr_response) {
-        return;
-    }
-
-    // If this is a DSO message, see if we have a session yet.
-    switch(dns_opcode_get(&comm->message->wire)) {
-    case dns_opcode_dso:
-        if (!comm->tcp_stream) {
-            ERROR("DSO message received on non-tcp socket " PRI_S_SRP, comm->name);
-            dp_simple_response(comm, dns_rcode_notimp);
-            return;
-        }
-
-        if (!comm->dso) {
-            comm->dso = dso_create(true, 0, comm->name, dns_push_callback, comm, comm);
-            if (!comm->dso) {
-                ERROR("Unable to create a dso context for " PRI_S_SRP, comm->name);
-                dp_simple_response(comm, dns_rcode_servfail);
-                ioloop_close(&comm->io);
-                return;
-            }
-            comm->dso->transport_finalize = dso_transport_finalize;
-        }
-        dso_message_received(comm->dso, (uint8_t *)&comm->message->wire, comm->message->length);
-        break;
-
-    case dns_opcode_query:
-        // In theory this is permitted but it can't really be implemented because there's no way
-        // to say "here's the answer for this, and here's why that failed.
-        if (ntohs(comm->message->wire.qdcount) != 1) {
-            dp_simple_response(comm, dns_rcode_formerr);
-            return;
-        }
-        if (!dns_rr_parse(&question, comm->message->wire.data, comm->message->length, &offset, false, false)) {
-            dp_simple_response(comm, dns_rcode_formerr);
-            return;
-        }
-        dp_dns_query(comm, &question);
-        dns_rrdata_free(&question);
-        break;
-
-        // No support for other opcodes yet.
-    default:
-        dp_simple_response(comm, dns_rcode_notimp);
-        break;
-    }
-}
-
-void dns_input(comm_t *comm)
-{
-    dns_evaluate(comm);
-    if (comm->message != NULL) {
-        message_free(comm->message);
-        comm->message = NULL;
-    }
-}
-
-static int
-usage(const char *progname)
-{
-    ERROR("usage: " PUB_S_SRP, progname);
-    ERROR("ex: dnssd-proxy");
-    return 1;
-}
-
-// Called whenever we get a connection.
-void
-connected(comm_t *comm)
-{
-    INFO("connection from " PRI_S_SRP, comm->name);
-    return;
-}
-
-static bool config_string_handler(char **ret, const char *filename, const char *string, int lineno, bool tdot,
-                                  bool ldot)
-{
-    char *s;
-    int add_trailing_dot = 0;
-    int add_leading_dot = ldot ? 1 : 0;
-    int len = strlen(string);
-
-    // Space for NUL and leading dot.
-    if (tdot && len > 0 && string[len - 1] != '.') {
-        add_trailing_dot = 1;
-    }
-    s = malloc(strlen(string) + add_leading_dot + add_trailing_dot + 1);
-    if (s == NULL) {
-        ERROR("Unable to allocate domain name " PRI_S_SRP, string);
-        return false;
-    }
-    *ret = s;
-    if (ldot) {
-        *s++ = '.';
-    }
-    strcpy(s, string);
-    if (add_trailing_dot) {
-        s[len] = '.';
-        s[len + 1] = 0;
-    }
-    return true;
-}
-
-// Config file parsing...
-static bool interface_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    interface_t *interface = calloc(1, sizeof *interface);
-    if (interface == NULL) {
-        ERROR("Unable to allocate interface " PUB_S_SRP, hunks[1]);
-        return false;
-    }
-
-    interface->name = strdup(hunks[1]);
-    if (interface->name == NULL) {
-        ERROR("Unable to allocate interface name " PUB_S_SRP, hunks[1]);
-        free(interface);
-        return false;
-    }
-
-    if (!strcmp(hunks[0], "nopush")) {
-        interface->no_push = true;
-    }
-
-    if (new_served_domain(interface, hunks[2]) == NULL) {
-        free(interface->name);
-        free(interface);
-        return false;
-    }
-    return true;
-}
-
-static bool port_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    char *ep = NULL;
-    long port = strtol(hunks[1], &ep, 10);
-    if (port < 0 || port > 65535 || *ep != 0) {
-        ERROR("Invalid port number: " PUB_S_SRP, hunks[1]);
-        return false;
-    }
-    if (!strcmp(hunks[0], "udp-port")) {
-        udp_port = port;
-    } else if (!strcmp(hunks[0], "tcp-port")) {
-        tcp_port = port;
-    } else if (!strcmp(hunks[0], "tls-port")) {
-        tls_port = port;
-    }
-    return true;
-}
-
-static bool listen_addr_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    if (num_listen_addrs == MAX_ADDRS) {
-        ERROR("Only %d IPv4 listen addresses can be configured.", MAX_ADDRS);
-        return false;
-    }
-    return config_string_handler(&listen_addrs[num_listen_addrs++], filename, hunks[1], lineno, false, false);
-}
-
-static bool tls_key_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    return config_string_handler(&tls_key_filename, filename, hunks[1], lineno, false, false);
-}
-
-static bool tls_cert_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    return config_string_handler(&tls_cert_filename, filename, hunks[1], lineno, false, false);
-}
-
-static bool tls_cacert_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    return config_string_handler(&tls_cacert_filename, filename, hunks[1], lineno, false, false);
-}
-
-config_file_verb_t dp_verbs[] = {
-    { "interface",    3, 3, interface_handler },    // interface <name> <domain>
-    { "nopush",       3, 3, interface_handler },    // nopush <name> <domain>
-    { "udp-port",     2, 2, port_handler },         // udp-port <number>
-    { "tcp-port",     2, 2, port_handler },         // tcp-port <number>
-    { "tls-port",     2, 2, port_handler },         // tls-port <number>
-    { "tls-key",      2, 2, tls_key_handler },      // tls-key <filename>
-    { "tls-cert",     2, 2, tls_cert_handler },     // tls-cert <filename>
-    { "tls-cacert",   2, 2, tls_cacert_handler },   // tls-cacert <filename>
-    { "listen-addr",  2, 2, listen_addr_handler },  // listen-addr <IP address>
-};
-#define NUMCFVERBS ((sizeof dp_verbs) / sizeof (config_file_verb_t))
-
-int
-main(int argc, char **argv)
-{
-    int i;
-    comm_t *listener[4 + MAX_ADDRS];
-    int num_listeners = 0;
-
-    udp_port = tcp_port = 53;
-    tls_port = 853;
-
-    // Parse command line arguments
-    for (i = 1; i < argc; i++) {
-	  return usage(argv[0]);
-    }
-
-    // Read the config file
-    if (!config_parse(NULL, "/etc/dnssd-relay.cf", dp_verbs, NUMCFVERBS)) {
-        return 1;
-    }
-
-    map_interfaces();
-
-    if (!srp_tls_init()) {
-        return 1;
-    }
-
-    if (!ioloop_init()) {
-        return 1;
-    }
-
-    for (i = 0; i < num_listen_addrs; i++) {
-        listener[num_listeners] = setup_listener_socket(AF_UNSPEC, IPPROTO_TCP, true,
-                                                        tls_port, listen_addrs[i], "DNS TLS Listener", dns_input,
-                                                        connected, 0);
-        if (listener[num_listeners] == NULL) {
-            ERROR("TLS4 listener: fail.");
-            return 1;
-        }
-        num_listeners++;
-	}
-
-    // If we haven't been given any addresses to listen on, listen on an IPv4 address and an IPv6 address.
-    if (num_listen_addrs == 0) {
-        listener[num_listeners] = setup_listener_socket(AF_INET, IPPROTO_TCP, true, tls_port, NULL,
-                                                        "IPv4 DNS TLS Listener", dns_input, 0, 0);
-        if (listener[num_listeners] == NULL) {
-            ERROR("UDP4 listener: fail.");
-            return 1;
-        }
-        num_listeners++;
-
-        listener[num_listeners] = setup_listener_socket(AF_INET6, IPPROTO_TCP, true, tls_port, NULL,
-                                                        "IPv6 DNS TLS Listener", dns_input, 0, 0);
-        if (listener[num_listeners] == NULL) {
-            ERROR("UDP6 listener: fail.");
-            return 1;
-        }
-        num_listeners++;
-    }
-
-    for (i = 0; i < num_listeners; i++) {
-        INFO("Started " PRI_S_SRP, listener[i]->name);
-    }
-
-    do {
-        int something = 0;
-        something = ioloop_events(0);
-        INFO("dispatched %d events.", something);
-    } while (1);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/dso-utils.c b/ServiceRegistration/dso-utils.c
deleted file mode 100644
index a1b0842..0000000
--- a/ServiceRegistration/dso-utils.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* dso-utils.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- */
-
-#include <netinet/in.h>
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "dso-utils.h"
-#include "dso.h"
-
-void
-dso_simple_response(comm_t *comm, message_t *message, const dns_wire_t *wire, int rcode)
-{
-    struct iovec iov;
-    dns_wire_t response;
-    memset(&response, 0, DNS_HEADER_SIZE);
-
-    // We take the ID and the opcode from the incoming message, because if the
-    // header has been mangled, we (a) wouldn't have gotten here and (b) don't
-    // have any better choice anyway.
-    response.id = wire->id;
-    dns_qr_set(&response, dns_qr_response);
-    dns_opcode_set(&response, dns_opcode_get(wire));
-    dns_rcode_set(&response, rcode);
-    iov.iov_base = &response;
-    iov.iov_len = DNS_HEADER_SIZE; // No RRs
-    ioloop_send_message(comm, message, &iov, 1);
-}
-
-bool
-dso_send_simple_response(dso_state_t *dso, int rcode, const dns_wire_t *header, const char *UNUSED rcode_name)
-{
-    dso_simple_response((comm_t *)dso->transport, NULL, header, rcode);
-    return true;
-}
-
-bool
-dso_send_formerr(dso_state_t *dso, const dns_wire_t *header)
-{
-    comm_t *transport = dso->transport;
-    (void)header;
-    dso_simple_response(transport, NULL, header, dns_rcode_formerr);
-    return true;
-}
-
-void
-dso_retry_delay_response(comm_t *comm, message_t *message, const dns_wire_t *wire, int rcode, uint32_t milliseconds)
-{
-    dns_wire_t response;
-    dns_towire_state_t towire;
-    struct iovec iov;
-    memset(&response, 0, DNS_HEADER_SIZE);
-    memset(&towire, 0, sizeof(towire));
-
-    towire.p = &response.data[0];  // We start storing RR data here.
-    towire.lim = ((uint8_t *)&response) + sizeof(response);
-    towire.message = &response;
-    towire.p_rdlength = NULL;
-    towire.p_opt = NULL;
-
-    response.id = wire->id;
-    dns_qr_set(&response, dns_qr_response);
-    dns_opcode_set(&response, dns_opcode_get(wire));
-    dns_rcode_set(&response, rcode);
-
-    dns_u16_to_wire(&towire, kDSOType_RetryDelay);
-    // This shouldn't be possible.
-    if (towire.p + 2 > towire.lim) {
-        FAULT("No room for dso length in Retry Delay message.");
-        return;
-    }
-    uint8_t *p_dso_length = towire.p;
-    towire.p += 2;
-
-    dns_u32_to_wire(&towire, milliseconds);
-
-    int16_t dso_length = towire.p - p_dso_length - 2;
-    iov.iov_len = (towire.p - (uint8_t *)&response);
-    iov.iov_base = &response;
-
-    towire.p = p_dso_length;
-    dns_u16_to_wire(&towire, dso_length);
-    ioloop_send_message(comm, message, &iov, 1);
-}
-
-int32_t
-dso_transport_idle(void * UNUSED context, int32_t UNUSED now, int32_t next_event)
-{
-    return next_event;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/dso-utils.h b/ServiceRegistration/dso-utils.h
deleted file mode 100644
index 11edbda..0000000
--- a/ServiceRegistration/dso-utils.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* dso-utils.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- */
-
-#define DNSMessageHeader dns_wire_t
-
-void dso_simple_response(comm_t *NONNULL comm, message_t *NULLABLE message, const dns_wire_t *NONNULL wire, int rcode);
-void dso_retry_delay_response(comm_t *NONNULL comm, message_t *NONNULL message, const dns_wire_t *NONNULL wire,
-                              int rcode, uint32_t milliseconds);
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/fromwire.c b/ServiceRegistration/fromwire.c
deleted file mode 100644
index a89418d..0000000
--- a/ServiceRegistration/fromwire.c
+++ /dev/null
@@ -1,729 +0,0 @@
-/* fromwire.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * DNS wire-format functions.
- *
- * These are really simple functions for constructing DNS messages wire format.
- * The flow is that there is a transaction structure which contains pointers to both
- * a message output buffer and a response input buffer.   The structure is initialized,
- * and then the various wire format functions are called repeatedly to store data.
- * If an error occurs during this process, it's okay to just keep going, because the
- * error is recorded in the transaction; once all of the copy-in functions have been
- * called, the error status can be checked once at the end.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "srp.h"
-#include "dns-msg.h"
-
-bool
-dns_opt_parse(dns_edns0_t *NONNULL *NULLABLE ret, dns_rr_t *rr)
-{
-    dns_edns0_t *edns0, **p_edns0 = ret;
-    unsigned offset = 0;
-    dns_rdata_unparsed_t opt;
-
-    // This would be a weird coding error.
-    if (rr->type != dns_rrtype_opt) {
-        return false;
-    }
-    opt = rr->data.unparsed;
-
-    // RDATA is a series of TLVs
-    while (offset < opt.len) {
-        uint16_t tlv_type, tlv_len;
-
-        // Parse the TLV type and length.
-        if (!dns_u16_parse(opt.data, opt.len, &offset, &tlv_type) ||
-            !dns_u16_parse(opt.data, opt.len, &offset, &tlv_len))
-        {
-            return false;
-        }
-
-        // Range check the contents.
-        if (offset + tlv_len > opt.len) {
-            return false;
-        }
-
-        edns0 = calloc(1, tlv_len + sizeof(*edns0));
-        if (edns0 == NULL) {
-            return false;
-        }
-        // Stash the record.
-        edns0->length = tlv_len;
-        edns0->type = tlv_type;
-        memcpy(edns0->data, &opt.data[offset], tlv_len);
-        *p_edns0 = edns0;
-        p_edns0 = &edns0->next;
-        offset += tlv_len;
-    }
-    return true;
-}
-
-dns_label_t * NULLABLE
-dns_label_parse_(const uint8_t *buf, unsigned mlen, unsigned *NONNULL offp, const char *file, int line)
-{
-    uint8_t llen = buf[*offp];
-    dns_label_t *rv;
-
-    // Make sure that we got the data this label claims to encompass.
-    if (*offp + llen + 1 > mlen) {
-        DEBUG("claimed length of label is too long: %u > %u.\n", *offp + llen + 1, mlen);
-        return NULL;
-    }
-
-#ifdef MALLOC_DEBUG_LOGGING
-    rv = debug_calloc(1, (sizeof(*rv) - DNS_MAX_LABEL_SIZE) + llen + 1, file, line);
-#else
-    (void)file; (void)line;
-    rv = calloc(1, (sizeof(*rv) - DNS_MAX_LABEL_SIZE) + llen + 1);
-#endif
-    if (rv == NULL) {
-        DEBUG("memory allocation for %u byte label (%.*s) failed.\n",
-              *offp + llen + 1, *offp + llen + 1, &buf[*offp + 1]);
-        return NULL;
-    }
-
-    rv->len = llen;
-    memcpy(rv->data, &buf[*offp + 1], llen);
-    rv->data[llen] = 0; // We NUL-terminate the label for convenience
-    *offp += llen + 1;
-    return rv;
-}
-
-static bool
-dns_name_parse_in(dns_label_t *NONNULL *NULLABLE ret, const uint8_t *buf, unsigned len,
-                   unsigned *NONNULL offp, unsigned base, const char *file, int line)
-{
-    dns_label_t *rv;
-
-    if (*offp == len) {
-        return false;
-    }
-
-    // A pointer?
-    if ((buf[*offp] & 0xC0) == 0xC0) {
-        unsigned pointer;
-        if (*offp + 2 > len) {
-            DEBUG("incomplete compression pointer: %u > %u", *offp + 2, len);
-            return false;
-        }
-        pointer = (((unsigned)buf[*offp] & 0x3f) << 8) | (unsigned)buf[*offp + 1];
-        *offp += 2;
-        if (pointer < DNS_HEADER_SIZE) {
-            // Don't allow pointers into the header.
-            DEBUG("compression pointer points into header: %u.\n", pointer);
-            return false;
-        }
-        pointer -= DNS_HEADER_SIZE;
-        if (pointer >= base) {
-            // Don't allow a pointer forward, or to a pointer we've already visited.
-            DEBUG("compression pointer points forward: %u >= %u.\n", pointer, base);
-            return false;
-        }
-        if (buf[pointer] & 0xC0) {
-            // If this is a pointer to a pointer, it's not valid.
-            DEBUG("compression pointer points into pointer: %u %02x%02x.\n", pointer,
-                  buf[pointer], pointer + 1 < len ? buf[pointer + 1] : 0xFF);
-            return false;
-        }
-        if (buf[pointer] + pointer >= base || buf[pointer] + pointer >= *offp) {
-            // Possibly this isn't worth checking.
-            DEBUG("compression pointer points to something that goes past current position: %u %u\n",
-                  pointer, buf[pointer]);
-            return false;
-        }
-        return dns_name_parse_in(ret, buf, len, &pointer, pointer, file, line);
-    }
-    // We don't support binary labels, which are historical, and at this time there are no other valid
-    // DNS label types.
-    if (buf[*offp] & 0xC0) {
-        DEBUG("invalid label type: %x\n", buf[*offp]);
-        return false;
-    }
-
-    rv = dns_label_parse_(buf, len, offp, file, line);
-    if (rv == NULL) {
-        return false;
-    }
-
-    *ret = rv;
-
-    if (rv->len == 0) {
-        return true;
-    }
-    return dns_name_parse_in(&rv->next, buf, len, offp, base, file, line);
-}
-
-bool
-dns_name_parse_(dns_label_t *NONNULL *NULLABLE ret, const uint8_t *buf,
-                unsigned len, unsigned *NONNULL offp, unsigned base, const char *file, int line)
-{
-    dns_label_t *rv = NULL, *next;
-
-    if (!dns_name_parse_in(&rv, buf, len, offp, base, file, line)) {
-        for (; rv != NULL; rv = next) {
-            next = rv->next;
-            free(rv);
-        }
-        return false;
-    }
-    *ret = rv;
-    return true;
-}
-
-bool
-dns_u8_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint8_t *NONNULL ret)
-{
-    uint8_t rv;
-    if (*offp + 1 > len) {
-        DEBUG("dns_u8_parse: not enough room: %u > %u.\n", *offp + 1, len);
-        return false;
-    }
-
-    rv = buf[*offp];
-    *offp += 1;
-    *ret = rv;
-    return true;
-}
-
-bool
-dns_u16_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint16_t *NONNULL ret)
-{
-    uint16_t rv;
-    if (*offp + 2 > len) {
-        DEBUG("dns_u16_parse: not enough room: %u > %u.\n", *offp + 2, len);
-        return false;
-    }
-
-    rv = (uint16_t)(buf[*offp] << 8) | (uint16_t)(buf[*offp + 1]);
-    *offp += 2;
-    *ret = rv;
-    return true;
-}
-
-bool
-dns_u32_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint32_t *NONNULL ret)
-{
-    uint32_t rv;
-    if (*offp + 4 > len) {
-        DEBUG("dns_u32_parse: not enough room: %u > %u.\n", *offp + 4, len);
-        return false;
-    }
-
-    rv = (((uint32_t)(buf[*offp]) << 24) | ((uint32_t)(buf[*offp + 1]) << 16) |
-          ((uint32_t)(buf[*offp + 2]) << 8) | (uint32_t)(buf[*offp + 3]));
-    *offp += 4;
-    *ret = rv;
-    return true;
-}
-
-bool
-dns_u64_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint64_t *NONNULL ret)
-{
-    uint64_t rv;
-    if (*offp + 8 > len) {
-        DEBUG("dns_u64_parse: not enough room: %u > %u.\n", *offp + 8, len);
-        return false;
-    }
-
-    rv = (((uint64_t)(buf[*offp]    ) << 56) | ((uint64_t)(buf[*offp + 1]) << 48) |
-          ((uint64_t)(buf[*offp + 2]) << 40) | ((uint64_t)(buf[*offp + 3]) << 32) |
-          ((uint64_t)(buf[*offp + 4]) << 24) | ((uint64_t)(buf[*offp + 5]) << 16) |
-          ((uint64_t)(buf[*offp + 6]) <<  8) | ((uint64_t)(buf[*offp + 7])));
-    *offp += 8;
-    *ret = rv;
-    return true;
-}
-
-static void
-dns_rrdata_dump(dns_rr_t *rr, bool dump_to_stderr)
-{
-    char nbuf[INET6_ADDRSTRLEN];
-    char buf[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-    char outbuf[2048];
-    char *obp;
-    size_t output_len, avail = 2048;
-
-#define ADVANCE(result, start, remaining) \
-    output_len = strlen(start);           \
-    result = start + output_len;          \
-    avail = (remaining) - output_len
-#define DEPCHAR(ch)     \
-    do {                     \
-        if (avail > 1) {     \
-            *obp++ = (ch);   \
-            *obp = 0;        \
-            --avail;         \
-        }                    \
-    } while (0)
-
-
-    switch(rr->type) {
-    case dns_rrtype_key:
-        snprintf(outbuf, sizeof(outbuf),
-                 "KEY <AC %d> <Z %d> <XT %d> <ZZ %d> <NAMTYPE %d> <ZZZZ %d> <ORY %d> %d %d ",
-                 ((rr->data.key.flags & 0xC000) >> 14 & 3), ((rr->data.key.flags & 0x2000) >> 13) & 1,
-                 ((rr->data.key.flags & 0x1000) >> 12) & 1, ((rr->data.key.flags & 0xC00) >> 10) & 3,
-                 ((rr->data.key.flags & 0x300) >> 8) & 3, ((rr->data.key.flags & 0xF0) >> 4) & 15,
-                 rr->data.key.flags & 15, rr->data.key.protocol, rr->data.key.algorithm);
-        ADVANCE(obp, outbuf, sizeof outbuf);
-
-        for (unsigned i = 0; i < rr->data.key.len; i++) {
-            if (i == 0) {
-                snprintf(obp, avail, "%d [%02x", rr->data.key.len, rr->data.key.key[i]);
-                ADVANCE(obp, obp, avail);
-            } else {
-                snprintf(obp, avail, " %02x", rr->data.key.key[i]);
-                ADVANCE(obp, obp, avail);
-            }
-        }
-        DEPCHAR(']');
-        break;
-
-    case dns_rrtype_sig:
-        dns_name_print(rr->data.sig.signer, buf, sizeof(buf));
-        snprintf(outbuf, sizeof(outbuf), "SIG %d %d %d %lu %lu %lu %d %s",
-                 rr->data.sig.type, rr->data.sig.algorithm, rr->data.sig.label,
-                 (unsigned long)rr->data.sig.rrttl, (unsigned long)rr->data.sig.expiry,
-                 (unsigned long)rr->data.sig.inception, rr->data.sig.key_tag, buf);
-        ADVANCE(obp, outbuf, sizeof outbuf);
-        for (unsigned i = 0; i < rr->data.sig.len; i++) {
-            if (i == 0) {
-                snprintf(obp, avail, "%d [%02x", rr->data.sig.len, rr->data.sig.signature[i]);
-                ADVANCE(obp, obp, avail);
-            } else {
-                snprintf(obp, avail, " %02x", rr->data.sig.signature[i]);
-                ADVANCE(obp, obp, avail);
-            }
-        }
-        DEPCHAR(']');
-        break;
-
-    case dns_rrtype_srv:
-        dns_name_print(rr->data.srv.name, buf, sizeof(buf));
-        snprintf(outbuf, sizeof(outbuf), "SRV %d %d %d %s", rr->data.srv.priority, rr->data.srv.weight,
-                 rr->data.srv.port, buf);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        break;
-
-    case dns_rrtype_ptr:
-        dns_name_print(rr->data.ptr.name, buf, sizeof(buf));
-        snprintf(outbuf, sizeof(outbuf), "PTR %s", buf);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        break;
-
-    case dns_rrtype_cname:
-        dns_name_print(rr->data.cname.name, buf, sizeof(buf));
-        snprintf(outbuf, sizeof(outbuf), "CNAME %s", buf);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        break;
-
-    case dns_rrtype_a:
-        inet_ntop(AF_INET, &rr->data.a, nbuf, sizeof(nbuf));
-        snprintf(outbuf, sizeof(outbuf), "A %s", nbuf);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        break;
-
-    case dns_rrtype_aaaa:
-        inet_ntop(AF_INET6, &rr->data.aaaa, nbuf, sizeof(nbuf));
-        snprintf(outbuf, sizeof(outbuf), "AAAA %s", nbuf);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        break;
-
-    case dns_rrtype_txt:
-        strcpy(outbuf, "TXT ");
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        for (unsigned i = 0; i < rr->data.txt.len; i++) {
-            if (isascii(rr->data.txt.data[i]) && isprint(rr->data.txt.data[i])) {
-                DEPCHAR(rr->data.txt.data[i]);
-            } else {
-                snprintf(obp, avail, "<%x>", rr->data.txt.data[i]);
-                ADVANCE(obp, obp, avail);
-            }
-        }
-        DEPCHAR('"');
-        break;
-
-    default:
-        snprintf(outbuf, sizeof(outbuf), "<rrtype %d>:", rr->type);
-        ADVANCE(obp, outbuf, sizeof(outbuf));
-        if (rr->data.unparsed.len == 0) {
-            snprintf(obp, avail, " <none>");
-            ADVANCE(obp, obp, avail);
-        } else {
-            for (unsigned i = 0; i < rr->data.unparsed.len; i++) {
-                snprintf(obp, avail, " %02x", rr->data.unparsed.data[i]);
-                ADVANCE(obp, obp, avail);
-            }
-        }
-        break;
-    }
-    if (dump_to_stderr) {
-        fprintf(stderr, "%s\n", outbuf);
-    } else {
-        DEBUG(PUB_S_SRP, outbuf);
-    }
-}
-
-bool
-dns_rdata_parse_data_(dns_rr_t *NONNULL rr, const uint8_t *buf, unsigned *NONNULL offp, unsigned target, uint16_t rdlen,
-                      unsigned rrstart, const char *file, int line)
-{
-    if (target < *offp) {
-        DEBUG("target %u < *offp %u", target, *offp);
-        return false;
-    }
-    switch(rr->type) {
-    case dns_rrtype_key:
-        if (!dns_u16_parse(buf, target, offp, &rr->data.key.flags) ||
-            !dns_u8_parse(buf, target, offp, &rr->data.key.protocol) ||
-            !dns_u8_parse(buf, target, offp, &rr->data.key.algorithm)) {
-            return false;
-        }
-        rr->data.key.len = (unsigned)(target - *offp);
-#ifdef MALLOC_DEBUG_LOGGING
-        rr->data.key.key = debug_malloc(rr->data.key.len, file, line);
-#else
-        rr->data.key.key = malloc(rr->data.key.len);
-#endif
-        if (!rr->data.key.key) {
-            return false;
-        }
-        memcpy(rr->data.key.key, &buf[*offp], rr->data.key.len);
-        *offp += rr->data.key.len;
-        break;
-
-    case dns_rrtype_sig:
-        rr->data.sig.start = rrstart;
-        if (!dns_u16_parse(buf, target, offp, &rr->data.sig.type) ||
-            !dns_u8_parse(buf, target, offp, &rr->data.sig.algorithm) ||
-            !dns_u8_parse(buf, target, offp, &rr->data.sig.label) ||
-            !dns_u32_parse(buf, target, offp, &rr->data.sig.rrttl) ||
-            !dns_u32_parse(buf, target, offp, &rr->data.sig.expiry) ||
-            !dns_u32_parse(buf, target, offp, &rr->data.sig.inception) ||
-            !dns_u16_parse(buf, target, offp, &rr->data.sig.key_tag) ||
-            !dns_name_parse_(&rr->data.sig.signer, buf, target, offp, *offp, file, line)) {
-            return false;
-        }
-        // The signature is what's left of the RRDATA.  It covers the message up to the signature, so we
-        // remember where it starts so as to know what memory to cover to validate it.
-        rr->data.sig.len = target - *offp;
-#ifdef MALLOC_DEBUG_LOGGING
-        rr->data.sig.signature = debug_malloc(rr->data.sig.len, file, line);
-#else
-        rr->data.sig.signature = malloc(rr->data.sig.len);
-#endif
-        if (!rr->data.sig.signature) {
-            return false;
-        }
-        memcpy(rr->data.sig.signature, &buf[*offp], rr->data.sig.len);
-        *offp += rr->data.sig.len;
-        break;
-
-    case dns_rrtype_srv:
-        if (!dns_u16_parse(buf, target, offp, &rr->data.srv.priority) ||
-            !dns_u16_parse(buf, target, offp, &rr->data.srv.weight) ||
-            !dns_u16_parse(buf, target, offp, &rr->data.srv.port)) {
-            return false;
-        }
-        // This fallthrough assumes that the first element in the srv, ptr and cname structs is
-        // a pointer to a domain name.
-
-    case dns_rrtype_ns:
-    case dns_rrtype_ptr:
-    case dns_rrtype_cname:
-        if (!dns_name_parse_(&rr->data.ptr.name, buf, target, offp, *offp, file, line)) {
-            return false;
-        }
-        break;
-
-    case dns_rrtype_a:
-        if (rdlen != 4) {
-            DEBUG("dns_rdata_parse: A rdlen is not 4: %u", rdlen);
-            return false;
-        }
-        memcpy(&rr->data.a, &buf[*offp], rdlen);
-        *offp = target;
-        break;
-
-    case dns_rrtype_aaaa:
-        if (rdlen != 16) {
-            DEBUG("dns_rdata_parse: AAAA rdlen is not 16: %u", rdlen);
-            return false;
-        }
-        memcpy(&rr->data.aaaa, &buf[*offp], rdlen);
-        *offp = target;
-        break;
-
-    case dns_rrtype_txt:
-    {
-        unsigned left = target - *offp;
-        if (left != rdlen) {
-            ERROR("TXT record length %u doesn't match remaining space %d", rdlen, left);
-        }
-        if (left > UINT8_MAX) {
-            ERROR("TXT record length %u is longer than 255", left);
-        }
-        rr->data.txt.len = (uint8_t)left;
-#ifdef MALLOC_DEBUG_LOGGING
-        rr->data.txt.data = debug_malloc(rr->data.txt.len, file, line);
-#else
-        rr->data.txt.data = malloc(rr->data.txt.len);
-#endif
-        if (rr->data.txt.data == NULL) {
-            DEBUG("dns_rdata_parse: no memory for TXT RR");
-            return false;
-        }
-        memcpy(rr->data.txt.data, &buf[*offp], rr->data.txt.len);
-        *offp = target;
-        break;
-    }
-
-    default:
-        if (rdlen > 0) {
-#ifdef MALLOC_DEBUG_LOGGING
-            rr->data.unparsed.data = debug_malloc(rdlen, file, line);
-#else
-            rr->data.unparsed.data = malloc(rdlen);
-#endif
-            if (rr->data.unparsed.data == NULL) {
-                return false;
-            }
-            memcpy(rr->data.unparsed.data, &buf[*offp], rdlen);
-        }
-        rr->data.unparsed.len = rdlen;
-        *offp = target;
-        break;
-    }
-    if (*offp != target) {
-        DEBUG("dns_rdata_parse: parse for rrtype %d not fully contained: %u %u", rr->type, target, *offp);
-        return false;
-    }
-    return true;
-}
-
-static bool
-dns_rdata_parse_(dns_rr_t *NONNULL rr,
-                 const uint8_t *buf, unsigned len, unsigned *NONNULL offp, unsigned rrstart, const char *file, int line)
-{
-    uint16_t rdlen;
-    unsigned target;
-
-    if (!dns_u16_parse(buf, len, offp, &rdlen)) {
-        return false;
-    }
-    target = *offp + rdlen;
-    if (target > len) {
-        return false;
-    }
-    return dns_rdata_parse_data_(rr, buf, offp, target, rdlen, rrstart, file, line);
-}
-
-bool
-dns_rr_parse_(dns_rr_t *NONNULL rr, const uint8_t *buf, unsigned len, unsigned *NONNULL offp, bool rrdata_expected,
-              bool dump_stderr, const char *file, int line)
-{
-    unsigned rrstart = *offp; // Needed to mark the start of the SIG RR for SIG(0).
-
-    memset(rr, 0, sizeof(*rr));
-    if (!dns_name_parse_(&rr->name, buf, len, offp, *offp, file, line)) {
-        return false;
-    }
-
-    if (!dns_u16_parse(buf, len, offp, &rr->type)) {
-        return false;
-    }
-
-    if (!dns_u16_parse(buf, len, offp, &rr->qclass)) {
-        return false;
-    }
-
-    if (rrdata_expected) {
-        if (!dns_u32_parse(buf, len, offp, &rr->ttl)) {
-            return false;
-        }
-        if (!dns_rdata_parse_(rr, buf, len, offp, rrstart, file, line)) {
-            return false;
-        }
-    }
-
-    DNS_NAME_GEN_SRP(rr->name, name_buf);
-    if (dump_stderr) {
-        fprintf(stderr, "rrtype: %u  qclass: %u  name: %s %s\n",
-              rr->type, rr->qclass, DNS_NAME_PARAM_SRP(rr->name, name_buf), rrdata_expected ? "  rrdata:" : "");
-    } else {
-        DEBUG("rrtype: %u  qclass: %u  name: " PRI_DNS_NAME_SRP PUB_S_SRP,
-              rr->type, rr->qclass, DNS_NAME_PARAM_SRP(rr->name, name_buf), rrdata_expected ? "  rrdata:" : "");
-    }
-    if (rrdata_expected) {
-        dns_rrdata_dump(rr, dump_stderr);
-    }
-    return true;
-}
-
-void
-dns_rrdata_free(dns_rr_t *rr)
-{
-    if (rr == NULL) {
-        return;
-    }
-    switch(rr->type) {
-    case dns_rrtype_a:
-    case dns_rrtype_aaaa:
-        break;
-
-    case dns_rrtype_key:
-        free(rr->data.key.key);
-        break;
-
-    case dns_rrtype_sig:
-        dns_name_free(rr->data.sig.signer);
-        free(rr->data.sig.signature);
-        break;
-
-    case dns_rrtype_srv:
-    case dns_rrtype_ptr:
-    case dns_rrtype_ns:
-    case dns_rrtype_cname:
-        dns_name_free(rr->data.ptr.name);
-#ifndef __clang_analyzer__
-        rr->data.ptr.name = NULL;
-#endif
-            break;
-
-    case dns_rrtype_txt:
-        free(rr->data.txt.data);
-#ifndef __clang_analyzer__
-        rr->data.txt.data = NULL;
-#endif
-        break;
-
-    default:
-        if (rr->data.unparsed.len > 0 && rr->data.unparsed.data != NULL) {
-            free(rr->data.unparsed.data);
-        }
-        rr->data.unparsed.data = NULL;
-    }
-}
-
-void
-dns_message_free(dns_message_t *message)
-{
-    dns_edns0_t *edns0, *next;
-
-#define FREE(count, sets)                               \
-    if (message->sets) {                                \
-        for (unsigned i = 0; i < message->count; i++) { \
-            dns_rr_t *set = &message->sets[i];          \
-            if (set->name) {                            \
-                dns_name_free(set->name);               \
-            }                                           \
-            dns_rrdata_free(set);                       \
-        }                                               \
-        free(message->sets);                            \
-    }
-    FREE(qdcount, questions);
-    FREE(ancount, answers);
-    FREE(nscount, authority);
-    FREE(arcount, additional);
-#undef FREE
-    for (edns0 = message->edns0; edns0 != NULL; edns0 = next) {
-        next = edns0->next;
-        free(edns0);
-    }
-    free(message);
-}
-
-bool
-dns_wire_parse_(dns_message_t *NONNULL *NULLABLE ret, dns_wire_t *message, unsigned len, bool dump_to_stderr,
-                const char *file, int line)
-{
-    unsigned offset = 0;
-    unsigned data_len = len - DNS_HEADER_SIZE;
-    dns_message_t *rv;
-
-    if (len < DNS_HEADER_SIZE) {
-        return false;
-    }
-#ifdef MALLOC_DEBUG_LOGGING
-    rv = debug_calloc(1, sizeof(*rv), file, line);
-#else
-    rv = calloc(1, sizeof(*rv));
-#endif
-    if (rv == NULL) {
-        return false;
-    }
-
-#define PARSE(count, sets, name, rrdata_expected)                                   \
-    rv->count = ntohs(message->count);                                              \
-    if (rv->count > 50) {                                                           \
-        rv->count = 0;                                                              \
-        dns_message_free(rv);                                                       \
-        return false;                                                               \
-    }                                                                               \
-    DEBUG("Section %s, %d records", name, rv->count);                               \
-                                                                                    \
-    if (rv->count != 0) {                                                           \
-        rv->sets = calloc(rv->count, sizeof(*rv->sets));                            \
-        if (rv->sets == NULL) {                                                     \
-            dns_message_free(rv);                                                   \
-            return false;                                                           \
-        }                                                                           \
-    }                                                                               \
-                                                                                    \
-    for (unsigned i = 0; i < rv->count; i++) {                                      \
-        if (!dns_rr_parse_(&rv->sets[i], message->data, data_len, &offset,          \
-                           rrdata_expected, dump_to_stderr, file, line)) {          \
-            dns_message_free(rv);                                                   \
-            ERROR(name " %d RR parse failed.\n", i);                                \
-            return false;                                                           \
-        }                                                                           \
-    }
-    PARSE(qdcount,  questions, "question", false);
-    PARSE(ancount,    answers, "answers", true);
-    PARSE(nscount,  authority, "authority", true);
-    PARSE(arcount, additional, "additional", true);
-#undef PARSE
-
-    for (unsigned i = 0; i < rv->arcount; i++) {
-        // Parse EDNS(0)
-        if (rv->additional[i].type == dns_rrtype_opt) {
-            if (!dns_opt_parse(&rv->edns0, &rv->additional[i])) {
-                dns_message_free(rv);
-                return false;
-            }
-        }
-    }
-    *ret = rv;
-    return true;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/hmac-macos.c b/ServiceRegistration/hmac-macos.c
deleted file mode 100644
index 949261d..0000000
--- a/ServiceRegistration/hmac-macos.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* hash.c
- *
- * Copyright (c) 2019 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.
- *
- * DNS SIG(0) signature generation for DNSSD SRP using Security Framework.
- *
- * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
- * into KEY RR data, and computing hashatures.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#define SRP_CRYPTO_MACOS_INTERNAL
-#include "srp-crypto.h"
-
-// Function to generate a signature given some data and a private key
-void
-srp_hmac_iov(hmac_key_t *key, uint8_t *output, size_t max, struct iovec *iov, int count)
-{
-    // int digest_size = 0;
-    // int i, line;
-    (void)count;(void)iov;(void)output; (void)key; (void)max;
-#define KABLOOIE line = __LINE__ - 1; goto kablooie
-#if 0
-    switch(key->algorithm) {
-    case  SRP_HMAC_TYPE_SHA256:
-        // digest_size = mbedtls_md_get_size(md_type);
-        // break;
-    default:
-        ERROR("srp_hmac_iov: unsupported HMAC hash algorithm: %d", key->algorithm);
-        return;
-    }
-    if (max < digest_size) {
-        ERROR("srp_hmac_iov: not enough space in output buffer (%lu) for hash (%d).",
-              (unsigned long)max, digest_size);
-        return;
-    }
-#endif
-    // if ((status = mbedtls_md_hmac_starts(&ctx, key->secret, key->length)) != 0) {
-    //     KABLOOIE;
-    // }
-	// for (i = 0; i < count; i++) {
-    //     if ((status = mbedtls_md_hmac_update(&ctx, iov[i].iov_base, iov[i].iov_len)) != 0) {
-    //         KABLOOIE;
-    //     }
-	// }
-	// if ((status = mbedtls_md_hmac_finish(&ctx, output)) != 0) {
-    //     KABLOOIE;
-	// }
-}
-
-int
-srp_base64_parse(char *src, size_t *len_ret, uint8_t *buf, size_t buflen)
-{
-    (void)src; (void)len_ret; (void)buf; (void)buflen;
-#if 0
-    size_t slen = strlen(src);
-    int ret = mbedtls_base64_decode(buf, buflen, len_ret, (const unsigned char *)src, slen);
-    if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
-        return ENOBUFS;
-    } else if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
-        return EILSEQ;
-    } else if (ret < 0) {
-        return EINVAL;
-    }
-    return 0;
-#else
-    return EINVAL;
-#endif
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/hmac-mbedtls.c b/ServiceRegistration/hmac-mbedtls.c
deleted file mode 100644
index cb44adc..0000000
--- a/ServiceRegistration/hmac-mbedtls.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* hash.c
- *
- * Copyright (c) 2019 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.
- *
- * DNS SIG(0) hashature generation for DNSSD SRP using mbedtls.
- *
- * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
- * into KEY RR data, and computing hashatures.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-
-// Function to generate a signature given some data and a private key
-void
-srp_hmac_iov(hmac_key_t *key, uint8_t *output, size_t max, struct iovec *iov, int count)
-{
-    int status;
-    char errbuf[64];
-    mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *md_type;
-    int digest_size;
-	int i, line;
-#define KABLOOIE line = __LINE__ - 1; goto kablooie
-
-    switch(key->algorithm) {
-    case  SRP_HMAC_TYPE_SHA256:
-        md_type = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
-        if (md_type == NULL) {
-            ERROR("srp_hmac_iov: HMAC_SHA256 support missing");
-            return;
-        }
-        digest_size = mbedtls_md_get_size(md_type);
-        break;
-    default:
-        ERROR("srp_hmac_iov: unsupported HMAC hash algorithm: %d", key->algorithm);
-        return;
-    }
-    if (max < digest_size) {
-        ERROR("srp_hmac_iov: not enough space in output buffer (%lu) for hash (%d).",
-              (unsigned long)max, digest_size);
-        return;
-    }
-
-    if ((status = mbedtls_md_setup(&ctx, md_type, 1)) != 0) {
-        KABLOOIE;
-    kablooie:
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("srp_hmac_iov failed at hmac-mbedtls.c line %d: " PUB_S_SRP, line, errbuf);
-    }
-
-    if ((status = mbedtls_md_hmac_starts(&ctx, key->secret, key->length)) != 0) {
-        KABLOOIE;
-    }
-	for (i = 0; i < count; i++) {
-        if ((status = mbedtls_md_hmac_update(&ctx, iov[i].iov_base, iov[i].iov_len)) != 0) {
-            KABLOOIE;
-        }
-	}
-	if ((status = mbedtls_md_hmac_finish(&ctx, output)) != 0) {
-        KABLOOIE;
-	}
-}
-
-int
-srp_base64_parse(char *src, size_t *len_ret, uint8_t *buf, size_t buflen)
-{
-    size_t slen = strlen(src);
-    int ret = mbedtls_base64_decode(buf, buflen, len_ret, (const unsigned char *)src, slen);
-    if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
-        return ENOBUFS;
-    } else if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
-        return EILSEQ;
-    } else if (ret < 0) {
-        return EINVAL;
-    }
-    return 0;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/hmac-openssl.c b/ServiceRegistration/hmac-openssl.c
deleted file mode 100644
index 76176f6..0000000
--- a/ServiceRegistration/hmac-openssl.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* hmac-openssl.c
- *
- * Copyright (c) 2019 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.
- *
- * Hashed message authentication code functions using OpenSSL.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#define SRP_CRYPTO_OPENSSL_INTERNAL
-#include "srp-crypto.h"
-
-// Function to generate a signature given some data and a private key
-void
-srp_hmac_iov(hmac_key_t *key, uint8_t *output, size_t max, struct iovec *iov, int count)
-{
-    int status;
-    char errbuf[64];
-    uint8_t kipad[SRP_SHA256_BLOCK_SIZE], kopad[SRP_SHA256_BLOCK_SIZE], intermediate[SRP_SHA256_HASH_SIZE];
-    EVP_MD_CTX inner, outer;
-    const EVP_MD md;
-    int i;
-
-    if (key->algorithm != SRP_HMAC_TYPE_SHA256) {
-        ERROR("srp_hmac_iov: unsupported HMAC hash algorithm: %d", key->algorithm);
-        return;
-    }
-    if (max < SRP_SHA256_HASH_SIZE) {
-        ERROR("srp_hmac_iov: not enough space in output buffer (%lu) for hash (%d).",
-              (unsigned long)max, SRP_SHA256_HASH_SIZE);
-        return;
-    }
-
-    md = EVP_sha256();
-    EVP_MD_CTX_INIT(&inner);
-
-    // If the key is longer than the block size, hash it and use the digest as the key.
-    if (key->length > SRP_SHA256_BLOCK_SIZE) {
-        if ((status = EVP_DigestInit(&inner, md)) != 0) {
-            ERROR("srp_hmac_iov failed to initialize key digest");
-            return;
-        }
-        // Compute H(K)
-        if ((status = EVP_DigestUpdate(&inner, key, key->length)) != 0) {
-            ERROR("srp_hmac_iov failed to hash key");
-            return;
-        }
-        if ((status = EVP_DigestFinal(&inner, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
-            ERROR("srp_hmac_iov failed to digest key");
-            return;
-        }
-        EVP_MD_CTX_INIT(&inner);
-    }
-
-    // Compute key ^ kipad and key ^ kopad
-    for (i = 0; i < SRP_SHA256_BLOCK_SIZE; i++) {
-        uint8_t byte = i >= key->length ? 0 : key->secret[i];
-        kipad[i] = byte ^ 0x36;
-        kopad[i] = byte ^ 0x5c;
-    }
-
-    if ((status = EVP_DigestInit(&inner, md)) != 0) {
-        ERROR("srp_hmac_iov failed to initialize inner digest");
-        return;
-    }
-    // Compute H(K xor ipad, text)
-    if ((status = EVP_DigestUpdate(&inner, kipad, SRP_SHA256_BLOCK_SIZE)) != 0) {
-        ERROR("srp_hmac_iov failed to hash ipad to inner digest");
-        return;
-    }
-    for (i = 0; i < count; i++) {
-        if ((status = EVP_DigestUpdate(&inner, iov[i].iov_base, iov[i].iov_len)) != 0) {
-            ERROR("srp_hmac_iov failed to hash chunk %d to inner digest", i);
-            return;
-        }
-    }
-    if ((status = EVP_DigestFinal(&inner, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
-        ERROR("srp_hmac_iov failed to hash ipad to inner digest");
-        return;
-    }
-
-    // Compute H(K xor opad, H(K xor ipad, text))
-    EVP_MD_CTX_INIT(&outer);
-    if ((status = EVP_DigestInit(&outer, md)) != 0) {
-        ERROR("srp_hmac_iov failed to initialize outer digest");
-        return;
-    }
-    if ((status = EVP_DigestUpdate(&outer, kopad, SRP_SHA256_BLOCK_SIZE)) != 0) {
-        ERROR("srp_hmac_iov failed to hash outer pad");
-        return;
-        goto kablooie;
-    }
-    if ((status = EVP_DigestUpdate(&outer, intermediate, SRP_SHA256_HASH_SIZE)) != 0) {
-        ERROR("srp_hmac_iov failed to hash outer digest");
-        return;
-        goto kablooie;
-    }
-    if ((status = EVP_DigestFinal(&outer, output, max)) != 0) {
-        ERROR("srp_hmac_iov failed to hash outer outer pad with inner digest");
-        return;
-    }
-    // Bob's your uncle...
-}
-
-int
-srp_base64_parse(char *src, size_t *len_ret, uint8_t *buf, size_t buflen)
-{
-    size_t slen = strlen(src);
-    int ret = mbedtls_base64_decode(buf, buflen, len_ret, (const unsigned char *)src, slen);
-    if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
-        return ENOBUFS;
-    } else if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
-        return EILSEQ;
-    } else if (ret < 0) {
-        return EINVAL;
-    }
-    return 0;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/interface-monitor-macos.h b/ServiceRegistration/interface-monitor-macos.h
deleted file mode 100644
index 786d542..0000000
--- a/ServiceRegistration/interface-monitor-macos.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* interface-monitor-macos.h
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __INTERFACE_MONITOR_MACOS_H__
-#define __INTERFACE_MONITOR_MACOS_H__
-
-#include <CoreUtils/CommonServices.h>
-#include <dispatch/dispatch.h>
-
-typedef struct ifmon_s *ifmon_t;
-
-CU_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-ifmon_t
-ifmon_create(dispatch_queue_t queue);
-
-void
-ifmon_set_primary_ip_changed_handler(ifmon_t monitor, dispatch_block_t handler);
-
-void
-ifmon_activate(ifmon_t monitor, dispatch_block_t completion_handler);
-
-sockaddr_ip
-ifmon_get_primary_ipv4_address(ifmon_t monitor);
-
-sockaddr_ip
-ifmon_get_primary_ipv6_address(ifmon_t monitor);
-
-void
-ifmon_invalidate(ifmon_t monitor);
-
-void
-ifmon_release(ifmon_t monitor);
-
-__END_DECLS
-
-CU_ASSUME_NONNULL_END
-
-#endif	// __INTERFACE_MONITOR_MACOS_H__
diff --git a/ServiceRegistration/ioloop-common.c b/ServiceRegistration/ioloop-common.c
deleted file mode 100644
index d8c6f23..0000000
--- a/ServiceRegistration/ioloop-common.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* ioloop-common.c
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- *
- * This file contains common code shared by service registration code.
- */
-
-//======================================================================================================================
-// MARK: - Headers
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include <dns_sd.h> // for DNSServiceRef and DNSRecordRef.
-#include <stdlib.h>
-#include <netinet/in.h>
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "ioloop-common.h"
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Functions
-
-dnssd_txn_t *NULLABLE
-dnssd_txn_create_shared_(const char *const NONNULL file, const int line)
-{
-    DNSServiceRef service_ref = NULL;
-    dnssd_txn_t *txn = NULL;
-
-    const DNSServiceErrorType dns_err = DNSServiceCreateConnection(&service_ref);
-    if (dns_err != kDNSServiceErr_NoError) {
-        goto exit;
-    }
-
-    txn = ioloop_dnssd_txn_add_(service_ref, NULL, NULL, NULL, file, line);
-    if (txn == NULL) {
-        MDNS_DISPOSE_DNS_SERVICE_REF(service_ref);
-        goto exit;
-    }
-
-exit:
-    return txn;
-}
-
-//======================================================================================================================
-
-service_connection_t *NULLABLE
-service_connection_create_(dnssd_txn_t *const NONNULL shared_connection, const char *const NONNULL file, const int line)
-{
-    service_connection_t *const connection = mdns_calloc(1, sizeof(*connection));
-    if (connection == NULL) {
-        return connection;
-    }
-
-    connection->shared_connection = shared_connection;
-    // Increase the reference count by one.
-    ioloop_dnssd_txn_retain_(connection->shared_connection, file, line);
-    // Some DNSService operations need a copy of the shared DNSServiceRef.
-    connection->service_ref = shared_connection->sdref;
-
-    // Before the DNSService operation that creates a real copy of the shared DNSServiceRef, all service_connection_t
-    // is sharing the same one.
-    connection->shares_service_ref = true;
-
-    return connection;
-}
-
-//======================================================================================================================
-
-void
-service_connection_cancel_and_release_(service_connection_t *const NONNULL connection,
-                                       const char *const NONNULL file, const int line)
-{
-    if (connection->shares_service_ref) {
-        if (connection->record_ref != NULL) {
-            DNSServiceRemoveRecord(connection->service_ref, connection->record_ref, 0);
-        }
-    } else {
-        MDNS_DISPOSE_DNS_SERVICE_REF(connection->service_ref);
-    }
-    // Decrease the reference count by one.
-    ioloop_dnssd_txn_release_(connection->shared_connection, file, line);
-
-    service_connection_t *conn_to_free = connection;
-    mdns_free(conn_to_free);
-}
-
-//======================================================================================================================
-
-void
-service_connection_set_service_ref(service_connection_t *const NONNULL connection,
-                                   const DNSServiceRef NONNULL new_service_ref)
-{
-    connection->service_ref = new_service_ref;
-    connection->shares_service_ref = false;
-}
-
-//======================================================================================================================
-
-DNSServiceRef NONNULL
-service_connection_get_service_ref(service_connection_t *const NONNULL connection)
-{
-    return connection->service_ref;
-}
-
-//======================================================================================================================
-
-void
-service_connection_set_record_ref(service_connection_t *const NONNULL connection,
-                                  DNSRecordRef const NONNULL new_record_ref)
-{
-    connection->record_ref = new_record_ref;
-    // connection->shares_service_ref is set to true by default.
-}
-
-//======================================================================================================================
-
-void
-service_connection_set_context(service_connection_t *const NONNULL connection, void *const NULLABLE context)
-{
-    connection->context = context;
-}
-
-//======================================================================================================================
-
-void *NULLABLE
-service_connection_get_context(const service_connection_t *const NONNULL connection)
-{
-    return connection->context;
-}
-
-//======================================================================================================================
-
-bool
-service_connection_uses_dnssd_connection(const service_connection_t *const NONNULL connection,
-                                         dnssd_txn_t *const NONNULL dnssd_connection)
-{
-    return connection->shared_connection == dnssd_connection;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/ioloop-common.h b/ServiceRegistration/ioloop-common.h
deleted file mode 100644
index 96ba23a..0000000
--- a/ServiceRegistration/ioloop-common.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* ioloop-common.h
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- *
- * This file contains structure definitions and function prototypes shared
- * by service registration code.
- */
-
-#ifndef __IOLOOP_COMMON_H__
-#define __IOLOOP_COMMON_H__
-
-//======================================================================================================================
-// MARK: - Structures
-
-typedef struct service_connection service_connection_t;
-struct service_connection {
-    // The reference counted DNSServiceRef.
-    dnssd_txn_t *NONNULL shared_connection;
-    // The copy if the shared DNSServiceRef.
-    DNSServiceRef NULLABLE service_ref;
-    // Indicates whether the service_ref above is a shared DNSServiceRef or a sub DNSServiceRef of a shared DNSServiceRef.
-    bool shares_service_ref;
-    // If the service_ref above is a shared DNSServiceRef, then record_ref is used to remove the record, since shared one
-    // is a global DNSServiceRef and cannot be used to stop DNSService operation.
-    DNSRecordRef NULLABLE record_ref;
-    // A customized context pointer.
-    void *NULLABLE context;
-};
-
-//======================================================================================================================
-// MARK: - Functions
-
-//======================================================================================================================
-// service_connection_t methods.
-
-/*!
- *  @brief
- *      Creates a special dnssd_txn_t to share its DNSServiceRef with all service_connection_t calls.
- *
- *  @result
- *      returns the created dnssd_txn_t if no error occurs, otherwise, NULL.
- */
-#define dnssd_txn_create_shared() dnssd_txn_create_shared_(__FILE__, __LINE__)
-dnssd_txn_t *NULLABLE
-dnssd_txn_create_shared_(const char *const NONNULL file, const int line);
-
-/*!
- *  @brief
- *      Create a service_connection_t that shares the same DNSServiceRef with the passed in dnssd_txn_t.
- *
- *  @param shared_connection
- *      The dnssd_txn_t created by ioloop_dnssd_txn_add() that shares its DNSServiceRef with service_connection_t created by this function.
- */
-#define service_connection_create(shared_conn) \
-    service_connection_create_((shared_conn), __FILE__, __LINE__)
-service_connection_t *NULLABLE
-service_connection_create_(dnssd_txn_t *const NONNULL shared_txn, const char *const NONNULL file, const int line);
-
-/*!
- *  @brief
- *      Cancel and release the DNSService operation created by this service_connection_t, and the object itself.
- *
- *  @param connection
- *      The service_connection_t created by service_connection_create().
- */
-#define service_connection_cancel_and_release(connection) \
-    service_connection_cancel_and_release_((connection), __FILE__, __LINE__)
-void
-service_connection_cancel_and_release_(service_connection_t *const NONNULL connection,
-                                       const char *const NONNULL file, const int line);
-
-/*!
- *  @brief
- *      Update the old DNSServiceRef with the new one.
- *
- *  @param connection
- *      The service_connection_t whose DNSServiceRef needs to be updated.
- *
- *  @param new_service_ref
- *      The new DNSServiceRef to use.
- */
-void
-service_connection_set_service_ref(service_connection_t *const NONNULL connection,
-                                   const DNSServiceRef NONNULL new_service_ref);
-
-/*!
- *  @brief
- *      Get the DNSServiceRef that is associated with the service_connection_t.
- *
- *  @param connection
- *      The service_connection_t that will be used to get the underline DNSServiceRef.
- *
- *  @result
- *      The underline DNSServiceRef.
- */
-DNSServiceRef NONNULL
-service_connection_get_service_ref(service_connection_t *const NONNULL connection);
-
-/*!
- *  @brief
- *      Set the DNSRecordRef for service_connection_t,  it is only meaningful for the connection that uses the shared DNSServiceRef directly.
- *
- *  @param connection
- *      The service_connection_t created by service_connection_create().
- *
- *  @param record_ref
- *      The DNSRecordRef returned by DNSService operations.
- */
-void
-service_connection_set_record_ref(service_connection_t *const NONNULL connection,
-                                  DNSRecordRef const NONNULL record_ref);
-
-/*!
- *  @brief
- *      Set the context for service_connection_t, which can be retrieved by service_connection_get_context().
- *
- *  @param connection
- *      The service_connection_t created by service_connection_create().
- *
- *  @param context
- *      A pointer to a  customizable data that might be useful for each DNSService operation.
- */
-void
-service_connection_set_context(service_connection_t *const NONNULL connection, void *const NULLABLE context);
-
-/*!
- *  @brief
- *      Set the context for service_connection_t, which is set by service_connection_set_context().
- *
- *  @param connection
- *      The service_connection_t created by service_connection_create().
- *
- *  @result
- *      A pointer to a  customizable data that might be useful for each DNSService operation.
- */
-void *NULLABLE
-service_connection_get_context(const service_connection_t *const NONNULL connection);
-
-/*!
- *  @brief
- *      Check if the service_connection_t shares the same DNSServiceRef with dnssd_txn_t.
- *
- *  @param connection
- *      The service_connection_t created by service_connection_create().
- *
- *  @param dnssd_connection
- *      The dnssd_txn_t created by ioloop_dnssd_txn_add().
- */
-bool
-service_connection_uses_dnssd_connection(const service_connection_t *const NONNULL connection,
-                                         dnssd_txn_t *const NONNULL dnssd_connection);
-
-//======================================================================================================================
-
-#endif // __IOLOOP_COMMON_H__
diff --git a/ServiceRegistration/ioloop.c b/ServiceRegistration/ioloop.c
deleted file mode 100644
index 4ed2697..0000000
--- a/ServiceRegistration/ioloop.c
+++ /dev/null
@@ -1,1800 +0,0 @@
-/* ioloop.c
- *
- * Copyright (c) 2018-2022 Apple, 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
- *
- *     https://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.
- *
- * Simple event dispatcher for DNS.
- */
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <inttypes.h>
-#ifdef USE_KQUEUE
-#include <sys/event.h>
-#endif
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <net/if.h>
-#include <ifaddrs.h>
-#include <spawn.h>
-
-#include "dns_sd.h"
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#ifndef EXCLUDE_TLS
-#include "srp-tls.h"
-#endif
-
-typedef struct async_event {
-    struct async_event *next;
-    async_callback_t callback;
-    void *context;
-} async_event_t;
-
-io_t *ios;
-wakeup_t *wakeups;
-subproc_t *subprocesses;
-async_event_t *async_events;
-int64_t ioloop_now;
-
-#ifdef USE_KQUEUE
-int kq;
-#endif
-static void subproc_finalize(subproc_t *subproc);
-
-int
-getipaddr(addr_t *addr, const char *p)
-{
-    if (inet_pton(AF_INET, p, &addr->sin.sin_addr)) {
-        addr->sa.sa_family = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-        addr->sa.sa_len = sizeof addr->sin;
-#endif
-        return sizeof addr->sin;
-    }  else if (inet_pton(AF_INET6, p, &addr->sin6.sin6_addr)) {
-        addr->sa.sa_family = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-        addr->sa.sa_len = sizeof addr->sin6;
-#endif
-        return sizeof addr->sin6;
-    } else {
-        return 0;
-    }
-}
-
-int64_t
-ioloop_timenow()
-{
-    int64_t now;
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    now = (int64_t)tv.tv_sec * 1000 + (int64_t)tv.tv_usec / 1000;
-    return now;
-}
-
-static void
-message_finalize(message_t *message)
-{
-    free(message);
-}
-
-void
-ioloop_message_retain_(message_t *message, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(message);
-}
-
-void
-ioloop_message_release_(message_t *message, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(message, message_finalize);
-}
-
-void
-ioloop_close(io_t *io)
-{
-    close(io->fd);
-    io->fd = -1;
-}
-
-static void
-add_io(io_t *io)
-{
-    io_t **iop;
-
-    // Add the new reader to the end of the list if it's not on the list.
-    for (iop = &ios; *iop != NULL && *iop != io; iop = &((*iop)->next))
-        ;
-    if (*iop == NULL) {
-        *iop = io;
-        io->next = NULL;
-        RETAIN_HERE(io);
-    }
-}
-
-void
-ioloop_add_reader(io_t *io, io_callback_t callback)
-{
-    add_io(io);
-
-    io->read_callback = callback;
-#ifdef USE_SELECT
-    io->want_read = true;
-#endif
-#ifdef USE_EPOLL
-#endif
-#ifdef USE_KQUEUE
-    struct kevent ev;
-    int rv;
-    EV_SET(&ev, io->fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, io);
-    rv = kevent(kq, &ev, 1, NULL, 0, NULL);
-    if (rv < 0) {
-        ERROR("kevent add: %s", strerror(errno));
-        return;
-    }
-#endif // USE_EPOLL
-}
-
-void
-ioloop_add_writer(io_t *io, io_callback_t callback)
-{
-    add_io(io);
-
-    io->write_callback = callback;
-#ifdef USE_SELECT
-    io->want_write = true;
-#endif
-#ifdef USE_EPOLL
-#endif
-#ifdef USE_KQUEUE
-    struct kevent ev;
-    int rv;
-    EV_SET(&ev, io->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, io);
-    rv = kevent(kq, &ev, 1, NULL, 0, NULL);
-    if (rv < 0) {
-        ERROR("kevent add: %s", strerror(errno));
-        return;
-    }
-#endif // USE_EPOLL
-}
-
-void
-drop_writer(io_t *io)
-{
-#ifdef USE_SELECT
-    io->want_write = false;
-#endif
-#ifdef USE_EPOLL
-#endif
-#ifdef USE_KQUEUE
-    struct kevent ev;
-    int rv;
-    EV_SET(&ev, io->fd, EVFILT_WRITE, EV_ADD | EV_DISABLE, 0, 0, io);
-    rv = kevent(kq, &ev, 1, NULL, 0, NULL);
-    if (rv < 0) {
-        ERROR("kevent add: %s", strerror(errno));
-        return;
-    }
-#endif // USE_EPOLL
-}
-
-static void
-add_remove_wakeup(wakeup_t *wakeup, bool remove)
-{
-    wakeup_t **p_wakeups;
-
-    // Add the new reader to the end of the list if it's not on the list.
-    for (p_wakeups = &wakeups; *p_wakeups != NULL && *p_wakeups != wakeup; p_wakeups = &((*p_wakeups)->next))
-        ;
-    if (remove) {
-        if (*p_wakeups != NULL) {
-            *p_wakeups = wakeup->next;
-            wakeup->next = NULL;
-        }
-    } else {
-        if (*p_wakeups == NULL) {
-            *p_wakeups = wakeup;
-            wakeup->next = NULL;
-        }
-    }
-}
-
-static void
-wakeup_finalize(void *context)
-{
-    wakeup_t *wakeup = context;
-    add_remove_wakeup(wakeup, true);
-    if (wakeup->finalize != NULL) {
-        wakeup->finalize(wakeup->context);
-    }
-    free(wakeup);
-}
-
-void
-ioloop_wakeup_retain_(wakeup_t *wakeup, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(wakeup);
-}
-
-void
-ioloop_wakeup_release_(wakeup_t *wakeup, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(wakeup, wakeup_finalize);
-}
-
-wakeup_t *
-ioloop_wakeup_create_(const char *file, int line)
-{
-    wakeup_t *ret = calloc(1, sizeof(*ret));
-    if (ret) {
-        RETAIN(ret);
-    }
-    return ret;
-}
-
-bool
-ioloop_add_wake_event(wakeup_t *wakeup, void *context, wakeup_callback_t callback, wakeup_callback_t finalize, int milliseconds)
-{
-    if (callback == NULL) {
-        ERROR("ioloop_add_wake_event called with null callback");
-        return false;
-    }
-    if (milliseconds < 0) {
-        ERROR("ioloop_add_wake_event called with negative timeout");
-        return false;
-    }
-    INFO("%p %p %d", wakeup, context, milliseconds);
-    add_remove_wakeup(wakeup, false);
-    wakeup->wakeup_time = ioloop_timenow() + milliseconds;
-    wakeup->finalize = finalize;
-    wakeup->wakeup = callback;
-    wakeup->context = context;
-    return true;
-}
-
-void
-ioloop_cancel_wake_event(wakeup_t *wakeup)
-{
-    if (wakeup->finalize) {
-        wakeup->finalize(wakeup->context);
-        wakeup->finalize = NULL;
-        wakeup->context = NULL;
-    }
-    add_remove_wakeup(wakeup, true);
-    wakeup->wakeup_time = 0;
-}
-
-bool
-ioloop_init(void)
-{
-    signal(SIGPIPE, SIG_IGN); // because why ever?
-#ifdef USE_KQUEUE
-    kq = kqueue();
-    if (kq < 0) {
-        ERROR("kqueue(): %s", strerror(errno));
-        return false;
-    }
-#endif
-    return true;
-}
-
-static void
-ioloop_io_finalize(io_t *io)
-{
-    if (io->io_finalize) {
-        io->io_finalize(io);
-    } else {
-        free(io);
-    }
-}
-
-int
-ioloop_events(int64_t timeout_when)
-{
-    io_t *io, **iop;
-    wakeup_t *wakeup, **p_wakeup;
-    int nev = 0, rv;
-    int64_t now = ioloop_timenow();
-    int64_t next_event;
-    int64_t timeout = 0;
-
-    if (ioloop_now != 0) {
-        INFO("%lld.%03lld seconds have passed on entry to ioloop_events",
-             (long long)((now - ioloop_now) / 1000), (long long)((now - ioloop_now) % 1000));
-    }
-    ioloop_now = now;
-
-#ifdef USE_SELECT
-    int nfds = 0;
-    fd_set reads, writes, errors;
-    struct timeval tv;
-
-    FD_ZERO(&reads);
-    FD_ZERO(&writes);
-    FD_ZERO(&errors);
-#endif
-#ifdef USE_KQUEUE
-    struct timespec ts;
-#endif
-
-start_over:
-    p_wakeup = &wakeups;
-
-    // A timeout of zero means don't time out.
-    if (timeout_when == 0) {
-        next_event = INT64_MAX;
-    } else {
-        next_event = timeout_when;
-    }
-
-    // Cycle through the list of timeouts.
-    while (*p_wakeup) {
-        wakeup = *p_wakeup;
-        if (wakeup->wakeup_time != 0) {
-            if (wakeup->wakeup_time <= ioloop_now) {
-                *p_wakeup = wakeup->next;
-                wakeup->wakeup_time = 0;
-                wakeup->wakeup(wakeup->context);
-                ++nev;
-
-                // In case either wakeup has been freed, or a new wakeup has been added, we need to start
-                // at the beginning again. This wakeup will never still be on the list unless it's been
-                // re-added with a later time, so this should always have the effect that every wakeup that's
-                // ready gets its callback called, and when all wakeups that are ready have been called,
-                // there are no wakeups that are ready remaining on the list, so our loop exits.
-                goto start_over;
-            } else {
-                p_wakeup = &wakeup->next;
-            }
-            if (wakeup->wakeup_time < next_event && wakeup->wakeup_time != 0) {
-                next_event = wakeup->wakeup_time;
-            }
-        } else {
-            *p_wakeup = wakeup->next;
-        }
-    }
-
-    // Deliver and consume any asynchronous events
-    while (async_events != NULL) {
-        async_event_t *event = async_events;
-        async_events = event->next;
-        event->callback(event->context);
-        free(event);
-    }
-
-    iop = &ios;
-    while (*iop) {
-        io = *iop;
-        // If the I/O is dead, finalize or free it.
-        if (io->fd == -1) {
-            *iop = io->next;
-            RELEASE_HERE(io, ioloop_io_finalize);
-            continue;
-        }
-
-        // One-time callback, used to call the listener ready callback after ioloop_listener_create() has
-        // returned;
-        if (io->ready != NULL) {
-            io->ready(io, io->context);
-            io->ready = NULL;
-        }
-
-        iop = &io->next;
-    }
-
-    INFO("now: %" PRIu64 " next_event %" PRIu64, ioloop_now, next_event);
-
-    // If we were given a timeout in the future, or told to wait indefinitely, wait until the next event.
-    if (timeout_when == 0 || timeout_when > ioloop_now) {
-        timeout = next_event - ioloop_now;
-        // Don't choose a time so far in the future that it might overflow some math in the kernel.
-        if (timeout > IOLOOP_DAY * 100) {
-            timeout = IOLOOP_DAY * 100;
-        }
-#ifdef USE_SELECT
-        tv.tv_sec = timeout / 1000;
-        tv.tv_usec = (timeout % 1000) * 1000;
-#endif
-#ifdef USE_KQUEUE
-        ts.tv_sec = timeout / 1000;
-        ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
-#endif
-    }
-
-    while (subprocesses != NULL) {
-        int status;
-        pid_t pid;
-        pid = waitpid(-1, &status, WNOHANG);
-        if (pid <= 0) {
-            break;
-        }
-        subproc_t **sp, *subproc;
-        for (sp = &subprocesses; (*sp) != NULL; sp = &(*sp)->next) {
-            subproc = *sp;
-            if (subproc->pid == pid) {
-                if (!WIFSTOPPED(status)) {
-                    *sp = subproc->next;
-                }
-                subproc->callback(subproc->context, status, NULL);
-                if (!WIFSTOPPED(status)) {
-                    subproc->finished = true;
-                    RELEASE_HERE(subproc, subproc_finalize);
-                    break;
-                }
-            }
-        }
-    }
-
-#ifdef USE_SELECT
-    for (io = ios; io; io = io->next) {
-        if (io->fd != -1 && (io->want_read || io->want_write)) {
-            if (io->fd >= nfds) {
-                nfds = io->fd + 1;
-            }
-            if (io->want_read) {
-                FD_SET(io->fd, &reads);
-            }
-            if (io->want_write) {
-                FD_SET(io->fd, &writes);
-            }
-        }
-    }
-#endif
-
-#ifdef USE_SELECT
-    INFO("waiting %lld %lld seconds", (long long)tv.tv_sec, (long long)tv.tv_usec);
-    rv = select(nfds, &reads, &writes, &errors, &tv);
-    if (rv < 0) {
-        ERROR("select: %s", strerror(errno));
-        exit(1);
-    }
-    now = ioloop_timenow();
-    INFO("%lld.%03lld seconds passed waiting, got %d events", (long long)((now - ioloop_now) / 1000),
-         (long long)((now - ioloop_now) % 1000), rv);
-    ioloop_now = now;
-    for (io = ios; io; io = io->next) {
-        if (io->fd != -1) {
-            if (FD_ISSET(io->fd, &reads)) {
-                if (io->read_callback != NULL) {
-                    io->read_callback(io, io->context);
-                }
-            } else if (FD_ISSET(io->fd, &writes)) {
-                if (io->write_callback != NULL) {
-                    io->write_callback(io, io->context);
-                }
-            }
-        }
-    }
-    nev += rv;
-#endif // USE_SELECT
-#ifdef USE_KQUEUE
-#define KEV_MAX 20
-    struct kevent evs[KEV_MAX];
-    int i;
-
-    INFO("waiting %lld/%lld seconds", (long long)ts.tv_sec, (long long)ts.tv_nsec);
-    do {
-        rv = kevent(kq, NULL, 0, evs, KEV_MAX, &ts);
-        now = ioloop_timenow();
-        INFO("%lld.%03lld seconds passed waiting, got %d events", (long long)((now - ioloop_now) / 1000),
-             (long long)((now - ioloop_now) % 1000), rv);
-        ioloop_now = now;
-        ts.tv_sec = 0;
-        ts.tv_nsec = 0;
-        if (rv < 0) {
-            if (errno == EINTR) {
-                rv = 0;
-            } else {
-                ERROR("kevent poll: %s", strerror(errno));
-                exit(1);
-            }
-        }
-        for (i = 0; i < rv; i++) {
-            io = evs[i].udata;
-            if (evs[i].filter == EVFILT_WRITE) {
-                io->write_callback(io, io->context);
-            } else if (evs[i].filter == EVFILT_READ) {
-                io->read_callback(io, io->context);
-            }
-        }
-        nev += rv;
-    } while (rv == KEV_MAX);
-#endif
-    return nev;
-}
-
-int
-ioloop(void)
-{
-    int nev;
-    do {
-        nev = ioloop_events(0);
-        INFO("%d", nev);
-    } while (nev >= 0);
-    ERROR("ioloop returned %d.", nev);
-    return -1;
-}
-
-static void
-udp_read_callback(io_t *io, void *context)
-{
-    comm_t *connection = (comm_t *)io;
-    addr_t src;
-    int rv;
-    struct msghdr msg;
-    struct iovec bufp;
-    uint8_t msgbuf[DNS_MAX_UDP_PAYLOAD];
-    char cmsgbuf[128];
-    struct cmsghdr *cmh;
-    message_t *message;
-    (void)context;
-
-    bufp.iov_base = msgbuf;
-    bufp.iov_len = DNS_MAX_UDP_PAYLOAD;
-    msg.msg_iov = &bufp;
-    msg.msg_iovlen = 1;
-    msg.msg_name = &src;
-    msg.msg_namelen = sizeof src;
-    msg.msg_control = cmsgbuf;
-    msg.msg_controllen = sizeof cmsgbuf;
-
-    rv = recvmsg(connection->io.fd, &msg, 0);
-    if (rv < 0) {
-        ERROR("udp_read_callback: %s", strerror(errno));
-        return;
-    }
-    message = ioloop_message_create(rv);
-    if (!message) {
-        ERROR("udp_read_callback: out of memory");
-        return;
-    }
-    memcpy(&message->src, &src, sizeof src);
-    message->length = rv;
-    memcpy(&message->wire, msgbuf, rv);
-
-    // For UDP, we use the interface index as part of the validation strategy, so go get
-    // the interface index.
-    for (cmh = CMSG_FIRSTHDR(&msg); cmh; cmh = CMSG_NXTHDR(&msg, cmh)) {
-        if (cmh->cmsg_level == IPPROTO_IPV6 && cmh->cmsg_type == IPV6_PKTINFO) {
-            struct in6_pktinfo pktinfo;
-
-            memcpy(&pktinfo, CMSG_DATA(cmh), sizeof pktinfo);
-            message->ifindex = pktinfo.ipi6_ifindex;
-
-            /* Get the destination address, for use when replying. */
-            message->local.sin6.sin6_family = AF_INET6;
-            message->local.sin6.sin6_port = 0;
-            message->local.sin6.sin6_addr = pktinfo.ipi6_addr;
-#ifndef NOT_HAVE_SA_LEN
-            message->local.sin6.sin6_len = sizeof message->local;
-#endif
-        } else if (cmh->cmsg_level == IPPROTO_IP && cmh->cmsg_type == IP_PKTINFO) {
-            struct in_pktinfo pktinfo;
-
-            memcpy(&pktinfo, CMSG_DATA(cmh), sizeof pktinfo);
-            message->ifindex = pktinfo.ipi_ifindex;
-
-            message->local.sin.sin_family = AF_INET;
-            message->local.sin.sin_port = 0;
-            message->local.sin.sin_addr = pktinfo.ipi_addr;
-#ifndef NOT_HAVE_SA_LEN
-            message->local.sin.sin_len = sizeof message->local;
-#endif
-        }
-    }
-    connection->datagram_callback(connection, message, connection->context);
-    RELEASE_HERE(message, message_finalize);
-}
-
-static void
-tcp_read_callback(io_t *io, void *context)
-{
-    uint8_t *read_ptr;
-    size_t read_len;
-    comm_t *connection = (comm_t *)io;
-    ssize_t rv;
-    (void)context;
-    if (connection->message_length_len < 2) {
-        read_ptr = connection->message_length_bytes;
-        read_len = 2 - connection->message_length_len;
-    } else {
-        read_ptr = &connection->buf[connection->message_cur];
-        read_len = connection->message_length - connection->message_cur;
-    }
-
-    if (connection->tls_context != NULL) {
-#ifndef EXCLUDE_TLS
-        rv = srp_tls_read(connection, read_ptr, read_len);
-        if (rv == 0) {
-            // This isn't an EOF: that's returned as an error status.   This just means that
-            // whatever data was available to be read was consumed by the TLS protocol without
-            // producing anything to read at the app layer.
-            return;
-        } else if (rv < 0) {
-            ERROR("TLS return that we can't handle.");
-            close(connection->io.fd);
-            connection->io.fd = -1;
-            srp_tls_context_free(connection);
-            return;
-        }
-#else
-        ERROR("tls context with TLS excluded in tcp_read_callback.");
-        return;
-#endif
-    } else {
-        rv = read(connection->io.fd, read_ptr, read_len);
-
-        if (rv < 0) {
-            ERROR("tcp_read_callback: %s", strerror(errno));
-            close(connection->io.fd);
-            connection->io.fd = -1;
-            // connection->io.finalize() will be called from the io loop.
-            return;
-        }
-
-        // If we read zero here, the remote endpoint has closed or shutdown the connection.  Either case is
-        // effectively the same--if we are sensitive to read events, that means that we are done processing
-        // the previous message.
-        if (rv == 0) {
-            ERROR("tcp_read_callback: remote end (%s) closed connection on %d", connection->name, connection->io.fd);
-            close(connection->io.fd);
-            connection->io.fd = -1;
-            if (connection->disconnected) {
-                connection->disconnected(connection, connection->context, 0);
-            }
-            // connection->io.finalize() will be called from the io loop.
-            return;
-        }
-    }
-    if (connection->message_length_len < 2) {
-        connection->message_length_len += rv;
-        if (connection->message_length_len == 2) {
-            connection->message_length = (((uint16_t)connection->message_length_bytes[0] << 8) |
-                                          ((uint16_t)connection->message_length_bytes[1]));
-
-            if (connection->message == NULL) {
-                connection->message = ioloop_message_create(connection->message_length);
-                if (!connection->message) {
-                    ERROR("udp_read_callback: out of memory");
-                    return;
-                }
-                connection->buf = (uint8_t *)&connection->message->wire;
-                connection->message->length = connection->message_length;
-                memset(&connection->message->src, 0, sizeof connection->message->src);
-            }
-        }
-    } else {
-        connection->message_cur += rv;
-        if (connection->message_cur == connection->message_length) {
-            connection->message_cur = 0;
-            connection->datagram_callback(connection, connection->message, connection->context);
-            // The callback may retain the message; we need to make way for the next one.
-            RELEASE_HERE(connection->message, message_finalize);
-            connection->message = NULL;
-            connection->message_length = connection->message_length_len = 0;
-        }
-    }
-}
-
-
-static bool
-tcp_send_response(comm_t *comm, message_t *responding_to, struct iovec *iov, int iov_len, bool send_length)
-{
-    struct msghdr mh;
-    struct iovec iovec[4];
-    char lenbuf[2];
-    ssize_t status;
-    size_t payload_length = 0;
-    int i;
-
-    // We don't anticipate ever needing more than four hunks, but if we get more, handle then?
-    if (iov_len > 3) {
-        ERROR("tcp_send_response: too many io buffers");
-        close(comm->io.fd);
-        comm->io.fd = -1;
-        return false;
-    }
-
-    i = 0;
-    if (send_length) {
-        i++;
-    }
-    for (i = 0; i < iov_len; i++) {
-        iovec[i + 1] = iov[i];
-        payload_length += iov[i].iov_len;
-    }
-    if (send_length) {
-        iovec[0].iov_base = &lenbuf[0];
-        iovec[0].iov_len = 2;
-
-        lenbuf[0] = payload_length / 256;
-        lenbuf[1] = payload_length & 0xff;
-
-        payload_length += 2;
-    }
-
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-    if (comm->tls_context != NULL) {
-#ifndef EXCLUDE_TLS
-        status = srp_tls_write(comm, iovec, iov_len + 1);
-#else
-        ERROR("TLS context not null with TLS excluded.");
-        status = -1;
-        errno = ENOTSUP;
-        return false;
-#endif
-    } else {
-        memset(&mh, 0, sizeof mh);
-        mh.msg_iov = &iovec[0];
-        mh.msg_iovlen = iov_len + 1;
-        mh.msg_name = 0;
-
-        status = sendmsg(comm->io.fd, &mh, MSG_NOSIGNAL);
-    }
-    if (status < 0 || status != payload_length) {
-        if (status < 0) {
-            ERROR("tcp_send_response: write failed: %s", strerror(errno));
-        } else {
-            ERROR("tcp_send_response: short write (%zd out of %zu bytes)", status, payload_length);
-        }
-        close(comm->io.fd);
-        comm->io.fd = -1;
-        return false;
-    }
-    return true;
-}
-
-static bool
-udp_send_message(comm_t *comm, addr_t *source, addr_t *dest, int ifindex, struct iovec *iov, int iov_len)
-{
-    struct msghdr mh;
-    uint8_t cmsg_buf[128];
-    struct cmsghdr *cmsg;
-    int status;
-
-    memset(&mh, 0, sizeof mh);
-    mh.msg_iov = iov;
-    mh.msg_iovlen = iov_len;
-    mh.msg_name = dest;
-    mh.msg_control = cmsg_buf;
-    if (source == NULL && ifindex == 0) {
-        mh.msg_controllen = 0;
-    } else {
-        mh.msg_controllen = sizeof cmsg_buf;
-        cmsg = CMSG_FIRSTHDR(&mh);
-
-        if (source->sa.sa_family == AF_INET) {
-            struct in_pktinfo *inp;
-            mh.msg_namelen = sizeof (struct sockaddr_in);
-            mh.msg_controllen = CMSG_SPACE(sizeof *inp);
-            cmsg->cmsg_level = IPPROTO_IP;
-            cmsg->cmsg_type = IP_PKTINFO;
-            cmsg->cmsg_len = CMSG_LEN(sizeof *inp);
-            inp = (struct in_pktinfo *)CMSG_DATA(cmsg);
-            memset(inp, 0, sizeof *inp);
-            inp->ipi_ifindex = ifindex;
-            if (source) {
-                inp->ipi_spec_dst = source->sin.sin_addr;
-                inp->ipi_addr = source->sin.sin_addr;
-            }
-        } else if (source->sa.sa_family == AF_INET6) {
-            struct in6_pktinfo *inp;
-            mh.msg_namelen = sizeof (struct sockaddr_in6);
-            mh.msg_controllen = CMSG_SPACE(sizeof *inp);
-            cmsg->cmsg_level = IPPROTO_IPV6;
-            cmsg->cmsg_type = IPV6_PKTINFO;
-            cmsg->cmsg_len = CMSG_LEN(sizeof *inp);
-            inp = (struct in6_pktinfo *)CMSG_DATA(cmsg);
-            memset(inp, 0, sizeof *inp);
-            inp->ipi6_ifindex = ifindex;
-            if (source) {
-                inp->ipi6_addr = source->sin6.sin6_addr;
-            }
-        } else {
-            ERROR("udp_send_response: unknown family %d", source->sa.sa_family);
-            abort();
-        }
-    }
-    status = sendmsg(comm->io.fd, &mh, 0);
-    if (status < 0) {
-        ERROR("udp_send_message: %s", strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-static bool
-udp_send_response(comm_t *comm, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    return udp_send_message(comm, &responding_to->local, &responding_to->src, responding_to->ifindex, iov, iov_len);
-}
-
-bool
-ioloop_send_multicast(comm_t *comm, int ifindex, struct iovec *iov, int iov_len)
-{
-    return udp_send_message(comm, NULL, &comm->multicast, ifindex, iov, iov_len);
-}
-
-static bool
-udp_send_connected_response(comm_t *comm, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    int status = writev(comm->io.fd, iov, iov_len);
-    (void)responding_to;
-    if (status < 0) {
-        ERROR("udp_send_connected: %s", strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-bool
-ioloop_send_message(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    if (connection->tcp_stream) {
-        return tcp_send_response(connection, responding_to, iov, iov_len, true);
-    } else {
-        if (connection->is_connected) {
-            return udp_send_connected_response(connection, responding_to, iov, iov_len);
-        } else if (connection->is_multicast) {
-            ERROR("ioloop_send_message: multicast send must use ioloop_send_multicast!");
-            return false;
-        } else if (responding_to == NULL) {
-            ERROR("ioloop_send_message: not connected and no responding_to message.");
-            return false;
-        } else {
-            return udp_send_response(connection, responding_to, iov, iov_len);
-        }
-    }
-}
-
-bool
-ioloop_send_final_message(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    bool ret = ioloop_send_message(connection, responding_to, iov, iov_len);
-    if (ret) {
-        shutdown(connection->io.fd, SHUT_WR);
-    }
-    return ret;
-}
-
-bool
-ioloop_send_data(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    if (connection->tcp_stream) {
-        return tcp_send_response(connection, responding_to, iov, iov_len, false);
-    }
-    return ioloop_send_message(connection, responding_to, iov, iov_len);
-}
-
-bool
-ioloop_send_final_data(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    if (connection->tcp_stream) {
-        bool ret = tcp_send_response(connection, responding_to, iov, iov_len, false);
-        if (ret) {
-            shutdown(connection->io.fd, SHUT_WR);
-        }
-        return ret;
-    }
-    return ioloop_send_message(connection, responding_to, iov, iov_len);
-}
-
-static void
-io_finalize(io_t *io)
-{
-    io_t **iop;
-    for (iop = &ios; *iop; iop = &(*iop)->next) {
-        if (*iop == io) {
-            *iop = io->next;
-            break;
-        }
-    }
-    free(io);
-}
-
-// When a communication is closed, scan the io event list to see if any other ios are referencing this one.
-static void
-comm_finalize(io_t *io)
-{
-    comm_t *comm = (comm_t *)io;
-    ERROR("comm_finalize");
-    if (comm->name != NULL) {
-        free(comm->name);
-    }
-    if (comm->finalize != NULL) {
-        comm->finalize(comm->context);
-    }
-    if (comm->message != NULL) {
-        RELEASE_HERE(comm->message, message_finalize);
-    }
-    io_finalize(&comm->io);
-}
-
-void
-ioloop_comm_retain_(comm_t *comm, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(&comm->io);
-}
-
-void
-ioloop_comm_release_(comm_t *comm, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(&comm->io, comm_finalize);
-}
-
-void
-ioloop_comm_cancel(comm_t *comm)
-{
-    close(comm->io.fd);
-    comm->io.fd = -1;
-}
-
-void
-ioloop_comm_context_set(comm_t *comm, void *context, finalize_callback_t callback)
-{
-    if (comm->context != NULL && comm->finalize != NULL) {
-        comm->finalize(comm->context);
-    }
-    comm->finalize = callback;
-    comm->context = context;
-}
-
-void
-ioloop_comm_connect_callback_set(comm_t *comm, connect_callback_t callback)
-{
-    comm->connected = callback;
-}
-
-void
-ioloop_comm_disconnect_callback_set(comm_t *comm, disconnect_callback_t callback)
-{
-    comm->disconnected = callback;
-}
-
-void
-ioloop_listener_retain_(comm_t *listener, const char *file, int line)
-{
-    RETAIN(&listener->io);
-}
-
-void
-ioloop_listener_release_(comm_t *listener, const char *file, int line)
-{
-    RELEASE(&listener->io, comm_finalize);
-}
-
-void
-ioloop_listener_cancel(comm_t *connection)
-{
-    if (connection->io.fd != -1) {
-        close(connection->io.fd);
-        connection->io.fd = -1;
-    }
-}
-
-static void
-listen_callback(io_t *io, void *context)
-{
-    comm_t *listener = (comm_t *)io;
-    int rv;
-    addr_t addr;
-    socklen_t addr_len = sizeof addr;
-    comm_t *comm;
-    char addrbuf[INET6_ADDRSTRLEN + 7];
-    int addrlen;
-    (void)context;
-
-    rv = accept(listener->io.fd, &addr.sa, &addr_len);
-    if (rv < 0) {
-        ERROR("accept: %s", strerror(errno));
-        close(listener->io.fd);
-        listener->io.fd = -1;
-        return;
-    }
-    inet_ntop(addr.sa.sa_family, (addr.sa.sa_family == AF_INET
-                                  ? (void *)&addr.sin.sin_addr
-                                  : (void *)&addr.sin6.sin6_addr), addrbuf, sizeof addrbuf);
-    addrlen = strlen(addrbuf);
-    snprintf(&addrbuf[addrlen], (sizeof addrbuf) - addrlen, "%%%d",
-             ntohs((addr.sa.sa_family == AF_INET ? addr.sin.sin_port : addr.sin6.sin6_port)));
-    comm = calloc(1, sizeof *comm);
-    comm->name = strdup(addrbuf);
-    comm->io.fd = rv;
-    comm->address = addr;
-    comm->datagram_callback = listener->datagram_callback;
-    comm->tcp_stream = true;
-    comm->context = listener->context;
-
-    if (listener->tls_context == (tls_context_t *)-1) {
-#ifndef EXCLUDE_TLS
-        if (!srp_tls_listen_callback(comm)) {
-            ERROR("TLS  setup failed.");
-            close(comm->io.fd);
-            free(comm);
-            return;
-        }
-#else
-        ERROR("TLS context not null in listen_callback when TLS excluded.");
-        return;
-#endif
-    }
-    if (listener->connected) {
-        listener->connected(comm, listener->context);
-    }
-    ioloop_add_reader(&comm->io, tcp_read_callback);
-
-#ifdef SO_NOSIGPIPE
-    int one = 1;
-    rv = setsockopt(comm->io.fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof one);
-    if (rv < 0) {
-        ERROR("SO_NOSIGPIPE failed: %s", strerror(errno));
-    }
-#endif
-}
-
-static void
-listener_ready_callback(io_t *io, void *context)
-{
-    comm_t *listener = (comm_t *)io;
-    if (listener->ready) {
-        listener->ready(listener->context, listener->listen_port);
-    }
-}
-
-comm_t *
-ioloop_listener_create(bool stream, bool tls, uint16_t *avoid_ports, int num_avoid_ports,
-                       const addr_t *ip_address, const char *multicast, const char *name,
-                       datagram_callback_t datagram_callback, connect_callback_t connected, cancel_callback_t cancel,
-                       ready_callback_t ready, finalize_callback_t finalize, tls_config_callback_t tls_config,
-                       void *context)
-{
-    comm_t *listener;
-    socklen_t sl;
-    int rv;
-    int false_flag = 0;
-    int true_flag = 1;
-    uint16_t port;
-    int family = (ip_address != NULL) ? ip_address->sa.sa_family : AF_UNSPEC;
-    int real_family = family == AF_UNSPEC ? AF_INET6 : family;
-    addr_t sockname;
-
-    listener = calloc(1, sizeof *listener);
-    if (listener == NULL) {
-        return NULL;
-    }
-    RETAIN_HERE(&listener->io);
-    listener->name = strdup(name);
-    if (!listener->name) {
-        RELEASE_HERE(&listener->io, comm_finalize);
-        return NULL;
-    }
-    listener->io.fd = socket(real_family, stream ? SOCK_STREAM : SOCK_DGRAM, stream ? IPPROTO_TCP : IPPROTO_UDP);
-    if (listener->io.fd < 0) {
-        ERROR("Can't get socket: %s", strerror(errno));
-        goto out;
-    }
-    rv = setsockopt(listener->io.fd, SOL_SOCKET, SO_REUSEADDR, &true_flag, sizeof true_flag);
-    if (rv < 0) {
-        ERROR("SO_REUSEADDR failed: %s", strerror(errno));
-        goto out;
-    }
-
-    rv = setsockopt(listener->io.fd, SOL_SOCKET, SO_REUSEPORT, &true_flag, sizeof true_flag);
-    if (rv < 0) {
-        ERROR("SO_REUSEPORT failed: %s", strerror(errno));
-        goto out;
-    }
-
-    if (ip_address == NULL || family == AF_LOCAL) {
-        port = 0;
-    } else {
-        port = (family == AF_INET) ? ip_address->sin.sin_port : ip_address->sin6.sin6_port;
-        listener->address = *ip_address;
-    }
-    listener->address.sa.sa_family = real_family;
-
-    if (multicast != 0) {
-        if (stream) {
-            ERROR("Unable to do non-datagram multicast.");
-            goto out;
-        }
-        if (family == AF_LOCAL) {
-            ERROR("Multicast not supported on local sockets.");
-            goto out;
-        }
-        sl = getipaddr(&listener->multicast, multicast);
-        if (sl == 0) {
-            goto out;
-        }
-        if (listener->multicast.sa.sa_family != family) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-            ERROR("multicast address %s from different family than listen address " PRI_SEGMENTED_IPv6_ADDR_SRP ".",
-                  multicast, SEGMENTED_IPv6_ADDR_PARAM_SRP(listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf));
-            goto out;
-        }
-        listener->is_multicast = true;
-
-        if (family == AF_INET) {
-            struct ip_mreq im;
-            int ttl = 255;
-            im.imr_multiaddr = listener->multicast.sin.sin_addr;
-            im.imr_interface.s_addr = 0;
-            rv = setsockopt(listener->io.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &im, sizeof im);
-            if (rv < 0) {
-                ERROR("Unable to join %s multicast group: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof ttl);
-            if (rv < 0) {
-                ERROR("Unable to set IP multicast TTL to 255 for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IP, IP_TTL, &ttl, sizeof ttl);
-            if (rv < 0) {
-                ERROR("Unable to set IP TTL to 255 for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IP, IP_MULTICAST_LOOP, &false_flag, sizeof false_flag);
-            if (rv < 0) {
-                ERROR("Unable to set IP Multcast loopback to false for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-        } else {
-            struct ipv6_mreq im;
-            int hops = 255;
-            im.ipv6mr_multiaddr = listener->multicast.sin6.sin6_addr;
-            im.ipv6mr_interface = 0;
-            rv = setsockopt(listener->io.fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &im, sizeof im);
-            if (rv < 0) {
-                ERROR("Unable to join %s multicast group: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof hops);
-            if (rv < 0) {
-                ERROR("Unable to set IPv6 multicast hops to 255 for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof hops);
-            if (rv < 0) {
-                ERROR("Unable to set IPv6 hops to 255 for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-            rv = setsockopt(listener->io.fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &false_flag, sizeof false_flag);
-            if (rv < 0) {
-                ERROR("Unable to set IPv6 Multcast loopback to false for %s: %s", multicast, strerror(errno));
-                goto out;
-            }
-        }
-    }
-
-    if (family == AF_INET6) {
-        // Don't use a dual-stack socket.
-        rv = setsockopt(listener->io.fd, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof true_flag);
-        if (rv < 0) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-            ERROR("Unable to set IPv6-only flag on %s socket for " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                  tls ? "TLS" : (stream ? "TCP" : "UDP"),
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf));
-            goto out;
-        }
-    }
-
-#ifndef NOT_HAVE_SA_LEN
-    sl = listener->address.sa.sa_len;
-#else
-    sl = real_family == AF_INET ? sizeof(listener->address.sin) : sizeof(listener->address.sin6);
-#endif
-    if (bind(listener->io.fd, &listener->address.sa, sl) < 0) {
-        if (family == AF_INET) {
-            IPv4_ADDR_GEN_SRP(&listener->address.sin.sin_addr.s_addr, ipv4_addr_buf);
-            ERROR("Can't bind to " PRI_IPv4_ADDR_SRP "#%d/%s: %s",
-                  IPv4_ADDR_PARAM_SRP(&listener->address.sin.sin_addr.s_addr, ipv4_addr_buf), ntohs(port),
-                  tls ? "tlsv4" : "tcpv4", strerror(errno));
-        } else {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(&listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-            ERROR("Can't bind to " PRI_SEGMENTED_IPv6_ADDR_SRP "#%d/%s: %s",
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf), ntohs(port),
-                  tls ? "tlsv6" : "tcpv6", strerror(errno));
-        }
-    out:
-        close(listener->io.fd);
-        listener->io.fd = -1;
-        RELEASE_HERE(&listener->io, comm_finalize);
-        return NULL;
-    }
-
-    // We may have bound to an unspecified port, so fetch the port we got.
-    if (port == 0 && family != AF_LOCAL) {
-        if (getsockname(listener->io.fd, (struct sockaddr *)&sockname, &sl) < 0) {
-            ERROR("ioloop_listener_create: getsockname: %s", strerror(errno));
-            goto out;
-        }
-        port = ntohs(real_family == AF_INET6 ? sockname.sin6.sin6_port : sockname.sin.sin_port);
-    }
-    listener->listen_port = port;
-
-    if (tls) {
-#ifndef EXCLUDE_TLS
-        if (!stream) {
-            ERROR("Asked to do TLS over UDP, which we don't do yet.");
-            goto out;
-        }
-        listener->tls_context = (tls_context_t *)-1;
-#else
-        ERROR("TLS requested when TLS is excluded.");
-        goto out;
-#endif
-    }
-
-    if (stream) {
-        if (listen(listener->io.fd, 5 /* xxx */) < 0) {
-            if (family == AF_INET) {
-                IPv4_ADDR_GEN_SRP(&listener->address.sin.sin_addr.s_addr, ipv4_addr_buf);
-                ERROR("Can't listen on " PRI_IPv4_ADDR_SRP "#%d/%s: %s",
-                      IPv4_ADDR_PARAM_SRP(&listener->address.sin.sin_addr.s_addr, ipv4_addr_buf), ntohs(port),
-                      tls ? "tlsv4" : "tcpv4", strerror(errno));
-            } else {
-                SEGMENTED_IPv6_ADDR_GEN_SRP(&listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-                ERROR("Can't listen on " PRI_SEGMENTED_IPv6_ADDR_SRP "#%d/%s: %s",
-                      SEGMENTED_IPv6_ADDR_PARAM_SRP(&listener->address.sin6.sin6_addr.s6_addr, ipv6_addr_buf), ntohs(port),
-                      tls ? "tlsv6" : "tcpv6", strerror(errno));
-            }
-            goto out;
-        }
-        listener->finalize = finalize;
-        ioloop_add_reader(&listener->io, listen_callback);
-        listener->tcp_stream = true;
-    } else {
-        rv = setsockopt(listener->io.fd, family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
-                        family == AF_INET ? IP_PKTINFO : IPV6_RECVPKTINFO, &true_flag, sizeof true_flag);
-        if (rv < 0) {
-            ERROR("Can't set %s: %s.", family == AF_INET ? "IP_PKTINFO" : "IPV6_RECVPKTINFO",
-                    strerror(errno));
-            goto out;
-        }
-        ioloop_add_reader(&listener->io, udp_read_callback);
-    }
-    listener->datagram_callback = datagram_callback;
-    listener->connected = connected;
-    listener->context = context;
-    listener->ready = ready;
-    listener->io.ready = listener_ready_callback;
-    listener->is_listener = true;
-    return listener;
-}
-
-// This is the callback for when we complete the handshake when connecting to a remote listener.
-static void
-connect_callback(io_t *io, void *context)
-{
-    int result;
-    socklen_t len = sizeof result;
-    comm_t *connection = (comm_t *)io;
-    bool getsockopt_failed = false;
-    (void)context;
-
-    // If connect failed, indicate that it failed.
-    if (getsockopt(io->fd, SOL_SOCKET, SO_ERROR, &result, &len) < 0) {
-        result = errno;
-        getsockopt_failed = true;
-    }
-    if (result != 0) {
-        ERROR("connect_callback: %ssocket %d: Error %d (%s)", getsockopt_failed ? "getsockopt " : "",
-              io->fd, result, strerror(result));
-        connection->disconnected(connection, connection->context, result);
-        ioloop_comm_cancel(connection);
-        return;
-    }
-
-    // If this is a TLS connection, set up TLS.
-    if (connection->tls_context == (tls_context_t *)-1) {
-#ifndef EXCLUDE_TLS
-        if (!srp_tls_connect_callback(connection)) {
-            connection->disconnected(connection, connection->context, 0);
-            ioloop_comm_cancel(connection);
-            return;
-        }
-#else
-        ERROR("connect_callback: tls_context triggered with TLS excluded.");
-        connection->disconnected(connection, connection->context, 0);
-        ioloop_comm_cancel(connection);
-        return;
-#endif
-    }
-
-    // We don't want to say we're connected until the TLS handshake is complete.
-    if (!connection->tls_handshake_incomplete) {
-        connection->connected(connection, connection->context);
-    }
-    drop_writer(&connection->io);
-    ioloop_add_reader(&connection->io, tcp_read_callback);
-}
-
-// Currently we don't do DNS lookups, despite the host identifier being an IP address.
-comm_t *NULLABLE
-ioloop_connection_create(addr_t *remote_address, bool tls, bool stream, bool stable, bool opportunistic,
-                         datagram_callback_t datagram_callback, connect_callback_t connected,
-                         disconnect_callback_t disconnected, finalize_callback_t finalize,
-                         void * context)
-{
-    comm_t *connection;
-    socklen_t sl;
-    char buf[INET6_ADDRSTRLEN + 7];
-    char *s;
-
-    if (!stream && (connected != NULL || disconnected != NULL)) {
-        ERROR("connected and disconnected callbacks not valid for datagram connections");
-        return NULL;
-    }
-    if (stream && (connected == NULL || disconnected == NULL)) {
-        ERROR("connected and disconnected callbacks are required for stream connections");
-        return NULL;
-    }
-    connection = calloc(1, sizeof *connection);
-    if (connection == NULL) {
-        ERROR("No memory for connection structure.");
-        return NULL;
-    }
-    RETAIN_HERE(&connection->io);
-    if (inet_ntop(remote_address->sa.sa_family, (remote_address->sa.sa_family == AF_INET
-                                                 ? (void *)&remote_address->sin.sin_addr
-                                                 : (void *)&remote_address->sin6.sin6_addr), buf,
-                  INET6_ADDRSTRLEN) == NULL) {
-        ERROR("inet_ntop failed to convert remote address: %s", strerror(errno));
-        RELEASE_HERE(&connection->io, comm_finalize);
-        return NULL;
-    }
-    s = buf + strlen(buf);
-    sprintf(s, "%%%hu", ntohs(remote_address->sa.sa_family == AF_INET
-                              ? remote_address->sin.sin_port
-                              : remote_address->sin6.sin6_port));
-    connection->name = strdup(buf);
-    if (!connection->name) {
-        RELEASE_HERE(&connection->io, comm_finalize);
-        return NULL;
-    }
-    connection->io.fd = socket(remote_address->sa.sa_family,
-                                 stream ? SOCK_STREAM : SOCK_DGRAM, stream ? IPPROTO_TCP : IPPROTO_UDP);
-    if (connection->io.fd < 0) {
-        ERROR("Can't get socket: %s", strerror(errno));
-        RELEASE_HERE(&connection->io, comm_finalize);
-        return NULL;
-    }
-    connection->address = *remote_address;
-    if (fcntl(connection->io.fd, F_SETFL, O_NONBLOCK) < 0) {
-        ERROR("connect_to_host: %s: Can't set O_NONBLOCK: %s", connection->name, strerror(errno));
-        RELEASE_HERE(&connection->io, comm_finalize);
-        return NULL;
-    }
-    // If a stable address has been requested, request a public address in source address selection.
-    if (stable && remote_address->sa.sa_family == AF_INET6) {
-// Linux doesn't currently follow RFC5014. These values are defined in linux/in6.h, but this can't be
-// safely included because it's incompatible with netinet/in.h. So until this is fixed, these values
-// are just copied out of the header; when it is fixed, the #if condition will evaluate to false.
-#if defined(LINUX)
-#  if !defined(IPV6_PREFER_SRC_PUBLIC)
-#    define IPV6_PREFER_SRC_TMP            0x0001
-#    define IPV6_PREFER_SRC_PUBLIC         0x0002
-#    define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100
-#  endif
-        int value = IPV6_PREFER_SRC_PUBLIC;
-        if (setsockopt(connection->io.fd, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &value, sizeof(value)) < 0) {
-            ERROR("unable to request stable (public) address: %s", strerror(errno));
-            return NULL;
-        }
-#else // Assume BSD
-// BSD doesn't follow RFC5014 either (at least xnu).
-        int value = 0;
-        if (setsockopt(connection->io.fd, IPPROTO_IPV6, IPV6_PREFER_TEMPADDR, &value, sizeof(value)) < 0) {
-            ERROR("unable to request stable (public) address.");
-            return NULL;
-        }
-#endif // LINUX
-    }
-#ifdef NOT_HAVE_SA_LEN
-    sl = (remote_address->sa.sa_family == AF_INET
-          ? sizeof remote_address->sin
-          : sizeof remote_address->sin6);
-#else
-    sl = remote_address->sa.sa_len;
-#endif
-    // Connect to the host
-    if (connect(connection->io.fd, &connection->address.sa, sl) < 0) {
-        if (errno != EINPROGRESS && errno != EAGAIN) {
-            ERROR("Can't connect to %s: %s", connection->name, strerror(errno));
-            RELEASE_HERE(&connection->io, comm_finalize);
-            return NULL;
-        }
-    }
-    // At this point if we are doing TCP, we do not yet have a connection, but the connection should be in
-    // progress, and we should get a write select event when the connection succeeds or fails.
-    // UDP is connectionless, so the connect() call just sets the default destination for send() on
-    // the socket.
-
-    if (tls) {
-#ifndef TLS_EXCLUDED
-        connection->tls_context = (tls_context_t *)-1;
-#else
-        ERROR("connect_to_host: tls requested when excluded.");
-        RELEASE_HERE(&connection->io, comm_finalize);
-        return NULL;
-#endif
-    }
-
-    connection->connected = connected;
-    connection->disconnected = disconnected;
-    connection->datagram_callback = datagram_callback;
-    connection->context = context;
-    connection->finalize = finalize;
-    connection->opportunistic = opportunistic;
-    if (!stream) {
-        connection->is_connected = true;
-        connection->tcp_stream = false;
-        ioloop_add_reader(&connection->io, udp_read_callback);
-    } else {
-        connection->tcp_stream = true;
-        ioloop_add_writer(&connection->io, connect_callback);
-    }
-
-    return connection;
-}
-
-static void
-subproc_finalize(subproc_t *subproc)
-{
-    int i;
-    for (i = 0; i < subproc->argc; i++) {
-        if (subproc->argv[i] != NULL) {
-            free(subproc->argv[i]);
-            subproc->argv[i] = NULL;
-        }
-    }
-    if (subproc->output_fd != NULL) {
-        ioloop_file_descriptor_release(subproc->output_fd);
-    }
-    if (subproc->finalize != NULL) {
-        subproc->finalize(subproc->context);
-    }
-    free(subproc);
-}
-
-static void
-subproc_output_finalize(void *context)
-{
-    subproc_t *subproc = context;
-    if (subproc->output_fd) {
-        subproc->output_fd = NULL;
-    }
-    RELEASE_HERE(subproc, subproc_finalize);
-}
-
-void
-ioloop_subproc_release_(subproc_t *subproc, const char *file, int line)
-{
-    RELEASE(subproc, subproc_finalize);
-}
-
-// Invoke the specified executable with the specified arguments.   Call callback when it exits.
-// All failures are reported through the callback.
-subproc_t *
-ioloop_subproc(const char *exepath, char **argv, int argc, subproc_callback_t callback,
-               io_callback_t output_callback, void *context)
-{
-    subproc_t *subproc;
-    int i, rv;
-    posix_spawn_file_actions_t actions;
-    posix_spawnattr_t attrs;
-
-    if (callback == NULL) {
-        ERROR("ioloop_subproc called with null callback");
-        return NULL;
-    }
-
-    if (argc > MAX_SUBPROC_ARGS) {
-        callback(NULL, 0, "too many subproc args");
-        return NULL;
-    }
-
-    subproc = calloc(1, sizeof(*subproc));
-    if (subproc == NULL) {
-        callback(NULL, 0, "out of memory");
-        return NULL;
-    }
-    RETAIN_HERE(subproc);
-    if (output_callback != NULL) {
-        rv = pipe(subproc->pipe_fds);
-        if (rv < 0) {
-            callback(NULL, 0, "unable to create pipe.");
-            RELEASE_HERE(subproc, subproc_finalize);
-            return NULL;
-        }
-        subproc->output_fd = ioloop_file_descriptor_create(subproc->pipe_fds[0], subproc, subproc_output_finalize);
-        if (subproc->output_fd == NULL) {
-            // subproc->output_fd holds a reference to subproc.
-            RETAIN_HERE(subproc);
-            callback(NULL, 0, "out of memory.");
-            close(subproc->pipe_fds[0]);
-            close(subproc->pipe_fds[1]);
-            RELEASE_HERE(subproc, subproc_finalize);
-            return NULL;
-        }
-    }
-
-    subproc->argv[0] = strdup(exepath);
-    if (subproc->argv[0] == NULL) {
-        RELEASE_HERE(subproc, subproc_finalize);
-        callback(NULL, 0, "out of memory");
-        return NULL;
-    }
-    subproc->argc++;
-    for (i = 0; i < argc; i++) {
-        subproc->argv[i + 1] = strdup(argv[i]);
-        if (subproc->argv[i + 1] == NULL) {
-            RELEASE_HERE(subproc, subproc_finalize);
-            callback(NULL, 0, "out of memory");
-            return NULL;
-        }
-        subproc->argc++;
-    }
-
-    // Set up for posix_spawn
-    posix_spawn_file_actions_init(&actions);
-    if (output_callback != NULL) {
-        posix_spawn_file_actions_adddup2(&actions, subproc->pipe_fds[1], STDOUT_FILENO);
-        posix_spawn_file_actions_addclose(&actions, subproc->pipe_fds[0]);
-        posix_spawn_file_actions_addclose(&actions, subproc->pipe_fds[1]);
-    }
-    posix_spawnattr_init(&attrs);
-    extern char **environ;
-    rv = posix_spawn(&subproc->pid, exepath, &actions, &attrs, subproc->argv, environ);
-    posix_spawn_file_actions_destroy(&actions);
-    posix_spawnattr_destroy(&attrs);
-    if (rv != 0) {
-        int err = rv < 0 ? errno : rv;
-        ERROR("posix_spawn failed for %s: %s", subproc->argv[0], strerror(err));
-        callback(subproc, 0, strerror(err));
-        RELEASE_HERE(subproc, subproc_finalize);
-        return NULL;
-    }
-    subproc->callback = callback;
-    subproc->context = context;
-    subproc->next = subprocesses;
-    subprocesses = subproc;
-    RETAIN_HERE(subproc);
-
-    // Now that we have a viable subprocess, add the reader callback.
-    if (output_callback != NULL && subproc->output_fd != NULL) {
-        close(subproc->pipe_fds[1]);
-        ioloop_add_reader(subproc->output_fd, output_callback);
-    }
-    return subproc;
-}
-
-void
-ioloop_subproc_run_sync(subproc_t *subproc)
-{
-    int nev;
-    RETAIN_HERE(subproc);
-    do {
-        nev = ioloop_events(0);
-        INFO("%d events", nev);
-        if (subproc->finished) {
-            RELEASE_HERE(subproc, subproc_finalize);
-            return;
-        }
-    } while (nev >= 0);
-    ERROR("ioloop returned %d.", nev);
-}
-
-#ifndef EXCLUDE_DNSSD_TXN_SUPPORT
-static void
-dnssd_txn_callback(io_t *io, void *context)
-{
-    dnssd_txn_t *txn = (dnssd_txn_t *)context;
-    // It's only safe to process the I/O if the DNSServiceRef hasn't been deallocated.
-    if (txn->sdref != NULL) {
-        int status = DNSServiceProcessResult(txn->sdref);
-        if (status != kDNSServiceErr_NoError) {
-            if (txn->failure_callback != NULL) {
-                txn->failure_callback(txn->context, status);
-            } else {
-                INFO("status %d", status);
-            }
-            ioloop_dnssd_txn_cancel(txn);
-        }
-    }
-}
-
-void
-dnssd_txn_finalize(dnssd_txn_t *txn)
-{
-    if (txn->sdref != NULL) {
-        ioloop_dnssd_txn_cancel(txn);
-    }
-    if (txn->finalize_callback) {
-        txn->finalize_callback(txn->context);
-    }
-}
-
-void
-dnssd_txn_io_finalize(void *context)
-{
-    dnssd_txn_t *txn = context;
-    txn->io = NULL;
-    RELEASE_HERE(txn, dnssd_txn_finalize);
-}
-
-void
-ioloop_dnssd_txn_cancel(dnssd_txn_t *txn)
-{
-    if (txn->sdref != NULL) {
-        DNSServiceRefDeallocate(txn->sdref);
-        txn->sdref = NULL;
-    } else {
-        INFO("dead transaction.");
-    }
-    if (txn->io != NULL) {
-        txn->io->fd = -1;
-        RELEASE_HERE(txn->io, dnssd_txn_io_finalize);
-    }
-}
-
-void
-ioloop_dnssd_txn_retain_(dnssd_txn_t *dnssd_txn, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(dnssd_txn);
-}
-
-void
-ioloop_dnssd_txn_release_(dnssd_txn_t *dnssd_txn, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(dnssd_txn, dnssd_txn_finalize);
-}
-
-dnssd_txn_t *
-ioloop_dnssd_txn_add_(DNSServiceRef ref, void *context,
-                      dnssd_txn_finalize_callback_t callback, dnssd_txn_failure_callback_t failure_callback,
-                      const char *file, int line)
-{
-    dnssd_txn_t *txn = calloc(1, sizeof(*txn));
-    if (txn != NULL) {
-        RETAIN(txn);
-        txn->sdref = ref;
-        txn->io = ioloop_file_descriptor_create(DNSServiceRefSockFD(txn->sdref), txn, dnssd_txn_io_finalize);
-        if (txn->io == NULL) {
-            RELEASE_HERE(txn, dnssd_txn_finalize);
-            return NULL;
-        }
-        // io holds a reference to txn
-        RETAIN_HERE(txn);
-        txn->finalize_callback = callback;
-        txn->failure_callback = failure_callback;
-        txn->context = context;
-        ioloop_add_reader(txn->io, dnssd_txn_callback);
-    }
-    return txn;
-}
-
-void
-ioloop_dnssd_txn_set_aux_pointer(dnssd_txn_t *NONNULL txn, void *aux_pointer)
-{
-    txn->aux_pointer = aux_pointer;
-}
-
-void *
-ioloop_dnssd_txn_get_aux_pointer(dnssd_txn_t *NONNULL txn)
-{
-    return txn->aux_pointer;
-}
-
-void *
-ioloop_dnssd_txn_get_context(dnssd_txn_t *NONNULL txn)
-{
-    return txn->context;
-}
-#endif // EXCLUDE_DNSSD_TXN_SUPPORT
-
-static void
-file_descriptor_finalize(void *context)
-{
-    io_t *file_descriptor = context;
-    if (file_descriptor->finalize) {
-        file_descriptor->finalize(file_descriptor->context);
-    }
-    if (file_descriptor->fd != -1) {
-        close(file_descriptor->fd);
-    }
-    free(file_descriptor);
-}
-
-void
-ioloop_file_descriptor_retain_(io_t *file_descriptor, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(file_descriptor);
-}
-
-void
-ioloop_file_descriptor_release_(io_t *file_descriptor, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(file_descriptor, file_descriptor_finalize);
-}
-
-io_t *
-ioloop_file_descriptor_create_(int fd, void *context, finalize_callback_t finalize, const char *file, int line)
-{
-    io_t *ret;
-    ret = calloc(1, sizeof(*ret));
-    if (ret) {
-        ret->fd = fd;
-        ret->context = context;
-        ret->finalize = finalize;
-        ret->io_finalize = file_descriptor_finalize;
-        RETAIN(ret);
-    }
-    return ret;
-}
-
-void
-ioloop_run_async(async_callback_t callback, void *context)
-{
-    async_event_t **epp, *event = calloc(1, sizeof(*event));
-    if (event == NULL) {
-        ERROR("no memory for async callback to %p, context %p", callback, context);
-    }
-
-    event->callback = callback;
-    event->context = context;
-
-    epp = &async_events;
-    while (*epp) {
-        epp = &(*epp)->next;
-    }
-
-    *epp = event;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/ioloop.h b/ServiceRegistration/ioloop.h
deleted file mode 100644
index ea098f4..0000000
--- a/ServiceRegistration/ioloop.h
+++ /dev/null
@@ -1,360 +0,0 @@
-/* ioloop.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * Definitions for simple dispatch implementation.
- */
-
-#ifndef __IOLOOP_H
-#define __IOLOOP_H
-
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-
-#include <dns_sd.h>
-
-#ifndef NSEC_PER_SEC
-#define NSEC_PER_SEC  1000000000ull
-#endif
-#ifndef NSEC_PER_MSEC
-#define NSEC_PER_MSEC    1000000ull
-#endif
-
-#define MSEC_PER_SEC (NSEC_PER_SEC / NSEC_PER_MSEC)
-
-#ifndef IN_LINKLOCAL
-#define IN_LINKLOCAL(x) (((uint32_t)(x) & 0xffff0000) == 0xA9FE0000) // 169.254.*
-#endif
-#ifndef IN_LOOPBACK
-#define IN_LOOPBACK(x) (((uint32_t)(x) & 0xff000000) == 0x7f000000) // 127.*
-#endif
-
-#ifndef __DSO_H
-typedef struct dso_state dso_state_t;
-#endif
-
-typedef union addr addr_t;
-union addr {
-    struct sockaddr sa;
-    struct sockaddr_in sin;
-    struct sockaddr_in6 sin6;
-    struct {
-        char len;
-        char family;
-        int index;
-        uint8_t addr[8];
-    } ether_addr;
-    struct sockaddr_un sun;
-};
-
-#define IOLOOP_NTOP(addr, buf) \
-    (((addr)->sa.sa_family == AF_INET || (addr)->sa.sa_family == AF_INET6) \
-     ? (inet_ntop((addr)->sa.sa_family, ((addr)->sa.sa_family == AF_INET \
-                                        ? (void *)&(addr)->sin.sin_addr \
-                                        : (void *)&(addr)->sin6.sin6_addr), buf, sizeof buf) != NULL) \
-    : snprintf(buf, sizeof buf, "Address type %d", (addr)->sa.sa_family))
-
-struct message {
-    int ref_count;
-#ifndef IOLOOP_MACOS
-    addr_t src;
-    addr_t local;
-#endif
-    int ifindex;
-    uint16_t length;
-    time_t received_time; // Only for SRP Replication, zero otherwise.
-    dns_wire_t wire;
-};
-
-
-typedef struct dso_transport comm_t;
-typedef struct io io_t;
-typedef struct subproc subproc_t;
-typedef struct wakeup wakeup_t;
-typedef struct dnssd_txn dnssd_txn_t;
-typedef struct interface_address_state interface_address_state_t;
-
-typedef void (*dnssd_txn_finalize_callback_t)(void *NONNULL context);
-typedef void (*dnssd_txn_failure_callback_t)(void *NONNULL context, int status);
-typedef void (*wakeup_callback_t)(void *NONNULL context);
-typedef void (*finalize_callback_t)(void *NONNULL context);
-typedef void (*cancel_callback_t)(void *NONNULL context);
-typedef void (*ready_callback_t)(void *NONNULL context, uint16_t port);
-typedef void (*io_callback_t)(io_t *NONNULL io, void *NONNULL context);
-typedef void (*comm_callback_t)(comm_t *NONNULL comm);
-typedef void (*datagram_callback_t)(comm_t *NONNULL comm, message_t *NONNULL message, void *NULLABLE context);
-typedef void (*connect_callback_t)(comm_t *NONNULL connection, void *NULLABLE context);
-typedef void (*disconnect_callback_t)(comm_t *NONNULL comm, void *NULLABLE context, int error);
-enum interface_address_change { interface_address_added, interface_address_deleted, interface_address_unchanged };
-typedef void (*interface_callback_t)(void *NULLABLE context, const char *NONNULL name,
-                                     const addr_t *NONNULL address, const addr_t *NONNULL netmask,
-                                     uint32_t flags, enum interface_address_change event_type);
-typedef void (*subproc_callback_t)(void *NULLABLE context, int status, const char *NULLABLE error);
-typedef void (*tls_config_callback_t)(void *NONNULL context);
-typedef void (*async_callback_t)(void *NULLABLE context);
-
-typedef struct tls_context tls_context_t;
-
-#define IOLOOP_SECOND   1000LL
-#define IOLOOP_MINUTE   60 * IOLOOP_SECOND
-#define IOLOOP_HOUR     60 * IOLOOP_MINUTE
-#define IOLOOP_DAY      24 * IOLOOP_HOUR
-
-struct interface_address_state {
-    interface_address_state_t *NULLABLE next;
-    char *NONNULL name;
-    addr_t addr;
-    addr_t mask;
-    uint32_t flags;
-};
-
-struct io {
-    int ref_count;
-    io_t *NULLABLE next;
-    io_callback_t NULLABLE read_callback;
-    io_callback_t NULLABLE write_callback;
-    finalize_callback_t NULLABLE finalize;
-    finalize_callback_t NULLABLE io_finalize;
-    void *NULLABLE context;
-    io_t *NULLABLE cancel_on_close;
-    io_callback_t NULLABLE ready;
-    bool want_read : 1;
-    bool want_write : 1;
-    int fd;
-};
-
-struct wakeup {
-    int ref_count;
-    wakeup_t *NULLABLE next;
-    void *NULLABLE context;
-    wakeup_callback_t NULLABLE wakeup;
-    finalize_callback_t NULLABLE finalize;
-#ifdef IOLOOP_MACOS
-    dispatch_source_t NULLABLE dispatch_source;
-#else
-    int64_t wakeup_time;
-#endif
-};
-
-struct dso_transport {
-#ifdef IOLOOP_MACOS
-    nw_connection_t NULLABLE connection;
-    nw_listener_t NULLABLE listener;
-    nw_parameters_t NULLABLE parameters;
-    int ref_count;
-    int writes_pending;
-    wakeup_t *NULLABLE idle_timer;
-    // nw_connection objects aren't necessarily ready to write to immediately. But when we create an outgoing connection, we
-    // typically want to write to it immediately. So we have a one-datum queue in case this happens; if the connection takes
-    // so long to get ready that another write happens, we drop the first write. This will work okay for UDP connections, where
-    // the retransmit logic is in the application. For future, we may want to rearchitect the flow so that the write is always
-    // done in a callback.
-    dispatch_data_t NULLABLE pending_write;
-#else
-    io_t io;
-    message_t *NULLABLE message;
-    int multicast_ifindex;
-#endif
-    uint16_t listen_port;
-    uint16_t *NULLABLE avoid_ports;
-    int num_avoid_ports;
-    bool avoiding;
-    char *NONNULL name;
-    void *NULLABLE context;
-    datagram_callback_t NULLABLE datagram_callback;
-    comm_callback_t NULLABLE close_callback;
-    connect_callback_t NULLABLE connected;
-    disconnect_callback_t NULLABLE disconnected;
-    finalize_callback_t NULLABLE finalize;
-    cancel_callback_t NULLABLE cancel;
-    ready_callback_t NULLABLE ready;
-    uint8_t *NULLABLE buf;
-    dso_state_t *NULLABLE dso;
-    tls_context_t *NULLABLE tls_context;
-    addr_t address, multicast;
-    size_t message_length_len;
-    size_t message_length, message_cur;
-    uint8_t message_length_bytes[2];
-#ifdef IOLOOP_MACOS
-    bool read_pending: 1; // Only ever one.
-    bool server: 1;       // Indicates that this connection was created by a listener
-    bool connection_ready: 1;
-    bool final_data : 1; // Indicates that the next message written will be the final message, so send a FIN.
-#else
-    bool tls_handshake_incomplete: 1;
-#endif // IOLOOP_MACOS
-    bool tls_rotation_ready: 1; // Indicates if the listener should rotate its TLS certificate.
-    bool tcp_stream: 1;
-    bool is_multicast: 1;
-    bool is_connected: 1;
-    bool is_listener: 1;
-    bool opportunistic: 1;
-};
-
-#define MAX_SUBPROC_ARGS 20
-struct subproc {
-    int ref_count;
-#ifdef IOLOOP_MACOS
-    dispatch_source_t NULLABLE dispatch_source;
-#else
-    subproc_t *NULLABLE next;
-#endif
-    int pipe_fds[2];
-    io_t *NULLABLE output_fd;
-    void *NULLABLE context;
-    subproc_callback_t NONNULL callback;
-    finalize_callback_t NULLABLE finalize;
-    char *NULLABLE argv[MAX_SUBPROC_ARGS + 1];
-    int argc;
-    pid_t pid;
-    bool finished : 1;
-};
-
-struct dnssd_txn {
-#ifndef IOLOOP_MACOS
-    io_t *NULLABLE io;
-#endif
-    int ref_count;
-    DNSServiceRef NULLABLE sdref;
-    void *NULLABLE context;
-    void *NULLABLE aux_pointer;
-    dnssd_txn_finalize_callback_t NULLABLE finalize_callback;
-    dnssd_txn_failure_callback_t NULLABLE failure_callback;
-};
-
-extern int64_t ioloop_now;
-int getipaddr(addr_t *NONNULL addr, const char *NONNULL p);
-int64_t ioloop_timenow(void);
-message_t *NULLABLE message_allocate(size_t message_size);
-void message_free(message_t *NONNULL message);
-void ioloop_close(io_t *NONNULL io);
-void ioloop_add_reader(io_t *NONNULL io, io_callback_t NONNULL callback);
-#define ioloop_wakeup_create() ioloop_wakeup_create_(__FILE__, __LINE__)
-wakeup_t *NULLABLE ioloop_wakeup_create_(const char *NONNULL file, int line);
-#define ioloop_wakeup_retain(wakeup) ioloop_wakeup_retain_(wakeup, __FILE__, __LINE__)
-void ioloop_wakeup_retain_(wakeup_t *NONNULL wakeup, const char *NONNULL file, int line);
-#define ioloop_wakeup_release(wakeup) ioloop_wakeup_release_(wakeup, __FILE__, __LINE__)
-void ioloop_wakeup_release_(wakeup_t *NONNULL wakeup, const char *NONNULL file, int line);
-bool ioloop_add_wake_event(wakeup_t *NONNULL wakeup, void *NULLABLE context,
-                           wakeup_callback_t NONNULL callback, finalize_callback_t NULLABLE finalize,
-                           int32_t milliseconds);
-void ioloop_cancel_wake_event(wakeup_t *NONNULL wakeup);
-
-bool ioloop_init(void);
-int ioloop(void);
-
-#define ioloop_comm_retain(comm) ioloop_comm_retain_(comm, __FILE__, __LINE__)
-void ioloop_comm_retain_(comm_t *NONNULL comm, const char *NONNULL file, int line);
-#define ioloop_comm_release(wakeup) ioloop_comm_release_(wakeup, __FILE__, __LINE__)
-void ioloop_comm_release_(comm_t *NONNULL comm, const char *NONNULL file, int line);
-void ioloop_comm_context_set(comm_t *NONNULL connection,
-                             void *NULLABLE context, finalize_callback_t NULLABLE callback);
-void ioloop_comm_connect_callback_set(comm_t *NONNULL comm, connect_callback_t NULLABLE callback);
-void ioloop_comm_disconnect_callback_set(comm_t *NONNULL comm, disconnect_callback_t NULLABLE callback);
-void ioloop_comm_cancel(comm_t *NONNULL comm);
-#define ioloop_listener_retain(comm) ioloop_listener_retain_(comm, __FILE__, __LINE__)
-void ioloop_listener_retain_(comm_t *NONNULL listener, const char *NONNULL file, int line);
-#define ioloop_listener_release(wakeup) ioloop_listener_release_(wakeup, __FILE__, __LINE__)
-void ioloop_listener_release_(comm_t *NONNULL listener, const char *NONNULL file, int line);
-void ioloop_listener_cancel(comm_t *NONNULL comm);
-comm_t *NULLABLE ioloop_listener_create(bool stream, bool tls, uint16_t *NULLABLE avoid_ports, int num_avoid_ports,
-                                        const addr_t *NULLABLE ip_address, const char *NULLABLE multicast,
-                                        const char *NONNULL name, datagram_callback_t NONNULL datagram_callback,
-                                        connect_callback_t NULLABLE connected, cancel_callback_t NULLABLE cancel,
-                                        ready_callback_t NULLABLE ready, finalize_callback_t NULLABLE finalize,
-                                        tls_config_callback_t NULLABLE tls_config, void *NULLABLE context);
-comm_t *NULLABLE ioloop_connection_create(addr_t *NONNULL remote_address, bool tls, bool stream, bool stable,
-                                          bool opportunistic, datagram_callback_t NONNULL datagram_callback,
-                                          connect_callback_t NULLABLE connected,
-                                          disconnect_callback_t NULLABLE disconnected,
-                                          finalize_callback_t NULLABLE finalize,
-                                          void *NULLABLE context);
-#define ioloop_message_create(x) ioloop_message_create_(x, __FILE__, __LINE__)
-message_t *NULLABLE ioloop_message_create_(size_t message_size, const char *NONNULL file, int line);
-#define ioloop_message_retain(wakeup) ioloop_message_retain_(wakeup, __FILE__, __LINE__)
-void ioloop_message_retain_(message_t *NONNULL message, const char *NONNULL file, int line);
-#define ioloop_message_release(wakeup) ioloop_message_release_(wakeup, __FILE__, __LINE__)
-void ioloop_message_release_(message_t *NONNULL message, const char *NONNULL file, int line);
-bool ioloop_send_multicast(comm_t *NONNULL comm, int ifindex, struct iovec *NONNULL iov, int iov_len);
-bool ioloop_send_message(comm_t *NONNULL connection, message_t *NULLABLE responding_to,
-                         struct iovec *NONNULL iov, int iov_len);
-bool ioloop_send_final_message(comm_t *NONNULL connection, message_t *NULLABLE responding_to,
-                               struct iovec *NONNULL iov, int iov_len);
-bool ioloop_send_data(comm_t *NONNULL connection, message_t *NULLABLE responding_to,
-                      struct iovec *NONNULL iov, int iov_len);
-bool ioloop_send_final_data(comm_t *NONNULL connection, message_t *NULLABLE responding_to,
-                            struct iovec *NONNULL iov, int iov_len);
-bool ioloop_map_interface_addresses(const char *NULLABLE ifname, void *NULLABLE context, interface_callback_t NULLABLE callback);
-#define ioloop_map_interface_addresses_here(here, ifname, context, callback) \
-    ioloop_map_interface_addresses_here_(here, ifname, context, callback, __FILE__, __LINE__)
-bool ioloop_map_interface_addresses_here_(interface_address_state_t *NONNULL *NULLABLE here,
-                                          const char *NULLABLE ifname, void *NULLABLE context, interface_callback_t NULLABLE callback,
-                                          const char *NONNULL file, int line);
-ssize_t ioloop_recvmsg(int sock, uint8_t *NONNULL buffer, size_t buffer_length, int *NONNULL ifindex,
-                       int *NONNULL hoplimit, addr_t *NONNULL source, addr_t *NONNULL destination);
-#define ioloop_subproc_release(subproc) ioloop_subproc_release_(subproc, __FILE__, __LINE__)
-void ioloop_subproc_release_(subproc_t *NONNULL subproc, const char *NONNULL file, int line);
-#define ioloop_subproc_retain(subproc) ioloop_subproc_retain_(subproc, __FILE__, __LINE__)
-void ioloop_subproc_retain_(subproc_t *NONNULL subproc, const char *NONNULL file, int line);
-subproc_t *NULLABLE ioloop_subproc(const char *NONNULL exepath, char *NULLABLE *NONNULL argv, int argc,
-                                   subproc_callback_t NULLABLE callback, io_callback_t NULLABLE output_callback,
-                                   void *NULLABLE context);
-void ioloop_subproc_run_sync(subproc_t *NONNULL subproc);
-#define ioloop_dnssd_txn_add(ref, context, finalize_callback, failure_callback) \
-    ioloop_dnssd_txn_add_(ref, context, finalize_callback, failure_callback, __FILE__, __LINE__)
-dnssd_txn_t *NULLABLE
-ioloop_dnssd_txn_add_(DNSServiceRef NONNULL ref, void *NULLABLE context,
-                      dnssd_txn_finalize_callback_t NULLABLE callback,
-                      dnssd_txn_failure_callback_t NULLABLE failure_callback, const char *NONNULL file, int line);
-void ioloop_dnssd_txn_cancel(dnssd_txn_t *NONNULL txn);
-#define ioloop_dnssd_txn_retain(txn) ioloop_dnssd_txn_retain_(txn, __FILE__, __LINE__)
-void ioloop_dnssd_txn_retain_(dnssd_txn_t *NONNULL txn, const char *NONNULL file, int line);
-#define ioloop_dnssd_txn_release(txn) ioloop_dnssd_txn_release_(txn, __FILE__, __LINE__)
-void ioloop_dnssd_txn_release_(dnssd_txn_t *NONNULL txn, const char *NONNULL file, int line);
-#endif
-void ioloop_dnssd_txn_set_aux_pointer(dnssd_txn_t *NONNULL txn, void *NULLABLE aux_pointer);
-void *NULLABLE ioloop_dnssd_txn_get_aux_pointer(dnssd_txn_t *NONNULL txn);
-void *NULLABLE ioloop_dnssd_txn_get_context(dnssd_txn_t *NONNULL txn);
-
-#define ioloop_file_descriptor_create(fd, context, finalize) \
-    ioloop_file_descriptor_create_(fd, context, finalize, __FILE__, __LINE__)
-io_t *NULLABLE ioloop_file_descriptor_create_(int fd, void *NULLABLE context, finalize_callback_t NULLABLE finalize,
-                                              const char *NONNULL file, int line);
-#define ioloop_file_descriptor_retain(file_descriptor) ioloop_file_descriptor_retain_(file_descriptor, __FILE__, \
-                                                            __LINE__)
-void ioloop_file_descriptor_retain_(io_t *NONNULL file_descriptor, const char *NONNULL file, int line);
-#define ioloop_file_descriptor_release(file_descriptor) ioloop_file_descriptor_release_(file_descriptor, __FILE__, \
-                                                            __LINE__)
-void ioloop_file_descriptor_release_(io_t *NONNULL file_descriptor, const char *NONNULL file, int line);
-
-bool ioloop_interface_monitor_start(void);
-void ioloop_run_async(async_callback_t NULLABLE callback, void *NULLABLE context);
-
-
-bool srp_load_file_data(void *NULLABLE host_context, const char *NONNULL filename, uint8_t *NONNULL buffer,
-                        uint16_t *NONNULL length, uint16_t buffer_size);
-bool srp_store_file_data(void *NULLABLE host_context, const char *NONNULL filename, uint8_t *NONNULL buffer,
-                         uint16_t length);
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/keydump.c b/ServiceRegistration/keydump.c
deleted file mode 100644
index 8c82661..0000000
--- a/ServiceRegistration/keydump.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* keydump.c
- *
- * Copyright (c) 2018 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.
- *
- * Dump the contents of a key file saved by e.g. srp-simple as a DNS key.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "srp-api.h"
-
-int
-main(int argc, char **argv)
-{
-    const char *key_name = "com.apple.srp-client.host-key";
-    srp_key_t *key;
-
-    key = srp_get_key(key_name, NULL);
-    if (key == NULL) {
-        if (key == NULL) {
-            printf("Unable to load key from %s.", key_name);
-            exit(1);
-        }
-    }
-
-    srp_print_key(key);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/log/log_srp.m b/ServiceRegistration/log/log_srp.m
index d2aea20..c76a3dd 100644
--- a/ServiceRegistration/log/log_srp.m
+++ b/ServiceRegistration/log/log_srp.m
@@ -22,11 +22,12 @@
 static NS_RETURNS_RETAINED NSAttributedString *
 srp_os_log_copy_formatted_string_ipv6_addr_segment(id value)
 {
-#define PREFIX_CLASS_MAX_LENGTH 6 // 6 is for <space>(ULA) or <space>(LUA) or <space>(GUA)
+#define PREFIX_CLASS_MAX_LENGTH 6 // 6 is for xxx:<space> where X is ULA, GUA, LLA or nothing.
 	NSData *data;
-	const uint8_t * addr_data;
 	NSAttributedString * a_str;
 	char buf[INET6_ADDRSTRLEN + PREFIX_CLASS_MAX_LENGTH];
+	uint16_t words[8]; // Word buffer
+    int num_words = 0;
 	char *delimiter;
 	char *ptr;
 	char *ptr_limit;
@@ -43,22 +44,27 @@
 #define IPv6_ADDR_SIZE 16
 	require_action(data.bytes != nil && data.length > 0 && data.length <= IPv6_ADDR_SIZE, exit,
 		a_str = AStrWithFormat(@"<failed to decode - NIL or invalid data length: %lu>", (unsigned long)data.length));
+	require_action((data.length & 1) == 0, exit,
+		a_str = AStrWithFormat(@"<failed to decode - odd data length: %lu>", (unsigned long)data.length));
 
-	addr_data = data.bytes;
+    const uint8_t *dptr = data.bytes;
+
+    // Clump bytes into sixteen-bit words.
+	for (size_t i = 0; i < data.length; i += 2) {
+        words[num_words] = (uint16_t)((dptr[i]) << 8) | (uint16_t)(dptr[i + 1]);
+        num_words++;
+    }
+
 	delimiter = "";
 	ptr = buf;
 	ptr_limit = buf + sizeof(buf);
-	for (size_t i = 0; i < data.length; i++) {
+	for (int i = 0; i < num_words; i++) {
 		size_t remaining = (size_t)(ptr_limit - ptr);
-		int result = snprintf(ptr, remaining, "%s%02x", delimiter, addr_data[i]);
+		int result = snprintf(ptr, remaining, "%s%x", delimiter, words[i]);
 		require_action(result > 0 && (size_t) result < remaining, exit,
-			a_str = AStrWithFormat(@"<failed to decode - snprintf: result: %ld remain: %lu>", i, remaining));
+			a_str = AStrWithFormat(@"<failed to decode - snprintf: result: %d remain: %lu>", i, remaining));
 		ptr += result;
-		if ((i + 1) % 2 == 0) {
-			delimiter = ":";
-		} else {
-			delimiter = "";
-		}
+        delimiter = ":";
 	}
 
 	ns_str = @(buf);
@@ -155,3 +161,12 @@
 
 	return result_str;
 }
+
+// Local Variables:
+// mode: C
+// tab-width: 4
+// c-file-style: "bsd"
+// c-basic-offset: 4
+// fill-column: 108
+// indent-tabs-mode: nil
+// End:
diff --git a/ServiceRegistration/macos-ioloop.c b/ServiceRegistration/macos-ioloop.c
deleted file mode 100644
index 4949315..0000000
--- a/ServiceRegistration/macos-ioloop.c
+++ /dev/null
@@ -1,1569 +0,0 @@
-/* macos-ioloop.c
- *
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- *
- * Simple event dispatcher for DNS.
- */
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <net/if.h>
-#include <ifaddrs.h>
-#include <dns_sd.h>
-
-#include <dispatch/dispatch.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "tls-macos.h"
-#include "tls-keychain.h"
-
-static bool connection_write_now(comm_t *NONNULL connection);
-
-dispatch_queue_t ioloop_main_queue;
-
-// Forward references
-static void tcp_start(comm_t *NONNULL connection);
-
-int
-getipaddr(addr_t *addr, const char *p)
-{
-    if (inet_pton(AF_INET, p, &addr->sin.sin_addr)) {
-        addr->sa.sa_family = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-        addr->sa.sa_len = sizeof addr->sin;
-#endif
-        return sizeof addr->sin;
-    }  else if (inet_pton(AF_INET6, p, &addr->sin6.sin6_addr)) {
-        addr->sa.sa_family = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-        addr->sa.sa_len = sizeof addr->sin6;
-#endif
-        return sizeof addr->sin6;
-    } else {
-        return 0;
-    }
-}
-
-int64_t
-ioloop_timenow(void)
-{
-    int64_t now;
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    now = (int64_t)tv.tv_sec * 1000 + (int64_t)tv.tv_usec / 1000;
-    return now;
-}
-
-static void
-wakeup_event(void *context)
-{
-    wakeup_t *wakeup = context;
-
-    // All ioloop wakeups are one-shot.
-    ioloop_cancel_wake_event(wakeup);
-
-    // Call the callback, which mustn't be null.
-    wakeup->wakeup(wakeup->context);
-}
-
-static void
-wakeup_finalize(void *context)
-{
-    wakeup_t *wakeup = context;
-    if (wakeup->ref_count == 0) {
-        if (wakeup->dispatch_source != NULL) {
-            dispatch_release(wakeup->dispatch_source);
-            wakeup->dispatch_source = NULL;
-        }
-        if (wakeup->finalize != NULL) {
-            wakeup->finalize(wakeup->context);
-        }
-        free(wakeup);
-    }
-}
-
-void
-ioloop_wakeup_retain_(wakeup_t *wakeup, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(wakeup);
-}
-
-void
-ioloop_wakeup_release_(wakeup_t *wakeup, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(wakeup, wakeup_finalize);
-}
-
-wakeup_t *
-ioloop_wakeup_create_(const char *file, int line)
-{
-    wakeup_t *ret = calloc(1, sizeof(*ret));
-    if (ret) {
-        RETAIN(ret);
-    }
-    return ret;
-}
-
-bool
-ioloop_add_wake_event(wakeup_t *wakeup, void *context, wakeup_callback_t callback, wakeup_callback_t finalize,
-                      int32_t milliseconds)
-{
-    if (callback == NULL) {
-        ERROR("ioloop_add_wake_event called with null callback");
-        return false;
-    }
-    if (milliseconds < 0) {
-        ERROR("ioloop_add_wake_event called with negative timeout");
-        return false;
-    }
-    if (wakeup->dispatch_source != NULL) {
-        ioloop_cancel_wake_event(wakeup);
-    }
-    wakeup->wakeup = callback;
-    wakeup->context = context;
-    wakeup->finalize = finalize;
-
-    wakeup->dispatch_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, ioloop_main_queue);
-    if (wakeup->dispatch_source == NULL) {
-        ERROR("dispatch_source_create failed in ioloop_add_wake_event().");
-        return false;
-    }
-    dispatch_source_set_event_handler_f(wakeup->dispatch_source, wakeup_event);
-    dispatch_set_context(wakeup->dispatch_source, wakeup);
-
-    // libdispatch doesn't allow events that are scheduled to happen right now. But it is actually useful to be
-    // able to trigger an event to happen immediately, and this is the easiest way to do it from ioloop-we
-    // can't rely on just scheduling an asynchronous event on an event loop because that's specific to Mac.
-    if (milliseconds <= 0) {
-        ERROR("ioloop_add_wake_event: milliseconds = %d", milliseconds);
-        milliseconds = 10;
-    }
-    dispatch_source_set_timer(wakeup->dispatch_source,
-                              dispatch_time(DISPATCH_TIME_NOW, milliseconds * NSEC_PER_SEC / 1000),
-                              milliseconds * NSEC_PER_SEC / 1000, NSEC_PER_SEC / 100);
-    dispatch_resume(wakeup->dispatch_source);
-
-    return true;
-}
-
-void
-ioloop_cancel_wake_event(wakeup_t *wakeup)
-{
-    if (wakeup && wakeup->dispatch_source != NULL) {
-        dispatch_source_cancel(wakeup->dispatch_source);
-        dispatch_release(wakeup->dispatch_source);
-        wakeup->dispatch_source = NULL;
-    }
-}
-
-bool
-ioloop_init(void)
-{
-    ioloop_main_queue = dispatch_get_main_queue();
-    dispatch_retain(ioloop_main_queue);
-    return true;
-}
-
-int
-ioloop(void)
-{
-    dispatch_main();
-    return 0;
-}
-
-#define connection_cancel(conn) connection_cancel_(conn, __FILE__, __LINE__)
-static void
-connection_cancel_(nw_connection_t connection, const char *file, int line)
-{
-    if (connection == NULL) {
-        INFO("null connection at " PUB_S_SRP ":%d", file, line);
-    } else {
-        INFO("%p: " PUB_S_SRP ":%d", connection, file, line);
-        nw_connection_cancel(connection);
-    }
-}
-
-static void
-comm_finalize(comm_t *comm)
-{
-    ERROR("comm_finalize");
-    if (comm->connection != NULL) {
-        nw_release(comm->connection);
-        comm->connection = NULL;
-    }
-    if (comm->listener != NULL) {
-        nw_release(comm->listener);
-        comm->listener = NULL;
-    }
-    if (comm->parameters) {
-        nw_release(comm->parameters);
-        comm->parameters = NULL;
-    }
-    if (comm->pending_write != NULL) {
-        dispatch_release(comm->pending_write);
-        comm->pending_write = NULL;
-    }
-    // If there is an nw_connection_t or nw_listener_t outstanding, then we will get an asynchronous callback
-    // later on.  So we can't actually free the data structure yet, but the good news is that comm_finalize() will
-    // be called again later when the last outstanding asynchronous cancel is done, and then all of the stuff
-    // that follows this will happen.
-#ifndef __clang_analyzer__
-    if (comm->ref_count > 0) {
-        return;
-    }
-#endif
-    if (comm->idle_timer != NULL) {
-        ioloop_cancel_wake_event(comm->idle_timer);
-        RELEASE_HERE(comm->idle_timer, wakeup_finalize);
-    }
-    if (comm->name != NULL) {
-        free(comm->name);
-    }
-    if (comm->finalize != NULL) {
-        comm->finalize(comm->context);
-    }
-    free(comm);
-}
-
-void
-ioloop_comm_retain_(comm_t *comm, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(comm);
-}
-
-void
-ioloop_comm_release_(comm_t *comm, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(comm, comm_finalize);
-}
-
-void
-ioloop_comm_cancel(comm_t *connection)
-{
-    if (connection->connection != NULL) {
-        INFO("%p %p", connection, connection->connection);
-        connection_cancel(connection->connection);
-    }
-    if (connection->idle_timer != NULL) {
-        ioloop_cancel_wake_event(connection->idle_timer);
-    }
-}
-
-void
-ioloop_comm_context_set(comm_t *comm, void *context, finalize_callback_t callback)
-{
-    if (comm->context != NULL && comm->finalize != NULL) {
-        comm->finalize(comm->context);
-    }
-    comm->finalize = callback;
-    comm->context = context;
-}
-
-void
-ioloop_comm_connect_callback_set(comm_t *comm, connect_callback_t callback)
-{
-    comm->connected = callback;
-}
-
-void
-ioloop_comm_disconnect_callback_set(comm_t *comm, disconnect_callback_t callback)
-{
-    comm->disconnected = callback;
-}
-
-static void
-message_finalize(message_t *message)
-{
-    free(message);
-}
-
-void
-ioloop_message_retain_(message_t *message, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(message);
-}
-
-void
-ioloop_message_release_(message_t *message, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(message, message_finalize);
-}
-
-static bool
-ioloop_send_message_inner(comm_t *connection, message_t *responding_to,
-                          struct iovec *iov, int iov_len, bool final, bool send_length)
-{
-    dispatch_data_t data = NULL, new_data, combined;
-    int i;
-    uint16_t len = 0;
-
-    // Not needed on OSX because UDP conversations are treated as "connections."
-    (void)responding_to;
-
-    if (connection->connection == NULL) {
-        return false;
-    }
-
-    // Create a dispatch_data_t object that contains the data in the iov.
-    for (i = 0; i < iov_len; i++) {
-        new_data = dispatch_data_create(iov[i].iov_base, iov[i].iov_len,
-                                        ioloop_main_queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
-        len += iov[i].iov_len;
-        if (data != NULL) {
-            if (new_data != NULL) {
-                // Subsequent times through
-                combined = dispatch_data_create_concat(data, new_data);
-                dispatch_release(data);
-                dispatch_release(new_data);
-                data = combined;
-            } else {
-                // Fail
-                dispatch_release(data);
-                data = NULL;
-            }
-        } else {
-            // First time through
-            data = new_data;
-        }
-        if (data == NULL) {
-            ERROR("ioloop_send_message: no memory.");
-            return false;
-        }
-    }
-
-    if (len == 0) {
-        if (data) {
-            dispatch_release(data);
-        }
-        return false;
-    }
-
-    // TCP requires a length as well as the payload.
-    if (send_length && connection->tcp_stream) {
-        len = htons(len);
-        new_data = dispatch_data_create(&len, sizeof (len), ioloop_main_queue, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
-        if (new_data == NULL) {
-            if (data != NULL) {
-                dispatch_release(data);
-            }
-            return false;
-        }
-        // Length is at beginning.
-        combined = dispatch_data_create_concat(new_data, data);
-        dispatch_release(data);
-        dispatch_release(new_data);
-        if (combined == NULL) {
-            return false;
-        }
-        data = combined;
-    }
-
-    if (connection->pending_write != NULL) {
-        ERROR("Dropping pending write on " PRI_S_SRP, connection->name ? connection->name : "<null>");
-    }
-    connection->pending_write = data;
-    connection->final_data = final;
-    if (connection->connection_ready) {
-        return connection_write_now(connection);
-    }
-    return true;
-}
-
-bool
-ioloop_send_message(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    return ioloop_send_message_inner(connection, responding_to, iov, iov_len, false, true);
-}
-
-bool
-ioloop_send_final_message(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    return ioloop_send_message_inner(connection, responding_to, iov, iov_len, true, true);
-}
-
-bool
-ioloop_send_data(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    return ioloop_send_message_inner(connection, responding_to, iov, iov_len, false, false);
-}
-
-bool
-ioloop_send_final_data(comm_t *connection, message_t *responding_to, struct iovec *iov, int iov_len)
-{
-    return ioloop_send_message_inner(connection, responding_to, iov, iov_len, true, false);
-}
-
-static bool
-connection_write_now(comm_t *connection)
-{
-    // Retain the connection once for each write that's pending, so that it's never finalized while
-    // there's a write in progress.
-    connection->writes_pending++;
-    RETAIN_HERE(connection);
-    nw_connection_send(connection->connection, connection->pending_write,
-                       (connection->final_data
-                        ? NW_CONNECTION_FINAL_MESSAGE_CONTEXT
-                        : NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT), true,
-                       ^(nw_error_t  _Nullable error) {
-                           if (error != NULL) {
-                               ERROR("ioloop_send_message: write failed: " PUB_S_SRP,
-                                     strerror(nw_error_get_error_code(error)));
-                               connection_cancel(connection->connection);
-                           }
-                           if (connection->writes_pending > 0) {
-                               connection->writes_pending--;
-                           } else {
-                               ERROR("ioloop_send_message: write callback reached with no writes marked pending.");
-                           }
-                           RELEASE_HERE(connection, comm_finalize);
-                       });
-    // nw_connection_send should retain this, so let go of our reference to it.
-    dispatch_release(connection->pending_write);
-    connection->pending_write = NULL;
-    return true;
-}
-
-static bool
-datagram_read(comm_t *connection, size_t length, dispatch_data_t content, nw_error_t error)
-{
-    message_t *message = NULL;
-    bool ret = true, *retp = &ret;
-
-    if (error != NULL) {
-        ERROR("datagram_read: " PUB_S_SRP, strerror(nw_error_get_error_code(error)));
-        ret = false;
-        goto out;
-    }
-    if (length > UINT16_MAX) {
-        ERROR("datagram_read: oversized datagram length %zd", length);
-        ret = false;
-        goto out;
-    }
-    message = ioloop_message_create(length);
-    if (message == NULL) {
-        ERROR("datagram_read: unable to allocate message.");
-        ret = false;
-        goto out;
-    }
-    message->length = (uint16_t)length;
-    dispatch_data_apply(content,
-                        ^bool (dispatch_data_t __unused region, size_t offset, const void *buffer, size_t size) {
-            if (message->length < offset + size) {
-                ERROR("datagram_read: data region %zd:%zd is out of range for message length %d",
-                      offset, size, message->length);
-                *retp = false;
-                return false;
-            }
-            memcpy(((uint8_t *)&message->wire) + offset, buffer, size);
-            return true;
-        });
-    if (ret == true) {
-        // Process the message.
-        connection->datagram_callback(connection, message, connection->context);
-    }
-
-    out:
-    if (message != NULL) {
-        ioloop_message_release(message);
-    }
-    if (!ret) {
-        connection_cancel(connection->connection);
-    }
-    return ret;
-}
-
-static void
-connection_error_to_string(nw_error_t error, char *errbuf, size_t errbuf_size)
-{
-    CFErrorRef cfe = NULL;
-    CFStringRef errString = NULL;
-    errbuf[0] = 0;
-    if (error != NULL) {
-        cfe = nw_error_copy_cf_error(error);
-        if (cfe != NULL) {
-            errString = CFErrorCopyDescription(cfe);
-            if (errString != NULL) {
-                CFStringGetCString(errString, errbuf, errbuf_size, kCFStringEncodingUTF8);
-                CFRelease(errString);
-            }
-            CFRelease(cfe);
-        }
-    }
-    if (errbuf[0] == 0) {
-        memcpy(errbuf, "<NULL>", 7);
-    }
-}
-
-static bool
-check_fail(comm_t *connection, size_t length, dispatch_data_t content, nw_error_t error, const char *source)
-{
-    bool fail = false;
-    INFO(PRI_S_SRP ": length %zd, content %p, content_length %ld, error %p, source %s",
-         connection->name, length, content, content == NULL ? -1 : (long)dispatch_data_get_size(content), error, source);
-    if (error != NULL) {
-        fail = true;
-    } else if (connection->connection == NULL) {
-        fail = true;
-    } else if (content == NULL) {
-        ERROR("no content returned in " PUB_S_SRP ": connection must have dropped unexpectedly for " PRI_S_SRP,
-              source, connection->name);
-        fail = true;
-    } else if (dispatch_data_get_size(content) != length) {
-        ERROR("short content returned in " PUB_S_SRP ": %zd != %zd: connection must have dropped unexpectedly for " PRI_S_SRP,
-              source, length, dispatch_data_get_size(content), connection->name);
-        fail = true;
-    }
-    if (fail) {
-        if (connection->connection != NULL) {
-            connection_cancel(connection->connection);
-        }
-    }
-    return fail;
-}
-
-static void
-tcp_read(comm_t *connection, size_t length, dispatch_data_t content, nw_error_t error)
-{
-    if (check_fail(connection, length, content, error, "tcp_read")) {
-        return;
-    }
-    if (datagram_read(connection, length, content, error)) {
-        // Wait for the next frame
-        tcp_start(connection);
-    }
-}
-
-static void
-tcp_read_length(comm_t *connection, dispatch_data_t content, nw_error_t error)
-{
-    size_t length;
-    uint32_t bytes_to_read;
-    const uint8_t *lenbuf;
-    dispatch_data_t map;
-
-    if (check_fail(connection, 2, content, error, "tcp_read_length")) {
-        return;
-    }
-
-    map = dispatch_data_create_map(content, (const void **)&lenbuf, &length);
-    if (map == NULL) {
-        ERROR("tcp_read_length: map create failed");
-        connection_cancel(connection->connection);
-        return;
-    }
-    dispatch_release(map);
-    bytes_to_read = ((unsigned)(lenbuf[0]) << 8) | ((unsigned)lenbuf[1]);
-    RETAIN_HERE(connection);
-    nw_connection_receive(connection->connection, bytes_to_read, bytes_to_read,
-                          ^(dispatch_data_t new_content, nw_content_context_t __unused new_context,
-                            bool __unused is_complete, nw_error_t new_error) {
-                              if (new_error) {
-                                  char errbuf[512];
-                                  connection_error_to_string(new_error, errbuf, sizeof(errbuf));
-                                  INFO("%p: " PUB_S_SRP, connection, errbuf);
-                                  goto out;
-                              }
-                              tcp_read(connection, bytes_to_read, new_content, new_error);
-                          out:
-                              RELEASE_HERE(connection, comm_finalize);
-                          });
-}
-
-static void
-connection_idle_wakeup_callback(void *context)
-{
-    comm_t *connection = context;
-    ERROR("Connection " PRI_S_SRP " has gone idle", connection->name);
-    connection_cancel(connection->connection);
-}
-
-static void
-tcp_start(comm_t *connection)
-{
-    if (connection->connection == NULL) {
-        return;
-    }
-
-    RETAIN_HERE(connection); // nw_connection_receive callback retains connection
-    nw_connection_receive(connection->connection, 2, 2,
-                          ^(dispatch_data_t content, nw_content_context_t __unused context,
-                            bool is_complete, nw_error_t error) {
-                              if (error) {
-                                  char errbuf[512];
-                                  connection_error_to_string(error, errbuf, sizeof(errbuf));
-                                  INFO("%p: " PUB_S_SRP, connection, errbuf);
-                                  goto out;
-                              }
-
-                              // For TCP connections, is_complete means the other end closed the connection.
-                              if (is_complete || content == NULL) {
-                                  INFO("remote end closed connection.");
-                                  connection_cancel(connection->connection);
-                              } else {
-                                  tcp_read_length(connection, content, error);
-                              }
-                          out:
-                              RELEASE_HERE(connection, comm_finalize);
-                          });
-}
-
-static void
-udp_start(comm_t *connection)
-{
-    if (connection->connection == NULL) {
-        return;
-    }
-
-    // UDP is connectionless; the "connection" is just a placeholder that allows us to reply to the source.
-    // In principle, the five-tuple that is represented by the connection object should die as soon as the
-    // client is done retransmitting, since a later transaction should come from a different source port.
-    // Consequently, we set an idle timer: if we don't see any packets on this five-tuple after twenty seconds,
-    // it's unlikely that we will see any more, so it's time to collect the connection.  If another packet
-    // does come in after this, a new connection will be created. The only risk is that if the cancel comes
-    // after a packet has arrived and been consumed by the nw_connection, but before we've called nw_connection_read,
-    // it will be lost. This should never happen for an existing SRP client, since the longest retry interval
-    // by default is 15 seconds; as the retry intervals get longer, it becomes safer to collect the connection
-    // and allow it to be recreated.
-    if (connection->server) {
-        if (connection->idle_timer == NULL) {
-            connection->idle_timer = ioloop_wakeup_create();
-            if (connection->idle_timer == NULL) {
-                // If we can't set up a timer, drop the connection now.
-                connection_cancel(connection->connection);
-                return;
-            }
-        }
-        ioloop_add_wake_event(connection->idle_timer, connection, connection_idle_wakeup_callback, NULL,
-                              20 * 1000); // 20 seconds (15 seconds is the SRP client retry interval)
-    }
-
-    RETAIN_HERE(connection); // When a read is pending, we have an extra refcount on the connection
-    nw_connection_receive_message(connection->connection,
-                                  ^(dispatch_data_t content, nw_content_context_t __unused context,
-                                    bool __unused is_complete, nw_error_t error) {
-                                      bool proceed = true;
-                                      if (error) {
-                                          char errbuf[512];
-                                          connection_error_to_string(error, errbuf, sizeof(errbuf));
-                                          INFO("%p: " PUB_S_SRP, connection, errbuf);
-                                          goto exit;
-                                      }
-                                      if (content != NULL) {
-                                          proceed = datagram_read(connection, dispatch_data_get_size(content),
-                                                                  content, error);
-                                      }
-                                      if (content == NULL) {
-                                          connection_cancel(connection->connection);
-                                      }
-                                      // Once we have a five-tuple connection, we can't easily get rid of it, so keep
-                                      // reading.
-                                      else if (proceed) {
-                                          udp_start(connection);
-                                      }
-                                  exit:
-                                      RELEASE_HERE(connection, comm_finalize);
-                                  });
-}
-
-static void
-connection_state_changed(comm_t *connection, nw_connection_state_t state, nw_error_t error)
-{
-    char errbuf[512];
-    connection_error_to_string(error, errbuf, sizeof(errbuf));
-
-    if (state == nw_connection_state_ready) {
-        INFO(PRI_S_SRP " state is ready; error = " PUB_S_SRP,
-             connection->name != NULL ? connection->name : "<no name>", errbuf);
-        // Set up a reader.
-        if (connection->tcp_stream) {
-            tcp_start(connection);
-        } else {
-            udp_start(connection);
-        }
-        connection->connection_ready = true;
-        // If there's a write pending, send it now.
-        if (connection->pending_write) {
-            connection_write_now(connection);
-        }
-        if (connection->connected != NULL) {
-            connection->connected(connection, connection->context);
-        }
-    } else if (state == nw_connection_state_failed || state == nw_connection_state_waiting) {
-        // Waiting is equivalent to failed because we are not giving libnetcore enough information to
-        // actually succeed when there is a problem connecting (e.g. "EHOSTUNREACH").
-        INFO(PRI_S_SRP " state is " PUB_S_SRP "; error = " PUB_S_SRP,
-             state == nw_connection_state_failed ? "failed" : "waiting",
-             connection->name != NULL ? connection->name : "<no name>", errbuf);
-        connection_cancel(connection->connection);
-    } else if (state == nw_connection_state_cancelled) {
-        INFO(PRI_S_SRP " state is canceled; error = " PUB_S_SRP,
-             connection->name != NULL ? connection->name : "<no name>", errbuf);
-        if (connection->disconnected != NULL) {
-            connection->disconnected(connection, connection->context, 0);
-        }
-        // This releases the final reference to the connection object, which was held by the nw_connection_t.
-        RELEASE_HERE(connection, comm_finalize);
-    } else {
-        if (error != NULL) {
-            // We can get here if e.g. the TLS handshake fails.
-            nw_connection_cancel(connection->connection);
-        }
-        INFO(PRI_S_SRP " state is %d; error = " PUB_S_SRP,
-             connection->name != NULL ? connection->name : "<no name>", state, errbuf);
-    }
-}
-
-static void
-connection_callback(comm_t *listener, nw_connection_t new_connection)
-{
-    comm_t *connection = calloc(1, sizeof *connection);
-    if (connection == NULL) {
-        ERROR("Unable to receive connection: no memory.");
-        nw_connection_cancel(new_connection);
-        return;
-    }
-
-    connection->connection = new_connection;
-    nw_retain(connection->connection);
-
-    nw_endpoint_t endpoint = nw_connection_copy_endpoint(connection->connection);
-    if (endpoint != NULL) {
-        nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint);
-        if (endpoint_type == nw_endpoint_type_address) {
-            char *port_string = nw_endpoint_copy_port_string(endpoint);
-            char *address_string = nw_endpoint_copy_address_string(endpoint);
-            if (port_string == NULL || address_string == NULL) {
-                ERROR("Unable to get description of new connection.");
-            } else {
-                asprintf(&connection->name, "%s connection from %s/%s", listener->name, address_string, port_string);
-                getipaddr(&connection->address, address_string);
-                if (connection->address.sa.sa_family == AF_INET6) {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(&connection->address.sin6.sin6_addr, rdata_buf);
-                    INFO("parsed connection IPv6 address is: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(&connection->address.sin6.sin6_addr, rdata_buf));
-                } else {
-                    IPv4_ADDR_GEN_SRP(&connection->address.sin.sin_addr, rdata_buf);
-                    INFO("parsed connection IPv4 address is: " PRI_IPv4_ADDR_SRP,
-                         IPv4_ADDR_PARAM_SRP(&connection->address.sin.sin_addr, rdata_buf));
-                }
-            }
-            free(port_string);
-            free(address_string);
-        } else {
-            ERROR("incoming connection of unexpected type %d", endpoint_type);
-            connection->name = nw_connection_copy_description(connection->connection);
-        }
-        nw_release(endpoint);
-    }
-    if (connection->name != NULL) {
-        INFO("Received connection from " PRI_S_SRP, connection->name);
-    } else {
-        ERROR("Unable to get description of new connection.");
-        connection->name = strdup("unidentified");
-    }
-
-    connection->datagram_callback = listener->datagram_callback;
-    connection->tcp_stream = listener->tcp_stream;
-    connection->server = true;
-    connection->context = listener->context;
-    RETAIN_HERE(connection); // The connection state changed handler has a reference to the connection.
-    nw_connection_set_state_changed_handler(connection->connection,
-                                            ^(nw_connection_state_t state, nw_error_t error)
-                                            { connection_state_changed(connection, state, error); });
-    nw_connection_set_queue(connection->connection, ioloop_main_queue);
-    nw_connection_start(connection->connection);
-    if (listener->connected != NULL) {
-        listener->connected(connection, listener->context);
-    }
-}
-
-static void
-listener_finalize(comm_t *listener)
-{
-    if (listener->listener != NULL) {
-        nw_release(listener->listener);
-        listener->listener = NULL;
-    }
-    if (listener->name != NULL) {
-        free(listener->name);
-    }
-    if (listener->parameters) {
-        nw_release(listener->parameters);
-    }
-    if (listener->avoid_ports != NULL) {
-        free(listener->avoid_ports);
-    }
-    if (listener->finalize) {
-        listener->finalize(listener->context);
-    }
-    free(listener);
-}
-
-void
-ioloop_listener_retain_(comm_t *listener, const char *file, int line)
-{
-    RETAIN(listener);
-}
-
-void
-ioloop_listener_release_(comm_t *listener, const char *file, int line)
-{
-    RELEASE(listener, listener_finalize);
-}
-
-void
-ioloop_listener_cancel(comm_t *connection)
-{
-    if (connection->listener != NULL) {
-        nw_listener_cancel(connection->listener);
-        // connection->listener will be released in ioloop_listener_state_changed_handler: nw_listener_state_cancelled.
-    }
-}
-
-static void
-ioloop_listener_state_changed_handler(comm_t *listener, nw_listener_state_t state, nw_error_t error)
-{
-    int i;
-
-#ifdef DEBUG_VERBOSE
-    if (listener->listener == NULL) {
-        if (state == nw_listener_state_cancelled) {
-            INFO("nw_listener gets released before the final nw_listener_state_cancelled event - name: " PRI_S_SRP,
-                 listener->name);
-        } else {
-            ERROR("nw_listener gets released before the listener is canceled - name: " PRI_S_SRP ", state: %d",
-                  listener->name, state);
-        }
-    }
-#endif // DEBUG_VERBOSE
-
-    // Should never happen.
-    if (listener->listener == NULL && state != nw_listener_state_cancelled) {
-        return;
-    }
-
-    if (error != NULL) {
-        char errbuf[512];
-        connection_error_to_string(error, errbuf, sizeof(errbuf));
-        INFO("state changed: " PUB_S_SRP, errbuf);
-        if (listener->listener != NULL) {
-            nw_listener_cancel(listener->listener);
-        }
-    } else {
-        if (state == nw_listener_state_waiting) {
-            INFO("waiting");
-            return;
-        } else if (state == nw_listener_state_failed) {
-            INFO("failed");
-            nw_listener_cancel(listener->listener);
-        } else if (state == nw_listener_state_ready) {
-            INFO("ready");
-            if (listener->avoiding) {
-                listener->listen_port = nw_listener_get_port(listener->listener);
-                if (listener->avoid_ports != NULL) {
-                    for (i = 0; i < listener->num_avoid_ports; i++) {
-                        if (listener->avoid_ports[i] == listener->listen_port) {
-                            INFO("Got port %d, which we are avoiding.",
-                                 listener->listen_port);
-                            listener->avoiding = true;
-                            listener->listen_port = 0;
-                            nw_listener_cancel(listener->listener);
-                            return;
-                        }
-                    }
-                }
-                INFO("Got port %d.", listener->listen_port);
-                listener->avoiding = false;
-                if (listener->ready) {
-                    listener->ready(listener->context, listener->listen_port);
-                }
-            }
-        } else if (state == nw_listener_state_cancelled) {
-            INFO("cancelled");
-            nw_release(listener->listener);
-            listener->listener = NULL;
-            if (listener->avoiding) {
-                listener->listener = nw_listener_create(listener->parameters);
-                if (listener->listener == NULL) {
-                    ERROR("ioloop_listener_state_changed_handler: Unable to recreate listener.");
-                    goto cancel;
-                } else {
-                    RETAIN_HERE(listener);
-                    nw_listener_set_state_changed_handler(listener->listener,
-                                                          ^(nw_listener_state_t ev_state, nw_error_t ev_error) {
-                            ioloop_listener_state_changed_handler(listener, ev_state, ev_error);
-                        });
-                }
-            } else {
-                ;
-            cancel:
-                if (listener->cancel) {
-                    listener->cancel(listener->context);
-                }
-                RELEASE_HERE(listener, listener_finalize);
-            }
-        }
-    }
-}
-
-comm_t *
-ioloop_listener_create(bool stream, bool tls, uint16_t *avoid_ports, int num_avoid_ports,
-                       const addr_t *ip_address, const char *multicast, const char *name,
-                       datagram_callback_t datagram_callback, connect_callback_t connected, cancel_callback_t cancel,
-                       ready_callback_t ready, finalize_callback_t finalize, tls_config_callback_t tls_config,
-                       void *context)
-{
-    comm_t *listener;
-    int family = (ip_address != NULL) ? ip_address->sa.sa_family : AF_UNSPEC;
-    uint16_t port;
-    char portbuf[10];
-    nw_endpoint_t endpoint;
-
-    if (ip_address == NULL) {
-        port = 0;
-    } else {
-        port = (family == AF_INET) ? ntohs(ip_address->sin.sin_port) : ntohs(ip_address->sin6.sin6_port);
-    }
-
-    if (multicast != NULL) {
-        ERROR("ioloop_setup_listener: multicast not supported.");
-        return NULL;
-    }
-
-    if (datagram_callback == NULL) {
-        ERROR("ioloop_setup: no datagram callback provided.");
-        return NULL;
-    }
-
-    snprintf(portbuf, sizeof(portbuf), "%d", port);
-    listener = calloc(1, sizeof(*listener));
-    if (listener == NULL) {
-        if (ip_address == NULL) {
-            ERROR("No memory for listener on <NULL>#%d", port);
-        } else if (family == AF_INET) {
-            IPv4_ADDR_GEN_SRP(&ip_address->sin.sin_addr.s_addr, ipv4_addr_buf);
-            ERROR("No memory for listener on " PRI_IPv4_ADDR_SRP "#%d",
-                  IPv4_ADDR_PARAM_SRP(&ip_address->sin.sin_addr.s_addr, ipv4_addr_buf), port);
-        } else if (family == AF_INET6) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(ip_address->sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-            ERROR("No memory for listener on " PRI_SEGMENTED_IPv6_ADDR_SRP "#%d",
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(ip_address->sin6.sin6_addr.s6_addr, ipv6_addr_buf), port);
-        } else {
-            ERROR("No memory for listener on <family address other than AF_INET or AF_INET6: %d>#%d", family, port);
-        }
-        return NULL;
-    }
-    if (avoid_ports != NULL) {
-        listener->avoid_ports = malloc(num_avoid_ports * sizeof(uint16_t));
-        if (listener->avoid_ports == NULL) {
-            if (ip_address == NULL) {
-                ERROR("No memory for listener avoid_ports on <NULL>#%d", port);
-            } else if (family == AF_INET) {
-                IPv4_ADDR_GEN_SRP(&ip_address->sin.sin_addr.s_addr, ipv4_addr_buf);
-                ERROR("No memory for listener avoid_ports on " PRI_IPv4_ADDR_SRP "#%d",
-                      IPv4_ADDR_PARAM_SRP(&ip_address->sin.sin_addr.s_addr, ipv4_addr_buf), port);
-            } else if (family == AF_INET6) {
-                SEGMENTED_IPv6_ADDR_GEN_SRP(ip_address->sin6.sin6_addr.s6_addr, ipv6_addr_buf);
-                ERROR("No memory for listener avoid_ports on " PRI_SEGMENTED_IPv6_ADDR_SRP "#%d",
-                      SEGMENTED_IPv6_ADDR_PARAM_SRP(ip_address->sin6.sin6_addr.s6_addr, ipv6_addr_buf), port);
-            } else {
-                ERROR("No memory for listener avoid_ports on <family address other than AF_INET or AF_INET6: %d>#%d",
-                      family, port);
-            }
-            free(listener);
-            return NULL;
-        }
-        listener->num_avoid_ports = num_avoid_ports;
-        listener->avoiding = true;
-    }
-    RETAIN_HERE(listener);
-    if (port == 0) {
-        endpoint = NULL;
-        // Even though we don't have any ports to avoid, we still want the "avoiding" behavior in this case, since that
-        // is what triggers a call to the ready handler, which passes the port number that we got to it.
-        listener->avoiding = true;
-    } else {
-        listener->listen_port = port;
-        char ip_address_str[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-        if (ip_address == NULL || family == AF_UNSPEC) {
-            if (family == AF_INET) {
-                snprintf(ip_address_str, sizeof(ip_address_str), "0.0.0.0");
-            } else {
-                // AF_INET6 or AF_UNSPEC
-                snprintf(ip_address_str, sizeof(ip_address_str), "::");
-            }
-        } else {
-            inet_ntop(family, ip_address->sa.sa_data, ip_address_str, sizeof(ip_address_str));
-        }
-        endpoint = nw_endpoint_create_host(ip_address_str, portbuf);
-        if (endpoint == NULL) {
-            ERROR("No memory for listener endpoint.");
-            RELEASE_HERE(listener, listener_finalize);
-            return NULL;
-        }
-    }
-
-    if (stream) {
-        nw_parameters_configure_protocol_block_t configure_tls_block = NW_PARAMETERS_DISABLE_PROTOCOL;
-        if (tls && tls_config != NULL) {
-            configure_tls_block = ^(nw_protocol_options_t tls_options) {
-                tls_config_context_t tls_context = {tls_options, ioloop_main_queue};
-                tls_config((void *)&tls_context);
-            };
-        }
-
-        listener->parameters = nw_parameters_create_secure_tcp(configure_tls_block, NW_PARAMETERS_DEFAULT_CONFIGURATION);
-    } else {
-        if (tls) {
-            ERROR("DTLS support not implemented.");
-            nw_release(endpoint);
-            RELEASE_HERE(listener, listener_finalize);
-            return NULL;
-        }
-        listener->parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL,
-                                                               NW_PARAMETERS_DEFAULT_CONFIGURATION);
-    }
-    if (listener->parameters == NULL) {
-        ERROR("No memory for listener parameters.");
-        nw_release(endpoint);
-        RELEASE_HERE(listener, listener_finalize);
-        return NULL;
-    }
-
-    if (endpoint != NULL) {
-        nw_parameters_set_local_endpoint(listener->parameters, endpoint);
-        nw_release(endpoint);
-    }
-
-    // Set SO_REUSEADDR.
-    nw_parameters_set_reuse_local_address(listener->parameters, true);
-
-    // Create the nw_listener_t.
-    listener->listener = nw_listener_create(listener->parameters);
-    if (listener->listener == NULL) {
-        ERROR("no memory for nw_listener object");
-        RELEASE_HERE(listener, listener_finalize);
-        return NULL;
-    }
-    nw_listener_set_new_connection_handler(listener->listener,
-                                           ^(nw_connection_t connection) { connection_callback(listener, connection); }
-                                           );
-
-    RETAIN_HERE(listener); // for the nw_listener_t
-    nw_listener_set_state_changed_handler(listener->listener, ^(nw_listener_state_t state, nw_error_t error) {
-            ioloop_listener_state_changed_handler(listener, state, error);
-        });
-
-    listener->name = strdup(name);
-    listener->datagram_callback = datagram_callback;
-    listener->cancel = cancel;
-    listener->ready = ready;
-    listener->finalize = finalize;
-    listener->context = context;
-    listener->connected = connected;
-    listener->tcp_stream = stream;
-
-    nw_listener_set_queue(listener->listener, ioloop_main_queue);
-    nw_listener_start(listener->listener);
-    // Listener has one refcount
-    return listener;
-}
-
-comm_t *
-ioloop_connection_create(addr_t *NONNULL remote_address, bool tls, bool stream, bool stable, bool opportunistic,
-                         datagram_callback_t datagram_callback, connect_callback_t connected,
-                         disconnect_callback_t disconnected, finalize_callback_t finalize, void *context)
-{
-    comm_t *connection;
-    char portbuf[10];
-    nw_parameters_t parameters;
-    nw_endpoint_t endpoint;
-    char addrbuf[INET6_ADDRSTRLEN];
-
-    inet_ntop(remote_address->sa.sa_family, (remote_address->sa.sa_family == AF_INET
-                                             ? (void *)&remote_address->sin.sin_addr
-                                             : (void *)&remote_address->sin6.sin6_addr), addrbuf, sizeof addrbuf);
-    snprintf(portbuf, sizeof(portbuf), "%d", (remote_address->sa.sa_family == AF_INET
-                            ? ntohs(remote_address->sin.sin_port)
-                            : ntohs(remote_address->sin6.sin6_port)));
-    connection = calloc(1, sizeof(*connection));
-    if (connection == NULL) {
-        ERROR("No memory for connection");
-        return NULL;
-    }
-    // If we don't release this because of an error, this is the caller's reference to the comm_t.
-    RETAIN_HERE(connection);
-    endpoint = nw_endpoint_create_host(addrbuf, portbuf);
-    if (endpoint == NULL) {
-        ERROR("No memory for connection endpoint.");
-        RELEASE_HERE(connection, comm_finalize);
-        return NULL;
-    }
-
-    if (stream) {
-        nw_parameters_configure_protocol_block_t configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL;
-        if (tls) {
-            // This sets up a block that's called when we get a TLS connection and want to verify
-            // the cert.   Right now we only support opportunistic security, which means we have
-            // no way to validate the cert.   Future work: add support for validating the cert
-            // using a TLSA record if one is present.
-            configure_tls = ^(nw_protocol_options_t tls_options) {
-                sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
-                sec_protocol_options_set_verify_block(sec_options,
-                                                      ^(sec_protocol_metadata_t metadata, sec_trust_t trust_ref,
-                                                        sec_protocol_verify_complete_t complete) {
-                                                          (void) metadata;
-                                                          (void) trust_ref;
-                                                          const bool valid = true;
-                                                          complete(valid);
-                                                      }, ioloop_main_queue);
-                nw_release(sec_options);
-            };
-        }
-
-        parameters = nw_parameters_create_secure_tcp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION);
-    } else {
-        if (tls) {
-            ERROR("DTLS support not implemented.");
-            nw_release(endpoint);
-            RELEASE_HERE(connection, comm_finalize);
-            return NULL;
-        }
-        parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL,
-                                                     NW_PARAMETERS_DEFAULT_CONFIGURATION);
-    }
-    if (parameters == NULL) {
-        ERROR("No memory for connection parameters.");
-        nw_release(endpoint);
-        RELEASE_HERE(connection, comm_finalize);
-        return NULL;
-    }
-
-    nw_protocol_stack_t protocol_stack = nw_parameters_copy_default_protocol_stack(parameters);
-
-    // If user asked for a stable address, set that option.
-    if (stable) {
-        nw_protocol_options_t ip_options = nw_protocol_stack_copy_internet_protocol(protocol_stack);
-        nw_ip_options_set_local_address_preference(ip_options, nw_ip_local_address_preference_stable);
-        nw_release(ip_options);
-    }
-
-    // Only set TCP options for TCP connections.
-    if (stream) {
-        nw_protocol_options_t tcp_options = nw_protocol_stack_copy_transport_protocol(protocol_stack);
-        nw_tcp_options_set_no_delay(tcp_options, true);
-        nw_tcp_options_set_enable_keepalive(tcp_options, true);
-        nw_release(tcp_options);
-        nw_release(protocol_stack);
-    }
-
-    connection->name = strdup(addrbuf);
-
-    // Create the nw_connection_t.
-    connection->connection = nw_connection_create(endpoint, parameters);
-    nw_release(endpoint);
-    nw_release(parameters);
-    if (connection->connection == NULL) {
-        ERROR("no memory for nw_connection object");
-        RELEASE_HERE(connection, comm_finalize);
-        return NULL;
-    }
-
-    connection->datagram_callback = datagram_callback;
-    connection->connected = connected;
-    connection->disconnected = disconnected;
-    connection->finalize = finalize;
-    connection->tcp_stream = stream;
-    connection->opportunistic = opportunistic;
-    connection->context = context;
-    RETAIN_HERE(connection); // The connection state changed handler has a reference to the connection.
-    nw_connection_set_state_changed_handler(connection->connection,
-                                            ^(nw_connection_state_t state, nw_error_t error)
-                                            { connection_state_changed(connection, state, error); });
-    nw_connection_set_queue(connection->connection, ioloop_main_queue);
-    nw_connection_start(connection->connection);
-    return connection;
-}
-
-static void
-subproc_finalize(subproc_t *subproc)
-{
-    int i;
-    for (i = 0; i < subproc->argc; i++) {
-        if (subproc->argv[i] != NULL) {
-            free(subproc->argv[i]);
-            subproc->argv[i] = NULL;
-        }
-    }
-    if (subproc->dispatch_source != NULL) {
-        dispatch_release(subproc->dispatch_source);
-    }
-    if (subproc->output_fd != NULL) {
-        ioloop_file_descriptor_release(subproc->output_fd);
-    }
-    if (subproc->finalize != NULL) {
-        subproc->finalize(subproc->context);
-    }
-    free(subproc);
-}
-
-static void subproc_cancel(void *context)
-{
-    subproc_t *subproc = context;
-    subproc->dispatch_source = NULL;
-    RELEASE_HERE(subproc, subproc_finalize);
-}
-
-static void
-subproc_event(void *context)
-{
-    subproc_t *subproc = context;
-    pid_t pid;
-    int status;
-
-    pid = waitpid(subproc->pid, &status, WNOHANG);
-    if (pid <= 0) {
-        return;
-    }
-    subproc->callback(subproc, status, NULL);
-    if (!WIFSTOPPED(status)) {
-        dispatch_source_cancel(subproc->dispatch_source);
-    }
-}
-
-static void
-subproc_output_finalize(void *context)
-{
-    subproc_t *subproc = context;
-    if (subproc->output_fd) {
-        subproc->output_fd = NULL;
-    }
-}
-
-void
-ioloop_subproc_release_(subproc_t *subproc, const char *file, int line)
-{
-    RELEASE(subproc, subproc_finalize);
-}
-
-// Invoke the specified executable with the specified arguments.   Call callback when it exits.
-// All failures are reported through the callback.
-subproc_t *
-ioloop_subproc(const char *exepath, char *NULLABLE *argv, int argc,
-               subproc_callback_t callback, io_callback_t output_callback, void *context)
-{
-    subproc_t *subproc;
-    int i, rv;
-    posix_spawn_file_actions_t actions;
-    posix_spawnattr_t attrs;
-
-    if (callback == NULL) {
-        ERROR("ioloop_add_wake_event called with null callback");
-        return NULL;
-    }
-
-    if (argc > MAX_SUBPROC_ARGS) {
-        callback(NULL, 0, "too many subproc args");
-        return NULL;
-    }
-
-    subproc = calloc(1, sizeof *subproc);
-    if (subproc == NULL) {
-        callback(NULL, 0, "out of memory");
-        return NULL;
-    }
-    RETAIN_HERE(subproc);
-    if (output_callback != NULL) {
-        rv = pipe(subproc->pipe_fds);
-        if (rv < 0) {
-            callback(NULL, 0, "unable to create pipe.");
-            RELEASE_HERE(subproc, subproc_finalize);
-            return NULL;
-        }
-        subproc->output_fd = ioloop_file_descriptor_create(subproc->pipe_fds[0], subproc, subproc_output_finalize);
-        if (subproc->output_fd == NULL) {
-            callback(NULL, 0, "out of memory.");
-            close(subproc->pipe_fds[0]);
-            close(subproc->pipe_fds[1]);
-            RELEASE_HERE(subproc, subproc_finalize);
-            return NULL;
-        }
-    }
-
-    subproc->argv[0] = strdup(exepath);
-    if (subproc->argv[0] == NULL) {
-        RELEASE_HERE(subproc, subproc_finalize);
-        callback(NULL, 0, "out of memory");
-        return NULL;
-    }
-    subproc->argc++;
-    for (i = 0; i < argc; i++) {
-        subproc->argv[i + 1] = strdup(argv[i]);
-        if (subproc->argv[i + 1] == NULL) {
-            RELEASE_HERE(subproc, subproc_finalize);
-            callback(NULL, 0, "out of memory");
-            return NULL;
-        }
-        subproc->argc++;
-    }
-
-    // Set up for posix_spawn
-    posix_spawn_file_actions_init(&actions);
-    if (output_callback != NULL) {
-        posix_spawn_file_actions_adddup2(&actions, subproc->pipe_fds[1], STDOUT_FILENO);
-        posix_spawn_file_actions_addclose(&actions, subproc->pipe_fds[0]);
-        posix_spawn_file_actions_addclose(&actions, subproc->pipe_fds[1]);
-    }
-    posix_spawnattr_init(&attrs);
-    extern char **environ;
-    rv = posix_spawn(&subproc->pid, exepath, &actions, &attrs, subproc->argv, environ);
-    posix_spawn_file_actions_destroy(&actions);
-    posix_spawnattr_destroy(&attrs);
-    if (rv < 0) {
-        ERROR("posix_spawn failed for " PUB_S_SRP ": " PUB_S_SRP, subproc->argv[0], strerror(errno));
-        callback(subproc, 0, strerror(errno));
-        RELEASE_HERE(subproc, subproc_finalize);
-        return NULL;
-    }
-    subproc->callback = callback;
-    subproc->context = context;
-
-    subproc->dispatch_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, subproc->pid, DISPATCH_PROC_EXIT,
-                                                      ioloop_main_queue);
-    if (subproc->dispatch_source == NULL) {
-        ERROR("dispatch_source_create failed in ioloop_add_wake_event().");
-        return false;
-    }
-    dispatch_retain(subproc->dispatch_source);
-    dispatch_source_set_event_handler_f(subproc->dispatch_source, subproc_event);
-    dispatch_source_set_cancel_handler_f(subproc->dispatch_source, subproc_cancel);
-    dispatch_set_context(subproc->dispatch_source, subproc);
-    dispatch_activate(subproc->dispatch_source);
-    RETAIN_HERE(subproc); // Dispatch has a reference
-
-    // Now that we have a viable subprocess, add the reader callback.
-    if (output_callback != NULL && subproc->output_fd != NULL) {
-        close(subproc->pipe_fds[1]);
-        ioloop_add_reader(subproc->output_fd, output_callback);
-    }
-    return subproc;
-}
-
-void
-ioloop_dnssd_txn_cancel(dnssd_txn_t *txn)
-{
-    if (txn->sdref != NULL) {
-        DNSServiceRefDeallocate(txn->sdref);
-        txn->sdref = NULL;
-    } else {
-        INFO("dead transaction.");
-    }
-}
-
-static void
-dnssd_txn_finalize(dnssd_txn_t *txn)
-{
-    if (txn->sdref != NULL) {
-        ioloop_dnssd_txn_cancel(txn);
-    }
-    if (txn->finalize_callback) {
-        txn->finalize_callback(txn->context);
-    }
-    free(txn);
-}
-
-void
-ioloop_dnssd_txn_retain_(dnssd_txn_t *dnssd_txn, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(dnssd_txn);
-}
-
-void
-ioloop_dnssd_txn_release_(dnssd_txn_t *dnssd_txn, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(dnssd_txn, dnssd_txn_finalize);
-}
-
-dnssd_txn_t *
-ioloop_dnssd_txn_add_(DNSServiceRef ref, void *context, dnssd_txn_finalize_callback_t finalize_callback,
-                      dnssd_txn_failure_callback_t failure_callback,
-                      const char *file, int line)
-{
-    dnssd_txn_t *txn = calloc(1, sizeof(*txn));
-    (void)file; (void)line;
-    (void)failure_callback;
-
-    if (txn != NULL) {
-        RETAIN(txn);
-        txn->sdref = ref;
-        txn->context = context;
-        txn->finalize_callback = finalize_callback;
-        DNSServiceSetDispatchQueue(ref, ioloop_main_queue);
-    }
-    return txn;
-}
-
-void
-ioloop_dnssd_txn_set_aux_pointer(dnssd_txn_t *NONNULL txn, void *aux_pointer)
-{
-    txn->aux_pointer = aux_pointer;
-}
-
-void *
-ioloop_dnssd_txn_get_aux_pointer(dnssd_txn_t *NONNULL txn)
-{
-    return txn->aux_pointer;
-}
-
-void *
-ioloop_dnssd_txn_get_context(dnssd_txn_t *NONNULL txn)
-{
-    return txn->context;
-}
-
-
-static void
-file_descriptor_finalize(void *context)
-{
-    io_t *file_descriptor = context;
-    if (file_descriptor->ref_count == 0) {
-        if (file_descriptor->finalize) {
-            file_descriptor->finalize(file_descriptor->context);
-        }
-        free(file_descriptor);
-    }
-}
-
-void
-ioloop_file_descriptor_retain_(io_t *file_descriptor, const char *file, int line)
-{
-    (void)file; (void)line;
-    RETAIN(file_descriptor);
-}
-
-void
-ioloop_file_descriptor_release_(io_t *file_descriptor, const char *file, int line)
-{
-    (void)file; (void)line;
-    RELEASE(file_descriptor, file_descriptor_finalize);
-}
-
-io_t *
-ioloop_file_descriptor_create_(int fd, void *context, finalize_callback_t finalize, const char *file, int line)
-{
-    io_t *ret;
-    ret = calloc(1, sizeof(*ret));
-    if (ret) {
-        ret->fd = fd;
-        ret->context = context;
-        ret->finalize = finalize;
-        RETAIN(ret);
-    }
-    return ret;
-}
-
-static void
-ioloop_read_cancel(void *context)
-{
-    io_t *io = context;
-
-    if (io->read_source != NULL) {
-        dispatch_release(io->read_source);
-        io->read_source = NULL;
-        // Release the reference count that dispatch was holding.
-        RELEASE_HERE(io, file_descriptor_finalize);
-    }
-}
-
-static void
-ioloop_read_event(void *context)
-{
-    io_t *io = context;
-
-    if (io->read_callback != NULL) {
-        io->read_callback(io, io->context);
-    }
-}
-
-void
-ioloop_close(io_t *io)
-{
-    if (io->read_source != NULL) {
-        dispatch_cancel(io->read_source);
-    }
-    if (io->write_source != NULL) {
-        dispatch_cancel(io->write_source);
-    }
-    io->fd = -1;
-}
-
-void
-ioloop_add_reader(io_t *NONNULL io, io_callback_t NONNULL callback)
-{
-    io->read_callback = callback;
-    if (io->read_source == NULL) {
-        io->read_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, io->fd, 0, ioloop_main_queue);
-    }
-    if (io->read_source == NULL) {
-        ERROR("dispatch_source_create: unable to create read dispatch source.");
-        return;
-    }
-    dispatch_source_set_event_handler_f(io->read_source, ioloop_read_event);
-    dispatch_source_set_cancel_handler_f(io->read_source, ioloop_read_cancel);
-    dispatch_set_context(io->read_source, io);
-    RETAIN_HERE(io); // Dispatch will hold a reference.
-    dispatch_resume(io->read_source);
-}
-
-void
-ioloop_run_async(async_callback_t callback, void *context)
-{
-    dispatch_async(ioloop_main_queue, ^{
-            callback(context);
-        });
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/nat64-macos.c b/ServiceRegistration/nat64-macos.c
deleted file mode 100644
index 39730c2..0000000
--- a/ServiceRegistration/nat64-macos.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* nat64-macos.c
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "nat64-macos.h"
-
-#include "interface-monitor-macos.h"
-#include "srp-log.h"
-#include <CoreUtils/CoreUtils.h>
-#include <mdns/pf.h>
-#include <mdns/system.h>
-
-static struct sockaddr_in nat64_primary_ipv4;
-static struct in6_addr nat64_prefix;
-static ifmon_t nat64_ifmon = NULL;
-static bool nat64_prefix_is_set = false;
-static bool nat64_active = false;
-
-static void
-nat64_reset(void)
-{
-    OSStatus err;
-    if (nat64_primary_ipv4.sin_family == AF_INET) {
-        err = mdns_pf_set_thread_nat64_rules(nat64_prefix.s6_addr, 64, nat64_primary_ipv4.sin_addr.s_addr);
-        if (!err) {
-            mdns_system_set_ipv4_forwarding(true);
-            mdns_system_set_ipv6_forwarding(true);
-            nat64_active = true;
-        } else {
-            ERROR("nat64_reset: failed to set NAT64 rules: %ld.", (long)err);
-        }
-    } else {
-        err = mdns_pf_delete_thread_rules();
-        if (err) {
-            ERROR("nat64_reset: failed to delete NAT64 rules: %ld.", (long)err);
-        }
-        mdns_system_set_ipv4_forwarding(false);
-        mdns_system_set_ipv6_forwarding(false);
-    }
-}
-
-void
-nat64_startup(const dispatch_queue_t queue)
-{
-    nat64_primary_ipv4.sin_family = AF_UNSPEC;
-    nat64_ifmon = ifmon_create(queue);
-    dispatch_block_t handler = ^{
-        const sockaddr_ip new_primary = ifmon_get_primary_ipv4_address(nat64_ifmon);
-        if (SockAddrCompareAddr(&nat64_primary_ipv4, &new_primary.v4) != 0) {
-            nat64_primary_ipv4 = new_primary.v4;
-            if (nat64_prefix_is_set) {
-                nat64_reset();
-            }
-        }
-    };
-    ifmon_set_primary_ip_changed_handler(nat64_ifmon, handler);
-    ifmon_activate(nat64_ifmon, handler);
-}
-
-void
-nat64_set_ula_prefix(const struct in6_addr *const ula_prefix)
-{
-    bool changed;
-    if (!nat64_prefix_is_set || (memcmp(nat64_prefix.s6_addr, ula_prefix->s6_addr, 5) != 0)) {
-        changed = true;
-    } else {
-        changed = false;
-    }
-    if (changed) {
-        // Set the 48-bit ULA prefix (0xfd + global identifier), then set the next 16 bits to all-ones to make the
-        // 64-bit IPv6 prefix.
-        memset(&nat64_prefix, 0, sizeof(nat64_prefix));
-        memcpy(&nat64_prefix.s6_addr[0], ula_prefix->s6_addr, 6);
-        memset(&nat64_prefix.s6_addr[6], 0xFF, 2);
-        nat64_prefix_is_set = true;
-        if (nat64_primary_ipv4.sin_family == AF_INET) {
-            nat64_reset();
-        }
-    }
-}
-
-const struct in6_addr *
-nat64_get_ipv6_prefix(void)
-{
-    return &nat64_prefix;
-}
-
-bool
-nat64_is_active(void)
-{
-    return nat64_active;
-}
diff --git a/ServiceRegistration/nat64-macos.h b/ServiceRegistration/nat64-macos.h
deleted file mode 100644
index ecfc96d..0000000
--- a/ServiceRegistration/nat64-macos.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* nat64-macos.h
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __NAT64_MACOS_H__
-#define __NAT64_MACOS_H__
-
-#include <CoreUtils/CoreUtils.h>
-#include <dispatch/dispatch.h>
-
-CU_ASSUME_NONNULL_BEGIN
-
-void
-nat64_startup(dispatch_queue_t queue);
-
-void
-nat64_set_ula_prefix(const struct in6_addr *prefix);
-
-const struct in6_addr *
-nat64_get_ipv6_prefix(void);
-
-bool
-nat64_is_active(void);
-
-CU_ASSUME_NONNULL_END
-
-#endif // __NAT64_MACOS_H__
diff --git a/ServiceRegistration/posix.c b/ServiceRegistration/posix.c
deleted file mode 100644
index fb750ce..0000000
--- a/ServiceRegistration/posix.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/* posix.c
- *
- * Copyright (c) 2018-2021 Apple, 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
- *
- *     https://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.
- *
- * utility functions common to all posix implementations (e.g., MacOS, Linux).
- */
-
-#define _GNU_SOURCE
-
-#include <netinet/in.h>
-#include <net/if.h>
-#ifndef LINUX
-#include <netinet/in_var.h>
-#include <net/if_dl.h>
-#endif
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <ifaddrs.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
-#include <arpa/inet.h>
-#include "dns_sd.h"
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-
-interface_address_state_t *interface_addresses;
-
-bool
-ioloop_map_interface_addresses(const char *ifname, void *context, interface_callback_t callback)
-{
-    return ioloop_map_interface_addresses_here(&interface_addresses, ifname, context, callback);
-}
-
-bool
-ioloop_map_interface_addresses_here_(interface_address_state_t **here, const char *ifname, void *context,
-                                     interface_callback_t callback, const char *file, int line)
-{
-    struct ifaddrs *ifaddrs, *ifp;
-    interface_address_state_t *kept_ifaddrs = NULL, **ki_end = &kept_ifaddrs;
-    interface_address_state_t *new_ifaddrs = NULL, **ni_end = &new_ifaddrs;
-    interface_address_state_t **ip, *nif;
-
-    if (getifaddrs(&ifaddrs) < 0) {
-        ERROR("getifaddrs failed: " PUB_S_SRP, strerror(errno));
-        return false;
-    }
-
-    for (ifp = ifaddrs; ifp; ifp = ifp->ifa_next) {
-        bool remove = false;
-        bool keep = true;
-
-        // It is impossible to have an interface without interface name.
-        if (ifp->ifa_name == NULL) {
-            continue;
-        }
-        if (ifname != NULL && strcmp(ifname, ifp->ifa_name)) {
-            continue;
-        }
-
-#ifndef LINUX
-        // Check for temporary addresses, etc.
-        if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_INET6) {
-            struct in6_ifreq ifreq;
-            int sock;
-            size_t len;
-            len = strlen(ifp->ifa_name);
-            if (len >= sizeof(ifreq.ifr_name)) {
-                len = sizeof(ifreq.ifr_name) - 1;
-            }
-            memcpy(ifreq.ifr_name, ifp->ifa_name, len);
-            ifreq.ifr_name[len] = 0;
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-                ERROR("socket(AF_INET6, SOCK_DGRAM): " PUB_S_SRP, strerror(errno));
-                continue;
-            }
-            memcpy(&ifreq.ifr_addr, ifp->ifa_addr, sizeof ifreq.ifr_addr);
-            if (ioctl(sock, SIOCGIFAFLAG_IN6, &ifreq) < 0) {
-                ERROR("ioctl(SIOCGIFAFLAG_IN6): " PUB_S_SRP, strerror(errno));
-                close(sock);
-                continue;
-            }
-            int flags = ifreq.ifr_ifru.ifru_flags6;
-            if (flags & (IN6_IFF_ANYCAST | IN6_IFF_TENTATIVE | IN6_IFF_DETACHED | IN6_IFF_TEMPORARY)) {
-                keep = false;
-            }
-            if (flags & IN6_IFF_DEPRECATED) {
-                remove = true;
-            }
-            close(sock);
-        }
-
-#ifdef DEBUG_AF_LINK
-        if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family != AF_INET && ifp->ifa_addr->sa_family != AF_INET6) {
-            struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifp->ifa_addr;
-            const uint8_t *addr = (uint8_t *)LLADDR(sdl);
-            INFO("%.*s index %d alen %d dlen %d SDL: %02x:%02x:%02x:%02x:%02x:%02x",
-                 sdl->sdl_nlen, sdl->sdl_data, sdl->sdl_index, sdl->sdl_alen, sdl->sdl_slen,
-                 addr[0],  addr[1],  addr[2], addr[3],  addr[4],  addr[5]);
-        }
-#endif // DEBUG_AF_LINK
-#endif // LINUX
-
-        // Is this an interface address we can use?
-        if (keep && ifp->ifa_addr != NULL && (
-#ifndef LINUX
-                ifp->ifa_addr->sa_family == AF_LINK ||
-#endif
-             ((ifp->ifa_addr->sa_family == AF_INET6 || ifp->ifa_addr->sa_family == AF_INET) && ifp->ifa_netmask != NULL)) &&
-            (ifp->ifa_flags & IFF_UP))
-        {
-            keep = false;
-            for (ip = here; *ip != NULL; ) {
-                interface_address_state_t *ia = *ip;
-                // Same interface and address?
-                if (!remove && !strcmp(ia->name, ifp->ifa_name) &&
-                    ifp->ifa_addr->sa_family == ia->addr.sa.sa_family &&
-                    (
-#ifndef LINUX
-                        ifp->ifa_addr->sa_family == AF_LINK ||
-#endif
-                     (((ifp->ifa_addr->sa_family == AF_INET &&
-                        ((struct sockaddr_in *)ifp->ifa_addr)->sin_addr.s_addr == ia->addr.sin.sin_addr.s_addr) ||
-                       (ifp->ifa_addr->sa_family == AF_INET6 &&
-                        !memcmp(&((struct sockaddr_in6 *)ifp->ifa_addr)->sin6_addr,
-                                &ia->addr.sin6.sin6_addr, sizeof ia->addr.sin6.sin6_addr))) &&
-                      ((ifp->ifa_netmask->sa_family == AF_INET &&
-                        ((struct sockaddr_in *)ifp->ifa_netmask)->sin_addr.s_addr == ia->mask.sin.sin_addr.s_addr) ||
-                       (ifp->ifa_netmask->sa_family == AF_INET6 &&
-                        !memcmp(&((struct sockaddr_in6 *)ifp->ifa_netmask)->sin6_addr,
-                                &ia->mask.sin6.sin6_addr, sizeof ia->mask.sin6.sin6_addr))))))
-                {
-                    *ip = ia->next;
-                    *ki_end = ia;
-                    ki_end = &ia->next;
-                    ia->next = NULL;
-                    keep = true;
-                    break;
-                } else {
-                    ip = &ia->next;
-                }
-            }
-            // If keep is false, this is a new interface/address.
-            if (!keep) {
-                size_t len = strlen(ifp->ifa_name);
-#ifdef MALLOC_DEBUG_LOGGING
-                nif = debug_calloc(1, len + 1 + sizeof(*nif), file, line);
-#else
-                (void)file;
-                (void)line;
-                nif = calloc(1, len + 1 + sizeof(*nif));
-#endif
-                // We don't have a way to fix nif being null; what this means is that we don't detect a new
-                // interface address.
-                if (nif != NULL) {
-                    nif->name = (char *)(nif + 1);
-                    memcpy(nif->name, ifp->ifa_name, len);
-                    nif->name[len] = 0;
-                    if (ifp->ifa_addr->sa_family == AF_INET) {
-                        nif->addr.sin = *((struct sockaddr_in *)ifp->ifa_addr);
-                        nif->mask.sin = *((struct sockaddr_in *)ifp->ifa_netmask);
-
-                        IPv4_ADDR_GEN_SRP(&nif->addr.sin.sin_addr.s_addr, __new_interface_ipv4_addr);
-                        INFO("new IPv4 interface address added - ifname: " PUB_S_SRP
-                             ", addr: " PRI_IPv4_ADDR_SRP, nif->name,
-                             IPv4_ADDR_PARAM_SRP(&nif->addr.sin.sin_addr.s_addr, __new_interface_ipv4_addr));
-                    } else if (ifp->ifa_addr->sa_family == AF_INET6) {
-                        nif->addr.sin6 = *((struct sockaddr_in6 *)ifp->ifa_addr);
-                        nif->mask.sin6 = *((struct sockaddr_in6 *)ifp->ifa_netmask);
-
-                        SEGMENTED_IPv6_ADDR_GEN_SRP(nif->addr.sin6.sin6_addr.s6_addr, __new_interface_ipv6_addr);
-                        INFO("new IPv6 interface address added - ifname: " PUB_S_SRP
-                             ", addr: " PRI_SEGMENTED_IPv6_ADDR_SRP, nif->name,
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(nif->addr.sin6.sin6_addr.s6_addr,
-                                                           __new_interface_ipv6_addr));
-                    } else {
-#ifndef LINUX
-                        struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifp->ifa_addr;
-                        memset(&nif->mask, 0, sizeof(nif->mask));
-                        if (sdl->sdl_alen == 6) {
-                            nif->addr.ether_addr.len = 6;
-                            memcpy(nif->addr.ether_addr.addr, LLADDR(sdl), 6);
-                        } else {
-                            nif->addr.ether_addr.len = 0;
-                        }
-                        nif->addr.ether_addr.index = sdl->sdl_index;
-                        nif->addr.ether_addr.family = AF_LINK;
-#endif // LINUX
-                    }
-                    nif->flags = ifp->ifa_flags;
-                    *ni_end = nif;
-                    ni_end = &nif->next;
-                }
-            }
-        }
-    }
-
-#ifndef LINUX
-    // Get rid of any link-layer addresses for which there is no other address on that interface
-    // This is clunky, but we can't assume that the AF_LINK address will come after some other
-    // address, so there's no more efficient way to do this that I can think of.
-    for (ip = &new_ifaddrs; *ip; ) {
-        if ((*ip)->addr.sa.sa_family == AF_LINK) {
-            bool drop = true;
-            for (nif = new_ifaddrs; nif; nif = nif->next) {
-                if (nif != *ip && !strcmp(nif->name, (*ip)->name)) {
-                    drop = false;
-                    break;
-                }
-            }
-            if (drop) {
-                nif = *ip;
-                *ip = nif->next;
-                free(nif);
-            } else {
-                ip = &(*ip)->next;
-            }
-        } else {
-            ip = &(*ip)->next;
-        }
-    }
-#endif // LINUX
-
-#ifdef TOO_MUCH_INFO
-    char infobuf[1000];
-    int i;
-    for (i = 0; i < 3; i++) {
-        char *infop = infobuf;
-        int len, lim = sizeof infobuf;
-        const char *title;
-        switch(i) {
-        case 0:
-            title = "deleted";
-            nif = *here;
-            break;
-        case 1:
-            title = "   kept";
-            nif = kept_ifaddrs;
-            break;
-        case 2:
-            title = "    new";
-            nif = new_ifaddrs;
-            break;
-        default:
-            abort();
-        }
-        for (; nif; nif = nif->next) {
-            snprintf(infop, lim, " %p (", nif);
-            len = (int)strlen(infop);
-            lim -= len;
-            infop += len;
-            inet_ntop(AF_INET6, &nif->addr.sin6.sin6_addr, infop, lim);
-            len = (int)strlen(infop);
-            lim -= len;
-            infop += len;
-            if (lim > 1) {
-                *infop++ = ')';
-                lim--;
-            }
-        }
-        *infop = 0;
-        INFO(PUB_S_SRP ":" PUB_S_SRP, title, infobuf);
-    }
-#endif
-
-    // Report and free deleted interface addresses...
-    for (ip = here; *ip; ) {
-        nif = *ip;
-        *ip = nif->next;
-        if (callback != NULL) {
-            callback(context, nif->name, &nif->addr, &nif->mask, nif->flags, interface_address_deleted);
-        }
-        free(nif);
-    }
-
-    // Report added interface addresses...
-    for (nif = new_ifaddrs; nif; nif = nif->next) {
-        if (callback != NULL) {
-            callback(context, nif->name, &nif->addr, &nif->mask, nif->flags, interface_address_added);
-        }
-    }
-
-    // Report unchanged interface addresses...
-    for (nif = kept_ifaddrs; nif; nif = nif->next) {
-        if (callback != NULL) {
-            callback(context, nif->name, &nif->addr, &nif->mask, nif->flags, interface_address_unchanged);
-        }
-    }
-
-    // Restore kept interface addresses and append new addresses to the list.
-    *here = kept_ifaddrs;
-    for (ip = here; *ip; ip = &(*ip)->next)
-        ;
-    *ip = new_ifaddrs;
-    freeifaddrs(ifaddrs);
-    return true;
-}
-
-ssize_t
-ioloop_recvmsg(int sock, uint8_t *buffer, size_t buffer_length, int *ifindex, int *hop_limit, addr_t *source,
-               addr_t *destination)
-{
-    ssize_t rv;
-    struct msghdr msg;
-    struct iovec bufp;
-    char cmsgbuf[128];
-    struct cmsghdr *cmh;
-
-    bufp.iov_base = buffer;
-    bufp.iov_len = buffer_length;
-    msg.msg_iov = &bufp;
-    msg.msg_iovlen = 1;
-    msg.msg_name = source;
-    msg.msg_namelen = sizeof(*source);
-    msg.msg_control = cmsgbuf;
-    msg.msg_controllen = sizeof(cmsgbuf);
-
-    rv = recvmsg(sock, &msg, 0);
-    if (rv < 0) {
-        return rv;
-    }
-
-    // For UDP, we use the interface index as part of the validation strategy, so go get
-    // the interface index.
-    for (cmh = CMSG_FIRSTHDR(&msg); cmh; cmh = CMSG_NXTHDR(&msg, cmh)) {
-        if (cmh->cmsg_level == IPPROTO_IPV6 && cmh->cmsg_type == IPV6_PKTINFO &&
-            cmh->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
-        {
-            struct in6_pktinfo pktinfo;
-
-            memcpy(&pktinfo, CMSG_DATA(cmh), sizeof pktinfo);
-            *ifindex = (int)pktinfo.ipi6_ifindex;
-
-            /* Get the destination address, for use when replying. */
-            destination->sin6.sin6_family = AF_INET6;
-            destination->sin6.sin6_port = 0;
-            destination->sin6.sin6_addr = pktinfo.ipi6_addr;
-#ifndef NOT_HAVE_SA_LEN
-            destination->sin6.sin6_len = sizeof(destination->sin6);
-#endif
-        } else if (cmh->cmsg_level == IPPROTO_IP && cmh->cmsg_type == IP_PKTINFO &&
-                   cmh->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
-            struct in_pktinfo pktinfo;
-
-            memcpy(&pktinfo, CMSG_DATA(cmh), sizeof pktinfo);
-            *ifindex = (int)pktinfo.ipi_ifindex;
-
-            destination->sin.sin_family = AF_INET;
-            destination->sin.sin_port = 0;
-            destination->sin.sin_addr = pktinfo.ipi_addr;
-#ifndef NOT_HAVE_SA_LEN
-            destination->sin.sin_len = sizeof(destination->sin);
-#endif
-        } else if (cmh->cmsg_level == IPPROTO_IPV6 && cmh->cmsg_type == IPV6_HOPLIMIT &&
-                   cmh->cmsg_len == CMSG_LEN(sizeof(int))) {
-            *hop_limit = *(int *)CMSG_DATA(cmh);
-        }
-    }
-    return rv;
-}
-
-message_t *
-ioloop_message_create_(size_t message_size, const char *file, int line)
-{
-    message_t *message;
-
-    // Never should have a message shorter than this.
-    if (message_size < DNS_HEADER_SIZE || message_size > UINT16_MAX) {
-        return NULL;
-    }
-
-    message = (message_t *)malloc(message_size + (sizeof(message_t)) - (sizeof(dns_wire_t)));
-    if (message) {
-        memset(message, 0, (sizeof(message_t)) - (sizeof(dns_wire_t)));
-        RETAIN(message);
-        message->length = (uint16_t)message_size;
-    }
-    return message;
-}
-
-#ifdef DEBUG_FD_LEAKS
-int
-get_num_fds(void)
-{
-    DIR *dirfd = opendir("/dev/fd");
-    int num = 0;
-    if (dirfd == NULL) {
-        return -1;
-    }
-    while (readdir(dirfd) != NULL) {
-        num++;
-    }
-    closedir(dirfd);
-    return num;
-}
-#endif // DEBUG_VERBOSE
-
-#ifdef MALLOC_DEBUG_LOGGING
-#undef malloc
-#undef calloc
-#undef strdup
-#undef free
-
-void *
-debug_malloc(size_t len, const char *file, int line)
-{
-    void *ret = malloc(len);
-    INFO("%p: malloc(%zu) at " PUB_S_SRP ":%d", ret, len, file, line);
-    return ret;
-}
-
-void *
-debug_calloc(size_t count, size_t len, const char *file, int line)
-{
-    void *ret = calloc(count, len);
-    INFO("%p: calloc(%zu, %zu) at " PUB_S_SRP ":%d", ret, count, len, file, line);
-    return ret;
-}
-
-char *
-debug_strdup(const char *s, const char *file, int line)
-{
-    char *ret = strdup(s);
-    INFO("%p: strdup(%p) at " PUB_S_SRP ":%d", ret, s, file, line);
-    return ret;
-}
-
-void
-debug_free(void *p, const char *file, int line)
-{
-    INFO("%p: free() at " PUB_S_SRP ":%d", p, file, line);
-    free(p);
-}
-#endif
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/ra-tester.c b/ServiceRegistration/ra-tester.c
deleted file mode 100644
index d0be8a2..0000000
--- a/ServiceRegistration/ra-tester.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* ra-tester.c
- *
- * Copyright (c) 2020-2022 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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * This is a standalone tester for the Thread Border Router code that configures and advertises routes. The
- * idea is to be able to test the configuration/control functionality without setting up a Thread network.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <dns_sd.h>
-#include <net/if.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dnssd-proxy.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "config-parse.h"
-#include "route.h"
-
-static void
-usage(void)
-{
-    ERROR("ra-tester -t <thread interface name> --h <home interface name>");
-    exit(1);
-}
-
-#ifdef FUZZING
-#define main ra_tester_main
-#endif
-
-int
-main(int argc, char **argv)
-{
-    int i;
-    bool log_stderr = true;
-
-    srp_server_t *server_state = calloc(1, sizeof(*server_state));
-    if (server_state == NULL) {
-        ERROR("no memory for server_state");
-        return 1;
-    }
-    server_state->name = strdup("ra-tester");
-    server_state->route_state = route_state_create(server_state, "ra-tester");
-    if (server_state->route_state == NULL) {
-        return 1;
-    }
-
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "-t")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            server_state->route_state->thread_interface_name = argv[i + 1];
-            i++;
-        } else if (!strcmp(argv[i], "-h")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            server_state->route_state->home_interface_name = argv[i + 1];
-            i++;
-        } else {
-            usage();
-        }
-    }
-
-    if (server_state->route_state->thread_interface_name == NULL) {
-        INFO("thread interface name required.");
-        usage();
-    }
-    if (server_state->route_state->home_interface_name == NULL) {
-        INFO("home interface name required.");
-        usage();
-    }
-    OPENLOG("ra-tester", log_stderr);
-
-    if (!ioloop_init()) {
-        return 1;
-    }
-
-    if (!start_icmp_listener()) {
-        return 1;
-    }
-
-    infrastructure_network_startup(server_state->route_state);
-
-    do {
-        int something = 0;
-        ioloop();
-        INFO("dispatched %d events.", something);
-    } while (1);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/route.c b/ServiceRegistration/route.c
deleted file mode 100644
index 845436d..0000000
--- a/ServiceRegistration/route.c
+++ /dev/null
@@ -1,5137 +0,0 @@
-/* route.c
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * This file contains an implementation of Thread Border Router routing.
- * The state of the Thread network is tracked, the state of the infrastructure
- * network is tracked, and policy decisions are made as to what to advertise
- * on both networks.
- */
-
-#ifndef LINUX
-#include <netinet/in.h>
-#include <net/if.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/nd6.h>
-#include <net/if_media.h>
-#include <sys/stat.h>
-#else
-#define _GNU_SOURCE
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <bsd/stdlib.h>
-#include <net/if.h>
-#endif
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/route.h>
-#include <netinet/icmp6.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <arpa/inet.h>
-#if !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
-#ifndef LINUX
-#include <sys/sysctl.h>
-#endif // LINUX
-#endif // !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
-#include <stdlib.h>
-#include <stddef.h>
-#include <dns_sd.h>
-#include <inttypes.h>
-#include <signal.h>
-
-#ifdef IOLOOP_MACOS
-#include <xpc/xpc.h>
-
-#include <TargetConditionals.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
-#include <SystemConfiguration/SCNetworkSignature.h>
-#include <network_information.h>
-
-#include <CoreUtils/CoreUtils.h>
-#endif // IOLOOP_MACOS
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "ioloop.h"
-#include "adv-ctl-server.h"
-#include "srp-crypto.h"
-
-# define THREAD_DATA_DIR "/var/lib/openthread"
-# define THREAD_ULA_FILE THREAD_DATA_DIR "/thread-mesh-ula"
-
-#if STUB_ROUTER // Stub Router is true if we're building a Thread Border router or an RA tester.
-#ifdef THREAD_BORDER_ROUTER
-#include "cti-services.h"
-#endif
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "dnssd-proxy.h"
-#if SRP_FEATURE_NAT64
-#include "nat64-macos.h"
-#endif
-#include "srp-proxy.h"
-#include "route.h"
-
-#ifdef LINUX
-#define CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG 1
-#endif
-
-struct icmp_listener {
-    io_t *io_state;
-    int sock;
-    uint32_t unsolicited_interval;
-};
-
-struct thread_prefix {
-    int ref_count;
-    thread_prefix_t *next;
-    struct in6_addr prefix;
-    int prefix_len;
-    bool user, ncp, stable;
-    bool previous_user, previous_ncp, previous_stable;
-};
-
-struct thread_pref_id {
-    int ref_count;
-    thread_pref_id_t *next;
-    uint8_t partition_id[4]; // Partition id on which this prefix is claimed
-    uint8_t prefix[5];       // 40-bit ULA prefix identifier (no need to keep the whole prefix)
-    bool user, ncp, stable;
-    bool previous_user, previous_ncp, previous_stable;
-};
-
-struct thread_service {
-    int ref_count;
-    thread_service_t *next;
-    uint8_t address[16]; // IPv6 address on which service is offered
-    uint8_t port[2];     // Port (network byte order)
-    bool user, ncp, stable;
-    bool previous_user, previous_ncp, previous_stable;
-};
-
-#ifdef LINUX
-struct in6_addr in6addr_linklocal_allnodes = {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}};
-struct in6_addr in6addr_linklocal_allrouters = {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}};
-#endif
-
-icmp_listener_t icmp_listener;
-route_state_t *route_states;
-
-#define CONFIGURE_STATIC_INTERFACE_ADDRESSES 1
-
-#define interface_create(route_state, name, iface) interface_create_(route_state, name, iface, __FILE__, __LINE__)
-interface_t *NULLABLE interface_create_(route_state_t *NONNULL route_state, const char *NONNULL name, int ifindex,
-                                        const char *NONNULL file, int line);
-
-static void refresh_interface_list(route_state_t *route_state);
-static void router_advertisement_send(interface_t *NONNULL interface, const struct in6_addr *destination);
-static void neighbor_solicit_send(interface_t *interface, struct in6_addr *destination);
-static void icmp_send(uint8_t *NONNULL message, size_t length,
-                      interface_t *NONNULL interface, const struct in6_addr *NONNULL destination);
-static void interface_beacon_schedule(interface_t *NONNULL interface, unsigned when);
-static void interface_prefix_configure(struct in6_addr prefix, interface_t *NONNULL interface);
-static void interface_prefix_evaluate(interface_t *interface);
-static void start_router_solicit(interface_t *interface);
-#ifndef RA_TESTER
-static void routing_policy_evaluate_all_interfaces(route_state_t *route_state, bool assume_changed);
-#endif
-static void routing_policy_evaluate(interface_t *interface, bool assume_changed);
-static void post_solicit_policy_evaluate(void *context);
-static void interface_active_state_evaluate(interface_t *interface, bool active_known, bool active);
-static void schedule_next_router_probe(interface_t *interface);
-
-#ifndef RA_TESTER
-static void thread_network_startup(route_state_t *route_state);
-static void thread_network_shutdown(route_state_t *route_state);
-static void partition_state_reset(route_state_t *route_state);
-static void partition_unpublish_prefix(route_state_t *route_state, thread_prefix_t *NONNULL prefix);
-static void partition_unpublish_adopted_prefix(route_state_t *route_state, bool wait);
-static void partition_adopt_prefix(route_state_t *route_state, thread_prefix_t *NONNULL prefix);
-static bool partition_prefix_is_present(route_state_t *route_state, struct in6_addr *prefix_addr, int length);
-static bool partition_pref_id_is_present(route_state_t *route_state, struct in6_addr *NONNULL prefix_addr);
-static thread_prefix_t *NULLABLE partition_find_lowest_valid_prefix(route_state_t *route_state);
-static thread_pref_id_t *NULLABLE partition_find_lowest_valid_pref_id(route_state_t *route_state);
-static void partition_pref_id_timeout(void *UNUSED NULLABLE context);
-static void partition_post_election_wakeup(void *UNUSED NULLABLE context);
-static void partition_post_partition_timeout(void *UNUSED NULLABLE context);
-static void partition_utun0_address_changed(route_state_t *route_state, const struct in6_addr *NONNULL addr, enum interface_address_change change);
-static bool partition_wait_for_prefix_settling(route_state_t *route_state, wakeup_callback_t NONNULL callback, uint64_t now);
-static void partition_got_tunnel_name(route_state_t *route_state);
-static void partition_prefix_set_changed(route_state_t *route_state);
-static void partition_pref_id_set_changed(route_state_t *route_state);
-static void partition_id_changed(route_state_t *route_state);
-static void partition_remove_service_done(void *UNUSED NULLABLE context, cti_status_t status);
-static void partition_stop_advertising_service(route_state_t *route_state);
-static void partition_proxy_listener_ready(void *UNUSED NULLABLE context, uint16_t port);
-static void partition_maybe_advertise_service(route_state_t *route_state);
-static void partition_service_set_changed(route_state_t *route_state);
-static void partition_maybe_enable_services(route_state_t *route_state);
-static void partition_disable_service(route_state_t *route_state);
-static void partition_schedule_service_add_wakeup(route_state_t *route_state);
-#endif
-
-route_state_t *
-route_state_create(srp_server_t *server_state, const char *name)
-{
-    route_state_t *new_route_state = calloc(1, sizeof(*new_route_state));
-    if (new_route_state == NULL || (new_route_state->name = strdup(name)) == NULL) {
-        free(new_route_state);
-        ERROR("no memory for route state.");
-        return NULL;
-    }
-#if !defined(RA_TESTER)
-    new_route_state->thread_network_running = false;
-    new_route_state->partition_may_offer_service = false;
-    new_route_state->partition_settle_satisfied = true;
-    new_route_state->current_thread_state = kCTI_NCPState_Uninitialized;
-#endif
-    new_route_state->have_non_thread_interface = false;
-    new_route_state->ula_serial = 1;
-    new_route_state->have_xpanid_prefix = false;
-    new_route_state->have_thread_prefix = false;
-    new_route_state->config_enable_dhcpv6_prefixes = false;
-    new_route_state->srp_server = server_state; // temporarily communicate the server_state object to route.c with a static assignment.
-    new_route_state->next = route_states;
-    route_states = new_route_state;
-    return new_route_state;
-}
-
-static void
-interface_finalize(void *context)
-{
-    interface_t *interface = context;
-    if (interface->name != NULL) {
-        free(interface->name);
-    }
-    if (interface->beacon_wakeup != NULL) {
-        ioloop_wakeup_release(interface->beacon_wakeup);
-    }
-    if (interface->post_solicit_wakeup != NULL) {
-        ioloop_wakeup_release(interface->post_solicit_wakeup);
-    }
-    if (interface->stale_evaluation_wakeup != NULL) {
-        ioloop_wakeup_release(interface->stale_evaluation_wakeup);
-    }
-    if (interface->router_solicit_wakeup != NULL) {
-        ioloop_wakeup_release(interface->router_solicit_wakeup);
-    }
-    if (interface->deconfigure_wakeup != NULL) {
-        ioloop_wakeup_release(interface->deconfigure_wakeup);
-    }
-    if (interface->neighbor_solicit_wakeup != NULL) {
-        ioloop_wakeup_release(interface->neighbor_solicit_wakeup);
-    }
-    if (interface->router_probe_wakeup != NULL) {
-        ioloop_wakeup_release(interface->router_probe_wakeup);
-    }
-    free(interface);
-}
-
-interface_t *
-interface_create_(route_state_t *route_state, const char *name, int ifindex, const char *file, int line)
-{
-    interface_t *ret;
-
-    if (name == NULL) {
-        ERROR("interface_create: missing name");
-        return NULL;
-    }
-
-    ret = calloc(1, sizeof(*ret));
-    if (ret) {
-        RETAIN(ret);
-        ret->name = strdup(name);
-        if (ret->name == NULL) {
-            ERROR("interface_create: no memory for name");
-            RELEASE(ret, interface_finalize);
-            return NULL;
-        }
-        ret->deconfigure_wakeup = ioloop_wakeup_create();
-        if (ret->deconfigure_wakeup == NULL) {
-            ERROR("No memory for interface deconfigure wakeup on " PUB_S_SRP ".", ret->name);
-            RELEASE(ret, interface_finalize);
-            return NULL;
-        }
-
-        ret->route_state = route_state;
-        ret->index = ifindex;
-        ret->inactive = true;
-        if (!strcmp(name, "lo") || !strcmp(name, "wpan0")) {
-            ret->ineligible = true;
-        } else {
-            ret->ineligible = false;
-        }
-    }
-    return ret;
-}
-
-#ifndef RA_TESTER
-static void
-thread_prefix_finalize(thread_prefix_t *prefix)
-{
-    free(prefix);
-}
-
-#define thread_prefix_create(prefix, prefix_length) thread_prefix_create_(prefix, prefix_length, __FILE__, __LINE__)
-static thread_prefix_t *
-thread_prefix_create_(struct in6_addr *address, int prefix_length, const char *file, int line)
-{
-    thread_prefix_t *prefix;
-
-    prefix = calloc(1, (sizeof *prefix));
-    if (prefix != NULL) {
-        memcpy(&prefix->prefix, address, 16);
-        prefix->prefix_len = prefix_length;
-        RETAIN(prefix);
-    }
-    return prefix;
-}
-
-static void
-thread_service_finalize(thread_service_t *service)
-{
-    free(service);
-}
-
-#define thread_service_create(address, port) thread_service_create_(address, port, __FILE__, __LINE__)
-static thread_service_t *
-thread_service_create_(uint8_t *address, uint8_t *port, const char *file, int line)
-{
-    thread_service_t *service;
-
-    service = calloc(1, sizeof(*service));
-    if (service != NULL) {
-        memcpy(&service->address, address, 16);
-        memcpy(&service->port, port, 2);
-        RETAIN(service);
-    }
-    return service;
-}
-
-static void
-thread_pref_id_finalize(thread_pref_id_t *pref_id)
-{
-    free(pref_id);
-}
-
-#define thread_pref_id_create(partition_id, prefix) thread_pref_id_create_(partition_id, prefix, __FILE__, __LINE__)
-static thread_pref_id_t *
-thread_pref_id_create_(uint8_t *partition_id, uint8_t *prefix, const char *file, int line)
-{
-    thread_pref_id_t *pref_id;
-
-    pref_id = calloc(1, sizeof(*pref_id));
-    if (pref_id != NULL) {
-        memcpy(&pref_id->partition_id, partition_id, 4);
-        memcpy(&pref_id->prefix, prefix, 5);
-        RETAIN(pref_id);
-    }
-    return pref_id;
-}
-#endif // RA_TESTER
-
-static void
-icmp_message_free(icmp_message_t *message)
-{
-    if (message->options != NULL) {
-        free(message->options);
-    }
-    if (message->wakeup != NULL) {
-        ioloop_cancel_wake_event(message->wakeup);
-        ioloop_wakeup_release(message->wakeup);
-    }
-    free(message);
-}
-
-static void
-icmp_message_dump(icmp_message_t *message,
-                  const struct in6_addr * const source_address, const struct in6_addr * const destination_address)
-{
-    link_layer_address_t *lladdr;
-    prefix_information_t *prefix_info;
-    route_information_t *route_info;
-    int i;
-    char retransmission_timer_buf[11]; // Maximum size of a uint32_t printed as decimal.
-    char *retransmission_timer = "infinite";
-
-    if (message->retransmission_timer != ND6_INFINITE_LIFETIME) {
-        snprintf(retransmission_timer_buf, sizeof(retransmission_timer_buf), "%" PRIu32, message->retransmission_timer);
-        retransmission_timer = retransmission_timer_buf;
-    }
-
-    SEGMENTED_IPv6_ADDR_GEN_SRP(source_address->s6_addr, src_addr_buf);
-    SEGMENTED_IPv6_ADDR_GEN_SRP(destination_address->s6_addr, dst_addr_buf);
-    if (message->type == icmp_type_router_advertisement) {
-        INFO("router advertisement from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
-             " hop_limit %d on " PUB_S_SRP ": checksum = %x "
-             "cur_hop_limit = %d flags = %x router_lifetime = %d reachable_time = %" PRIu32
-             " retransmission_timer = " PUB_S_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
-             message->hop_limit, message->interface->name, message->checksum, message->cur_hop_limit, message->flags,
-             message->router_lifetime, message->reachable_time, retransmission_timer);
-    } else if (message->type == icmp_type_router_solicitation) {
-        INFO("router solicitation from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
-             " hop_limit %d on " PUB_S_SRP ": code = %d checksum = %x",
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
-             message->hop_limit, message->interface->name,
-             message->code, message->checksum);
-    } else {
-        INFO("icmp message from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP " hop_limit %d on "
-             PUB_S_SRP ": type = %d code = %d checksum = %x",
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
-             message->hop_limit, message->interface->name, message->type,
-             message->code, message->checksum);
-    }
-
-    for (i = 0; i < message->num_options; i++) {
-        icmp_option_t *option = &message->options[i];
-        switch(option->type) {
-        case icmp_option_source_link_layer_address:
-            lladdr = &option->option.link_layer_address;
-            INFO("  source link layer address " PRI_MAC_ADDR_SRP, MAC_ADDR_PARAM_SRP(lladdr->address));
-            break;
-        case icmp_option_target_link_layer_address:
-            lladdr = &option->option.link_layer_address;
-            INFO("  destination link layer address " PRI_MAC_ADDR_SRP, MAC_ADDR_PARAM_SRP(lladdr->address));
-            break;
-        case icmp_option_prefix_information:
-            prefix_info = &option->option.prefix_information;
-            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix_info->prefix.s6_addr, prefix_buf);
-            INFO("  prefix info: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d %x %" PRIu32 " %" PRIu32,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix_info->prefix.s6_addr, prefix_buf), prefix_info->length,
-                 prefix_info->flags, prefix_info->valid_lifetime, prefix_info->preferred_lifetime);
-            break;
-        case icmp_option_route_information:
-            route_info = &option->option.route_information;
-                SEGMENTED_IPv6_ADDR_GEN_SRP(route_info->prefix.s6_addr, router_prefix_buf);
-            INFO("  route info: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d %x %d",
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(route_info->prefix.s6_addr, router_prefix_buf), route_info->length,
-                 route_info->flags, route_info->route_lifetime);
-            break;
-        default:
-            INFO("  option type %d", option->type);
-            break;
-        }
-    }
-}
-
-static bool
-icmp_message_parse_options(icmp_message_t *message, uint8_t *icmp_buf, unsigned length, unsigned *offset)
-{
-    uint8_t option_type, option_length_8;
-    unsigned option_length;
-    unsigned scan_offset = *offset;
-    icmp_option_t *option;
-    uint32_t reserved32;
-    prefix_information_t *prefix_information;
-    route_information_t *route_information;
-    int prefix_bytes;
-
-    // Count the options and validate the lengths
-    message->num_options = 0;
-    while (scan_offset < length) {
-        if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_type)) {
-            return false;
-        }
-        if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_length_8)) {
-            return false;
-        }
-        if (option_length_8 == 0) { // RFC4191 section 4.6: The value 0 is invalid.
-            ERROR("icmp_option_parse: option type %d length 0 is invalid.", option_type);
-            return false;
-        }
-        if (scan_offset + option_length_8 * 8 - 2 > length) {
-            ERROR("icmp_option_parse: option type %d length %d is longer than remaining available space %u",
-                  option_type, option_length_8 * 8, length - scan_offset + 2);
-            return false;
-        }
-        scan_offset += option_length_8 * 8 - 2;
-        message->num_options++;
-    }
-    // If there are no options, we're done. No options is valid, so return true.
-    if (message->num_options == 0) {
-        return true;
-    }
-    message->options = calloc(message->num_options, sizeof(*message->options));
-    if (message->options == NULL) {
-        ERROR("No memory for icmp options.");
-        return false;
-    }
-    option = message->options;
-    while (*offset < length) {
-        scan_offset = *offset;
-        if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_type)) {
-            return false;
-        }
-        if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_length_8)) {
-            return false;
-        }
-        // We already validated the length in the previous pass.
-        option->type = option_type;
-        option_length = option_length_8 * 8;
-
-        switch(option_type) {
-        case icmp_option_source_link_layer_address:
-        case icmp_option_target_link_layer_address:
-            // At this juncture we are assuming that everything we care about looks like an
-            // ethernet interface.  So for this case, length should be 8.
-            if (option_length != 8) {
-                INFO("Ignoring unexpectedly long link layer address: %d", option_length);
-                // Don't store the option.
-                message->num_options--;
-                *offset += option_length;
-                continue;
-            }
-            option->option.link_layer_address.length = 6;
-            memcpy(option->option.link_layer_address.address, &icmp_buf[scan_offset], 6);
-            break;
-        case icmp_option_prefix_information:
-            prefix_information = &option->option.prefix_information;
-            // Only a length of 32 is valid.  This is an invalid ICMP packet, not just misunderunderstood
-            if (option_length != 32) {
-                return false;
-            }
-            // prefix length 8
-            if (!dns_u8_parse(icmp_buf, length, &scan_offset, &prefix_information->length)) {
-                return false;
-            }
-            // flags 8a
-            if (!dns_u8_parse(icmp_buf, length, &scan_offset, &prefix_information->flags)) {
-                return false;
-            }
-            // valid lifetime 32
-            if (!dns_u32_parse(icmp_buf, length, &scan_offset,
-                               &prefix_information->valid_lifetime)) {
-                return false;
-            }
-            // preferred lifetime 32
-            if (!dns_u32_parse(icmp_buf, length, &scan_offset,
-                               &prefix_information->preferred_lifetime)) {
-                return false;
-            }
-            // reserved2 32
-            if (!dns_u32_parse(icmp_buf, length, &scan_offset, &reserved32)) {
-                return false;
-            }
-            // prefix 128
-            memcpy(&prefix_information->prefix, &icmp_buf[scan_offset], 16);
-            break;
-        case icmp_option_route_information:
-            route_information = &option->option.route_information;
-
-            // route length 8
-            if (!dns_u8_parse(icmp_buf, length, &scan_offset, &route_information->length)) {
-                return false;
-            }
-            switch(option_length) {
-            case 8:
-                prefix_bytes = 0;
-                break;
-            case 16:
-                prefix_bytes = 8;
-                break;
-            case 24:
-                prefix_bytes = 16;
-                break;
-            default:
-                ERROR("invalid route information option length %d for route length %d",
-                      option_length, route_information->length);
-                return false;
-            }
-            // flags 8
-            if (!dns_u8_parse(icmp_buf, length, &scan_offset, &route_information->flags)) {
-                return false;
-            }
-            // route lifetime 32
-            if (!dns_u32_parse(icmp_buf, length, &scan_offset, &route_information->route_lifetime)) {
-                return false;
-            }
-            // route (64, 96 or 128)
-            if (prefix_bytes > 0) {
-                memcpy(&route_information->prefix, &icmp_buf[scan_offset], prefix_bytes);
-            }
-            memset(&((uint8_t *)&route_information->prefix)[prefix_bytes], 0, 16 - prefix_bytes);
-            break;
-        default:
-        case icmp_option_mtu:
-        case icmp_option_redirected_header:
-            // don't care
-            break;
-        }
-        *offset += option_length;
-        option++;
-    }
-    return true;
-}
-
-
-static void
-interface_wakeup_finalize(void *context)
-{
-    interface_t *interface = context;
-    interface->beacon_wakeup = NULL;
-}
-
-static void
-interface_deconfigure_finalize(void *context)
-{
-    interface_t *interface = context;
-    interface->deconfigure_wakeup = NULL;
-}
-
-static void
-interface_prefix_deconfigure(void *context)
-{
-    interface_t *interface = context;
-    INFO("post solicit wakeup.");
-
-    if (interface->preferred_lifetime != 0) {
-        INFO("PUT PREFIX DECONFIGURE CODE HERE!!");
-        interface->valid_lifetime = 0;
-    }
-    interface->deprecate_deadline = 0;
-}
-
-static bool
-want_routing(route_state_t *route_state)
-{
-#ifdef RA_TESTER
-    (void)route_state;
-    return true;
-#else
-    return (route_state->partition_can_provide_routing &&
-            route_state->partition_has_xpanid);
-#endif
-}
-
-static void
-interface_beacon_send(interface_t *interface, const struct in6_addr *destination)
-{
-    uint64_t now = ioloop_timenow();
-#ifndef RA_TESTER
-    route_state_t *route_state = interface->route_state;
-#endif
-
-    INFO(PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP,
-         interface->deprecate_deadline > now ? " ddl>now" : "",
-#ifdef RA_TESTER
-         "", "", "",
-#else
-         route_state->partition_can_provide_routing ? " canpr" : " !canpr",
-         route_state->partition_has_xpanid ? " havexp" : " !havexp",
-         interface->suppress_ipv6_prefix ? " suppress" : " !suppress",
-#endif
-         interface->our_prefix_advertised ? " advert" : " !advert",
-         interface->sent_first_beacon ? "" : " first beacon");
-
-    if (interface->deprecate_deadline > now) {
-        // The remaining valid and preferred lifetimes is the time left until the deadline.
-        interface->valid_lifetime = (uint32_t)((interface->deprecate_deadline - now) / 1000);
-        interface->preferred_lifetime = (uint32_t)((interface->deprecate_deadline - now) / 1000);
-        // When we're deprecating the prefix, we don't actually want to make the preferred lifetime zero, because
-        // this will cause IP address flapping if we miss a router advertisement.
-#define FIVE_MINUTES 5 * 60
-        if (interface->preferred_lifetime > FIVE_MINUTES) {
-            interface->preferred_lifetime = FIVE_MINUTES;
-        }
-        if (interface->valid_lifetime < icmp_listener.unsolicited_interval / 1000) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
-            INFO("prefix valid life time is less than the unsolicited interval, stop advertising it "
-                 "and prepare to deconfigure the prefix - ifname: " PUB_S_SRP "prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                 ", preferred time: %" PRIu32 ", valid time: %" PRIu32 ", unsolicited interval: %" PRIu32,
-                 interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf),
-                 interface->preferred_lifetime, interface->valid_lifetime, icmp_listener.unsolicited_interval / 1000);
-            interface->our_prefix_advertised = false;
-            ioloop_add_wake_event(interface->deconfigure_wakeup,
-                                  interface, interface_prefix_deconfigure,
-                                  interface_deconfigure_finalize, interface->valid_lifetime * 1000);
-        }
-    }
-
-#ifndef RA_TESTER
-    // If we have been beaconing, and router mode has been disabled, and we don't have
-    // an on-link prefix to advertise, discontinue beaconing.
-    if (want_routing(route_state) || interface->our_prefix_advertised) {
-#endif
-
-    // Send an RA.
-        router_advertisement_send(interface, destination);
-        if (destination == &in6addr_linklocal_allnodes) {
-            interface->sent_first_beacon = true;
-            interface->last_beacon = ioloop_timenow();;
-        }
-#ifndef CONTINUE_ADVERTISING_DURING_DEPRECATION
-        // If we are deprecating, just send the initial deprecation to shorten the preferred lifetime, and then go silent.
-        if (interface->deprecate_deadline > now && !interface->suppress_ipv6_prefix) {
-            INFO("suppressing ipv6 prefix on " PUB_S_SRP, interface->name);
-            interface->suppress_ipv6_prefix = true;
-        }
-#endif
-
-#ifndef RA_TESTER
-    } else {
-        INFO("didn't send: " PUB_S_SRP PUB_S_SRP PUB_S_SRP,
-             route_state->partition_can_provide_routing ? "canpr" : "!canpr",
-             route_state->partition_has_xpanid ? " route_state->xpanid" : " !route_state->xpanid",
-             interface->our_prefix_advertised ? " advert" : " !advert");
-    }
-#endif
-    if (destination == &in6addr_linklocal_allnodes) {
-        if (interface->num_beacons_sent < MAX_RA_RETRANSMISSION - 1) {
-            // Schedule a beacon for between 8 and 16 seconds in the future (<MAX_INITIAL_RTR_ADVERT_INTERVAL)
-            interface_beacon_schedule(interface, 8000 + srp_random16() % 8000);
-        } else {
-            interface_beacon_schedule(interface, icmp_listener.unsolicited_interval);
-        }
-        interface->num_beacons_sent++;
-    }
-}
-
-static void
-interface_beacon(void *context)
-{
-    interface_t *interface = context;
-    interface_beacon_send(interface, &in6addr_linklocal_allnodes);
-}
-
-static void
-interface_beacon_schedule(interface_t *interface, unsigned when)
-{
-    uint64_t now = ioloop_timenow();
-    unsigned interval;
-
-
-    // Make sure we haven't send an RA too recently.
-    if (when < MIN_DELAY_BETWEEN_RAS && now - interface->last_beacon < MIN_DELAY_BETWEEN_RAS) {
-        when = MIN_DELAY_BETWEEN_RAS;
-    }
-    // Add up to a second of jitter.
-    when += srp_random16() % 1024;
-    interface->next_beacon = now + when;
-    if (interface->beacon_wakeup == NULL) {
-        interface->beacon_wakeup = ioloop_wakeup_create();
-        if (interface->beacon_wakeup == NULL) {
-            ERROR("Unable to allocate beacon wakeup for " PUB_S_SRP, interface->name);
-            return;
-        }
-    } else {
-        // We can reschedule a beacon for sooner if we get a router solicit; in this case, we
-        // need to cancel the existing beacon wakeup, and if there is none scheduled, this will
-        // be a no-op.
-        ioloop_cancel_wake_event(interface->beacon_wakeup);
-    }
-    if (interface->next_beacon - now > UINT_MAX) {
-        interval = UINT_MAX;
-    } else {
-        interval = (unsigned)(interface->next_beacon - now);
-    }
-    INFO("Scheduling " PUB_S_SRP "beacon on " PUB_S_SRP " for %u milliseconds in the future",
-         interface->sent_first_beacon ? "" : "first ", interface->name, interval);
-    ioloop_add_wake_event(interface->beacon_wakeup, interface, interface_beacon, interface_wakeup_finalize, interval);
-}
-
-static void
-router_discovery_start(interface_t *interface)
-{
-    INFO("Starting router discovery on " PUB_S_SRP, interface->name);
-
-    // Immediately when an interface shows up, start doing router solicits.
-    start_router_solicit(interface);
-
-    if (interface->post_solicit_wakeup == NULL) {
-        interface->post_solicit_wakeup = ioloop_wakeup_create();
-        if (interface->post_solicit_wakeup == NULL) {
-            ERROR("No memory for post-solicit RA wakeup on " PUB_S_SRP ".", interface->name);
-        }
-    } else {
-        ioloop_cancel_wake_event(interface->post_solicit_wakeup);
-    }
-
-    // In 20 seconds, check the results of router discovery and update policy as needed.
-    if (interface->post_solicit_wakeup) {
-        ioloop_add_wake_event(interface->post_solicit_wakeup, interface, post_solicit_policy_evaluate,
-                              NULL, 20 * 1000);
-    }
-    interface->router_discovery_in_progress = true;
-    interface->router_discovery_started = true;
-}
-
-#ifdef FLUSH_STALE_ROUTERS
-static void
-flush_stale_routers(interface_t *interface, uint64_t now)
-{
-    icmp_message_t *router, **p_router;
-
-    // Flush stale routers.
-    for (p_router = &interface->routers; *p_router != NULL; ) {
-        router = *p_router;
-        if (now - router->received_time > MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE)  {
-            *p_router = router->next;
-            SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_addr_buf);
-            INFO("flushing stale router - ifname: " PUB_S_SRP
-                 ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP, interface->name,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf));
-            icmp_message_free(router);
-        } else {
-            p_router = &(*p_router)->next;
-        }
-    }
-}
-#endif // FLUSH_STALE_ROUTERS
-
-static void
-router_discovery_stop(interface_t *interface, uint64_t now)
-{
-    if (!interface->router_discovery_started) {
-        INFO("router discovery not yet started.");
-        return;
-    }
-    if (!interface->router_discovery_complete) {
-        INFO("stopping router discovery on " PUB_S_SRP, interface->name);
-    }
-    if (interface->router_solicit_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->router_solicit_wakeup);
-    }
-    if (interface->post_solicit_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->post_solicit_wakeup);
-    }
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    if (interface->vicarious_discovery_complete != NULL) {
-        ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
-        INFO("stopping vicarious router discovery on " PUB_S_SRP, interface->name);
-    }
-    interface->vicarious_router_discovery_in_progress = false;
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    interface->router_discovery_complete = true;
-    interface->router_discovery_in_progress = false;
-    // clear out need_reconfigure_prefix when router_discovery_complete is set back to true.
-    interface->need_reconfigure_prefix = false;
-#ifdef FLUSH_STALE_ROUTERS
-    flush_stale_routers(interface, now);
-#else
-    (void)now;
-#endif // FLUSH_STALE_ROUTERS
-
-    // See if we need a new prefix on the interface.
-    interface_prefix_evaluate(interface);
-}
-
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-static void
-adjust_router_received_time(interface_t *const interface, const uint64_t now, const int64_t time_adjusted)
-{
-    icmp_message_t *router;
-
-    if (interface->routers == NULL) {
-        if (interface->our_prefix_advertised) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __ipv6_prefix);
-            INFO("No router information available for the interface - "
-                 "ifname: " PUB_S_SRP ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __ipv6_prefix));
-        } else {
-            INFO("No router information available for the interface - "
-                 "ifname: " PUB_S_SRP, interface->name);
-        }
-
-        goto exit;
-    }
-
-    for (router = interface->routers; router != NULL; router = router->next) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_addr_buf);
-        // Only adjust the received time once.
-        if (router->received_time_already_adjusted) {
-            INFO("received time already adjusted - remaining time: %llu, "
-                  "router src: " PRI_SEGMENTED_IPv6_ADDR_SRP, (now - router->received_time) / MSEC_PER_SEC,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf));
-            continue;
-        }
-        require_action_quiet(
-            (time_adjusted > 0 && (UINT64_MAX - now) > (uint64_t)time_adjusted) ||
-            (time_adjusted < 0 && now > ((uint64_t)-time_adjusted)), exit,
-            ERROR("adjust_router_received_time: invalid adjusted values is causing overflow - "
-                  "now: %" PRIu64 ", time_adjusted: %" PRId64, now, time_adjusted));
-        router->received_time = now + time_adjusted;
-        router->received_time_already_adjusted = true; // Only adjust the icmp message received time once.
-        INFO("router received time is adjusted - router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
-              ", adjusted value: %" PRId64,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf), time_adjusted);
-    }
-
-exit:
-    return;
-}
-
-static void
-make_all_routers_nearly_stale(interface_t *interface, uint64_t now)
-{
-    // Make every router go stale in 19.999 seconds.   This means that if we don't get a response
-    // to our solicit in 20 seconds, then when the timeout callback is called, there will be no
-    // routers on the interface that aren't stale, which will trigger router discovery.
-    adjust_router_received_time(interface, now, 19999 - 600 * MSEC_PER_SEC);
-}
-
-static void
-vicarious_discovery_callback(void *context)
-{
-    interface_t *interface = context;
-    INFO("Vicarious router discovery finished on " PUB_S_SRP ".", interface->name);
-    interface->vicarious_router_discovery_in_progress = false;
-    // At this point, policy evaluate will show all the routes that were present before vicarious
-    // discovery as stale, so policy_evaluate will start router discovery if we didn't get any
-    // RAs containing on-link prefixes.
-    routing_policy_evaluate(interface, false);
-}
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-
-#ifndef RA_TESTER
-static void
-routing_policy_evaluate_all_interfaces(route_state_t *route_state, bool assume_changed)
-{
-    interface_t *interface;
-
-    for (interface = route_state->interfaces; interface; interface = interface->next) {
-        routing_policy_evaluate(interface, assume_changed);
-    }
-}
-#endif
-
-#ifdef FLUSH_STALE_ROUTERS
-static void
-stale_router_policy_evaluate(void *context)
-{
-    interface_t *interface = context;
-    INFO("Evaluating stale routers on " PUB_S_SRP, interface->name);
-
-    flush_stale_routers(interface, ioloop_timenow());
-
-    // See if we need a new prefix on the interface.
-    interface_prefix_evaluate(interface);
-
-    routing_policy_evaluate(interface, true);
-}
-#endif // FLUSH_STALE_ROUTERS
-
-static bool
-prefix_usable(icmp_message_t *router, prefix_information_t *prefix)
-{
-    if (router->interface == NULL) {
-        FAULT("no interface");
-        return false;
-    }
-    return ((prefix->flags & ND_OPT_PI_FLAG_ONLINK) &&
-            ((prefix->flags & ND_OPT_PI_FLAG_AUTO) ||
-             (router->interface->route_state->config_enable_dhcpv6_prefixes && (router->flags & ND_RA_FLAG_MANAGED))) &&
-            prefix->preferred_lifetime > 0);
-}
-
-static void
-routing_policy_evaluate(interface_t *interface, bool assume_changed)
-{
-    icmp_message_t *router;
-    bool new_prefix = false;    // new prefix means that srp-mdns-proxy received a new prefix from the wire, which it
-                                // did not know before.
-    bool on_link_prefix_present = false;
-    bool something_changed = assume_changed;
-    uint64_t now = ioloop_timenow();
-    bool stale_routers_exist = false;
-    uint64_t stale_refresh_time = 0;
-    route_state_t *route_state = interface->route_state;
-
-    // No action on interfaces that aren't eligible for routing or that isn't currently active.
-    if (interface->ineligible || interface->inactive) {
-        INFO("not evaluating policy on " PUB_S_SRP " because it's " PUB_S_SRP, interface->name,
-             interface->ineligible ? "ineligible" : "inactive");
-        return;
-    }
-
-    // We can't tell whether any particular prefix is usable until we've gotten the xpanid.
-    if (route_state->have_xpanid_prefix) {
-        // Look at all the router advertisements we've seen to see if any contain a usable prefix which is not the
-        // prefix we'd advertise. Routers advertising that prefix are all Thread BRs, and it's fine for more than
-        // one router to advertise a prefix, so we will also advertise it for redundancy.
-        for (router = interface->routers; router; router = router->next) {
-            icmp_option_t *option = router->options;
-            int i;
-            bool usable = false;
-            for (i = 0; i < router->num_options; i++, option++) {
-                if (option->type == icmp_option_prefix_information) {
-                    prefix_information_t *prefix = &option->option.prefix_information;
-                    if (prefix_usable(router, prefix)) {
-                        // We don't consider the prefix we would advertise to be infrastructure-provided if we see it
-                        // advertised by another router, because that router is also a Thread BR, and we don't want
-                        // to get into dueling prefixes with it.
-                        if (memcmp(&option->option.prefix_information.prefix, &route_state->xpanid_prefix, 8))
-                        {
-                            uint32_t preferred_lifetime_offset = MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE / MSEC_PER_SEC;
-                            uint32_t preferred_lifetime = prefix->preferred_lifetime;
-
-                            // Infinite preferred lifetime. Bogus.
-                            if (preferred_lifetime == UINT32_MAX) {
-                                preferred_lifetime = 60 * 60;   // One hour
-                            }
-
-                            // If the remaining time on this prefix is less than the stale time gap, use an offset that's the
-                            // valid lifetime minus sixty seconds so that we have time if the prefix expires.
-                            if (preferred_lifetime < preferred_lifetime_offset + 60) {
-                                // If the preferred lifetime is less than a minute, we're not going to count this as a valid
-                                // on-link prefix.
-                                if (preferred_lifetime < 60) {
-                                    SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
-                                    SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
-                                    INFO("router " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising " PRI_SEGMENTED_IPv6_ADDR_SRP
-                                         " has a preferred lifetime of %d, which is not enough to count as usable.",
-                                         SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
-                                         SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
-                                         preferred_lifetime);
-                                    continue;
-                                }
-                                preferred_lifetime_offset = preferred_lifetime - 60;
-                            }
-
-                            // Lifetimes are in seconds, but henceforth we will compare with clock times, which are in ms.
-                            preferred_lifetime_offset *= MSEC_PER_SEC;
-
-                            // If the prefix' preferred lifetime plus the time received is in the past, the prefix doesn't
-                            // count as an on-link prefix that's present.
-                            if (router->received_time + preferred_lifetime_offset < now) {
-                                SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
-                                SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
-                                INFO("router " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising " PRI_SEGMENTED_IPv6_ADDR_SRP
-                                     " was received %d seconds ago with a preferred lifetime of %d.",
-                                     SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
-                                     SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
-                                     (int)((now - router->received_time) / 1000), preferred_lifetime);
-
-                                continue;
-                            }
-
-                            // This prefix is in principle usable. It may not actually be usable if it is stale, but we mark it usable so it
-                            // will continue to be probed.
-                            usable = true;
-
-                            // router->reachable will be true immediately after receiving a router advertisement until we do a
-                            // probe and don't get a response. It will become true again if, during a later probe, we get a
-                            // response.
-                            if (!router->reachable) {
-                                SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
-                                SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
-                                INFO("router %p " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising %d %p " PRI_SEGMENTED_IPv6_ADDR_SRP
-                                     " was last known to be reachable %d seconds ago.",
-                                     router,
-                                     SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
-                                     i, option,
-                                     SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
-                                     (int)((now - router->latest_na) / 1000));
-                                continue;
-                            }
-
-                            // Otherwise, if this router's on-link prefix will expire later than any other we've seen
-                            if (stale_refresh_time < router->received_time + preferred_lifetime_offset) {
-                                stale_refresh_time = router->received_time + preferred_lifetime_offset;
-                            }
-
-                            // If this is a new icmp_message received now and contains PIO.
-                            if (router->new_router) {
-                                new_prefix = true;
-                                router->new_router = false; // clear the bit since srp-mdns-proxy already processed it.
-                            }
-
-                            // This router has a usable prefix.
-                            usable = true;
-
-                            // Right now all we need is to see if there is an on-link prefix.
-                            on_link_prefix_present = true;
-                            SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_add_buf);
-                            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, __pio_prefix_buf);
-                            INFO("router has usable PIO - ifname: " PUB_S_SRP ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                                 ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                                 interface->name,
-                                 SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_add_buf),
-                                 SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, __pio_prefix_buf));
-                        } else {
-                            SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
-                            INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
-                                 " is advertising the xpanid prefix: not counting as usable ",
-                                 SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf));
-                        }
-                    } else {
-                        SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_add_buf);
-                        SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, __pio_prefix_buf);
-                        INFO("router has unusable PIO - ifname: " PUB_S_SRP ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                             ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                             interface->name,
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_add_buf),
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, __pio_prefix_buf));
-                    }
-                }
-            }
-            // Remember whether or not this router has a usable prefix.
-            router->usable = usable;
-        }
-    }
-
-    INFO("policy on " PUB_S_SRP ": " PUB_S_SRP "stale " /* stale_routers_exist ? */
-         PUB_S_SRP "started " /* interface->router_discovery_started ? */
-         PUB_S_SRP "disco " /* interface->router_discovery_complete ? */
-         PUB_S_SRP "present " /* on_link_prefix_present ? */
-         PUB_S_SRP "advert " /* interface->our_prefix_advertised ? */
-         PUB_S_SRP "conf " /* interface->on_link_prefix_configured ? */
-         PUB_S_SRP "new_prefix " /* new_prefix ? */
-         "preferred = %" PRIu32 " valid = %" PRIu32 " deadline = %" PRIu64,
-         interface->name, stale_routers_exist ? "" : "!", interface->router_discovery_started ? "" : "!",
-         interface->router_discovery_complete ? "" : "!",
-         on_link_prefix_present ? "" : "!", interface->our_prefix_advertised ? "" : "!",
-         interface->on_link_prefix_configured ? "" : "!", new_prefix ? "" : "!",
-         interface->preferred_lifetime, interface->valid_lifetime, interface->deprecate_deadline);
-
-    // If there are stale routers, start doing router discovery again to see if we can get them to respond.
-    // Note that doing router discover just because we haven't seen an RA is actually not allowed in RFC 4861,
-    // so this shouldn't be enabled.
-    // Also, if we have not yet done router discovery, do it now.
-    if ((!interface->router_discovery_started || !interface->router_discovery_complete
-#if SRP_FEATURE_STALE_ROUTER_DISCOVERY
-         || stale_routers_exist
-#endif //SRP_FEATURE_STALE_ROUTER_DISCOVERY
-            ) && !on_link_prefix_present) {
-        if (!interface->router_discovery_in_progress) {
-            // Start router discovery.
-            INFO("starting router discovery");
-            router_discovery_start(interface);
-        } else {
-            INFO("router discovery in progress");
-        }
-    }
-    // If we are advertising a prefix and there's another on-link prefix, deprecate the one we are
-    // advertising.
-    else if (interface->our_prefix_advertised && on_link_prefix_present) {
-        // If we have been advertising a preferred prefix, deprecate it.
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
-        if (interface->preferred_lifetime == BR_PREFIX_LIFETIME) {
-            INFO("routing_policy_evaluate: deprecating interface prefix in 30 minutes - prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
-            interface->deprecate_deadline = now + BR_PREFIX_LIFETIME * 1000;
-            something_changed = true;
-            interface->preferred_lifetime = FIVE_MINUTES;
-        } else {
-            INFO("prefix deprecating in progress - prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
-        }
-    }
-    // If there is no on-link prefix and we aren't advertising, or have deprecated, start advertising
-    // again (or for the first time).
-    else if (!on_link_prefix_present && interface->router_discovery_complete &&
-             (!interface->our_prefix_advertised || interface->deprecate_deadline != 0 ||
-              interface->preferred_lifetime == 0)) {
-
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
-        INFO("advertising prefix again - ifname: " PUB_S_SRP
-             ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP, interface->name,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
-
-        // If we were deprecating, stop.
-        ioloop_cancel_wake_event(interface->deconfigure_wakeup);
-        interface->deprecate_deadline = 0;
-
-        // Start advertising immediately, 30 minutes.
-        interface->preferred_lifetime = interface->valid_lifetime = BR_PREFIX_LIFETIME;
-
-        // If the on-link prefix isn't configured on the interface, do that.
-        if (!interface->on_link_prefix_configured) {
-#ifndef RA_TESTER
-            if (!interface->is_thread) {
-#endif
-                interface_prefix_configure(interface->ipv6_prefix, interface);
-#ifndef RA_TESTER
-            } else {
-                INFO("Not setting up " PUB_S_SRP " because it is the thread interface", interface->name);
-            }
-#endif
-        } else {
-            // Configuring the on-link prefix takes a while, so we want to re-evaluate after it's finished.
-            interface->our_prefix_advertised = true;
-            something_changed = true;
-        }
-    }
-    // If there is no on-link prefix present, and srp-mdns-proxy itself is advertising the prefix, and it has configured
-    // an on-link prefix, and the interface is not thread interface, and it just got an interface address removal event,
-    // it is possible that the IPv6 routing has been flushed due to loss of address in configd, so here we explicitly
-    // reconfigure the IPv6 prefix and the routing.
-    else if (interface->need_reconfigure_prefix && !on_link_prefix_present && interface->our_prefix_advertised &&
-             interface->on_link_prefix_configured && !interface->is_thread) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
-        INFO("reconfigure ipv6 prefix due to possible network changes -"
-             " prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
-        interface_prefix_configure(interface->ipv6_prefix, interface);
-        interface->need_reconfigure_prefix = false;
-    }
-
-    // If the on-link prefix goes away, stop suppressing the one we've been advertising (if it's still valid).
-    if (!on_link_prefix_present && interface->suppress_ipv6_prefix) {
-        INFO("un-suppressing ipv6 prefix.");
-        interface->suppress_ipv6_prefix = false;
-    }
-
-    // If we've been looking to see if there's an on-link prefix, and we got one from the new router advertisement,
-    // stop looking for new one.
-    if (new_prefix) {
-        router_discovery_stop(interface, now);
-    }
-
-    // If anything changed, do an immediate beacon; otherwise wait until the next one.
-    // Also when something changed, set the number of transmissions back to zero so that
-    // we send a few initial beacons quickly for reliability.
-    if (something_changed) {
-        INFO("change on " PUB_S_SRP ": " PUB_S_SRP "started " PUB_S_SRP "disco " PUB_S_SRP "present " PUB_S_SRP "advert " PUB_S_SRP
-             "conf preferred = %" PRIu32 " valid = %" PRIu32 " deadline = %" PRIu64,
-             interface->name, interface->router_discovery_started ? "" : "!",
-             interface->router_discovery_complete ? "" : "!", on_link_prefix_present ? "" : "!",
-             interface->our_prefix_advertised ? "" : "!", interface->on_link_prefix_configured ? "" : "!",
-             interface->preferred_lifetime,
-             interface->valid_lifetime, interface->deprecate_deadline);
-        interface->num_beacons_sent = 0;
-        interface_beacon_schedule(interface, 0);
-    }
-
-    // It's possible for us to start configuring the interface because there's no on-link prefix, and then see
-    // an advertisement for an on-link prefix before interface configuration completes. When this happens, we
-    // need to delete the address we just configured, because we're not going to be advertising it. We always
-    // get a policy re-evaluation event when interface configuration completes, so this will happen immediately.
-    // At this point we have not yet sent a router advertisement with the prefix, so even though it has a preferred
-    // lifetime of about 1800 seconds here, we can safely set it to zero without leaving stale information
-    // in any host's routing table.
-    if (!interface->our_prefix_advertised && interface->on_link_prefix_configured) {
-        INFO("on-link prefix appeared during interface configuration. removing");
-        interface->preferred_lifetime = 0;
-        interface_prefix_deconfigure(interface);
-    }
-
-#ifdef FLUSH_STALE_ROUTERS
-    // If we have an on-link prefix, schedule a policy re-evaluation at the stale router interval.
-    if (on_link_prefix_present) {
-        if (stale_refresh_time < now) {
-            ERROR("Stale refresh time is in the past: %" PRIu64 "!", stale_refresh_time);
-        } else {
-            // The math used to compute refresh timeout guarantees that refresh_timeout will be <10 minutes.
-            int refresh_timeout = (int)(stale_refresh_time - now);
-
-            if (interface->stale_evaluation_wakeup == NULL) {
-                interface->stale_evaluation_wakeup = ioloop_wakeup_create();
-                if (interface->stale_evaluation_wakeup == NULL) {
-                    ERROR("No memory for stale router evaluation wakeup on " PUB_S_SRP ".", interface->name);
-                }
-            } else {
-                ioloop_cancel_wake_event(interface->stale_evaluation_wakeup);
-            }
-            ioloop_add_wake_event(interface->stale_evaluation_wakeup,
-                                  interface, stale_router_policy_evaluate, NULL, refresh_timeout);
-        }
-    }
-#endif // FLUSH_STALE_ROUTERS
-
-    // Once router discovery is complete, start doing aliveness checks on whatever we discovered (if anything).
-    if (interface->last_router_probe == 0 && interface->router_discovery_started && interface->router_discovery_complete) {
-        schedule_next_router_probe(interface);
-    }
-}
-
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-static void
-start_vicarious_router_discovery_if_appropriate(interface_t *const interface)
-{
-    if (!interface->our_prefix_advertised &&
-        !interface->vicarious_router_discovery_in_progress && !interface->router_discovery_in_progress)
-    {
-        if (interface->vicarious_discovery_complete == NULL) {
-            interface->vicarious_discovery_complete = ioloop_wakeup_create();
-        } else {
-            ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
-        }
-        if (interface->vicarious_discovery_complete != NULL) {
-            ioloop_add_wake_event(interface->vicarious_discovery_complete,
-                                  interface, vicarious_discovery_callback, NULL, 20 * 1000);
-            interface->vicarious_router_discovery_in_progress = true;
-        }
-        // In order for vicarious router discovery to be useful, we need all of the routers
-        // that were present when the first solicit was received to be stale when we give up
-        // on vicarious discovery.  If we got any router advertisements, these will not be
-        // stale, and that means vicarious discovery succeeded.
-        make_all_routers_nearly_stale(interface, ioloop_timenow());
-        INFO("Starting vicarious router discovery on " PUB_S_SRP,
-             interface->name);
-    }
-}
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-
-static void
-retransmit_unicast_beacon(void *context)
-{
-    icmp_message_t *message = context;
-
-    // Schedule retranmsission
-    interface_beacon_send(message->interface, &message->source);
-    ioloop_add_wake_event(message->wakeup, message, retransmit_unicast_beacon, NULL,
-                          MIN_DELAY_BETWEEN_RAS + srp_random16() % RA_FUZZ_TIME);
-
-    // Discontinue retransmission after the third we've sent.
-    if (message->messages_sent++ > 2) {
-        icmp_message_t **sp = &message->interface->solicits;
-        while (*sp != NULL) {
-            if (*sp == message) {
-                *sp = message->next;
-                icmp_message_free(message);
-                break;
-            } else {
-                sp = &(*sp)->next;
-            }
-        }
-    }
-}
-
-// This gets called to check to see if any of the usable routers are still responding. It gets called whenever
-// we get a router solicit, to ensure that the solicit gets a quick response, and also gets called once every
-// minute so that we quickly notice when a router becomes unreachable.
-
-static void
-send_router_probes(void *context)
-{
-    interface_t *interface = context;
-
-    // After sending three probes, do a policy evaluation.
-    if (interface->num_solicits_sent++ > MAX_NS_RETRANSMISSIONS - 1) {
-        // Mark routers from which we received neighbor advertises during the probe as reachable. Routers
-        // that did not respond are no longer reachable.
-        for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
-            router->reachable = router->reached;
-        }
-        routing_policy_evaluate(interface, false);
-        schedule_next_router_probe(interface);
-        return;
-    }
-
-    // Send Neighbor Solicits to any usable routers that haven't responded yet and schedule the next call to
-    // send_router_probes...
-    for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
-        // Don't probe routers that aren't usable, and don't re-probe a router that's already responded in this probe cycle.
-        if (!router->usable || router->reached) {
-            continue;
-        }
-        neighbor_solicit_send(router->interface, &router->source);
-    }
-    ioloop_add_wake_event(interface->neighbor_solicit_wakeup, interface, send_router_probes, NULL,
-                          MIN_DELAY_BETWEEN_RAS + srp_random16() % RA_FUZZ_TIME);
-}
-
-static void
-check_router_aliveness(void *context)
-{
-    interface_t *interface = context;
-
-    if (!interface->probing) {
-        interface->probing = true;
-        if (interface->neighbor_solicit_wakeup == NULL) {
-            interface->neighbor_solicit_wakeup = ioloop_wakeup_create();
-        }
-        if (interface->neighbor_solicit_wakeup != NULL) {
-            interface->num_solicits_sent = 0;
-            // Clear the reached flag on all routers
-            for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
-                router->reached = false;
-            }
-            send_router_probes(interface);
-        }
-    }
-}
-
-static void
-schedule_next_router_probe(interface_t *interface)
-{
-    if (interface->router_probe_wakeup == NULL) {
-        interface->router_probe_wakeup = ioloop_wakeup_create();
-    }
-    if (interface->router_probe_wakeup != NULL) {
-        INFO("scheduling router probe in 60 seconds.");
-        ioloop_add_wake_event(interface->router_probe_wakeup, interface, check_router_aliveness, NULL, 60 * 1000);
-        interface->probing = false;
-        interface->last_router_probe = ioloop_timenow();
-    }
-}
-
-static void
-router_solicit(icmp_message_t *message)
-{
-    interface_t *iface, *interface;
-    bool is_retransmission = false;
-
-    // Further validate the message
-    if (message->hop_limit != 255 || message->code != 0) {
-        ERROR("Invalid router solicitation, hop limit = %d, code = %d", message->hop_limit, message->code);
-        goto out;
-    }
-    if (IN6_IS_ADDR_UNSPECIFIED(&message->source)) {
-        icmp_option_t *option = message->options;
-        int i;
-        for (i = 0; i < message->num_options; i++) {
-            if (option->type == icmp_option_source_link_layer_address) {
-                ERROR("source link layer address in router solicitation from unspecified IP address");
-                goto out;
-            }
-            option++;
-        }
-    } else {
-        // Make sure it's not from this host
-        for (iface = message->route_state->interfaces; iface; iface = iface->next) {
-            if (iface->have_link_layer_address && !memcmp(&message->source,
-                                                          &iface->link_local, sizeof(message->source))) {
-                INFO("dropping router solicitation sent from this host.");
-                goto out;
-            }
-        }
-    }
-    interface = message->interface;
-
-    SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, source_buf);
-    INFO(PUB_S_SRP " solicit on " PUB_S_SRP ": source address is " PRI_SEGMENTED_IPv6_ADDR_SRP,
-         is_retransmission ? "retransmitted" : "initial",
-         message->interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, source_buf));
-
-    // See if this is a retransmission...
-    icmp_message_t **sp;
-    sp = &interface->solicits;
-    while (*sp != NULL) {
-        icmp_message_t *solicit = *sp;
-        // Same source? Not already found?
-        if (!is_retransmission && !memcmp(&message->source, &solicit->source, sizeof(message->source))) {
-            uint64_t now = ioloop_timenow();
-            // RFC 4861 limits RS transmissions to 3, separated by four seconds. Allowing for a bit of slop,
-            // if it was received in the past 15 seconds, this is a retransmission.
-            if (now - solicit->received_time > 15 * 1000) {
-                *sp = solicit->next;
-                icmp_message_free(solicit);
-            } else {
-                solicit->retransmissions_received++;
-                is_retransmission = true;
-
-                // Since this is a retransmission, that hints that there might not be any live routers
-                // on this link, so check to see if the routers we are aware of are alive.
-                check_router_aliveness(interface);
-
-                sp = &(*sp)->next;
-            }
-        } else {
-            sp = &(*sp)->next;
-        }
-    }
-
-    // Schedule an immediate send. If this is a retransmission, just let our retransmission schedule
-    // dictate when to send the next one.
-    if (!is_retransmission && !interface->ineligible && !interface->inactive) {
-        message->wakeup = ioloop_wakeup_create();
-        if (message->wakeup == NULL) {
-            ERROR("no memory for solicit wakeup.");
-        } else {
-            // Save the message for later
-            *sp = message;
-            // Start the unicast RA transmission train for this RS.
-            retransmit_unicast_beacon(message);
-            message = NULL;
-        }
-    } else {
-        INFO("not sending a router advertisement.");
-    }
-
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    // When we receive a router solicit, it means that a host is looking for a router.   We should
-    // expect to hear replies if they are multicast.   If we hear no replies, it could mean there is
-    // no on-link prefix.   In this case, we restart our own router discovery process.  There is no
-    // need to do this if we are the one advertising a prefix.
-    start_vicarious_router_discovery_if_appropriate(interface);
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-out:
-    if (message != NULL) {
-        icmp_message_free(message);
-    }
-}
-
-static void
-router_advertisement(icmp_message_t *message)
-{
-    interface_t *iface;
-    icmp_message_t *router, **rp;
-    if (message->hop_limit != 255 || message->code != 0 || !IN6_IS_ADDR_LINKLOCAL(&message->source)) {
-        ERROR("Invalid router advertisement, hop limit = %d, code = %d", message->hop_limit, message->code);
-        icmp_message_free(message);
-        return;
-    }
-    for (iface = message->route_state->interfaces; iface != NULL; iface = iface->next) {
-        if (iface->have_link_layer_address && !memcmp(&message->source,
-                                                      &iface->link_local, sizeof(message->source))) {
-            INFO("dropping router advertisement sent from this host.");
-            icmp_message_free(message);
-            return;
-        }
-    }
-
-    // See if we've had other advertisements from this router.
-    int num_ras_this_router = 0;
-    for (rp = &message->interface->routers; *rp != NULL; rp = &(*rp)->next) {
-        router = *rp;
-        // The new RA is from the same router as this previous RA.
-        if (!memcmp(&router->source, &message->source, sizeof(message->source))) {
-            int router_usable_prefixes = 0, message_usable_prefixes = 0;
-            int prefixes_withdrawn = 0;
-            int prefixes_added = 0;
-            int prefixes_unchanged = 0;
-            icmp_option_t *router_option = router->options;
-            int i, j;
-
-            // Remember how many RAs we have from this router.
-            num_ras_this_router++;
-
-            // Count the number of usable prefixes retained, withdrawn, and revived, as well as the total number of
-            // usable prefixes in the old RA.
-            for (i = 0; i < router->num_options; i++, router_option++) {
-                if (router_option->type == icmp_option_prefix_information) {
-                    icmp_option_t *message_option = message->options;
-                    prefix_information_t *router_prefix = &router_option->option.prefix_information;
-                    bool router_usable = prefix_usable(router, router_prefix);
-
-                    if (router_usable) {
-                        router_usable_prefixes++;
-                    }
-
-                    for (j = 0; j < message->num_options; j++, message_option++) {
-                        if (message_option->type == icmp_option_prefix_information) {
-                            prefix_information_t *message_prefix = &message_option->option.prefix_information;
-
-                            // Same prefix?
-                            if (router_prefix->length == message_prefix->length &&
-                                !memcmp(&router_prefix->prefix, &message_prefix->prefix, sizeof(router_prefix->prefix)))
-                            {
-                                // Is it still usable?
-                                message_prefix->found = true;
-                                bool message_usable = prefix_usable(message, message_prefix);
-                                if (router_usable && !message_usable) {
-                                    prefixes_withdrawn++;
-                                } else if (!router_usable && message_usable) {
-                                    prefixes_added++; // Added in the sense that it became usable.
-                                } else {
-                                    prefixes_unchanged++;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            // Count the number of /new/ usable prefixes added in the new RA, and the total number of usable prefixes in
-            // the new RA.
-            icmp_option_t *option = message->options;
-            for (i = 0; i < message->num_options; i++, option++) {
-                if (option->type == icmp_option_prefix_information) {
-                    prefix_information_t *prefix = &option->option.prefix_information;
-                    if (prefix_usable(message, prefix)) {
-                        message_usable_prefixes++;
-                        if (!prefix->found) {
-                            prefixes_added++;
-                        }
-                    }
-                }
-            }
-            INFO("router_usable: %d  message_usable: %d  withdrawn: %d  added: %d  unchanged: %d",
-                 router_usable_prefixes, message_usable_prefixes,
-                 prefixes_withdrawn, prefixes_added, prefixes_unchanged);
-            if (
-                // We have to discard the old RA if all its prefixes were withdrawn.
-                (router_usable_prefixes > 0 && prefixes_withdrawn == router_usable_prefixes) ||
-                // We don't need the old RA if all the prefixes that weren't withdrawn are also in the new RA
-                // This is true even if there are no un-withdrawn prefixes in the new RA.
-                (router_usable_prefixes - prefixes_withdrawn == message_usable_prefixes - prefixes_added))
-            {
-                message->next = router->next;
-                *rp = message;
-                icmp_message_free(router);
-                break;
-            }
-            // We need both otherwise, so just continue down the list.
-        }
-    }
-    // If we got rid of the old RA, *rp will be non-NULL. If we didn't find a match for the old RA, or if we
-    // need to keep the old RA, then *rp will be NULL, meaning that we should keep the new RA.
-    if (*rp == NULL) {
-        *rp = message;
-    }
-
-    // Limit the number of RAs we'll retain from an individual router to five (arbitrarily). This prevents weird patterns
-    // of prefix adds and withdrawals from causing the list to grow without bound. Because we lose information by doing this,
-    // it's possible that we could wind up advertising a usable prefix when we don't need to, but this is a safe failure
-    // mode.
-#define MAX_RAS_PER_ROUTER 5
-    if (num_ras_this_router > MAX_RAS_PER_ROUTER) {
-        for (rp = &message->interface->routers; *rp != NULL; ) {
-            router = *rp;
-            if (!memcmp(&router->source, &message->source, sizeof(message->source))) {
-                *rp = router->next;
-                icmp_message_free(router);
-                // This should always be true, but it's no problem if it's not.
-                if (--num_ras_this_router <= MAX_RAS_PER_ROUTER) {
-                    break;
-                }
-            } else {
-                rp = &(*rp)->next;
-            }
-        }
-    }
-
-    // When we receive an RA, we can assume that the router is reachable, and skip immediately probing with a
-    // neighbor solicit.
-    message->latest_na = message->received_time;
-    message->reachable = true;
-
-    // Something may have changed, so do a policy recalculation for this interface
-    routing_policy_evaluate(message->interface, false);
-}
-
-static void
-neighbor_advertisement(icmp_message_t *message)
-{
-    if (message->hop_limit != 255 || message->code != 0) {
-        ERROR("Invalid neighbor advertisement, hop limit = %d, code = %d", message->hop_limit, message->code);
-        return;
-    }
-
-    // If this NA matches a router that has advertised a usable prefix, mark the router as alive by setting the
-    // "latest_na" value to the current time. We don't care about NAs for routers that are not advertising a usable
-    // prefix.
-    for (icmp_message_t *router = message->interface->routers; router != NULL; router = router->next) {
-        if (!memcmp(&message->source, &router->source, sizeof(message->source))) {
-            if (router->usable) {
-                SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, source_buf);
-                INFO("usable neighbor advertisement recieved on " PUB_S_SRP " from " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                     message->interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, source_buf));
-                router->latest_na = ioloop_timenow();
-                router->reached = true;
-                return;
-            } else {
-                router->latest_na = ioloop_timenow();
-                router->reached = true;
-                return;
-            }
-        }
-    }
-    return;
-}
-
-static void
-icmp_message(route_state_t *route_state, uint8_t *icmp_buf, unsigned length, int ifindex, int hop_limit, addr_t *src, addr_t *dest)
-{
-    unsigned offset = 0;
-    uint32_t reserved32;
-    interface_t *interface;
-    icmp_message_t *message = calloc(1, sizeof(*message));
-    if (message == NULL) {
-        ERROR("Unable to allocate icmp_message_t for parsing");
-        return;
-    }
-
-    message->source = src->sin6.sin6_addr;
-    message->destination = dest->sin6.sin6_addr;
-    message->hop_limit = hop_limit;
-    for (interface = route_state->interfaces; interface; interface = interface->next) {
-        if (interface->index == ifindex) {
-            message->interface = interface;
-            break;
-        }
-    }
-    message->received_time = ioloop_timenow();
-    message->received_time_already_adjusted = false;
-    message->new_router = true;
-    message->route_state = route_state;
-
-    if (message->interface == NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, src_buf);
-        SEGMENTED_IPv6_ADDR_GEN_SRP(message->destination.s6_addr, dst_buf);
-        INFO("ICMP message type %d from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
-             " on interface index %d, which isn't listed.",
-             icmp_buf[0], SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, src_buf),
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(message->destination.s6_addr, dst_buf), ifindex);
-        icmp_message_free(message);
-        return;
-    }
-
-    if (length < sizeof (struct icmp6_hdr)) {
-        ERROR("Short ICMP message: length %d is shorter than ICMP header length %zd", length, sizeof(struct icmp6_hdr));
-        icmp_message_free(message);
-        return;
-    }
-    INFO("length %d", length);
-
-    // The increasingly innaccurately named dns parse functions will work fine for this.
-    if (!dns_u8_parse(icmp_buf, length, &offset, &message->type)) {
-        goto out;
-    }
-    if (!dns_u8_parse(icmp_buf, length, &offset, &message->code)) {
-        goto out;
-    }
-    // XXX check the checksum
-    if (!dns_u16_parse(icmp_buf, length, &offset, &message->checksum)) {
-        goto out;
-    }
-    switch(message->type) {
-    case icmp_type_router_advertisement:
-        if (!dns_u8_parse(icmp_buf, length, &offset, &message->cur_hop_limit)) {
-            goto out;
-        }
-        if (!dns_u8_parse(icmp_buf, length, &offset, &message->flags)) {
-            goto out;
-        }
-        if (!dns_u16_parse(icmp_buf, length, &offset, &message->router_lifetime)) {
-            goto out;
-        }
-        if (!dns_u32_parse(icmp_buf, length, &offset, &message->reachable_time)) {
-            goto out;
-        }
-        if (!dns_u32_parse(icmp_buf, length, &offset, &message->retransmission_timer)) {
-            goto out;
-        }
-
-        if (!icmp_message_parse_options(message, icmp_buf, length, &offset)) {
-            goto out;
-        }
-        icmp_message_dump(message, &message->source, &message->destination);
-        router_advertisement(message);
-        // router_advertisement() is given ownership of the message
-        return;
-
-    case icmp_type_router_solicitation:
-        if (!dns_u32_parse(icmp_buf, length, &offset, &reserved32)) {
-            goto out;
-        }
-        if (!icmp_message_parse_options(message, icmp_buf, length, &offset)) {
-            goto out;
-        }
-        icmp_message_dump(message, &message->source, &message->destination);
-        router_solicit(message);
-        // router_solicit() is given ownership of the message.
-        return;
-
-    case icmp_type_neighbor_advertisement:
-        icmp_message_dump(message, &message->source, &message->destination);
-        neighbor_advertisement(message);
-        break;
-
-    case icmp_type_neighbor_solicitation:
-    case icmp_type_echo_request:
-    case icmp_type_echo_reply:
-    case icmp_type_redirect:
-        break;
-    }
-
-out:
-    icmp_message_free(message);
-    return;
-}
-
-#ifndef FUZZING
-static
-#endif
-void
-icmp_callback(io_t *NONNULL io, void *UNUSED context)
-{
-    ssize_t rv;
-    uint8_t icmp_buf[1500];
-    int ifindex = 0;
-    addr_t src, dest;
-    int hop_limit = 0;
-
-#ifndef FUZZING
-    rv = ioloop_recvmsg(io->fd, &icmp_buf[0], sizeof(icmp_buf), &ifindex, &hop_limit, &src, &dest);
-#else
-    rv = read(io->fd, &icmp_buf, sizeof(icmp_buf));
-#endif
-    if (rv < 0) {
-        ERROR("icmp_callback: can't read ICMP message: " PUB_S_SRP, strerror(errno));
-        return;
-    }
-    for (route_state_t *route_state = route_states; route_state != NULL; route_state = route_state->next) {
-        icmp_message(route_state, icmp_buf, (unsigned)rv, ifindex, hop_limit, &src, &dest); // rv will never be > sizeof(icmp_buf)
-    }
-}
-
-#if   defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG) || \
-      defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG)
-static void
-link_route_done(void *context, int status, const char *error)
-{
-    interface_t *interface = context;
-
-    if (error != NULL) {
-        ERROR("link_route_done on " PUB_S_SRP ": " PUB_S_SRP, interface->name, error);
-    } else {
-        INFO("link_route_done on " PUB_S_SRP ": %d.", interface->name, status);
-    }
-    ioloop_subproc_release(interface->link_route_adder_process);
-    interface->link_route_adder_process = NULL;
-    // Now that the on-link prefix is configured, time for a policy re-evaluation.
-    interface->on_link_prefix_configured = true;
-    routing_policy_evaluate(interface, true);
-}
-#endif
-
-static void
-interface_prefix_configure(struct in6_addr prefix, interface_t *interface)
-{
-    int sock;
-    route_state_t *route_state = interface->route_state;
-
-    sock = socket(PF_INET6, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        ERROR("interface_prefix_configure: socket(PF_INET6, SOCK_DGRAM, 0) failed " PUB_S_SRP ": " PUB_S_SRP,
-              interface->name, strerror(errno));
-        return;
-    }
-#ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
-    struct in6_addr interface_address = prefix;
-    char addrbuf[INET6_ADDRSTRLEN + 4];
-    // Use our ULA prefix as the host identifier.
-    memcpy(&interface_address.s6_addr[10], &route_state->srp_server->ula_prefix.s6_addr[0], 6);
-    inet_ntop(AF_INET6, &interface_address, addrbuf, INET6_ADDRSTRLEN);
-#if   defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG)
-    char *args[] = { "set", interface->name, "MANUAL-V6", addrbuf, "64" };
-
-    if (interface->link_route_adder_process != NULL) {
-        ERROR("interface_prefix_configure: " PUB_S_SRP " already configuring the route.", interface->name);
-        return;
-    }
-    INFO("/sbin/ipconfig " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " "
-         PUB_S_SRP, args[0], args[1], args[2], args[3], args[4]);
-    interface->link_route_adder_process = ioloop_subproc("/usr/sbin/ipconfig", args, 5, link_route_done, interface, NULL);
-    if (interface->link_route_adder_process == NULL) {
-        ERROR("interface_prefix_configure: unable to set interface address for %s to %s.", interface->name, addrbuf);
-    }
-#elif defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG)
-    char *eos = addrbuf + strlen(addrbuf);
-    if (sizeof(addrbuf) - (eos - addrbuf) < 4) {
-        ERROR("interface_prefix_configure: this shouldn't happen: no space in addrbuf");
-        return;
-    }
-    strcpy(eos, "/64");
-    char *args[] = { interface->name, "add", addrbuf };
-
-    if (interface->link_route_adder_process != NULL) {
-        ERROR("interface_prefix_configure: " PUB_S_SRP " already configuring the route.", interface->name);
-        return;
-    }
-    INFO("/sbin/ifconfig %s %s %s", args[0], args[1], args[2]);
-    interface->link_route_adder_process = ioloop_subproc("/sbin/ifconfig", args, 3, link_route_done, NULL, interface);
-    if (interface->link_route_adder_process == NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
-        ERROR("interface_prefix_configure: unable to set interface address for " PUB_S_SRP " to "
-              PRI_SEGMENTED_IPv6_ADDR_SRP ".", interface->name,
-              SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf));
-    }
-#else
-    struct in6_aliasreq alias_request;
-    int ret;
-
-    memset(&alias_request, 0, sizeof(alias_request));
-    strlcpy(alias_request.ifra_name, interface->name, IFNAMSIZ);
-    alias_request.ifra_addr.sin6_family = AF_INET6;
-    alias_request.ifra_addr.sin6_len = sizeof(alias_request.ifra_addr);
-    memcpy(&alias_request.ifra_addr.sin6_addr, &interface_address, sizeof(alias_request.ifra_addr.sin6_addr));
-    alias_request.ifra_prefixmask.sin6_len = sizeof(alias_request.ifra_addr);
-    alias_request.ifra_prefixmask.sin6_family = AF_INET6;
-    memset(&alias_request.ifra_prefixmask.sin6_addr, 0xff, 8); // /64.
-    alias_request.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; // seconds, I hope?
-    alias_request.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; // seconds, I hope?
-
-    ret = ioctl(sock, SIOCAIFADDR_IN6, &alias_request);
-    if (ret < 0) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
-        ERROR("interface_prefix_configure: can't configure static address " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP
-              ": " PUB_S_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf), interface->name,
-              strerror(errno));
-    } else {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
-        INFO("added address " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PUB_S_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf), interface->name);
-    }
-#endif // CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG
-#else
-    (void)prefix;
-#endif // CONFIGURE_STATIC_INTERFACE_ADDRESSES
-    close(sock);
-}
-
-static void
-set_thread_forwarding(void)
-{
-#ifdef LINUX
-    const char *procfile = "/proc/sys/net/ipv6/conf/all/forwarding";
-    int fd = open(procfile, O_WRONLY);
-    if (fd < 0) {
-        ERROR("%s: %s", procfile, strerror(errno));
-    } else {
-        ssize_t ret = write(fd, "1", 1);
-        if (ret < 0) {
-            ERROR("write: %s", strerror(errno));
-        } else if (ret != 1) {
-            ERROR("invalid write: %zd", ret);
-        }
-        close(fd);
-    }
-#else
-    int wun = 1;
-    int ret = sysctlbyname("net.inet6.ip6.forwarding", NULL, 0, &wun, sizeof(wun));
-    if (ret < 0) {
-        ERROR(PUB_S_SRP, strerror(errno));
-    } else {
-        INFO("Enabled IPv6 forwarding.");
-    }
-#endif
-}
-
-#ifdef NEED_THREAD_RTI_SETTER
-static void
-thread_rti_done(void *UNUSED context, int status, const char *error)
-{
-    route_state_t *route_state = context;
-
-    if (error != NULL) {
-        ERROR("thread_rti_done: " PUB_S_SRP, error);
-    } else {
-        INFO("%d.", status);
-    }
-    ioloop_subproc_release(route_state->thread_rti_setter_process);
-    route_state->thread_rti_setter_process = NULL;
-}
-
-static void
-set_thread_rti(route_state_t *route_state)
-{
-    char *args[] = { "-w", "net.inet6.icmp6.nd6_process_rti=1" };
-    route_state->thread_rti_setter_process = ioloop_subproc("/usr/sbin/sysctl", args, 2, thread_rti_done,
-                                               NULL, route_state);
-    if (route_state->thread_rti_setter_process == NULL) {
-        ERROR("Unable to set thread rti enabled.");
-    }
-}
-#endif
-
-#if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
-#ifdef ADD_PREFIX_WITH_WPANCTL
-static void
-thread_prefix_done(void *context, int status, const char *error)
-{
-    route_state_t *route_state = context;
-
-    if (error != NULL) {
-        ERROR("thread_prefix_done: " PUB_S_SRP, error);
-    } else {
-        interface_t *interface;
-
-        INFO("%d.", status);
-        for (interface = route_state->interfaces; interface; interface = interface->next) {
-            if (!interface->inactive) {
-                interface_beacon_schedule(interface, 0);
-            }
-        }
-    }
-    ioloop_subproc_release(route_state->thread_prefix_adder_process);
-    route_state->thread_prefix_adder_process = NULL;
-}
-#endif
-
-static void
-cti_add_prefix_callback(void *context, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    interface_t *interface;
-    INFO("%d", status);
-    for (interface = route_state->interfaces; interface; interface = interface->next) {
-        if (!interface->inactive) {
-            interface_beacon_schedule(interface, 0);
-        }
-    }
-}
-
-static thread_prefix_t *
-get_advertised_thread_prefix(route_state_t *route_state)
-{
-    if (route_state->published_thread_prefix != NULL) {
-        return route_state->published_thread_prefix;
-    } else {
-        return route_state->adopted_thread_prefix;
-    }
-    return NULL;
-}
-
-static void
-set_thread_prefix(route_state_t *route_state)
-{
-    char addrbuf[INET6_ADDRSTRLEN];
-    thread_prefix_t *advertised_thread_prefix = get_advertised_thread_prefix(route_state);
-    if (advertised_thread_prefix == NULL) {
-        ERROR("set_thread_prefix: no advertised thread prefix.");
-        return;
-    }
-    SEGMENTED_IPv6_ADDR_GEN_SRP(advertised_thread_prefix->prefix.s6_addr, thread_prefix_buf);
-    inet_ntop(AF_INET6, &advertised_thread_prefix->prefix, addrbuf, sizeof addrbuf);
-#ifdef ADD_PREFIX_WITH_WPANCTL
-    char *args[] = { "add-prefix", "--stable", "--preferred", "--slaac", "--default-route", "--on-mesh", addrbuf };
-    INFO("/usr/local/bin/wpanctl " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " "
-         PRI_SEGMENTED_IPv6_ADDR_SRP, args[0], args[1], args[2], args[3], args[4], args[5],
-         SEGMENTED_IPv6_ADDR_PARAM_SRP(advertised_thread_prefix->prefix.s6_addr, thread_prefix_buf));
-    route_state->thread_prefix_adder_process = ioloop_subproc("/usr/local/bin/wpanctl", args, 7, thread_prefix_done,
-                                                 NULL, NULL);
-    if (route_state->thread_prefix_adder_process == NULL) {
-        ERROR("Unable to add thread interface prefix.");
-    }
-#else
-    INFO("add_prefix(true, true, true, true, " PRI_SEGMENTED_IPv6_ADDR_SRP ")",
-         SEGMENTED_IPv6_ADDR_PARAM_SRP(advertised_thread_prefix->prefix.s6_addr, thread_prefix_buf));
-    int status = cti_add_prefix(route_state, cti_add_prefix_callback, NULL,
-                                &advertised_thread_prefix->prefix, advertised_thread_prefix->prefix_len,
-                                true, true, true, true);
-    if (status != kCTIStatus_NoError) {
-        ERROR("Unable to add thread interface prefix.");
-    }
-#endif
-}
-#endif // THREAD_BORDER_ROUTRER && !RA_TESTER
-
-static void
-router_advertisement_send(interface_t *interface, const struct in6_addr *destination)
-{
-    uint8_t *message;
-    dns_towire_state_t towire;
-    route_state_t *route_state = interface->route_state;
-
-    // Thread blocks RAs so no point sending them.
-    if (interface->inactive
-#ifndef RA_TESTER
-        || interface->is_thread
-#endif
-        ) {
-        return;
-    }
-
-#define MAX_ICMP_MESSAGE 1280
-    message = malloc(MAX_ICMP_MESSAGE);
-    if (message == NULL) {
-        ERROR("router_advertisement_send: unable to construct ICMP Router Advertisement: no memory");
-        return;
-    }
-
-    // Construct the ICMP header and options for each interface.
-    memset(&towire, 0, sizeof towire);
-    towire.p = message;
-    towire.lim = message + MAX_ICMP_MESSAGE;
-
-    // Construct the ICMP header.
-    // We use the DNS message construction functions because it's easy; probably should just make
-    // the towire functions more generic.
-    dns_u8_to_wire(&towire, ND_ROUTER_ADVERT);  // icmp6_type
-    dns_u8_to_wire(&towire, 0);                 // icmp6_code
-    dns_u16_to_wire(&towire, 0);                // The kernel computes the checksum (we don't technically have it).
-    dns_u8_to_wire(&towire, 0);                 // Hop limit, we don't set.
-    dns_u8_to_wire(&towire, 0);                 // Flags.  We don't offer DHCP, so We set neither the M nor the O bit.
-    // We are not a home agent, so no H bit.  Lifetime is 0, so Prf is 0.
-#ifdef ROUTER_LIFETIME_HACK
-    dns_u16_to_wire(&towire, BR_PREFIX_LIFETIME); // Router lifetime, hacked.  This shouldn't ever be enabled.
-#else
-#ifdef RA_TESTER
-    // Advertise a default route on the simulated thread network
-    if (!strcmp(interface->name, route_state->thread_interface_name)) {
-        dns_u16_to_wire(&towire, BR_PREFIX_LIFETIME); // Router lifetime for default route
-    } else {
-#endif
-        dns_u16_to_wire(&towire, 0);            // Router lifetime for non-default default route(s).
-#ifdef RA_TESTER
-    }
-#endif // RA_TESTER
-#endif // ROUTER_LIFETIME_HACK
-    dns_u32_to_wire(&towire, 0);                // Reachable time for NUD, we have no opinion on this.
-    dns_u32_to_wire(&towire, 0);                // Retransmission timer, again we have no opinion.
-
-    // Send Source link-layer address option
-    if (interface->have_link_layer_address) {
-        dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
-        dns_u8_to_wire(&towire, 1); // length / 8
-        dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
-        INFO("advertising source lladdr " PRI_MAC_ADDR_SRP
-             " on " PUB_S_SRP, MAC_ADDR_PARAM_SRP(interface->link_layer), interface->name);
-    }
-
-#ifndef RA_TESTER
-    // Send MTU of 1280 for Thread?
-    if (interface->is_thread) {
-        dns_u8_to_wire(&towire, ND_OPT_MTU);
-        dns_u8_to_wire(&towire, 1); // length / 8
-        dns_u32_to_wire(&towire, 1280);
-        INFO("advertising MTU of 1280 on " PUB_S_SRP, interface->name);
-    }
-#endif
-
-    // Send Prefix Information option if there's no IPv6 on the link.
-    if (interface->our_prefix_advertised && !interface->suppress_ipv6_prefix) {
-        dns_u8_to_wire(&towire, ND_OPT_PREFIX_INFORMATION);
-        dns_u8_to_wire(&towire, 4); // length / 8
-        dns_u8_to_wire(&towire, 64); // On-link prefix is always 64 bits
-        dns_u8_to_wire(&towire, ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO); // On link, autoconfig
-        dns_u32_to_wire(&towire, interface->valid_lifetime);
-        dns_u32_to_wire(&towire, interface->preferred_lifetime);
-        dns_u32_to_wire(&towire, 0); // Reserved
-        dns_rdata_raw_data_to_wire(&towire, &interface->ipv6_prefix, sizeof interface->ipv6_prefix);
-        SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf);
-        INFO("advertising on-link prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf), interface->name);
-
-    }
-
-#ifndef ND_OPT_ROUTE_INFORMATION
-#define ND_OPT_ROUTE_INFORMATION 24
-#endif
-    // In principle we can either send routes to links that are reachable by this router,
-    // or just advertise a router to the entire ULA /48.   In theory it doesn't matter
-    // which we do; if we support HNCP at some point we probably need to be specific, but
-    // for now being general is fine because we have no way to share a ULA.
-    // Unfortunately, some RIO implementations do not work with specific routes, so for now
-    // We are doing it the easy way and just advertising the /48.
-#define SEND_INTERFACE_SPECIFIC_RIOS 1
-#ifdef SEND_INTERFACE_SPECIFIC_RIOS
-
-    // If neither ROUTE_BETWEEN_NON_THREAD_LINKS nor RA_TESTER are defined, then we never want to
-    // send an RIO other than for the thread network prefix.
-#if defined (ROUTE_BETWEEN_NON_THREAD_LINKS) || defined(RA_TESTER)
-    interface_t *ifroute;
-    // Send Route Information option for other interfaces.
-    for (ifroute = route_state->interfaces; ifroute; ifroute = ifroute->next) {
-        if (ifroute->inactive) {
-            continue;
-        }
-        if (want_routing(route_state) &&
-            ifroute->our_prefix_advertised &&
-#ifdef SEND_ON_LINK_ROUTE
-            // In theory we don't want to send RIO for the on-link prefix, but there's this bug, see.
-            true &&
-#else
-            ifroute != interface &&
-#endif
-#ifdef RA_TESTER
-            // For the RA tester, we don't need to send an RIO to the thread network because we're the
-            // default router for that network.
-            strcmp(interface->name, route_state->thread_interface_name)
-#else
-            true
-#endif
-            )
-        {
-            dns_u8_to_wire(&towire, ND_OPT_ROUTE_INFORMATION);
-            dns_u8_to_wire(&towire, 2); // length / 8
-            dns_u8_to_wire(&towire, 64); // Interface prefixes are always 64 bits
-            dns_u8_to_wire(&towire, 0); // There's no reason at present to prefer one Thread BR over another
-            dns_u32_to_wire(&towire, BR_PREFIX_LIFETIME); // Route lifetime 1800 seconds (30 minutes)
-            dns_rdata_raw_data_to_wire(&towire, &ifroute->ipv6_prefix, 8); // /64 requires 8 bytes.
-            SEGMENTED_IPv6_ADDR_GEN_SRP(ifroute->ipv6_prefix.s6_addr, ipv6_prefix_buf);
-            INFO("Sending route to " PRI_SEGMENTED_IPv6_ADDR_SRP "%%" PUB_S_SRP " on " PUB_S_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(ifroute->ipv6_prefix.s6_addr, ipv6_prefix_buf),
-                 ifroute->name, interface->name);
-        }
-    }
-#endif // ROUTE_BETWEEN_NON_THREAD_LINKS || RA_TESTER
-
-#ifndef RA_TESTER
-    // Send route information option for thread prefix
-    thread_prefix_t *advertised_thread_prefix = get_advertised_thread_prefix(route_state);
-    if (advertised_thread_prefix != NULL) {
-        dns_u8_to_wire(&towire, ND_OPT_ROUTE_INFORMATION);
-        dns_u8_to_wire(&towire, 2); // length / 8
-        dns_u8_to_wire(&towire, 64); // Interface prefixes are always 64 bits
-        dns_u8_to_wire(&towire, 0); // There's no reason at present to prefer one Thread BR over another
-        dns_u32_to_wire(&towire, BR_PREFIX_LIFETIME); // Route lifetime 1800 seconds (30 minutes)
-        dns_rdata_raw_data_to_wire(&towire, &advertised_thread_prefix->prefix, 8); // /64 requires 8 bytes.
-        SEGMENTED_IPv6_ADDR_GEN_SRP(advertised_thread_prefix->prefix.s6_addr, thread_prefix_buf);
-        INFO("Sending route to " PRI_SEGMENTED_IPv6_ADDR_SRP "%%" PUB_S_SRP " on " PUB_S_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(advertised_thread_prefix->prefix.s6_addr, thread_prefix_buf),
-             route_state->thread_interface_name, interface->name);
-    }
-#endif
-#else
-#ifndef SKIP_SLASH_48
-    dns_u8_to_wire(&towire, ND_OPT_ROUTE_INFORMATION);
-    dns_u8_to_wire(&towire, 3); // length / 8
-    dns_u8_to_wire(&towire, 48); // ULA prefixes are always 48 bits
-    dns_u8_to_wire(&towire, 0); // There's no reason at present to prefer one Thread BR over another
-    dns_u32_to_wire(&towire, BR_PREFIX_LIFETIME); // Route lifetime 1800 seconds (30 minutes)
-    dns_rdata_raw_data_to_wire(&towire, &route_state->srp_server->ula_prefix, 16); // /48 requires 16 bytes
-#endif // SKIP_SLASH_48
-#endif // SEND_INTERFACE_SPECIFIC_RIOS
-
-    if (towire.error) {
-        ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
-        towire.error = 0;
-    } else {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(destination->s6_addr, destination_buf);
-        INFO("sending advertisement to " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(destination->s6_addr, destination_buf),
-             interface->name);
-        icmp_send(message, towire.p - message, interface, destination);
-    }
-    free(message);
-}
-
-static void
-router_solicit_send(interface_t *interface)
-{
-    uint8_t *message;
-    dns_towire_state_t towire;
-
-    // Thread blocks RSs so no point sending them.
-    if (interface->inactive
-#ifndef RA_TESTER
-        || interface->is_thread
-#endif
-        ) {
-        return;
-    }
-
-#define MAX_ICMP_MESSAGE 1280
-    message = malloc(MAX_ICMP_MESSAGE);
-    if (message == NULL) {
-        ERROR("Unable to construct ICMP Router Advertisement: no memory");
-        return;
-    }
-
-    // Construct the ICMP header and options for each interface.
-    memset(&towire, 0, sizeof towire);
-    towire.p = message;
-    towire.lim = message + MAX_ICMP_MESSAGE;
-
-    // Construct the ICMP header.
-    // We use the DNS message construction functions because it's easy; probably should just make
-    // the towire functions more generic.
-    dns_u8_to_wire(&towire, ND_ROUTER_SOLICIT);  // icmp6_type
-    dns_u8_to_wire(&towire, 0);                  // icmp6_code
-    dns_u16_to_wire(&towire, 0);                 // The kernel computes the checksum (we don't technically have it).
-    dns_u32_to_wire(&towire, 0);                 // Reserved32
-
-    // Send Source link-layer address option
-    if (interface->have_link_layer_address) {
-        dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
-        dns_u8_to_wire(&towire, 1); // length / 8
-        dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
-    }
-
-    if (towire.error) {
-        ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
-    } else {
-        icmp_send(message, towire.p - message, interface, &in6addr_linklocal_allrouters);
-    }
-    free(message);
-}
-
-static void
-neighbor_solicit_send(interface_t *interface, struct in6_addr *destination)
-{
-    uint8_t *message;
-    dns_towire_state_t towire;
-
-#define MAX_ICMP_MESSAGE 1280
-    message = malloc(MAX_ICMP_MESSAGE);
-    if (message == NULL) {
-        ERROR("Unable to construct ICMP Router Advertisement: no memory");
-        return;
-    }
-
-    // Construct the ICMP header and options for each interface.
-    memset(&towire, 0, sizeof towire);
-    towire.p = message;
-    towire.lim = message + MAX_ICMP_MESSAGE;
-
-    // Construct the ICMP header.
-    // We use the DNS message construction functions because it's easy; probably should just make
-    // the towire functions more generic.
-    dns_u8_to_wire(&towire, ND_NEIGHBOR_SOLICIT);  // icmp6_type
-    dns_u8_to_wire(&towire, 0);                    // icmp6_code
-    dns_u16_to_wire(&towire, 0);                   // The kernel computes the checksum (we don't technically have it).
-    dns_u32_to_wire(&towire, 0);                   // Reserved32
-    dns_rdata_raw_data_to_wire(&towire, destination, sizeof(*destination)); // Target address of solicit
-
-    // Send Source link-layer address option
-    if (interface->have_link_layer_address) {
-        dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
-        dns_u8_to_wire(&towire, 1); // length / 8
-        dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
-    }
-
-    if (towire.error) {
-        ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
-    } else {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(destination, dest_buf);
-        INFO("sending neighbor solicit on " PUB_S_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(destination, dest_buf));
-        icmp_send(message, towire.p - message, interface, destination);
-    }
-    free(message);
-}
-
-static void
-icmp_send(uint8_t *message, size_t length, interface_t *interface, const struct in6_addr *destination)
-{
-#ifdef FUZZING
-    char buffer[length];
-    memcpy(buffer, message, length);
-    return;
-#endif
-    struct iovec iov;
-    struct in6_pktinfo *packet_info;
-    socklen_t cmsg_length = CMSG_SPACE(sizeof(*packet_info)) + CMSG_SPACE(sizeof (int));
-    uint8_t *cmsg_buffer;
-    struct msghdr msg_header;
-    struct cmsghdr *cmsg_pointer;
-    int hop_limit = 255;
-    ssize_t rv;
-    struct sockaddr_in6 dest;
-
-    // Make space for the control message buffer.
-    cmsg_buffer = calloc(1, cmsg_length);
-    if (cmsg_buffer == NULL) {
-        ERROR("Unable to construct ICMP Router Advertisement: no memory");
-        return;
-    }
-
-    // Send the message
-    memset(&dest, 0, sizeof(dest));
-    dest.sin6_family = AF_INET6;
-    dest.sin6_scope_id = interface->index;
-#ifndef NOT_HAVE_SA_LEN
-    dest.sin6_len = sizeof(dest);
-#endif
-    msg_header.msg_namelen = sizeof(dest);
-    dest.sin6_addr = *destination;
-
-    msg_header.msg_name = &dest;
-    iov.iov_base = message;
-    iov.iov_len = length;
-    msg_header.msg_iov = &iov;
-    msg_header.msg_iovlen = 1;
-    msg_header.msg_control = cmsg_buffer;
-    msg_header.msg_controllen = cmsg_length;
-
-    // Specify the interface
-    cmsg_pointer = CMSG_FIRSTHDR(&msg_header);
-    cmsg_pointer->cmsg_level = IPPROTO_IPV6;
-    cmsg_pointer->cmsg_type = IPV6_PKTINFO;
-    cmsg_pointer->cmsg_len = CMSG_LEN(sizeof(*packet_info));
-    packet_info = (struct in6_pktinfo *)CMSG_DATA(cmsg_pointer);
-    memset(packet_info, 0, sizeof(*packet_info));
-    packet_info->ipi6_ifindex = interface->index;
-
-    // Router advertisements and solicitations have a hop limit of 255
-    cmsg_pointer = CMSG_NXTHDR(&msg_header, cmsg_pointer);
-    cmsg_pointer->cmsg_level = IPPROTO_IPV6;
-    cmsg_pointer->cmsg_type = IPV6_HOPLIMIT;
-    cmsg_pointer->cmsg_len = CMSG_LEN(sizeof(int));
-    memcpy(CMSG_DATA(cmsg_pointer), &hop_limit, sizeof(hop_limit));
-
-    // Send it
-    rv = sendmsg(icmp_listener.io_state->fd, &msg_header, 0);
-    if (rv < 0) {
-        uint8_t *in6_addr_bytes = ((struct sockaddr_in6 *)(msg_header.msg_name))->sin6_addr.s6_addr;
-        SEGMENTED_IPv6_ADDR_GEN_SRP(in6_addr_bytes, in6_addr_buf);
-        ERROR("icmp_send: sending " PUB_S_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP " on interface " PUB_S_SRP
-              " index %d: " PUB_S_SRP, message[0] == ND_ROUTER_SOLICIT ? "solicit" : "advertise",
-              SEGMENTED_IPv6_ADDR_PARAM_SRP(in6_addr_bytes, in6_addr_buf),
-              interface->name, interface->index, strerror(errno));
-    } else if ((size_t)rv != iov.iov_len) {
-        ERROR("icmp_send: short send to interface " PUB_S_SRP ": %zd < %zd", interface->name, rv, iov.iov_len);
-    }
-    free(cmsg_buffer);
-}
-
-static void
-post_solicit_policy_evaluate(void *context)
-{
-    interface_t *interface = context;
-    INFO("Done waiting for router discovery to finish on " PUB_S_SRP, interface->name);
-    interface->router_discovery_complete = true;
-    interface->router_discovery_in_progress = false;
-#ifdef FLUSH_STALE_ROUTERS
-    flush_stale_routers(interface, ioloop_timenow());
-#endif // FLUSH_STALE_ROUTERS
-
-    // See if we need a new prefix on the interface.
-    interface_prefix_evaluate(interface);
-
-    routing_policy_evaluate(interface, true);
-    // Always clear out need_reconfigure_prefix when router_discovery_complete is set to true.
-    interface->need_reconfigure_prefix = false;
-}
-
-static void
-ula_record(const char *ula_printable)
-{
-    size_t len = strlen(ula_printable);
-    if (access(THREAD_DATA_DIR, F_OK) < 0) {
-        if (mkdir(THREAD_DATA_DIR, 0700) < 0) {
-            ERROR("ula_record: " THREAD_DATA_DIR " not present and can't be created: %s", strerror(errno));
-            return;
-        }
-    }
-    srp_store_file_data(NULL, THREAD_ULA_FILE, (uint8_t *)ula_printable, len);
-}
-
-void
-route_ula_generate(route_state_t *route_state)
-{
-    char ula_prefix_buffer[INET6_ADDRSTRLEN];
-    struct in6_addr ula_prefix, old_ula_prefix;
-    bool prefix_changed;
-
-    // Already have a prefix?
-    if (route_state->srp_server->ula_prefix.s6_addr[0] == 0xfd) {
-        old_ula_prefix = route_state->srp_server->ula_prefix;
-        prefix_changed = true;
-    } else {
-        prefix_changed = false;
-    }
-
-    memset(&ula_prefix, 0, sizeof(ula_prefix));
-    srp_randombytes(&ula_prefix.s6_addr[1], 5);
-    ula_prefix.s6_addr[0] = 0xfd;
-
-    inet_ntop(AF_INET6, &ula_prefix, ula_prefix_buffer, sizeof ula_prefix_buffer);
-
-    ula_record(ula_prefix_buffer);
-    if (prefix_changed) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(old_ula_prefix.s6_addr, old_prefix_buf);
-        SEGMENTED_IPv6_ADDR_GEN_SRP(ula_prefix.s6_addr, new_prefix_buf);
-        INFO("ula-generate: prefix changed from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(old_ula_prefix.s6_addr, old_prefix_buf),
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(ula_prefix.s6_addr, new_prefix_buf));
-    } else {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(ula_prefix.s6_addr, new_prefix_buf);
-        INFO("ula-generate: generated ULA prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(ula_prefix.s6_addr, new_prefix_buf));
-    }
-
-    // Set up the thread prefix.
-    route_state->my_thread_prefix = ula_prefix;
-    route_state->srp_server->ula_prefix = ula_prefix;
-    route_state->have_thread_prefix = true;
-#if SRP_FEATURE_NAT64
-    if (route_state->srp_server->srp_nat64_enabled) {
-        nat64_set_ula_prefix(&ula_prefix);
-    }
-#endif
-}
-
-void
-route_ula_setup(route_state_t *route_state)
-{
-    bool have_stored_ula_prefix = false;
-
-    char ula_buf[INET6_ADDRSTRLEN];
-    uint16_t length;
-    if (srp_load_file_data(NULL, THREAD_ULA_FILE, (uint8_t *)ula_buf, &length, sizeof(ula_buf) - 1)) {
-        ula_buf[length] = 0;
-        if (inet_pton(AF_INET6, ula_buf, &route_state->srp_server->ula_prefix)) {
-            have_stored_ula_prefix = true;
-        } else {
-            INFO("ula prefix %.*s is not valid", length, ula_buf);
-        }
-    } else {
-        INFO("Couldn't open ULA file " THREAD_ULA_FILE ".");
-    }
-
-    // If we didn't already successfully fetch a stored prefix, try to store one.
-    if (!have_stored_ula_prefix) {
-        route_ula_generate(route_state);
-    } else {
-        // Set up the thread prefix.
-        route_state->my_thread_prefix = route_state->srp_server->ula_prefix;
-        route_state->have_thread_prefix = true;
-#if SRP_FEATURE_NAT64
-        if (route_state->srp_server->srp_nat64_enabled) {
-            nat64_set_ula_prefix(&route_state->srp_server->ula_prefix);
-        }
-#endif
-    }
-}
-
-bool
-start_icmp_listener(void)
-{
-    int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-    int true_flag = 1;
-#ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
-    int false_flag = 0;
-#endif
-    struct icmp6_filter filter;
-    ssize_t rv;
-
-    if (sock < 0) {
-        ERROR("Unable to listen for icmp messages: " PUB_S_SRP, strerror(errno));
-        close(sock);
-        return false;
-    }
-
-    // Only accept router advertisements and router solicits.
-    ICMP6_FILTER_SETBLOCKALL(&filter);
-    ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
-    ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
-    ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
-    rv = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
-    if (rv < 0) {
-        ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
-        close(sock);
-        return false;
-    }
-
-    // We want a source address and interface index
-    rv = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &true_flag, sizeof(true_flag));
-    if (rv < 0) {
-        ERROR("Can't set IPV6_RECVPKTINFO: " PUB_S_SRP ".", strerror(errno));
-        close(sock);
-        return false;
-    }
-
-    // We need to be able to reject RAs arriving from off-link.
-    rv = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &true_flag, sizeof(true_flag));
-    if (rv < 0) {
-        ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
-        close(sock);
-        return false;
-    }
-
-#ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
-    // Prevent our router advertisements from updating our routing table.
-    rv = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &false_flag, sizeof(false_flag));
-    if (rv < 0) {
-        ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
-        close(sock);
-        return false;
-    }
-#endif
-
-    icmp_listener.io_state = ioloop_file_descriptor_create(sock, NULL, NULL);
-    if (icmp_listener.io_state == NULL) {
-        ERROR("No memory for ICMP I/O structure.");
-        close(sock);
-        return false;
-    }
-
-    // Beacon out a router advertisement every three minutes.
-    icmp_listener.unsolicited_interval = 3 * 60 * 1000;
-    ioloop_add_reader(icmp_listener.io_state, icmp_callback);
-
-    return true;
-}
-
-static void
-interface_router_solicit_finalize(void *context)
-{
-    interface_t *interface = context;
-    interface->router_solicit_wakeup = NULL;
-}
-
-static void
-router_solicit_callback(void *context)
-{
-    interface_t *interface = context;
-    if (interface->is_thread) {
-        INFO("discontinuing router solicitations on thread interface " PUB_S_SRP, interface->name);
-        return;
-    }
-    if (interface->num_solicits_sent >= 3) {
-        INFO("Done sending router solicitations on " PUB_S_SRP ".", interface->name);
-        return;
-    }
-    INFO("sending router solicitation on " PUB_S_SRP , interface->name);
-    router_solicit_send(interface);
-
-    interface->num_solicits_sent++;
-    ioloop_add_wake_event(interface->router_solicit_wakeup,
-                          interface, router_solicit_callback, interface_router_solicit_finalize,
-                          RTR_SOLICITATION_INTERVAL * 1000 + srp_random16() % 1024);
-}
-
-static void
-start_router_solicit(interface_t *interface)
-{
-    if (interface->router_solicit_wakeup == NULL) {
-        interface->router_solicit_wakeup = ioloop_wakeup_create();
-        if (interface->router_solicit_wakeup == 0) {
-            ERROR("No memory for router solicit wakeup on " PUB_S_SRP ".", interface->name);
-            return;
-        }
-    } else {
-        ioloop_cancel_wake_event(interface->router_solicit_wakeup);
-    }
-    interface->num_solicits_sent = 0;
-    ioloop_add_wake_event(interface->router_solicit_wakeup, interface, router_solicit_callback,
-                          interface_router_solicit_finalize, 128 + srp_random16() % 896);
-}
-
-static void
-icmp_interface_subscribe(interface_t *interface, bool added)
-{
-    struct ipv6_mreq req;
-    int rv;
-
-    if (icmp_listener.io_state == NULL) {
-        ERROR("Interface subscribe without ICMP listener.");
-        return;
-    }
-
-    memset(&req, 0, sizeof req);
-    if (interface->index == -1) {
-        ERROR("icmp_interface_subscribe called before interface index fetch for " PUB_S_SRP, interface->name);
-        return;
-    }
-
-    req.ipv6mr_multiaddr = in6addr_linklocal_allrouters;
-    req.ipv6mr_interface = interface->index;
-    rv = setsockopt(icmp_listener.io_state->fd, IPPROTO_IPV6, added ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &req,
-                    sizeof req);
-    if (rv < 0) {
-        ERROR("Unable to " PUB_S_SRP " all-routers multicast group on " PUB_S_SRP ": " PUB_S_SRP,
-              added ? "join" : "leave", interface->name, strerror(errno));
-        return;
-    } else {
-        INFO(PUB_S_SRP "subscribed on interface " PUB_S_SRP, added ? "" : "un",
-             interface->name);
-    }
-
-    req.ipv6mr_multiaddr = in6addr_linklocal_allnodes;
-    req.ipv6mr_interface = interface->index;
-    rv = setsockopt(icmp_listener.io_state->fd, IPPROTO_IPV6, added ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &req,
-                    sizeof req);
-    if (rv < 0) {
-        ERROR("Unable to " PUB_S_SRP " all-nodes multicast group on " PUB_S_SRP ": " PUB_S_SRP,
-              added ? "join" : "leave", interface->name, strerror(errno));
-        return;
-    } else {
-        INFO(PUB_S_SRP "subscribed on interface " PUB_S_SRP, added ? "" : "un",
-             interface->name);
-    }
-
-}
-
-static interface_t *
-find_interface(route_state_t *route_state, const char *name, int ifindex)
-{
-    interface_t **p_interface, *interface = NULL;
-
-    for (p_interface = &route_state->interfaces; *p_interface; p_interface = &(*p_interface)->next) {
-        interface = *p_interface;
-        if (!strcmp(name, interface->name)) {
-            if (ifindex != -1 && interface->index != ifindex) {
-                INFO("interface name " PUB_S_SRP " index changed from %d to %d", name, interface->index, ifindex);
-                interface->index = ifindex;
-            }
-            break;
-        }
-    }
-
-    // If it's a new interface, make a structure.
-    // We could do a callback, but don't have a use case
-    if (*p_interface == NULL) {
-        interface = interface_create(route_state, name, ifindex);
-        if (interface != NULL) {
-            if (route_state->thread_interface_name != NULL && !strcmp(name, route_state->thread_interface_name)) {
-                interface->is_thread = true;
-            }
-            *p_interface = interface;
-        }
-    }
-    return interface;
-}
-
-
-static void
-interface_shutdown(interface_t *interface)
-{
-    icmp_message_t *router, *next;
-    INFO("Interface " PUB_S_SRP " went away.", interface->name);
-    if (interface->beacon_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->beacon_wakeup);
-    }
-    if (interface->post_solicit_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->post_solicit_wakeup);
-    }
-    if (interface->stale_evaluation_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->stale_evaluation_wakeup);
-    }
-    if (interface->router_solicit_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->router_solicit_wakeup);
-    }
-    if (interface->deconfigure_wakeup != NULL) {
-        ioloop_cancel_wake_event(interface->deconfigure_wakeup);
-    }
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    if (interface->vicarious_discovery_complete != NULL) {
-        ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
-    }
-    interface->vicarious_router_discovery_in_progress = false;
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    for (router = interface->routers; router; router = next) {
-        next = router->next;
-        icmp_message_free(router);
-    }
-    interface->routers = NULL;
-    interface->last_beacon = interface->next_beacon = 0;
-    interface->deprecate_deadline = 0;
-    interface->preferred_lifetime = interface->valid_lifetime = 0;
-    interface->num_solicits_sent = 0;
-    interface->inactive = true;
-    interface->ineligible = true;
-    interface->our_prefix_advertised = false;
-    interface->suppress_ipv6_prefix = false;
-    interface->have_link_layer_address = false;
-    interface->on_link_prefix_configured = false;
-    interface->sent_first_beacon = false;
-    interface->num_beacons_sent = 0;
-    interface->router_discovery_started = false;
-    interface->router_discovery_complete = false;
-    interface->router_discovery_in_progress = false;
-    interface->need_reconfigure_prefix = false;
-}
-
-static void
-interface_prefix_evaluate(interface_t *interface)
-{
-    route_state_t *route_state = interface->route_state;
-    // Set up the interface prefix using the prefix number for the link.
-    interface->ipv6_prefix = route_state->xpanid_prefix;
-}
-
-static void
-interface_active_state_evaluate(interface_t *interface, bool active_known, bool active)
-{
-    route_state_t *route_state = interface->route_state;
-    INFO("evaluating interface active status - ifname: " PUB_S_SRP
-         ", active_known: " PUB_S_SRP ", active: " PUB_S_SRP ", inactive: " PUB_S_SRP,
-         interface->name, active_known ? "true" : "false", active ? "true" : "false",
-         interface->inactive ? "true" : "false");
-
-    if (active_known && !active) {
-        if (!interface->inactive) {
-#ifndef RA_TESTER
-            bool active_infrastructure = false;
-            for (interface_t *scan = route_state->interfaces; scan != NULL; scan = scan->next) {
-                if (scan != interface && !scan->inactive && !scan->ineligible) {
-                    active_infrastructure = true;
-                }
-            }
-            // Don't be a border router if there is no infrastructure interface left.
-            if (route_state->thread_network_running && !active_infrastructure && !interface->inactive && !interface->ineligible) {
-                INFO("interface " PUB_S_SRP " went away, and there is no other infrastructure interface: shutting down thread network",
-                     interface->name);
-
-                thread_network_shutdown(route_state);
-            } else {
-                INFO("interface " PUB_S_SRP " went away, "
-                     PUB_S_SRP "thread " PUB_S_SRP "infra " PUB_S_SRP "inactive " PUB_S_SRP "ineligible.",
-                     interface->name,
-                     route_state->thread_network_running ? "" : "!", active_infrastructure ? "" : "!",
-                     interface->inactive ? "" : "!", interface->ineligible ? "" : "!");
-            }
-#else // RA_TESTER
-            INFO("interface " PUB_S_SRP " went away.", interface->name);
-#endif
-            // Set up the thread-local prefix
-            interface_prefix_evaluate(interface);
-
-            // We need to reevaluate routing policy on the new primary interface now, because
-            // there may be no new event there to trigger one.
-            routing_policy_evaluate(interface, true);
-
-            // Clean the slate.
-            icmp_interface_subscribe(interface, false);
-            interface_shutdown(interface);
-
-            // Zero IPv4 addresses.
-            interface->num_ipv4_addresses = 0;
-
-#if !defined(RA_TESTER) && SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY && SRP_FEATURE_DYNAMIC_CONFIGURATION
-            // Clear the corresponding served_domain_t in dnssd-proxy that is associated with this removed interface.
-            delete_served_domain_by_interface_name(interface->name);
-#endif
-
-            INFO("interface went down - ifname: " PUB_S_SRP, interface->name);
-        }
-    } else if (active_known) {
-        if (interface->inactive) {
-#ifndef RA_TESTER
-            bool active_infrastructure = false;
-            for (interface_t *scan = route_state->interfaces; scan != NULL; scan = scan->next) {
-                if (scan != interface && !scan->inactive && !scan->ineligible) {
-                    active_infrastructure = true;
-                }
-            }
-            // If this is the first infrastructure interface to show up, start the thread network
-            if (!route_state->thread_network_running &&
-                !active_infrastructure && interface->inactive && !interface->ineligible)
-            {
-                INFO("interface " PUB_S_SRP " showed up, and there is no other infrastructure interface: starting thread network",
-                     interface->name);
-                thread_network_startup(route_state);
-            } else {
-                INFO("interface " PUB_S_SRP " showed up, "
-                     PUB_S_SRP "thread " PUB_S_SRP "infra " PUB_S_SRP "inactive " PUB_S_SRP "ineligible.",
-                     interface->name,
-                     route_state->thread_network_running ? "" : "!", active_infrastructure ? "" : "!",
-                     interface->inactive ? "" : "!", interface->ineligible ? "" : "!");
-            }
-#else // !RA_TESTER
-            INFO("interface " PUB_S_SRP " showed up.", interface->name);
-#endif
-#ifdef RA_TESTER
-            if (!strcmp(interface->name, route_state->thread_interface_name) ||
-                !strcmp(interface->name, route_state->home_interface_name))
-            {
-#endif
-                // Zero IPv4 addresses.
-                interface->num_ipv4_addresses = 0;
-
-                icmp_interface_subscribe(interface, true);
-                interface->inactive = false;
-
-                interface_prefix_evaluate(interface);
-                if (want_routing(route_state)) {
-                    INFO("starting router discovery");
-                    router_discovery_start(interface);
-
-                    // If we already have a thread prefix, trigger beaconing now.
-                    if (route_state->published_thread_prefix != NULL || route_state->adopted_thread_prefix != NULL) {
-                        interface_beacon_schedule(interface, 0);
-                    } else {
-                        INFO("No prefix on thread network, so not scheduling beacon.");
-                    }
-                } else {
-                    INFO("Can't provide routing, so not scheduling beacon.");
-                }
-#ifdef RA_TESTER
-            } else {
-                INFO("skipping interface " PUB_S_SRP " because it's not home or thread.", interface->name);
-            }
-#endif
-        }
-    }
-}
-
-
-static void
-ifaddr_callback(void *context, const char *name, const addr_t *address, const addr_t *mask,
-                unsigned flags, enum interface_address_change change)
-{
-    char addrbuf[INET6_ADDRSTRLEN];
-    const uint8_t *addrbytes, *maskbytes, *prefp;
-    int preflen, i;
-    interface_t *interface;
-    route_state_t *route_state = context;
-
-#ifndef POSIX_BUILD
-    interface = find_interface(route_state, name, -1);
-#else
-    interface = find_interface(route_state, name, if_nametoindex(name));
-#endif
-    if (interface == NULL) {
-        ERROR("find_interface returned NULL for " PUB_S_SRP, name);
-        return;
-    }
-
-    const bool is_thread_interface = interface->is_thread;
-
-    if (address->sa.sa_family == AF_INET) {
-        addrbytes = (uint8_t *)&address->sin.sin_addr;
-        maskbytes = (uint8_t *)&mask->sin.sin_addr;
-        prefp = maskbytes + 3;
-        preflen = 32;
-        if (change == interface_address_added) {
-            // Just got an IPv4 address?
-            if (!interface->num_ipv4_addresses) {
-                if (!(flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
-                    interface_prefix_evaluate(interface);
-                }
-            }
-            interface->num_ipv4_addresses++;
-        } else if (change == interface_address_deleted) {
-            interface->num_ipv4_addresses--;
-            // Just lost our last IPv4 address?
-            if (!(flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
-                if (!interface->num_ipv4_addresses) {
-                    interface_prefix_evaluate(interface);
-                }
-            }
-        }
-    } else if (address->sa.sa_family == AF_INET6) {
-        addrbytes = (uint8_t *)&address->sin6.sin6_addr;
-        maskbytes = (uint8_t *)&mask->sin6.sin6_addr;
-        prefp = maskbytes + 15;
-        preflen = 128;
-#ifndef LINUX
-    } else if (address->sa.sa_family == AF_LINK) {
-        snprintf(addrbuf, sizeof addrbuf, "%02x:%02x:%02x:%02x:%02x:%02x",
-                 address->ether_addr.addr[0], address->ether_addr.addr[1],
-                 address->ether_addr.addr[2], address->ether_addr.addr[3],
-                 address->ether_addr.addr[4], address->ether_addr.addr[5]);
-        prefp = (uint8_t *)&addrbuf[0]; maskbytes = prefp + 1; // Skip prefix length calculation
-        preflen = 0;
-        addrbytes = NULL;
-#endif
-    } else {
-        INFO("Unknown address type %d", address->sa.sa_family);
-        return;
-    }
-
-    if (change != interface_address_unchanged) {
-#ifndef LINUX
-        if (address->sa.sa_family == AF_LINK) {
-            if (!interface->ineligible) {
-                INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_MAC_ADDR_SRP " flags %x",
-                     name, is_thread_interface ? " (thread)" : "",
-                     change == interface_address_added ? "added" : "removed",
-                     MAC_ADDR_PARAM_SRP(address->ether_addr.addr), flags);
-            }
-        } else {
-#endif
-            for (; prefp >= maskbytes; prefp--) {
-                if (*prefp) {
-                    break;
-                }
-                preflen -= 8;
-            }
-            for (i = 0; i < 8; i++) {
-                if (*prefp & (1<<i)) {
-                    break;
-                }
-                --preflen;
-            }
-            inet_ntop(address->sa.sa_family, addrbytes, addrbuf, sizeof addrbuf);
-            if (!interface->ineligible) {
-                if (address->sa.sa_family == AF_INET) {
-                    IPv4_ADDR_GEN_SRP(addrbytes, addr_buf);
-                    INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_IPv4_ADDR_SRP
-                         "/%d flags %x", name, is_thread_interface ? " (thread)" : "",
-                         change == interface_address_added ? "added" : "removed",
-                         IPv4_ADDR_PARAM_SRP(addrbytes, addr_buf), preflen, flags);
-                } else if (address->sa.sa_family == AF_INET6) {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(addrbytes, addr_buf);
-                    INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_SEGMENTED_IPv6_ADDR_SRP
-                         "/%d flags %x", name, is_thread_interface ? " (thread)" : "",
-                         change == interface_address_added ? "added" : "removed",
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(addrbytes, addr_buf), preflen, flags);
-                } else {
-                    INFO("invalid sa_family: %d", address->sa.sa_family);
-                }
-
-                // Only notify dnssd-proxy when srp-mdns-proxy and dnssd-proxy is combined together.
-            #if !defined(RA_TESTER) && (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-                // Notify dnssd-proxy that address is added or removed.
-                if (!is_thread_interface) {
-                    if (change == interface_address_added) {
-                        if (!interface->inactive) {
-                            dnssd_proxy_ifaddr_callback(context, name, address, mask, flags, change);
-                        }
-                    } else { // change == interface_address_removed
-                        dnssd_proxy_ifaddr_callback(context, name, address, mask, flags, change);
-                    }
-                }
-            #endif // #if !defined(RA_TESTER) && (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-
-                // When new IP address is removed, it is possible that the existing router information, such as
-                // PIO and RIO is no longer valid since srp-mdns-proxy is losing its IP address. In order to let it to
-                // flush the stale router information as soon as possible, we mark all the router as stale immediately,
-                // by setting the router received time to a value which is 601s ago (router will be stale if the router
-                // information is received for more than 600s). And then do router discovery for 20s, so we can ensure
-                // that all the stale router information will be updated during the discovery, or flushed away. If all
-                // routers are flushed, then srp-mdns-proxy will advertise its own prefix and configure the new IPv6
-                // address.
-                if ((address->sa.sa_family == AF_INET || address->sa.sa_family == AF_INET6) &&
-                    change == interface_address_deleted)
-                {
-#ifdef VICARIOUS_ROUTER_DISCOVERY
-                    INFO("making all routers stale and start router discovery due to removed address");
-                    adjust_router_received_time(interface, ioloop_timenow(),
-                                                -(MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE + MSEC_PER_SEC));
-#endif
-                    // Explicitly set router_discovery_complete to false so we can ensure that srp-mdns-proxy will start
-                    // the router discovery immediately.
-                    interface->router_discovery_complete = false;
-                    interface->router_discovery_started = false;
-                    // Set need_reconfigure_prefix to true to let routing_policy_evaluate know that the router discovery
-                    // is caused by interface removal event, so when the router discovery finished and nothing changes,
-                    // it can reconfigure the IPv6 routing in case configured does not handle it correctly.
-                    interface->need_reconfigure_prefix = true;
-                    routing_policy_evaluate(interface, false);
-                }
-            }
-#ifndef LINUX
-        }
-#endif
-    }
-
-    // Not a broadcast interface
-    if (flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
-        // Not the thread interface
-        if (!is_thread_interface) {
-            return;
-        }
-    }
-
-    // 169.254.*
-    if (address->sa.sa_family == AF_INET && IN_LINKLOCAL(address->sin.sin_addr.s_addr)) {
-        return;
-    }
-
-    if (interface->index == -1) {
-        interface->index = address->ether_addr.index;
-    }
-
-#if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
-    if (is_thread_interface && address->sa.sa_family == AF_INET6) {
-        partition_utun0_address_changed(route_state, &address->sin6.sin6_addr, change);
-    }
-#endif
-
-    if (address->sa.sa_family == AF_INET) {
-    } else if (address->sa.sa_family == AF_INET6) {
-        if (IN6_IS_ADDR_LINKLOCAL(&address->sin6.sin6_addr)) {
-            interface->link_local = address->sin6.sin6_addr;
-        }
-#ifndef LINUX
-    } else if (address->sa.sa_family == AF_LINK) {
-        if (address->ether_addr.len == 6) {
-            memcpy(interface->link_layer, address->ether_addr.addr, 6);
-            interface->have_link_layer_address = true;
-        }
-#endif
-    }
-#if defined(POSIX_BUILD)
-    interface_active_state_evaluate(interface, true, true);
-#endif
-}
-
-static void
-refresh_interface_list(route_state_t *route_state)
-{
-    interface_t *interface;
-    bool UNUSED have_active = false;
-    ioloop_map_interface_addresses_here(&route_state->interface_addresses, NULL, route_state, ifaddr_callback);
-    for (interface = route_state->interfaces; interface; interface = interface->next) {
-        if (!interface->ineligible && !interface->inactive) {
-            have_active = true;
-        }
-    }
-
-#ifndef RA_TESTER
-    // Notice if we have lost or gained infrastructure.
-    if (have_active && !route_state->have_non_thread_interface) {
-        INFO("we have an active interface");
-        route_state->have_non_thread_interface = true;
-        route_state->partition_can_advertise_service = true;
-    } else if (!have_active && route_state->have_non_thread_interface) {
-        INFO("we no longer have an active interface");
-        route_state->have_non_thread_interface = false;
-        // Stop advertising the service, if we are doing so.
-        partition_discontinue_srp_service(route_state);
-    }
-#endif // RA_TESTER
-}
-
-
-#if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
-#if !defined(RA_TESTER)
-#if defined(POSIX_BUILD)
-static void
-wpan_reconnect_wakeup_callback(void *context)
-{
-    if (route_state->wpan_reconnect_wakeup != NULL) {
-        ioloop_wakeup_release(route_state->wpan_reconnect_wakeup);
-        route_state->wpan_reconnect_wakeup = NULL;
-    }
-    // Attempt to restart the thread network...
-    infrastructure_network_startup(context);
-}
-#endif
-
-static void
-attempt_wpan_reconnect(route_state_t *route_state)
-{
-#if defined(POSIX_BUILD)
-    if (route_state->wpan_reconnect_wakeup == NULL) {
-        route_state->wpan_reconnect_wakeup = ioloop_wakeup_create();
-        if (route_state->wpan_reconnect_wakeup == NULL) {
-            ERROR("attempt_wpan_reconnect: can't allocate wpan reconnect wait wakeup.");
-            return;
-        }
-        INFO("delaying for ten seconds before attempt to reconnect to thread daemon.");
-        ioloop_add_wake_event(route_state->wpan_reconnect_wakeup, NULL,
-                              wpan_reconnect_wakeup_callback, NULL, 10 * 1000);
-        partition_state_reset(route_state);
-#endif
-    }
-}
-#endif // RA_TESTER
-
-static void
-cti_get_tunnel_name_callback(void *context, const char *name, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    INFO("" PUB_S_SRP " %d", name != NULL ? name : "<null>", status);
-    if (status != kCTIStatus_NoError) {
-        return;
-    }
-    route_state->num_thread_interfaces = 1;
-    if (route_state->thread_interface_name != NULL) {
-        free(route_state->thread_interface_name);
-    }
-    route_state->thread_interface_name = strdup(name);
-    if (route_state->thread_interface_name == NULL) {
-        ERROR("No memory to save thread interface name " PUB_S_SRP, name);
-        return;
-    }
-    INFO("Thread interface at " PUB_S_SRP, route_state->thread_interface_name);
-    partition_got_tunnel_name(route_state);
-}
-
-static void
-cti_get_role_callback(void *context, cti_network_node_type_t role, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    bool am_thread_router = false;
-
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    if (status == kCTIStatus_NoError) {
-        route_state->partition_last_role_change = ioloop_timenow();
-
-        if (role == kCTI_NetworkNodeType_Router || role == kCTI_NetworkNodeType_Leader) {
-            am_thread_router = true;
-        }
-
-        INFO("role is: " PUB_S_SRP " (%d)\n ", am_thread_router ? "router" : "not router", role);
-    } else {
-        ERROR("cti_get_role_callback: nonzero status %d", status);
-    }
-
-    // Our thread role doesn't actually matter, but it's useful to report it in the logs.
-}
-
-static void
-cti_get_state_callback(void *context, cti_network_state_t state, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    bool associated = false;
-
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(context);
-        return;
-    }
-
-    route_state->partition_last_state_change = ioloop_timenow();
-
-    if (status == kCTIStatus_NoError) {
-        if ((state == kCTI_NCPState_Associated)     || (state == kCTI_NCPState_Isolated) ||
-            (state == kCTI_NCPState_NetWake_Asleep) || (state == kCTI_NCPState_NetWake_Waking))
-        {
-            associated = true;
-        }
-
-        INFO("state is: " PUB_S_SRP " (%d)\n ", associated ? "associated" : "not associated", state);
-    } else {
-        ERROR("cti_get_state_callback: nonzero status %d", status);
-    }
-
-    if (route_state->current_thread_state != state) {
-        if (associated) {
-            route_state->current_thread_state = state;
-            partition_maybe_enable_services(route_state); // but probably not
-        } else {
-            route_state->current_thread_state = state;
-            partition_disable_service(route_state);
-        }
-    }
-}
-
-static void
-cti_get_partition_id_callback(void *context, uint64_t partition_id, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    if (status == kCTIStatus_NoError) {
-        INFO("Partition ID changed to %" PRIu64, partition_id);
-        // Partition ID is actually only 32 bits
-        route_state->thread_partition_id[0] = (uint8_t)((partition_id >> 24) & 255);
-        route_state->thread_partition_id[1] = (uint8_t)((partition_id >> 16) & 255);
-        route_state->thread_partition_id[2] = (uint8_t)((partition_id >> 8) & 255);
-        route_state->thread_partition_id[3] = (uint8_t)(partition_id & 255);
-
-        partition_id_changed(route_state);
-    } else {
-        ERROR("nonzero status %d", status);
-    }
-}
-
-static void
-re_evaluate_interfaces(route_state_t *route_state)
-{
-    for (interface_t *interface = route_state->interfaces; interface != NULL; interface = interface->next) {
-        interface_prefix_evaluate(interface);
-    }
-
-    partition_maybe_enable_services(route_state);
-}
-
-static void
-cti_get_xpanid_callback(void *context, uint64_t new_xpanid, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    if (status == kCTIStatus_NoError) {
-        if (route_state->partition_has_xpanid) {
-            ERROR("Unexpected change to XPANID from %" PRIu64 " to %" PRIu64,
-                  route_state->xpanid, new_xpanid);
-        } else {
-            INFO("XPANID is now %" PRIu64, new_xpanid);
-        }
-    } else {
-        ERROR("nonzero status %d", status);
-        return;
-    }
-
-    route_state->xpanid = new_xpanid;
-    route_state->partition_has_xpanid = true;
-    memset(&route_state->xpanid_prefix, 0, sizeof(route_state->xpanid_prefix));
-    route_state->xpanid_prefix.s6_addr[0] = 0xfd;
-    for (int i = 1; i < 8; i++) {
-        route_state->xpanid_prefix.s6_addr[i] = ((route_state->xpanid >> ((15 - i) * 8)) & 255);
-    }
-    route_state->have_xpanid_prefix = true;
-    re_evaluate_interfaces(route_state);
-}
-
-static void
-thread_service_note(thread_service_t *service, const char *event_description)
-{
-    uint16_t port;
-
-    port = (service->port[0] << 8) | service->port[1];
-    SEGMENTED_IPv6_ADDR_GEN_SRP(service->address, service_add_buf);
-    INFO("SRP service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d " PUB_S_SRP,
-         SEGMENTED_IPv6_ADDR_PARAM_SRP(service->address, service_add_buf),
-         port, event_description);
-}
-
-static void
-thread_pref_id_note(thread_pref_id_t *pref_id, const char *event_description)
-{
-    struct in6_addr addr;
-
-    addr.s6_addr[0] = 0xfd;
-    memcpy(&addr.s6_addr[1], pref_id->prefix, 5);
-    memset(&addr.s6_addr[6], 0, 10);
-    SEGMENTED_IPv6_ADDR_GEN_SRP(addr.s6_addr, addr_buf);
-    INFO("pref:id " PRI_SEGMENTED_IPv6_ADDR_SRP ":%02x%02x%02x%02x " PUB_S_SRP,
-         SEGMENTED_IPv6_ADDR_PARAM_SRP(addr.s6_addr, addr_buf),
-         pref_id->partition_id[0], pref_id->partition_id[1], pref_id->partition_id[2], pref_id->partition_id[3],
-         event_description);
-}
-
-typedef struct state_debug_accumulator {
-    char change[20]; // " +stable +user +ncp"
-    char *p_change;
-    size_t left;
-    bool changed;
-} accumulator_t;
-
-static void
-accumulator_init(accumulator_t *accumulator)
-{
-    memset(accumulator, 0, sizeof(*accumulator));
-    accumulator->p_change = accumulator->change;
-    accumulator->left = sizeof(accumulator->change);
-}
-
-static void
-accumulate(accumulator_t *accumulator, bool previous, bool cur, const char *name)
-{
-    size_t len;
-    if (previous != cur) {
-        snprintf(accumulator->p_change, accumulator->left, "%s%s%s",
-                 accumulator->p_change == accumulator->change ? "" : " ", cur ? "+" : "-", name);
-        len = strlen(accumulator->p_change);
-        accumulator->p_change += len;
-        accumulator->left -= len;
-        accumulator->changed = true;
-    }
-}
-
-static void
-cti_service_list_callback(void *context, cti_service_vec_t *services, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    size_t i;
-    thread_service_t **pservice = &route_state->thread_services, *service = NULL;
-    thread_pref_id_t **ppref_id = &route_state->thread_pref_ids, *pref_id = NULL;
-
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    if (status != kCTIStatus_NoError) {
-        ERROR("cti_service_list_callback: %d", status);
-    } else {
-        // Delete any SRP services that are not in the list provided by Thread.
-        while (*pservice != NULL) {
-            service = *pservice;
-            for (i = 0; i < services->num; i++) {
-                cti_service_t *cti_service = services->services[i];
-                // Is this a valid SRP service?
-                if (IS_SRP_SERVICE(cti_service)) {
-                    // Is this service still present?
-                    if (!memcmp(&service->address, cti_service->server, 16) &&
-                        !memcmp(&service->port, &cti_service->server[16], 2)) {
-                        break;
-                    }
-                }
-            }
-            if (i == services->num) {
-                thread_service_note(service, "went away");
-                *pservice = service->next;
-                RELEASE_HERE(service, thread_service_finalize);
-                service = NULL;
-            } else {
-                // We'll re-initialize these flags from the service list when we check for duplicates.
-                service->previous_user = service->user;
-                service->user = false;
-                service->previous_stable = service->stable;
-                service->stable = false;
-                service->previous_ncp = service->ncp;
-                service->ncp = false;
-                pservice = &service->next;
-            }
-        }
-        // On exit, pservice is pointing to the end-of-list pointer.
-
-        // Delete any pref_id services that are not in the list provided by Thread.
-        while (*ppref_id != NULL) {
-            pref_id = *ppref_id;
-            for (i = 0; i < services->num; i++) {
-                cti_service_t *cti_service = services->services[i];
-                // Is this an SRP service?
-                if (IS_PREF_ID_SERVICE(cti_service)) {
-                    // Is this service still present?
-                    if (!memcmp(&pref_id->partition_id, cti_service->server, 4) &&
-                        !memcmp(pref_id->prefix, &cti_service->server[4], 5))
-                    {
-                        break;
-                    }
-                }
-            }
-            if (i == services->num) {
-                thread_pref_id_note(pref_id, "went away");
-                *ppref_id = pref_id->next;
-                RELEASE_HERE(pref_id, thread_pref_id_finalize);
-            } else {
-                // We'll re-initialize these flags from the service list when we check for duplicates.
-                pref_id->previous_user = pref_id->user;
-                pref_id->user = false;
-                pref_id->previous_stable = pref_id->stable;
-                pref_id->stable = false;
-                pref_id->previous_ncp = pref_id->ncp;
-                pref_id->ncp = false;
-                ppref_id = &pref_id->next;
-            }
-        }
-        // On exit, pservice is pointing to the end-of-list pointer.
-
-        // Add any services that are not present.
-        for (i = 0; i < services->num; i++) {
-            cti_service_t *cti_service = services->services[i];
-            if (IS_SRP_SERVICE(cti_service)) {
-                for (service = route_state->thread_services; service != NULL; service = service->next) {
-                    if (!memcmp(&service->address, cti_service->server, 16) &&
-                        !memcmp(&service->port, &cti_service->server[16], 2)) {
-                        break;
-                    }
-                }
-                if (service == NULL) {
-                    service = thread_service_create(cti_service->server, &cti_service->server[16]);
-                    if (service == NULL) {
-                        ERROR("cti_service_list_callback: no memory for service.");
-                    } else {
-                        thread_service_note(service, "showed up");
-                        *pservice = service;
-                        pservice = &service->next;
-                    }
-                }
-                // Also, since we're combing the list, update ncp, user and stable flags.   Note that a service can
-                // appear more than once in the thread service list.
-                if (service != NULL) {
-                    if (cti_service->flags & kCTIFlag_NCP) {
-                        service->ncp = true;
-                    } else {
-                        service->user = true;
-                    }
-                    if (cti_service->flags & kCTIFlag_Stable) {
-                        service->stable = true;
-                    }
-                }
-            } else if (IS_PREF_ID_SERVICE(cti_service)) {
-                for (pref_id = route_state->thread_pref_ids; pref_id != NULL; pref_id = pref_id->next) {
-                    if (!memcmp(&pref_id->partition_id, cti_service->server, 4) &&
-                        !memcmp(pref_id->prefix, &cti_service->server[4], 5))
-                    {
-                        break;
-                    }
-                }
-                if (pref_id == NULL) {
-                    pref_id = thread_pref_id_create(cti_service->server, &cti_service->server[4]);
-                    if (pref_id == NULL) {
-                        ERROR("cti_service_list_callback: no memory for pref_id.");
-                    } else {
-                        thread_pref_id_note(pref_id, "showed up");
-                        *ppref_id = pref_id;
-                        ppref_id = &pref_id->next;
-                    }
-                }
-                // Also, since we're combing the list, update ncp, user and stable flags.   Note that a pref_id can
-                // appear more than once in the thread pref_id list.
-                if (pref_id != NULL) {
-                    if (!pref_id->ncp && (cti_service->flags & kCTIFlag_NCP)) {
-                        pref_id->ncp = true;
-                    } else if (!pref_id->user && !(cti_service->flags & kCTIFlag_NCP)) {
-                        pref_id->user = true;
-                    }
-                    if (cti_service->flags & kCTIFlag_Stable) {
-                        pref_id->stable = true;
-                    }
-                }
-            }
-        }
-
-        accumulator_t accumulator;
-        for (service = route_state->thread_services; service != NULL; service = service->next) {
-            accumulator_init(&accumulator);
-            accumulate(&accumulator, service->previous_ncp, service->ncp, "ncp");
-            accumulate(&accumulator, service->previous_stable, service->ncp, "stable");
-            accumulate(&accumulator, service->previous_user, service->user, "user");
-            if (accumulator.changed) {
-                thread_service_note(service, accumulator.change);
-            }
-        }
-        for (pref_id = route_state->thread_pref_ids; pref_id != NULL; pref_id = pref_id->next) {
-            accumulator_init(&accumulator);
-            accumulate(&accumulator, pref_id->previous_ncp, pref_id->ncp, "ncp");
-            accumulate(&accumulator, pref_id->previous_stable, pref_id->ncp, "stable");
-            accumulate(&accumulator, pref_id->previous_user, pref_id->user, "user");
-            if (accumulator.changed) {
-                thread_pref_id_note(pref_id, accumulator.change);
-            }
-        }
-
-        // At this point the thread prefix list contains the same information as what we just received.
-        // Trigger a "prefix set changed" event.
-        partition_service_set_changed(route_state);
-    }
-}
-
-void
-adv_ctl_add_prefix(route_state_t *route_state, const uint8_t *const data)
-{
-    thread_prefix_t **ppref = &route_state->thread_prefixes, *prefix = NULL;
-
-    for (prefix = route_state->thread_prefixes; prefix != NULL; prefix = prefix->next) {
-        if (!memcmp(&prefix->prefix, data, BR_PREFIX_SLASH_64_BYTES)) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-            INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " already there",
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-            break;
-        }
-    }
-    if (prefix == NULL) {
-        prefix = thread_prefix_create((struct in6_addr *)data, BR_PREFIX_SLASH_64_BYTES);
-        if (prefix == NULL) {
-            ERROR("no memory for prefix.");
-        } else {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-            INFO("adding prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-            prefix->next = *ppref;
-            *ppref = prefix;
-        }
-    }
-}
-
-void
-adv_ctl_remove_prefix(route_state_t *route_state, const uint8_t *const data)
-{
-    thread_prefix_t **ppref = &route_state->thread_prefixes, *prefix = NULL;
-
-    while (*ppref != NULL) {
-        prefix = *ppref;
-        if (!memcmp(&prefix->prefix, data, BR_PREFIX_SLASH_64_BYTES)) {
-            *ppref = prefix->next;
-            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-            INFO("removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-            RELEASE_HERE(prefix, thread_prefix_finalize);
-            return;
-        } else {
-            ppref = &prefix->next;
-        }
-    }
-    INFO("no prefix removed.");
-}
-
-static void
-cti_prefix_list_callback(void *context, cti_prefix_vec_t *prefixes, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    size_t i;
-    thread_prefix_t **ppref = &route_state->thread_prefixes, *prefix = NULL;
-
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        attempt_wpan_reconnect(route_state);
-        return;
-    }
-
-    if (status != kCTIStatus_NoError) {
-        ERROR("cti_get_prefix_list_callback: %d", status);
-    } else {
-        // Delete any prefixes that are not in the list provided by Thread.
-        while (*ppref != NULL) {
-            prefix = *ppref;
-            for (i = 0; i < prefixes->num; i++) {
-                cti_prefix_t *cti_prefix = prefixes->prefixes[i];
-                // Is this prefix still present?
-                if (!memcmp(&prefix->prefix, &cti_prefix->prefix, 8)) {
-                    break;
-                }
-            }
-            if (i == prefixes->num) {
-                *ppref = prefix->next;
-                SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-                INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " went away",
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-                RELEASE_HERE(prefix, thread_prefix_finalize);
-            } else {
-                // We'll re-initialize these flags from the prefix list when we check for duplicates.
-                prefix->user = false;
-                prefix->stable = false;
-                prefix->ncp = false;
-                ppref = &prefix->next;
-            }
-        }
-        // On exit, ppref is pointing to the end-of-list pointer.
-
-        // Add any prefixes that are not present.
-        for (i = 0; i < prefixes->num; i++) {
-            cti_prefix_t *cti_prefix = prefixes->prefixes[i];
-            for (prefix = route_state->thread_prefixes; prefix != NULL; prefix = prefix->next) {
-                if (!memcmp(&prefix->prefix, &cti_prefix->prefix, 16)) {
-                    break;
-                }
-            }
-            if (prefix == NULL) {
-                prefix = thread_prefix_create(&cti_prefix->prefix, cti_prefix->prefix_length);
-                if (prefix == NULL) {
-                    ERROR("cti_prefix_list_callback: no memory for prefix.");
-                } else {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-                    INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " showed up",
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-                    *ppref = prefix;
-                    ppref = &prefix->next;
-                }
-            }
-            // Also, since we're combing the list, update ncp, user and stable flags.   Note that a prefix can
-            // appear more than once in the thread prefix list.
-            if (prefix != NULL) {
-                if (cti_prefix->flags & kCTIFlag_NCP) {
-                    prefix->ncp = true;
-                } else {
-                    prefix->user = true;
-                }
-                if (cti_prefix->flags & kCTIFlag_Stable) {
-                    prefix->stable = true;
-                }
-            }
-        }
-
-        // At this point the thread prefix list contains the same information as what we just received.
-        // Trigger a "prefix set changed" event.
-        partition_prefix_set_changed(route_state);
-    }
-}
-#endif // THREAD_BORDER_ROUTER && !RA_TESTER
-
-void
-infrastructure_network_startup(route_state_t *route_state)
-{
-    INFO("Thread network started.");
-
-//    ioloop_network_watcher_start(network_watch_event);
-    set_thread_forwarding();
-}
-
-#if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
-static void
-thread_network_startup(route_state_t *route_state)
-{
-    int status = cti_get_state(&route_state->thread_state_context, route_state, cti_get_state_callback, NULL);
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_network_node_type(&route_state->thread_role_context, route_state, cti_get_role_callback, NULL);
-    }
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_service_list(&route_state->thread_service_context, route_state, cti_service_list_callback, NULL);
-    }
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_prefix_list(&route_state->thread_prefix_context, route_state, cti_prefix_list_callback, NULL);
-    }
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_tunnel_name(route_state, cti_get_tunnel_name_callback, NULL);
-    }
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_partition_id(&route_state->thread_partition_id_context, route_state,
-                                      cti_get_partition_id_callback, NULL);
-    }
-    if (status == kCTIStatus_NoError) {
-        status = cti_get_extended_pan_id(&route_state->thread_xpanid_context, route_state, cti_get_xpanid_callback, NULL);
-    }
-    if (status != kCTIStatus_NoError) {
-        if (status == kCTIStatus_DaemonNotRunning) {
-            attempt_wpan_reconnect(route_state);
-        } else {
-            ERROR("initial network setup failed");
-        }
-    }
-    route_state->thread_network_running = true;
-}
-#endif //  defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
-
-#ifndef RA_TESTER
-static void
-thread_network_shutdown(route_state_t *route_state)
-{
-    // Stop publishing a default route on the Thread network.
-    if (route_state->adopted_thread_prefix != NULL) {
-        partition_unpublish_prefix(route_state, route_state->adopted_thread_prefix);
-        INFO("removing adopted thread prefix to remove.");
-    } else {
-        INFO("no adopted thread prefix to remove.");
-    }
-    if (route_state->published_thread_prefix != NULL) {
-        partition_unpublish_prefix(route_state, route_state->published_thread_prefix);
-        INFO("removing published thread prefix to remove.");
-    } else {
-        INFO("no published thread prefix to remove.");
-    }
-
-    if (route_state->thread_state_context) {
-        INFO("discontinuing state events");
-        cti_events_discontinue(route_state->thread_state_context);
-        route_state->thread_state_context = NULL;
-    }
-    if (route_state->thread_role_context) {
-        INFO("discontinuing role events");
-        cti_events_discontinue(route_state->thread_role_context);
-        route_state->thread_role_context = NULL;
-    }
-    if (route_state->thread_service_context) {
-        INFO("discontinuing service events");
-        cti_events_discontinue(route_state->thread_service_context);
-        route_state->thread_service_context = NULL;
-    }
-    if (route_state->thread_prefix_context) {
-        INFO("discontinuing prefix events");
-        cti_events_discontinue(route_state->thread_prefix_context);
-        route_state->thread_prefix_context = NULL;
-    }
-    if (route_state->thread_partition_id_context) {
-        INFO("discontinuing partition ID events");
-        cti_events_discontinue(route_state->thread_partition_id_context);
-        route_state->thread_partition_id_context = NULL;
-    }
-    partition_state_reset(route_state);
-}
-#endif // RA_TESTER
-
-void
-infrastructure_network_shutdown(route_state_t *route_state)
-{
-    interface_t *interface;
-
-#ifndef RA_TESTER
-    if (route_state->thread_network_running) {
-        thread_network_shutdown(route_state);
-    }
-#endif
-    INFO("Infrastructure network shutdown.");
-    // Stop all activity on interfaces.
-    for (interface = route_state->interfaces; interface; interface = interface->next) {
-        interface_shutdown(interface);
-    }
-}
-
-#ifndef RA_TESTER
-static void
-partition_state_reset(route_state_t *route_state)
-{
-    thread_prefix_t *prefix, *next_prefix = NULL;
-    thread_service_t *service, *next_service = NULL;
-    thread_pref_id_t *pref_id, *next_pref_id = NULL;
-
-    // Remove any saved state from the thread network.
-    for (prefix = route_state->thread_prefixes; prefix != NULL; prefix = next_prefix) {
-        next_prefix = prefix->next;
-        RELEASE_HERE(prefix, thread_prefix_finalize);
-    }
-    route_state->thread_prefixes = NULL;
-
-    if (route_state->published_thread_prefix != NULL) {
-        RELEASE_HERE(route_state->published_thread_prefix, thread_prefix_finalize);
-        route_state->published_thread_prefix = NULL;
-    }
-    if (route_state->adopted_thread_prefix != NULL) {
-        RELEASE_HERE(route_state->adopted_thread_prefix, thread_prefix_finalize);
-        route_state->adopted_thread_prefix = NULL;
-    }
-
-    for (service = route_state->thread_services; service != NULL; service = next_service) {
-        next_service = service->next;
-        RELEASE_HERE(service, thread_service_finalize);
-    }
-    route_state->thread_services = NULL;
-
-    for (pref_id = route_state->thread_pref_ids; pref_id != NULL; pref_id = next_pref_id) {
-        next_pref_id = pref_id->next;
-        RELEASE_HERE(pref_id, thread_pref_id_finalize);
-    }
-    route_state->thread_pref_ids = NULL;
-
-    route_state->current_thread_state = kCTI_NCPState_Uninitialized;
-
-    route_state->partition_last_prefix_set_change = 0;
-    route_state->partition_last_pref_id_set_change = 0;
-    route_state->partition_last_partition_id_change = 0;
-    route_state->partition_last_role_change = 0;
-    route_state->partition_last_state_change = 0;
-    route_state->partition_settle_start = 0;
-    route_state->partition_service_last_add_time = 0;
-    route_state->partition_id_is_known = false;
-    route_state->partition_have_prefix_list = false;
-    route_state->partition_have_pref_id_list = false;
-    route_state->partition_tunnel_name_is_known = false;
-    route_state->partition_can_advertise_service = false;
-    route_state->partition_can_provide_routing = false;
-    route_state->partition_has_xpanid = false;
-    route_state->partition_may_offer_service = false;
-    route_state->partition_settle_satisfied = true;
-
-    if (route_state->partition_settle_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_settle_wakeup);
-    }
-
-    if (route_state->partition_post_partition_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_post_partition_wakeup);
-    }
-
-    if (route_state->partition_pref_id_wait_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_pref_id_wait_wakeup);
-    }
-
-    if (route_state->partition_service_add_pending_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_service_add_pending_wakeup);
-    }
-
-    route_state->thread_network_running = false;
-}
-
-static int UNUSED
-prefcmp(uint8_t *a, uint8_t *b, int len)
-{
-    int i;
-    for (i = 0; i < len; i++) {
-        if (a[i] < b[i]) return -1;
-        if (a[i] > b[i]) return 1;
-    }
-    return 0;
-}
-
-static void
-partition_prefix_remove_callback(void *context, cti_status_t status)
-{
-    route_state_t *UNUSED route_state = context;
-    if (status != kCTIStatus_NoError) {
-        ERROR("partition_prefix_remove_callback: failed to unpublish my prefix: %d.", status);
-    } else {
-        INFO("done unpublishing my prefix.");
-    }
-}
-
-static void
-partition_stop_advertising_pref_id_done(void *UNUSED context, cti_status_t status)
-{
-    route_state_t *UNUSED route_state = context;
-    INFO("%d", status);
-}
-
-void
-partition_stop_advertising_pref_id(route_state_t *route_state)
-{
-    // This should remove any copy of the service that this BR is advertising.
-    uint8_t service_info[] = { 0, 0, 0, 1 };
-    int status;
-
-    INFO("%" PRIu64 "/%02x" , THREAD_ENTERPRISE_NUMBER, service_info[0]);
-    service_info[0] = THREAD_PREF_ID_OPTION & 255;
-    status = cti_remove_service(route_state, partition_stop_advertising_pref_id_done,
-                                NULL, THREAD_ENTERPRISE_NUMBER, service_info, 1);
-    if (status != kCTIStatus_NoError) {
-        INFO("status %d", status);
-    }
-}
-
-static void
-partition_advertise_pref_id_done(void *context, cti_status_t status)
-{
-    route_state_t *UNUSED route_state = context;
-    INFO("%d", status);
-}
-
-static void
-partition_advertise_pref_id(route_state_t *route_state, uint8_t *prefix)
-{
-    // This should remove any copy of the service that this BR is advertising.
-    uint8_t service_info[] = { 0, 0, 0, 1 };
-    uint8_t pref_id[9];
-    memcpy(pref_id, route_state->thread_partition_id, 4);
-    memcpy(&pref_id[4], prefix, 5);
-    uint8_t full_prefix[6] = {0xfd, prefix[0], prefix[1], prefix[2], prefix[3], prefix[4]};
-
-    service_info[0] = THREAD_PREF_ID_OPTION & 255;
-    IPv6_PREFIX_GEN_SRP(full_prefix, sizeof(full_prefix), prefix_buf);
-    INFO("%" PRIu64 "/%02x/%02x%02x%02x%02x" PRI_IPv6_PREFIX_SRP,
-         THREAD_ENTERPRISE_NUMBER, service_info[0], pref_id[0], pref_id[1], pref_id[2], pref_id[3],
-         IPv6_PREFIX_PARAM_SRP(prefix_buf));
-    int status = cti_add_service(route_state, partition_advertise_pref_id_done, NULL,
-                                 THREAD_ENTERPRISE_NUMBER, service_info, 1, pref_id, sizeof pref_id);
-    if (status != kCTIStatus_NoError) {
-        INFO("status %d", status);
-    }
-}
-
-static void
-partition_id_update(route_state_t *route_state)
-{
-    thread_prefix_t *advertised_prefix = get_advertised_thread_prefix(route_state);
-    if (advertised_prefix == NULL) {
-        INFO("no advertised prefix, not advertising pref:id.");
-    } else if (advertised_prefix == route_state->adopted_thread_prefix) {
-        INFO("not advertising pref:id for adopted prefix.");
-        partition_stop_advertising_pref_id(route_state);
-    } else {
-        partition_advertise_pref_id(route_state, ((uint8_t *)&advertised_prefix->prefix) + 1);
-        INFO("advertised pref:id for our prefix.");
-    }
-}
-
-static void
-partition_unpublish_prefix(route_state_t *route_state, thread_prefix_t *prefix)
-{
-    cti_status_t status = cti_remove_prefix(route_state, partition_prefix_remove_callback, NULL,
-                                            &prefix->prefix, 64);
-    if (status != kCTIStatus_NoError) {
-        ERROR("partition_unpublish_prefix: prefix remove failed: %d.", status);
-    }
-    partition_stop_advertising_pref_id(route_state);
-}
-
-static void
-partition_refresh_and_re_evaluate(route_state_t *route_state)
-{
-    refresh_interface_list(route_state);
-    routing_policy_evaluate_all_interfaces(route_state, true);
-}
-
-typedef struct unadvertised_prefix_remove_state  unadvertised_prefix_remove_state_t;
-struct unadvertised_prefix_remove_state {
-    int ref_count;
-    int num_unadvertised_prefixes;
-    int num_removals;
-    route_state_t *route_state;
-    void (*continuation)(route_state_t *route_state);
-};
-
-static void
-unadvertised_prefix_remove_state_finalize(unadvertised_prefix_remove_state_t *state)
-{
-    void (*continuation)(route_state_t *route_state) = state->continuation;
-    route_state_t *route_state = state->route_state;
-    free(state);
-    if (continuation != NULL) {
-        continuation(route_state);
-    } else {
-        INFO("no continuation.");
-    }
-}
-
-static void
-partition_remove_all_prefixes_done(void *context, cti_status_t status)
-{
-    unadvertised_prefix_remove_state_t *state = context;
-    state->num_removals++;
-    if (state->num_removals == state->num_unadvertised_prefixes) {
-        INFO("DONE: status = %d num_removals = %d num_unadvertised = %d",
-             status, state->num_removals, state->num_unadvertised_prefixes);
-    } else {
-        INFO("!DONE: status = %d num_removals = %d num_unadvertised = %d",
-             status, state->num_removals, state->num_unadvertised_prefixes);
-    }
-#ifndef __clang_analyzer__ // clang_analyzer is unable to follow the reference through the cti code.
-    RELEASE_HERE(state, unadvertised_prefix_remove_state_finalize);
-#endif
-}
-
-static void
-partition_remove_all_unwanted_prefixes_inner(unadvertised_prefix_remove_state_t *state,
-                                             thread_prefix_t *prefix, bool check)
-{
-    route_state_t *route_state = state->route_state;
-    // Retain a copy of state for the partition_remove_all_prefixes_done callback, which is either called
-    // when the remove finishes or directly if we decide not to remove this prefix.
-    RETAIN_HERE(state);
-
-    // Don't unpublish the adopted or published prefix.
-    if (!check ||
-        ((route_state->published_thread_prefix == NULL ||
-          memcmp(&route_state->published_thread_prefix->prefix, &prefix->prefix, 8)) &&
-         (route_state->adopted_thread_prefix == NULL ||
-          memcmp(&route_state->adopted_thread_prefix->prefix, &prefix->prefix, 8))))
-    {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-        INFO("removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-        cti_status_t status = cti_remove_prefix(state, partition_remove_all_prefixes_done,
-                                                NULL, &prefix->prefix, 64);
-        if (status != kCTIStatus_NoError) {
-            partition_remove_all_prefixes_done(state, status);
-        }
-    } else {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-        INFO("not removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " because it's the " PUB_S_SRP " prefix",
-             route_state->published_thread_prefix == NULL ? "adopted" : "published",
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-        // Do the accounting anyway.
-        partition_remove_all_prefixes_done(state, kCTIStatus_NotPermitted);
-    }
-}
-
-static void
-partition_remove_all_unwanted_prefixes(route_state_t *route_state, void (*continuation)(route_state_t *route_state),
-                                       thread_prefix_t *prefix_1, thread_prefix_t *prefix_2)
-{
-    unadvertised_prefix_remove_state_t *state = calloc(1, sizeof(*state));
-    if (state == NULL) {
-        INFO("no memory");
-        return;
-    }
-    // Retain our copy of state
-    RETAIN_HERE(state);
-    state->route_state = route_state;
-
-    // It's possible for us to get into a state where a prefix is published by this BR, but doesn't
-    // have a pref:id and isn't recognized as belonging to this BR.  This should never happen in practice,
-    // but if it does happen, the only thing that will eliminate it is a reboot.   In case this happens,
-    // we go through the list of prefixes that are marked ncp and unpublish them.
-    thread_prefix_t *prefix;
-
-    state->continuation = continuation;
-    for (prefix = route_state->thread_prefixes; prefix; prefix = prefix->next) {
-        if (!partition_pref_id_is_present(route_state, &prefix->prefix)) {
-            // It's possible for partition_remove_all_unwanted_prefixes to get called before we have a full list of
-            // recently-published prefixes. It is possible for either the published prefix or the adopted prefix to
-            // not be on the list of prefixes. The caller may however have wanted to change either of those pointers;
-            // in this case, it will pass in either or both of those pointers as prefix_1 and prefix_2; if we see those
-            // prefixes on the list, we don't need to unpublish them twice.
-            if (prefix_1 != NULL && !memcmp(&prefix->prefix, &prefix_1->prefix, 8)) {
-                prefix_1 = prefix;
-            } else if (prefix_2 != NULL && !memcmp(&prefix->prefix, &prefix_2->prefix, 8)) {
-                prefix_2 = prefix;
-            } else {
-                state->num_unadvertised_prefixes++;
-            }
-        }
-    }
-    if (prefix_1 != NULL) {
-        state->num_unadvertised_prefixes++;
-    }
-    if (prefix_2 != NULL) {
-        state->num_unadvertised_prefixes++;
-    }
-
-    // Now actually remove the prefixes.
-    for (prefix = route_state->thread_prefixes; prefix; prefix = prefix->next) {
-        if (prefix_1 != prefix && prefix_2 != prefix) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
-            if (!partition_pref_id_is_present(route_state, &prefix->prefix)) {
-                INFO("removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-                partition_remove_all_unwanted_prefixes_inner(state, prefix, true);
-            } else {
-                INFO("not removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " because pref id is present",
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
-            }
-        }
-    }
-    if (prefix_1 != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(prefix_1->prefix.s6_addr, prefix_buf);
-        INFO("removing prefix_1 " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix_1->prefix.s6_addr, prefix_buf));
-        partition_remove_all_unwanted_prefixes_inner(state, prefix_1, false);
-    }
-    if (prefix_2 != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(prefix_2->prefix.s6_addr, prefix_buf);
-        INFO("removing prefix_2 " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix_2->prefix.s6_addr, prefix_buf));
-        partition_remove_all_unwanted_prefixes_inner(state, prefix_2, false);
-    }
-
-    RELEASE_HERE(state, unadvertised_prefix_remove_state_finalize);
-}
-
-static void
-partition_unpublish_adopted_prefix(route_state_t *route_state, bool wait)
-{
-    // Unpublish the adopted prefix
-    if (route_state->adopted_thread_prefix != NULL) {
-        partition_unpublish_prefix(route_state, route_state->adopted_thread_prefix);
-        INFO("started to unadopt prefix.");
-        RELEASE_HERE(route_state->adopted_thread_prefix, thread_prefix_finalize);
-        route_state->adopted_thread_prefix = NULL;
-    }
-
-    // Something changed, so do a routing policy update unless wait==true
-    if (!wait) {
-        partition_refresh_and_re_evaluate(route_state);
-    }
-}
-
-static void
-partition_publish_prefix_finish(route_state_t *route_state)
-{
-    INFO("prefix unpublishing has completed, time to update the prefix.");
-
-    partition_id_update(route_state);
-    set_thread_prefix(route_state);
-
-    // Something changed, so do a routing policy update.
-    partition_refresh_and_re_evaluate(route_state);
-}
-
-void
-partition_publish_my_prefix(route_state_t *route_state)
-{
-    void (*continuation)(route_state_t *route_state) = NULL;
-    thread_prefix_t *prefix_1 = NULL;
-    thread_prefix_t *prefix_2 = NULL;
-
-    if (route_state->adopted_thread_prefix != NULL) {
-        prefix_1 = route_state->adopted_thread_prefix;
-        route_state->adopted_thread_prefix = NULL;
-    }
-
-    // If we already have a published thread prefix, it really should be my_thread_prefix.
-    if (route_state->published_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf);
-        // This should always be false.
-        if (memcmp(&route_state->published_thread_prefix->prefix, &route_state->my_thread_prefix, 8)) {
-            INFO("Published prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " is not my prefix",
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf));
-            prefix_2 = route_state->published_thread_prefix;
-            route_state->published_thread_prefix = NULL;
-            continuation = partition_publish_prefix_finish;
-        } else {
-            INFO("Published prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " is my prefix",
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf));
-        }
-    }
-    if (route_state->published_thread_prefix == NULL) {
-        // Publish the prefix
-        route_state->published_thread_prefix = thread_prefix_create(&route_state->my_thread_prefix, 64);
-        if (route_state->published_thread_prefix == NULL) {
-            ERROR("partition_publish_my_prefix: No memory for locally-advertised thread prefix");
-            goto out;
-        }
-        continuation = partition_publish_prefix_finish;
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->my_thread_prefix.s6_addr, prefix_buf);
-        INFO("Publishing my prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->my_thread_prefix.s6_addr, prefix_buf));
-    }
-    partition_remove_all_unwanted_prefixes(route_state, continuation, prefix_1, prefix_2);
-out:
-    if (prefix_1 != NULL) {
-        RELEASE_HERE(prefix_1, thread_prefix_finalize);
-    }
-    if (prefix_2 != NULL) {
-        RELEASE_HERE(prefix_2, thread_prefix_finalize);
-    }
-}
-
-static void
-partition_adopt_prefix(route_state_t *route_state, thread_prefix_t *prefix)
-{
-    void (*continuation)(route_state_t *route_state) = NULL;
-    thread_prefix_t *prefix_1 = NULL;
-    thread_prefix_t *prefix_2 = NULL;
-
-    if (route_state->published_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("Removing published prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf));
-        prefix_1 = route_state->published_thread_prefix;
-        route_state->published_thread_prefix = NULL;
-    }
-
-    // If we already have an advertised thread prefix, it might not have changed.
-    if (route_state->adopted_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf);
-        if (memcmp(&route_state->adopted_thread_prefix->prefix, &prefix->prefix, 8)) {
-            INFO("Removing previously adopted prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf));
-            prefix_2 = route_state->adopted_thread_prefix;
-            continuation = partition_publish_prefix_finish;
-        } else {
-            INFO("Keeping previously adopted prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf));
-        }
-    }
-    if (route_state->adopted_thread_prefix == NULL) {
-        // Adopt the prefix
-        route_state->adopted_thread_prefix = prefix;
-        RETAIN_HERE(route_state->adopted_thread_prefix);
-        continuation = partition_publish_prefix_finish;
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("Adopting prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf));
-    }
-    partition_remove_all_unwanted_prefixes(route_state, continuation, prefix_1, prefix_2);
-
-    if (prefix_1 != NULL) {
-        RELEASE_HERE(prefix_1, thread_prefix_finalize);
-    }
-    if (prefix_2 != NULL) {
-        RELEASE_HERE(prefix_2, thread_prefix_finalize);
-    }
-}
-
-// Check to see if a specific prefix is still present.
-static bool
-partition_prefix_is_present(route_state_t *route_state, struct in6_addr *address, int length)
-{
-    thread_prefix_t *prefix;
-    // For now we assume that the comparison is as a /64.
-    for (prefix = route_state->thread_prefixes; prefix; prefix = prefix->next) {
-        if (prefix->prefix_len == length && !memcmp((uint8_t *)&prefix->prefix, (uint8_t *)address, 8)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// Check to see if a valid pref:id for the specified prefix is present.
-static bool
-partition_pref_id_is_present(route_state_t *route_state, struct in6_addr *prefix_addr)
-{
-    thread_pref_id_t *pref_id;
-    uint8_t *prefix_bytes = (uint8_t *)prefix_addr;
-
-    INFO("published_thread_prefix = %p; prefix = %p", route_state->published_thread_prefix,
-         prefix_addr);
-
-    // The published prefix's pref:id is always considered present.
-    if (route_state->published_thread_prefix != NULL &&
-        !memcmp(prefix_addr, &route_state->published_thread_prefix->prefix, 8)) {
-        INFO("prefix is published prefix");
-        return true;
-    }
-
-    for (pref_id = route_state->thread_pref_ids; pref_id; pref_id = pref_id->next) {
-        // A pref:id is valid if the partition ID matches the current partition ID.
-        // A pref:id matches a prefix if the 40 variable bits in the ULA /48 are the same.
-        if (!memcmp(route_state->thread_partition_id, pref_id->partition_id, 4) &&
-            !memcmp(prefix_bytes + 1, pref_id->prefix, 5))
-        {
-            INFO("pref:id is present");
-            return true;
-        } else {
-            IPv6_PREFIX_GEN_SRP(pref_id->prefix, sizeof(pref_id->prefix), pref_id_prefix);
-            if (memcmp(route_state->thread_partition_id, pref_id->partition_id, 4)) {
-                INFO("pref:id for " PRI_IPv6_PREFIX_SRP
-                     ":%02x%02x%02x%02x does not match partition id %02x%02x%02x%02x",
-                     IPv6_PREFIX_PARAM_SRP(pref_id_prefix),
-                     pref_id->partition_id[0], pref_id->partition_id[1], pref_id->partition_id[2],
-                     pref_id->partition_id[3],
-                     route_state->thread_partition_id[0], route_state->thread_partition_id[1],
-                     route_state->thread_partition_id[2], route_state->thread_partition_id[3]);
-            } else {
-                INFO("pref:id for " PRI_IPv6_PREFIX_SRP ":%02x%02x%02x%02x does not match prefix %02x%02x%02x%02x%02x",
-                     IPv6_PREFIX_PARAM_SRP(pref_id_prefix),
-                     pref_id->partition_id[0], pref_id->partition_id[1], pref_id->partition_id[2],
-                     pref_id->partition_id[3],
-                     prefix_bytes[1], prefix_bytes[2], prefix_bytes[3], prefix_bytes[4], prefix_bytes[5]);
-            }
-        }
-    }
-    return false;
-}
-
-// Find the lowest valid prefix present.  The return value may be the published prefix.
-static thread_prefix_t *
-partition_find_lowest_valid_prefix(route_state_t *route_state)
-{
-    thread_prefix_t *prefix, *lowest = route_state->published_thread_prefix;
-
-    // Are there other prefixes published?
-    for (prefix = route_state->thread_prefixes; prefix != NULL; prefix = prefix->next) {
-        // The prefix we publish doesn't count.
-        if (route_state->published_thread_prefix != NULL && !memcmp(&prefix->prefix,
-                                                                    &route_state->published_thread_prefix->prefix, 8)) {
-            continue;
-        }
-        if (partition_pref_id_is_present(route_state, &prefix->prefix)) {
-            if (lowest == NULL || memcmp(&prefix->prefix, &lowest->prefix, 8) < 0) {
-                lowest = prefix;
-            }
-            break;
-        }
-    }
-    return lowest;
-}
-
-// Find the lowest valid pref:id.  The return value may be the pref:id for the published prefix.
-static thread_pref_id_t *
-partition_find_lowest_valid_pref_id(route_state_t *route_state)
-{
-    thread_pref_id_t *lowest = NULL;
-    thread_pref_id_t *pref_id;
-
-    for (pref_id = route_state->thread_pref_ids; pref_id != NULL; pref_id = pref_id->next) {
-        if (lowest == NULL || memcmp(pref_id->prefix, lowest->prefix, 5) < 0) {
-            lowest = pref_id;
-        }
-    }
-    return lowest;
-}
-
-// The prefix ID timeout has gone off.  At this time we evaluate the state of the network: the fact that we
-// got a wakeup means that there has been no partition event and nothing has changed about the set of
-// prefixes published on the thread mesh since the wakeup was scheduled.  We don't schedule this wakeup unless
-// there is more than one prefix on the thread mesh.   So that means that when the wakeup is called, there
-// is still more than one prefix+pref:id pair active on the link--an undesirable situation.   So we now
-// hold an election.  If we lose, we drop our prefix+pref:id pair in favor of the winner.  If we win,
-// we do nothing--we are expecting the BR(s) publishing the other prefix+pref:id pair(s) to drop them.
-static void
-partition_pref_id_timeout(void *context)
-{
-    route_state_t *route_state = context;
-    thread_prefix_t *prefix = partition_find_lowest_valid_prefix(route_state);
-
-    // This should never happen because we wouldn't have set the timeout.
-    if (prefix == NULL) {
-        INFO("no published prefix.");
-        return;
-    }
-
-    // If we won, do nothing.
-    if (route_state->published_thread_prefix != NULL &&
-        (prefix == route_state->published_thread_prefix ||
-         !memcmp(&prefix->prefix, &route_state->published_thread_prefix->prefix, 8)))
-    {
-        INFO("published prefix is the lowest; keeping it.");
-        return;
-    }
-
-    // published_thread_prefix should never be null here.
-    // If our published prefix is not the lowest prefix, then we should drop it and adopt the lowest prefix.
-    if (route_state->published_thread_prefix != NULL &&
-        memcmp(&prefix->prefix, &route_state->published_thread_prefix->prefix, 8))
-    {
-        INFO("published prefix is not lowest valid prefix.  Adopting lowest valid prefix.");
-        partition_adopt_prefix(route_state, prefix);
-        return;
-    }
-
-    // We should never get here.
-    if (route_state->adopted_thread_prefix != NULL) {
-        if (!memcmp(&route_state->adopted_thread_prefix->prefix, &prefix->prefix, 8)) {
-            ERROR("no published prefix.  Already adopted lowest.");
-            return;
-        }
-        // Unadopt this prefix since it's not lowest.
-        partition_unpublish_adopted_prefix(route_state, false);
-        // adopted_thread_prefix is now NULL
-    }
-
-    // And we should never get here.
-    ERROR("no published prefix.  Adopting lowest.");
-    partition_adopt_prefix(route_state, prefix);
-}
-
-// When we see a new partition, if there isn't a prefix to adopt and we aren't publishing one,
-// we wait n seconds to see if some other BR publishes a prefix, but also publish our own pref:id.
-// If no router on the partition is publishing a prefix, then after n seconds we hold an election,
-// choosing the pref:id with the lowest ULA.  If that's this router, then we will publish our prefix,
-// but if not, we want to check after a bit to make sure a prefix /does/ get published.   If after
-// another n seconds, we still don't see a valid prefix+pref:id pair, we publish our own; if this
-// later turns out to have been a mistake, we will hold the election again and remove the one we
-// published if we don't win.
-static void
-partition_post_election_wakeup(void *context)
-{
-    route_state_t *route_state = context;
-    thread_prefix_t *prefix = partition_find_lowest_valid_prefix(route_state);
-
-    // There is no valid prefix published.   Publish ours.
-    if (prefix == NULL) {
-        INFO("no valid thread prefix present, publishing mine.");
-        partition_publish_my_prefix(route_state);
-        return;
-    }
-
-    // It's perfectly valid to not have adopted the lowest prefix at this point.
-    // However, if we have adopted a prefix, we shouldn't be here because the timeout should have been
-    // canceled.
-    if (route_state->adopted_thread_prefix != NULL &&
-        memcmp(&route_state->adopted_thread_prefix->prefix, &prefix->prefix, 8))
-    {
-        ERROR("partition_post_election_wakeup: adopted prefix is not lowest.");
-    } else {
-        ERROR("partition_post_election_wakeup: adopted prefix is lowest.");
-    }
-}
-
-// This is the initial wakeup as described under partition_post_election_wakeup.   At this time
-// if there is a valid published pref:id pair, we adopt it; if not, then we hold an election based
-// on all of the on-partition pref:id pairs that we see.   If we win, we publish our prefix; otherwise
-// give the winner time to publish its prefix.
-static void
-partition_post_partition_timeout(void *context)
-{
-    route_state_t *route_state = context;
-    thread_prefix_t *prefix = partition_find_lowest_valid_prefix(route_state);
-    thread_pref_id_t *pref_id;
-
-    // Is there a prefix+pref:id published?
-    // Actually at this point we should already have adopted it and the wakeup should have been canceled.
-    if (prefix != NULL) {
-        ERROR("partition_post_partition_timeout: wakeup when there's a valid lowest prefix.");
-        return;
-    }
-
-    // Are there pref:id services published that list a lower ULA than ours?
-    pref_id = partition_find_lowest_valid_pref_id(route_state);
-
-    if (pref_id == NULL) {
-        INFO("There are no prefixes published, publishing my prefix.");
-        partition_publish_my_prefix(route_state);
-        return;
-    }
-
-    // If not, publish ours.
-    if (memcmp(((uint8_t *)&route_state->my_thread_prefix) + 1, pref_id->prefix, 5) < 0) {
-        INFO("my prefix id is lowest, publishing my prefix.");
-        partition_publish_my_prefix(route_state);
-        return;
-    }
-
-    // If so, wait another ten seconds to see if one of them publishes a prefix
-    // If we have adopted a prefix, set a timer after which we will drop it and start advertising if nothing has
-    // happened
-    if (route_state->partition_post_partition_wakeup != NULL) {  // shouldn't be!
-        ioloop_cancel_wake_event(route_state->partition_post_partition_wakeup);
-    } else {
-        route_state->partition_post_partition_wakeup = ioloop_wakeup_create();
-        if (route_state->partition_post_partition_wakeup == NULL) {
-            ERROR("partition_post_partition_timeout: can't allocate pref:id wait wakeup.");
-            return;
-        }
-    }
-    // Allow ten seconds for the services state to settle, after which time we should either have a pref:id backing
-    // up a prefix, or should advertise a prefix.
-    INFO("waiting for other BR to publish its prefixes.");
-    ioloop_add_wake_event(route_state->partition_post_partition_wakeup, NULL,
-                          partition_post_election_wakeup, NULL, 10 * 1000);
-}
-
-static void
-partition_proxy_listener_ready(void *context, uint16_t port)
-{
-    srp_server_t *server_state = context;
-    route_state_t *route_state = server_state->route_state;
-    INFO("listening on port %d", port);
-    route_state->srp_service_listen_port = port;
-    if (route_state->have_non_thread_interface) {
-        route_state->partition_can_advertise_service = true;
-        partition_maybe_advertise_service(route_state);
-    } else {
-        partition_discontinue_srp_service(route_state);
-    }
-}
-
-void
-partition_start_srp_listener(route_state_t *route_state)
-{
-#define max_avoid_ports 100
-    uint16_t avoid_ports[max_avoid_ports];
-    int num_avoid_ports = 0;
-    thread_service_t *service;
-
-    for (service = route_state->thread_services; service; service = service->next) {
-        // Track the port regardless.
-        if (num_avoid_ports < max_avoid_ports) {
-            avoid_ports[num_avoid_ports] = (service->port[0] << 8) | (service->port[1]);
-            num_avoid_ports++;
-        }
-    }
-
-    INFO("starting listener.");
-    route_state->srp_listener = srp_proxy_listen(avoid_ports, num_avoid_ports,
-                                                 partition_proxy_listener_ready, route_state->srp_server);
-    if (route_state->srp_listener == NULL) {
-        ERROR("partition_start_srp_listener: Unable to start SRP Proxy listener, so can't advertise it");
-        return;
-    }
-}
-
-void
-partition_discontinue_srp_service(route_state_t *route_state)
-{
-    if (route_state->srp_listener != NULL) {
-        INFO("discontinuing proxy service on port %d", route_state->srp_service_listen_port);
-        srp_proxy_listener_cancel(route_state->srp_listener);
-        route_state->srp_listener = NULL;
-    }
-
-    // Won't match
-    memset(&route_state->srp_listener_ip_address, 0, 16);
-    route_state->srp_service_listen_port = 0;
-    route_state->partition_can_advertise_service = false;
-
-    // Stop advertising the service, if we are doing so.
-    partition_stop_advertising_service(route_state);
-}
-
-// An address on utun0 has changed.  Evaluate what to do with our listener service.
-// This gets called from ifaddr_callback().   If we don't yet have a thread service configured,
-// it should be called for unchanged addresses as well as changed.
-static void
-partition_utun0_address_changed(route_state_t *route_state, const struct in6_addr *addr, enum interface_address_change change)
-{
-    thread_prefix_t *advertised_prefix = NULL;
-
-    // Figure out what our current prefix is.
-    if (route_state->published_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("partition_utun0_address_changed: advertised prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " is my prefix.",
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf));
-        advertised_prefix = route_state->published_thread_prefix;
-    } else if (route_state->adopted_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("partition_utun0_address_changed: advertised prefix " PRI_SEGMENTED_IPv6_ADDR_SRP
-             " is another router's prefix.",
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf));
-        advertised_prefix = route_state->adopted_thread_prefix;
-    }
-
-    SEGMENTED_IPv6_ADDR_GEN_SRP(addr, addr_buf);
-    // Is this the address we are currently using?
-    if (!memcmp(&route_state->srp_listener_ip_address, addr, 16)) {
-        // Did it go away?   If so, drop the listener.
-        if (change == interface_address_deleted) {
-            INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP ": listener address removed.",
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-            if (route_state->srp_listener != NULL) {
-                INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                     ": canceling listener on removed address.", SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-                partition_discontinue_srp_service(route_state);
-            }
-        } else {
-            // This should never happen.
-            if (change == interface_address_added) {
-                ERROR("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                      ": address we're listening on was added.", SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-            }
-
-            // Is it on the prefix we're currently publishing?
-            if (advertised_prefix != NULL && !memcmp(&advertised_prefix->prefix, addr, 8)) {
-                INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                     ": listener address is on the advertised prefix--no action needed.",
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-            } else {
-                // In this case hopefully we'll get a new IP address we _can_ listen on in a subsequent call.
-                INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                     ": listener address is not on the advertised prefix--no action taken.",
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-            }
-        }
-
-        // In no case can we do anything further.
-        return;
-    }
-
-    // If we have a prefix, see if we need to do anything.
-    if (advertised_prefix != NULL) {
-        // If this is not the address we are currently using, and it showed up, is it on the prefix we
-        // are advertising?
-        if (!memcmp(&advertised_prefix->prefix, addr, 8)) {
-            // If we are not listening on an address, or we are listening on an address that isn't on the
-            // prefix we are advertising, we need to stop, if needed, and start up a new listener.
-            if (route_state->srp_listener_ip_address.s6_addr[0] == 0 ||
-                memcmp(&advertised_prefix->prefix, &route_state->srp_listener_ip_address, 8))
-            {
-                // See if we already have a listener; if so, stop it.
-                if (route_state->srp_listener_ip_address.s6_addr[0] != 0) {
-                    INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP ": stopping old listener.",
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-                    srp_proxy_listener_cancel(route_state->srp_listener);
-                    route_state->srp_listener = NULL;
-                    memset(&route_state->srp_listener_ip_address, 0, sizeof(route_state->srp_listener_ip_address));
-                }
-                if (route_state->srp_listener == NULL) {
-                    if (!route_state->have_non_thread_interface) {
-                        INFO("partition_utun0_address_changed: not starting a listener because we have no infrastructure");
-                    } else {
-                        INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP ": starting a new listener.",
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-                        memcpy(&route_state->srp_listener_ip_address, addr, 16);
-                        route_state->srp_service_listen_port = 0;
-                        partition_start_srp_listener(route_state);
-                    }
-                }
-            }
-        } else {
-            INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-                 ": this address not on advertised prefix, so no action to take.",
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-        }
-    } else {
-        INFO("partition_utun0_address_changed: " PRI_SEGMENTED_IPv6_ADDR_SRP
-             ": no advertised prefix, so no action to take.", SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
-    }
-}
-
-// We call this function to see if we have a complete, recent set of information; if not, we wait a bit for the set
-// to become complete, but after 500ms we assume it won't be and proceed.
-static bool
-partition_wait_for_prefix_settling(route_state_t *route_state, wakeup_callback_t callback, uint64_t now)
-{
-    // Remember when we started waiting for the partition data to settle.
-    if (route_state->partition_settle_satisfied) {
-        route_state->partition_settle_start = now;
-        route_state->partition_settle_satisfied = false;
-    }
-
-    if (route_state->partition_settle_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_settle_wakeup);
-    }
-
-    // If we aren't able to offer service, just wait.
-    if (!route_state->partition_may_offer_service) {
-        INFO("not able to offer service--deferring.");
-        return true;
-    }
-
-    // If we've gotten updates on everything, we're good to go.   The reason for comparing against
-    // partition_settle_start is that if we've been seriously throttled for some reason, it might take
-    // more than 500ms to get a callback, even though all the events came in between when we asked
-    // for the initial callback and when we got it.   Tunnel ID shouldn't change after startup.
-    if (route_state->partition_last_prefix_set_change >= route_state->partition_settle_start &&
-        route_state->partition_last_pref_id_set_change >= route_state->partition_settle_start &&
-        route_state->partition_last_partition_id_change >= route_state->partition_settle_start &&
-        route_state->partition_last_role_change >= route_state->partition_settle_start &&
-        route_state->partition_last_state_change >= route_state->partition_settle_start &&
-        route_state->partition_tunnel_name_is_known)
-    {
-        route_state->partition_settle_satisfied = true;
-        INFO("satisfied after %" PRIu64 "ms.", now - route_state->partition_settle_start);
-        return false; // means don't wait
-    }
-
-    // If we've waited longer than 500ms and aren't satisfied, complain, but then proceed.
-    if (now - route_state->partition_settle_start >= 500) {
-        ERROR("unsatisfied after %" PRIu64 "ms",
-              now - route_state->partition_settle_start);
-        route_state->partition_settle_satisfied = true; // not really, but there's always next time.
-        return false; // proceed if possible.
-    }
-
-    // Otherwise, wake up 500ms after we started waiting for things to settle, and reconnoiter.
-    if (route_state->partition_settle_wakeup == NULL) {
-        route_state->partition_settle_wakeup = ioloop_wakeup_create();
-        if (route_state->partition_settle_wakeup == NULL) {
-            ERROR("Unable to postpone partition settlement wakeup: no memory.");
-            route_state->partition_settle_satisfied = true;
-            return false;
-        }
-    }
-    ioloop_add_wake_event(route_state->partition_settle_wakeup, route_state, callback, NULL,
-                          500 - (int)(now - route_state->partition_settle_start));
-    return true;
-}
-
-static void
-partition_got_tunnel_name(route_state_t *route_state)
-{
-    route_state->partition_tunnel_name_is_known = true;
-    for (interface_t *interface = route_state->interfaces; interface; interface = interface->next) {
-        if (!strcmp(interface->name, route_state->thread_interface_name)) {
-            interface->is_thread = true;
-            break;
-        }
-    }
-    refresh_interface_list(route_state);
-}
-
-// We have a recent prefix list and either have a recent pref:id list or one probably isn't coming.
-static void
-partition_prefix_list_or_pref_id_list_changed(void *context)
-{
-    route_state_t *route_state = context;
-
-    // If we haven't had a pref:id update recently, wait a bit to see if one came with the most recent network data.
-    if (partition_wait_for_prefix_settling(route_state, partition_prefix_list_or_pref_id_list_changed, ioloop_timenow())) {
-        ERROR("waiting for prefix info to settle.");
-        return;
-    }
-
-    // If we aren't ready to advertise service, do nothing.
-    if (!route_state->partition_may_offer_service) {
-        INFO("can't offer service yet.");
-        return;
-    }
-
-    // If there are no prefixes, then it doesn't matter what's on the prefix ID list: publish a prefix now.
-    if (route_state->thread_prefixes == NULL) {
-        INFO("have no prefixes, publishing my prefix");
-        partition_publish_my_prefix(route_state);
-        return;
-    }
-
-    // It is a failure of the thread network software for us to get to this point without knowing the thread
-    // partition ID.   We should have received it on startup.   So the case where this would happen would be if
-    // on startup we simply didn't get it, which should never happen.   What we'll do if this happens is make
-    // one up.
-    if (route_state->partition_id_is_known == false) {
-        ERROR("partition ID never showed up!");
-    }
-
-    // If we are already publishing a prefix and pref:id, we don't have to do anything to the prefix right now.
-    if (route_state->published_thread_prefix != NULL) {
-        // We do need to trigger an interface scan though.
-        refresh_interface_list(route_state);
-
-        // Also, if there's more than one prefix present, set a timer for an hour from now, at which point we will
-        // consider dropping our prefix.
-        if (route_state->thread_prefixes != NULL && route_state->thread_prefixes->next != NULL) {
-            INFO("published prefix is unchanged, setting up the pref:id timer");
-            if (route_state->partition_pref_id_wait_wakeup != NULL) {
-                ioloop_cancel_wake_event(route_state->partition_pref_id_wait_wakeup);
-            } else {
-                route_state->partition_pref_id_wait_wakeup = ioloop_wakeup_create();
-                if (route_state->partition_pref_id_wait_wakeup == NULL) {
-                    ERROR("Unable to set a timer to wake up after the an hour to check the partition id.");
-                    return;
-                }
-            }
-            // The thread network can be pretty chaotic right after the BR comes up, so if we see a partition during the
-            // first 60 seconds, don't treat it as a real partition event, and do the re-election in 60 seconds rather
-            // than an hour.
-            uint64_t time_since_zero = ioloop_timenow() - route_state->partition_last_state_change;
-            uint32_t pref_id_timeout_time = 3600 * 1000;
-            if (time_since_zero < 60 * 1000) {
-                pref_id_timeout_time = 60 * 1000;
-            }
-            ioloop_add_wake_event(route_state->partition_pref_id_wait_wakeup, route_state, partition_pref_id_timeout, NULL,
-                                  pref_id_timeout_time);
-            INFO("added partition pref id timeout");
-        } else {
-            INFO("published prefix is unchanged");
-        }
-        return;
-    }
-
-    // If we have adopted a prefix and the prefix and pref:id are still present, do nothing.
-    if (route_state->adopted_thread_prefix != NULL) {
-        if (partition_prefix_is_present(route_state, &route_state->adopted_thread_prefix->prefix,
-                                        route_state->adopted_thread_prefix->prefix_len) &&
-            partition_pref_id_is_present(route_state, &route_state->adopted_thread_prefix->prefix))
-        {
-            INFO("adopted prefix is unchanged");
-            return;
-        }
-        // If the adopted prefix is no longer present, stop using it.
-        partition_unpublish_adopted_prefix(route_state, false);
-        // adopted_thread_prefix is now NULL.
-    }
-
-    // If there is a prefix present for which there is already a matching pref:id, adopt that prefix and pref:id now.
-    // drop the thread_post_partition_timeout timer.
-    thread_prefix_t *prefix;
-    for (prefix = route_state->thread_prefixes; prefix; prefix = prefix->next) {
-        if (partition_pref_id_is_present(route_state, &prefix->prefix)) {
-            INFO("adopting new prefix");
-            partition_adopt_prefix(route_state, prefix);
-            // When we adopt a prefix, it was already on-link, and quite possibly we already have an address
-            // configured on that prefix on utun0.  Calling refresh_interface_list() will trigger the listener
-            // if in fact that's the case.   If the address hasn't come up on utun0 yet, then when it comes up
-            // that will trigger the listener.
-            refresh_interface_list(route_state);
-            return;
-        }
-        if (route_state->partition_post_partition_wakeup != NULL) {
-            ioloop_cancel_wake_event(route_state->partition_post_partition_wakeup);
-        }
-    }
-
-    // At this point there is a prefix, but no pref:id, and it's /not/ the prefix that we published.  This
-    // means that a partition has happened and the BR that published the prefix is on the other partition,
-    // or else that the BR that published the prefix has gone offline and has been offline for at least
-    // four minutes.
-    // It's possible that either condition will heal, but in the meantime publish a prefix.   The reason for
-    // the urgency is that if we have a partition, and both routers are still online, then routing will be
-    // screwed up until we publish a new prefix and migrate all the accessories on our partition to the
-    // new prefix.
-    INFO("there is a prefix, but no pref:id, so it's stale. Publishing my prefix.");
-    partition_publish_my_prefix(route_state);
-}
-
-// The list of published prefix has changed.  Evaluate what to do with our partition state.
-// Mostly what we do when the prefix list changes is the same as what we do if the pref:id list
-// changes, but if we get an empty prefix list, it doesn't matter what's on the pref:id list,
-// so we act immediately.
-static void
-partition_prefix_set_changed(route_state_t *route_state)
-{
-    // Time stamp most recent prefix set update.
-    route_state->partition_last_prefix_set_change = ioloop_timenow();
-
-    // Otherwise, we have a prefix list and a pref:id list, so we can make decisions.
-    partition_prefix_list_or_pref_id_list_changed(route_state);
-}
-
-// The set of published pref:id's changed.  Evaluate what to do with our pref:id
-static void
-partition_pref_id_set_changed(route_state_t *route_state)
-{
-    // Time stamp most recent prefix set update.
-    route_state->partition_last_prefix_set_change = ioloop_timenow();
-
-    // Otherwise, we have a prefix list and a pref:id list, so we can make decisions.
-    partition_prefix_list_or_pref_id_list_changed(route_state);
-}
-
-// The partition ID changed.
-static void
-partition_id_changed(route_state_t *route_state)
-{
-    route_state->partition_last_partition_id_change = ioloop_timenow();
-
-    // If we've never seen a partition ID before, this is not (necessarily) a partition.
-    if (!route_state->partition_id_is_known) {
-        INFO("first time through.");
-        route_state->partition_id_is_known = true;
-        return;
-    }
-
-    // If we get a partition ID when we aren't a router, we should (I think!) ignore it.
-    if (!route_state->partition_can_provide_routing) {
-        INFO("we aren't able to offer routing yet, so ignoring.");
-        return;
-    }
-
-    // If we are advertising a prefix, update our pref:id
-    if (route_state->published_thread_prefix != NULL) {
-        INFO("updating advertised prefix id");
-        partition_id_update(route_state);
-        // In principle we didn't change anything material to the routing subsystem, so no need to re-evaluate current
-        // policy.
-        return;
-    }
-
-    // Propose our prefix as a possible lowest prefix in case there's an election.
-    partition_stop_advertising_pref_id(route_state);
-    partition_advertise_pref_id(route_state, ((uint8_t *)(&route_state->my_thread_prefix)) + 1);
-
-    // If we have adopted a prefix, set a timer after which we will drop it and start advertising if nothing has
-    // happened
-    if (route_state->partition_post_partition_wakeup != NULL) {
-        ioloop_cancel_wake_event(route_state->partition_post_partition_wakeup);
-    } else {
-        route_state->partition_post_partition_wakeup = ioloop_wakeup_create();
-        if (route_state->partition_post_partition_wakeup == NULL) {
-            ERROR("partition_id_changed: can't allocate pref:id wait wakeup.");
-            return;
-        }
-    }
-    // Allow ten seconds for the services state to settle, after which time we should either have a pref:id backing
-    // up a prefix, or should advertise a prefix.
-    INFO("waiting for other BRs to propose their prefixes.");
-    ioloop_add_wake_event(route_state->partition_post_partition_wakeup, route_state,
-                          partition_post_partition_timeout, NULL, 10 * 1000);
-}
-
-static void
-partition_remove_service_done(void *context, cti_status_t status)
-{
-    route_state_t *route_state = context;
-    INFO("%d", status);
-
-    // Flush any advertisements we're currently doing, since the accessories that advertised them will
-    // notice the service is gone and start advertising with a different service.
-#if defined(SRP_FEATURE_REPLICATION)
-    if (!route_state->srp_server->srp_replication_enabled) {
-#endif
-        srp_mdns_flush(route_state->srp_server);
-#if defined(SRP_FEATURE_REPLICATION)
-    }
-#endif
-}
-
-static void
-partition_stop_advertising_service(route_state_t *route_state)
-{
-    // This should remove any copy of the service that this BR is advertising.
-    INFO("%" PRIu64 "/%x", THREAD_ENTERPRISE_NUMBER, THREAD_SRP_SERVER_OPTION);
-    uint8_t service_info[] = { 0, 0, 0, 1 };
-    int status;
-
-    service_info[0] = THREAD_SRP_SERVER_OPTION & 255;
-    status = cti_remove_service(route_state, partition_remove_service_done, NULL,
-                                THREAD_ENTERPRISE_NUMBER, service_info, 1);
-    if (status != kCTIStatus_NoError) {
-        INFO("status %d", status);
-    }
-}
-
-static void
-partition_add_service_callback(void *context, cti_status_t status)
-{
-    route_state_t *UNUSED route_state = context;
-    if (status != kCTIStatus_NoError) {
-        INFO("status = %d", status);
-    } else {
-        INFO("status = %d", status);
-    }
-}
-
-static void
-partition_start_advertising_service(route_state_t *route_state)
-{
-    uint8_t service_info[] = {0, 0, 0, 1};
-    uint8_t server_info[18];
-    int ret;
-
-    memcpy(&server_info, &route_state->srp_listener_ip_address, 16);
-    server_info[16] = (route_state->srp_service_listen_port >> 8) & 255;
-    server_info[17] = route_state->srp_service_listen_port & 255;
-
-    SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->srp_listener_ip_address.s6_addr, server_ip_buf);
-    service_info[0] = THREAD_SRP_SERVER_OPTION & 255;
-    INFO("%" PRIu64 "/%02x/" PRI_SEGMENTED_IPv6_ADDR_SRP ":%d" ,
-         THREAD_ENTERPRISE_NUMBER, service_info[0],
-         SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->srp_listener_ip_address.s6_addr, server_ip_buf),
-         route_state->srp_service_listen_port);
-
-    ret = cti_add_service(route_state, partition_add_service_callback, NULL,
-                          THREAD_ENTERPRISE_NUMBER, service_info, 1, server_info, sizeof server_info);
-    if (ret != kCTIStatus_NoError) {
-        INFO("status %d", ret);
-    }
-
-    // Wait a while for the service add to be reflected in an event.
-    partition_schedule_service_add_wakeup(route_state);
-}
-
-static void
-partition_service_add_wakeup(void *context)
-{
-    route_state_t *route_state = context;
-    route_state->partition_service_last_add_time = 0;
-    partition_maybe_advertise_service(route_state);
-}
-
-static void
-partition_schedule_service_add_wakeup(route_state_t *route_state)
-{
-    if (route_state->partition_service_add_pending_wakeup == NULL) {
-        route_state->partition_service_add_pending_wakeup = ioloop_wakeup_create();
-        if (route_state->partition_service_add_pending_wakeup == NULL) {
-            ERROR("Can't schedule service add pending wakeup: no memory!");
-            return;
-        }
-    } else {
-        ioloop_cancel_wake_event(route_state->partition_service_add_pending_wakeup);
-    }
-    // Wait ten seconds.
-    ioloop_add_wake_event(route_state->partition_service_add_pending_wakeup, route_state,
-                          partition_service_add_wakeup, NULL, 10 * 1000);
-}
-
-static void
-partition_maybe_advertise_service(route_state_t *route_state)
-{
-    thread_service_t *service, *lowest[2];
-    int num_services = 0;
-    int i;
-    bool should_remove_service = false;
-    bool should_advertise_service = false;
-    int64_t last_add_time;
-
-    // If we aren't ready to advertise a service, there's nothing to do.
-    if (!route_state->partition_can_advertise_service) {
-        INFO("no service to advertise yet.");
-        return;
-    }
-
-    if (route_state->partition_service_blocked) {
-        INFO("service advertising is disabled.");
-        return;
-    }
-
-    for (i = 0; i < 16; i++) {
-        if (route_state->srp_listener_ip_address.s6_addr[i] != 0) {
-            break;
-        }
-    }
-    if (i == 16) {
-        INFO("no listener.");
-        return;
-    }
-
-    // The add service function requires a remove prior to the add, so if we are doing an add, we need to wait
-    // for things to stabilize before allowing the removal of a service to trigger a re-evaluation.
-    // Therefore, if we've done an add in the past ten seconds, wait ten seconds before trying another add.
-    last_add_time = ioloop_timenow() - route_state->partition_service_last_add_time;
-    INFO("last_add_time = %" PRId64, last_add_time);
-    if (last_add_time < 10 * 1000) {
-        partition_schedule_service_add_wakeup(route_state);
-        return;
-    }
-    lowest[0] = NULL;
-    lowest[1] = NULL;
-
-    for (service = route_state->thread_services; service; service = service->next) {
-        int port = (service->port[0] << 8) | service->port[1];
-        SEGMENTED_IPv6_ADDR_GEN_SRP(service->address, srv_addr_buf);
-
-        // A service only counts if its prefix is present and its prefix id is present and matches the
-        // current partition id.
-        if (partition_prefix_is_present(route_state, (struct in6_addr *)service->address, 64)) {
-            if (partition_pref_id_is_present(route_state, (struct in6_addr *)service->address)) {
-                num_services++;
-                for (i = 0; i < 2; i++) {
-                    if (lowest[i] == NULL) {
-                        lowest[i] = service;
-                        INFO("service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d goes in open slot %d.",
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(service->address, srv_addr_buf), port, i);
-                        break;
-                    } else if (memcmp(service->address, lowest[i]->address, 16) < 0) {
-                        int lowport;
-
-                        if (lowest[1] != NULL) {
-                            lowport = (lowest[1]->port[0] << 8) | lowest[1]->port[1];
-                            SEGMENTED_IPv6_ADDR_GEN_SRP(lowest[1]->address, lowest_1_buf);
-                            INFO("Superseding " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d in slot 1",
-                                 SEGMENTED_IPv6_ADDR_PARAM_SRP(lowest[1]->address, lowest_1_buf), lowport);
-                        }
-                        if (i == 0) {
-                            lowport = (lowest[0]->port[0] << 8)| lowest[0]->port[1];
-                            SEGMENTED_IPv6_ADDR_GEN_SRP(lowest[0]->address, lowest_0_buf);
-                            INFO("Moving " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d from slot 0 to slot 1",
-                                 SEGMENTED_IPv6_ADDR_PARAM_SRP(lowest[0]->address, lowest_0_buf), lowport);
-                            lowest[1] = lowest[0];
-                        }
-                        INFO("service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d goes in slot %d.",
-                             SEGMENTED_IPv6_ADDR_PARAM_SRP(service->address, srv_addr_buf), port, i);
-                        lowest[i] = service;
-                        break;
-                    }
-                }
-            } else {
-                INFO("service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d doesn't count because the pref:id is not present.",
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(service->address, srv_addr_buf), port);
-            }
-        } else {
-                INFO("service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d doesn't count because the prefix is not present.",
-                     SEGMENTED_IPv6_ADDR_PARAM_SRP(service->address, srv_addr_buf), port);
-        }
-    }
-
-    should_remove_service = true;
-    for (i = 0; i < 2; i++) {
-        if (lowest[i] == NULL) {
-            INFO("adding service because there's an open slot.");
-            should_remove_service = false;
-            should_advertise_service = true;
-            break;
-        } else {
-            int sign = memcmp(((uint8_t *)(&route_state->srp_listener_ip_address)), lowest[i]->address, 16);
-            if (sign == 0) {
-                // We're already advertising the service and we win the election.
-                // If the port hasn't changed, don't update the service
-                uint16_t port = (lowest[i]->port[0] << 8) | lowest[i]->port[1];
-                if (port != route_state->srp_service_listen_port) {
-                    INFO("old service was present and prefix would win election.");
-                    should_remove_service = false;
-                    should_advertise_service = true;
-                } else {
-                    INFO("service already present and would win election.");
-                    should_remove_service = false;
-                    should_advertise_service = false;
-                }
-                break;
-            } else if (sign < 0) {
-                INFO("service not present but wins election.");
-                should_remove_service = false;
-                should_advertise_service = true;
-                break;
-            } else {
-                INFO("Service would not win election with lowest[%d]", i);
-            }
-        }
-    }
-
-    // Always remove service before adding it, but also remove it if it lost the election.
-    if (should_remove_service) {
-        partition_stop_advertising_service(route_state);
-        route_state->partition_service_last_add_time = ioloop_timenow();
-    }
-    if (should_advertise_service) {
-        partition_start_advertising_service(route_state);
-        route_state->partition_service_last_add_time = ioloop_timenow();
-    }
-}
-
-static void
-partition_service_set_changed(route_state_t *route_state)
-{
-    partition_pref_id_set_changed(route_state);
-    partition_maybe_advertise_service(route_state);
-}
-
-static void partition_maybe_enable_services(route_state_t *route_state)
-{
-    bool am_associated = route_state->current_thread_state == kCTI_NCPState_Associated;
-    if (am_associated) {
-        INFO("Enabling service, which was disabled because of the thread role or state.");
-        route_state->partition_may_offer_service = true;
-        route_state->partition_can_provide_routing = true;
-        refresh_interface_list(route_state);
-        partition_prefix_list_or_pref_id_list_changed(route_state);
-        routing_policy_evaluate_all_interfaces(route_state, true);
-    } else {
-        INFO("Not enabling service: " PUB_S_SRP,
-             am_associated ? "associated" : "!associated");
-    }
-}
-
-static void partition_disable_service(route_state_t *route_state)
-{
-    bool done_something = false;
-
-    // When our node type or state is such that we should no longer be publishing a prefix, the NCP will
-    // automatically remove the published prefix.  In case this happens, we do not want to remember the
-    // prefix as already having been published.  So drop our recollection of the adopted and published
-    // prefixes; this will get cleaned up when the network comes back if there's an inconsistency.
-    if (route_state->adopted_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("unadopting prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->adopted_thread_prefix->prefix.s6_addr, prefix_buf));
-        RELEASE_HERE(route_state->adopted_thread_prefix, thread_prefix_finalize);
-        route_state->adopted_thread_prefix = NULL;
-        done_something = true;
-    }
-    if (route_state->published_thread_prefix != NULL) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf);
-        INFO("un-publishing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
-             SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->published_thread_prefix->prefix.s6_addr, prefix_buf));
-        RELEASE_HERE(route_state->published_thread_prefix, thread_prefix_finalize);
-        route_state->published_thread_prefix = NULL;
-        done_something = true;
-    }
-
-    // We want to always say something when we pass through this state.
-    if (!done_something) {
-	    INFO("nothing to do.");
-    }
-
-    route_state->partition_may_offer_service = false;
-    route_state->partition_can_provide_routing = false;
-}
-#endif // RA_TESTER
-#endif // STUB_ROUTER
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/route.h b/ServiceRegistration/route.h
deleted file mode 100644
index 4634e68..0000000
--- a/ServiceRegistration/route.h
+++ /dev/null
@@ -1,406 +0,0 @@
-/* route.h
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This code adds border router support to 3rd party HomeKit Routers as part of Apple’s commitment to the CHIP project.
- *
- * Definitions for route.c
- */
-
-#ifndef __SERVICE_REGISTRATION_ROUTE_H
-#define __SERVICE_REGISTRATION_ROUTE_H
-#if defined(USE_IPCONFIGURATION_SERVICE)
-#include <SystemConfiguration/SystemConfiguration.h>
-#include "IPConfigurationService.h"
-#endif
-
-// RFC 4861 specifies a minimum of 4 seconds between RAs. We add a bit of fuzz.
-#define MIN_DELAY_BETWEEN_RAS 4000
-#define RA_FUZZ_TIME          1000
-
-// RFC 4861 specifies a maximum of three transmissions when sending an RA.
-#define MAX_RA_RETRANSMISSION 3
-
-// There's no limit for unicast neighbor solicits, but we limit it to three.
-#define MAX_NS_RETRANSMISSIONS 3
-
-// 60 seconds between router probes, three retries, four seconds per retry. We should have an answer from the router at
-// most 76 seconds after the previous answer, assuming that it takes four seconds for the response to arrive, which is
-// of course ridiculously long.
-#define MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_UNREACHABLE 76 * MSEC_PER_SEC
-
-// The end of the valid lifetime of the prefix is the time we received it plus the valid lifetime that was expressed in
-// the PIO option of the RA that advertised the prefix. If we have a prefix that is within ten minutes of expiring, we
-// consider it stale and start advertising a prefix. This should never happen in a network where a router is advertising
-// a prefix--if it does, either we're having trouble receiving multicast RAs (meaning that we don't get every beacon) or
-// the router has gone away.
-#define MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE      600 * MSEC_PER_SEC
-
-// The Thread BR prefix needs to stick around long enough that it's not likely to accidentally disappear because of
-// dropped multicasts, but short enough that it goes away quickly when a router that's advertising IPv6 connectivity
-// comes online.
-#define BR_PREFIX_LIFETIME 30 * 60
-
-#define BR_PREFIX_SLASH_64_BYTES 8
-
-
-#ifndef RTR_SOLICITATION_INTERVAL
-#define RTR_SOLICITATION_INTERVAL       4       /* 4sec */
-#endif
-
-#ifndef ND6_INFINITE_LIFETIME
-#define ND6_INFINITE_LIFETIME           0xffffffff
-#endif
-
-
-
-typedef struct interface interface_t;
-typedef struct icmp_message icmp_message_t;
-struct interface {
-    int ref_count;
-
-    interface_t *NULLABLE next;
-    char *NONNULL name;
-
-    // Wakeup event for next beacon.
-    wakeup_t *NULLABLE beacon_wakeup;
-
-    // Wakeup event called after we're done sending solicits.  At this point we delete all routes more than 10 minutes
-    // old; if none are left, then we assume there's no IPv6 service on the interface.
-    wakeup_t *NULLABLE post_solicit_wakeup;
-
-    // Wakeup event to trigger the next router solicit or neighbor solicit to be sent.
-    wakeup_t *NULLABLE router_solicit_wakeup;
-
-    // Wakeup event to trigger the next router solicit to be sent.
-    wakeup_t *NULLABLE neighbor_solicit_wakeup;
-
-    // Wakeup event to deconfigure the on-link prefix after it is no longer valid.
-    wakeup_t *NULLABLE deconfigure_wakeup;
-
-#if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-    // Wakeup event to detect that vicarious router discovery is complete
-    wakeup_t *NULLABLE vicarious_discovery_complete;
-#endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
-
-    // Wakeup event to periodically notice whether routers we have heard previously on this interface have gone stale.
-    wakeup_t *NULLABLE stale_evaluation_wakeup;
-
-    // Wakeup event to periodically probe routers for reachability
-    wakeup_t *NULLABLE router_probe_wakeup;
-
-    // The route state object to which this interface belongs.
-    route_state_t *NULLABLE route_state;
-
-    // List of Router Advertisement messages from different routers.
-    icmp_message_t *NULLABLE routers;
-
-    // List of Router Solicit messages from different hosts for which we are still transmitting unicast
-    // RAs (we sent three unicast RAs per solicit to ensure delivery).
-    icmp_message_t *NULLABLE solicits;
-
-    int prefix_number;
-
-#if defined(USE_IPCONFIGURATION_SERVICE)
-    // The service used to configure this interface with an address in the on-link prefix
-    IPConfigurationServiceRef NULLABLE ip_configuration_service;
-
-    // SCDynamicStoreRef
-    SCDynamicStoreRef NULLABLE ip_configuration_store;
-#else
-    subproc_t *NULLABLE link_route_adder_process;
-#endif
-
-    struct in6_addr link_local;  // Link-local address
-    struct in6_addr ipv6_prefix; // This is the prefix we advertise, if advertise_ipv6_prefix is true.
-
-    // Absolute time of last beacon, and of next beacon.
-    uint64_t last_beacon, next_beacon;
-
-    // Absolute deadline for deprecating the on-link prefix we've been announcing
-    uint64_t deprecate_deadline;
-
-    // Last time we did a router probe
-    uint64_t last_router_probe;
-
-    // Preferred lifetime for the on-link prefix
-    uint32_t preferred_lifetime;
-
-    // Valid lifetime for the on-link prefix
-    uint32_t valid_lifetime;
-
-    // When the interface becomes active, we send up to three solicits.
-    // Later on, we send three neighbor solicit probes every sixty seconds to verify router reachability
-    int num_solicits_sent;
-
-    // The interface index according to the operating systme.
-    int index;
-
-    // Number of IPv4 addresses configured on link.
-    int num_ipv4_addresses;
-
-    // Number of beacons sent. After the first three, the inter-beacon interval goes up.
-    int num_beacons_sent;
-
-    // The interface link layer address, if known.
-    uint8_t link_layer[6];
-
-    // True if the interface is not usable.
-    bool inactive;
-
-    // True if this interface can never be used for routing to the thread network (e.g., loopback, tunnels, etc.)
-    bool ineligible;
-
-    // True if we've determined that it's the thread interface.
-    bool is_thread;
-
-    // True if we have (or intended to) advertised our own prefix on this link. It should be true until the prefix
-    // we advertised should have expired on all hosts that might have received it. This will be set before we actually
-    // advertise a prefix, so before the first time we advertise a prefix it may be set even though the prefix can't
-    // appear in any host's routing table yet.
-    bool our_prefix_advertised;
-
-    // True if we should suppress on-link prefix. This would be the case when deprecating if we aren't sending
-    // periodic updates of the deprecated prefix.
-    bool suppress_ipv6_prefix;
-
-    // True if we've gotten a link-layer address.
-    bool have_link_layer_address;
-
-    // True if the on-link prefix is configured on the interface.
-    bool on_link_prefix_configured;
-
-    // True if we've sent our first beacon since the interface came up.
-    bool sent_first_beacon;
-
-    // Indicates whether or not router discovery was ever started for this interface.
-    bool router_discovery_started;
-
-    // Indicates whether or not router discovery has completed for this interface.
-    bool router_discovery_complete;
-
-    // Indicates whether we're currently doing router discovery, so that we don't
-    // restart it when we're already doing it.
-    bool router_discovery_in_progress;
-
-    // Indicates that we've received a router discovery message from some other host,
-    // and are waiting 20 seconds to snoop for replies to that RD message that are
-    // multicast.   If we hear no replies during that time, we trigger router discovery.
-    bool vicarious_router_discovery_in_progress;
-
-    // True if we are probing usable routers with neighbor solicits to see if they are still alive.
-    bool probing;
-
-    // Indicates that we have received an interface removal event, it is useful when srp-mdns-proxy is changed to a new
-    // network where the network signature are the same and they both have no IPv6 service (so no IPv6 prefix will be
-    // removed), in such case there will be no change from srp-mdns-proxy's point of view. However, configd may still
-    // flush the IPv6 routing since changing network would cause interface up/down. When the flushing happens,
-    // srp-mdns-proxy should be able to reconfigure the IPv6 routing by reconfiguring IPv6 prefix. By setting
-    // need_reconfigure_prefix only when interface address removal happens and check it during the routing evaluation
-    // srp-mdns-proxy can reconfigure it after the routing evaluation finishes, like router discovery.
-    bool need_reconfigure_prefix;
-};
-
-typedef enum icmp_option_type {
-    icmp_option_source_link_layer_address =  1,
-    icmp_option_target_link_layer_address =  2,
-    icmp_option_prefix_information        =  3,
-    icmp_option_redirected_header         =  4,
-    icmp_option_mtu                       =  5,
-    icmp_option_route_information         = 24,
-} icmp_option_type_t;
-
-typedef enum icmp_type {
-    icmp_type_echo_request           = 128,
-    icmp_type_echo_reply             = 129,
-    icmp_type_router_solicitation    = 133,
-    icmp_type_router_advertisement   = 134,
-    icmp_type_neighbor_solicitation  = 135,
-    icmp_type_neighbor_advertisement = 136,
-    icmp_type_redirect               = 137,
-} icmp_type_t;
-
-typedef struct link_layer_address {
-    uint16_t length;
-    uint8_t address[32];
-} link_layer_address_t;
-
-typedef struct prefix_information {
-    struct in6_addr prefix;
-    uint8_t length;
-    uint8_t flags;
-    uint32_t valid_lifetime;
-    uint32_t preferred_lifetime;
-    bool found; // For comparing RAs
-} prefix_information_t;
-
-typedef struct route_information {
-    struct in6_addr prefix;
-    uint8_t length;
-    uint8_t flags;
-    uint32_t route_lifetime;
-} route_information_t;
-
-typedef struct icmp_option {
-    icmp_option_type_t type;
-    union {
-        link_layer_address_t link_layer_address;
-        prefix_information_t prefix_information;
-        route_information_t route_information;
-    } option;
-} icmp_option_t;
-
-struct icmp_message {
-    icmp_message_t *NULLABLE next;
-    interface_t *NULLABLE interface;
-    icmp_option_t *NULLABLE options;
-    wakeup_t *NULLABLE wakeup;
-    route_state_t *NULLABLE route_state;
-
-    bool usable;                         // True if this router was usable at the last policy evaluation
-    bool reachable;                      // True if this router was reachable when last probed
-    bool reached;                        // Set to true when we get a neighbor advertise from the router
-    bool new_router;                     // If this router information is a newly received one.
-    bool received_time_already_adjusted; // if the received time of the message is already adjusted by vicarious mode
-    int retransmissions_received;        // # times we've received a solicit from this host during retransmit window
-    int messages_sent;                   // # of unicast RAs we've sent in response to a solicit, or # of unicast NSs
-                                         // we've sent to confirm router aliveness
-
-    struct in6_addr source;
-    struct in6_addr destination;
-
-    uint64_t received_time;
-    uint64_t latest_na;                 // Most recent time at which we successfully got a neighbor advertise
-
-    uint32_t reachable_time;
-    uint32_t retransmission_timer;
-    uint8_t cur_hop_limit;          // Current hop limit for Router Advertisement messages.
-    uint8_t flags;
-    uint8_t type;
-    uint8_t code;
-    uint16_t checksum;              // We hope the kernel figures this out for us.
-    uint16_t router_lifetime;
-
-    int num_options;
-    int hop_limit;                  // Hop limit provided by the kernel, must be 255.
-};
-
-typedef struct icmp_listener icmp_listener_t;
-typedef struct thread_prefix thread_prefix_t;
-typedef struct thread_pref_id thread_pref_id_t;
-typedef struct thread_service thread_service_t;
-typedef struct route_state route_state_t;
-typedef struct srp_server_state srp_server_t;
-
-struct route_state {
-    route_state_t *NULLABLE next;
-    const char *NULLABLE name;
-    srp_server_t *NULLABLE srp_server;
-    interface_address_state_t *NULLABLE interface_addresses;
-    struct thread_prefix *NULLABLE thread_prefixes, *NULLABLE published_thread_prefix, *NULLABLE adopted_thread_prefix;
-    struct thread_pref_id *NULLABLE thread_pref_ids;
-    struct thread_service *NULLABLE thread_services;
-
-    // If true, a prefix with L=1, A=0 in an RA with M=1 is treated as usable. The reason it's not treated as
-    // usable by default is that this will break Thread for Android phones on networks where IPv6 is present
-    // but only DHCPv6 is supported.
-    bool config_enable_dhcpv6_prefixes;
-
-    interface_t *NULLABLE interfaces;
-    bool have_thread_prefix;
-    struct in6_addr my_thread_prefix;
-    struct in6_addr srp_listener_ip_address;
-    uint16_t srp_service_listen_port;
-    uint8_t thread_partition_id[4];
-    srp_proxy_listener_state_t *NULLABLE srp_listener;
-    struct in6_addr xpanid_prefix;
-    bool have_xpanid_prefix;
-    int num_thread_interfaces; // Should be zero or one.
-    int ula_serial;
-    subproc_t *NULLABLE thread_interface_enumerator_process;
-    subproc_t *NULLABLE thread_prefix_adder_process;
-    subproc_t *NULLABLE thread_rti_setter_process;
-    subproc_t *NULLABLE thread_forwarding_setter_process;
-    subproc_t *NULLABLE tcpdump_logger_process;
-    char *NULLABLE thread_interface_name;
-    char *NULLABLE home_interface_name;
-    bool have_non_thread_interface;
-    uint64_t xpanid;
-
-#ifndef RA_TESTER
-    cti_network_state_t current_thread_state;
-    cti_connection_t NULLABLE thread_role_context;
-    cti_connection_t NULLABLE thread_state_context;
-    cti_connection_t NULLABLE thread_service_context;
-    cti_connection_t NULLABLE thread_prefix_context;
-    cti_connection_t NULLABLE thread_partition_id_context;
-    cti_connection_t NULLABLE thread_xpanid_context;
-    bool thread_network_running;
-#endif
-
-#if !defined(RA_TESTER)
-    wakeup_t *NULLABLE wpan_reconnect_wakeup;
-#endif !defined(RA_TESTER)
-#if !defined(RA_TESTER)
-    uint64_t partition_last_prefix_set_change;
-    uint64_t partition_last_pref_id_set_change;
-    uint64_t partition_last_partition_id_change;
-    uint64_t partition_last_role_change;
-    uint64_t partition_last_state_change;
-    uint64_t partition_settle_start;
-    uint64_t partition_service_last_add_time;
-    bool partition_id_is_known;
-    bool partition_have_prefix_list;
-    bool partition_have_pref_id_list;
-    bool partition_tunnel_name_is_known;
-    bool partition_can_advertise_service;
-    bool partition_service_blocked;
-    bool partition_can_provide_routing;
-    bool partition_has_xpanid;
-    bool partition_may_offer_service;
-    bool partition_settle_satisfied;
-    wakeup_t *NULLABLE partition_settle_wakeup;
-    wakeup_t *NULLABLE partition_post_partition_wakeup;
-    wakeup_t *NULLABLE partition_pref_id_wait_wakeup;
-    wakeup_t *NULLABLE partition_service_add_pending_wakeup;
-#endif // RA_TESTER
-};
-
-extern srp_server_t *NONNULL srp_server; // temporary static srp server pointer
-
-route_state_t *NULLABLE route_state_create(srp_server_t *NONNULL server_state, const char *NONNULL name);
-void route_ula_setup(route_state_t *NULLABLE route_state);
-void route_ula_generate(route_state_t *NULLABLE route_state);
-bool start_route_listener(route_state_t *NULLABLE route_state);
-bool start_icmp_listener(void);
-void icmp_leave_join(int sock, int ifindex, bool join);
-void infrastructure_network_startup(route_state_t *NULLABLE route_state);
-void infrastructure_network_shutdown(route_state_t *NULLABLE route_state);
-void partition_stop_advertising_pref_id(route_state_t *NULLABLE route_state);
-void partition_start_srp_listener(route_state_t *NULLABLE route_state);
-void partition_publish_my_prefix(route_state_t *NULLABLE route_state);
-void partition_discontinue_srp_service(route_state_t *NULLABLE route_state);
-void adv_ctl_add_prefix(route_state_t *NONNULL route_state, const uint8_t *NONNULL data);
-void adv_ctl_remove_prefix(route_state_t *NONNULL route_state, const uint8_t *NONNULL data);
-#endif // __SERVICE_REGISTRATION_ROUTE_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/sign-macos.c b/ServiceRegistration/sign-macos.c
deleted file mode 100644
index b4b0396..0000000
--- a/ServiceRegistration/sign-macos.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* sign-macos.c
- *
- * Copyright (c) 2018-2021 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
- *
- *     https://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.
- *
- * DNS SIG(0) signature generation for DNSSD SRP using mbedtls.
- *
- * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
- * into KEY RR data, and computing signatures.
- *
- * This is the implementation for Mac OS X.
- */
-
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <sys/random.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <dns_sd.h>
-
-#include "srp.h"
-#include "srp-api.h"
-#include "dns-msg.h"
-#define SRP_CRYPTO_MACOS_INTERNAL
-#include "srp-crypto.h"
-
-// Key is stored in an opaque data structure, for mbedtls this is an mbedtls_pk_context.
-// Function to read a public key from a KEY record
-// Function to validate a signature given some data and a public key (not required on client)
-
-// Function to free a key
-void
-srp_keypair_free(srp_key_t *key)
-{
-    free(key);
-}
-
-uint16_t
-srp_random16()
-{
-    return (uint16_t)(arc4random_uniform(65536));
-}
-
-uint32_t
-srp_random32()
-{
-    return arc4random();
-}
-
-uint64_t
-srp_random64()
-{
-    uint64_t ret;
-    arc4random_buf(&ret, sizeof(ret));
-    return ret;
-}
-
-bool
-srp_randombytes(uint8_t *dest, size_t num)
-{
-    arc4random_buf(dest, num);
-    return true;
-}
-
-static void
-srp_sec_error_print(const char *reason, OSStatus status)
-{
-    const char *utf8 = NULL;
-    CFStringRef err = SecCopyErrorMessageString(status, NULL);
-    if (err != NULL) {
-        utf8 = CFStringGetCStringPtr(err, kCFStringEncodingUTF8);
-    }
-    if (utf8 != NULL) {
-        ERROR(PUB_S_SRP ": " PUB_S_SRP, reason, utf8);
-    } else {
-        ERROR(PUB_S_SRP ": %d", reason, (int)status);
-    }
-    if (err != NULL) {
-        CFRelease(err);
-    }
-}
-
-// Function to generate a key
-static srp_key_t *
-srp_get_key_internal(const char *key_name, bool delete)
-{
-    long two56 = 256;
-    srp_key_t *key = NULL;
-    OSStatus status;
-
-    CFMutableDictionaryRef key_parameters = CFDictionaryCreateMutable(NULL, 8,
-                                                                      &kCFTypeDictionaryKeyCallBacks,
-                                                                      &kCFTypeDictionaryValueCallBacks);
-    CFMutableDictionaryRef pubkey_parameters;
-
-    if (key_parameters != NULL) {
-        CFDictionaryAddValue(key_parameters, kSecAttrIsPermanent, kCFBooleanTrue);
-        CFDictionaryAddValue(key_parameters, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
-        CFNumberRef num = CFNumberCreate(NULL, kCFNumberLongType, &two56);
-        CFDictionaryAddValue(key_parameters, kSecAttrKeySizeInBits, num);
-        CFRelease(num);
-        CFStringRef str = CFStringCreateWithCString(NULL, key_name, kCFStringEncodingUTF8);
-        CFDictionaryAddValue(key_parameters, kSecAttrLabel, str);
-        CFRelease(str);
-        CFDictionaryAddValue(key_parameters, kSecReturnRef, kCFBooleanTrue);
-        CFDictionaryAddValue(key_parameters, kSecMatchLimit, kSecMatchLimitOne);
-        CFDictionaryAddValue(key_parameters, kSecClass, kSecClassKey);
-        pubkey_parameters = CFDictionaryCreateMutableCopy(NULL, 8, key_parameters);
-        if (pubkey_parameters != NULL) {
-            CFDictionaryAddValue(key_parameters, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
-            CFDictionaryAddValue(pubkey_parameters, kSecAttrKeyClass, kSecAttrKeyClassPublic);
-            CFDictionaryAddValue(pubkey_parameters, kSecAttrIsExtractable, kCFBooleanTrue);
-            CFDictionaryAddValue(key_parameters, kSecAttrIsExtractable, kCFBooleanTrue);
-            CFDictionaryAddValue(pubkey_parameters, kSecAttrAccessible,
-                                 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly);
-            if (delete) {
-                status = SecItemDelete(key_parameters);
-                if (status == errSecSuccess) {
-                    status = SecItemDelete(pubkey_parameters);
-                    if (status != errSecSuccess) {
-                        ERROR("srp_get_key_internal: failed to delete the public key");
-                    }
-                }
-                key = NULL;
-            } else {
-                key = calloc(1, sizeof(*key));
-
-                if (key != NULL) {
-                    CFErrorRef error = NULL;
-
-                    // See if the key is already on the keychain.
-                    status = SecItemCopyMatching(key_parameters, (CFTypeRef *)&key->private);
-                    if (status == errSecSuccess) {
-                        status = SecItemCopyMatching(pubkey_parameters, (CFTypeRef *)&key->public);
-                    } else {
-                        key->private = SecKeyCreateRandomKey(key_parameters, &error);
-                        if (key->private != NULL) {
-                            key->public = SecKeyCopyPublicKey(key->private);
-                        }
-                    }
-                    if (key->public == NULL || key->private == NULL) {
-                        if (error != NULL) {
-                            CFShow(error);
-                        } else {
-                            srp_sec_error_print("Failed to get key pair", status);
-                        }
-                        free(key);
-                        key = NULL;
-                    }
-                }
-            }
-            CFRelease(key_parameters);
-            CFRelease(pubkey_parameters);
-        }
-    }
-    return key;
-}
-
-srp_key_t *
-srp_get_key(const char *key_name, void *__unused os_context)
-{
-    return srp_get_key_internal(key_name, false);
-}
-
-// Remove an existing key
-int
-srp_reset_key(const char *key_name, void *__unused os_context)
-{
-    srp_get_key_internal(key_name, true);
-    return kDNSServiceErr_NoError;
-}
-
-// void to get the length of the public key
-size_t
-srp_pubkey_length(srp_key_t *key)
-{
-    (void)key;
-    return ECDSA_KEY_SIZE;
-}
-
-uint8_t
-srp_key_algorithm(srp_key_t *key)
-{
-    (void)key;
-    return dnssec_keytype_ecdsa;
-}
-
-size_t
-srp_signature_length(srp_key_t *key)
-{
-    (void)key;
-    return ECDSA_KEY_SIZE;
-}
-
-// Function to copy out the public key as binary data
-size_t
-srp_pubkey_copy(uint8_t *buf, size_t max, srp_key_t *key)
-{
-    CFErrorRef error = NULL;
-    size_t ret = 0;
-    CFDataRef pubkey = SecKeyCopyExternalRepresentation(key->public, &error);
-    if (pubkey == NULL) {
-        if (error != NULL) {
-            CFShow(error);
-        } else {
-            ERROR("Unknown failure in SecKeyCopyExternalRepresentation");
-        }
-    } else {
-        const uint8_t *bytes = CFDataGetBytePtr(pubkey);
-        unsigned long len = (unsigned long)CFDataGetLength(pubkey);
-
-        // Should be 04 | X | Y
-        if (bytes[0] != 4) {
-            ERROR("Unexpected preamble to public key: %d", bytes[0]);
-        } else if (len - 1 > max) {
-            ERROR("Not enough room for public key in buffer: %ld > %zd", len - 1, max);
-        } else if (len - 1 != ECDSA_KEY_SIZE) {
-            ERROR("Unexpected key size %ld", len - 1);
-        } else {
-            memcpy(buf, bytes + 1, len - 1);
-            ret = ECDSA_KEY_SIZE;
-        }
-        CFRelease(pubkey);
-    }
-    return ret;
-}
-
-// Function to generate a signature given some data and a private key
-int
-srp_sign(uint8_t *output, size_t max, uint8_t *message, size_t msglen,
-         uint8_t *rr, size_t rdlen, srp_key_t *key)
-{
-    CFMutableDataRef payload = NULL;
-    CFDataRef signature = NULL;
-    CFErrorRef error = NULL;
-    const uint8_t *bytes;
-    unsigned long len;
-    int ret = 0;
-
-    if (max < ECDSA_SHA256_SIG_SIZE) {
-        ERROR("srp_sign: not enough space in output buffer (%lu) for signature (%d).",
-              (unsigned long)max, ECDSA_SHA256_SIG_SIZE);
-        return 0;
-    }
-
-    payload = CFDataCreateMutable(NULL, (CFIndex)(msglen + rdlen));
-    if (payload == NULL) {
-        ERROR("srp_sign: CFDataCreateMutable failed on length %zd", msglen + rdlen);
-        return 0;
-    }
-    CFDataAppendBytes(payload, rr, (CFIndex)rdlen);
-    CFDataAppendBytes(payload, message, (CFIndex)msglen);
-
-    signature = SecKeyCreateSignature(key->private,
-                                      kSecKeyAlgorithmECDSASignatureMessageX962SHA256, payload, &error);
-    CFRelease(payload);
-    if (error != NULL) {
-        CFRelease(signature);
-        CFShow(error);
-        return 0;
-    }
-    if (signature == NULL) {
-        ERROR("No error, but no signature.");
-        return 0;
-    }
-
-    len = (unsigned long)CFDataGetLength(signature);
-    bytes = CFDataGetBytePtr(signature);
-    // The buffer is ASN.1 DER encoded as two numbers, so should be 30 <len> 02 <len> <bytes> 02 <len> <bytes>.
-    if (len < 8) {
-        ERROR("signature is too short to parse: %lu bytes", len);
-        goto out;
-    }
-#define ASN1_SEQUENCE 0x30
-    if (bytes[0] != ASN1_SEQUENCE) {
-        ERROR("Unexpected ASN.1 type for signature: %x", bytes[0]);
-        goto out;
-    }
-    unsigned len_sequence = bytes[1];
-    if (len_sequence != len - 2) { // This is the length of the sequence, which is the remainder of the buffer
-        ERROR("Unexpected ASN.1 sequence length %u when %lu bytes remain", len_sequence, len - 2);
-        goto out;
-    }
-    const uint8_t *sequence_start = &bytes[2];
-    unsigned sequence_available = len_sequence;
-    int index = 0;
-    while (sequence_available > 0) {
-        if (index > 1) {
-            ERROR("Unexpected extra datum in top-level ASN.1 sequence for signature.");
-            goto out;
-        }
-#define ASN1_INTEGER 0x02
-        if (sequence_start[0] != ASN1_INTEGER) {
-            ERROR("Unexpected ASN.1 type for key half %d: %x", index, bytes[2]);
-            goto out;
-        }
-        unsigned len_half = sequence_start[1];
-        if (len_half > sequence_available - 2 || len_half > ECDSA_SHA256_SIG_PART_SIZE + 1) {
-            ERROR("key half %d is too long: length %u, sequence length %u, sig part size %d",
-                  index, len_half, len_sequence, ECDSA_SHA256_SIG_PART_SIZE);
-            goto out;
-        }
-        // Now that we've bounds-checked this key half, reduce the available space by its length for
-        // the next round.
-        sequence_available = sequence_available - len_half - 2;
-
-        // The key data are bignums. If the first byte of either bignum is >0x7f, it will include a leading zero
-        // to make it unsigned, which we don't need.
-        const uint8_t *key_half = sequence_start[2] == 0 ? &sequence_start[3] : &sequence_start[2];
-        if (sequence_start[2] == 0) {
-            len_half--;
-        }
-
-        unsigned long diff = ECDSA_SHA256_SIG_PART_SIZE - len_half;
-        uint8_t *output_start = output + index * ECDSA_SHA256_SIG_PART_SIZE;
-        if (diff > 0) {
-            memset(output_start, 0, diff);
-        }
-        memcpy(output_start + diff, key_half, len_half);
-        sequence_start = key_half + len_half;
-        index++;
-    }
-    ret = ECDSA_SHA256_SIG_PART_SIZE * 2;
-
-    for (int j = 0; j < 2; j++) {
-        const uint8_t *buf = j == 0 ? bytes : output;
-        char sigbuf[300];
-        char *sigbufp = sigbuf;
-        for (unsigned i = 0; i < len && (size_t)(sigbufp - sigbuf) < sizeof(sigbuf) - 3; i++) {
-            snprintf(sigbufp, 4, "%02x ", buf[i]);
-            sigbufp += 3;
-        }
-        *sigbufp = 0;
-        INFO("%s: %s", j == 0 ? "input" : "output", sigbuf);
-    }
-
-out:
-    if (signature != NULL) {
-        CFRelease(signature);
-    }
-    return ret;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/sign-mbedtls.c b/ServiceRegistration/sign-mbedtls.c
deleted file mode 100644
index 72c9ca5..0000000
--- a/ServiceRegistration/sign-mbedtls.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/* sign-mbedtls.c
- *
- * Copyright (c) 2018-2019 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.
- *
- * DNS SIG(0) signature generation for DNSSD SRP using mbedtls.
- *
- * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
- * into KEY RR data, and computing signatures.
- *
- * This is the implementation for mbedtls, e.g. on Thread Devices, Linux, and OpenWRT.
- */
-
-#include <stdio.h>
-#ifdef THREAD_DEVKIT_ADK
-#include <openthread/random_noncrypto.h>
-#include "HAPPlatformRandomNumber.h"
-#else
-#include <arpa/inet.h>
-#ifdef LINUX_GETENTROPY
-#define _GNU_SOURCE
-#include <linux/random.h>
-#include <sys/syscall.h>
-#else
-#include <sys/random.h>
-#endif // LINUX_GETENTROPY
-#endif // THREAD_DEVKIT_ADK
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "dns_sd.h"
-
-// For debugging
-#ifdef DEBUG_SHA256
-int
-srp_mbedtls_sha256_update_ret(const char *thing_name,
-                              mbedtls_sha256_context *sha, uint8_t *data, size_t len)
-{
-    int i;
-    fprintf(stderr, "%s %lu: ", thing_name, (unsigned long)len);
-    if (len > 400) {
-        len = 400;
-    }
-
-    for (i = 0; i < len; i++) {
-        fprintf(stderr, "%02x", data[i]);
-    }
-    fputs("\n", stderr);
-    return mbedtls_sha256_update_ret(sha, data, len);
-}
-
-int
-srp_mbedtls_sha256_finish_ret(mbedtls_sha256_context *sha, uint8_t *hash)
-{
-    int i;
-    int status = mbedtls_sha256_finish_ret(sha, hash);
-    fprintf(stderr, "hash:     ");
-    for (i = 0; i < ECDSA_SHA256_HASH_SIZE; i++) {
-        fprintf(stderr, "%02x", hash[i]);
-    }
-    fputs("\n", stderr);
-    return status;
-}
-#endif
-
-// Key is stored in an opaque data structure, for mbedtls this is an mbedtls_pk_context.
-// Function to read a public key from a KEY record
-// Function to validate a signature given some data and a public key (not required on client)
-
-// Function to free a key
-void
-srp_keypair_free(srp_key_t *key)
-{
-    mbedtls_pk_free(&key->key);
-    free(key);
-}
-
-// Needed to seed the RNG with good entropy data.
-static int
-get_entropy(void *data, unsigned char *output, size_t len, size_t *outlen)
-{
-#ifdef THREAD_DEVKIT_ADK
-    HAPPlatformRandomNumberFill(output, len);
-    *outlen = len;
-    return 0;
-#else
-#ifdef LINUX_GETENTROPY
-    int result = syscall(SYS_getrandom, output, len, GRND_RANDOM);
-#else
-    int result = getentropy(output, len);
-#endif
-    (void)data;
-
-    if (result != 0) {
-        ERROR("getentropy returned %s", strerror(errno));
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-    }
-    *outlen = len;
-#endif // THREAD_DEVKIT_ADK
-    return 0;
-}
-
-// mbedtls on embedded devices seems to react poorly to multiple rng contexts, so we create just
-// one and keep it around.   It would be nice if this got fixed, but it's actually more efficient
-// to have one context, so not something we need to fix.
-typedef struct rng_state {
-    mbedtls_entropy_context entropy_context;
-    mbedtls_ctr_drbg_context rng_context;
-    char errbuf[64];
-} rng_state_t;
-
-static rng_state_t *rng_state;
-
-bool
-rng_state_fetch(void)
-{
-    int status;
-
-    if (rng_state == NULL) {
-        rng_state = calloc(1, sizeof *rng_state);
-        if (rng_state == NULL) {
-            ERROR("srp_random16(): no memory for state.");
-            goto fail;
-        }
-
-        mbedtls_entropy_init(&rng_state->entropy_context);
-        status = mbedtls_entropy_add_source(&rng_state->entropy_context, get_entropy,
-                                            NULL, 1, MBEDTLS_ENTROPY_SOURCE_STRONG);
-        if (status != 0) {
-            mbedtls_strerror(status, rng_state->errbuf, sizeof rng_state->errbuf);
-            ERROR("mbedtls_entropy_add_source failed: %s", rng_state->errbuf);
-            goto fail;
-        }
-
-        mbedtls_ctr_drbg_init(&rng_state->rng_context);
-        status = mbedtls_ctr_drbg_seed(&rng_state->rng_context,
-                                       mbedtls_entropy_func, &rng_state->entropy_context, NULL, 0);
-
-        if (status != 0) {
-            mbedtls_strerror(status, rng_state->errbuf, sizeof rng_state->errbuf);
-            ERROR("mbedtls_ctr_drbg_seed failed: %s", rng_state->errbuf);
-        fail:
-            free(rng_state);
-            rng_state = NULL;
-            return false;
-        }
-    }
-    return true;
-}
-
-static srp_key_t *
-srp_key_setup(void)
-{
-    srp_key_t *key = calloc(1, sizeof(*key));
-
-    if (key == NULL) {
-        return key;
-    }
-
-    mbedtls_pk_init(&key->key);
-    if (rng_state_fetch()) {
-        return key;
-    }
-    mbedtls_pk_free(&key->key);
-    free(key);
-    return NULL;
-}
-
-uint16_t
-srp_random16()
-{
-    int status;
-    uint16_t ret;
-    char errbuf[64];
-    if (rng_state_fetch()) {
-        status = mbedtls_ctr_drbg_random(&rng_state->rng_context, (unsigned char *)&ret, sizeof ret);
-        if (status != 0) {
-            mbedtls_strerror(status, errbuf, sizeof errbuf);
-            ERROR("mbedtls_ctr_drbg_random failed: %s", errbuf);
-            return 0xffff;
-        }
-        return ret;
-    }
-    return 0xffff;
-}
-
-uint32_t
-srp_random32()
-{
-    int status;
-    uint32_t ret;
-    char errbuf[64];
-    if (rng_state_fetch()) {
-        status = mbedtls_ctr_drbg_random(&rng_state->rng_context, (unsigned char *)&ret, sizeof ret);
-        if (status != 0) {
-            mbedtls_strerror(status, errbuf, sizeof errbuf);
-            ERROR("mbedtls_ctr_drbg_random failed: %s", errbuf);
-            return 0xffffffff;
-        }
-        return ret;
-    }
-    return 0xffffffff;
-}
-
-uint64_t
-srp_random64()
-{
-    int status;
-    uint64_t ret;
-    char errbuf[64];
-    if (rng_state_fetch()) {
-        status = mbedtls_ctr_drbg_random(&rng_state->rng_context, (unsigned char *)&ret, sizeof ret);
-        if (status != 0) {
-            mbedtls_strerror(status, errbuf, sizeof errbuf);
-            ERROR("mbedtls_ctr_drbg_random failed: %s", errbuf);
-            return 0xffffffffffffffffull;
-        }
-        return ret;
-    }
-    return 0xffffffffffffffffull;
-}
-
-bool
-srp_randombytes(uint8_t *dest, size_t num)
-{
-    int status;
-    char errbuf[64];
-    if (rng_state_fetch()) {
-        status = mbedtls_ctr_drbg_random(&rng_state->rng_context, (unsigned char *)dest, num);
-        if (status != 0) {
-            mbedtls_strerror(status, errbuf, sizeof errbuf);
-            ERROR("mbedtls_ctr_drbg_random failed: %s", errbuf);
-            return false;
-        }
-        return true;
-    }
-    return false;
-}
-
-srp_key_t *
-srp_load_key_from_buffer(const uint8_t *buffer, size_t length)
-{
-    srp_key_t *key;
-    int status;
-    char errbuf[64];
-
-    key = srp_key_setup();
-    if (key == NULL) {
-        return NULL;
-    }
-
-    if ((status = mbedtls_pk_parse_key(&key->key, buffer, length, NULL, 0)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_pk_parse_key failed: %s", errbuf);
-    } else if (!mbedtls_pk_can_do(&key->key, MBEDTLS_PK_ECDSA)) {
-        ERROR("Buffer does not contain a usable ECDSA key.");
-    } else {
-        return key;
-    }
-    srp_keypair_free(key);
-    return NULL;
-}
-
-// Function to generate a key
-srp_key_t *
-srp_generate_key(void)
-{
-    srp_key_t *key;
-    int status;
-    char errbuf[64];
-    const mbedtls_pk_info_t *key_type;
-
-    INFO("srp_key_setup");
-    key = srp_key_setup();
-    if (key == NULL) {
-        ERROR("srp_key_setup() failed.");
-        return NULL;
-    }
-    key_type = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
-    if (key_type == NULL) {
-        INFO("mbedtls_pk_info_from_type failed");
-        return NULL;
-    }
-
-    INFO("mbedtls_pk_setup");
-    if ((status = mbedtls_pk_setup(&key->key, key_type)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_pk_setup failed: %s", errbuf);
-    } else {
-        INFO("mbedtls_pk_ecdsa_genkey");
-        if ((status = mbedtls_ecdsa_genkey(mbedtls_pk_ec(key->key), MBEDTLS_ECP_DP_SECP256R1,
-                                           mbedtls_ctr_drbg_random, &rng_state->rng_context)) != 0) {
-            mbedtls_strerror(status, errbuf, sizeof errbuf);
-            ERROR("mbedtls_ecdsa_genkey failed: %s", errbuf);
-        } else {
-            return key;
-        }
-    }
-    srp_keypair_free(key);
-    return NULL;
-}
-
-// Copy an srp_key_t into a buffer.   Key is not necessarily aligned with the beginning of the
-// buffer; the return value, if not NULL, is the beginning of the key.   If NULL, the buffer wasn't
-// big enough.
-uint8_t *
-srp_store_key_to_buffer(uint8_t *buffer, size_t *length, srp_key_t *key)
-{
-    size_t len = mbedtls_pk_write_key_der(&key->key, buffer, *length);
-    uint8_t *ret;
-    char errbuf[64];
-    if (len <= 0) {
-        mbedtls_strerror(len, errbuf, sizeof errbuf);
-        ERROR("mbedtls_pk_write_key_der failed: %s", errbuf);
-        return NULL;
-    }
-    ret = &buffer[*length - len];
-    *length = len;
-    return ret;
-}
-
-srp_key_t *
-srp_get_key(const char *key_name, void *os_context)
-{
-    uint8_t buf[256];
-    uint16_t buf_length;
-    uint8_t *key_bytes;
-    size_t keydata_length;
-    int err;
-    srp_key_t *key;
-
-    err = srp_load_key_data(os_context, key_name, buf, &buf_length, sizeof buf);
-    if (err == kDNSServiceErr_NoError) {
-        key = srp_load_key_from_buffer(buf, buf_length);
-        if (key == NULL) {
-            INFO("load key fail");
-            return NULL;
-        }
-        // Otherwise we have a key.
-    } else if (err == kDNSServiceErr_NoSuchKey) {
-        key = srp_generate_key();
-        if (key == NULL) {
-            INFO("gen key fail");
-            return NULL;
-        }
-        keydata_length = sizeof buf;
-        if ((key_bytes = srp_store_key_to_buffer(buf, &keydata_length, key)) == NULL) {
-            INFO("store key fail");
-            return NULL;
-        }
-        // Note that it's possible for key_bytes != buf.
-        err = srp_store_key_data(os_context, key_name, key_bytes, (uint16_t)keydata_length);
-        if (err != kDNSServiceErr_NoError) {
-            INFO("store key data fail");
-            return NULL;
-        }
-    } else {
-        INFO("weird error %d", err);
-        return NULL;
-    }
-    return key;
-}
-
-// Function to get the length of the public key
-size_t
-srp_pubkey_length(srp_key_t *key)
-{
-    return ECDSA_KEY_SIZE;
-}
-
-uint8_t
-srp_key_algorithm(srp_key_t *key)
-{
-    return dnssec_keytype_ecdsa;
-}
-
-size_t
-srp_signature_length(srp_key_t *key)
-{
-    return ECDSA_KEY_SIZE;
-}
-
-// Function to copy out the public key as binary data
-size_t
-srp_pubkey_copy(uint8_t *buf, size_t max, srp_key_t *key)
-{
-    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key->key);
-    char errbuf[64];
-    int status;
-
-    if (max < ECDSA_KEY_SIZE) {
-        return 0;
-    }
-
-    // Currently ECP only.
-    if ((status = mbedtls_mpi_write_binary(&ecp->Q.X, buf, ECDSA_KEY_PART_SIZE)) != 0 ||
-        (status = mbedtls_mpi_write_binary(&ecp->Q.Y, buf + ECDSA_KEY_PART_SIZE, ECDSA_KEY_PART_SIZE)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_mpi_write_binary: %s", errbuf);
-        return 0;
-    }
-
-#ifdef MBEDTLS_PUBKEY_DUMP
-    int i;
-    fprintf(stderr, "pubkey %d: ", ECDSA_KEY_SIZE);
-    for (i = 0; i < ECDSA_KEY_SIZE; i++) {
-        fprintf(stderr, "%02x", buf[i]);
-    }
-    putc('\n', stderr);
-#endif // MBEDTLS_PUBKEY_DUMP
-    return ECDSA_KEY_SIZE;
-}
-
-// Function to generate a signature given some data and a private key
-int
-srp_sign(uint8_t *output, size_t max, uint8_t *message, size_t msglen, uint8_t *rr, size_t rdlen, srp_key_t *key)
-{
-    int success = 1;
-    int status;
-    unsigned char hash[ECDSA_SHA256_HASH_SIZE];
-    char errbuf[64];
-    mbedtls_sha256_context *sha;
-    uint8_t shabuf[16 + sizeof(*sha)];
-    uint32_t *sbp;
-    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key->key);
-    mbedtls_mpi r, s;
-
-    if (max < ECDSA_SHA256_SIG_SIZE) {
-        ERROR("srp_sign: not enough space in output buffer (%lu) for signature (%d).",
-              (unsigned long)max, ECDSA_SHA256_SIG_SIZE);
-        return 0;
-    }
-
-    sbp = (uint32_t *)shabuf;
-    sha = (mbedtls_sha256_context *)sbp;
-    mbedtls_sha256_init(sha);
-    memset(hash, 0, sizeof hash);
-    mbedtls_mpi_init(&r);
-    mbedtls_mpi_init(&s);
-
-    // Calculate the hash across first the SIG RR (minus the signature) and then the message
-    // up to but not including the SIG RR.
-    status = mbedtls_sha256_starts_ret(sha, 0);
-    if (status == 0) {
-        status = srp_mbedtls_sha256_update_ret("rr", sha, rr, rdlen);
-    }
-    if (status == 0) {
-        status = srp_mbedtls_sha256_update_ret("message", sha, message, msglen);
-    }
-    if (status == 0) {
-        status = srp_mbedtls_sha256_finish_ret(sha, hash);
-    }
-    if (status != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_sha_256 hash failed: %s", errbuf);
-        success = 0;
-        goto cleanup;
-    }
-
-    status = mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, hash, sizeof hash,
-                                mbedtls_ctr_drbg_random, &rng_state->rng_context);
-    if (status != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_ecdsa_sign failed: %s", errbuf);
-        success = 0;
-        goto cleanup;
-    }
-
-    if ((status = mbedtls_mpi_write_binary(&r, output, ECDSA_SHA256_SIG_PART_SIZE)) != 0 ||
-        (status = mbedtls_mpi_write_binary(&s, output + ECDSA_SHA256_SIG_PART_SIZE,
-                                           ECDSA_SHA256_SIG_PART_SIZE)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_ecdsa_sign failed: %s", errbuf);
-        success = 0;
-        goto cleanup;
-    }
-cleanup:
-    mbedtls_mpi_free(&r);
-    mbedtls_mpi_free(&s);
-    return success;
-}
-
-#ifndef THREAD_DEVKIT_ADK
-int
-srp_reset_key(const char *key_name, void *UNUSED os_context)
-{
-    return srp_remove_key_file(os_context, key_name);
-}
-#endif
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-api.h b/ServiceRegistration/srp-api.h
deleted file mode 100644
index 7168922..0000000
--- a/ServiceRegistration/srp-api.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* srp-api.h
- *
- * Copyright (c) 2019 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.
- *
- * Structure definitions for the Service Registration Protocol gateway.
- */
-
-#include "srp.h"
-#if defined(THREAD_DEVKIT_ADK) || defined(LINUX)
-#include "../mDNSShared/dns_sd.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*srp_hostname_conflict_callback_t)(const char *NONNULL hostname);
-typedef void (*srp_wakeup_callback_t)(void *NONNULL state);
-typedef void (*srp_datagram_callback_t)(void *NONNULL state, void *NONNULL message, size_t message_length);
-
-// The below functions provide a way for the host to inform the SRP service of the state of the network.
-
-// Call this before calling anything else.   Context will be passed back whenever the srp code
-// calls any of the host functions.
-int srp_host_init(void *NULLABLE host_context);
-
-// Call this to reset the host key (e.g. on factory reset)
-int srp_host_key_reset(void);
-
-// This function can be called by accessories that have different requirements for lease intervals.
-// Normally new_lease_time would be 3600 (1 hour) and new_key_lease_type would be 604800 (7 days).
-int srp_set_lease_times(uint32_t new_lease_time, uint32_t new_key_lease_time);
-
-// Called when a new address is configured that should be advertised.  This can be called during a refresh,
-// in which case it doesn't mark the network state as changed if the address was already present.
-int srp_add_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen);
-
-// Called whenever the SRP server address changes or the SRP server becomes newly reachable.  This can be
-// called during a refresh, in which case it doesn't mark the network state as changed if the address was
-// already present.
-int srp_add_server_address(const uint8_t *NONNULL port, uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen);
-
-// Called when the node knows its hostname (usually once).   The callback is called if we try to do an SRP
-// update and find out that the hostname is in use; in this case, the callback is expected to generate a new
-// hostname and re-register it.   It is permitted to call srp_set_hostname() from the callback.
-// If the hostname is changed by the callback, then it is used immediately on return from the callback;
-// if the hostname is changed in any other situation, nothing is done with the new name until
-// srp_network_state_stable() is called.
-int srp_set_hostname(const char *NONNULL hostname, srp_hostname_conflict_callback_t NULLABLE callback);
-
-// Called when a network state change is complete (that is, all new addresses have been saved and
-// any update to the SRP server address has been provided).   This is only needed when not using the
-// refresh mechanism.
-int srp_network_state_stable(bool *NULLABLE did_something);
-
-// Delete a previously-configured SRP server address.  This should not be done during a refresh.
-int srp_delete_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen);
-
-// Delete a previously-configured SRP server address.  This should not be done during a refresh.
-int srp_delete_server_address(uint16_t rrtype, const uint8_t *NONNULL port, const uint8_t *NONNULL rdata,
-                              uint16_t rdlen);
-
-// Call this to start an address refresh.   This makes sense to do in cases where the caller
-// is not tracking changes, but rather is just doing a full refresh whenever the network state
-// is seen to have changed.   When the refresh is done, if any addresses were added or removed,
-// network_state_changed will be true, and so a call to dnssd_network_state_change_finished()
-// will trigger an update; if nothing changed, no update will be sent.
-int srp_start_address_refresh(void);
-
-// Call this when the address refresh is done.   This invokes srp_network_state_stable().
-int srp_finish_address_refresh(bool *NULLABLE did_something);
-
-// Call this to deregister everything that's currently registered.  A return value other than kDNSServiceErr_NoError
-// means that there's nothing to deregister.
-int srp_deregister(void *NULLABLE os_context);
-
-// Call this to deregister a specific service instance, identified by the DNSServiceRef.  A return value
-// other than kDNSServiceErr_NoError means that the specified service instance wasn't found.
-int srp_deregister_instance(DNSServiceRef NULLABLE sdRef);
-
-// The below functions must be provided by the host.
-
-// This function fetches a key with the specified name for use in signing SRP updates.
-// At present, only ECDSA is supported.   If a key with the specified name doesn't exist,
-// the host is expected to generate and store it.
-srp_key_t *NULLABLE srp_get_key(const char *NONNULL key_name, void *NULLABLE host_context);
-
-// This function clears the key with the specified name.
-int srp_reset_key(const char *NONNULL key_name, void *NULLABLE host_context);
-
-// This function fetches the IP address type (rrtype), address (rrdata x rdlength) and port (port[0],
-// port[1]) of the most recent server with which the SRP client has successfully registered from stable
-// storage.  If the fetch is successful and there was a server recorded in stable storage, it returns true;
-// otherwise it returns false. A false status can mean that there's no way to fetch this information, that
-// no registration has happened in the past, or that there was some other error accessing stable storage.
-bool srp_get_last_server(uint16_t *NONNULL rrtype, uint8_t *NONNULL rrdata, uint16_t rdlength,
-                         uint8_t *NONNULL port, void *NULLABLE host_context);
-
-// This function stores the IP address type (rrtype), address (rrdata x rdlength) and port (port[0],
-// port[1]) of the most recent server with which the SRP client has successfully registered to stable
-// storage.  If the store is successful, it returns true; otherwise it returns false. A false status can
-// mean that there's no way to store this information, or that there was an error writing this information
-// to stable storage.
-bool srp_save_last_server(uint16_t rrtype, uint8_t *NONNULL rrdata, uint16_t rdlength,
-                          uint8_t *NONNULL port, void *NULLABLE host_context);
-
-// This is called to create a context for sending and receiving UDP messages to and from a specified
-// remote host address and port.  The context passed is to be used whenever the srp host implementation
-// does a callback, e.g. when a datagram arrives or when a wakeup occurs (see srp_set_wakeup()).
-// The context is not actually connected to a specific address and port until srp_connect_udp() is
-// invoked on it.
-int srp_make_udp_context(void *NULLABLE host_context, void *NULLABLE *NONNULL p_context,
-                         srp_datagram_callback_t NONNULL callback, void *NONNULL context);
-
-// Connect a udp context to a particular destination.  The context has to have already been created by
-// srp_make_udp_context().  When packets are received, they will be passed to the callback set
-// in srp_make_udp_context().   This must not be called on a context that is already bound to
-// some other destination--call srp_disconnect_udp() first if reusing.
-int
-srp_connect_udp(void *NONNULL context, const uint8_t *NONNULL port, uint16_t address_type,
-                const uint8_t *NONNULL address, uint16_t addrlen);
-
-// Disconnect a udp context.  This is used to dissociate from the udp context state that was created
-// by a previous call to srp_connect_udp
-int
-srp_disconnect_udp(void *NONNULL context);
-
-// This gets rid of the UDP context, frees any associated memory, cancels any outstanding wakeups.
-// The freeing may occur later than the deactivating, depending on how the underlying event loop
-// works.
-int srp_deactivate_udp_context(void *NONNULL host_context, void *NONNULL context);
-
-// This is called to send a datagram to a UDP connection.   The UDP connection is identified by the
-// anonymous pointer that was returned by srp_make_udp_context().
-int srp_send_datagram(void *NULLABLE host_context,
-                      void *NONNULL context, void *NONNULL message, size_t message_length);
-
-// This is called with the context returned by srp_make_udp_context.  The caller is expected to schedule
-// a wakeup event <milliseconds> in the future, when when that event occurs, it's expected to call the
-// callback with the context that was passed to srp_make_udp_context.
-int srp_set_wakeup(void *NULLABLE host_context,
-                   void *NONNULL context, int milliseconds, srp_wakeup_callback_t NONNULL callback);
-
-// This is called to cancel a wakeup, and should not fail even if there is no wakeup pending.
-int srp_cancel_wakeup(void *NULLABLE host_context, void *NONNULL context);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-client.c b/ServiceRegistration/srp-client.c
deleted file mode 100644
index decea60..0000000
--- a/ServiceRegistration/srp-client.c
+++ /dev/null
@@ -1,1625 +0,0 @@
-/* srp-client.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * SRP Client
- *
- * DNSServiceRegister API for SRP.   See dns_sd.h for details on the API.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <errno.h>
-#ifdef THREAD_DEVKIT_ADK
-#include "../mDNSShared/dns_sd.h"
-#else
-#include <dns_sd.h>
-#include <arpa/inet.h>
-#endif
-#include "srp.h"
-#include "srp-api.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-
-// By default, never wait longer than an hour to do another registration attempt.
-#define DEFAULT_MAX_ATTEMPT_INTERVAL       1000 * 60 * 60
-
-// Default retry interval is 15 seconds--three attempts. This is how long we will remain in the process of retrying
-// an update on a particular server before we give up on that server.
-
-#define DEFAULT_MAX_RETRY_INTERVAL         1000 * 15
-
-// When we start talking to a particular server, we allow 2 seconds before the first retransmission
-#define INITIAL_NEXT_RETRANSMISSION_TIME   2000
-
-// When we fail to get through to any server, we will initially re-attempt contacting that server after
-// this amount of time
-#define INITIAL_NEXT_ATTEMPT_TIME          1000 * 2 * 60
-
-
-typedef struct client_state client_state_t;
-
-typedef struct service_addr service_addr_t;
-struct service_addr {
-    service_addr_t *NULLABLE next;
-    dns_rr_t rr;
-    uint8_t port[2];
-};
-
-typedef struct _DNSServiceRef_t reg_state_t;
-typedef struct update_context {
-    void *udp_context;
-    void *message;
-    client_state_t *NONNULL client;
-    service_addr_t *server;
-    size_t message_length;
-    uint32_t next_retransmission_time;
-    uint32_t next_attempt_time;
-    uint32_t lease_time;
-    uint32_t key_lease_time;
-    uint32_t serial;
-    uint32_t interface_serial;
-    bool notified;  // Callers have been notified.
-    bool connected; // UDP context is connected.
-    bool removing;  // We are removing the current registration(s)
-} update_context_t;
-
-struct _DNSServiceRef_t {
-    reg_state_t *NULLABLE next;
-    uint32_t serial;
-    DNSServiceFlags flags;
-    uint32_t interfaceIndex;
-    char *NULLABLE name;
-    char *NULLABLE regtype;
-    char *NULLABLE domain;
-    char *NULLABLE host;
-    int port;
-    uint16_t txtLen;
-    void *NULLABLE txtRecord;
-    DNSServiceRegisterReply callback;
-    bool succeeded;
-    bool called_back;
-    bool removing;
-    bool skip;
-    void *NULLABLE context;
-};
-
-struct client_state {
-    client_state_t *next;
-    reg_state_t *registrations;
-    char *hostname;
-    int hostname_rename_number; // If we've had a naming conflict, this will be nonzero.
-    srp_hostname_conflict_callback_t hostname_conflict_callback;
-    srp_key_t *key;
-    void *os_context;
-    uint32_t lease_time;
-    uint32_t key_lease_time;
-    uint32_t registration_serial;
-    uint32_t srp_max_attempt_interval;
-    uint32_t srp_max_retry_interval;
-    service_addr_t stable_server;
-    bool srp_server_synced;
-
-    uint32_t client_serial;
-    bool client_serial_set;
-
-    // Currently we only ever have one update in flight.  If we decide we need to send another,
-    // we need to cancel the one we're currently doing.
-    update_context_t *active_update;
-};
-
-// Implementation of SRP network entry points, which can be called by the network implementation on the
-// hosting platform.
-
-static bool network_state_changed = false;
-static bool doing_refresh = false;
-static service_addr_t *interfaces;
-static service_addr_t *servers;
-static service_addr_t *interface_refresh_state;
-static service_addr_t *server_refresh_state;
-static uint8_t no_port[2];
-static uint32_t interface_serial;
-
-client_state_t *clients;
-client_state_t *current_client;
-bool zero_addresses = false; // for testing, used by srp-ioloop.c.
-
-// Forward references
-static int do_srp_update(client_state_t *client, bool definite, bool *did_something);
-static void udp_response(void *v_update_context, void *v_message, size_t message_length);
-static dns_wire_t *NULLABLE generate_srp_update(client_state_t *client, uint32_t update_lease_time,
-                                                uint32_t update_key_lease_time, size_t *NONNULL p_length,
-                                                service_addr_t *NONNULL server, uint32_t serial, bool remove);
-static bool srp_is_network_active(void);
-
-#define VALIDATE_IP_ADDR                                         \
-    if ((rrtype != dns_rrtype_a && rrtype != dns_rrtype_aaaa) || \
-        (rrtype == dns_rrtype_a && rdlen != 4) ||                \
-        (rrtype == dns_rrtype_aaaa && rdlen != 16)) {            \
-        return kDNSServiceErr_Invalid;                           \
-    }
-
-// Call this before calling anything else.   Context will be passed back whenever the srp code
-// calls any of the host functions.
-int
-srp_host_init(void *context)
-{
-    client_state_t *new_client = calloc(1, sizeof(*new_client));
-    if (new_client == NULL) {
-        return kDNSServiceErr_NoMemory;
-    }
-    new_client->os_context = context;
-    new_client->lease_time = 3600;       // 1 hour for registration leases
-    new_client->key_lease_time = 604800; // 7 days for key leases
-    new_client->registration_serial = 0;
-    new_client->srp_max_attempt_interval = DEFAULT_MAX_ATTEMPT_INTERVAL;
-    new_client->srp_max_retry_interval = DEFAULT_MAX_RETRY_INTERVAL;
-
-    current_client = new_client;
-    new_client->next = clients;
-    clients = current_client;
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_host_key_reset(void)
-{
-    if (current_client->key != NULL) {
-        srp_keypair_free(current_client->key);
-        current_client->key = NULL;
-    }
-    return srp_reset_key("com.apple.srp-client.host-key", current_client->os_context);
-}
-
-int
-srp_set_lease_times(uint32_t new_lease_time, uint32_t new_key_lease_time)
-{
-    current_client->lease_time = new_lease_time;
-    current_client->key_lease_time = new_key_lease_time;
-    return kDNSServiceErr_NoError;
-}
-
-static void
-sync_from_stable_storage(update_context_t *update)
-{
-    service_addr_t *server;
-    client_state_t *client = update->client;
-    if (!client->srp_server_synced) {
-        client->srp_server_synced =
-            srp_get_last_server(&client->stable_server.rr.type, (uint8_t *)&client->stable_server.rr.data,
-                                sizeof(client->stable_server.rr.data), &client->stable_server.port[0],
-                                client->os_context);
-        // Nothing read.
-        if (!client->srp_server_synced) {
-            return;
-        }
-    } else {
-        if (update->server != NULL) {
-            return;
-        }
-    }
-
-    // See if one of the advertised servers is the one we last updated.
-    for (server = servers; server; server = server->next) {
-        if (server->rr.type == client->stable_server.rr.type &&
-            !memcmp(&server->port, &client->stable_server.port, 2) &&
-            ((server->rr.type == dns_rrtype_a && !memcmp(&server->rr.data, &client->stable_server.rr.data, 4)) ||
-             (server->rr.type == dns_rrtype_aaaa && !memcmp(&server->rr.data, &client->stable_server.rr.data, 16))))
-        {
-            update->server = server;
-            return;
-        }
-    }
-}
-
-static void
-sync_to_stable_storage(update_context_t *update)
-{
-    client_state_t *client = update->client;
-    if (!client->srp_server_synced) {
-        client->srp_server_synced =
-            srp_save_last_server(client->stable_server.rr.type, (uint8_t *)&client->stable_server.rr.data,
-                                 client->stable_server.rr.type == dns_rrtype_a ? 4 : 16,
-                                 client->stable_server.port, client->os_context);
-    }
-}
-
-// Find an address on a list of addresses.
-static service_addr_t **
-find_address(service_addr_t **addrs, const uint8_t *port, uint16_t rrtype, const uint8_t *rdata, uint16_t rdlen)
-{
-    service_addr_t *addr, **p_addr = addrs;
-
-    while (*p_addr != NULL) {
-        addr = *p_addr;
-        if (addr->rr.type == rrtype && !memcmp(&addr->rr.data, rdata, rdlen) && !memcmp(addr->port, port, 2)) {
-            break;
-        }
-        p_addr = &addr->next;
-    }
-    return p_addr;
-}
-
-// Worker function to add an address and notice whether the network state has changed (so as to trigger a
-// refresh).
-static int
-add_address(service_addr_t **list, service_addr_t **refresh,
-            const uint8_t *port, uint16_t rrtype, const uint8_t *rdata, uint16_t rdlen, bool interface_serial_update)
-{
-    service_addr_t *addr, **p_addr, **p_refresh;
-
-    VALIDATE_IP_ADDR;
-
-    // See if the address is on the refresh list.
-    p_refresh = find_address(refresh, port, rrtype, rdata, rdlen);
-
-    // See also if it's on the address list (shouldn't be on both).  This also finds the end of the list.
-    p_addr = find_address(list, port, rrtype, rdata, rdlen);
-    if (*p_addr != NULL) {
-        return kDNSServiceErr_NoError;
-    }
-
-    if (*p_refresh != NULL) {
-        addr = *p_refresh;
-
-        // This shouldn't happen, but if it does, free the old address.
-        if (*p_addr != NULL) {
-            ERROR("duplicate address during refresh!");
-            free(addr);
-            return kDNSServiceErr_NoError;
-        }
-
-        *p_refresh = addr->next;
-        addr->next = NULL;
-        *p_addr = addr;
-
-        // In this case, the network state has not changed.
-        return kDNSServiceErr_NoError;
-    }
-
-    addr = calloc(1, sizeof *addr);
-    if (addr == NULL) {
-        return kDNSServiceErr_NoMemory;
-    }
-    addr->rr.type = rrtype;
-    addr->rr.qclass = dns_qclass_in;
-    memcpy(&addr->rr.data, rdata, rdlen);
-    memcpy(&addr->port, port, 2);
-    *p_addr = addr;
-    network_state_changed = true;
-    if (interface_serial_update) {
-        interface_serial++;
-    }
-
-    // Print IPv6 address directly here because the code has to be portable for ADK, and OpenThread environment
-    // has no support for INET6_ADDRSTRLEN.
-    INFO("added " PUB_S_SRP
-         " address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x port %u (%04x)",
-         *list == servers ? "server" : "interface",
-         rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7],
-         rdata[8], rdata[9], rdata[10], rdata[11], rdata[12], rdata[13], rdata[14], rdata[15],
-         port != NULL ? (port[0] << 8 | port[1]) : 0, port != NULL ? (port[0] << 8 | port[1]) : 0);
-
-    return kDNSServiceErr_NoError;
-}
-
-// Called when a new address is configured that should be advertised.  This can be called during a refresh,
-// in which case it doesn't mark the network state as changed if the address was already present.
-int
-srp_add_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
-{
-    return add_address(&interfaces, &interface_refresh_state, no_port, rrtype, rdata, rdlen, true);
-}
-
-// Called whenever the SRP server address changes or the SRP server becomes newly reachable.  This can be
-// called during a refresh, in which case it doesn't mark the network state as changed if the address was
-// already present.
-int
-srp_add_server_address(const uint8_t *port, uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
-{
-    VALIDATE_IP_ADDR;
-
-    return add_address(&servers, &server_refresh_state, port, rrtype, rdata, rdlen, false);
-}
-
-// Called when the node knows its hostname (usually once).   The callback is called if we try to do an SRP
-// update and find out that the hostname is in use; in this case, the callback is expected to generate a new
-// hostname and re-register it.   It is permitted to call srp_set_hostname() from the callback.
-// If the hostname is changed by the callback, then it is used immediately on return from the callback;
-// if the hostname is changed in any other situation, nothing is done with the new name until
-// srp_network_state_stable() is called.
-int
-srp_set_hostname(const char *NONNULL name, srp_hostname_conflict_callback_t callback)
-{
-    if (current_client->hostname != NULL) {
-        free(current_client->hostname);
-    }
-    current_client->hostname = strdup(name);
-    if (current_client->hostname == NULL) {
-        return kDNSServiceErr_NoMemory;
-    }
-    current_client->hostname_conflict_callback = callback;
-    network_state_changed = true;
-    return kDNSServiceErr_NoError;
-}
-
-// Called when a network state change is complete (that is, all new addresses have been saved and
-// any update to the SRP server address has been provided).   This is only needed when not using the
-// refresh mechanism.
-static bool
-srp_is_network_active(void)
-{
-    INFO("nsc = %d servers = %p interfaces = %p, hostname = " PRI_S_SRP,
-          network_state_changed, servers, interfaces,
-         current_client->hostname ? current_client->hostname : "<not set>");
-    return servers != NULL && (interfaces != NULL || zero_addresses) && current_client->hostname != NULL;
-}
-
-int
-srp_network_state_stable(bool *did_something)
-{
-    client_state_t *client;
-    int status = kDNSServiceErr_NoError;
-    if (network_state_changed && srp_is_network_active()) {
-        network_state_changed = false;
-        for (client = clients; client; client = client->next) {
-            int ret = do_srp_update(client, false, did_something);
-            // In the normal case, there will only be one client, and therefore one return status.  For testing,
-            // we allow more than one client; if we get an error here, we return it, but we still launch all the
-            // updates.
-            if (ret != kDNSServiceErr_NoError && status == kDNSServiceErr_NoError) {
-                status = ret;
-            }
-        }
-    }
-    return kDNSServiceErr_NoError;
-}
-
-// Worker function to delete a server or interface address that was previously configured.
-static int
-delete_address(service_addr_t **list, const uint8_t *port, uint16_t rrtype, const uint8_t *NONNULL rdata,
-               uint16_t rdlen, bool interface_serial_update)
-{
-    service_addr_t *addr, **p_addr;
-
-    // Delete API and refresh API are incompatible.
-    if (doing_refresh) {
-        return kDNSServiceErr_BadState;
-    }
-    VALIDATE_IP_ADDR;
-
-    // See if we know this address.
-    p_addr = find_address(list, port, rrtype, rdata, rdlen);
-    if (*p_addr != NULL) {
-        addr = *p_addr;
-        *p_addr = addr->next;
-        free(addr);
-        network_state_changed = true;
-        if (interface_serial_update) {
-            interface_serial++;
-        }
-        return kDNSServiceErr_NoError;
-    }
-    return kDNSServiceErr_NoSuchRecord;
-}
-
-// Delete a previously-configured SRP server address.  This should not be done during a refresh.
-int
-srp_delete_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
-{
-    return delete_address(&interfaces, no_port, rrtype, rdata, rdlen, true);
-}
-
-// Delete a previously-configured SRP server address.  This should not be done during a refresh.
-int
-srp_delete_server_address(uint16_t rrtype, const uint8_t *port, const uint8_t *NONNULL rdata, uint16_t rdlen)
-{
-    return delete_address(&servers, port, rrtype, rdata, rdlen, false);
-}
-
-// Call this to start an address refresh.   This makes sense to do in cases where the caller
-// is not tracking changes, but rather is just doing a full refresh whenever the network state
-// is seen to have changed.   When the refresh is done, if any addresses were added or removed,
-// network_state_changed will be true, and so a call to dnssd_network_state_change_finished()
-// will trigger an update; if nothing changed, no update will be sent.
-int
-srp_start_address_refresh(void)
-{
-    if (doing_refresh) {
-        return kDNSServiceErr_BadState;
-    }
-    doing_refresh = true;
-    interface_refresh_state = interfaces;
-    server_refresh_state = servers;
-    interfaces = NULL;
-    servers = NULL;
-    network_state_changed = false;
-    return kDNSServiceErr_NoError;
-}
-
-// Call this when the address refresh is done.   This invokes srp_network_state_stable().
-int
-srp_finish_address_refresh(bool *did_something)
-{
-    service_addr_t *addr, *next;
-    int i;
-    if (!doing_refresh) {
-        return kDNSServiceErr_BadState;
-    }
-    for (i = 0; i < 2; i++) {
-        if (i == 0) {
-            next = server_refresh_state;
-            server_refresh_state = NULL;
-        } else {
-            if (interface_refresh_state != NULL) {
-                interface_serial++;
-            }
-            next = interface_refresh_state;
-            interface_refresh_state = NULL;
-        }
-        if (next != NULL) {
-            network_state_changed = true;
-        }
-        while (next) {
-            uint8_t *rdata = (uint8_t *)&next->rr.data;
-            // Print IPv6 address directly here because the code has to be portable for ADK, and OpenThread environment
-            // has no support for INET6_ADDRSTRLEN.
-            INFO("deleted " PUB_S_SRP
-                 " address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x port %u (%x)",
-                 i ? "interface" : "server",
-                 rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7],
-                 rdata[8], rdata[9], rdata[10], rdata[11], rdata[12], rdata[13], rdata[14], rdata[15],
-                 (next->port[0] << 8) | next->port[1], (next->port[0] << 8) | next->port[1]);
-            addr = next;
-            next = addr->next;
-            free(addr);
-        }
-    }
-    doing_refresh = false;
-    return srp_network_state_stable(did_something);
-}
-
-// Implementation of the API that the application will call to update the TXT record after having registered
-// a service previously with a different TXT record.   In principle this can also update a record added with
-// DNSServiceAddRecord or DNSServiceRegisterRecord, but we don't support those APIs at present.
-
-DNSServiceErrorType
-DNSServiceUpdateRecord(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags,
-                       uint16_t rdlen, const void *rdata, uint32_t ttl)
-{
-    reg_state_t *registration;
-    void *txtRecord = NULL;
-
-    (void)RecordRef;
-    (void)flags;
-    (void)ttl;
-
-    if (sdRef == NULL || RecordRef != NULL || rdata == NULL) {
-        return kDNSServiceErr_Invalid;
-    }
-
-    // Add it to the list (so it will appear valid to DNSServiceRefDeallocate()).
-    for (registration = current_client->registrations; registration != NULL; registration = registration->next) {
-        if (registration == sdRef) {
-            break;
-        }
-    }
-    if (registration == NULL) {
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (rdlen != 0) {
-        txtRecord = malloc(rdlen);
-        if (txtRecord == NULL) {
-            return kDNSServiceErr_NoMemory;
-        }
-        memcpy(txtRecord, rdata, rdlen);
-    } else {
-        registration->txtRecord = NULL;
-    }
-
-    if (registration->txtRecord != NULL) {
-        free(registration->txtRecord);
-    }
-
-    registration->txtRecord = txtRecord;
-    registration->txtLen = rdlen;
-    network_state_changed = true;
-    return kDNSServiceErr_NoError;
-}
-
-// Implementation of the API that applications will call to register services.   This is independent of the
-// hosting platform API.
-DNSServiceErrorType
-DNSServiceRegister(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
-                   const char *NULLABLE name, const char *NULLABLE regtype, const char *NULLABLE domain,
-                   const char *NULLABLE host, uint16_t port,
-                   uint16_t txtLen, const void *txtRecord,
-                   DNSServiceRegisterReply callBack, void *context)
-{
-    reg_state_t **rp, *reg = calloc(1, sizeof *reg);
-    if (reg == NULL) {
-        return kDNSServiceErr_NoMemory;
-    }
-
-    // Add it to the list (so it will appear valid to DNSServiceRefDeallocate()).
-    rp = &current_client->registrations;
-    while (*rp) {
-        rp = &((*rp)->next);
-    }
-    *rp = reg;
-
-    // If we don't already have a hostname, use the one from the registration.
-    if (current_client->hostname == NULL) {
-        srp_set_hostname(host, NULL);
-    }
-
-    reg->serial = current_client->registration_serial++;
-    reg->flags = flags;
-    reg->interfaceIndex = interfaceIndex;
-    reg->called_back = true;
-#define stashName(thing)                        \
-    if (thing != NULL) {                        \
-        reg->thing = strdup(thing);             \
-        if (reg->thing == NULL) {               \
-            DNSServiceRefDeallocate(reg);       \
-            return kDNSServiceErr_NoMemory;     \
-        }                                       \
-    } else {                                    \
-        reg->thing = NULL;                      \
-    }
-    stashName(name);
-    stashName(regtype);
-    stashName(domain);
-    stashName(host);
-    reg->port = port;
-    reg->txtLen = txtLen;
-    if (txtLen != 0) {
-        reg->txtRecord = malloc(txtLen);
-        if (reg->txtRecord == NULL) {
-            DNSServiceRefDeallocate(reg);
-            return kDNSServiceErr_NoMemory;
-        }
-        memcpy(reg->txtRecord, txtRecord, txtLen);
-    } else {
-        reg->txtRecord = NULL;
-    }
-    reg->callback = callBack;
-    reg->context = context;
-    *sdRef = reg;
-    network_state_changed = true;
-    return kDNSServiceErr_NoError;
-}
-
-void
-DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-    reg_state_t **rp, *reg = NULL;
-    bool found = false;
-    client_state_t *client;
-
-    if (sdRef == NULL) {
-        return;
-    }
-
-    for (client = clients; client; client = client->next) {
-        // Remove it from the list.
-        rp = &client->registrations;
-        reg = *rp;
-        while (*rp) {
-            if (reg == sdRef) {
-                *rp = reg->next;
-                found = true;
-                break;
-            }
-            rp = &((*rp)->next);
-            reg = *rp;
-        }
-
-        if (found) {
-            break;
-        }
-    }
-
-    // This avoids a bogus free.
-    if (!found || reg == NULL) {
-        return;
-    }
-    if (reg->name != NULL) {
-        free(reg->name);
-    }
-    if (reg->regtype != NULL) {
-        free(reg->regtype);
-    }
-    if (reg->domain != NULL) {
-        free(reg->domain);
-    }
-    if (reg->host != NULL) {
-        free(reg->host);
-    }
-    if (reg->txtRecord != NULL) {
-        free(reg->txtRecord);
-    }
-    free(reg);
-}
-
-static void
-update_finalize(update_context_t *update)
-{
-    client_state_t *client = update->client;
-    INFO("%p %p %p", update, update->udp_context, update->message);
-    if (update->udp_context != NULL) {
-        srp_deactivate_udp_context(client->os_context, update->udp_context);
-    }
-    if (update->message != NULL) {
-        free(update->message);
-    }
-    free(update);
-}
-
-static void
-do_callbacks(client_state_t *client, reg_state_t *registration, uint32_t serial, int err, bool succeeded)
-{
-    reg_state_t *rp;
-    bool work;
-
-    // The callback can modify the list, so we use a marker to remember where we are in the list rather
-    // than remembering a pointer which could be invalidated.  If a callback adds a registration, that
-    // registration doesn't get called because called_back is set to true when a registration is added.
-    for (rp = client->registrations; rp; rp = rp->next) {
-        if (rp->serial <= serial) {
-            rp->called_back = false;
-        }
-    }
-    do {
-        work = false;
-        for (rp = client->registrations; rp; rp = rp->next) {
-            if (registration != NULL && registration != rp) {
-                continue;
-            }
-            if (rp->serial > serial || rp->callback == NULL || rp->called_back) {
-                continue;
-            }
-            work = true;
-            rp->called_back = true;
-            if (succeeded) {
-                rp->succeeded = true;
-            }
-            if (rp->callback != NULL) {
-                rp->callback(rp, kDNSServiceFlagsAdd, err, rp->name, rp->regtype, rp->domain, rp->context);
-                break;
-            }
-        }
-    } while (work);
-}
-
-static void
-udp_retransmit(void *v_update_context)
-{
-    update_context_t *context = v_update_context;
-    client_state_t *client;
-    service_addr_t *next_server = NULL;
-    int err;
-
-    client = context->client;
-
-    if (!srp_is_network_active()) {
-        INFO("network is down, discontinuing renewals.");
-        if (client->active_update != NULL) {
-            update_finalize(client->active_update);
-            client->active_update = NULL;
-        }
-        return;
-    }
-    // It shouldn't be possible for this to happen.
-    if (client->active_update == NULL) {
-        INFO("no active update for " PRI_S_SRP " (%p).",
-             client->hostname ? client->hostname : "<null>", client);
-        return;
-    }
-    INFO("next_attempt %" PRIu32 " next_retransmission %" PRIu32 " for " PRI_S_SRP " (%p)",
-         context->next_attempt_time, context->next_retransmission_time,
-         client->hostname ? client->hostname : "<null>", client);
-
-    // If next retransmission time is zero, this means that we gave up our last attempt to register, and have
-    // now waited long enough to try again.  We will then use an exponential backoff for 90 seconds before giving
-    // up again; if we give up again, we will wait longer to retry, up to an hour.
-    if (context->next_retransmission_time == 0) {
-        // If there are no servers, we don't need to schedule a re-attempt: when a server is seen, we will do
-        // an update immediately.
-        if (servers == NULL) {
-            return;
-        }
-        next_server = servers;
-
-        // If this attempt fails, don't try again for a while longer, but limit the retry interval to an hour.
-        context->next_attempt_time *= 2;
-        if (context->next_attempt_time > client->srp_max_attempt_interval) {
-            context->next_attempt_time = client->srp_max_attempt_interval;
-        }
-        context->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-    }
-    // If this would be our fourth retry on a particular server, try the next server.
-    else if (context->next_retransmission_time > client->srp_max_retry_interval) {
-        // If we are removing, there is no point in trying the next server--just give up and report a timeout.
-        if (context->removing) {
-            do_callbacks(client, NULL, context->serial, kDNSServiceErr_Timeout, false);
-            // Once the goodbye retransmission has timed out, we're done.
-            return;
-        }
-        for (next_server = servers; next_server; next_server = next_server->next) {
-            if (next_server == context->server) {
-                // We're going to use the next server after the one we just tried.  If we run out of servers,
-                // we'll give up for a while.
-                next_server = next_server->next;
-                break;
-            }
-        }
-
-        // If we run off the end of the list, give up for a bit.
-        if (next_server == NULL) {
-            context->next_retransmission_time = 0;
-        } else {
-            context->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-        }
-    }
-    // Otherwise, we are still trying to win with a particular server, so back off exponentially.
-    else {
-        context->next_retransmission_time *= 2;
-    }
-
-    // If we are giving up on the current server, get rid of any udp state.
-    if (context->next_retransmission_time == 0 || next_server != NULL) {
-        if (next_server != NULL) {
-            context->server = next_server;
-        }
-        srp_disconnect_udp(context->udp_context);
-        context->connected = false;
-        if (context->message != NULL) {
-            free(context->message);
-        }
-        context->message = NULL;
-        context->message_length = 0;
-        context->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-        context->next_attempt_time = INITIAL_NEXT_ATTEMPT_TIME;
-    }
-
-    // If we are not giving up, send the next packet.
-    if (context->server != NULL && context->next_retransmission_time != 0) {
-        if (!context->connected) {
-            // Create a UDP context for this transaction.
-            err = srp_connect_udp(context->udp_context, context->server->port, context->server->rr.type,
-                                  (uint8_t *)&context->server->rr.data,
-                                  context->server->rr.type == dns_rrtype_a ? 4 : 16);
-            // In principle if it fails here, it might succeed later, so we just don't send a packet and let
-            // the timeout take care of it.
-            if (err != kDNSServiceErr_NoError) {
-                ERROR("udp_retransmit: error %d creating udp context.", err);
-            } else {
-                if (context->server->rr.type == dns_rrtype_a) {
-                    IPv4_ADDR_GEN_SRP(&context->server->rr.data.a, addr_buf);
-                    INFO("updating server at address " PRI_IPv4_ADDR_SRP,
-                         IPv4_ADDR_PARAM_SRP(&context->server->rr.data.a, addr_buf));
-                } else if (context->server->rr.type == dns_rrtype_aaaa) {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(&context->server->rr.data.aaaa, addr_buf);
-                    INFO("updating server at address " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(&context->server->rr.data.aaaa, addr_buf));
-                }
-                context->connected = true;
-            }
-        }
-
-        if (context->message == NULL) {
-            context->message = generate_srp_update(client, client->lease_time, client->key_lease_time, &context->message_length,
-                                                   context->server, context->serial, context->removing);
-            if (context->message == NULL) {
-                ERROR("No memory for message.");
-                return;
-            }
-        }
-
-        if (context->connected) {
-            // Send the datagram to the server
-            err = srp_send_datagram(client->os_context, context->udp_context, context->message, context->message_length);
-            if (err != kDNSServiceErr_NoError) {
-                ERROR("udp_retransmit: error %d sending a datagram.", err);
-            }
-        }
-    }
-
-    // If we've given up for now, either schedule a next attempt or notify the caller; otherwise, schedule the next retransmission.
-    if (context->next_retransmission_time == 0) {
-        bool timeout_requested = false;
-        reg_state_t *registration;
-        for (registration = client->registrations; registration; registration = registration->next) {
-            if (registration->callback != NULL && registration->serial <= context->serial &&
-                (registration->flags & kDNSServiceFlagsTimeout))
-            {
-                timeout_requested = true;
-            }
-        }
-        // If any of the callers requested a timeout, we treat it as if they all did, and call all the callbacks with the "timed out"
-        // error.
-        if (timeout_requested) {
-            do_callbacks(client, NULL, context->serial, kDNSServiceErr_Timeout, false);
-            err = kDNSServiceErr_NoError;
-        } else {
-            err = srp_set_wakeup(client->os_context, context->udp_context, context->next_attempt_time, udp_retransmit);
-        }
-    } else {
-        err = srp_set_wakeup(client->os_context, context->udp_context,
-                             context->next_retransmission_time - 512 + srp_random16() % 1024, udp_retransmit);
-    }
-    if (err != kDNSServiceErr_NoError) {
-        INFO("error %d setting wakeup", err);
-        // what to do?
-    }
-}
-
-static void
-renew_callback(void *v_update_context)
-{
-    update_context_t *context = v_update_context;
-    client_state_t *client = context->client;
-    INFO("renew callback");
-    do_srp_update(client, true, NULL);
-}
-
-// This function will, if hostname_rename_number is nonzero, create a hostname using the chosen hostname plus
-// space plus the number as ascii text.   The caller is responsible for freeing the return value if it's not NULL.
-static char *
-conflict_print(client_state_t *client, dns_towire_state_t *towire, char **return_hostname, char *chosen_hostname)
-{
-    char *conflict_hostname;
-    size_t hostname_len;
-
-    if (client->hostname_rename_number == 0) {
-        *return_hostname = chosen_hostname;
-        return NULL;
-    }
-
-    hostname_len = strlen(chosen_hostname);
-    // 7 is max length of decimal short (5) plus space plus NUL
-    if (hostname_len + 7 > DNS_MAX_LABEL_SIZE) {
-        hostname_len = DNS_MAX_LABEL_SIZE - 7;
-    }
-    conflict_hostname = malloc(hostname_len + 7);
-    if (conflict_hostname == NULL) {
-        if (towire != NULL) {
-            towire->line = __LINE__;
-            towire->outer_line = -1;
-            towire->error = true;
-        }
-        *return_hostname = chosen_hostname;
-        return NULL;
-    }
-
-    memcpy(conflict_hostname, chosen_hostname, hostname_len);
-    snprintf(conflict_hostname + hostname_len, 7, " %d", client->hostname_rename_number);
-    *return_hostname = conflict_hostname;
-    return conflict_hostname;
-}
-
-static void
-udp_response(void *v_update_context, void *v_message, size_t message_length)
-{
-    update_context_t *context = v_update_context;
-    client_state_t *client = context->client;
-    dns_wire_t *message = v_message;
-    int err;
-    int rcode = dns_rcode_get(message);
-    (void)message_length;
-    uint32_t new_lease_time = 0;
-    bool lease_time_sent = false;
-    reg_state_t *registration;
-    const uint8_t *p = message->data;
-    const uint8_t *end = (const uint8_t *)v_message + message_length;
-    bool resolve_name_conflict = false;
-    char *conflict_hostname = NULL, *chosen_hostname;
-
-    INFO("Got a response for %p, rcode = %d", client, dns_rcode_get(message));
-
-    // Cancel the existing retransmit wakeup, since we definitely don't want to retransmit to the current
-    // server.
-    err = srp_cancel_wakeup(client->os_context, context->udp_context);
-    if (err != kDNSServiceErr_NoError) {
-        INFO("%d", err);
-    }
-
-    if (rcode == dns_rcode_noerror || rcode == dns_rcode_yxdomain) {
-        // We want a different UDP source port for each transaction, so cancel the current UDP state.
-        srp_disconnect_udp(context->udp_context);
-        if (context->message != NULL) {
-            free(context->message);
-        }
-        context->message = NULL;
-        context->message_length = 0;
-        context->connected = false;
-        context->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-        context->next_attempt_time = INITIAL_NEXT_ATTEMPT_TIME;
-    }
-
-    // When we are doing a remove, we don't actually care what the result is--if we get back an answer, we call
-    // the callback.
-    if (context->removing) {
-        do_callbacks(client, NULL, context->serial, kDNSServiceErr_NoSuchRecord, false);
-        return;
-    }
-
-    // Deal with the response.
-    switch (rcode) {
-    case dns_rcode_noerror:
-        // Remember the server we connected with.  active_update and active_update->server should always be
-        // non-NULL here.
-        if (client->active_update != NULL) {
-            if (client->active_update->server != NULL) {
-                // If the new server is not the one that's mentioned in stable_server, then update the one
-                // in stable_server.
-                if (client->active_update->server->rr.type != client->stable_server.rr.type ||
-                    (client->stable_server.rr.type == dns_rrtype_a
-                     ? memcmp(&client->stable_server.rr.data, &client->active_update->server->rr.data, 4)
-                     : (client->stable_server.rr.type == dns_rrtype_aaaa
-                        ? memcmp(&client->stable_server.rr.data, &client->active_update->server->rr.data, 16)
-                        : true)) ||
-                    memcmp(client->stable_server.port, client->active_update->server->port, 2))
-                {
-                    memcpy(&client->stable_server, client->active_update->server, sizeof(client->stable_server));
-                    client->srp_server_synced = false;
-                }
-                sync_to_stable_storage(client->active_update);
-            }
-            client->active_update->interface_serial = interface_serial;
-        }
-
-        for (reg_state_t *rp = client->registrations; rp != NULL; rp = rp->next) {
-            if (rp->removing) {
-                INFO("removal for " PRI_S_SRP "." PRI_S_SRP " completed.", rp->name, rp->regtype);
-                do_callbacks(client, rp, context->serial, kDNSServiceErr_NoSuchRecord, false);
-                rp->skip = true; // The caller should do DNSServiceRefDeallocate, but if they don't, we don't want
-                                 // to either continually send removes, nor to send the update again.
-            }
-        }
-
-        // Get the renewal time
-        // At present, there's no code to actually parse a real DNS packet in the client, so
-        // we rely on the server returning just an EDNS0 option; if this assumption fails, we
-        // are out of luck.
-        if (message->qdcount == 0 && message->ancount == 0 && message->nscount == 0 && ntohs(message->arcount) == 1 &&
-            // We expect the edns0 option to be:
-            // root label - 1 byte
-            // type = 2 bytes
-            // class = 2 bytes
-            // ttl = 4 bytes
-            // rdlength = 2 bytes
-            // total of 11 bytes
-            // data
-            end - p > 11 && // Enough room for an EDNS0 option
-            *p == 0 &&       // root label
-            p[1] == (dns_rrtype_opt >> 8) && p[2] == (dns_rrtype_opt & 255)) // opt rrtype
-        {
-            // skip class and ttl, we don't care
-            const uint8_t *opt_start = &p[11]; // Start of opt data
-            uint16_t opt_len = (((uint16_t)p[9]) << 8) + p[10]; // length of opt data
-            const uint8_t *opt_cur = opt_start;
-            uint16_t opt_remaining = opt_len;
-            // Scan for options until there's no room.
-            while (opt_cur + 4 <= end) {
-                int option_code = (((uint16_t)opt_cur[0]) << 8) + opt_cur[1];
-                int option_len =  (((uint16_t)opt_cur[2]) << 8) + opt_cur[3];
-                const uint8_t *option_data = opt_cur + 4;
-                if (option_len + option_data <= end) {
-                    if (option_code == dns_opt_update_lease) {
-                        if (option_len == 8) {
-                            new_lease_time = (((uint32_t)option_data[0] << 24) | ((uint32_t)option_data[1] << 16) |
-                                              ((uint32_t)option_data[2] << 8) | ((uint32_t)option_data[3]));
-                            INFO("Lease time set to %" PRIu32, new_lease_time);
-                            lease_time_sent = true;
-                        }
-                    } else if (option_code == dns_opt_srp_serial) {
-                        if (option_len == 4) {
-                            if (client->client_serial_set) {
-                                ERROR("Response erroneously contains serial number when we sent one.");
-                            } else {
-                                client->client_serial =
-                                    (((uint32_t)option_data[0] << 24) | ((uint32_t)option_data[1] << 16) |
-                                     ((uint32_t)option_data[2] << 8) | ((uint32_t)option_data[3]));
-                                client->client_serial_set = true;
-                            }
-                        }
-                    }
-                }
-                opt_cur = option_data + option_len;
-                opt_remaining = opt_remaining - (option_len + 4);
-            }
-        }
-
-        // If we didn't get back a serial number, generate a random one. This should never happen.
-        // Of course, since earlier versions of SRP didn't have a serial number, it /will/ happen
-        // when communicating with older SRP servers, which is why we do this.
-        if (!client->client_serial_set) {
-            client->client_serial = srp_random32();
-            client->client_serial_set = true;
-            ERROR("Server didn't offer a serial number when we didn't send one: set to %" PRIx32 "!",
-                  client->client_serial );
-        }
-
-        if (!lease_time_sent) {
-            new_lease_time = context->lease_time;
-            INFO("Lease time defaults to %" PRIu32, new_lease_time);
-            DEBUG("len %zd qd %d an %d ns %d ar %d data %02x %02x %02x %02x %02x %02x %02x %02x %02x"
-                  " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-                  end - p, ntohs(message->qdcount), ntohs(message->ancount),
-                  ntohs(message->nscount), ntohs(message->arcount),
-                  p[0], p[1], p[2], p[3], p[3], p[5], p[6], p[7], p[8], p[9], p[10], p[11],
-                  p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19], p[20], p[21], p[22]);
-        }
-
-        // Set up to renew.  Time is in milliseconds, and we want to renew at 80% of the lease time.
-        srp_set_wakeup(client->os_context, context->udp_context, (new_lease_time * 1000) * 8 / 10, renew_callback);
-
-        do_callbacks(client, NULL, context->serial, kDNSServiceErr_NoError, true);
-        break;
-    case dns_rcode_yxdomain:
-        // Get the actual hostname that we sent.
-        if (client->hostname_conflict_callback != NULL && client->hostname != NULL) {
-            conflict_hostname = conflict_print(client, NULL, &chosen_hostname, client->hostname);
-            client->hostname_conflict_callback(chosen_hostname);
-            if (conflict_hostname != NULL) {
-                free(conflict_hostname);
-            }
-        } else {
-            resolve_name_conflict = true;
-        }
-
-        bool resolve_with_callback = false;
-        for (registration = client->registrations; registration; registration = registration->next) {
-            if (registration->callback != NULL && registration->serial <= context->serial &&
-                (registration->flags & kDNSServiceFlagsNoAutoRename))
-            {
-                resolve_with_callback = true;
-            }
-        }
-        if (resolve_with_callback) {
-            do_callbacks(client, NULL, context->serial, kDNSServiceErr_NameConflict, false);
-            resolve_name_conflict = false;
-        } else {
-            resolve_name_conflict = true;
-        }
-
-        if (resolve_name_conflict) {
-            // If we get a name conflict, try using a low number to rename, but only twice; it's time consuming to do
-            // this, so if we get two conflicts, we switch to using a random number.
-            if (client->hostname_rename_number < 2) {
-                client->hostname_rename_number++;
-            } else {
-                client->hostname_rename_number = srp_random16();
-            }
-            // When we get a name conflict response, we need to re-do the update immediately
-            // (with a 0-500ms delay of course).
-            do_srp_update(client, true, NULL);
-        }
-        break;
-
-    default:
-        // If we get here, it means that the server failed to process the transmission, and there is no
-        // action we can take to change the situation other than trying another server. We set the
-        // retransmission time for the current server long enough to force a switch to the next server,
-        // if any.
-        context->next_retransmission_time = client->srp_max_retry_interval + 1;
-        // Immediately invoke the retransmit timer--there is no reason to wait.
-        udp_retransmit(context);
-        break;
-    }
-}
-
-// Generate a new SRP update message
-static dns_wire_t *
-generate_srp_update(client_state_t *client, uint32_t update_lease_time, uint32_t update_key_lease_time,
-                    size_t *NONNULL p_length, service_addr_t *server, uint32_t serial, bool removing)
-{
-    dns_wire_t *message;
-    const char *zone_name = "default.service.arpa";
-    const char *service_type = "_ipps._tcp";
-    const char *txt_record = "0";
-    uint16_t key_tag;
-    dns_towire_state_t towire;
-    dns_name_pointer_t p_host_name;
-    dns_name_pointer_t p_zone_name;
-    dns_name_pointer_t p_service_name;
-    dns_name_pointer_t p_service_instance_name;
-    int line, pass;
-    service_addr_t *addr;
-    reg_state_t *reg;
-    char *conflict_hostname = NULL, *chosen_hostname;
-
-#define INCREMENT(x) (x) = htons(ntohs(x) + 1)
-    memset(&towire, 0, sizeof towire);
-
-    // Get the key if we don't already have it.
-    if (client->key == NULL) {
-        client->key = srp_get_key("com.apple.srp-client.host-key", client->os_context);
-        if (client->key == NULL) {
-            INFO("No key gotten.");
-            return NULL;
-        }
-    }
-
-#define CH if (towire.error) { line = __LINE__; goto fail; }
-
-    if (client->hostname == NULL) {
-        ERROR("generate_srp_update called with NULL hostname.");
-        return NULL;
-    }
-
-    // Allocate a message buffer.
-    message = calloc(1, sizeof *message);
-    if (message == NULL) {
-        return NULL;
-    }
-    towire.p = &message->data[0];               // We start storing RR data here.
-    towire.lim = &message->data[DNS_DATA_SIZE]; // This is the limit to how much we can store.
-    towire.message = message;
-
-    // Generate a random UUID.
-    message->id = srp_random16();
-    message->bitfield = 0;
-    dns_qr_set(message, dns_qr_query);
-    dns_opcode_set(message, dns_opcode_update);
-
-    message->qdcount = 0;
-    // Copy in Zone name (and save pointer)
-    // ZTYPE = SOA
-    // ZCLASS = IN
-    dns_full_name_to_wire(&p_zone_name, &towire, zone_name); CH;
-    dns_u16_to_wire(&towire, dns_rrtype_soa); CH;
-    dns_u16_to_wire(&towire, dns_qclass_in); CH;
-    INCREMENT(message->qdcount);
-
-    message->ancount = 0;
-    // PRCOUNT = 0
-
-    message->nscount = 0;
-    // UPCOUNT = ...
-
-    // Host Description:
-    //  * Delete all RRsets from <hostname>; remember the pointer to hostname
-    //      NAME = hostname label followed by pointer to SOA name.
-    //      TYPE = ANY
-    //      CLASS = ANY
-    //      TTL = 0
-    //      RDLENGTH = 0
-
-    conflict_hostname = conflict_print(client, &towire, &chosen_hostname, client->hostname); CH;
-    dns_name_to_wire(&p_host_name, &towire, chosen_hostname); CH;
-    dns_pointer_to_wire(&p_host_name, &towire, &p_zone_name); CH;
-    dns_u16_to_wire(&towire, dns_rrtype_any); CH;
-    dns_u16_to_wire(&towire, dns_qclass_any); CH;
-    dns_ttl_to_wire(&towire, 0); CH;
-    dns_u16_to_wire(&towire, 0); CH;
-    INCREMENT(message->nscount);
-
-    //  * Add addresses: A and/or AAAA RRsets, each of which contains one
-    //    or more A or AAAA RRs.
-    //      NAME = pointer to hostname from Delete (above)
-    //      TYPE = A or AAAA
-    //      CLASS = IN
-    //      TTL = 3600 ?
-    //      RDLENGTH = number of RRs * RR length (4 or 16)
-    //      RDATA = <the data>
-    if (!removing) {
-        for (pass = 0; pass < 2; pass++) {
-            bool have_good_address = false;
-
-            for (addr = interfaces; addr; addr = addr->next) {
-                // If we have an IPv6 address that's on the same prefix as the server's address, send only that
-                // IPv6 address.
-                if (addr->rr.type != dns_rrtype_aaaa ||
-                    (addr->rr.type == server->rr.type && !memcmp(&addr->rr.data, &server->rr.data, 8)))
-                {
-                    have_good_address = true;
-                }
-                if (have_good_address || pass == 1) {
-                    dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
-                    dns_u16_to_wire(&towire, addr->rr.type); CH;
-                    dns_u16_to_wire(&towire, dns_qclass_in); CH;
-                    dns_ttl_to_wire(&towire, 3600); CH;
-                    dns_rdlength_begin(&towire); CH;
-                    dns_rdata_raw_data_to_wire(&towire, &addr->rr.data,
-                                               addr->rr.type == dns_rrtype_a ? 4 : 16); CH;
-                    dns_rdlength_end(&towire); CH;
-                    INCREMENT(message->nscount);
-                }
-                if (have_good_address) {
-                    break;
-                }
-            }
-            if (have_good_address) {
-                break;
-            }
-        }
-   }
-
-    //  * Exactly one KEY RR:
-    //      NAME = pointer to hostname from Delete (above)
-    //      TYPE = KEY
-    //      CLASS = IN
-    //      TTL = 3600
-    //      RDLENGTH = length of key + 4 (32 bits)
-    //      RDATA = <flags(16) = 0000 0010 0000 0001, protocol(8) = 3, algorithm(8) = 8?, public key(variable)>
-    dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
-    dns_u16_to_wire(&towire, dns_rrtype_key); CH;
-    dns_u16_to_wire(&towire, dns_qclass_in); CH;
-    dns_ttl_to_wire(&towire, 3600); CH;
-    dns_rdlength_begin(&towire); CH;
-    key_tag = dns_rdata_key_to_wire(&towire, 0, 2, 1, client->key); CH;
-    dns_rdlength_end(&towire); CH;
-    INCREMENT(message->nscount);
-
-    // If we are removing the host, we don't need to send instances.
-    if (!removing) {
-
-        // Emit any registrations.
-        for (reg = client->registrations; reg; reg = reg->next) {
-            // Only remove the registrations that are actually registered. Normally this will be all of them, but it's
-            // possible for a registration to be added but not to have been updated yet, and then for us to get a remove
-            // call, in which case we don't need to remove it.
-            if (((removing || reg->removing) && reg->serial > serial) || reg->skip) {
-                continue;
-            }
-
-            // Service:
-            //   * Update PTR RR
-            //     NAME = service name (_a._b.service.arpa)
-            //     TYPE = PTR
-            //     CLASS = IN
-            //     TTL = 3600
-            //     RDLENGTH = 2
-            //     RDATA = service instance name
-
-            // Service registrations can have subtypes, in which case we need to send multiple PTR records, one for
-            // the main type and one for each subtype. Subtypes are represented in the regtype by following the
-            // primary service type with subtypes, separated by commas. So we have to parse through that to get
-            // the actual domain names to register.
-            const char *commap = reg->regtype == NULL ? service_type : reg->regtype;
-            dns_name_pointer_t p_sub_service_name;
-            bool primary = true;
-            do {
-                char regtype[DNS_MAX_LABEL_SIZE_ESCAPED + 6]; // plus NUL, ._sub
-                int i;
-                // Copy the next service type into regtype, ending when we hit the end of reg->regtype
-                // or when we hit a comma.
-                for (i = 0; *commap != '\0' && *commap != ',' && i < DNS_MAX_LABEL_SIZE_ESCAPED; i++) {
-                    regtype[i] = *commap;
-                    commap++;
-                }
-
-                // If we hit a comma, skip over the comma for the beginning of the next subtype.
-                if (*commap == ',') {
-                    commap++;
-                }
-
-                // If we aren't at a NULL or a comma, it means that the label was too long, so the output
-                // is invalid.
-                else if (*commap != '\0') {
-                    towire.error = ENOBUFS; CH;
-                }
-
-                // First time through, it's the base type, so emit the service name and a pointer to the
-                // zone name. Other times through, it's a subtype, so the pointer is now to the base type,
-                // and since the API makes ._sub implicit, we have to add that.
-                if (primary) {
-                    regtype[i] = 0;
-                    dns_name_to_wire(&p_service_name, &towire, regtype); CH;
-                    dns_pointer_to_wire(&p_service_name, &towire, &p_zone_name); CH;
-                } else {
-                    // Copy in the string and the NUL. We know there's space (see above).
-                    memcpy(&regtype[i], "._sub", 6);
-                    dns_name_to_wire(&p_sub_service_name, &towire, regtype); CH;
-                    dns_pointer_to_wire(&p_sub_service_name, &towire, &p_service_name); CH;
-                }
-                dns_u16_to_wire(&towire, dns_rrtype_ptr); CH;
-                if (reg->removing) {
-                    dns_u16_to_wire(&towire, dns_qclass_none); CH;
-                    dns_ttl_to_wire(&towire, 0); CH;
-                } else {
-                    dns_u16_to_wire(&towire, dns_qclass_in); CH;
-                    dns_ttl_to_wire(&towire, 3600); CH;
-                }
-                dns_rdlength_begin(&towire); CH;
-                if (reg->name != NULL) {
-                    char *service_instance_name, *to_free = conflict_print(client, &towire, &service_instance_name, reg->name);
-                    dns_name_to_wire(&p_service_instance_name, &towire, service_instance_name); CH;
-                    if (to_free != NULL) {
-                        free(to_free);
-                    }
-                } else {
-                    dns_name_to_wire(&p_service_instance_name, &towire, chosen_hostname); CH;
-                }
-                dns_pointer_to_wire(&p_service_instance_name, &towire, &p_service_name); CH;
-                dns_rdlength_end(&towire); CH;
-                INCREMENT(message->nscount);
-                primary = false;
-                // We don't need to remove subtypes: removing the instance removes all its subtypes.
-                if (reg->removing) {
-                    break;
-                }
-            } while (*commap != '\0');
-
-            // Service Instance:
-            //   * Delete all RRsets from service instance name
-            //      NAME = service instance name (save pointer to service name, which is the second label)
-            //      TYPE = ANY
-            //      CLASS = ANY
-            //      TTL = 0
-            //      RDLENGTH = 0
-            dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
-            dns_u16_to_wire(&towire, dns_rrtype_any); CH;
-            dns_u16_to_wire(&towire, dns_qclass_any); CH;
-            dns_ttl_to_wire(&towire, 0); CH;
-            dns_u16_to_wire(&towire, 0); CH;
-            INCREMENT(message->nscount);
-
-            if (!reg->removing) {
-                //   * Add one SRV RRset pointing to Host Description
-                //      NAME = pointer to service instance name from above
-                //      TYPE = SRV
-                //      CLASS = IN
-                //      TTL = 3600
-                //      RDLENGTH = 8
-                //      RDATA = <priority(16) = 0, weight(16) = 0, port(16) = service port, target = pointer to hostname>
-                dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
-                dns_u16_to_wire(&towire, dns_rrtype_srv); CH;
-                dns_u16_to_wire(&towire, dns_qclass_in); CH;
-                dns_ttl_to_wire(&towire, 3600); CH;
-                dns_rdlength_begin(&towire); CH;
-                dns_u16_to_wire(&towire, 0); CH; // priority
-                dns_u16_to_wire(&towire, 0); CH; // weight
-                dns_u16_to_wire(&towire, reg->port); CH; // port
-                dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
-                dns_rdlength_end(&towire); CH;
-                INCREMENT(message->nscount);
-
-                //   * Add one or more TXT records
-                //      NAME = pointer to service instance name from above
-                //      TYPE = TXT
-                //      CLASS = IN
-                //      TTL = 3600
-                //      RDLENGTH = <length of text>
-                //      RDATA = <text>
-                dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
-                dns_u16_to_wire(&towire, dns_rrtype_txt); CH;
-                dns_u16_to_wire(&towire, dns_qclass_in); CH;
-                dns_ttl_to_wire(&towire, 3600); CH;
-                dns_rdlength_begin(&towire); CH;
-                if (reg->txtRecord != NULL) {
-                    dns_rdata_raw_data_to_wire(&towire, reg->txtRecord, reg->txtLen);
-                } else {
-                    dns_rdata_txt_to_wire(&towire, txt_record); CH;
-                }
-                dns_rdlength_end(&towire); CH;
-                INCREMENT(message->nscount);
-            }
-        }
-    }
-
-    // What about services with more than one name?   Are these multiple service descriptions?
-
-    // ARCOUNT = 2
-    //   EDNS(0) options
-    //     ...
-    //   SIG(0)
-
-    message->arcount = 0;
-    dns_edns0_header_to_wire(&towire, DNS_MAX_UDP_PAYLOAD, 0, 0, 1); CH; // XRCODE = 0; VERSION = 0; DO=1
-    dns_rdlength_begin(&towire); CH;
-    dns_u16_to_wire(&towire, dns_opt_update_lease); CH;  // OPTION-CODE
-    dns_edns0_option_begin(&towire); CH;                 // OPTION-LENGTH
-    if (removing) {
-        // If we are removing the record, lease time should be zero. Key_lease_time can be nonzero, but we
-        // aren't currently offering a way to do that in the server. Nevertheless, we send a key lease time.
-        dns_u32_to_wire(&towire, 0); CH;
-        dns_u32_to_wire(&towire, update_key_lease_time); CH;
-    } else {
-        dns_u32_to_wire(&towire, update_lease_time); CH;     // LEASE (e.g. 1 hour)
-        dns_u32_to_wire(&towire, update_key_lease_time); CH; // KEY-LEASE (7 days)
-    }
-    dns_edns0_option_end(&towire); CH;                   // Now we know OPTION-LENGTH
-    // Now send a serial number if we have one. We send the current serial number plus one.
-    if (client->client_serial_set) {
-        // Increment the serial number. We increment the serial number each time we generate a new update, which can
-        // mean that if we have to switch to a new server, the serial number increases by more than one before we get
-        // a success response. This should be okay.
-        client->client_serial = client->client_serial + 1;
-        dns_u16_to_wire(&towire, dns_opt_srp_serial); CH;
-        dns_edns0_option_begin(&towire); CH;
-        dns_u32_to_wire(&towire, client->client_serial);
-        dns_edns0_option_end(&towire); CH;                   // Now we know OPTION-LENGTH
-    }
-    dns_rdlength_end(&towire); CH;
-    INCREMENT(message->arcount);
-
-    // The signature must be computed before counting the signature RR in the header counts.
-    dns_sig0_signature_to_wire(&towire, client->key, key_tag, &p_host_name, chosen_hostname, zone_name); CH;
-    INCREMENT(message->arcount);
-    *p_length = towire.p - (uint8_t *)message;
-
-    if (conflict_hostname != NULL) {
-        free(conflict_hostname);
-    }
-    return message;
-
-fail:
-    if (conflict_hostname != NULL) {
-        free(conflict_hostname);
-    }
-
-    if (towire.error) {
-        ERROR("Ran out of message space at srp-client.c:%d (%d, %d)",
-              line, towire.line, towire.outer_line);
-    }
-    if (client->active_update != NULL) {
-        update_finalize(client->active_update);
-        client->active_update = NULL;
-    }
-    if (message != NULL) {
-        free(message);
-    }
-    return NULL;
-}
-
-// Send SRP updates for host records that have changed.
-static int
-do_srp_update(client_state_t *client, bool definite, bool *did_something)
-{
-    int err;
-    service_addr_t *server;
-
-    // Cancel any ongoing active update.
-    if (!definite && client->active_update != NULL) {
-        bool server_changed = true;
-        for (server = servers; server != NULL; server = server->next) {
-            if (server == client->active_update->server) {
-                server_changed = false;
-            }
-        }
-        if (client->active_update->interface_serial == interface_serial && !server_changed) {
-            INFO("addresses to register are the same; server is the same.");
-            return kDNSServiceErr_NoError;
-        }
-    }
-
-    // At this point we're definitely doing something.
-    if (did_something) {
-        *did_something = true;
-    }
-
-    // Get rid of the previous update, if any.
-    if (client->active_update != NULL) {
-        update_finalize(client->active_update);
-        client->active_update = NULL;
-    }
-
-    // Make an update context.
-    update_context_t *active_update = calloc(1, sizeof(*active_update));
-    if (active_update == NULL) {
-        err = kDNSServiceErr_NoMemory;
-    } else {
-        // If possible, use the server we used last time.
-        active_update->client = client;
-        sync_from_stable_storage(active_update);
-        if (active_update->server == NULL) {
-            active_update->server = servers;
-        }
-        active_update->serial = client->registration_serial;
-        active_update->message = NULL;
-        active_update->message_length = 0;
-        active_update->lease_time = client->lease_time;
-        active_update->key_lease_time = client->key_lease_time;
-        err = srp_make_udp_context(client->os_context, &active_update->udp_context, udp_response, active_update);
-
-        // XXX use some random jitter on these times.
-        active_update->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-        active_update->next_attempt_time = INITIAL_NEXT_ATTEMPT_TIME;
-        err = srp_set_wakeup(client->os_context, active_update->udp_context, srp_random16() % 1023, udp_retransmit);
-    }
-    client->active_update = active_update;
-    return err;
-}
-
-// Deregister all existing registrations.
-int
-srp_deregister(void *os_context)
-{
-    reg_state_t *rp;
-    bool something_to_deregister = false;
-    client_state_t *client;
-
-    for (client = clients; client; client = client->next) {
-        if (client->os_context == os_context) {
-            break;
-        }
-    }
-    if (client == NULL) {
-        return kDNSServiceErr_Invalid;
-    }
-
-    if (client->active_update == NULL) {
-        INFO("no active update.");
-        return kDNSServiceErr_NoSuchRecord;
-    }
-
-    // See if there are any registrations that have succeeded.
-    for (rp = client->registrations; rp; rp = rp->next) {
-        if (rp->serial <= client->active_update->serial && rp->succeeded) {
-            something_to_deregister = true;
-        }
-    }
-
-    // If so, start a deregistration update; otherwise return NoSuchRecord.
-    if (something_to_deregister) {
-        if (client->active_update->message) {
-            free(client->active_update->message);
-            client->active_update->message = NULL;
-        }
-        client->active_update->removing = true;
-        client->active_update->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-        client->active_update->next_attempt_time = INITIAL_NEXT_ATTEMPT_TIME;
-        udp_retransmit(client->active_update);
-        return kDNSServiceErr_NoError;
-    } else {
-        return kDNSServiceErr_NoSuchRecord;
-    }
-}
-
-// Deregister a specific registration
-int
-srp_deregister_instance(DNSServiceRef sdRef)
-{
-    client_state_t *client;
-    reg_state_t *rp;
-
-    // We only expect to find one match.
-    for (client = clients; client; client = client->next) {
-        for (rp = client->registrations; rp; rp = rp->next) {
-            if (rp == sdRef) {
-                goto found;
-            }
-        }
-    }
-    return kDNSServiceErr_NoSuchRecord;
-found:
-    rp->removing = true;
-    if (client->active_update->message) {
-        free(client->active_update->message);
-        client->active_update->message = NULL;
-    }
-    client->active_update->next_retransmission_time = INITIAL_NEXT_RETRANSMISSION_TIME;
-    client->active_update->next_attempt_time = INITIAL_NEXT_ATTEMPT_TIME;
-    udp_retransmit(client->active_update);
-    return kDNSServiceErr_NoError;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-crypto.h b/ServiceRegistration/srp-crypto.h
deleted file mode 100644
index 98595d2..0000000
--- a/ServiceRegistration/srp-crypto.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* srp-crypto.h
- *
- * Copyright (c) 2018-2021 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
- *
- *     https://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.
- *
- * DNS SIG(0) signature generation for DNSSD SRP using mbedtls.
- *
- * Functions required for loading, saving, and generating public/private keypairs, extracting the public key
- * into KEY RR data, and computing signatures.
- */
-
-#ifndef __SRP_CRYPTO_H
-#define __SRP_CRYPTO_H
-
-#include "srp.h"
-
-// Anonymous key structure, depends on the target.
-typedef struct srp_key srp_key_t;
-typedef struct hmac_key hmac_key_t;
-struct hmac_key {
-    int algorithm;
-    dns_name_t *NONNULL name;
-    uint8_t *NONNULL secret;
-    int length;
-};
-
-#define ECDSA_KEY_SIZE             64
-#define ECDSA_KEY_PART_SIZE        32
-#define ECDSA_SHA256_HASH_SIZE     32
-#define ECDSA_SHA256_SIG_SIZE      64
-#define ECDSA_SHA256_SIG_PART_SIZE 32
-
-#define SIG_HEADERLEN    11
-#define SIG_STATIC_RDLEN 18
-
-#define dnssec_keytype_ecdsa 13
-
-#define SRP_SHA256_DIGEST_SIZE 32
-#define SRP_SHA256_BLOCK_SIZE  64
-#define SRP_HMAC_TYPE_SHA256   1
-
-#ifdef SRP_CRYPTO_MACOS_INTERNAL
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/Security.h>
-// #include <Security/SecTransform.h>
-#include <CoreServices/CoreServices.h>
-
-struct srp_key {
-    SecKeyRef NONNULL public;
-    SecKeyRef NONNULL private;
-};
-
-// An ECDSASHA256 signature in ASN.1 DER format is 0x30 | x | 0x02 | y | r | 0x02 | z | s, where x is the
-// length of the whole sequence (minus the first byte), y is the encoded length of r, and z is
-// the encoded length of s.
-       // type               offset in output buffer      sub-template    size of output buffer
-       // ----               -----------------------      ------------    ---------------------
-#define ECDSA_SIG_TEMPLATE(name)                                                                          \
-    static const SecAsn1Template sig_template[] = {                                                       \
-        { SEC_ASN1_SEQUENCE, 0,                                 NULL,     sizeof(raw_signature_data_t) }, \
-        { SEC_ASN1_INTEGER,  offsetof(raw_signature_data_t, r), NULL,     0 },                            \
-        { SEC_ASN1_INTEGER,  offsetof(raw_signature_data_t, s), NULL,     0 },                            \
-        { 0,                 0,                           NULL,           0 }                             \
-    };
-
-#if !TARGET_OS_IPHONE && !TARGET_OS_TV && !TARGET_OS_WATCH
-#endif // MACOS only
-#endif // SRP_CRYPTO_MACOS_INTERNAL
-
-#ifdef SRP_CRYPTO_MBEDTLS
-#include <mbedtls/error.h>
-#include <mbedtls/pk.h>
-#include <mbedtls/md.h>
-#include <mbedtls/ecp.h>
-#include <mbedtls/ecdsa.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/sha256.h>
-#include <mbedtls/base64.h>
-
-// Works just fine with mbedtls.
-#define KEYCOPY_WORKS 1
-
-// The SRP key includes both the ecdsa key and the pseudo-random number generator context, so that we can
-// use the PRNG for signing as well as generating keys.   The PRNG is seeded with a high-entropy data source.
-// This structure assumes that we are just using this one key; if we want to support multiple keys then
-// the entropy source and PRNG should be shared by all keys (of course, that's not thread-safe, so...)
-struct srp_key {
-    mbedtls_pk_context key;
-};
-
-// Uncomment the following line to print the data being feed into the hash operation for debugging purpose.
-// #define DEBUG_SHA256
-#ifdef DEBUG_SHA256
-int srp_mbedtls_sha256_update_ret(const char *NONNULL thing_name,
-                                  mbedtls_sha256_context *NONNULL sha, uint8_t *NONNULL message, size_t msglen);
-int srp_mbedtls_sha256_finish_ret(mbedtls_sha256_context *NONNULL sha, uint8_t *NONNULL hash);
-#else
-#define srp_mbedtls_sha256_update_ret(name, ...) mbedtls_sha256_update_ret(__VA_ARGS__)
-#define srp_mbedtls_sha256_finish_ret mbedtls_sha256_finish_ret
-#endif // DEBUG_SHA256
-#ifdef THREAD_DEVKIT_ADK
-#define mbedtls_strerror(code, buf, bufsize) snprintf(buf, bufsize, "%d", (int)(code))
-#endif
-
-// The following entry points must be provided by the host for hosts that use mbedtls signing.
-
-// The SRP host is expected to load the SRP-specific host key out of stable storage.
-// If no key has previously been stored, this function must return kDNSServiceErr_NoSuchKey.
-// If the key doesn't fit in the buffer, this function must return kDNSServiceErr_NoMemory.
-// Otherwise, the function is expected to copy the key into the buffer and store the key length
-// through the length pointer, and return kDNSServiceErr_NoError.
-int srp_load_key_data(void *NULLABLE host_context, const char *NONNULL key_name,
-                      uint8_t *NONNULL buffer, uint16_t *NONNULL length, uint16_t buffer_size);
-
-// The SRP host is expected to store the SRP-specific host key in stable storage.
-// If the key store fails, the server returns a relevant kDNSServiceErr_* error,
-// such as kDNSServiceErr_NoMemory.  Otherwise, the function returns kDNSServiceErr_NoError.
-// It is generally expected that storing the key will not fail--if it does fail, SRP can't
-// function.
-int srp_store_key_data(void *NULLABLE host_context, const char *NONNULL key_name, uint8_t *NONNULL buffer,
-                       uint16_t length);
-
-int srp_remove_key_file(void *NULLABLE host_context, const char *NONNULL key_name);
-#endif // SRP_CRYPTO_MBEDTLS
-
-// sign_*.c:
-void srp_keypair_free(srp_key_t *NONNULL key);
-uint64_t srp_random64(void);
-uint32_t srp_random32(void);
-uint16_t srp_random16(void);
-bool srp_randombytes(uint8_t *NONNULL dest, size_t num);
-uint8_t srp_key_algorithm(srp_key_t *NONNULL key);
-size_t srp_pubkey_length(srp_key_t *NONNULL key);
-size_t srp_signature_length(srp_key_t *NONNULL key);
-size_t srp_pubkey_copy(uint8_t *NONNULL buf, size_t max, srp_key_t *NONNULL key);
-int srp_sign(uint8_t *NONNULL output, size_t max, uint8_t *NONNULL message, size_t msglen,
-             uint8_t *NONNULL rdata, size_t rdlen, srp_key_t *NONNULL key);
-
-// verify_*.c:
-bool srp_sig0_verify(dns_wire_t *NONNULL message, dns_rr_t *NONNULL key, dns_rr_t *NONNULL signature);
-void srp_print_key(srp_key_t *NONNULL key);
-
-// hash_*.c:
-void srp_hmac_iov(hmac_key_t *NONNULL key, uint8_t *NONNULL output, size_t max, struct iovec *NONNULL iov, int count);
-int srp_base64_parse(char *NONNULL src, size_t *NONNULL len_ret, uint8_t *NONNULL buf, size_t buflen);
-#endif // __SRP_CRYPTO_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-dns-proxy.c b/ServiceRegistration/srp-dns-proxy.c
deleted file mode 100644
index fc4d6df..0000000
--- a/ServiceRegistration/srp-dns-proxy.c
+++ /dev/null
@@ -1,1186 +0,0 @@
-/* srp-dns-proxy.c
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * This is a DNSSD Service Registration Protocol gateway.   The purpose of this is to make it possible
- * for SRP clients to update DNS servers that don't support SRP.
- *
- * The way it works is that this gateway listens on port ANY:53 and forwards either to another port on
- * the same host (not recommended) or to any port (usually 53) on a different host.   Requests are accepted
- * over both TCP and UDP in principle, but UDP requests should be from constrained nodes, and rely on
- * network topology for authentication.
- *
- * Note that this is not a full DNS proxy, so you can't just put it in front of a DNS server.
- */
-
-// Get DNS server IP address
-// Get list of permitted source subnets for TCP updates
-// Get list of permitted source subnet/interface tuples for UDP updates
-// Set up UDP listener
-// Set up TCP listener (no TCP Fast Open)
-// Event loop
-// Transaction processing:
-//   1. If UDP, validate that it's from a subnet that is valid for the interface on which it was received.
-//   2. If TCP, validate that it's from a permitted subnet
-//   3. Check that the message is a valid SRP update according to the rules
-//   4. Check the signature
-//   5. Do a DNS Update with prerequisites to prevent overwriting a host record with the same owner name but
-//      a different key.
-//   6. Send back the response
-
-#define __APPLE_USE_RFC_3542
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <dns_sd.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "srp-gw.h"
-#include "config-parse.h"
-#include "srp-proxy.h"
-
-static addr_t dns_server;
-static dns_name_t *service_update_zone; // The zone to update when we receive an update for default.service.arpa.
-static hmac_key_t *key;
-
-static int
-usage(const char *progname)
-{
-    ERROR("usage: %s -s <addr> <port> -k <key-file> -t <subnet> ... -u <ifname> <subnet> ...", progname);
-    ERROR("  -s can only appear once.");
-    ERROR("  -k can appear once.");
-    ERROR("  -t can only appear once, and is followed by one or more subnets.");
-    ERROR("  -u can appear more than once, is followed by one interface name, and");
-    ERROR("     one or more subnets.");
-    ERROR("  <addr> is an IPv4 address or IPv6 address.");
-    ERROR("  <port> is a UDP port number.");
-    ERROR("  <key-file> is a file containing an HMAC-SHA256 key for authenticating updates to the auth server.");
-    ERROR("  <subnet> is an IP address followed by a slash followed by the prefix width.");
-    ERROR("  <ifname> is the printable name of the interface.");
-    ERROR("ex: srp-gw -s 2001:DB8::1 53 -k srp.key -t 2001:DB8:1300::/48 -u en0 2001:DB8:1300:1100::/56");
-    return 1;
-}
-
-// Free the data structures into which the SRP update was parsed.   The pointers to the various DNS objects that these
-// structures point to are owned by the parsed DNS message, and so these do not need to be freed here.
-void
-update_free_parts(service_instance_t *service_instances, service_instance_t *added_instances,
-                  service_t *services, dns_host_description_t *host_description)
-{
-    service_instance_t *sip;
-    service_t *sp;
-
-    for (sip = service_instances; sip; ) {
-        service_instance_t *next = sip->next;
-        free(sip);
-        sip = next;
-    }
-    for (sip = added_instances; sip; ) {
-        service_instance_t *next = sip->next;
-        free(sip);
-        sip = next;
-    }
-    for (sp = services; sp; ) {
-        service_t *next = sp->next;
-        free(sp);
-        sp = next;
-    }
-    if (host_description != NULL) {
-        free(host_description);
-    }
-}
-
-// Free all the stuff that we accumulated while processing the SRP update.
-void
-update_free(update_t *update)
-{
-    // Free all of the structures we collated RRs into:
-    update_free_parts(update->instances, update->added_instances, update->services, update->host);
-    // We don't need to free the zone name: it's either borrowed from the message,
-    // or it's service_update_zone, which is static.
-    message_free(update->message);
-    dns_message_free(update->parsed_message);
-    free(update);
-}
-
-
-#define name_to_wire(towire, name) name_to_wire_(towire, name, __LINE__)
-void
-name_to_wire_(dns_towire_state_t *towire, dns_name_t *name, int line)
-{
-    // Does compression...
-    dns_concatenate_name_to_wire_(towire, name, NULL, NULL, line);
-}
-
-void
-rdata_to_wire(dns_towire_state_t *towire, dns_rr_t *rr)
-{
-    dns_rdlength_begin(towire);
-
-    // These are the only types we expect to see.  If something else were passed, it would be written as rdlen=0.
-    switch(rr->type) {
-    case dns_rrtype_ptr:
-        name_to_wire(towire, rr->data.ptr.name);
-        break;
-
-    case dns_rrtype_srv:
-        dns_u16_to_wire(towire, rr->data.srv.priority);
-        dns_u16_to_wire(towire, rr->data.srv.weight);
-        dns_u16_to_wire(towire, rr->data.srv.port);
-        name_to_wire(towire, rr->data.srv.name);
-        break;
-
-    case dns_rrtype_txt:
-        dns_rdata_raw_data_to_wire(towire, rr->data.txt.data, rr->data.txt.len);
-        break;
-
-    case dns_rrtype_key:
-        dns_u16_to_wire(towire, rr->data.key.flags);
-        dns_u8_to_wire(towire, rr->data.key.protocol);
-        dns_u8_to_wire(towire, rr->data.key.algorithm);
-        dns_rdata_raw_data_to_wire(towire, rr->data.key.key, rr->data.key.len);
-        break;
-
-    case dns_rrtype_a:
-        dns_rdata_raw_data_to_wire(towire, &rr->data.a, sizeof rr->data.a);
-        break;
-
-    case dns_rrtype_aaaa:
-        dns_rdata_raw_data_to_wire(towire, &rr->data.aaaa, sizeof rr->data.aaaa);
-        break;
-    }
-
-    dns_rdlength_end(towire);
-}
-
-// We only list the types we are using--there are other types that we don't support.
-typedef enum prereq_type prereq_type_t;
-enum prereq_type {
-    update_rrset_equals,     // RFC 2136 section 2.4.2: RRset Exists (Value Dependent)
-    update_name_not_in_use,  // RFC 2136 section 2.4.5: Name Is Not In Use
-};
-
-void
-add_prerequisite(dns_wire_t *msg, dns_towire_state_t *towire, prereq_type_t ptype, dns_name_t *name, dns_rr_t *rr)
-{
-    char namebuf[DNS_MAX_NAME_SIZE + 1];
-    if (ntohs(msg->nscount) != 0 || ntohs(msg->arcount) != 0) {
-        ERROR("%s: adding prerequisite after updates", dns_name_print(name, namebuf, sizeof namebuf));
-        towire->truncated = true;
-    }
-    name_to_wire(towire, name);
-    switch(ptype) {
-    case update_rrset_equals:
-        dns_u16_to_wire(towire, rr->type);
-        dns_u16_to_wire(towire, rr->qclass);
-        dns_ttl_to_wire(towire, 0);
-        rdata_to_wire(towire, rr);
-        break;
-    case update_name_not_in_use:
-        dns_u16_to_wire(towire, dns_rrtype_any);   // TYPE
-        dns_u16_to_wire(towire, dns_qclass_none);  // CLASS
-        dns_ttl_to_wire(towire, 0);                // TTL
-        dns_u16_to_wire(towire, 0);                // RDLEN
-        break;
-    }
-    msg->ancount = htons(ntohs(msg->ancount) + 1);
-}
-
-// We actually only support one type of delete, so it's a bit silly to specify it, but in principle we might
-// want more later.
-typedef enum delete_type delete_type_t;
-enum delete_type {
-    delete_name, // RFC 2136 section 2.5.3: Delete all RRsets from a name
-};
-
-void
-add_delete(dns_wire_t *msg, dns_towire_state_t *towire, delete_type_t dtype, dns_name_t *name)
-{
-    name_to_wire(towire, name);
-    switch(dtype) {
-    case delete_name:
-        dns_u16_to_wire(towire, dns_rrtype_any);   // TYPE
-        dns_u16_to_wire(towire, dns_qclass_any);   // CLASS
-        dns_ttl_to_wire(towire, 0);                // TTL
-        dns_u16_to_wire(towire, 0);                // RDLEN
-        break;
-    }
-    msg->nscount = htons(ntohs(msg->nscount) + 1);
-}
-
-// Copy the RR we received in the SRP update out in wire format.
-
-void
-add_rr(dns_wire_t *msg, dns_towire_state_t *towire, dns_name_t *name, dns_rr_t *rr)
-{
-    if (rr != NULL) {
-        name_to_wire(towire, name);
-        dns_u16_to_wire(towire, rr->type);   // TYPE
-        dns_u16_to_wire(towire, rr->qclass); // CLASS
-        dns_ttl_to_wire(towire, rr->ttl);    // TTL
-        rdata_to_wire(towire, rr);           // RDLEN
-        msg->nscount = htons(ntohs(msg->nscount) + 1);
-    }
-}
-
-// Construct an update of the specified type, assuming that the record being updated
-// either exists or does not exist, depending on the value of exists.   Actual records
-// to be update are taken from the update_t.
-//
-// Analysis:
-//
-// The goal of the update is to either bring the zone to the state described in the SRP update, or
-// determine that the state described in the SRP update conflicts with what is already present in
-// the zone.
-//
-// Possible scenarios:
-// 1. Update and Zone are the same (A and AAAA records may differ):
-//    Prerequisites:
-//    a. for each instance: KEY RR exists on instance name and is the same
-//    b. for host: KEY RR exists on host name and is the same
-//    Update:
-//    a. for each instance: delete all records on instance name, add KEY RR, add SRV RR, add TXT RR
-//    b. for host: delete host instance, add A, AAAA and KEY RRs
-//    c. for each service: add PTR record pointing on service name to service instance name
-//
-// We should try 1 first, because it should be the steady state case; that is, it should be what happens
-// most of the time.
-// If 1 fails, then we could have some service instances present and others not.   There is no way to
-// know without trying.   We can at this point either try to add each service instance in a separate update,
-// or assume that none are present and add them all at once, and then if this fails add them individually.
-// I think that it makes sense to try them all first, because that should be the second most common case:
-//
-// 2. Nothing in update is present in zone:
-//    Prerequisites:
-//    a. For each instance: instance name is not in use
-//    b. Host name is not in use
-//    Update:
-//    a. for each instance: add KEY RR, add SRV RR, add TXT RR on instance name
-//    b. for host: add A, AAAA and KEY RRs on host name
-//    c. for each service: add PTR record pointing on service name to service instance name
-//
-// If either (1) or (2) works, we're done.   If both fail, then we need to do the service instance updates
-// and host update one by one.   This is a bit nasty because we actually have to try twice: once assuming
-// the RR exists, and once assuming it doesn't.   If any of the instance updates fail, or the host update
-// fails, we delete all the ones that succeeded.
-//
-// In the cases other than (1) and (2), we can add all the service PTRs in the host update, because they're
-// only added if the host update succeeds; if it fails, we have to go back and remove all the service
-// instances.
-//
-// One open question for the SRP document: we probably want to signal whether the conflict is with the
-// hostname or one of the service instance names.   We can do this with an EDNS(0) option.
-//
-// The flow will be:
-// - Try to update assuming everything is there already (case 1)
-// - Try to update assuming nothing is there already (case 2)
-// - For each service instance:
-//   - Try to update assuming it's not there; if this succeeds, add this instance to the list of
-//     instances that have been added. If not:
-//     - Try to update assuming it is there
-//     - If this fails, go to fail
-// - Try to update the host (and also services) assuming the host is not there.   If this fails:
-//   - Try to update the host (and also services) assuming the host is there.  If this succeeds:
-//     - return success
-// fail:
-// - For each service instance in the list of instances that have been added:
-//   - delete all records on the instance name.
-//
-// One thing that isn't accounted for here: it's possible that a previous update added some but not all
-// instances in the current update.  Subsequently, some other device may have claimed an instance that is
-// present but in conflict in the current update.   In this case, all of the instances prior to that one
-// in the update will actually have been updated by this update, but then the update as a whole will fail.
-// I think this is unlikely to be an actual problem, and there's no way to address it without a _lot_ of
-// complexity.
-
-bool
-construct_update(update_t *update)
-{
-    dns_towire_state_t towire;
-    dns_wire_t *msg = update->update; // Solely to reduce the amount of typing.
-    service_instance_t *instance;
-    service_t *service;
-    host_addr_t *host_addr;
-
-    // Set up the message constructor
-    memset(&towire, 0, sizeof towire);
-    towire.p = &msg->data[0];  // We start storing RR data here.
-    towire.lim = &msg->data[0] + update->update_max; // This is the limit to how much we can store.
-    towire.message = msg;
-
-    // Initialize the update message...
-    memset(msg, 0, DNS_HEADER_SIZE);
-    dns_qr_set(msg, dns_qr_query);
-    dns_opcode_set(msg, dns_opcode_update);
-    msg->id = srp_random16();
-
-    // An update always has one question, which is the zone name.
-    msg->qdcount = htons(1);
-    name_to_wire(&towire, update->zone_name);
-    dns_u16_to_wire(&towire, dns_rrtype_soa);
-    dns_u16_to_wire(&towire, dns_qclass_in);
-
-    switch(update->state) {
-    case connect_to_server:
-        ERROR("Update construction requested when still connecting.");
-        update->update_length = 0;
-        return false;
-
-        // Do a DNS Update for a service instance
-    case refresh_existing:
-        // Add a "KEY exists and is <x> and a PTR exists and is <x> prerequisite for each instance being updated.
-        for (instance = update->instances; instance; instance = instance->next) {
-            add_prerequisite(msg, &towire, update_rrset_equals, instance->name, update->host->key);
-        }
-        add_prerequisite(msg, &towire, update_rrset_equals, update->host->name, update->host->key);
-        // Now add a delete for each service instance
-        for (instance = update->instances; instance; instance = instance->next) {
-            add_delete(msg, &towire, delete_name, instance->name);
-        }
-        add_delete(msg, &towire, delete_name, update->host->name);
-
-    add_instances:
-        // Now add the update for each instance.
-        for (instance = update->instances; instance; instance = instance->next) {
-            add_rr(msg, &towire, instance->name, update->host->key);
-            add_rr(msg, &towire, instance->name, instance->srv);
-            add_rr(msg, &towire, instance->name, instance->txt);
-        }
-        // Add the update for each service
-        for (service = update->services; service; service = service->next) {
-            add_rr(msg, &towire, service->rr->name, service->rr);
-        }
-        // Add the host records...
-        add_rr(msg, &towire, update->host->name, update->host->key);
-        for (host_addr = update->host->addrs; host_addr; host_addr = host_addr->next) {
-            add_rr(msg, &towire, update->host->name, &host_addr->rr);
-        }
-        break;
-
-    case create_nonexistent:
-        // Add a "name not in use" prerequisite for each instance being updated.
-        for (instance = update->instances; instance; instance = instance->next) {
-            add_prerequisite(msg, &towire, update_name_not_in_use, instance->name, (dns_rr_t *)NULL);
-        }
-        add_prerequisite(msg, &towire, update_name_not_in_use, update->host->name, (dns_rr_t *)NULL);
-        goto add_instances;
-
-    case create_nonexistent_instance:
-        // The only prerequisite is that this specific service instance doesn't exist.
-        add_prerequisite(msg, &towire, update_name_not_in_use, update->instance->name, (dns_rr_t *)NULL);
-        goto add_instance;
-
-    case refresh_existing_instance:
-        // If instance already exists, prerequisite is that it has the same key, and we also have to
-        // delete all RRs on the name before adding our RRs, in case they have changed.
-        add_prerequisite(msg, &towire, update_rrset_equals, update->instance->name, update->host->key);
-        add_delete(msg, &towire, delete_name, update->instance->name);
-    add_instance:
-        add_rr(msg, &towire, update->instance->name, update->host->key);
-        add_rr(msg, &towire, update->instance->name, update->instance->srv);
-        add_rr(msg, &towire, update->instance->name, update->instance->txt);
-        break;
-
-    case create_nonexistent_host:
-        add_prerequisite(msg, &towire, update_name_not_in_use, update->host->name, (dns_rr_t *)NULL);
-        goto add_host;
-
-    case refresh_existing_host:
-        add_prerequisite(msg, &towire, update_rrset_equals, update->host->name, update->host->key);
-        add_delete(msg, &towire, delete_name, update->host->name);
-        // Add the service PTRs here--these don't need to be in a separate update, because if we get here
-        // the only thing that can make adding them not okay is if adding the host fails.
-        // Add the update for each service
-        for (service = update->services; service; service = service->next) {
-            add_rr(msg, &towire, service->rr->name, service->rr);
-        }
-    add_host:
-        // Add the host records...
-        add_rr(msg, &towire, update->host->name, update->host->key);
-        for (host_addr = update->host->addrs; host_addr; host_addr = host_addr->next) {
-            add_rr(msg, &towire, update->host->name, &host_addr->rr);
-        }
-        break;
-
-    case delete_failed_instance:
-        // Delete all the instances we successfull added before discovering a problem.
-        // It is possible in principle that these could have been overwritten by some other
-        // process and we could be deleting the wrong stuff, but in practice this should
-        // never happen if these are legitimately managed by SRP.   Once a name has been
-        // claimed by SRP, it should continue to be managed by SRP until its lease expires
-        // and SRP deletes it, at which point it is of course fair game.
-        for (instance = update->instances; instance; instance = instance->next) {
-            add_delete(msg, &towire, delete_name, instance->name);
-        }
-        break;
-    }
-    if (towire.error != 0) {
-        ERROR("construct_update: error %s while generating update at line %d", strerror(towire.error), towire.line);
-        return false;
-    }
-    update->update_length = towire.p - (uint8_t *)msg;
-    return true;
-}
-
-void
-update_finished(update_t *update, int rcode)
-{
-    comm_t *comm = update->client;
-    struct iovec iov;
-    dns_wire_t response;
-    INFO("Update Finished, rcode = " PUB_S_SRP, dns_rcode_name(rcode));
-
-    memset(&response, 0, DNS_HEADER_SIZE);
-    response.id = update->message->wire.id;
-    response.bitfield = update->message->wire.bitfield;
-    dns_rcode_set(&response, rcode);
-    dns_qr_set(&response, dns_qr_response);
-
-    iov.iov_base = &response;
-    iov.iov_len = DNS_HEADER_SIZE;
-
-    comm->send_response(comm, update->message, &iov, 1);
-
-    // If success, construct a response
-    // If fail, send a quick status code
-    // Signal host name conflict and instance name conflict using different rcodes (?)
-    // Okay, so if there's a host name/instance name conflict, and the host name has the right key, then
-    // the instance name is actually bogus and should be overwritten.
-    // If the host has the wrong key, and the instance is present, then the instance is also bogus.
-    // So in each of these cases, perhaps we should just gc the instance.
-    // This would mean that there is nothing to signal: either the instance is a mismatch, and we
-    // overwrite it and return success, or the host is a mismatch and we gc the instance and return failure.
-    ioloop_close(&update->server->io);
-    update_free(update);
-}
-
-void
-update_send(update_t *update)
-{
-    struct iovec iov[4];
-    dns_towire_state_t towire;
-    dns_wire_t *msg = update->update;
-    struct timeval tv;
-    uint8_t *p_mac;
-#ifdef DEBUG_DECODE_UPDATE
-    dns_message_t *decoded;
-#endif
-
-    // Set up the message constructor
-    memset(&towire, 0, sizeof towire);
-    towire.p = (uint8_t *)msg + update->update_length;  // We start storing RR data here.
-    towire.lim = &msg->data[0] + update->update_max;    // This is the limit to how much we can store.
-    towire.message = msg;
-    towire.p_rdlength = NULL;
-    towire.p_opt = NULL;
-
-    // If we have a key, sign the message with the key using TSIG HMAC-SHA256.
-    if (key != NULL) {
-        // Maintain an IOV with the bits of the message that we need to sign.
-        iov[0].iov_base = msg;
-
-        name_to_wire(&towire, key->name);
-        iov[0].iov_len = towire.p - (uint8_t *)iov[0].iov_base;
-        dns_u16_to_wire(&towire, dns_rrtype_tsig);            // RRTYPE
-        iov[1].iov_base = towire.p;
-        dns_u16_to_wire(&towire, dns_qclass_any);             // CLASS
-        dns_ttl_to_wire(&towire, 0);                          // TTL
-        iov[1].iov_len = towire.p - (uint8_t *)iov[1].iov_base;
-        // The message digest skips the RDLEN field.
-        dns_rdlength_begin(&towire);                          // RDLEN
-        iov[2].iov_base = towire.p;
-        dns_full_name_to_wire(NULL, &towire, "hmac-sha256."); // Algorithm Name
-        gettimeofday(&tv, NULL);
-        dns_u48_to_wire(&towire, tv.tv_sec);                  // Time since epoch
-        dns_u16_to_wire(&towire, 300);                        // Fudge interval
-                                                              // (clocks can be skewed by up to 5 minutes)
-        // Message digest doesn't cover MAC size or MAC fields, for obvious reasons, nor original message ID.
-        iov[2].iov_len = towire.p - (uint8_t *)iov[2].iov_base;
-        dns_u16_to_wire(&towire, SRP_SHA256_DIGEST_SIZE);       // MAC Size
-        p_mac = towire.p;                                     // MAC
-        if (!towire.error) {
-            if (towire.p + SRP_SHA256_DIGEST_SIZE >= towire.lim) {
-                towire.error = ENOBUFS;
-                towire.truncated = true;
-                towire.line = __LINE__;
-            } else {
-                towire.p += SRP_SHA256_DIGEST_SIZE;
-            }
-        }
-        // We have to copy the message ID into the tsig signature; this is because in some cases, although not this one,
-        // the message ID will be overwritten.   So the copy of the ID is what's validated, but it's copied into the
-        // header for validation, so we don't include it when generating the hash.
-        dns_rdata_raw_data_to_wire(&towire, &msg->id, sizeof msg->id);
-        iov[3].iov_base = towire.p;
-        dns_u16_to_wire(&towire, 0);                     // TSIG Error (always 0 on send).
-        dns_u16_to_wire(&towire, 0);                     // Other Len (MBZ?)
-        iov[3].iov_len = towire.p - (uint8_t *)iov[3].iov_base;
-        dns_rdlength_end(&towire);
-
-        // Okay, we have stored the TSIG signature, now compute the message digest.
-        srp_hmac_iov(key, p_mac, SRP_SHA256_DIGEST_SIZE, &iov[0], 4);
-        msg->arcount = htons(ntohs(msg->arcount) + 1);
-        update->update_length = towire.p - (const uint8_t *)msg;
-    }
-
-    if (towire.error != 0) {
-        ERROR("update_send: error \"%s\" while generating update at line %d",
-              strerror(towire.error), towire.line);
-        update_finished(update, dns_rcode_servfail);
-        return;
-    }
-
-#ifdef DEBUG_DECODE_UPDATE
-    if (!dns_wire_parse(&decoded, msg, update->update_length, false)) {
-        ERROR("Constructed message does not successfully parse.");
-        update_finished(update, dns_rcode_servfail);
-        return;
-    }
-#endif
-
-    // Transmit the update
-    iov[0].iov_base = update->update;
-    iov[0].iov_len = update->update_length;
-    update->server->send_response(update->server, update->message, iov, 1);
-}
-
-void
-update_connect_callback(comm_t *comm)
-{
-    update_t *update = comm->context;
-
-    // Once we're connected, construct the first update.
-    INFO("Connected to " PUB_S_SRP ".", comm->name);
-    // STATE CHANGE: connect_to_server -> refresh_existing
-    update->state = refresh_existing;
-    if (!construct_update(update)) {
-        update_finished(update, dns_rcode_servfail);
-        return;
-    }
-    update_send(update);
-}
-
-const char *NONNULL
-update_state_name(update_state_t state)
-{
-    switch(state) {
-    case connect_to_server:
-        return "connect_to_server";
-    case create_nonexistent:
-        return "create_nonexistent";
-    case refresh_existing:
-        return "refresh_existing";
-    case create_nonexistent_instance:
-        return "create_nonexistent_instance";
-    case refresh_existing_instance:
-        return "refresh_existing_instance";
-    case create_nonexistent_host:
-        return "create_nonexistent_host";
-    case refresh_existing_host:
-        return "refresh_existing_host";
-    case delete_failed_instance:
-        return "delete_failed_instance";
-    }
-    return "unknown state";
-}
-
-void
-update_finalize(io_t *context)
-{
-}
-
-void
-update_disconnect_callback(comm_t *comm, int error)
-{
-    update_t *update = comm->context;
-
-    if (update->state == connect_to_server) {
-        INFO(PUB_S_SRP " disconnected: " PUB_S_SRP, comm->name, strerror(error));
-        update_finished(update, dns_rcode_servfail);
-    } else {
-        // This could be bad if any updates succeeded.
-        ERROR("%s disconnected during update in state %s: %s",
-              comm->name, update_state_name(update->state), strerror(error));
-        update_finished(update, dns_rcode_servfail);
-    }
-}
-
-void
-update_reply_callback(comm_t *comm)
-{
-    update_t *update = comm->context;
-    dns_wire_t *wire = &comm->message->wire;
-    char namebuf[DNS_MAX_NAME_SIZE + 1], namebuf1[DNS_MAX_NAME_SIZE + 1];
-    service_instance_t **pinstance;
-    update_state_t initial_state;
-    service_instance_t *initial_instance;
-
-    initial_instance = update->instance;
-    initial_state = update->state;
-
-    INFO("Message from " PUB_S_SRP " in state " PUB_S_SRP ", rcode = " PUB_S_SRP ".", comm->name,
-        update_state_name(update->state), dns_rcode_name(dns_rcode_get(wire)));
-
-    // Sanity check the response
-    if (dns_qr_get(wire) == dns_qr_query) {
-        ERROR("Received a query from the authoritative server!");
-        update_finished(update, dns_rcode_servfail);
-        return;
-    }
-    if (dns_opcode_get(wire) != dns_opcode_update) {
-        ERROR("Received a response with opcode %d from the authoritative server!",
-              dns_opcode_get(wire));
-        update_finished(update, dns_rcode_servfail);
-        return;
-    }
-    if (update->update == NULL) {
-        ERROR("Received a response from auth server when no update has been sent yet.");
-        update_finished(update, dns_rcode_servfail);
-    }
-    // This isn't an error in the protocol, because we might be pipelining.   But we _aren't_ pipelining,
-    // so there is only one message in flight.   So the message IDs should match.
-    if (update->update->id != wire->id) {
-        ERROR("Response doesn't have the expected id: %x != %x.", wire->id, update->update->id);
-        update_finished(update, dns_rcode_servfail);
-    }
-
-    // Handle the case where the update succeeded.
-    switch(dns_rcode_get(wire)) {
-    case dns_rcode_noerror:
-        switch(update->state) {
-        case connect_to_server:  // Can't get a response when connecting.
-        invalid:
-            ERROR("Invalid rcode \"%s\" for state %s",
-                  dns_rcode_name(dns_rcode_get(wire)), update_state_name(update->state));
-            update_finished(update, dns_rcode_servfail);
-            return;
-
-        case create_nonexistent:
-            DM_NAME_GEN_SRP(update->host->name, freshly_added_name_buf);
-            INFO("SRP Update for host " PRI_DM_NAME_SRP " was freshly added.",
-                     DM_NAME_PARAM_SRP(update->host->name, freshly_added_name_buf));
-            update_finished(update, dns_rcode_noerror);
-            return;
-
-        case refresh_existing:
-            DM_NAME_GEN_SRP(update->host->name, refreshed_name_buf);
-            INFO("SRP Update for host " PRI_DM_NAME_SRP " was refreshed.",
-                 DM_NAME_PARAM_SRP(update->host->name, refreshed_name_buf));
-            update_finished(update, dns_rcode_noerror);
-            return;
-
-        case create_nonexistent_instance:
-            DM_NAME_GEN_SRP(update->instance->name, create_instance_buf);
-            INFO("Instance create for " PRI_DM_NAME_SRP " succeeded",
-                 DM_NAME_PARAM_SRP(update->instance->name, create_instance_buf));
-            // If we created a new instance, we need to remember it in case we have to undo it.
-            // To do that, we have to take it off the list.
-            for (pinstance = &update->instances; *pinstance != NULL; pinstance = &((*pinstance)->next)) {
-                if (*pinstance == update->instance) {
-                    break;
-                }
-            }
-            *pinstance = update->instance->next;
-            // If there are no more instances to update, then do the host add.
-            if (*pinstance == NULL) {
-                // STATE CHANGE: create_nonexistent_instance -> create_nonexistent_host
-                update->state = create_nonexistent_host;
-            } else {
-                // Not done yet, do the next one.
-                update->instance = *pinstance;
-            }
-            break;
-
-        case refresh_existing_instance:
-            DM_NAME_GEN_SRP(update->instance->name, refreshed_instance_buf);
-            INFO("Instance refresh for " PRI_S_SRP " succeeded",
-                 DM_NAME_PARAM_SRP(update->instance->name, refreshed_instance_buf));
-
-            // Move on to the next instance to update.
-            update->instance = update->instance->next;
-            // If there are no more instances to update, then do the host add.
-            if (update->instance == NULL) {
-                // STATE CHANGE: refresh_existing_instance -> create_nonexistent_host
-                update->state = create_nonexistent_host;
-            } else {
-                // Not done yet, do the next one.
-                // STATE CHANGE: refresh_existing_instance -> create_nonexistent_instance
-                update->state = create_nonexistent_instance;
-            }
-            break;
-
-        case create_nonexistent_host:
-            DM_NAME_GEN_SRP(update->instance->name, new_host_buf);
-            INFO("SRP Update for new host " PRI_S_SRP " was successful.",
-                 DM_NAME_PARAM_SRP(update->instance->name, new_host_buf));
-            update_finished(update, dns_rcode_noerror);
-            return;
-
-        case refresh_existing_host:
-            DM_NAME_GEN_SRP(update->instance->name, existing_host_buf);
-            INFO("SRP Update for existing host " PRI_S_SRP " was successful.",
-                 DM_NAME_PARAM_SRP(update->instance->name, existing_host_buf));
-            update_finished(update, dns_rcode_noerror);
-            return;
-
-        case delete_failed_instance:
-            DM_NAME_GEN_SRP(update->host->name, failed_instance_buf);
-            INFO("Instance deletes for host %s succeeded",
-                 DM_NAME_PARAM_SRP(update->host->name, failed_instance_buf));
-            update_finished(update, update->fail_rcode);
-            return;
-        }
-        break;
-
-        // We will get NXRRSET if we were adding an existing host with the prerequisite that a KEY
-        // RR exist on the name with the specified value.  Some other KEY RR may exist, or there may
-        // be no such RRSET; we can't tell from this response.
-    case dns_rcode_nxrrset:
-        switch(update->state) {
-        case connect_to_server:           // Can't get a response while connecting.
-        case create_nonexistent:          // Can't get nxdomain when creating.
-        case create_nonexistent_instance: // same
-        case create_nonexistent_host:     // same
-        case delete_failed_instance:      // There are no prerequisites for deleting failed instances, so
-                                          // in principle this should never fail.
-            goto invalid;
-
-        case refresh_existing:
-            // If we get an NXDOMAIN when doing a refresh, it means either that there is a conflict,
-            // or that one of the instances we are refreshing doesn't exist.   So now do the instances
-            // one at a time.
-
-            // STATE CHANGE: refresh_existing -> create_nonexistent
-            update->state = create_nonexistent;
-            update->instance = update->instances;
-            break;
-
-        case refresh_existing_instance:
-            // In this case, we tried to update an existing instance and found that the prerequisite
-            // didn't match.   This means either that there is a conflict, or else that the instance
-            // expired and was deleted between the time that we attempted to create it and the time
-            // we attempted to update it.  We could account for this with an create_nonexistent_instance_again
-            // state, but currently do not.
-
-            // If we have added some instances, we need to delete them before we send the fail response.
-            if (update->added_instances != NULL) {
-                // STATE CHANGE: refresh_existing_instance -> delete_failed_instance
-                update->state = delete_failed_instance;
-            delete_added_instances:
-                update->instance = update->added_instances;
-                update->fail_rcode = dns_rcode_get(wire);
-                break;
-            } else {
-                update_finished(update, dns_rcode_get(wire));
-                return;
-            }
-
-        case refresh_existing_host:
-            // In this case, there is a conflicting host entry.  This means that all the service
-            // instances that exist and are owned by the key we are using are bogus, whether we
-            // created them or they were already there.  However, it is not our mission to remove
-            // pre-existing messes here, so we'll just delete the ones we added.
-            if (update->added_instances != NULL) {
-                // STATE CHANGE: refresh_existing_host -> delete_failed_instance
-                update->state = delete_failed_instance;
-                goto delete_added_instances;
-            }
-            update_finished(update, dns_rcode_get(wire));
-            return;
-        }
-        break;
-        // We get YXDOMAIN if we specify a prerequisite that the name not exist, but it does exist.
-    case dns_rcode_yxdomain:
-       switch(update->state) {
-        case connect_to_server:         // We can't get a response while connecting.
-        case refresh_existing:          // If we are refreshing, our prerequisites are all looking for
-        case refresh_existing_instance: // a specific RR with a specific value, so we can never get
-        case refresh_existing_host:     // YXDOMAIN.
-        case delete_failed_instance:    // And if we are deleting failed instances, we should never get an error.
-            goto invalid;
-
-        case create_nonexistent:
-            // If we get an NXDOMAIN when doing a refresh, it means either that there is a conflict,
-            // or that one of the instances we are refreshing doesn't exist.   So now do the instances
-            // one at a time.
-
-            // STATE CHANGE: create_nonexistent -> create_nonexistent_instance
-            update->state = create_nonexistent_instance;
-            update->instance = update->instances;
-            break;
-
-        case create_nonexistent_instance:
-            // STATE CHANGE: create_nonexistent_instance -> refresh_existing_instance
-            update->state = refresh_existing_instance;
-            break;
-
-        case create_nonexistent_host:
-            // STATE CHANGE: create_nonexistent_host -> refresh_existing_host
-            update->state = refresh_existing_host;
-            break;
-       }
-       break;
-
-    case dns_rcode_notauth:
-        ERROR("DNS Authoritative server does not think we are authorized to update it, please fix.");
-        update_finished(update, dns_rcode_servfail);
-        return;
-
-        // We may want to return different error codes or do more informative logging for some of these:
-    case dns_rcode_formerr:
-    case dns_rcode_servfail:
-    case dns_rcode_notimp:
-    case dns_rcode_refused:
-    case dns_rcode_yxrrset:
-    case dns_rcode_notzone:
-    case dns_rcode_dsotypeni:
-    default:
-        goto invalid;
-    }
-
-    if (update->state != initial_state) {
-        INFO("Update state changed from " PUB_S_SRP " to " PUB_S_SRP, update_state_name(initial_state),
-             update_state_name(update->state));
-    }
-    if (update->instance != initial_instance) {
-        DM_NAME_GEN_SRP(initial_instance->name, initial_name_buf);
-        DM_NAME_GEN_SRP(update->instance->name, updated_name_buf);
-        INFO("Update instance changed from " PRI_DM_NAME_SRP " to " PRI_DM_NAME_SRP,
-             DM_NAME_PARAM_SRP(initial_instance->name, initial_name_buf),
-             DM_NAME_PARAM_SRP(update->instance->name, updated_name_buf));
-    }
-    if (construct_update(update)) {
-        update_send(update);
-    } else {
-        ERROR("Failed to construct update");
-        update_finished(update, dns_rcode_servfail);
-    }
-     return;
-}
-
-bool
-srp_update_start(comm_t *connection, dns_message_t *parsed_message, dns_host_description_t *host,
-                 service_instance_t *instance, service_t *service, dns_name_t *update_zone,
-                 uint32_t lease_time, uint32_t key_lease_time)
-{
-    update_t *update;
-
-    // Allocate the data structure
-    update = calloc(1, sizeof *update);
-    if (update == NULL) {
-        ERROR("start_dns_update: unable to allocate update structure!");
-        return false;
-    }
-    // Allocate the buffer in which updates will be constructed.
-    update->update = calloc(1, DNS_MAX_UDP_PAYLOAD);
-    if (update->update == NULL) {
-        ERROR("start_dns_update: unable to allocate update message buffer.");
-        return false;
-    }
-    update->update_max = DNS_DATA_SIZE;
-
-    // Retain the stuff we're supposed to send.
-    update->host = host;
-    update->instances = instance;
-    update->services = service;
-    update->parsed_message = parsed_message;
-    update->message = connection->message;
-    update->state = connect_to_server;
-    update->zone_name = update_zone;
-    update->client = connection;
-
-    // Start the connection to the server
-    update->server = ioloop_connect(&dns_server, false, true, update_reply_callback,
-                                    update_connect_callback, update_disconnect_callback, update_finalize, update);
-    if (update->server == NULL) {
-        free(update);
-        return false;
-    }
-    INFO("Connecting to auth server.");
-    return true;
-}
-
-static bool
-key_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno)
-{
-    hmac_key_t *key = context;
-    long val;
-    char *endptr;
-    size_t len;
-    uint8_t keybuf[SRP_SHA256_DIGEST_SIZE];
-    int error;
-
-    // Validate the constant-size stuff first.
-    if (strcasecmp(hunks[1], "in")) {
-        ERROR("Expecting tsig key class IN, got %s.", hunks[1]);
-        return false;
-    }
-
-    if (strcasecmp(hunks[2], "key")) {
-        ERROR("expecting tsig key type KEY, got %s", hunks[2]);
-        return false;
-    }
-
-    // There's not much meaning to be extracted from the flags.
-    val = strtol(hunks[3], &endptr, 10);
-    if (*endptr != 0 || endptr == hunks[3]) {
-        ERROR("Invalid key flags: %s", hunks[3]);
-        return false;
-    }
-
-    // The protocol number as produced by BIND will always be 3, meaning DNSSEC, but of
-    // course we aren't using this key for DNSSEC, so it's not clear that we should take
-    // this seriously; hence we just check to see that it's a number.
-    val = strtol(hunks[4], &endptr, 10);
-    if (*endptr != 0 || endptr == hunks[4]) {
-        ERROR("Invalid protocol number: %s", hunks[4]);
-        return false;
-    }
-
-    // The key algorithm should be HMAC-SHA253.  BIND uses 163, but this is not registered
-    // with IANA.   So again, we don't actually require this, but we do validate it so that
-    // if someone generated the wrong key type, they'll get a message.
-    val = strtol(hunks[5], &endptr, 10);
-    if (*endptr != 0 || endptr == hunks[5]) {
-        ERROR("Invalid protocol number: %s", hunks[5]);
-        return false;
-    }
-    if (val != 163) {
-        INFO("Warning: Protocol number for HMAC-SHA256 TSIG KEY is not 163, but %ld", val);
-    }
-
-    key->name = dns_pres_name_parse(hunks[0]);
-    if (key->name == NULL) {
-        ERROR("Invalid key name: %s", hunks[0]);
-        return false;
-    }
-
-    error = srp_base64_parse(hunks[6], &len, keybuf, sizeof keybuf);
-    if (error != 0) {
-        ERROR("Invalid HMAC-SHA256 key: %s", strerror(errno));
-        goto fail;
-    }
-
-    // The key should be 32 bytes (256 bits).
-    if (len == 0) {
-        ERROR("Invalid (null) secret for key %s", hunks[0]);
-        goto fail;
-    }
-    key->secret = malloc(len);
-    if (key->secret == NULL) {
-        ERROR("Unable to allocate space for secret for key %s", hunks[0]);
-    fail:
-        dns_name_free(key->name);
-        key->name = NULL;
-        return false;
-    }
-    memcpy(key->secret, keybuf, len);
-    key->length = len;
-    key->algorithm = SRP_HMAC_TYPE_SHA256;
-    return true;
-}
-
-config_file_verb_t key_verbs[] = {
-    { NULL, 7, 7, key_handler }
-};
-#define NUMKEYVERBS ((sizeof key_verbs) / sizeof (config_file_verb_t))
-
-hmac_key_t *
-parse_hmac_key_file(const char *filename)
-{
-    hmac_key_t *key = calloc(1, sizeof *key);
-    if (key == NULL) {
-        ERROR("No memory for tsig key structure.");
-        return NULL;
-    }
-    if (!config_parse(key, filename, key_verbs, NUMKEYVERBS)) {
-        ERROR("Failed to parse key file.");
-        free(key);
-        return NULL;
-    }
-    return key;
-}
-
-int
-main(int argc, char **argv)
-{
-    int i;
-    subnet_t *tcp_validators = NULL;
-    udp_validator_t *udp_validators = NULL;
-    udp_validator_t *NULLABLE *NONNULL up = &udp_validators;
-    subnet_t *NULLABLE *NONNULL nt = &tcp_validators;
-    subnet_t *NULLABLE *NONNULL sp;
-    addr_t pref;
-    uint16_t port;
-    socklen_t len, prefalen;
-    char *s, *p;
-    int width;
-    bool got_server = false;
-
-    // Read the configuration from the command line.
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "-s")) {
-            if (got_server) {
-                ERROR("only one authoritative server can be specified.");
-                return usage(argv[0]);
-            }
-            if (++i == argc) {
-                ERROR("-s is missing dns server IP address.");
-                return usage(argv[0]);
-            }
-            len = getipaddr(&dns_server, argv[i]);
-            if (!len) {
-                ERROR("Invalid IP address: %s.", argv[i]);
-                return usage(argv[0]);
-            }
-            if (++i == argc) {
-                ERROR("-s is missing dns server port.");
-                return usage(argv[0]);
-            }
-            port = strtol(argv[i], &s, 10);
-            if (s == argv[i] || s[0] != '\0') {
-                ERROR("Invalid port number: %s", argv[i]);
-                return usage(argv[0]);
-            }
-            if (dns_server.sa.sa_family == AF_INET) {
-                dns_server.sin.sin_port = htons(port);
-            } else {
-                dns_server.sin6.sin6_port = htons(port);
-            }
-            got_server = true;
-        } else if (!strcmp(argv[i], "-k")) {
-            if (++i == argc) {
-                ERROR("-k is missing key file name.");
-                return usage(argv[0]);
-            }
-            key = parse_hmac_key_file(argv[i]);
-            // Someething should already have printed the error message.
-            if (key == NULL) {
-                return 1;
-            }
-        } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "-u")) {
-            if (!strcmp(argv[i], "-u")) {
-                if (++i == argc) {
-                    ERROR("-u is missing interface name.");
-                    return usage(argv[0]);
-                }
-                *up = calloc(1, sizeof **up);
-                if (*up == NULL) {
-                    ERROR("udp_validators: out of memory.");
-                    return usage(argv[0]);
-                }
-                (*up)->ifname = strdup(argv[i]);
-                if ((*up)->ifname == NULL) {
-                    ERROR("udp validators: ifname: out of memory.");
-                    return usage(argv[0]);
-                }
-                sp = &((*up)->subnets);
-            } else {
-                sp = nt;
-            }
-
-            if (++i == argc) {
-                ERROR("%s requires at least one prefix.", argv[i - 1]);
-                return usage(argv[0]);
-            }
-            s = strchr(argv[i], '/');
-            if (s == NULL) {
-                ERROR("%s is not a prefix.", argv[i]);
-                return usage(argv[0]);
-            }
-            *s = 0;
-            ++s;
-            prefalen = getipaddr(&pref, argv[i]);
-            if (!prefalen) {
-                ERROR("%s is not a valid prefix address.", argv[i]);
-                return usage(argv[0]);
-            }
-            width = strtol(s, &p, 10);
-            if (s == p || p[0] != '\0') {
-                ERROR("%s (prefix width) is not a number.", p);
-                return usage(argv[0]);
-            }
-            if (width < 0 ||
-                (pref.sa.sa_family == AF_INET && width > 32) ||
-                (pref.sa.sa_family == AF_INET6 && width > 64)) {
-                ERROR("%s is not a valid prefix length for %s", p,
-                        pref.sa.sa_family == AF_INET ? "IPv4" : "IPv6");
-                return usage(argv[0]);
-            }
-
-            *nt = calloc(1, sizeof **nt);
-            if (!*nt) {
-                ERROR("tcp_validators: out of memory.");
-                return 1;
-            }
-
-            (*nt)->preflen = width;
-            (*nt)->family = pref.sa.sa_family;
-            if (pref.sa.sa_family == AF_INET) {
-                memcpy((*nt)->bytes, &pref.sin.sin_addr, 4);
-            } else {
-                memcpy((*nt)->bytes, &pref.sin6.sin6_addr, 8);
-            }
-
-            // *up will be non-null for -u and null for -t.
-            if (*up) {
-                up = &((*up)->next);
-            } else {
-                nt = sp;
-            }
-        }
-    }
-    if (!got_server) {
-        ERROR("No authoritative DNS server specified to take updates!");
-        return 1;
-    }
-
-    if (!ioloop_init()) {
-        return 1;
-    }
-
-    if (!srp_proxy_listen("home.arpa")) {
-        return 1;
-    }
-
-    // For now, hardcoded, should be configurable
-    service_update_zone = dns_pres_name_parse("home.arpa");
-
-    do {
-        int something = 0;
-        something = ioloop_events(0);
-        INFO("dispatched %d events.", something);
-    } while (1);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-features.h b/ServiceRegistration/srp-features.h
deleted file mode 100644
index b9dcab3..0000000
--- a/ServiceRegistration/srp-features.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* srp-features.h
- *
- * Copyright (c) 2020-2021 Apple 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
- *
- *     https://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.
- *
- * This file contains compile time feature flag which enables or disables
- * different behavior of srp-mdns-proxy.
- */
-
-#ifndef __SRP_FEATURES_H__
-#define __SRP_FEATURES_H__
-
-// SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY: controls whether to initialize dnssd-proxy in srp-mdns-proxy.
-#if defined(BUILD_SRP_MDNS_PROXY) && (BUILD_SRP_MDNS_PROXY == 1)
-// We can only have combined srp-dnssd-proxy if we are building srp-mdns-proxy
-#  define SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY 1
-#    define SRP_FEATURE_DYNAMIC_CONFIGURATION 1
-#else
-#  ifndef SRP_FEATURE_REPLICATION
-#    define SRP_FEATURE_REPLICATION 1
-#  endif
-#  ifndef THREAD_BORDER_ROUTER
-#    define THREAD_BORDER_ROUTER 1
-#  endif
-#  define STUB_ROUTER 1
-#  ifndef SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY
-#    define SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY 1
-#  endif
-#  ifndef SRP_FEATURE_DYNAMIC_CONFIGURATION
-#    define SRP_FEATURE_DYNAMIC_CONFIGURATION 0
-#endif
-#endif
-
-// SRP_FEATURE_CAN_GENERATE_TLS_CERT: controls whether to let srp-mdns-proxy generate the TLS certificate internally.
-#if defined(__APPLE__)
-    // All the Apple platforms support security framework, so it can generate TLS certifcate internally.
-    #define SRP_FEATURE_CAN_GENERATE_TLS_CERT 1
-#else
-    #define SRP_FEATURE_CAN_GENERATE_TLS_CERT 0
-#endif
-
-#if !defined(SRP_FEATURE_NAT64)
-    #define SRP_FEATURE_NAT64 0
-#endif
-
-// At present we never want this, but we're keeping the code around.
-#define SRP_ALLOWS_MDNS_CONFLICTS 0
-
-#endif // __SRP_FEATURES_H__
diff --git a/ServiceRegistration/srp-filedata.c b/ServiceRegistration/srp-filedata.c
deleted file mode 100644
index c02e271..0000000
--- a/ServiceRegistration/srp-filedata.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* srp-ioloop.c
- *
- * Copyright (c) 2019 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.
- *
- * srp host API implementation for Posix using ioloop primitives.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dns_sd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "srp.h"
-#include "srp-api.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-
-bool
-srp_load_file_data(void *host_context, const char *filename, uint8_t *buffer, uint16_t *length, uint16_t buffer_size)
-{
-    off_t flen;
-    ssize_t len;
-    int file;
-    (void)host_context;
-
-    file = open(filename, O_RDONLY);
-    if (file < 0) {
-        ERROR("srp_load_file_data: %s: open: %s", filename, strerror(errno));
-        return false;
-    }
-
-    // Get the length of the file.
-    flen = lseek(file, 0, SEEK_END);
-    lseek(file, 0, SEEK_SET);
-    if (flen > buffer_size) {
-        ERROR("srp_load_file_data: %s: lseek: %s", filename, strerror(errno));
-        close(file);
-        return false;
-    }
-    len = read(file, buffer, (size_t)flen); // Note: flen always positive, no loss of precision.
-    if (len < 0 || len != flen) {
-        if (len < 0) {
-            ERROR("srp_load_file_data: %s: read: %s", filename, strerror(errno));
-        } else {
-            ERROR("srp_load_file_data: %s: short read %d out of %d", filename, (int)len, (int)flen);
-        }
-        close(file);
-        return false;
-    }
-    close(file);
-    *length = (uint16_t)len;
-    return true;
-}
-
-bool
-srp_store_file_data(void *host_context, const char *filename, uint8_t *buffer, uint16_t length)
-{
-    ssize_t len;
-    int file;
-    (void)host_context;
-    file = open(filename, O_WRONLY | O_CREAT, 0600);
-    if (file < 0) {
-        ERROR("srp_store_file_data: %s: %s", filename, strerror(errno));
-        return false;
-   }
-    len = write(file, buffer, length);
-    if (len < 0 || len != length) {
-        if (len < 0) {
-            ERROR("srp_store_file_data: " PUB_S_SRP ": " PUB_S_SRP, filename, strerror(errno));
-        } else {
-            ERROR("srp_store_file_data: short write %d out of %d on file " PUB_S_SRP, (int)len, (int)length, filename);
-        }
-        unlink(filename);
-        close(file);
-        return false;
-    }
-    close(file);
-    return true;
-}
-
-
-bool
-srp_get_last_server(uint16_t *NONNULL rrtype, uint8_t *NONNULL rdata, uint16_t rdlim,
-                    uint8_t *NONNULL port, void *NULLABLE host_context)
-{
-    uint8_t buffer[22];
-    unsigned offset = 0;
-    uint16_t length;
-    uint16_t rdlength;
-
-    if (!srp_load_file_data(host_context, "/var/run/srp-last-server", buffer, &length, sizeof(buffer))) {
-        return false;
-    }
-    if (length < 10) { // rrtype + rdlength + ipv4 address + port
-        ERROR("srp_get_last_server: stored server data is too short: %d", length);
-        return false;
-    }
-    *rrtype = (((uint16_t)buffer[offset]) << 8) | buffer[offset + 1];
-    offset += 2;
-    rdlength = (((uint16_t)buffer[offset]) << 8) | buffer[offset + 1];
-    offset += 2;
-    if ((*rrtype == dns_rrtype_a && rdlength != 4) || (*rrtype == dns_rrtype_aaaa && rdlength != 16)) {
-        ERROR("srp_get_last_server: invalid rdlength %d for %s record",
-              rdlength, *rrtype == dns_rrtype_a ? "A" : "AAAA");
-        return false;
-    }
-    if (length < rdlength + 6) { // rrtype + rdlength + address + port
-        ERROR("srp_get_last_server: stored server data length %d is too short", length);
-        return false;
-    }
-    if (rdlength > rdlim) {
-        ERROR("srp_get_last_server: no space for %s data in provided buffer size %d",
-              *rrtype == dns_rrtype_a ? "A" : "AAAA", rdlim);
-        return false;
-    }
-    memcpy(rdata, &buffer[offset], rdlength);
-    offset += rdlength;
-    memcpy(port, &buffer[offset], 2);
-    return true;
-}
-
-bool
-srp_save_last_server(uint16_t rrtype, uint8_t *NONNULL rdata, uint16_t rdlength,
-                     uint8_t *NONNULL port, void *NULLABLE host_context)
-{
-    dns_towire_state_t towire;
-    uint8_t buffer[24];
-    size_t length;
-    memset(&towire, 0, sizeof(towire));
-    towire.p = buffer;
-    towire.lim = towire.p + sizeof(buffer);
-
-    if (rdlength != 4 && rdlength != 16) {
-        ERROR("srp_save_last_server: invalid IP address length %d", rdlength);
-        return false;
-    }
-    dns_u16_to_wire(&towire, rrtype);
-    dns_u16_to_wire(&towire, rdlength);
-    dns_rdata_raw_data_to_wire(&towire, rdata, rdlength);
-    dns_rdata_raw_data_to_wire(&towire, port, 2);
-
-    if (towire.error) {
-        ERROR("srp_save_last_server: " PUB_S_SRP " at %d (%p:%p:%p) while constructing output buffer",
-              strerror(towire.error), towire.line, towire.p, towire.lim, buffer);
-        return false;
-    }
-
-    length = towire.p - buffer;
-    if (!srp_store_file_data(host_context, "/var/run/srp-last-server", buffer, length)) {
-        return false;
-    }
-    return true;
-}
-
-#ifdef SRP_CRYPTO_MBEDTLS
-int
-srp_load_key_data(void *host_context, const char *key_name, uint8_t *buffer, uint16_t *length, uint16_t buffer_size)
-{
-    if (srp_load_file_data(host_context, key_name, buffer, length, buffer_size)) {
-        return kDNSServiceErr_NoError;
-    }
-    return kDNSServiceErr_NoSuchKey;
-}
-
-int
-srp_store_key_data(void *host_context, const char *key_name, uint8_t *buffer, uint16_t length)
-{
-    if (!srp_store_file_data(host_context, key_name, buffer, length)) {
-        return kDNSServiceErr_Unknown;
-    }
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_remove_key_file(void *host_context, const char *key_name)
-{
-	if (unlink(key_name) < 0) {
-		return kDNSServiceErr_Unknown;
-	}
-	return kDNSServiceErr_NoError;
-}
-#endif // SRP_CRYPTO_MBEDTLS_INTERNAL
diff --git a/ServiceRegistration/srp-gw.h b/ServiceRegistration/srp-gw.h
deleted file mode 100644
index 6a4f3e9..0000000
--- a/ServiceRegistration/srp-gw.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* srp-gw.c
- *
- * Copyright (c) 2019-2021 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
- *
- *     https://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.
- *
- * Structure definitions for the Service Registration Protocol gateway.
- */
-
-typedef struct subnet subnet_t;
-struct subnet {
-    subnet_t *NULLABLE next;
-    uint8_t preflen;
-    uint8_t family;
-    char bytes[8];
-};
-
-typedef struct udp_validator udp_validator_t;
-struct udp_validator {
-    udp_validator_t *NULLABLE next;
-    char *NONNULL ifname;
-    int ifindex;
-    subnet_t *NONNULL subnets;
-};
-
-typedef struct delete delete_t;
-struct delete {
-    delete_t *NULLABLE next;
-    dns_name_t *NONNULL name;
-    dns_name_t *NONNULL zone;
-    bool consumed;
-};
-
-typedef struct host_addr host_addr_t;
-struct host_addr {
-    host_addr_t *NULLABLE next;
-    dns_rr_t rr;
-};
-typedef struct dns_host_description dns_host_description_t;
-struct dns_host_description {
-    dns_name_t *NONNULL name;
-    host_addr_t *NULLABLE addrs;
-    dns_rr_t *NULLABLE key;
-    delete_t *NULLABLE delete;
-    int num_instances;
-};
-
-typedef struct service service_t;
-struct service {
-    service_t *NULLABLE next;
-    service_t *NULLABLE base_type; // A pointer back in the list, or to self
-    dns_rr_t *NONNULL rr; // The service name is rr->name.
-    dns_name_t *NONNULL zone;
-};
-
-typedef struct service_instance service_instance_t;
-struct service_instance {
-    service_instance_t *NULLABLE next;
-    dns_host_description_t *NULLABLE host;
-    dns_name_t *NONNULL name;
-    delete_t *NULLABLE delete;
-    service_t *NONNULL service;
-    int num_instances;
-    dns_rr_t *NULLABLE srv, *NULLABLE txt;
-};
-
-// The update_t structure is used to maintain the ongoing state of a particular DNS Update.
-
-typedef enum update_state update_state_t;
-enum update_state {
-    connect_to_server,              // Establish a connection with the auth server.
-    create_nonexistent,             // Update service instance assuming it's not already there (case 1).
-    refresh_existing,               // Update service instance assuming it's already there and the same (case 2).
-    create_nonexistent_instance,    // Update service instance assuming it's not there
-    refresh_existing_instance,      // Update host assuming it's there and the same
-    create_nonexistent_host,        // Update a host that's not present (and also the services)
-    refresh_existing_host,          // Update a host that's present (and also the services)
-    delete_failed_instance,         // The update failed, so delete service instances that were successfully added.
-};
-
-typedef enum update_event update_event_t;
-enum update_event {
-    update_event_connected,
-    update_event_disconnected,
-    update_event_response_received
-};
-
-typedef struct update update_t;
-struct update {
-    comm_t *NONNULL server;                       // Connection to authoritative server
-    comm_t *NONNULL client;                       // Connection to SRP client (which might just be a UDP socket).
-    update_state_t state;
-    dns_host_description_t *NONNULL host;
-    service_instance_t *NONNULL instances;
-    service_instance_t *NULLABLE instance;        // If we are updating instances one at a time.
-    service_instance_t *NULLABLE added_instances; // Instances we have successfully added.
-    service_t *NONNULL services;
-    dns_name_t *NULLABLE zone_name;               // If NULL, we are processing an update for services.arpa.
-    message_t *NONNULL message;
-    dns_message_t *NONNULL parsed_message;
-    dns_wire_t *NONNULL update;                   // The current update...
-    size_t update_length;
-    size_t update_max;
-    uint8_t fail_rcode;                           // rcode to return after deleting added service instances.
-};
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-ioloop.c b/ServiceRegistration/srp-ioloop.c
deleted file mode 100644
index 0c861fc..0000000
--- a/ServiceRegistration/srp-ioloop.c
+++ /dev/null
@@ -1,1193 +0,0 @@
-/* srp-ioloop.c
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * srp host API implementation for Posix using ioloop primitives.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dns_sd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "srp.h"
-#include "srp-api.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dso-utils.h"
-#include "dso.h"
-
-#include "cti-services.h"
-
-static int lease_time = 0;
-static bool random_leases = false;
-static bool delete_registrations = false;
-static bool use_thread_services = false;
-static bool change_txt_record = false;
-static bool new_ip_dup = false;
-static bool dup_instance_name = false;
-static bool random_txt_record = false;
-static bool remove_added_service = false;
-static bool let_added_service_expire = false;
-static bool expecting_second_add = true;
-static int num_clients = 1;
-static int bogusify_signatures = false;
-static int bogus_remove = false;
-static int push_query = false;
-static int push_unsubscribe = false;
-static int push_exhaust = false;
-static bool test_subtypes = false;
-static bool test_diff_subtypes = false;
-static uint8_t first_bogus_address[] = { 198, 51, 100, 1 }; // RFC 5737 documentaiton prefix TEST-NET-2
-static uint8_t second_bogus_address[] = { 203, 0, 113, 1 }; // RFC 5737 documentaiton prefix TEST-NET-3
-static bool host_only = false;
-extern bool zero_addresses;
-
-const uint64_t thread_enterprise_number = 52627;
-
-cti_connection_t thread_service_context;
-
-static const char *interface_name = NULL;
-static wakeup_t *wait_for_remote_disconnect = NULL;
-static dso_state_t *disconnect_expected = NULL;
-
-#define SRP_IO_CONTEXT_MAGIC 0xFEEDFACEFADEBEEFULL  // BEES!   Everybody gets BEES!
-typedef struct io_context {
-    uint64_t magic_cookie1;
-    wakeup_t *wakeup;
-    void *NONNULL srp_context;
-    comm_t *NULLABLE connection;
-    srp_wakeup_callback_t wakeup_callback;
-    srp_datagram_callback_t datagram_callback;
-    uint64_t magic_cookie2;
-    bool deactivated, closed;
-} io_context_t;
-wakeup_t *remove_wakeup;
-
-typedef struct srp_client {
-    DNSServiceRef sdref;
-    int index;
-    wakeup_t *wakeup;
-    char *name;
-    bool updated_txt_record;
-} srp_client_t;
-
-static void start_push_query(void);
-
-static int
-validate_io_context(io_context_t **dest, void *src)
-{
-    io_context_t *context = src;
-    if (context->magic_cookie1 == SRP_IO_CONTEXT_MAGIC &&
-        context->magic_cookie2 == SRP_IO_CONTEXT_MAGIC)
-   {
-        *dest = context;
-        return kDNSServiceErr_NoError;
-    }
-    return kDNSServiceErr_BadState;
-}
-
-static void
-datagram_callback(comm_t *connection, message_t *message, void *context)
-{
-    (void)connection;
-    io_context_t *io_context = context;
-    if (!io_context->deactivated) {
-        io_context->datagram_callback(io_context->srp_context,
-                                      &message->wire, message->length);
-    }
-}
-
-static void
-wakeup_callback(void *context)
-{
-    io_context_t *io_context;
-    if (validate_io_context(&io_context, context) == kDNSServiceErr_NoError) {
-        INFO("wakeup on context %p srp_context %p", io_context, io_context->srp_context);
-        if (!io_context->deactivated) {
-            io_context->wakeup_callback(io_context->srp_context);
-        }
-    } else {
-        INFO("wakeup with invalid context: %p", context);
-    }
-}
-
-int
-srp_deactivate_udp_context(void *host_context, void *in_context)
-{
-    io_context_t *io_context;
-    int err;
-    (void)host_context;
-
-    err = validate_io_context(&io_context, in_context);
-    if (err == kDNSServiceErr_NoError) {
-        if (io_context->wakeup != NULL) {
-            ioloop_cancel_wake_event(io_context->wakeup);
-            ioloop_wakeup_release(io_context->wakeup);
-        }
-        // Deactivate can be called with a connection still active; in this case, we need to wait for the
-        // cancel event before freeing the structure. Otherwise, we can free it immediately.
-        if (io_context->connection != NULL) {
-            ioloop_comm_cancel(io_context->connection);
-            io_context->deactivated = true;
-            io_context->closed = true;
-        } else {
-            free(io_context);
-        }
-    }
-    return err;
-}
-
-int
-srp_disconnect_udp(void *context)
-{
-    io_context_t *io_context;
-    int err;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        if (io_context->connection) {
-            ioloop_comm_cancel(io_context->connection);
-        }
-        io_context->closed = true;
-    }
-    return err;
-}
-
-static void
-srp_udp_context_canceled(comm_t *UNUSED NONNULL comm, void *NULLABLE context, int UNUSED error)
-{
-    io_context_t *io_context = context;
-
-    if (io_context->connection) {
-        ioloop_comm_release(io_context->connection);
-        io_context->connection = NULL;
-    }
-    if (io_context->deactivated) {
-        free(io_context);
-    }
-}
-
-int
-srp_connect_udp(void *context, const uint8_t *port, uint16_t address_type, const uint8_t *address, uint16_t addrlen)
-{
-    io_context_t *io_context;
-    addr_t remote;
-    int err;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        if (io_context->connection) {
-            ERROR("srp_connect_udp called with non-null I/O context.");
-            return kDNSServiceErr_Invalid;
-        }
-
-        if (address_type == dns_rrtype_a) {
-            if (addrlen != 4) {
-                return kDNSServiceErr_Invalid;
-            }
-            remote.sa.sa_family = AF_INET;
-            memcpy(&remote.sin.sin_addr, address, addrlen);
-#ifndef NOT_HAVE_SA_LEN
-            remote.sa.sa_len = sizeof remote.sin;
-#endif
-            memcpy(&remote.sin.sin_port, port, 2);
-        } else {
-            if (addrlen != 16) {
-                return kDNSServiceErr_Invalid;
-            }
-            remote.sa.sa_family = AF_INET6;
-            memcpy(&remote.sin6.sin6_addr, address, addrlen);
-#ifndef NOT_HAVE_SA_LEN
-            remote.sa.sa_len = sizeof remote.sin;
-#endif
-            memcpy(&remote.sin6.sin6_port, port, 2);
-        }
-
-        io_context->connection = ioloop_connection_create(&remote, false, false, false, true, datagram_callback,
-                                                          NULL, srp_udp_context_canceled, NULL, io_context);
-        if (io_context->connection == NULL) {
-            return kDNSServiceErr_NoMemory;
-        }
-    }
-    return err;
-}
-
-int
-srp_make_udp_context(void *host_context, void **p_context, srp_datagram_callback_t callback, void *context)
-{
-    (void)host_context;
-
-    io_context_t *io_context = calloc(1, sizeof *io_context);
-    if (io_context == NULL) {
-        return kDNSServiceErr_NoMemory;
-    }
-    io_context->magic_cookie1 = io_context->magic_cookie2 = SRP_IO_CONTEXT_MAGIC;
-    io_context->datagram_callback = callback;
-    io_context->srp_context = context;
-
-    io_context->wakeup = ioloop_wakeup_create();
-    if (io_context->wakeup == NULL) {
-        free(io_context);
-        return kDNSServiceErr_NoMemory;
-    }
-
-    *p_context = io_context;
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_set_wakeup(void *host_context, void *context, int milliseconds, srp_wakeup_callback_t callback)
-{
-    int err;
-    io_context_t *io_context;
-    (void)host_context;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        io_context->wakeup_callback = callback;
-        INFO("srp_set_wakeup on context %p, srp_context %p", io_context, io_context->srp_context);
-        ioloop_add_wake_event(io_context->wakeup, io_context, wakeup_callback, NULL, milliseconds);
-    }
-    return err;
-}
-
-int
-srp_cancel_wakeup(void *host_context, void *context)
-{
-    int err;
-    io_context_t *io_context;
-    (void)host_context;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        ioloop_cancel_wake_event(io_context->wakeup);
-    }
-    return err;
-}
-
-int
-srp_send_datagram(void *host_context, void *context, void *message, size_t message_length)
-{
-    int err;
-    struct iovec iov;
-    io_context_t *io_context;
-    (void)host_context;
-
-    memset(&iov, 0, sizeof iov);
-    iov.iov_base = message;
-    iov.iov_len = message_length;
-
-    if (bogusify_signatures) {
-        ((uint8_t *)message)[message_length - 10] = ~(((uint8_t *)message)[message_length - 10]);
-    }
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        if (!ioloop_send_message(io_context->connection, message, &iov, 1)) {
-            return kDNSServiceErr_Unknown;
-        }
-    }
-    return err;
-}
-
-static void
-interface_callback(void *context, const char *NONNULL name,
-                   const addr_t *NONNULL address, const addr_t *NONNULL netmask,
-                   uint32_t flags, enum interface_address_change event_type)
-{
-    bool drop = false;
-    uint8_t *rdata;
-    uint16_t rdlen;
-    uint16_t rrtype;
-    cti_service_vec_t *cti_services = context;
-
-    (void)netmask;
-    (void)index;
-    (void)event_type;
-
-    if (address->sa.sa_family == AF_INET) {
-        rrtype = dns_rrtype_a;
-        rdata = (uint8_t *)&address->sin.sin_addr;
-        rdlen = 4;
-
-        // Should use IN_LINKLOCAL and IN_LOOPBACK macros here, but for some reason they are not present on
-        // OpenWRT.
-        if (rdata[0] == 127) {
-            drop = true;
-        } else if (rdata[0] == 169 && rdata[1] == 254) {
-            drop = true;
-        }
-    } else if (address->sa.sa_family == AF_INET6) {
-        rrtype = dns_rrtype_aaaa;
-        rdata = (uint8_t *)&address->sin6.sin6_addr;
-        rdlen = 16;
-        if (IN6_IS_ADDR_LOOPBACK(&address->sin6.sin6_addr)) {
-            drop = true;
-        } else if (IN6_IS_ADDR_LINKLOCAL(&address->sin6.sin6_addr)) {
-            drop = true;
-        }
-    } else {
-        return;
-    }
-    if (drop) {
-        if (address->sa.sa_family == AF_INET) {
-            IPv4_ADDR_GEN_SRP(rdata, ipv4_rdata_buf);
-            DEBUG("interface_callback: ignoring " PUB_S_SRP " " PRI_IPv4_ADDR_SRP, name,
-                  IPv4_ADDR_PARAM_SRP(rdata, ipv4_rdata_buf));
-        } else if (address->sa.sa_family == AF_INET6) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(rdata, ipv6_rdata_buf);
-            DEBUG("interface_callback: ignoring " PUB_S_SRP " " PRI_SEGMENTED_IPv6_ADDR_SRP, name,
-                  SEGMENTED_IPv6_ADDR_PARAM_SRP(rdata, ipv6_rdata_buf));
-        } else {
-            INFO("ignoring with non-v4/v6 address" PUB_S_SRP, name);
-        }
-        return;
-    }
-
-    if (address->sa.sa_family == AF_INET) {
-        IPv4_ADDR_GEN_SRP(rdata, ipv4_rdata_buf);
-        DEBUG("interface_callback: " PUB_S_SRP " " PRI_IPv4_ADDR_SRP " %x", name,
-              IPv4_ADDR_PARAM_SRP(rdata, ipv4_rdata_buf), flags);
-    } else if (address->sa.sa_family == AF_INET6) {
-        SEGMENTED_IPv6_ADDR_GEN_SRP(rdata, ipv6_rdata_buf);
-        DEBUG("interface_callback: " PUB_S_SRP " " PRI_SEGMENTED_IPv6_ADDR_SRP " %x", name,
-              SEGMENTED_IPv6_ADDR_PARAM_SRP(rdata, ipv6_rdata_buf), flags);
-    } else {
-        DEBUG("interface_callback: " PUB_S_SRP "<none IPv4/IPv6 address> %x", name, flags);
-    }
-
-    // This is a workaround for a bug in the utun0 code, where packets sent to the IP address of the local
-    // thread interface are dropped and do not reach the SRP server. To address this, if we find a service
-    // that is on a local IPv6 address, we replace the address with ::1.
-    if (cti_services != NULL && rrtype == dns_rrtype_aaaa) {
-        size_t i;
-        for (i = 0; i < cti_services->num; i++) {
-            cti_service_t *cti_service = cti_services->services[i];
-            // Look for SRP service advertisements only.
-            if (IS_SRP_SERVICE(cti_service)) {
-                // Local IP address?
-                if (!memcmp(cti_service->server, rdata, 16)) {
-                    // ::
-                    memset(cti_service->server, 0, 15);
-                    // 1
-                    cti_service->server[15] = 1;
-                }
-            }
-        }
-    }
-
-    srp_add_interface_address(rrtype, rdata, rdlen);
-}
-
-static void
-remove_callback(void *context)
-{
-    srp_client_t *client = context;
-    if (bogus_remove) {
-        srp_set_hostname("bogus-api-test", NULL);
-    }
-    srp_deregister(client);
-}
-
-static void
-second_register_callback(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                         const char *name, const char *regtype, const char *domain, void *context)
-{
-    srp_client_t *client = context;
-
-    (void)regtype;
-    (void)flags;
-    (void)name;
-    (void)regtype;
-    (void)domain;
-    INFO("Second Register Reply for %s: %d", client->name, errorCode);
-
-    if (errorCode == kDNSServiceErr_NoError) {
-        if (expecting_second_add) {
-            expecting_second_add = false;
-            if (remove_added_service) {
-                srp_deregister_instance(sdref);
-                srp_network_state_stable(NULL);
-            } else if (let_added_service_expire) {
-                DNSServiceRefDeallocate(sdref);
-            }
-        } else {
-            // Test succeeded
-            exit(0);
-        }
-    } else {
-        // Test failed
-        exit(1);
-    }
-}
-
-
-static void
-register_callback(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                  const char *name, const char *regtype, const char *domain, void *context)
-{
-    srp_client_t *client = context;
-
-    (void)regtype;
-    (void)flags;
-    (void)name;
-    (void)regtype;
-    (void)domain;
-    INFO("Register Reply for %s: %d", client->name, errorCode);
-
-    if (errorCode == kDNSServiceErr_NoError && change_txt_record && !client->updated_txt_record) {
-        TXTRecordRef txt;
-        const void *txt_data = NULL;
-        uint16_t txt_len = 0;
-        char txt_buf[128];
-
-        TXTRecordCreate(&txt, sizeof(txt_buf), txt_buf);
-        TXTRecordSetValue(&txt, "foo", 1, "1");
-        TXTRecordSetValue(&txt, "bar", 3, "1.1");
-        txt_data = TXTRecordGetBytesPtr(&txt);
-        txt_len = TXTRecordGetLength(&txt);
-
-        (void)DNSServiceUpdateRecord(sdref, NULL, 0, txt_len, txt_data, 0);
-        client->updated_txt_record = true;
-        srp_network_state_stable(NULL);
-        return;
-    }
-
-    if (errorCode == kDNSServiceErr_NoError && delete_registrations) {
-        client->wakeup = ioloop_wakeup_create();
-        if (client->wakeup == NULL) {
-            ERROR("Unable to allocate a wakeup for %s.", client->name);
-            exit(1);
-        }
-
-        // Do a remove in five seconds.
-        ioloop_add_wake_event(client->wakeup, client, remove_callback, NULL, 5000);
-    }
-
-    // We get this with the duplicate instance name. In this case, we change the host IP address. This validates
-    // the bit of code in srp-mdns-proxy that removes the added address when the update fails--when we look up the
-    // registered address, we should see only the second bogus address, not the first.
-    if (errorCode == kDNSServiceErr_NameConflict) {
-        char nnbuf[128];
-        char rtbuf[128];
-        srp_delete_interface_address(dns_rrtype_a, first_bogus_address, sizeof(first_bogus_address));
-        srp_add_interface_address(dns_rrtype_a, second_bogus_address, sizeof(second_bogus_address));
-        strcpy(nnbuf, name);
-        strcpy(rtbuf, regtype);
-        nnbuf[0] = 'a';
-        INFO("changing service instance name from " PRI_S_SRP " to " PRI_S_SRP " type " PRI_S_SRP, name, nnbuf, rtbuf);
-        DNSServiceRefDeallocate(sdref);
-        int err = DNSServiceRegister(&sdref, kDNSServiceFlagsNoAutoRename, 0, nnbuf, rtbuf, 0, 0, htons(1234),
-                                     0, NULL, register_callback, client);
-        if (err != kDNSServiceErr_NoError) {
-            ERROR("DNSServiceRegister rename failed: %d", err);
-            exit(1);
-        }
-        srp_network_state_stable(NULL);
-    }
-}
-
-comm_t *dso_connection;
-typedef struct connection_list connection_list_t;
-struct connection_list {
-    connection_list_t *next;
-    comm_t *connection;
-};
-connection_list_t *dso_connection_list;
-uint16_t subscribe_xid;
-uint16_t keepalive_xid;
-
-static void
-send_push_unsubscribe(void)
-{
-    struct iovec iov;
-    INFO("unsubscribe");
-    dns_wire_t dns_message;
-    uint8_t *buffer = (uint8_t *)&dns_message;
-    dns_towire_state_t towire;
-    dso_message_t message;
-    dso_make_message(&message, buffer, sizeof(dns_message), dso_connection->dso, true, false, 0, 0, NULL);
-    memset(&towire, 0, sizeof(towire));
-    towire.p = &buffer[DNS_HEADER_SIZE];
-    towire.lim = towire.p + (sizeof(dns_message) - DNS_HEADER_SIZE);
-    towire.message = &dns_message;
-    dns_u16_to_wire(&towire, kDSOType_DNSPushUnsubscribe);
-    dns_rdlength_begin(&towire);
-    dns_full_name_to_wire(NULL, &towire, "_hap._udp.openthread.thread.home.arpa");
-    dns_u16_to_wire(&towire, dns_rrtype_ptr);
-    dns_u16_to_wire(&towire, dns_qclass_in);
-    dns_rdlength_end(&towire);
-
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - buffer;
-    iov.iov_base = buffer;
-    ioloop_send_message(dso_connection, NULL, &iov, 1);
-    subscribe_xid = dns_message.id; // We need this to identify the response.
-
-    // Send a keepalive message so that we can get the response, since the unsubscribe is not a response-requiring request.
-    dso_make_message(&message, buffer, sizeof(dns_message), dso_connection->dso, false, false, 0, 0, NULL);
-    memset(&towire, 0, sizeof(towire));
-    towire.p = &buffer[DNS_HEADER_SIZE];
-    towire.lim = towire.p + (sizeof(dns_message) - DNS_HEADER_SIZE);
-    towire.message = &dns_message;
-    dns_u16_to_wire(&towire, kDSOType_Keepalive);
-    dns_rdlength_begin(&towire);
-    dns_u32_to_wire(&towire, 600);
-    dns_u32_to_wire(&towire, 600);
-    dns_rdlength_end(&towire);
-    keepalive_xid = dns_message.id;
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - buffer;
-    iov.iov_base = buffer;
-    ioloop_send_message(dso_connection, NULL, &iov, 1);
-}
-
-static void
-dso_remote_disconnect_didnt_happen(void *UNUSED context)
-{
-    INFO("remote disconnect didn't happen");
-    exit(1);
-}
-
-static void
-handle_retry_delay(dso_state_t *dso, uint32_t delay)
-{
-    INFO("Got our retry delay, %ums...", delay);
-    wait_for_remote_disconnect = ioloop_wakeup_create();
-    if (!wait_for_remote_disconnect) {
-        INFO("can't wait for remote disconnect.");
-        exit(1);
-    }
-    // Wait six seconds for remote disconnect, which should happen in five.
-    ioloop_add_wake_event(wait_for_remote_disconnect, NULL, dso_remote_disconnect_didnt_happen, NULL, 6 * 1000);
-    disconnect_expected = dso;
-}
-
-static void
-dso_message(message_t *message, dso_state_t *dso, bool response)
-{
-#if PRINT_TO_STDERR
-    char name[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-    char ptrname[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-#endif
-    unsigned offset, max;
-    dns_rr_t rr;
-    uint8_t *message_bytes;
-
-    switch(dso->primary.opcode) {
-    case kDSOType_RetryDelay:
-        if (response) {
-            INFO("server sent a retry delay TLV as a response.");
-            exit(1);
-        }
-        dso_retry_delay(dso, &message->wire);
-        break;
-
-    case kDSOType_Keepalive:
-        if (response) {
-            INFO("Keepalive response from server, rcode = %d", dns_rcode_get(&message->wire));
-            exit(0);
-        } else {
-            INFO("Keepalive from server");
-        }
-        break;
-
-    case kDSOType_DNSPushSubscribe:
-        if (response) {
-            // This is a protocol error--the response isn't supposed to contain a primary TLV.
-            INFO("DNS Push response from server, rcode = %d", dns_rcode_get(&message->wire));
-            exit(1);
-        } else {
-            INFO("Unexpected DNS Push request from server, rcode = %d", dns_rcode_get(&message->wire));
-        }
-        break;
-
-    case kDSOType_DNSPushUpdate:
-        // DNS Push Updates are never responses.
-        // DNS Push updates are compressed, so we can't just parse data out of the primary--we need to align
-        // our parse with the start of the message data.
-        message_bytes = (uint8_t *)message->wire.data;
-        offset = (unsigned)(dso->primary.payload - message_bytes); // difference can never be greater than sizeof(message->wire).
-        max = offset + dso->primary.length;
-        while (offset < max) {
-            if (!dns_rr_parse(&rr, message_bytes, max, &offset, true, true)) {
-                // Should have emitted an error earlier
-                break;
-            }
-#if PRINT_TO_STDERR
-            dns_name_print(rr.name, name, sizeof(name));
-            if (rr.type != dns_rrtype_ptr) {
-                fprintf(stderr, "%s: type %u class %u ttl %" PRIu32 "\n", name, rr.type, rr.qclass, rr.ttl);
-            } else {
-                dns_name_print(rr.data.ptr.name, ptrname, sizeof(ptrname));
-                fprintf(stderr, "%s IN PTR %s\n", name, ptrname);
-            }
-#endif
-        }
-        if (push_unsubscribe) {
-            send_push_unsubscribe();
-        } else if (!push_exhaust) {
-            exit(0);
-        }
-        break;
-
-    case kDSOType_NoPrimaryTLV: // No Primary TLV
-        if (response) {
-            if (message->wire.id == subscribe_xid) {
-                int rcode = dns_rcode_get(&message->wire);
-                INFO("DNS Push Subscribe response from server, rcode = %d", rcode);
-                if (rcode != dns_rcode_noerror) {
-                    exit(0);
-                }
-                if (push_exhaust) {
-                    start_push_query();
-                }
-            } else if (message->wire.id == keepalive_xid) {
-                int rcode = dns_rcode_get(&message->wire);
-                INFO("DNS Keepalive response from server, rcode = %d", rcode);
-                exit(0);
-            } else {
-                int rcode = dns_rcode_get(&message->wire);
-                INFO("Unexpected DSO response from server, rcode = %d", rcode);
-            }
-        } else {
-            INFO("DSO request with no primary TLV.");
-            exit(1);
-        }
-        break;
-
-    default:
-        INFO("dso_message: unexpected primary TLV %d", dso->primary.opcode);
-        dso_simple_response(dso_connection, NULL, &message->wire, dns_rcode_dsotypeni);
-        break;
-    }
-}
-
-static void
-dso_event_callback(void *UNUSED context, void *event_context, dso_state_t *dso, dso_event_type_t eventType)
-{
-    message_t *message;
-    dso_query_receive_context_t *response_context;
-    dso_disconnect_context_t *disconnect_context;
-
-    switch(eventType)
-    {
-    case kDSOEventType_DNSMessage:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Message (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DNSResponse:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Response (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DSOMessage:
-        INFO("DSO Message (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        message = event_context;
-        dso_message(message, dso, false);
-        break;
-    case kDSOEventType_DSOResponse:
-        INFO("DSO Response (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        response_context = event_context;
-        message = response_context->message_context;
-        dso_message(message, dso, true);
-        break;
-
-    case kDSOEventType_Finalize:
-        INFO("Finalize");
-        break;
-
-    case kDSOEventType_Connected:
-        INFO("Connected to " PRI_S_SRP, dso->remote_name);
-        break;
-
-    case kDSOEventType_ConnectFailed:
-        INFO("Connection to " PRI_S_SRP " failed", dso->remote_name);
-        break;
-
-    case kDSOEventType_Disconnected:
-        INFO("Connection to " PRI_S_SRP " disconnected", dso->remote_name);
-        if (dso == disconnect_expected) {
-            INFO("remote end disconnected as expected.");
-            exit(0);
-        }
-        break;
-    case kDSOEventType_ShouldReconnect:
-        INFO("Connection to " PRI_S_SRP " should reconnect (not for a server)", dso->remote_name);
-        break;
-    case kDSOEventType_Inactive:
-        INFO("Inactivity timer went off, closing connection.");
-        break;
-    case kDSOEventType_Keepalive:
-        INFO("should send a keepalive now.");
-        break;
-    case kDSOEventType_KeepaliveRcvd:
-        INFO("keepalive received.");
-        break;
-    case kDSOEventType_RetryDelay:
-        disconnect_context = event_context;
-        INFO("retry delay received, %d seconds", disconnect_context->reconnect_delay);
-        handle_retry_delay(dso, disconnect_context->reconnect_delay);
-        break;
-    }
-}
-
-static void
-dso_connected(comm_t *connection, void *UNUSED context)
-{
-    struct iovec iov;
-    INFO("connected");
-    connection->dso = dso_state_create(false, 1, connection->name, dso_event_callback,
-                                       dso_connection, NULL, dso_connection);
-    if (connection->dso == NULL) {
-        ERROR("can't create dso state object.");
-        exit(1);
-    }
-    dns_wire_t dns_message;
-    uint8_t *buffer = (uint8_t *)&dns_message;
-    dns_towire_state_t towire;
-    dso_message_t message;
-    dso_make_message(&message, buffer, sizeof(dns_message), connection->dso, false, false, 0, 0, NULL);
-    memset(&towire, 0, sizeof(towire));
-    towire.p = &buffer[DNS_HEADER_SIZE];
-    towire.lim = towire.p + (sizeof(dns_message) - DNS_HEADER_SIZE);
-    towire.message = &dns_message;
-    dns_u16_to_wire(&towire, kDSOType_DNSPushSubscribe);
-    dns_rdlength_begin(&towire);
-    dns_full_name_to_wire(NULL, &towire, "_hap._udp.openthread.thread.home.arpa");
-    dns_u16_to_wire(&towire, dns_rrtype_ptr);
-    dns_u16_to_wire(&towire, dns_qclass_in);
-    dns_rdlength_end(&towire);
-
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - buffer;
-    iov.iov_base = buffer;
-    ioloop_send_message(dso_connection, NULL, &iov, 1);
-    subscribe_xid = dns_message.id; // We need this to identify the response.
-}
-
-static void
-dso_disconnected(comm_t *UNUSED connection, void *UNUSED context, int UNUSED error)
-{
-    fprintf(stderr, "disconnected.");
-    exit(0);
-}
-
-static void
-dso_datagram_callback(comm_t *connection, message_t *message, void *UNUSED context)
-{
-    // If this is a DSO message, see if we have a session yet.
-    switch(dns_opcode_get(&message->wire)) {
-    case dns_opcode_dso:
-        if (connection->dso == NULL) {
-            INFO("dso message received with no DSO object on connection " PRI_S_SRP, connection->name);
-            exit(1);
-        }
-        dso_message_received(connection->dso, (uint8_t *)&message->wire, message->length, message);
-        return;
-        break;
-    }
-    INFO("datagram on connection " PRI_S_SRP " not handled, type = %d.",
-         connection->name, dns_opcode_get(&message->wire));
-}
-
-static void
-start_push_query(void)
-{
-    // If we can (should always be able to) remember the list of connections we've created.
-    if (dso_connection != NULL) {
-        connection_list_t *connection = calloc(1, sizeof (*connection));
-        if (connection != NULL) {
-            connection->connection = dso_connection;
-            connection->next = dso_connection_list;
-            dso_connection_list = connection;
-        }
-    }
-
-    addr_t address;
-    memset(&address, 0, sizeof(address));
-    address.sa.sa_family = AF_INET;
-    address.sin.sin_port = htons(853);
-    address.sin.sin_addr.s_addr = htonl(0x7f000001);  // localhost.
-                                                      // tls, stream, stable, opportunistic
-    dso_connection = ioloop_connection_create(&address, true,   true,   true, true,
-                                              dso_datagram_callback, dso_connected, dso_disconnected, NULL, NULL);
-    if (dso_connection == NULL) {
-        ERROR("Unable to create dso connection.");
-        exit(1);
-    }
-}
-
-static void
-usage(void)
-{
-    fprintf(stderr,
-            "srp-client [--lease-time <seconds>] [--client-count <client count>] [--server <address>%%<port>]\n"
-            "           [--push-query] [--push-unsubscribe]\n"
-            "           [--random-leases] [--delete-registrations] [--use-thread-services] [--log-stderr]\n"
-            "           [--interface <interface name>] [--bogusify-signatures] [--remove-added-service]\n"
-            "           [--dup-instance-name] [--service-port <port number>] [--expire-added-service]\n"
-            "           [--random-txt-record] [--bogus-remove] [--test-subtypes] [--test-diff-subtypes]\n"
-            "           [--new-ip-dup] [--push-exhaust]\n");
-    exit(1);
-}
-
-
-static void
-cti_service_list_callback(void *UNUSED context, cti_service_vec_t *services, cti_status_t status)
-{
-    size_t i;
-
-    if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
-        INFO("disconnected");
-        exit(1);
-    }
-
-    if (!new_ip_dup && !zero_addresses) {
-        srp_start_address_refresh();
-        ioloop_map_interface_addresses(interface_name, services, interface_callback);
-    }
-    for (i = 0; i < services->num; i++) {
-        cti_service_t *cti_service = services->services[i];
-        // Look for SRP service advertisements only.
-        if (IS_SRP_SERVICE(cti_service)) {
-            srp_add_server_address(&cti_service->server[16], dns_rrtype_aaaa, cti_service->server, 16);
-        }
-    }
-    if (!new_ip_dup && !zero_addresses) {
-        srp_finish_address_refresh(NULL);
-    }
-    srp_network_state_stable(NULL);
-}
-
-int
-main(int argc, char **argv)
-{
-
-    uint8_t server_address[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1 };
-    uint8_t bogus_address[16] = { 0xfc,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1 };
-        // { 0x26, 0x20, 0x01, 0x49, 0x00, 0x0f, 0x1a, 0x4d, 0x04, 0xff, 0x61, 0x5a, 0xa2, 0x2a, 0xab, 0xe8 };
-    int err;
-    DNSServiceRef sdref;
-    int *nump;
-    char *end;
-    (void)argc;
-    (void)argv;
-    int i;
-    bool have_server_address = false;
-    bool log_stderr = false;
-    char instance_name[128];
-    const char *service_type = "_ipps._tcp";
-    uint16_t service_port = 0;
-    bool bogus_server = false;
-
-    ioloop_init();
-
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "--lease-time")) {
-            nump = &lease_time;
-        number:
-            if (i + 1 == argc) {
-                usage();
-            }
-            *nump = (uint32_t)strtoul(argv[i + 1], &end, 10);
-            if (end == argv[i + 1] || end[0] != 0) {
-                usage();
-            }
-            i++;
-        } else if (!strcmp(argv[i], "--client-count")) {
-            nump = &num_clients;
-            goto number;
-        } else if (!strcmp(argv[i], "--interface")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            interface_name = argv[i + 1];
-            i++;
-        } else if (!strcmp(argv[i], "--server")) {
-            char *percent;
-            uint8_t addrbuf[16];
-            uint16_t addrtype = dns_rrtype_aaaa;
-            int addrlen = 16;
-
-            if (i + 1 == argc) {
-                usage();
-            }
-            percent = strchr(argv[i + 1], '%');
-            if (percent == NULL || percent[1] == 0) {
-                usage();
-            }
-            *percent = 0;
-            percent++;
-
-            const unsigned long in_server_port = strtoul(percent, &end, 10);
-            if (in_server_port > UINT16_MAX || end == percent || end[0] != 0) {
-                usage();
-            }
-            uint8_t server_port[2];
-            server_port[0] = ((uint16_t)in_server_port) >> 8;
-            server_port[1] = ((uint16_t)in_server_port) & 255;
-
-            if (inet_pton(AF_INET6, argv[i + 1], addrbuf) < 1) {
-                if (inet_pton(AF_INET, argv[i + 1], addrbuf) < 1) {
-                    usage();
-                } else {
-                    addrtype = dns_rrtype_a;
-                    addrlen = 4;
-                }
-            }
-            srp_add_server_address(server_port, addrtype, addrbuf, addrlen);
-            have_server_address = true;
-            i++;
-        } else if (!strcmp(argv[i], "--random-leases")) {
-            random_leases = true;
-        } else if (!strcmp(argv[i], "--delete-registrations")) {
-            delete_registrations = true;
-        } else if (!strcmp(argv[i], "--use-thread-services")) {
-            use_thread_services = true;
-        } else if (!strcmp(argv[i], "--dup-instance-name")) {
-            dup_instance_name = true;
-        } else if (!strcmp(argv[i], "--new-ip-dup")) {
-            new_ip_dup = true;
-        } else if (!strcmp(argv[i], "--log-stderr")) {
-            log_stderr = true;
-            OPENLOG("srp-client", true);
-        } else if (!strcmp(argv[i], "--change-txt-record")) {
-            change_txt_record = true;
-        } else if (!strcmp(argv[i], "--random-txt-record")) {
-            random_txt_record = true;
-        } else if (!strcmp(argv[i], "--remove-added-service")) {
-            remove_added_service = true;
-        } else if (!strcmp(argv[i], "--expire-added-service")) {
-            let_added_service_expire = true;
-        } else if (!strcmp(argv[1], "--bogus-server-test")) {
-            bogus_server = true;
-        } else if (!strcmp(argv[i], "--bogusify-signatures")) {
-            bogusify_signatures = true;
-        } else if (!strcmp(argv[i], "--bogus-remove")) {
-            bogus_remove = true;
-        } else if (!strcmp(argv[i], "--push-query")) {
-            push_query = true;
-        } else if (!strcmp(argv[i], "--push-unsubscribe")) {
-            push_unsubscribe = true;
-        } else if (!strcmp(argv[i], "--push-exhaust")) {
-            push_exhaust = true;
-        } else if (!strcmp(argv[i], "--test-subtypes")) {
-            test_subtypes = true;
-        } else if (!strcmp(argv[i], "--test-diff-subtypes")) {
-            test_diff_subtypes = true;
-        } else if (!strcmp(argv[i], "--host-only")) {
-            host_only = true;
-        } else if (!strcmp(argv[i], "--zero-addresses")) {
-            zero_addresses = true;
-        } else if (!strcmp(argv[i], "--service-type")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            service_type = argv[i + 1];
-            i++;
-        } else if (!strcmp(argv[i], "--service-port")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-
-            const int in_service_port = atoi(argv[i + 1]);
-            if (in_service_port == 0 || in_service_port > UINT16_MAX) {
-                fprintf(stderr, "Service port number %d is out of range or invalid, should be in (0, 65535].\n",
-                        in_service_port);
-                usage();
-            }
-
-            service_port = (uint16_t)in_service_port;
-            i++;
-        } else {
-            usage();
-        }
-    }
-
-    if (!log_stderr) {
-        OPENLOG("srp-client", false);
-    }
-
-    // If we're asked to do a push query, we're not actually going to act as an SRP client, just do the push query.
-    if (push_query || push_exhaust) {
-        start_push_query();
-        ioloop();
-        exit(1);
-    }
-
-    if (!use_thread_services && !new_ip_dup && !zero_addresses) {
-        ioloop_map_interface_addresses(interface_name, NULL, interface_callback);
-    }
-
-    if (!have_server_address && !use_thread_services) {
-        uint8_t port[] = { 0, 53 };
-        if (bogus_server) {
-            srp_add_server_address(port, dns_rrtype_aaaa, bogus_address, 16);
-        }
-        srp_add_server_address(port, dns_rrtype_aaaa, server_address, 16);
-    }
-
-    if (dup_instance_name) {
-        num_clients = 2;
-        strcpy(instance_name, "dup-name-test");
-    }
-    if (new_ip_dup || zero_addresses) {
-        // Set up the test to validate the "failed update removes address" code in srp-mdns-proxy.
-        srp_add_interface_address(dns_rrtype_a, first_bogus_address, sizeof(first_bogus_address));
-        if (zero_addresses) {
-            srp_delete_interface_address(dns_rrtype_a, first_bogus_address, sizeof(first_bogus_address));
-        }
-    }
-
-    for (i = 0; i < num_clients; i++) {
-        srp_client_t *client;
-        char hnbuf[128];
-        TXTRecordRef txt;
-        const void *txt_data = NULL;
-        uint16_t txt_len = 0;
-        char txt_buf[128];
-
-        client = calloc(1, sizeof(*client));
-        if (client == NULL) {
-            ERROR("no memory for client %d", i);
-            exit(1);
-        }
-
-        if (num_clients == 1) {
-            strcpy(hnbuf, "srp-api-test");
-        } else {
-            snprintf(hnbuf, sizeof(hnbuf), "srp-api-test-%d", i);
-        }
-        client->name = strdup(hnbuf);
-        if (client->name == NULL) {
-            ERROR("No memory for client name %s", hnbuf);
-            exit(1);
-        }
-        client->index = i;
-
-        srp_host_init(client);
-        srp_set_hostname(hnbuf, NULL);
-
-        if (random_leases) {
-            int random_lease_time = 30 + srp_random16() % 1800; // random
-            INFO("Client %d, lease time = %d", i, random_lease_time);
-            srp_set_lease_times(random_lease_time, 7 * 24 * 3600); // random host lease, 7 day key lease
-        } else if (lease_time > 0) {
-            srp_set_lease_times(lease_time, 7 * 24 * 3600); // specified host lease, 7 day key lease
-        } else if (let_added_service_expire) {
-            srp_set_lease_times(30, 30); // Use short lease times so the lease expires quickly.
-        }
-
-        if (change_txt_record) {
-            TXTRecordCreate(&txt, sizeof(txt_buf), txt_buf);
-            TXTRecordSetValue(&txt, "foo", 1, "0");
-            TXTRecordSetValue(&txt, "bar", 3, "1.1");
-            txt_data = TXTRecordGetBytesPtr(&txt);
-            txt_len = TXTRecordGetLength(&txt);
-        }
-        if (random_txt_record) {
-            char rbuf[6];
-            snprintf(rbuf, sizeof(rbuf), "%u", srp_random16());
-            TXTRecordCreate(&txt, sizeof(txt_buf), txt_buf);
-            TXTRecordSetValue(&txt, "foo", strlen(rbuf), rbuf);
-            INFO("TXTRecordSetValue(..., \"foo\", %zd, %s)", strlen(rbuf), rbuf);
-            txt_data = TXTRecordGetBytesPtr(&txt);
-            txt_len = TXTRecordGetLength(&txt);
-        }
-
-        if (service_port == 0) {
-            // If no service port is specified (0 indicates that port is unspecified), the index i will be used to
-            // generate the port number.
-            service_port = (i % UINT16_MAX) == 0 ? 1 : (i % UINT16_MAX);
-        }
-
-        if (!test_subtypes && !test_diff_subtypes && !host_only) {
-            err = DNSServiceRegister(&sdref, new_ip_dup ? kDNSServiceFlagsNoAutoRename : 0, 0,
-                                     dup_instance_name ? instance_name : hnbuf, service_type, 0, 0, htons(service_port),
-                                     txt_len, txt_data, register_callback, client);
-            if (err != kDNSServiceErr_NoError) {
-                ERROR("DNSServiceRegister failed: %d", err);
-                exit(1);
-            }
-        }
-        if (remove_added_service || let_added_service_expire) {
-            expecting_second_add = true;
-            err = DNSServiceRegister(&sdref, 0, 0, hnbuf, "_second._tcp,foo", 0, 0, htons(service_port),
-                                     txt_len, txt_data, second_register_callback, client);
-            if (err != kDNSServiceErr_NoError) {
-                ERROR("second DNSServiceRegister failed: %d", err);
-                exit(1);
-            }
-        }
-        // Here we register two services with subtypes. The idea is to see that the srp parsing code does not
-        // associate the second subtype with the first service instance and report an error. In order to
-        // attempt to trigger the error, we need the service instance name of the second service instance
-        // to be different.
-        if (test_subtypes || test_diff_subtypes) {
-            expecting_second_add = true;
-            err = DNSServiceRegister(&sdref, 0, 0, hnbuf, "_ipps._tcp,subtype",
-                                     0, 0, htons(service_port), txt_len, txt_data, register_callback, client);
-            if (err != kDNSServiceErr_NoError) {
-                ERROR("DNSServiceRegister failed: %d", err);
-                exit(1);
-            }
-            if (test_diff_subtypes) {
-                err = DNSServiceRegister(&sdref, 0, 0, hnbuf, "_second._tcp,othersub",
-                                         0, 0, htons(service_port), txt_len, txt_data, second_register_callback, client);
-                if (err != kDNSServiceErr_NoError) {
-                    ERROR("DNSServiceRegister failed: %d", err);
-                    exit(1);
-                }
-            } else {
-                char shnbuf[132];
-                snprintf(shnbuf, sizeof(shnbuf), "foo-%s", hnbuf);
-                err = DNSServiceRegister(&sdref, 0, 0, shnbuf, "_ipps._tcp,othersub",
-                                         0, 0, htons(service_port), txt_len, txt_data, second_register_callback, client);
-                if (err != kDNSServiceErr_NoError) {
-                    ERROR("DNSServiceRegister failed: %d", err);
-                    exit(1);
-                }
-            }
-        }
-    }
-
-    if (use_thread_services) {
-        cti_get_service_list(&thread_service_context, NULL, cti_service_list_callback, NULL);
-    } else {
-        srp_network_state_stable(NULL);
-    }
-    ioloop();
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-log.c b/ServiceRegistration/srp-log.c
deleted file mode 100644
index a88639a..0000000
--- a/ServiceRegistration/srp-log.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* srp-log.c
- *
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- *
- * This file contains the functions that help to create better logs.
- */
-
-#include "srp-log.h"
-
-#ifndef THREAD_DEVKIT_ADK
-#include <netinet/in.h> // For struct in_addr and struct in6_addr used in "dns-msg.h".
-#endif
-#include "dns-msg.h" // For dns_qclass_xxx and dns_rrtype_xxx.
-
-//======================================================================================================================
-// MARK: - Functions
-
-const char *
-dns_qclass_to_string(const uint16_t qclass)
-{
-#define CASE_TO_STR(s) case dns_qclass_ ## s: return (#s)
-    switch(qclass)
-    {
-        CASE_TO_STR(in);
-        CASE_TO_STR(chaos);
-        CASE_TO_STR(hesiod);
-        CASE_TO_STR(none);
-        CASE_TO_STR(any);
-    }
-#undef CASE_TO_STR
-    FAULT("Invalid qclass - qclass: %u", qclass);
-    return "<INVALID dns_qclass>";
-}
-
-//======================================================================================================================
-
-const char *
-dns_rrtype_to_string(const uint16_t rrtype)
-{
-#define CASE_TO_STR(s) case dns_rrtype_ ## s: return (#s)
-    switch(rrtype)
-    {
-        CASE_TO_STR(a);
-        CASE_TO_STR(ns);
-        CASE_TO_STR(md);
-        CASE_TO_STR(mf);
-        CASE_TO_STR(cname);
-        CASE_TO_STR(soa);
-        CASE_TO_STR(mb);
-        CASE_TO_STR(mg);
-        CASE_TO_STR(mr);
-        CASE_TO_STR(null);
-        CASE_TO_STR(wks);
-        CASE_TO_STR(ptr);
-        CASE_TO_STR(hinfo);
-        CASE_TO_STR(minfo);
-        CASE_TO_STR(mx);
-        CASE_TO_STR(txt);
-        CASE_TO_STR(rp);
-        CASE_TO_STR(afsdb);
-        CASE_TO_STR(x25);
-        CASE_TO_STR(isdn);
-        CASE_TO_STR(rt);
-        CASE_TO_STR(nsap);
-        CASE_TO_STR(nsap_ptr);
-        CASE_TO_STR(sig);
-        CASE_TO_STR(key);
-        CASE_TO_STR(px);
-        CASE_TO_STR(gpos);
-        CASE_TO_STR(aaaa);
-        CASE_TO_STR(loc);
-        CASE_TO_STR(nxt);
-        CASE_TO_STR(eid);
-        CASE_TO_STR(nimloc);
-        CASE_TO_STR(srv);
-        CASE_TO_STR(atma);
-        CASE_TO_STR(naptr);
-        CASE_TO_STR(kx);
-        CASE_TO_STR(cert);
-        CASE_TO_STR(a6);
-        CASE_TO_STR(dname);
-        CASE_TO_STR(sink);
-        CASE_TO_STR(opt);
-        CASE_TO_STR(apl);
-        CASE_TO_STR(ds);
-        CASE_TO_STR(sshfp);
-        CASE_TO_STR(ipseckey);
-        CASE_TO_STR(rrsig);
-        CASE_TO_STR(nsec);
-        CASE_TO_STR(dnskey);
-        CASE_TO_STR(dhcid);
-        CASE_TO_STR(nsec3);
-        CASE_TO_STR(nsec3param);
-        CASE_TO_STR(tlsa);
-        CASE_TO_STR(smimea);
-        CASE_TO_STR(hip);
-        CASE_TO_STR(ninfo);
-        CASE_TO_STR(rkey);
-        CASE_TO_STR(talink);
-        CASE_TO_STR(cds);
-        CASE_TO_STR(cdnskey);
-        CASE_TO_STR(openpgpkey);
-        CASE_TO_STR(csync);
-        CASE_TO_STR(zonemd);
-        CASE_TO_STR(svcb);
-        CASE_TO_STR(https);
-        CASE_TO_STR(spf);
-        CASE_TO_STR(uinfo);
-        CASE_TO_STR(uid);
-        CASE_TO_STR(gid);
-        CASE_TO_STR(unspec);
-        CASE_TO_STR(nid);
-        CASE_TO_STR(l32);
-        CASE_TO_STR(l64);
-        CASE_TO_STR(lp);
-        CASE_TO_STR(eui48);
-        CASE_TO_STR(eui64);
-        CASE_TO_STR(tkey);
-        CASE_TO_STR(tsig);
-        CASE_TO_STR(ixfr);
-        CASE_TO_STR(axfr);
-        CASE_TO_STR(mailb);
-        CASE_TO_STR(maila);
-        CASE_TO_STR(any);
-        CASE_TO_STR(uri);
-        CASE_TO_STR(caa);
-        CASE_TO_STR(avc);
-        CASE_TO_STR(doa);
-        CASE_TO_STR(amtrelay);
-        CASE_TO_STR(ta);
-        CASE_TO_STR(dlv);
-    }
-#undef CASE_TO_STR
-    FAULT("Invalid dns_rrtype - rrtype: %u", rrtype);
-    return "<INVALID dns_rrtype>";
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-log.h b/ServiceRegistration/srp-log.h
deleted file mode 100644
index 3603859..0000000
--- a/ServiceRegistration/srp-log.h
+++ /dev/null
@@ -1,431 +0,0 @@
-/* srp-log.h
- *
- * Copyright (c) 2020-2021 Apple 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
- *
- *     https://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.
- *
- * This file contains the utilities that are used to print log that
- * redacts private information about the user, and function prototypes that
- * helps to create better logs.
- */
-
-
-#ifndef __SRP_LOG_H__
-#define __SRP_LOG_H__
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef POSIX_BUILD
-#include <limits.h>
-#include <sys/param.h>
-#endif
-
-#ifdef __APPLE__
-#include <os/log.h> // For os_log related APIs
-#endif // #ifdef __APPLE__
-
-#ifdef DEBUG
-    #undef DEBUG
-    // #define DEBUG_VERBOSE
-#endif
-
-// We always want this until we start shipping
-#define DEBUG_VERBOSE
-
-//======================================================================================================================
-// MARK: - Log Macros
-
-#ifdef FUZZING
-    #define OPENLOG(progname, consolep)
-    #define ERROR(fmt, ...)
-    #define INFO(fmt, ...)
-    #define DEBUG(fmt, ...)
-    #define FAULT(fmt, ...)
-#elif defined(THREAD_DEVKIT_ADK)
-
-    #include "srp-platform.h"
-
-    #define OPENLOG(progname, consolep) srp_openlog(option)
-    #define ERROR(fmt, ...)   srp_log_error(fmt, ##__VA_ARGS__)
-    #define INFO(fmt, ...)    srp_log_info(fmt, ##__VA_ARGS__)
-    #ifdef DEBUG_VERBOSE
-        #define DEBUG(fmt, ...) srp_log_debug(fmt, ##__VA_ARGS__)
-    #else
-        #define DEBUG(fmt, ...)
-    #endif // DEBUG VERBOSE
-    #define FAULT(fmt, ...) srp_log_error(fmt, ##__VA_ARGS__)
-    #define NO_CLOCK
-#else // ifdef THREAD_DEVKIT_ADK
-
-    #ifdef LOG_FPRINTF_STDERR
-        #define OPENLOG(progname, consolep) do { (void)(consolep); (void)progname; } while (0)
-        #define ERROR(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
-        #define INFO(fmt, ...)  fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
-        #define FAULT(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
-        #ifdef DEBUG_VERBOSE
-            #ifdef IOLOOP_MACOS
-                int get_num_fds(void);
-            #endif // ifdef IOLOOP_MACOS
-            #define DEBUG(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
-        #else // ifdef DEBUG_VERBOSE
-            #define DEBUG(fmt, ...)
-        #endif
-        #define FAULT(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
-    #else // ifdef LOG_FPRINTF_STDERR
-        #include <syslog.h>
-
-        // Apple device always has OS_LOG support.
-        #ifdef __APPLE__
-            #define OS_LOG_ENABLED 1
-            #include <os/log.h>
-
-            // Define log level
-            #define LOG_TYPE_FAULT      OS_LOG_TYPE_FAULT
-            #define LOG_TYPE_ERROR      OS_LOG_TYPE_ERROR
-            #define LOG_TYPE_DEFAULT    OS_LOG_TYPE_DEFAULT
-            #define LOG_TYPE_DEBUG      OS_LOG_TYPE_DEBUG
-            // Define log macro
-            #define log_with_component_and_type(CATEGORY, LEVEL, FORMAT, ...) \
-                os_log_with_type((CATEGORY), (LEVEL), ("%{public}s: " FORMAT), __FUNCTION__, ##__VA_ARGS__)
-
-            #define OPENLOG(progname, consolep) \
-                do { if (consolep) { putenv("ACTIVITY_LOG_STDERR=1"); } (void)progname; } while (0)
-            #define FAULT(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_FAULT, \
-                                            FORMAT, ##__VA_ARGS__)
-            #define ERROR(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_ERROR, \
-                                            FORMAT, ##__VA_ARGS__)
-
-            #ifdef DEBUG_VERBOSE
-                #ifdef DEBUG_FD_LEAKS
-                    int get_num_fds(void);
-                    #define INFO(FORMAT, ...) \
-                        do { \
-                            int foo = get_num_fds(); \
-                            log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_DEFAULT, "%d " FORMAT, foo, \
-                                ##__VA_ARGS__); \
-                        } while(0)
-                #else // ifdef IOLOOP_MACOS
-                    #define INFO(FORMAT, ...)   log_with_component_and_type(OS_LOG_DEFAULT, \
-                                                    LOG_TYPE_DEFAULT, FORMAT, ##__VA_ARGS__)
-                #endif // ifdef IOLOOP_MACOS
-
-                #define DEBUG(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, \
-                                                LOG_TYPE_DEBUG, FORMAT, ##__VA_ARGS__)
-            #else // ifdef DEBUG_VERBOSE
-                #define INFO(FORMAT, ...)   log_with_component_and_type(OS_LOG_DEFAULT, \
-                                                LOG_TYPE_DEFAULT, FORMAT, ##__VA_ARGS__)
-                #define DEBUG(FORMAT, ...)  do {} while(0)
-            #endif // ifdef DEBUG_VERBOSE
-        #else // ifdef __APPLE__
-            #define OS_LOG_ENABLED 0
-
-            #define OPENLOG(progname, consolep) openlog(progname, (consolep ? LOG_PERROR : 0) | LOG_PID, LOG_DAEMON)
-            #define FAULT(fmt, ...) syslog(LOG_CRIT, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-            #define ERROR(fmt, ...) syslog(LOG_ERR, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-
-            #ifdef DEBUG_VERBOSE
-                #ifdef DEBUG_FD_LEAKS
-                    int get_num_fds(void);
-                    #define INFO(fmt, ...) \
-                        do { \
-                            int foo = get_num_fds(); \
-                            syslog(LOG_INFO, "%s: %d " fmt, __FUNCTION__, foo, ##__VA_ARGS__); \
-                        } while (0)
-                #else // ifdef IOLOOP_MACOS
-                    #define INFO(fmt, ...)  syslog(LOG_INFO, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-                #endif // ifdef IOLOOP_MACOS
-                #define DEBUG(fmt, ...) syslog(LOG_DEBUG, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-            #else // ifdef DEBUG_VERBOSE
-                #define INFO(fmt, ...)  syslog(LOG_INFO, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-                #define DEBUG(fmt, ...) do {} while(0)
-            #endif // ifdef DEBUG_VERBOSE
-        #endif // ifdef __APPLE__
-    #endif // ifdef LOG_FPRINTF_STDERR
-#endif // ifdef THREAD_DEVKIT_ADK
-
-//======================================================================================================================
-// MARK: - Log Specifiers
-/**
- * With the logging routines defined above, the logging macros are defined to facilitate the log redaction enforced by
- * os_log on Apple platforms. By using the specifier "%{mask.hash}", the "<private>" text in the logs of customer device
- * would be shown as a hashing value, which could be used as a way to associate other SRP logs even if it's redacted.
- *
- * On Apple platforms, the current existing log routines will be defined as:
- * #define log_with_component_and_type(CATEGORY, LEVEL, FORMAT, ...) os_log_with_type((CATEGORY), (LEVEL), (FORMAT), \
- *                                                                      ##__VA_ARGS__)
- * #define ERROR(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_ERROR, FORMAT, ##__VA_ARGS__)
- * #define INFO(FORMAT, ...)   log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_DEFAULT, FORMAT, ##__VA_ARGS__)
- * #define DEBUG(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_DEBUG, FORMAT, ##__VA_ARGS__)
- * And to follow the same log level with os_log, FAULT() is defined.
- * #define FAULT(FORMAT, ...)  log_with_component_and_type(OS_LOG_DEFAULT, LOG_TYPE_FAULT, FORMAT, ##__VA_ARGS__)
- * Therefore, all the previous logs would be put under OS_LOG_DEFAULT category.
- * FAULT level lof will be mapped to  LOG_TYPE_FAULT in os_log.
- * ERROR level log will be mapped to LOG_TYPE_ERROR in os_log.
- * INFO level log will be mapped to LOG_TYPE_DEFAULT in os_log.
- * DEBUG level log woll be mapped to LOG_TYPE_DEBUG in os_log.
- *
- * On platforms other than Apple, syslog will be used to write logs.
- * FAULT level lof will be mapped to  LOG_CRIT in syslog.
- * ERROR level log will be mapped to LOG_ERR in syslog.
- * INFO level log will be mapped to LOG_INFO in syslog.
- * DEBUG level log woll be mapped to LOG_DEBUG in syslog.
- *
- * The defined specifiers are:
- * String specifier:
- *      PUB_S_SRP: Use this in the format string when trying to log string and do not want it to be redacted.
- *      PRI_S_SRP: Use this when trying to log string and redact it to a hash string.
- *      Usage:
- *          INFO("Public string: " PUB_S_SRP, ", private string: " PRI_S_SRP, string_ptr, string_ptr);
- *
- * DNS name (with dns_label_t type) specifier:
- *      DNS_NAME_GEN_SRP: Always call this before logging DNS name.
- *      PUB_DNS_NAME_SRP: Use this in the format string when trying to log DNS name and do not want it to be redacted.
- *      PRI_DNS_NAME_SRP: Use this in the format string when trying to log DNS name and redact it to a hash string.
- *      DNS_NAME_PARAM_SRP: Always use DNS_NAME_PARAM_SRP in the paramter list.
- *      Usage:
- *          DNS_NAME_GEN_SRP(dns_name_ptr, dns_name_buf);
- *          INFO("Public DNS name: " PUB_DNS_NAME_SRP, ", private DNS name: " PRI_DNS_NAME_SRP,
- *              DNS_NAME_PARAM_SRP(dns_name_ptr, dns_name_buf), DNS_NAME_PARAM_SRP(dns_name_ptr, dns_name_buf));
- *
- * IPv4 address specifier (with in_addr * type or a pointer to uint8_t[4]):
- *      IPv4_ADDR_GEN_SRP: Always call this before logging IPv4 address.
- *      PUB_IPv4_ADDR_SRP: Use this in the format string when trying to log IPv4 address and do not want it to be
- *                         redacted.
- *      PRI_IPv4_ADDR_SRP: Use this in the format string when trying to log IPv4 address and redact it to a hash string.
- *      IPv4_ADDR_PARAM_SRP: Always use IPv4_ADDR_PARAM_SRP in the paramter list.
- *      Usage:
- *          IPv4_ADDR_GEN_SRP(in_addr_ptr_1, in_addr_buf_1);
- *          IPv4_ADDR_GEN_SRP(in_addr_ptr_2, in_addr_buf_2);
- *          INFO("Public IPv4 address: " PUB_IPv4_ADDR_SRP, ", private IPv4 address: " PRI_IPv4_ADDR_SRP,
- *              IPv4_ADDR_PARAM_SRP(in_addr_ptr_1, in_addr_buf_1), IPv4_ADDR_PARAM_SRP(in_addr_ptr_2, in_addr_buf_2));
- *
- * IPv6 address specifier (with in6_addr * type or a pointer to uint8_t[16]):
- *      IPv6_ADDR_GEN_SRP: Always call this before logging IPv6 address.
- *      PUB_IPv6_ADDR_SRP: Use this in the format string when trying to log IPv6 address and do not want it to be
- *                         redacted.
- *      PRI_IPv6_ADDR_SRP: Use this in the format string when trying to log IPv6 address and redact it to a hash string.
- *      IPv6_ADDR_PARAM_SRP: Always use IPv6_ADDR_PARAM_SRP in the paramter list.
- *      Usage:
- *          IPv6_ADDR_GEN_SRP(in6_addr_ptr_1, in6_addr_buf_1);
- *          IPv6_ADDR_GEN_SRP(in6_addr_ptr_2, in6_addr_buf_2);
- *          INFO("Public IPv6 address: " PUB_IPv6_ADDR_SRP, ", private IPv6 address: " PRI_IPv6_ADDR_SRP,
- *              IPv6_ADDR_PARAM_SRP(in6_addr_ptr_1, in6_addr_buf_1),
- *              IPv6_ADDR_PARAM_SRP(in6_addr_ptr_2, in6_addr_buf_2));
- *
- * Segmented IPv6  address specifier (with in6_addr * type or a pointer to uint8_t[16]):
- *      SEGMENTED_IPv6_ADDR_GEN_SRP: Always call this before logging segmented IPv6 address.
- *      PUB_SEGMENTED_IPv6_ADDR_SRP: Use this in the format string when trying to log segmented IPv6 address and do not
- *                                   want it to be redacted.
- *      PRI_SEGMENTED_IPv6_ADDR_SRP: Use this in the format string when trying to log segmented IPv6 address and redact
- *                                   it to a hash string.
- *      SEGMENTED_IPv6_ADDR_PARAM_SRP: Always use SEGMENTED_IPv6_ADDR_PARAM_SRP in the paramter list.
- *      Usage:
- *          SEGMENTED_IPv6_ADDR_GEN_SRP(in6_addr_ptr_1, in6_addr_buf_1);
- *          SEGMENTED_IPv6_ADDR_GEN_SRP(in6_addr_ptr_2, in6_addr_buf_2);
- *          INFO("Public IPv6 address: " PUB_SEGMENTED_IPv6_ADDR_SRP, ", private IPv6 address: "
- *               PRI_SEGMENTED_IPv6_ADDR_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(in6_addr_ptr_1, in6_addr_buf_1),
- *               SEGMENTED_IPv6_ADDR_PARAM_SRP(in6_addr_ptr_2, in6_addr_buf_2));
- *      Note:
- *          Segmented IPv6 is prefered when logging IPv6 address in SRP, because the address is divided to: 48 bit
- *          prefix, 16 bit subnet, 64 bit host, which makes it easier to match the prefix even when log redaction is
- *          turned on and the address is hashed to a string.
- *
- * IPv6 prefix specifier (with a pointer to uint8_t[] array):
- *      IPv6_PREFIX_GEN_SRP: Always call this before logging IPv6 prefix (which is also segmented).
- *      PUB_IPv6_PREFIX_SRP: Use this in the format string when trying to log IPv6 prefix and do not want it to be
- *                           redacted.
- *      PRI_IPv6_PREFIX_SRP: Use this in the format string when trying to log IPv6 prefix and redact it to a hash
- *                           string.
- *      IPv6_PREFIX_PARAM_SRP: Always use IPv6_PREFIX_PARAM_SRP in the paramter list.
- *      Usage:
- *          IPv6_PREFIX_GEN_SRP(in6_prefix_ptr_1, sizeof(in6_prefix_1), in6_prefix_buf_1);
- *          IPv6_PREFIX_GEN_SRP(in6_prefix_ptr_2, sizeof(in6_prefix_2), in6_prefix_buf_2);
- *          INFO("Public IPv6 prefix: " PUB_IPv6_PREFIX_SRP, ", private IPv6 prefix: " PRI_IPv6_PREFIX_SRP,
- *              IPv6_PREFIX_PARAM_SRP(in6_prefix_buf_1), IPv6_PREFIX_PARAM_SRP(in6_prefix_buf_2));
- *
- * Mac address specifier (with a pointer to uint8_t[6] array):
- *      PUB_MAC_ADDR_SRP: Use this in the format string when trying to log Mac address and do not want it to be
- *                        redacted.
- *      PRI_MAC_ADDR_SRP: Use this in the format string when trying to log Mac address and redact it to a hash string.
- *      MAC_ADDR_PARAM_SRP: Always use MAC_ADDR_PARAM_SRP in the paramter list.
- *      Usage:
- *          INFO("Public MAC address: " PUB_MAC_ADDR_SRP, ", private MAC address: " PRI_MAC_ADDR_SRP,
- *              MAC_ADDR_PARAM_SRP(mac_addr), MAC_ADDR_PARAM_SRP(mac_addr));
- */
-
-// Helper macro to display if the correspoding IPv6 is ULA (Unique Local Address), LUA (Link Local Address)
-// or GUA (Global Unicast Address).
-// ULA starts with FC00::/7.
-// LUA starts with fe80::/10.
-// GUA starts with 2000::/3.
-#define IS_IPV6_ADDR_ULA(ADDR) ( ((ADDR)[0] & 0xFE) == 0xFC )
-#define IS_IPV6_ADDR_LUA(ADDR) ( ((ADDR)[0] == 0xFE) && ((uint8_t)(ADDR)[1] & 0xC0) == 0x80 )
-#define IS_IPV6_ADDR_GUA(ADDR) ( ((ADDR)[0] & 0xE0) == 0x20 )
-#define ADDRESS_RANGE_STR(ADDR) (                                                           \
-                                    IS_IPV6_ADDR_ULA(ADDR) ?                                \
-                                        " (ULA)" :                                          \
-                                        (( IS_IPV6_ADDR_LUA(ADDR) ) ?                       \
-                                                " (LUA)" :                                  \
-                                                ( IS_IPV6_ADDR_GUA(ADDR) ? " (GUA)" : "" )) \
-                                )
-
-// Logging macros
-#if OS_LOG_ENABLED
-    // Define log specifier
-    // String
-    #define PUB_S_SRP "%{public}s"
-    #define PRI_S_SRP "%{private, mask.hash}s"
-    // DNS name, when the pointer to DNS name is NULL, <NULL> will be logged.
-    #define DNS_NAME_GEN_SRP(NAME, BUF_NAME) \
-        char BUF_NAME[DNS_MAX_NAME_SIZE_ESCAPED + 1]; \
-        if (NAME != NULL) { \
-            dns_name_print(NAME, BUF_NAME, sizeof(BUF_NAME)); \
-        } else { \
-            snprintf(BUF_NAME, sizeof(BUF_NAME), "<null>"); \
-        }
-    #define PUB_DNS_NAME_SRP PUB_S_SRP
-    #define PRI_DNS_NAME_SRP PRI_S_SRP
-    #define DNS_NAME_PARAM_SRP(NAME, BUF) (BUF)
-    // IP address
-    // IPv4
-    #define IPv4_ADDR_GEN_SRP(ADDR, BUF_NAME) do {} while(0)
-    #define PUB_IPv4_ADDR_SRP "%{public, network:in_addr}.4P"
-    #define PRI_IPv4_ADDR_SRP "%{private, mask.hash, network:in_addr}.4P"
-    #define IPv4_ADDR_PARAM_SRP(ADDR, BUF) ((uint8_t *)ADDR)
-    // IPv6
-    #define IPv6_ADDR_GEN_SRP(ADDR, BUF_NAME) do {} while(0)
-    #define PUB_IPv6_ADDR_SRP "%{public, network:in6_addr}.16P%{public}s"
-    #define PRI_IPv6_ADDR_SRP "%{private, mask.hash, network:in6_addr}.16P%{public}s"
-    #define IPv6_ADDR_PARAM_SRP(ADDR, BUF) ((uint8_t *)ADDR), ADDRESS_RANGE_STR((uint8_t *)ADDR)
-    // Segmented IPv6
-    // Subnet part can always be public.
-    #define SEGMENTED_IPv6_ADDR_GEN_SRP(ADDR, BUF_NAME) do {} while(0)
-    #define PUB_SEGMENTED_IPv6_ADDR_SRP "{%{public, srp:in6_addr_segment}.6P%{public}s, " \
-                                            "%{public, srp:in6_addr_segment}.2P, " \
-                                            "%{public, srp:in6_addr_segment}.8P}"
-    #define PRI_SEGMENTED_IPv6_ADDR_SRP "{%{private, mask.hash, srp:in6_addr_segment}.6P%{public}s, " \
-                                            "%{public, mask.hash, srp:in6_addr_segment}.2P, " \
-                                            "%{private, mask.hash, srp:in6_addr_segment}.8P}"
-    #define SEGMENTED_IPv6_ADDR_PARAM_SRP(ADDR, BUF) ((uint8_t *)(ADDR)), ADDRESS_RANGE_STR((uint8_t *)ADDR), \
-                                                        ((uint8_t *)(ADDR) + 6), ((uint8_t *)(ADDR) + 8)
-    // MAC address
-    #define PUB_MAC_ADDR_SRP "%{public, srp:mac_addr}.6P"
-    #define PRI_MAC_ADDR_SRP "%{private, mask.hash, srp:mac_addr}.6P"
-    #define MAC_ADDR_PARAM_SRP(ADDR) ((uint8_t *)ADDR)
-
-#else // ifdef OS_LOG_ENABLED
-    // When os_log is not available, all logs would be public.
-    // Define log specifier
-    // String
-    #define PUB_S_SRP "%s"
-    #define PRI_S_SRP PUB_S_SRP
-    // DNS name, when the pointer to DNS name is NULL, <NULL> will be logged.
-    #if defined(MDNS_NO_STRICT) && (!MDNS_NO_STRICT)
-        #define SRP_LOG_STRNCPY_STRICT mdns_strlcpy
-    #else
-        #define SRP_LOG_STRNCPY_STRICT strlcpy
-    #endif
-    #ifdef IOLOOP_MACOS
-        #define SRP_LOG_STRNCPY SRP_LOG_STRNCPY_STRICT
-    #else
-        #define SRP_LOG_STRNCPY strncpy
-    #endif // IOLOOP_MACOS
-    #define DNS_NAME_GEN_SRP(NAME, BUF_NAME) \
-        char BUF_NAME[DNS_MAX_NAME_SIZE_ESCAPED + 1]; \
-        if (NAME != NULL) { \
-            dns_name_print(NAME, BUF_NAME, sizeof(BUF_NAME)); \
-        } else { \
-            SRP_LOG_STRNCPY(BUF_NAME, "<null>", \
-                            sizeof("<null>") < sizeof(BUF_NAME) ? sizeof("<null>") : sizeof(BUF_NAME)); \
-        }
-    #define PUB_DNS_NAME_SRP "%s"
-    #define PRI_DNS_NAME_SRP PUB_DNS_NAME_SRP
-    #define DNS_NAME_PARAM_SRP(NAME, BUF) (BUF)
-    // IP address
-    // IPv4
-    #define IPv4_ADDR_GEN_SRP(ADDR, BUF_NAME) char BUF_NAME[INET_ADDRSTRLEN]; \
-                                                    inet_ntop(AF_INET, ((uint8_t *)ADDR), BUF_NAME, sizeof(BUF_NAME))
-    #define PUB_IPv4_ADDR_SRP "%s"
-    #define PRI_IPv4_ADDR_SRP PUB_IPv4_ADDR_SRP
-    #define IPv4_ADDR_PARAM_SRP(ADDR, BUF) (BUF)
-    // IPv6
-    #define IPv6_ADDR_GEN_SRP(ADDR, BUF_NAME) char BUF_NAME[INET6_ADDRSTRLEN]; \
-                                                    inet_ntop(AF_INET6, ((uint8_t *)ADDR), BUF_NAME, sizeof(BUF_NAME))
-    #define PUB_IPv6_ADDR_SRP "%s%s"
-    #define PRI_IPv6_ADDR_SRP PUB_IPv6_ADDR_SRP
-    #define IPv6_ADDR_PARAM_SRP(ADDR, BUF) (BUF), ADDRESS_RANGE_STR((uint8_t *)ADDR)
-    // Segmented IPv6
-    #define SEGMENTED_IPv6_ADDR_GEN_SRP(ADDR, BUF_NAME) IPv6_ADDR_GEN_SRP(ADDR, BUF_NAME)
-
-    #define PUB_SEGMENTED_IPv6_ADDR_SRP PUB_IPv6_ADDR_SRP
-    #define PRI_SEGMENTED_IPv6_ADDR_SRP PRI_IPv6_ADDR_SRP
-    #define SEGMENTED_IPv6_ADDR_PARAM_SRP(ADDR, BUF) IPv6_ADDR_PARAM_SRP(ADDR, BUF)
-    // MAC address
-    #define PUB_MAC_ADDR_SRP "%02x:%02x:%02x:%02x:%02x:%02x"
-    #define PRI_MAC_ADDR_SRP PUB_MAC_ADDR_SRP
-    #define MAC_ADDR_PARAM_SRP(ADDR) ((uint8_t *)ADDR)[0], ((uint8_t *)ADDR)[1], ((uint8_t *)ADDR)[2], \
-                                        ((uint8_t *)ADDR)[3], ((uint8_t *)ADDR)[4], ((uint8_t *)ADDR)[5]
-
-#endif // ifdef OS_LOG_ENABLED
-
-// IPv6 ULA 48-bit prefix
-#define IPv6_PREFIX_GEN_SRP(PREFIX, PREFIX_LEN, BUF_NAME) \
-    struct in6_addr _in6_addr_##BUF_NAME##_full_addr = {0}; \
-    memcpy(_in6_addr_##BUF_NAME##_full_addr.s6_addr, (PREFIX), \
-        MIN(sizeof(_in6_addr_##BUF_NAME##_full_addr.s6_addr), (PREFIX_LEN))); \
-    SEGMENTED_IPv6_ADDR_GEN_SRP(_in6_addr_##BUF_NAME##_full_addr.s6_addr, BUF_NAME);
-#define PUB_IPv6_PREFIX_SRP PUB_SEGMENTED_IPv6_ADDR_SRP
-#define PRI_IPv6_PREFIX_SRP PRI_SEGMENTED_IPv6_ADDR_SRP
-#define IPv6_PREFIX_PARAM_SRP(BUF_NAME) SEGMENTED_IPv6_ADDR_PARAM_SRP(_in6_addr_##BUF_NAME##_full_addr.s6_addr, \
-                                            BUF_NAME)
-
-//======================================================================================================================
-// MARK: - To String Helpers
-
-/*!
- *  @brief
- *      Convert DNS question class to its corresponding text description.
- *
- *  @param qclass
- *      The DNS question class value in the DNS message.
- *
- *  @result
- *      The corresponding text description for the given DNS question class if it is valid. Otherwise, an error string will be returned.
- */
-const char *
-dns_qclass_to_string(uint16_t qclass);
-
-/*!
- *  @brief
- *      Convert DNS record type to its corresponding text description.
- *
- *  @param rrtype
- *      The DNS record type value of the DNS record.
- *
- *  @result
- *      The corresponding text description for the given DNS record type if it is valid. Otherwise, an error string will be returned.
- */
-const char *
-dns_rrtype_to_string(uint16_t rrtype);
-
-#endif // __SRP_LOG_H__
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-mdns-proxy.c b/ServiceRegistration/srp-mdns-proxy.c
deleted file mode 100644
index d9e47e7..0000000
--- a/ServiceRegistration/srp-mdns-proxy.c
+++ /dev/null
@@ -1,3244 +0,0 @@
-/* srp-mdns-proxy.c
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains the SRP Advertising Proxy, which is an SRP Server
- * that offers registered addresses using mDNS.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dns_sd.h>
-#include <net/if.h>
-#include <inttypes.h>
-#include <sys/resource.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dnssd-proxy.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "config-parse.h"
-#include "cti-services.h"
-#include "route.h"
-#include "adv-ctl-server.h"
-#include "srp-replication.h"
-#include "ioloop-common.h"
-
-
-#if SRP_FEATURE_NAT64
-#include "nat64-macos.h"
-#endif
-
-static const char local_suffix_ld[] = ".local";
-static const char *local_suffix = &local_suffix_ld[1];
-
-//======================================================================================================================
-// MARK: - Forward references
-
-static void register_host_record_completion(DNSServiceRef sdref, DNSRecordRef rref,
-                                            DNSServiceFlags flags, DNSServiceErrorType error_code, void *context);
-static void register_instance_completion(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType error_code,
-                                         const char *name, const char *regtype, const char *domain, void *context);
-static void update_from_host(adv_host_t *host);
-static void start_host_update(adv_host_t *host);
-static void prepare_update(adv_host_t *host, client_update_t *client_update);
-static void delete_host(void *context);
-static void lease_callback(void *context);
-static void adv_host_finalize(adv_host_t *host);
-static void adv_record_finalize(adv_record_t *record);
-static void adv_update_finalize(adv_update_t *update);
-
-//======================================================================================================================
-// MARK: - Functions
-
-static void
-remove_shared_record(srp_server_t *server_state, adv_record_t *record)
-{
-    RETAIN_HERE(record);
-    if (record->rref != NULL && record->shared_txn != 0 &&
-        record->shared_txn == (intptr_t)server_state->shared_registration_txn)
-    {
-        DNSServiceRemoveRecord(server_state->shared_registration_txn->sdref, record->rref, 0);
-        RELEASE_HERE(record, adv_record_finalize); // Release the DNSService callback's reference
-    }
-    record->rref = NULL;
-    record->shared_txn = 0;
-    RELEASE_HERE(record, adv_record_finalize);
-}
-
-
-static void
-adv_record_finalize(adv_record_t *record)
-{
-    // We should not be able to get to the finalize function without having removed the rref, because the DNSService
-    // callback always holds a reference to the record.
-    if (record->update != NULL) {
-        RELEASE_HERE(record->update, adv_update_finalize);
-    }
-    if (record->host != NULL) {
-        RELEASE_HERE(record->host, adv_host_finalize);
-    }
-    free(record->rdata);
-    free(record);
-}
-
-static void
-adv_instance_finalize(adv_instance_t *instance)
-{
-    if (instance->txn != NULL) {
-        ioloop_dnssd_txn_cancel(instance->txn);
-        ioloop_dnssd_txn_release(instance->txn);
-    }
-    if (instance->txt_data != NULL) {
-        free(instance->txt_data);
-    }
-    if (instance->instance_name != NULL) {
-        free(instance->instance_name);
-    }
-    if (instance->service_type != NULL) {
-        free(instance->service_type);
-    }
-    if (instance->host != NULL) {
-        RELEASE_HERE(instance->host, adv_host_finalize);
-        instance->host = NULL;
-    }
-    if (instance->message != NULL) {
-        ioloop_message_release(instance->message);
-        instance->message = NULL;
-    }
-    if (instance->update != NULL) {
-        RELEASE_HERE(instance->update, adv_update_finalize);
-        instance->update = NULL;
-    }
-    free(instance);
-}
-
-static void
-adv_instance_context_release(void *NONNULL context)
-{
-    adv_instance_t *instance = context;
-    RELEASE_HERE(instance, adv_instance_finalize);
-}
-
-#define DECLARE_VEC_CREATE(type)                        \
-static type ## _vec_t *                                 \
-type ## _vec_create(int size)                           \
-{                                                       \
-    type ## _vec_t *vec;                                \
-                                                        \
-    vec = calloc(1, sizeof(*vec));                      \
-    if (vec != NULL) {                                  \
-        if (size == 0) {                                \
-            size = 1;                                   \
-        }                                               \
-        vec->vec = calloc(size, sizeof (*(vec->vec)));  \
-        if (vec->vec == NULL) {                         \
-            free(vec);                                  \
-            vec = NULL;                                 \
-        } else {                                        \
-            RETAIN_HERE(vec);                           \
-        }                                               \
-    }                                                   \
-    return vec;                                         \
-}
-
-#define DECLARE_VEC_COPY(type)                          \
-static type ## _vec_t *                                 \
-type ## _vec_copy(type ## _vec_t *vec)                  \
-{                                                       \
-    type ## _vec_t *new_vec;                            \
-    int i;                                              \
-                                                        \
-    new_vec = type ## _vec_create(vec->num);            \
-    if (new_vec != NULL) {                              \
-        for (i = 0; i < vec->num; i++) {                \
-            if (vec->vec[i] != NULL) {                  \
-                new_vec->vec[i] = vec->vec[i];          \
-                RETAIN_HERE(new_vec->vec[i]);           \
-            }                                           \
-        }                                               \
-        new_vec->num = vec->num;                        \
-    }                                                   \
-    return new_vec;                                     \
-}
-
-#define DECLARE_VEC_FINALIZE(type)                          \
-static void                                                 \
-type ## _vec_finalize(type ## _vec_t *vec)                  \
-{                                                           \
-    int i;                                                  \
-                                                            \
-    for (i = 0; i < vec->num; i++) {                        \
-        if (vec->vec[i] != NULL) {                          \
-            RELEASE_HERE(vec->vec[i], type ## _finalize);   \
-            vec->vec[i] = NULL;                             \
-        }                                                   \
-    }                                                       \
-    free(vec->vec);                                         \
-    free(vec);                                              \
-}
-
-DECLARE_VEC_CREATE(adv_instance);
-DECLARE_VEC_COPY(adv_instance);
-DECLARE_VEC_FINALIZE(adv_instance);
-
-DECLARE_VEC_CREATE(adv_record);
-DECLARE_VEC_COPY(adv_record);
-DECLARE_VEC_FINALIZE(adv_record);
-
-// We call advertise_finished when a client request has finished, successfully or otherwise.
-#if SRP_FEATURE_REPLICATION
-static bool
-srp_replication_advertise_finished(adv_host_t *host, char *hostname, srp_server_t *server_state,
-                                   srpl_connection_t *srpl_connection, comm_t *connection, int rcode)
-{
-	if (server_state->srp_replication_enabled) {
-        INFO("hostname = " PRI_S_SRP "  host = %p  server_state = %p  srpl_connection = %p  connection = %p  rcode = "
-             PUB_S_SRP, hostname, host, server_state, srpl_connection, connection, dns_rcode_name(rcode));
-        if (connection == NULL) {
-            // connection is the SRP client connection on which an update arrived. If it's null,
-            // this is an SRP replication update, not an actual client we're communicating with.
-            INFO("replication advertise finished: host " PRI_S_SRP ": rcode = " PUB_S_SRP,
-                 hostname, dns_rcode_name(rcode));
-            if (srpl_connection != NULL) {
-                srpl_advertise_finished_event_send(hostname, rcode, server_state);
-
-                if (host != NULL && host->srpl_connection != NULL) {
-                    if (rcode == dns_rcode_noerror) {
-                        host->update_server_id = host->srpl_connection->remote_server_id;
-                        host->server_stable_id = host->srpl_connection->stashed_host.server_stable_id;
-                        INFO("replicated host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id);
-                    }
-
-                    // This is the safest place to clear this pointer--we do not want the srpl_connection pointer to not
-                    // get reset because of some weird sequence of events, leaving this host unable to be further updated
-                    // or worse.
-                    srpl_connection_release(host->srpl_connection);
-                    host->srpl_connection = NULL;
-                } else {
-                    if (host != NULL) {
-                        INFO("disconnected host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id);
-                    }
-                }
-            } else {
-                if (host != NULL) {
-                    INFO("context-free host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id);
-                }
-            }
-            return true;
-        }
-
-        if (host != NULL) {
-            if (rcode == dns_rcode_noerror) {
-                memcpy(&host->server_stable_id, &host->server_state->ula_prefix, sizeof(host->server_stable_id));
-            }
-            INFO("local host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id);
-            srpl_srp_client_update_finished_event_send(host, rcode);
-            host->update_server_id = 0;
-        }
-    } else {
-        if (host != NULL) {
-            memcpy(&host->server_stable_id, &host->server_state->ula_prefix, sizeof(host->server_stable_id));
-            host->update_server_id = 0;
-        }
-    }
-    return false;
-}
-#endif // SRP_FEATURE_REPLICATION
-
-// We call advertise_finished when a client request has finished, successfully or otherwise.
-static void
-advertise_finished(adv_host_t *host, char *hostname, srp_server_t *server_state, srpl_connection_t *srpl_connection,
-                   comm_t *connection, message_t *message, int rcode, client_update_t *client)
-{
-    struct iovec iov;
-    dns_wire_t response;
-
-#if SRP_FEATURE_REPLICATION
-    if (srp_replication_advertise_finished(host, hostname, server_state, srpl_connection, connection, rcode)) {
-        return;
-    }
-#else
-    (void)host;
-#endif // SRP_FEATURE_REPLICATION
-    INFO("host " PRI_S_SRP ": rcode = " PUB_S_SRP ", lease = %d, key_lease = %d", hostname, dns_rcode_name(rcode),
-         client ? client->host_lease : 0, client ? client->key_lease : 0);
-
-    memset(&response, 0, DNS_HEADER_SIZE);
-    response.id = message->wire.id;
-    response.bitfield = message->wire.bitfield;
-    dns_rcode_set(&response, rcode);
-    dns_qr_set(&response, dns_qr_response);
-
-    iov.iov_base = &response;
-    // If this was a successful update, send back the lease time, which will either
-    // be what the client asked for, or a shorter lease, depending on what limit has
-    // been set.
-    if (client != NULL) {
-        dns_towire_state_t towire;
-        memset(&towire, 0, sizeof towire);
-        towire.p = &response.data[0];               // We start storing RR data here.
-        towire.lim = &response.data[DNS_DATA_SIZE]; // This is the limit to how much we can store.
-        towire.message = &response;
-        response.qdcount = 0;
-        response.ancount = 0;
-        response.nscount = 0;
-        response.arcount = htons(1);
-        dns_edns0_header_to_wire(&towire, DNS_MAX_UDP_PAYLOAD, 0, 0, 1);
-        dns_rdlength_begin(&towire);
-        dns_u16_to_wire(&towire, dns_opt_update_lease);  // OPTION-CODE
-        dns_edns0_option_begin(&towire);                 // OPTION-LENGTH
-        dns_u32_to_wire(&towire, client->host_lease);    // LEASE (e.g. 1 hour)
-        dns_u32_to_wire(&towire, client->key_lease);     // KEY-LEASE (7 days)
-        dns_edns0_option_end(&towire);                   // Now we know OPTION-LENGTH
-        if (!client->serial_sent) {
-            dns_u16_to_wire(&towire, dns_opt_srp_serial);    // OPTION-CODE
-            dns_edns0_option_begin(&towire);                 // OPTION-LENGTH
-            dns_u32_to_wire(&towire, client->serial_number); // LEASE (e.g. 1 hour)
-            dns_edns0_option_end(&towire);                   // Now we know OPTION-LENGTH
-        }
-        dns_rdlength_end(&towire);
-        // It should not be possible for this to happen; if it does, the client
-        // might not renew its lease in a timely manner.
-        if (towire.error) {
-            ERROR("advertise_finished: unexpectedly failed to send EDNS0 lease option.");
-            iov.iov_len = DNS_HEADER_SIZE;
-        } else {
-            iov.iov_len = towire.p - (uint8_t *)&response;
-        }
-    } else {
-        iov.iov_len = DNS_HEADER_SIZE;
-    }
-    ioloop_send_message(connection, message, &iov, 1);
-}
-
-static void
-retry_callback(void *context)
-{
-    adv_host_t *host = (adv_host_t *)context;
-    if (host->update == NULL) {
-        update_from_host(host);
-    } else {
-        start_host_update(host);
-    }
-}
-
-static void
-wait_retry(adv_host_t *host)
-{
-    int64_t now = ioloop_timenow();
-#define MIN_HOST_RETRY_INTERVAL 15
-#define MAX_HOST_RETRY_INTERVAL 120
-    // If we've been retrying long enough for the lease to expire, give up.
-    if (!host->lease_expiry || host->lease_expiry < now) {
-        INFO("host lease has expired, not retrying: lease_expiry = %" PRId64
-             " now = %" PRId64 " difference = %" PRId64, host->lease_expiry, now, host->lease_expiry - now);
-        delete_host(host);
-        return;
-    }
-    if (host->retry_interval == 0) {
-        host->retry_interval = MIN_HOST_RETRY_INTERVAL;
-    } else if (host->retry_interval < MAX_HOST_RETRY_INTERVAL) {
-        host->retry_interval *= 2;
-    }
-    INFO("waiting %d seconds...", host->retry_interval);
-    ioloop_add_wake_event(host->retry_wakeup, host, retry_callback, NULL, host->retry_interval * 1000);
-}
-
-static bool
-setup_shared_registration_txn(srp_server_t *server_state)
-{
-    if (server_state->shared_registration_txn == NULL) {
-        DNSServiceRef sdref;
-        int err = DNSServiceCreateConnection(&sdref);
-        if (err != kDNSServiceErr_NoError) {
-            return false;
-        }
-        server_state->shared_registration_txn = ioloop_dnssd_txn_add(sdref, NULL, NULL, NULL);
-        if (server_state->shared_registration_txn == NULL) {
-            ERROR("unable to create shared connection for registration.");
-            DNSServiceRefDeallocate(sdref);
-            return false;
-        }
-        INFO("server_state->shared_registration_txn = %p  sdref = %p", server_state->shared_registration_txn, sdref);
-    }
-    return true;
-}
-static void
-service_disconnected(srp_server_t *server_state, intptr_t service_pointer)
-{
-    if (service_pointer == (intptr_t)server_state->shared_registration_txn &&
-        server_state->shared_registration_txn != NULL)
-    {
-        INFO("server_state->shared_registration_txn = %p  sdref = %p",
-             server_state->shared_registration_txn, server_state->shared_registration_txn->sdref);
-        ioloop_dnssd_txn_cancel(server_state->shared_registration_txn);
-        ioloop_dnssd_txn_release(server_state->shared_registration_txn);
-        server_state->shared_registration_txn = NULL;
-    }
-}
-
-static void
-client_free(client_update_t *client)
-{
-    srp_update_free_parts(client->instances, NULL, client->services, client->removes, client->host);
-    if (client->parsed_message != NULL) {
-        dns_message_free(client->parsed_message);
-    }
-    if (client->message != NULL) {
-        ioloop_message_release(client->message);
-    }
-    if (client->connection != NULL) {
-        ioloop_comm_release(client->connection);
-    }
-    free(client);
-}
-
-static void
-adv_record_vec_remove_update(adv_record_vec_t *vec, adv_update_t *update)
-{
-    for (int i = 0; i < vec->num; i++) {
-        if (vec->vec[i] != NULL && vec->vec[i]->update != NULL && vec->vec[i]->update == update) {
-            RELEASE_HERE(vec->vec[i]->update, adv_update_finalize);
-            vec->vec[i]->update = NULL;
-        }
-    }
-}
-
-static void
-adv_instance_vec_remove_update(adv_instance_vec_t *vec, adv_update_t *update)
-{
-    for (int i = 0; i < vec->num; i++) {
-        if (vec->vec[i] != NULL && vec->vec[i]->update != NULL && vec->vec[i]->update == update) {
-            RELEASE_HERE(vec->vec[i]->update, adv_update_finalize);
-            vec->vec[i]->update = NULL;
-        }
-    }
-}
-
-static void
-adv_update_free_instance_vectors(adv_update_t *NONNULL update)
-{
-    if (update->update_instances != NULL) {
-        adv_instance_vec_remove_update(update->update_instances, update);
-        RELEASE_HERE(update->update_instances, adv_instance_vec_finalize);
-        update->update_instances = NULL;
-    }
-    if (update->remove_instances != NULL) {
-        adv_instance_vec_remove_update(update->remove_instances, update);
-        RELEASE_HERE(update->remove_instances, adv_instance_vec_finalize);
-        update->remove_instances = NULL;
-    }
-    if (update->renew_instances != NULL) {
-        adv_instance_vec_remove_update(update->renew_instances, update);
-        RELEASE_HERE(update->renew_instances, adv_instance_vec_finalize);
-        update->renew_instances = NULL;
-    }
-    if (update->add_instances != NULL) {
-        adv_instance_vec_remove_update(update->add_instances, update);
-        RELEASE_HERE(update->add_instances, adv_instance_vec_finalize);
-        update->add_instances = NULL;
-    }
-}
-
-static void
-adv_update_finalize(adv_update_t *NONNULL update)
-{
-    if (update->host != NULL) {
-        RELEASE_HERE(update->host, adv_host_finalize);
-    }
-
-    if (update->client != NULL) {
-        client_free(update->client);
-        update->client = NULL;
-    }
-
-    if (update->remove_addresses != NULL) {
-        adv_record_vec_remove_update(update->remove_addresses, update);
-        RELEASE_HERE(update->remove_addresses, adv_record_vec_finalize);
-    }
-
-    if (update->add_addresses != NULL) {
-        adv_record_vec_remove_update(update->add_addresses, update);
-        RELEASE_HERE(update->add_addresses, adv_record_vec_finalize);
-    }
-
-    adv_update_free_instance_vectors(update);
-    if (update->key != NULL) {
-        RELEASE_HERE(update->key, adv_record_finalize);
-    }
-    free(update);
-}
-
-static void
-adv_update_cancel(adv_update_t *NONNULL update)
-{
-    adv_host_t *host = update->host;
-    bool faulted = false;
-
-    RETAIN_HERE(update); // ensure that update remains valid for the duration of this function call.
-
-    if (host != NULL) {
-        RETAIN_HERE(host); // in case the update is holding the last reference to the host
-        RELEASE_HERE(update->host, adv_host_finalize);
-        update->host = NULL;
-
-        INFO("cancelling update %p for host " PRI_S_SRP, update, host->registered_name);
-
-        if (host->update == update) {
-            RELEASE_HERE(host->update, adv_update_finalize);
-            host->update = NULL;
-        }
-    } else {
-        INFO("canceling update with no host.");
-    }
-
-    adv_update_free_instance_vectors(update);
-
-    if (update->add_addresses != NULL) {
-        // Any record that we attempted to add as part of this update should be removed because the update failed.
-        for (int i = 0; i < update->add_addresses->num; i++) {
-            adv_record_t *record = update->add_addresses->vec[i];
-            if (record != NULL) {
-                if (host == NULL) {
-                    if (!faulted) {
-                        FAULT("unable to clean up host address registration because host object is gone from update.");
-                        faulted = true;
-                    }
-                } else {
-                    if (record->rref != NULL) {
-                        remove_shared_record(host->server_state, record);
-                    }
-                }
-            }
-        }
-        adv_record_vec_remove_update(update->add_addresses, update);
-        RELEASE_HERE(update->add_addresses, adv_record_vec_finalize);
-        update->add_addresses = NULL;
-    }
-
-    if (update->remove_addresses != NULL) {
-        adv_record_vec_remove_update(update->remove_addresses, update);
-        RELEASE_HERE(update->remove_addresses, adv_record_vec_finalize);
-        update->remove_addresses = NULL;
-    }
-
-    if (update->key != NULL) {
-        if (update->key->update != NULL) {
-            RELEASE_HERE(update->key->update, adv_update_finalize);
-            update->key->update = NULL;
-        }
-        // Any record that we attempted to add as part of this update should be removed because the update failed.
-        if (update->key->rref != NULL) {
-            if (host == NULL) {
-                if (!faulted) {
-                    FAULT("unable to clean up host key registration because host object is gone from update.");
-                    faulted = true;
-                }
-            } else {
-                remove_shared_record(host->server_state, update->key);
-            }
-        }
-        RELEASE_HERE(update->key, adv_record_finalize);
-        update->key = NULL;
-    }
-    if (host != NULL) {
-        RELEASE_HERE(host, adv_host_finalize);
-    }
-    RELEASE_HERE(update, adv_update_finalize);
-}
-
-static void
-update_failed(adv_update_t *update, int rcode, bool expire)
-{
-    // Retain the update for the life of this function call, since we may well release the last other reference to it.
-    RETAIN_HERE(update);
-
-    // If we still have a client waiting for the result of this update, tell it we failed.
-    // Updates that have never worked are abandoned when the client is notified.
-    if (update->client != NULL) {
-        adv_host_t *host = update->host;
-        client_update_t *client = update->client;
-        adv_update_cancel(update);
-        advertise_finished(host, host->name, host->server_state, host->srpl_connection,
-                           client->connection, client->message, rcode, NULL);
-        client_free(client);
-        update->client = NULL;
-        // If we don't have a lease yet, or the old lease has expired, remove the host.
-        // However, if the expire flag is false, it's because we're already finalizing the
-        // host, so doing an expiry here would double free the host. In this case, we leave
-        // it to the caller to do the expiry (really, to finalize the host).
-        if (expire && (host->lease_expiry == 0 || host->lease_expiry <= ioloop_timenow())) {
-            delete_host(host);
-        }
-        RELEASE_HERE(update, adv_update_finalize);
-        return;
-    }
-    adv_update_cancel(update);
-    RELEASE_HERE(update, adv_update_finalize);
-}
-
-static void
-host_addr_free(adv_host_t *host)
-{
-    int i;
-
-    // We can't actually deallocate the address vector until the host object is collected, so deallocate the address
-    // records.
-    if (host->addresses != NULL) {
-        for (i = 0; i < host->addresses->num; i++) {
-            if (host->addresses->vec[i] != NULL) {
-                INFO("Removing AAAA record for " PRI_S_SRP, host->registered_name);
-                remove_shared_record(host->server_state, host->addresses->vec[i]);
-                RELEASE_HERE(host->addresses->vec[i], adv_record_finalize);
-                host->addresses->vec[i] = NULL;
-            }
-        }
-        host->addresses->num = 0;
-    }
-}
-
-// Free just those parts that are no longer needed when the host is no longer valid.
-static void
-host_invalidate(adv_host_t *host)
-{
-    int i;
-
-    // Get rid of the retry wake event.
-    if (host->retry_wakeup != NULL) {
-        ioloop_cancel_wake_event(host->retry_wakeup);
-    }
-
-    // Remove the address records.
-    host_addr_free(host);
-
-    // Remove the services.
-    if (host->instances != NULL) {
-        for (i = 0; i < host->instances->num; i++) {
-            if (host->instances->vec[i] != NULL) {
-                if (host->instances->vec[i] != NULL && host->instances->vec[i]->txn != NULL) {
-                    ioloop_dnssd_txn_cancel(host->instances->vec[i]->txn);
-                    ioloop_dnssd_txn_release(host->instances->vec[i]->txn);
-                    host->instances->vec[i]->txn = NULL;
-                }
-            }
-        }
-        RELEASE_HERE(host->instances, adv_instance_vec_finalize);
-        host->instances = NULL;
-    }
-
-    if (host->update != NULL) {
-        RELEASE_HERE(host->update, adv_update_finalize);
-        host->update = NULL;
-    }
-    if (host->key_record != NULL) {
-        remove_shared_record(host->server_state, host->key_record);
-        RELEASE_HERE(host->key_record, adv_record_finalize);
-        host->key_record = NULL;
-    }
-    host->update = NULL;
-    host->removed = true;
-}
-
-// Free everything associated with the host, including the host object.
-static void
-adv_host_finalize(adv_host_t *host)
-{
-    // Just in case this hasn't happened yet, free the non-identifying host data and cancel any outstanding
-    // transactions.
-    host_invalidate(host);
-
-    if (host->addresses != NULL) {
-        RELEASE_HERE(host->addresses, adv_record_vec_finalize);
-        host->addresses = NULL;
-    }
-
-
-    if (host->key_rdata != NULL) {
-        free(host->key_rdata);
-        host->key_rdata = NULL;
-    }
-    if (host->key_record != NULL) {
-        RELEASE_HERE(host->key_record, adv_record_finalize);
-        host->key_record = NULL;
-    }
-
-    if (host->message != NULL) {
-        ioloop_message_release(host->message);
-        host->message = NULL;
-    }
-
-    // We definitely don't want a lease callback at this point.
-    if (host->lease_wakeup != NULL) {
-        ioloop_cancel_wake_event(host->lease_wakeup);
-        ioloop_wakeup_release(host->lease_wakeup);
-    }
-    // Get rid of the retry wake event.
-    if (host->retry_wakeup != NULL) {
-        ioloop_cancel_wake_event(host->retry_wakeup);
-        ioloop_wakeup_release(host->retry_wakeup);
-    }
-
-
-    INFO("removed " PRI_S_SRP ", key_id %x", host->name ? host->name : "<null>", host->key_id);
-
-    // In the default case, host->name and host->registered_name point to the same memory: we don't want a double free.
-    if (host->registered_name == host->name) {
-        host->registered_name = NULL;
-    }
-    if (host->name != NULL) {
-        free(host->name);
-    }
-    if (host->registered_name != NULL) {
-        free(host->registered_name);
-    }
-    free(host);
-}
-
-void
-srp_adv_host_release_(adv_host_t *host, const char *file, int line)
-{
-    RELEASE(host, adv_host_finalize);
-}
-
-void
-srp_adv_host_retain_(adv_host_t *host, const char *file, int line)
-{
-    RETAIN(host);
-}
-
-bool
-srp_adv_host_valid(adv_host_t *host)
-{
-    // If the host has been removed, it's not valid.
-    if (host->removed) {
-        return false;
-    }
-    // If there is no key data, the host is invalid.
-    if (host->key_rdata == NULL) {
-        return false;
-    }
-    return true;
-}
-
-int
-srp_current_valid_host_count(srp_server_t *server_state)
-{
-    adv_host_t *host;
-    int count = 0;
-    for (host = server_state->hosts; host; host = host->next) {
-        if (srp_adv_host_valid(host)) {
-            count++;
-        }
-    }
-    return count;
-}
-
-int
-srp_hosts_to_array(srp_server_t *server_state, adv_host_t **host_array, int max)
-{
-    int count = 0;
-    for (adv_host_t *host = server_state->hosts; count < max && host != NULL; host = host->next) {
-        if (srp_adv_host_valid(host)) {
-            host_array[count] = host;
-            RETAIN_HERE(host_array[count]);
-            count++;
-        }
-    }
-    return count;
-}
-
-adv_host_t *
-srp_adv_host_copy_(srp_server_t *server_state, dns_name_t *name, const char *file, int line)
-{
-    for (adv_host_t *host = server_state->hosts; host; host = host->next) {
-        if (srp_adv_host_valid(host) && dns_names_equal_text(name, host->name)) {
-            RETAIN(host);
-            return host;
-        }
-    }
-    return NULL;
-}
-
-
-static void
-host_remove(adv_host_t *host)
-{
-    // This host is no longer valid. Get rid of the associated transactions and other stuff that's not required to
-    // identify it, and then release the host list reference to it.
-    host_invalidate(host);
-    // Note that while adv_host_finalize calls host_invalidate, adv_host_finalize won't necessarily be called here because there
-    // may be outstanding references on the host. It's okay to call host_invalidate twice--the second time it should be
-    // a no-op.
-    RELEASE_HERE(host, adv_host_finalize);
-}
-
-static adv_host_t **
-host_ready(adv_host_t *host)
-{
-    adv_host_t **p_hosts;
-
-    // Find the host on the list of hosts.
-    for (p_hosts = &host->server_state->hosts; *p_hosts != NULL; p_hosts = &(*p_hosts)->next) {
-        if (*p_hosts == host) {
-            break;
-        }
-    }
-    if (*p_hosts == NULL) {
-        ERROR("called with nonexistent host.");
-        return NULL;
-    }
-
-    // It's possible that we got an update to this host, but haven't processed it yet.  In this
-    // case, we don't want to get rid of the host, but we do want to get rid of it later if the
-    // update fails.  So postpone the removal for a bit.
-    if (host->update != NULL) {
-        INFO("reached with pending updates on host " PRI_S_SRP ".", host->registered_name);
-        ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, NULL, 10 * 1000);
-        host->lease_expiry = ioloop_timenow() + 10 * 1000; // ten seconds
-        return NULL;
-    }
-
-    return p_hosts;
-}
-
-static void
-lease_callback(void *context)
-{
-    int64_t now = ioloop_timenow();
-    adv_host_t **p_hosts, *host = context;
-    int i, num_instances = 0;
-
-    p_hosts = host_ready(host);
-    if (p_hosts == NULL) {
-        INFO("host expired");
-        return;
-    }
-
-    INFO("host " PRI_S_SRP, host->name);
-
-    // If the host entry lease has expired, any instance leases have also.
-    if (host->lease_expiry < now) {
-        delete_host(host);
-        return;
-    }
-
-    INFO("host " PRI_S_SRP " is still alive", host->name);
-
-    if (host->instances == NULL) {
-        INFO("no instances");
-        return;
-    }
-
-    // Find instances that have expired and release them.
-    for (i = 0; i < host->instances->num; i++) {
-        adv_instance_t *instance = host->instances->vec[i];
-        if (instance == NULL) {
-            continue;
-        }
-        if (instance->lease_expiry < now) {
-            INFO("host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " has expired",
-                 host->name, instance->instance_name, instance->service_type);
-            host->instances->vec[i] = NULL;
-            RELEASE_HERE(instance, adv_instance_finalize);
-            continue;
-        } else {
-            INFO("host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " has not expired",
-                 host->name, instance->instance_name, instance->service_type);
-        }
-        num_instances++;
-    }
-
-    int64_t next_lease_expiry = host->lease_expiry;
-
-    // Get rid of holes in the host instance vector and compute the next lease callback time
-    int j = 0;
-
-    for (i = 0; i < host->instances->num; i++) {
-        if (host->instances->vec[i] != NULL) {
-            adv_instance_t *instance = host->instances->vec[i];
-            host->instances->vec[j++] = instance;
-            if (next_lease_expiry > instance->lease_expiry) {
-                next_lease_expiry = instance->lease_expiry;
-            }
-        }
-    }
-    INFO("host " PRI_S_SRP " lost %d instances", host->name, host->instances->num - j);
-    host->instances->num = j;
-
-    // Now set a timer for the next lease expiry event
-    uint64_t when = next_lease_expiry - now;
-    if (when > INT32_MAX) {
-        when = INT32_MAX;
-    }
-
-    ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, NULL, (uint32_t)when);
-}
-
-// Called when we definitely want to make all the advertisements associated with a host go away.
-static void
-delete_host(void *context)
-{
-    adv_host_t **p_hosts, *host = context;
-
-    p_hosts = host_ready(host);
-    if (p_hosts == NULL) {
-        return;
-    }
-
-    INFO("deleting host " PRI_S_SRP, host->name);
-
-    // De-link the host.
-    *p_hosts = host->next;
-
-    // Get rid of any transactions attached to the host, any timer events, and any other associated data.
-    host_remove(host);
-}
-
-// We remember the message that produced this instance so that if we get an update that doesn't update everything,
-// we know which instances /were/ updated by this particular message. instance->recent_message is a copy of the pointer
-// to the message that most recently updated this instance. When we set instance->recent_message, we don't yet know
-// if the update is going to succeed; if it fails, we can't have changed update->message. If it succeeds, then when we
-// get down to update_finished, we can compare the message that did the update to instance->recent_message; if they
-// are the same, then we set the message on the instance.
-// Note that we only set instance->recent_message during register_instance_completion, so there's no timing race that
-// could happen as a result of receiving a second update to the same instance before the first has been processed.
-static void
-set_instance_message(adv_instance_t *instance, message_t *message)
-{
-    if (message != NULL && (ptrdiff_t)message == instance->recent_message) {
-        if (instance->message != NULL) {
-            ioloop_message_release(instance->message);
-        }
-        instance->message = message;
-        ioloop_message_retain(instance->message);
-        instance->recent_message = 0;
-    }
-}
-
-static void
-update_finished(adv_update_t *update)
-{
-    adv_host_t *host = update->host;
-    client_update_t *client = update->client;
-    int num_addresses = 0;
-    adv_record_vec_t *addresses = NULL;
-    int num_instances = 0;
-    adv_instance_vec_t *instances = NULL;
-    int i, j;
-    int num_host_addresses = 0;
-    int num_add_addresses = 0;
-    int num_host_instances = 0;
-    int num_add_instances = 0;
-    message_t *message = NULL;
-
-    // Get the message that produced the update, if any
-    if (client != NULL) {
-        message = client->message;
-    }
-
-    // Once an update has finished, we need to apply all of the proposed changes to the host object.
-    if (host->addresses != NULL) {
-        for (i = 0; i < host->addresses->num; i++) {
-            if (host->addresses->vec[i] != NULL &&
-                (update->remove_addresses == NULL || update->remove_addresses->vec[i] == NULL))
-            {
-                num_host_addresses++;
-            }
-        }
-    }
-
-    if (update->add_addresses != NULL) {
-        for (i = 0; i < update->add_addresses->num; i++) {
-            if (update->add_addresses->vec[i] != NULL) {
-                num_add_addresses++;
-            }
-        }
-    }
-
-    num_addresses = num_host_addresses + num_add_addresses;
-    if (num_addresses > 0) {
-        addresses = adv_record_vec_create(num_addresses);
-        if (addresses == NULL) {
-            update_failed(update, dns_rcode_servfail, true);
-            return;
-        }
-
-        j = 0;
-
-        if (host->addresses != NULL) {
-            for (i = 0; i < host->addresses->num; i++) {
-                if (host->addresses->vec[i] != NULL &&
-                    (update->remove_addresses == NULL || update->remove_addresses->vec[i] == NULL))
-                {
-#ifdef DEBUG_VERBOSE
-                    uint8_t *rdp = host->addresses->vec[i]->rdata;
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(rdp, rdp_buf);
-                    INFO("retaining " PRI_SEGMENTED_IPv6_ADDR_SRP "on host " PRI_S_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name);
-#endif
-                    addresses->vec[j] = host->addresses->vec[i];
-                    RETAIN_HERE(addresses->vec[j]);
-                    j++;
-                }
-            }
-        }
-        if (update->add_addresses != NULL) {
-            for (i = 0; i < update->add_addresses->num; i++) {
-                if (update->add_addresses->vec[i] != NULL) {
-#ifdef DEBUG_VERBOSE
-                    uint8_t *rdp = update->add_addresses->vec[i]->rdata;
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(rdp, rdp_buf);
-                    INFO("adding " PRI_SEGMENTED_IPv6_ADDR_SRP "to host " PRI_S_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name);
-#endif
-                    addresses->vec[j] = update->add_addresses->vec[i];
-                    RETAIN_HERE(addresses->vec[j]);
-                    j++;
-                    if (update->add_addresses->vec[i]->update != NULL) {
-                        RELEASE_HERE(update->add_addresses->vec[i]->update, adv_update_finalize);
-                        update->add_addresses->vec[i]->update = NULL;
-                    }
-                    RELEASE_HERE(update->add_addresses->vec[i], adv_record_finalize);
-                    update->add_addresses->vec[i] = NULL;
-                }
-            }
-        }
-        addresses->num = j;
-    }
-
-    // Do the same for instances.
-    if (host->instances != NULL) {
-        for (i = 0; i < host->instances->num; i++) {
-            // We're counting the number of non-NULL instances in the host instance vector, which is probably always
-            // going to be the same as host->instances->num, but we are not relying on this.
-            if (host->instances->vec[i] != NULL) {
-                num_host_instances++;
-            }
-        }
-    }
-
-    if (update->add_instances != NULL) {
-        for (i = 0; i < update->add_instances->num; i++) {
-            if (update->add_instances->vec[i] != NULL) {
-                num_add_instances++;
-            }
-        }
-    }
-
-    num_instances = num_add_instances + num_host_instances;
-    instances = adv_instance_vec_create(num_instances);
-    if (instances == NULL) {
-        if (addresses != NULL) {
-            RELEASE_HERE(addresses, adv_record_vec_finalize);
-            addresses = NULL;
-        }
-        update_failed(update, dns_rcode_servfail, true);
-        return;
-    }
-
-    j = 0;
-    if (host->instances != NULL) {
-        for (i = 0; i < host->instances->num; i++) {
-            if (j == num_instances) {
-                FAULT("j (%d) == num_instances (%d)", j, num_instances);
-                break;
-            }
-            if (update->update_instances != NULL && update->update_instances->vec[i] != NULL) {
-                adv_instance_t *instance = update->update_instances->vec[i];
-                if (update->remove_instances != NULL && update->remove_instances->vec[i] != NULL) {
-                    adv_instance_t *removed_instance = update->remove_instances->vec[i];
-                    INFO("removed instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                         removed_instance->instance_name, removed_instance->service_type, removed_instance->port);
-                    INFO("added instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                         instance->instance_name, instance->service_type, instance->port);
-                } else {
-                    INFO("updated instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                         instance->instance_name, instance->service_type, instance->port);
-                }
-                // Implicit RETAIN/RELEASE
-                instances->vec[j] = instance;
-                RETAIN_HERE(instances->vec[j]);
-                j++;
-                RELEASE_HERE(update->update_instances->vec[i], adv_instance_finalize);
-                update->update_instances->vec[i] = NULL;
-                if (instance->update != NULL) {
-                    RELEASE_HERE(instance->update, adv_update_finalize);
-                    instance->update = NULL;
-                }
-                set_instance_message(instance, message);
-            } else {
-                if (update->remove_instances != NULL && update->remove_instances->vec[i] != NULL) {
-                    adv_instance_t *instance = update->remove_instances->vec[i];
-                    INFO("removed instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                         instance->instance_name, instance->service_type, instance->port);
-                    instances->vec[j] = instance;
-                    RETAIN_HERE(instances->vec[j]);
-                    j++;
-                    instance->removed = true;
-                    if (message != NULL) {
-                        instance->message = message;
-                        ioloop_message_retain(instance->message);
-                    }
-                    if (instance->txn == NULL) {
-                        ERROR("instance " PRI_S_SRP "." PRI_S_SRP " for host " PRI_S_SRP " has no connection.",
-                              instance->instance_name, instance->service_type, host->name);
-                    } else {
-                        ioloop_dnssd_txn_cancel(instance->txn);
-                        ioloop_dnssd_txn_release(instance->txn);
-                        instance->txn = NULL;
-                    }
-                } else {
-                    if (host->instances->vec[i] != NULL) {
-                        adv_instance_t *instance = host->instances->vec[i];
-                        INFO("kept instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                             instance->instance_name, instance->service_type, instance->port);
-                        instances->vec[j] = instance;
-                        RETAIN_HERE(instances->vec[j]);
-                        j++;
-                        set_instance_message(instance, message);
-                    }
-                }
-            }
-        }
-    }
-
-    // Set the message on all of the instances that were renewed to the current message.
-    if (update->renew_instances != NULL) {
-        for (i = 0; i < update->renew_instances->num; i++) {
-            adv_instance_t *instance = update->renew_instances->vec[i];
-            if (instance != NULL) {
-                if (instance->message != NULL) {
-                    ioloop_message_release(instance->message);
-                }
-                if (message != NULL) {
-                    instance->message = message;
-                    ioloop_message_retain(instance->message);
-                }
-                instance->recent_message = 0;
-                INFO("renewed instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                     instance->instance_name, instance->service_type, instance->port);
-            }
-        }
-    }
-
-    if (update->add_instances != NULL) {
-        for (i = 0; i < update->add_instances->num; i++) {
-            adv_instance_t *instance = update->add_instances->vec[i];
-            if (instance != NULL) {
-                INFO("added instance " PRI_S_SRP " " PRI_S_SRP " %d",
-                      instance->instance_name, instance->service_type, instance->port);
-                instances->vec[j] = instance;
-                RETAIN_HERE(instances->vec[j]);
-                j++;
-                RELEASE_HERE(update->add_instances->vec[i], adv_instance_finalize);
-                update->add_instances->vec[i] = NULL;
-                if (instance->update != NULL) {
-                    RELEASE_HERE(instance->update, adv_update_finalize);
-                    instance->update = NULL;
-                }
-                set_instance_message(instance, message);
-            }
-        }
-    }
-    instances->num = j;
-
-    for (i = 0; i < instances->num; i++) {
-    }
-
-    // At this point we can safely modify the host object because we aren't doing any more
-    // allocations.
-    if (host->addresses != NULL) {
-        RELEASE_HERE(host->addresses, adv_record_vec_finalize);
-    }
-    host->addresses = addresses; // Either NULL or else returned retained by adv_record_vec_create().
-
-    if (host->instances != NULL) {
-        for (i = 0; i < host->instances->num; i++) {
-            adv_instance_t *instance = host->instances->vec[i];
-            if (instance != NULL) {
-                INFO("old host instance %d " PRI_S_SRP "." PRI_S_SRP " for host " PRI_S_SRP " has ref_count %d",
-                     i, instance->instance_name, instance->service_type, host->name, instance->ref_count);
-            } else {
-                INFO("old host instance %d is NULL", i);
-            }
-        }
-        RELEASE_HERE(host->instances, adv_instance_vec_finalize);
-    }
-    host->instances = instances;
-
-    if (host->key_record != NULL && update->key != NULL && host->key_record != update->key) {
-        remove_shared_record(host->server_state, host->key_record);
-        RELEASE_HERE(host->key_record, adv_record_finalize);
-        host->key_record = NULL;
-    }
-    if (host->key_record == NULL && update->key != NULL) {
-        host->key_record = update->key;
-        RETAIN_HERE(host->key_record);
-        if (update->key->update != NULL) {
-            RELEASE_HERE(update->key->update, adv_update_finalize);
-            update->key->update = NULL;
-        }
-    }
-
-    // Remove any instances that are to be removed
-    if (update->remove_addresses != NULL) {
-        for (i = 0; i < update->remove_addresses->num; i++) {
-            adv_record_t *record = update->remove_addresses->vec[i];
-            if (record != NULL) {
-                remove_shared_record(host->server_state, record);
-            }
-        }
-    }
-
-    if (client) {
-        // If this is an update from a client, do the serial number processing.
-        if (client->serial_sent) {
-            INFO("host " PRI_S_SRP " serial number %" PRIu32 "->%" PRIu32 " (from client)",
-                 host->name, host->serial_number, client->serial_number);
-            host->serial_number = client->serial_number;
-            host->have_serial_number = true;
-        } else {
-            // When the client doesn't know its serial number, and we have a recorded serial number, we want to make up a new
-            // serial number that's enough ahead of the old one that it's unlikely there's a higher number elsewhere from recent
-            // communications between the client and a server we're not currently able to reach.
-            if (host->have_serial_number) {
-                INFO("host " PRI_S_SRP " serial number %" PRIu32 "->%" PRIu32 " (from history)",
-                     host->name, host->serial_number, host->serial_number + 50);
-                client->serial_number = host->serial_number + 50;
-                host->have_serial_number = true;
-            } else {
-                host->serial_number = (uint32_t)time(NULL);
-                client->serial_number = host->serial_number;
-                INFO("host " PRI_S_SRP " serial number NONE->%" PRIu32 " (from time)",
-                     host->name, client->serial_number);
-                host->have_serial_number = true;
-            }
-        }
-
-        if (host->message != NULL) {
-            ioloop_message_release(host->message);
-        }
-        host->message = client->message;
-        ioloop_message_retain(host->message);
-        advertise_finished(host, host->name, host->server_state, host->srpl_connection,
-                           client->connection, client->message, dns_rcode_noerror, client);
-        client_free(client);
-        update->client = NULL;
-        if (host->message->received_time != 0) {
-            host->update_time = host->message->received_time;
-        } else {
-            host->update_time = srpl_time();
-        }
-    }
-
-    RETAIN_HERE(update); // We need to hold a reference to the update since this might be the last.
-
-    // The update should still be on the host.
-    if (host->update == NULL) {
-        ERROR("p_update is null.");
-    } else {
-        RELEASE_HERE(host->update, adv_update_finalize);
-        host->update = NULL;
-    }
-
-    // Reset the retry interval, since we succeeded in updating.
-    host->retry_interval = 0;
-
-    // Set the lease time based on this update. Even if we scheduled an update for the next time we
-    // enter the dispatch loop, we still want to schedule a lease expiry here, because it's possible
-    // that in the process of returning to the dispatch loop, the scheduled update will be removed.
-    host->lease_interval = update->host_lease;
-    host->key_lease = update->key_lease;
-
-    // We want the lease expiry event to fire the next time the lease on any instance expires, or
-    // at the time the lease for the current update would expire, whichever is sooner.
-    int64_t next_lease_expiry = INT64_MAX;
-    int64_t now = ioloop_timenow();
-
-#define LEASE_EXPIRY_DEBUGGING 1
-    // update->lease_expiry is nonzero if we are re-doing a previous registration.
-    if (update->lease_expiry != 0) {
-        if (update->lease_expiry < now) {
-#ifdef LEASE_EXPIRY_DEBUGGING
-            ERROR("lease expiry for host " PRI_S_SRP " happened %" PRIu64 " milliseconds ago.",
-                  host->registered_name, now - update->lease_expiry);
-#endif
-            // Expire the lease when next we hit the run loop
-            next_lease_expiry = now;
-        } else {
-#ifdef LEASE_EXPIRY_DEBUGGING
-            INFO("lease_expiry (1) for host " PRI_S_SRP " set to %" PRId64, host->name,
-                 (int64_t)(update->lease_expiry - now));
-#endif
-            next_lease_expiry = update->lease_expiry;
-        }
-        host->lease_expiry = update->lease_expiry;
-    }
-    // This is the more usual case.
-    else {
-#ifdef LEASE_EXPIRY_DEBUGGING
-        INFO("lease_expiry (2) for host " PRI_S_SRP " set to %d", host->name, host->lease_interval * 1000);
-#endif
-        next_lease_expiry = now + host->lease_interval * 1000;
-        host->lease_expiry = next_lease_expiry;
-    }
-
-    // We're doing two things here: setting the lease expiry on instances that were touched by the current
-    // update, and also finding the soonest update.
-    for (i = 0; i < host->instances->num; i++) {
-        adv_instance_t *instance = host->instances->vec[i];
-
-        if (instance != NULL) {
-            // This instance was updated by the current update, so set its lease time to
-            // next_lease_expiry.
-            if (instance->message == message) {
-                if (instance->removed) {
-#ifdef LEASE_EXPIRY_DEBUGGING
-                    INFO("lease_expiry (7) for host " PRI_S_SRP " removed instance " PRI_S_SRP "." PRI_S_SRP
-                         " left at %" PRId64, host->name, instance->instance_name, instance->service_type,
-                         (int64_t)(instance->lease_expiry - now));
-#endif
-                } else {
-#ifdef LEASE_EXPIRY_DEBUGGING
-                    INFO("lease_expiry (4) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " set to %" PRId64,
-                         host->name, instance->instance_name, instance->service_type,
-                         (int64_t)(host->lease_expiry - now));
-#endif
-                    instance->lease_expiry = host->lease_expiry;
-                }
-            }
-            // Instance was not updated by this update, so see if it expires sooner than this update
-            // (which is likely).
-            else if (instance->lease_expiry > now && instance->lease_expiry < next_lease_expiry) {
-#ifdef LEASE_EXPIRY_DEBUGGING
-                INFO("lease_expiry (3) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " set to %" PRId64,
-                     host->name, instance->instance_name, instance->service_type,
-                     (int64_t)(instance->lease_expiry - now));
-#endif
-                next_lease_expiry = instance->lease_expiry;
-            } else {
-                if (instance->lease_expiry <= now) {
-#ifdef LEASE_EXPIRY_DEBUGGING
-                    INFO("lease_expiry (5) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP
-                         " in the past at %" PRId64,
-                         host->name, instance->instance_name, instance->service_type,
-                         (int64_t)(now - instance->lease_expiry));
-#endif
-                    next_lease_expiry = now;
-#ifdef LEASE_EXPIRY_DEBUGGING
-                } else {
-                    INFO("lease_expiry (6) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP
-                         " is later than next_lease_expiry by %" PRId64, host->name, instance->instance_name,
-                         instance->service_type, (int64_t)(next_lease_expiry - instance->lease_expiry));
-
-#endif
-                }
-            }
-        }
-    }
-
-    // Now set a timer for the next lease expiry.
-    uint64_t when = next_lease_expiry - now;
-    if (when > INT32_MAX) {
-        when = INT32_MAX;
-    }
-
-    if (next_lease_expiry == now) {
-        INFO("scheduling immediate call to lease_callback in the run loop for " PRI_S_SRP, host->name);
-        ioloop_run_async(lease_callback, host);
-    } else {
-        INFO("scheduling wakeup to lease_callback in %" PRIu64 " for host " PRI_S_SRP,
-             when / 1000, host->name);
-        ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, NULL, (uint32_t)when);
-    }
-
-    // Instance vectors can hold circular references to the update object, which won't get freed until we call
-    // adv_update_finalize, which we will never do because of the circular reference. So break any remaining
-    // circular references before releasing the update.
-    adv_update_free_instance_vectors(update);
-
-    // This is letting go of the reference we retained earlier in this function, not some outstanding reference retained elsewhere.
-    RELEASE_HERE(update, adv_update_finalize);
-}
-
-static void
-process_dnsservice_error(adv_update_t *update, int err)
-{
-    if (err != kDNSServiceErr_NoError) {
-        update_failed(update, dns_rcode_servfail, true);
-        if (err == kDNSServiceErr_ServiceNotRunning) {
-            if (update->host != NULL) {
-                if (update->host->server_state != NULL) {
-                    service_disconnected(update->host->server_state,
-                                         (intptr_t)update->host->server_state->shared_registration_txn);
-                }
-                wait_retry(update->host);
-            }
-        }
-    }
-}
-
-// When the host registration has completed, we get this callback.   Completion either means that we succeeded in
-// registering the record, or that something went wrong and the registration has failed.
-static void
-register_instance_completion(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType error_code,
-                             const char *name, const char *regtype, const char *domain, void *context)
-{
-    (void)flags;
-    (void)sdref;
-    adv_instance_t *instance = context;
-    adv_update_t *update = instance->update;
-    adv_host_t *host = instance->host;
-
-    // Retain the instance for the life of this function, just in case we release stuff that is holding the last reference to it.
-    RETAIN_HERE(instance);
-
-    // It's possible that we could restart a host update due to an error while a callback is still pending on a stale
-    // update.  In this case, we just cancel all of the work that's been done on the stale update (it's probably already
-    // moot anyway.
-    if (update != NULL && host->update != update) {
-        INFO("registration for service " PRI_S_SRP "." PRI_S_SRP " completed with invalid state.", name, regtype);
-        RELEASE_HERE(instance->update, adv_update_finalize);
-        instance->update = NULL;
-        RELEASE_HERE(instance, adv_instance_finalize);
-        return;
-    }
-
-    // We will generally get a callback on success or failure of the initial registration; this is what causes
-    // the update to complete or fail. We may get subsequent callbacks because of name conflicts. So the first
-    // time we get a callback, instance->update will always be valid; thereafter, it will not, so null it out.
-    if (update != NULL) {
-        RETAIN_HERE(update); // We need to hold onto this until we are done with the update.
-        RELEASE_HERE(instance->update, adv_update_finalize);
-        instance->update = NULL;
-    }
-
-    if (error_code == kDNSServiceErr_NoError) {
-        INFO("registration for service " PRI_S_SRP "." PRI_S_SRP "." PRI_S_SRP " -> "
-             PRI_S_SRP " has completed.", instance->instance_name, instance->service_type, domain,
-             host->registered_name);
-        INFO("registration is under " PRI_S_SRP "." PRI_S_SRP PRI_S_SRP, name, regtype,
-             domain);
-
-        // In principle update->instance should always be non-NULL here because a no-error response should
-        // only happen once or not at all. But just to be safe...
-        if (update != NULL) {
-            if (instance->update_pending) {
-                if (update->client != NULL) {
-                    instance->recent_message = (ptrdiff_t)update->client->message; // for comparison later in update_finished
-                }
-                update->num_instances_completed++;
-                if (update->num_records_completed == update->num_records_started &&
-                    update->num_instances_completed == update->num_instances_started)
-                {
-                    update_finished(update);
-                }
-                RELEASE_HERE(update, adv_update_finalize);
-                instance->update_pending = false;
-                update = NULL;
-            }
-        } else {
-            ERROR("no error, but update is NULL for instance " PRI_S_SRP " (" PRI_S_SRP
-                  " " PRI_S_SRP " " PRI_S_SRP ")", instance->instance_name, name, regtype, domain);
-        }
-    } else {
-        INFO("registration for service " PRI_S_SRP "." PRI_S_SRP "." PRI_S_SRP " -> "
-             PRI_S_SRP " failed with code %d", instance->instance_name, instance->service_type, domain,
-             host->registered_name, error_code);
-
-        // If the reason this failed is that we couldn't talk to mDNSResponder, or mDNSResponder disconnected, then we want to retry
-        // later on in the hopes that mDNSResponder will come back.
-        if (error_code == kDNSServiceErr_ServiceNotRunning || error_code == kDNSServiceErr_DefunctConnection) {
-            service_disconnected(host->server_state, instance->shared_txn);
-            instance->shared_txn = 0;
-            wait_retry(host);
-        } else {
-            if (update != NULL) {
-                update_failed(update, error_code == kDNSServiceErr_NameConflict ? dns_rcode_yxdomain : dns_rcode_servfail, true);
-                if (instance->update != NULL) {
-                    RELEASE_HERE(instance->update, adv_update_finalize);
-                    instance->update = NULL;
-                }
-                RELEASE_HERE(update, adv_update_finalize);
-            }
-        }
-
-        // The transaction still holds a reference to the instance. instance->txn should never be NULL here. When we cancel
-        // the transaction, the reference the transaction held on the instance will be released.
-        if (instance->txn == NULL) {
-            FAULT("instance->txn is NULL!");
-        } else {
-            ioloop_dnssd_txn_cancel(instance->txn);
-            ioloop_dnssd_txn_release(instance->txn);
-            instance->txn = NULL;
-        }
-    }
-    RELEASE_HERE(instance, adv_instance_finalize);
-}
-
-static bool
-extract_instance_name(char *instance_name, size_t instance_name_max,
-                      char *service_name, size_t service_name_max, service_instance_t *instance)
-{
-    dns_name_t *end_of_service_name = instance->service->rr->name->next;
-    size_t service_index;
-    service_t *service, *base_type;
-    if (end_of_service_name != NULL) {
-        if (end_of_service_name->next != NULL) {
-            end_of_service_name = end_of_service_name->next;
-        }
-    }
-    dns_name_print_to_limit(instance->service->rr->name, end_of_service_name, service_name, service_name_max);
-
-    // It's possible that the registration might include subtypes. If so, we need to convert them to the
-    // format that DNSServiceRegister expects: service_type,subtype,subtype...
-    service_index = strlen(service_name);
-    base_type = instance->service->base_type;
-    for (service = instance->service->next; service != NULL && service->base_type == base_type; service = service->next)
-    {
-        if (service_index + service->rr->name->len + 2 > service_name_max) {
-            ERROR("service name: " PRI_S_SRP " is too long for additional subtype " PRI_S_SRP,
-                  service_name, service->rr->name->data);
-            return false;
-        }
-        service_name[service_index++] = ',';
-        memcpy(&service_name[service_index], service->rr->name->data, service->rr->name->len + 1);
-        service_index += service->rr->name->len;
-    }
-
-    // Make a presentation-format version of the service instance name.
-    dns_name_print_to_limit(instance->name, instance->name != NULL ? instance->name->next : NULL,
-                            instance_name, instance_name_max);
-    return true;
-}
-
-static bool
-register_instance(adv_instance_t *instance)
-{
-    int err = kDNSServiceErr_Unknown;
-    bool exit_status = false;
-    srp_server_t *server_state = instance->host->server_state;
-
-    INFO("DNSServiceRegister(" PRI_S_SRP ", " PRI_S_SRP ", " PRI_S_SRP ", %d)",
-         instance->instance_name, instance->service_type, instance->host->registered_name, instance->port);
-
-    // If we don't yet have a shared connection, create one.
-    if (!setup_shared_registration_txn(server_state)) {
-        wait_retry(instance->host);
-        goto exit;
-    }
-    DNSServiceRef service_ref = server_state->shared_registration_txn->sdref;
-    if (__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)) {
-        DNSServiceAttributeRef attr = DNSServiceAttributeCreate();
-        if (attr == NULL) {
-            ERROR("Failed to create new DNSServiceAttributeRef");
-            err = kDNSServiceErr_NoMemory;
-        } else {
-            if (instance->update->client != NULL && instance->update->client->message != NULL &&
-                instance->update->client->message->received_time != 0)
-            {
-                DNSServiceAttributeSetTimestamp(attr, (uint32_t)(srpl_time() - instance->update->client->message->received_time));
-            } else {
-                DNSServiceAttributeSetTimestamp(attr, 0);
-            }
-            err = DNSServiceRegisterWithAttribute(&service_ref, (kDNSServiceFlagsShareConnection |
-                                                                 kDNSServiceFlagsNoAutoRename | kDNSServiceFlagsShared),
-                                                  server_state->advertise_interface,
-                                                  instance->instance_name, instance->service_type, local_suffix,
-                                                  instance->host->registered_name, htons(instance->port), instance->txt_length,
-                                                  instance->txt_data, attr, register_instance_completion, instance);
-            DNSServiceAttributeDeallocate(attr);
-        }
-    } else {
-        err = DNSServiceRegister(&service_ref,
-                                 kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename | kDNSServiceFlagsShared,
-                                 server_state->advertise_interface,
-                                 instance->instance_name, instance->service_type, local_suffix,
-                                 instance->host->registered_name, htons(instance->port), instance->txt_length,
-                                 instance->txt_data, register_instance_completion, instance);
-    }
-
-    // This would happen if we pass NULL for regtype, which we don't, or if we run out of memory, or if
-    // the server isn't running; in the second two cases, we can always try again later.
-    if (err != kDNSServiceErr_NoError) {
-        if (err == kDNSServiceErr_ServiceNotRunning || err == kDNSServiceErr_DefunctConnection) {
-            INFO("DNSServiceRegister failed: " PUB_S_SRP ,
-                 err == kDNSServiceErr_ServiceNotRunning ? "not running" : "defunct");
-            service_disconnected(server_state, instance->shared_txn);
-        } else {
-            INFO("DNSServiceRegister failed: %d", err);
-        }
-        goto exit;
-    }
-    if (instance->update != NULL) {
-        instance->update->num_instances_started++;
-        instance->update_pending = true;
-    }
-    // After DNSServiceRegister succeeds, it creates a copy of DNSServiceRef that indirectly uses the shared connection,
-    // so we update it here.
-    instance->txn = ioloop_dnssd_txn_add(service_ref, instance, adv_instance_context_release, NULL);
-    if (instance->txn == NULL) {
-        ERROR("no memory for instance transaction.");
-        goto exit;
-    }
-    instance->shared_txn = (intptr_t)server_state->shared_registration_txn;
-    RETAIN_HERE(instance); // for the callback
-    exit_status = true;
-
-exit:
-    return exit_status;
-}
-
-// When we get a late name conflict on the hostname, we need to update the host registration and all of the
-// service registrations. To do this, we construct an update and then apply it. If there is already an update
-// in progress, we put this update at the end of the list.
-static void
-update_from_host(adv_host_t *host)
-{
-    adv_update_t *update = NULL;
-    int i;
-
-    if (host->update != NULL) {
-        ERROR("already have an update.");
-    }
-
-    // Allocate the update structure.
-    update = calloc(1, sizeof *update);
-    if (update == NULL) {
-        ERROR("no memory for update.");
-        goto fail;
-    }
-    RETAIN_HERE(update);
-
-    if (host->addresses != NULL) {
-        update->add_addresses = adv_record_vec_copy(host->addresses);
-        if (update->add_addresses == NULL) {
-            ERROR("no memory for addresses");
-            goto fail;
-        }
-        for (i = 0; i < update->add_addresses->num; i++) {
-            if (update->add_addresses->vec[i] != NULL) {
-                update->add_addresses->vec[i]->update = update;
-                RETAIN_HERE(update);
-            }
-        }
-    }
-
-    // We can never update more instances than currently exist for this host.
-    if (host->instances != NULL) {
-        update->update_instances = adv_instance_vec_copy(host->instances);
-        if (update->update_instances == NULL) {
-            ERROR("no memory for update_instances");
-            goto fail;
-        }
-        for (i = 0; i < update->update_instances->num; i++) {
-            if (update->update_instances->vec[i] != NULL) {
-                update->update_instances->vec[i]->update = update;
-                RETAIN_HERE(update);
-            }
-        }
-
-        // We aren't actually adding or deleting any instances, but...
-        update->remove_instances = adv_instance_vec_create(host->instances->num);
-        if (update->remove_instances == NULL) {
-            ERROR("no memory for remove_instances");
-            goto fail;
-        }
-        update->remove_instances->num = host->instances->num;
-
-        update->add_instances = adv_instance_vec_create(host->instances->num);
-        if (update->add_instances == NULL) {
-            ERROR("no memory for add_instances");
-            goto fail;
-        }
-        update->add_instances->num = host->instances->num;
-    }
-
-
-    // At this point we have figured out all the work we need to do, so hang it off an update structure.
-    update->host = host;
-    RETAIN_HERE(update->host);
-    update->host_lease = host->lease_interval;
-    update->key_lease = host->key_lease;
-    update->lease_expiry = host->lease_expiry;
-
-    // Stash the update on the host.
-    host->update = update;
-    RETAIN_HERE(host->update);                  // host gets a reference
-    RELEASE_HERE(update, adv_update_finalize);  // we're done with our reference.
-    start_host_update(host);
-    return;
-
-fail:
-    if (update != NULL) {
-        adv_update_cancel(update);
-        RELEASE_HERE(update, adv_update_finalize);
-    }
-    wait_retry(host);
-    return;
-}
-
-// When the host registration has completed, we get this callback.   Completion either means that we succeeded in
-// registering the record, or that something went wrong and the registration has failed.
-static void
-register_host_record_completion(DNSServiceRef sdref, DNSRecordRef rref,
-                                DNSServiceFlags flags, DNSServiceErrorType error_code, void *context)
-{
-    adv_record_t *record = context;
-    adv_host_t *host = NULL;
-    adv_update_t *update = NULL;
-    (void)sdref;
-    (void)rref;
-    (void)error_code;
-    (void)flags;
-
-    // For analyzer, can't actually happen.
-    if (record == NULL) {
-        ERROR("null record");
-        return;
-    }
-    host = record->host;
-    if (host == NULL) {
-        ERROR("no host");
-        return;
-    }
-
-    // Make sure record remains valid for the duration of this call.
-    RETAIN_HERE(record);
-
-    // It's possible that we could restart a host update due to an error while a callback is still pending on a stale
-    // update.  In this case, we just cancel all of the work that's been done on the stale update (it's probably already
-    // moot anyway.
-    if (record->update != NULL && host->update != record->update) {
-        INFO("registration for host record completed with invalid state.");
-        adv_update_cancel(record->update);
-        RELEASE_HERE(record->update, adv_update_finalize);
-        record->update = NULL;
-        remove_shared_record(host->server_state, record); // This will prevent further callbacks and release the reference held by the transaction.
-        RELEASE_HERE(record, adv_record_finalize); // The callback has a reference to the record.
-        RELEASE_HERE(record, adv_record_finalize); // Release the reference to the record that we retained at the beginning
-        return;
-
-    }
-    update = record->update;
-    if (update == NULL) {
-        // We shouldn't ever get a callback with update==NULL (which means that the update completed successfully) that's not an
-        // error.
-        if (error_code == kDNSServiceErr_NoError) {
-            FAULT("update is NULL, registration for host record completed with invalid state.");
-        }
-    } else {
-        RETAIN_HERE(update);
-    }
-
-    if (error_code == kDNSServiceErr_NoError) {
-        // If the update is pending, it means that we just finished registering this record for the first time,
-        // so we can count it as complete and check to see if there is any work left to do; if not, we call
-        // update_finished to apply the update to the host object.
-        const char *note = " has completed.";
-        if (record->update_pending) {
-            record->update_pending = false;
-            if (update != NULL) {
-                update->num_records_completed++;
-                if (update->num_records_completed == update->num_records_started &&
-                    update->num_instances_completed == update->num_instances_started)
-                {
-                    update_finished(update);
-                }
-            }
-        } else {
-            note = " got spurious success callback after completion.";
-        }
-
-        if (record->rrtype == dns_rrtype_a) {
-            IPv4_ADDR_GEN_SRP(record->rdata, addr_buf);
-            INFO("registration for host " PRI_S_SRP " address " PRI_IPv4_ADDR_SRP PUB_S_SRP,
-                 host->registered_name, IPv4_ADDR_PARAM_SRP(record->rdata, addr_buf), note);
-        } else if (record->rrtype == dns_rrtype_aaaa) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, addr_buf);
-            INFO("registration for host " PRI_S_SRP " address " PRI_SEGMENTED_IPv6_ADDR_SRP PUB_S_SRP,
-                 host->registered_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, addr_buf), note);
-        } else if (record->rrtype == dns_rrtype_key) {
-            INFO("registration for host " PRI_S_SRP " key" PUB_S_SRP, host->registered_name, note);
-        } else {
-            INFO("registration for host " PRI_S_SRP " unknown record type %d " PUB_S_SRP, host->registered_name, record->rrtype, note);
-        }
-    } else {
-        if (record->rrtype == dns_rrtype_a) {
-            IPv4_ADDR_GEN_SRP(record->rdata, addr_buf);
-            INFO("registration for host " PRI_S_SRP " address " PRI_IPv4_ADDR_SRP " failed, error code = %d.",
-             host->registered_name, IPv4_ADDR_PARAM_SRP(record->rdata, addr_buf), error_code);
-        } else if (record->rrtype == dns_rrtype_aaaa) {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, addr_buf);
-            INFO("registration for host " PRI_S_SRP " address " PRI_SEGMENTED_IPv6_ADDR_SRP " failed, error code = %d.",
-                 host->registered_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, addr_buf), error_code);
-        } else if (record->rrtype == dns_rrtype_key) {
-            INFO("registration for host " PRI_S_SRP " key failed, error code = %d.", host->registered_name, error_code);
-        } else {
-            INFO("registration for host " PRI_S_SRP " unknown record type %d failed, error code = %d.",
-                 host->registered_name, record->rrtype, error_code);
-        }
-
-        // If the reason this failed is that we couldn't talk to mDNSResponder, or mDNSResponder disconnected, then we want to retry
-        // later on in the hopes that mDNSResponder will come back.
-        if (error_code == kDNSServiceErr_ServiceNotRunning || error_code == kDNSServiceErr_DefunctConnection) {
-            service_disconnected(host->server_state, record->shared_txn);
-            if (update != NULL) {
-                wait_retry(host);
-            }
-        } else {
-            // The other error we could get is a name conflict. This means that some other advertising proxy or host on
-            // the network is advertising the hostname we chose, and either got there first with no TSR record, or got
-            // its copy of the host information later than ours. So if we get a name conflict, it's up to the client or
-            // the replication peer to make the next move.
-            if (update != NULL) {
-                update_failed(update, error_code == kDNSServiceErr_NameConflict ? dns_rcode_yxdomain : dns_rcode_servfail, true);
-            }
-        }
-        // Regardless of what else happens, this transaction is dead, so get rid of our references to it.
-        remove_shared_record(host->server_state, record);
-    }
-    if (update != NULL) {
-        RELEASE_HERE(update, adv_update_finalize);
-    }
-    RELEASE_HERE(record, adv_record_finalize); // Release the reference to the record that we retained at the beginning
-}
-
-static adv_instance_t *
-adv_instance_create(service_instance_t *raw, adv_host_t *host, adv_update_t *update)
-{
-    char service_type[DNS_MAX_LABEL_SIZE_ESCAPED * 2 + 2]; // sizeof '.' + sizeof '\0'.
-    char instance_name[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-    char *txt_data;
-
-    // Allocate the raw registration
-    adv_instance_t *instance = calloc(1, sizeof *instance);
-    if (instance == NULL) {
-        ERROR("adv_instance:create: unable to allocate raw registration struct.");
-        return NULL;
-    }
-    RETAIN_HERE(instance);
-    instance->host = host;
-    RETAIN_HERE(instance->host);
-    instance->update = update;
-    RETAIN_HERE(instance->update);
-
-    // SRV records have priority, weight and port, but DNSServiceRegister only uses port.
-    instance->port = (raw->srv == NULL) ? 0 : raw->srv->data.srv.port;
-
-    // Make a presentation-format version of the service name.
-    if (!extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, raw)) {
-        RELEASE_HERE(instance, adv_instance_finalize);
-        return NULL;
-    }
-
-    instance->instance_name = strdup(instance_name);
-    if (instance->instance_name == NULL) {
-        ERROR("adv_instance:create: unable to allocate instance name.");
-        RELEASE_HERE(instance, adv_instance_finalize);
-        return NULL;
-    }
-    instance->service_type = strdup(service_type);
-    if (instance->service_type == NULL) {
-        ERROR("adv_instance:create: unable to allocate instance type.");
-        RELEASE_HERE(instance, adv_instance_finalize);
-        return NULL;
-    }
-
-    // Allocate the text record buffer
-    if (raw->txt != NULL) {
-        txt_data = malloc(raw->txt->data.txt.len);
-        if (txt_data == NULL) {
-            RELEASE_HERE(instance, adv_instance_finalize);
-            ERROR("adv_instance:create: unable to allocate txt_data buffer");
-            return NULL;
-        }
-        // Format the txt buffer as required by DNSServiceRegister().
-        memcpy(txt_data, raw->txt->data.txt.data, raw->txt->data.txt.len);
-        instance->txt_data = txt_data;
-        instance->txt_length = raw->txt->data.txt.len;
-    } else {
-        instance->txt_data = NULL;
-        instance->txt_length = 0;
-    }
-    return instance;
-}
-
-#define adv_record_create(rrtype, rdlen, rdata, host) \
-    adv_record_create_(rrtype, rdlen, rdata, host, __FILE__, __LINE__)
-static adv_record_t *
-adv_record_create_(uint16_t rrtype, uint16_t rdlen, uint8_t *rdata, adv_host_t *host, const char *file, int line)
-{
-
-    adv_record_t *new_record = calloc(1, sizeof(*new_record) + rdlen - 1);
-    if (new_record == NULL) {
-        ERROR("no memory for new_record");
-        return NULL;
-    }
-    new_record->rdata = malloc(rdlen);
-    if (new_record->rdata == NULL) {
-        ERROR("no memory for new_record->rdata");
-        free(new_record);
-        return NULL;
-    }
-    new_record->host = host;
-    RETAIN(host);
-    new_record->rrtype = rrtype;
-    new_record->rdlen = rdlen;
-    memcpy(new_record->rdata, rdata, rdlen);
-    RETAIN(new_record);
-    return new_record;
-}
-
-// Given a base type, which might be _foo._tcp, and an instance type, which might also be _foo._tcp or
-// might have subtypes, like _foo.tcp,bar, return true if base_type matches the base type of instance_type,
-// without any subtypes.
-static bool
-service_types_equal(const char *base_type, const char *instance_type)
-{
-    size_t len;
-    char *comma = strchr(instance_type, ',');
-    if (comma == NULL) {
-        len = strlen(instance_type);
-    } else {
-        len = comma - instance_type;
-    }
-    if (strlen(base_type) != len) {
-        return false;
-    }
-    if (memcmp(base_type, instance_type, len)) {
-        return false;
-    }
-    return true;
-}
-
-static bool
-register_host_record(adv_host_t *host, adv_record_t *record)
-{
-    int err;
-
-    // If this record is already registered, get rid of the old transaction.
-    if (record->rref != NULL) {
-        remove_shared_record(host->server_state, record);
-    }
-
-    // If we don't yet have a shared connection, create one.
-    if (!setup_shared_registration_txn(host->server_state)) {
-        return false;
-    }
-
-    const DNSServiceRef service_ref = host->server_state->shared_registration_txn->sdref;
-
-    INFO("DNSServiceRegisterRecord(%p %p %d %d %s %d %d %d %p %d %p %p)",
-         service_ref, &record->rref,
-         kDNSServiceFlagsShared,
-         host->server_state->advertise_interface, host->registered_name,
-         record->rrtype, dns_qclass_in, record->rdlen, record->rdata, 3600,
-         register_host_record_completion, record);
-
-    if (__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)) {
-        DNSServiceAttributeRef attr = DNSServiceAttributeCreate();
-        if (attr == NULL) {
-            ERROR("Failed to create new DNSServiceAttributeRef");
-            return false;
-        } else {
-            if (host->update != NULL && host->update->client != NULL && host->update->client->message != NULL &&
-                host->update->client->message->received_time != 0)
-            {
-                DNSServiceAttributeSetTimestamp(attr, (uint32_t)(srpl_time() - host->update->client->message->received_time));
-            } else {
-                DNSServiceAttributeSetTimestamp(attr, 0);
-            }
-            err = DNSServiceRegisterRecordWithAttribute(service_ref, &record->rref,
-                                                        kDNSServiceFlagsShared | kDNSServiceFlagsQueueRequest,
-                                                        host->server_state->advertise_interface, host->registered_name,
-                                                        record->rrtype, dns_qclass_in, record->rdlen, record->rdata, 3600,
-                                                        attr, register_host_record_completion, record);
-            DNSServiceAttributeDeallocate(attr);
-        }
-    } else {
-        err = DNSServiceRegisterRecord(service_ref, &record->rref,
-                                       kDNSServiceFlagsShared,
-                                       host->server_state->advertise_interface, host->registered_name,
-                                       record->rrtype, dns_qclass_in, record->rdlen, record->rdata, 3600,
-                                       register_host_record_completion, record);
-    }
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("DNSServiceRegisterRecord failed on host: %d", err);
-        return false;
-    }
-    record->shared_txn = (intptr_t)host->server_state->shared_registration_txn;
-    RETAIN_HERE(record); // for the callback
-    record->update_pending = true;
-    return true;
-}
-
-static void
-update_instance_tsr(adv_instance_t *instance)
-{
-    DNSServiceAttributeRef attr;
-    int err;
-
-    if (instance->txn == NULL) {
-        ERROR("txn is NULL updating instance TSR.");
-        return;
-    }
-    if (instance->txn->sdref == NULL) {
-        ERROR("sdref is NULL when updating instance TSR.");
-        return;
-    }
-    if (__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)) {
-        attr = DNSServiceAttributeCreate();
-        if (attr == NULL) {
-            ERROR("failed to create new DNSServiceAttributeRef");
-        } else {
-            if (instance->update != NULL && instance->update->client != NULL && instance->update->client->message != NULL &&
-                instance->update->client->message->received_time != 0)
-            {
-                DNSServiceAttributeSetTimestamp(attr, (uint32_t)(srpl_time() - instance->update->client->message->received_time));
-            } else {
-                DNSServiceAttributeSetTimestamp(attr, 0);
-            }
-            err = DNSServiceUpdateRecordWithAttribute(instance->txn->sdref, NULL, 0, 0, NULL, 0, attr);
-            DNSServiceAttributeDeallocate(attr);
-            if (err == kDNSServiceErr_NoError) {
-                INFO("DNSServiceUpdateRecordWithAttribute for instance tsr succeed");
-            } else {
-                INFO("DNSServiceUpdateRecordWithAttribute for instance tsr failed: %d", err);
-                // We should never get a bad reference error; if we do, it's likely the result of a previous
-                // mDNSResponder crash. In this case, we might as well get rid of the transaction.
-                if (err == kDNSServiceErr_BadReference || err == kDNSServiceErr_BadParam) {
-                    ioloop_dnssd_txn_cancel(instance->txn);
-                    ioloop_dnssd_txn_release(instance->txn);
-                    instance->txn = NULL;
-                }
-            }
-        }
-    }
-}
-
-static void
-update_host_tsr(adv_record_t *record)
-{
-    DNSServiceAttributeRef attr;
-    int err;
-    dnssd_txn_t *shared_txn;
-
-    if (record->host == NULL || record->rref == NULL) {
-        ERROR("record->host[%p], record->rref[%p] when we update host TSR.", record->host, record->rref);
-        return;
-    }
-
-    shared_txn = record->host->server_state->shared_registration_txn;
-    if (shared_txn == NULL) {
-        ERROR("shared_txn is NULL when we update host TSR.");
-        return;
-    }
-    if (shared_txn->sdref == NULL) {
-        ERROR("shared_txn->sdref is NULL when we update host TSR.");
-        return;
-    }
-    if (__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)) {
-        attr = DNSServiceAttributeCreate();
-        if (attr == NULL) {
-            ERROR("failed to create new DNSServiceAttributeRef");
-        } else {
-            if (record->update != NULL && record->update->client != NULL && record->update->client->message != NULL &&
-                record->update->client->message->received_time != 0)
-            {
-                DNSServiceAttributeSetTimestamp(attr, (uint32_t)(srpl_time() - record->update->client->message->received_time));
-            } else {
-                DNSServiceAttributeSetTimestamp(attr, 0);
-            }
-            err = DNSServiceUpdateRecordWithAttribute(shared_txn->sdref, record->rref, 0, 0, NULL, 0, attr);
-            DNSServiceAttributeDeallocate(attr);
-            if (err == kDNSServiceErr_NoError) {
-                INFO("DNSServiceUpdateRecordWithAttribute for host tsr succeed");
-            } else {
-                INFO("DNSServiceUpdateRecordWithAttribute for host tsr failed: %d", err);
-            }
-        }
-    }
-}
-
-// When we need to register a host with mDNSResponder, start_host_update is called.   This can be either because
-// we just got a new registration for a host, or if the daemon dies and we need to re-do the host registration.
-// This just registers the host; if that succeeds, then we register the service instances.
-static void
-start_host_update(adv_host_t *host)
-{
-    adv_update_t *update = host->update;
-    int err;
-    int i;
-
-    // No work to do?
-    if (update == NULL) {
-        ERROR("start_host_update: no work to do for host " PRI_S_SRP, host->registered_name);
-        return;
-    }
-
-    update->num_records_started = 0;
-
-    // Add all of the addresses that have been registered.
-    if (update->add_addresses != NULL) {
-        for (i = 0; i < update->add_addresses->num; i++) {
-            if (update->add_addresses->vec[i] != NULL) {
-                if (!register_host_record(host, update->add_addresses->vec[i])) {
-                    update_failed(update, dns_rcode_servfail, true);
-                    return;
-                } else {
-                    update->num_records_started++;
-                }
-            }
-        }
-    }
-
-    if (update->key != NULL) {
-        if (!register_host_record(host, update->key)) {
-            update_failed(update, dns_rcode_servfail, true);
-            return;
-        }
-        update->num_records_started++;
-    }
-
-    // If the shared transaction has changed since the key record was added, add it again.
-    if (update->key == NULL && host->key_record != NULL &&
-        host->key_record->shared_txn != (intptr_t)host->server_state->shared_registration_txn)
-    {
-        update->key = host->key_record;
-        RETAIN_HERE(update->key);
-        RELEASE_HERE(host->key_record, adv_record_finalize);
-        host->key_record = NULL;
-        update->key->rref = NULL;
-        update->key->update = update;
-        RETAIN_HERE(update);
-        if (!register_host_record(host, update->key)) {
-            update_failed(update, dns_rcode_servfail, true);
-            return;
-        }
-        update->num_records_started++;
-    }
-
-    if (update->num_records_started == 0) {
-        adv_record_t *record = update->key != NULL ? update->key : (host->key_record != NULL ? host->key_record : NULL);
-        if (record == NULL) {
-            INFO("no key record found.");
-        } else {
-            update_host_tsr(record);
-        }
-    }
-
-    if (host->instances != NULL) {
-        // For each service instance that's being added, register it.
-        if (update->add_instances != NULL) {
-            for (i = 0; i < update->add_instances->num; i++) {
-                if (update->add_instances->vec[i] != NULL) {
-                    if (!register_instance(update->add_instances->vec[i])) {
-                        update_failed(update, dns_rcode_servfail, true);
-                        return;
-                    }
-                }
-            }
-        }
-
-        // For each service instance that's being renewed, update its TSR if the original registration still exist,
-        // Otherwise re-register the instance.
-        if (update->renew_instances != NULL) {
-            for (i = 0; i < update->renew_instances->num; i++) {
-                if (update->renew_instances->vec[i] != NULL) {
-                    adv_instance_t *instance = update->renew_instances->vec[i];
-                    if (instance->txn != NULL) {
-                        // Make sure the instance was registered on the current shared connection.
-                        if (host->server_state != NULL &&
-                            ((intptr_t)host->server_state->shared_registration_txn == instance->shared_txn))
-                        {
-                            update_instance_tsr(instance);
-                        } else {
-                            // If not, dispose of the transaction and re-register.
-                            INFO("instance %p shared connection %" PRIxPTR " is stale, re-registering",
-                                 instance, instance->shared_txn);
-                            ioloop_dnssd_txn_cancel(instance->txn);
-                            ioloop_dnssd_txn_release(instance->txn);
-                            instance->txn = NULL;
-                            goto renew_instance;
-                        }
-                    } else {
-                        INFO("renew_instances txn is NULL, re-registering");
-                    renew_instance:
-                        if (!register_instance(update->renew_instances->vec[i])) {
-                            update_failed(update, dns_rcode_servfail, true);
-                            return;
-                        }
-                    }
-                }
-            }
-        }
-
-        // Sanity check that the instance vector sizes match between host and update.
-        if (update->update_instances != NULL && update->update_instances->num != host->instances->num) {
-            FAULT("update instance count %d differs from host instance count %d",
-                  update->update_instances->num, host->instances->num);
-            update_failed(update, dns_rcode_servfail, true);
-            return;
-        }
-        if (update->remove_instances != NULL && update->remove_instances->num != host->instances->num) {
-            FAULT("delete instance count %d differs from host instance count %d",
-                  update->remove_instances->num, host->instances->num);
-            update_failed(update, dns_rcode_servfail, true);
-            return;
-        }
-        for (i = 0; i < host->instances->num; i++) {
-            if (update->update_instances->vec[i] != NULL && !update->update_instances->vec[i]->removed) {
-                // Here we are removing a registration before we know that the update will succeed. We have no choice,
-                // because mDNSResponder doesn't provide a way to do an atomic update--we have to remove and then add.
-                // If the update as a whole fails, the host entry will remain, but the registration that we tried to
-                // update will be lost, and we don't really have a way to recover it.
-                if (host->instances->vec[i]->txn != NULL) {
-                    ioloop_dnssd_txn_cancel(host->instances->vec[i]->txn);
-                    ioloop_dnssd_txn_release(host->instances->vec[i]->txn);
-                    host->instances->vec[i]->txn = NULL;
-                }
-
-                if (!register_instance(update->update_instances->vec[i])) {
-                    INFO("register instance failed.");
-                    return;
-                }
-            }
-        }
-    }
-
-    if (update->num_instances_started == 0 && update->num_records_started == 0) {
-        INFO("no service or record updates, so we're finished.");
-        update_finished(update);
-        return;
-    }
-
-    if (__builtin_available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)) {
-        err = DNSServiceSendQueuedRequests(host->server_state->shared_registration_txn->sdref);
-        if (err == kDNSServiceErr_Invalid) {
-            INFO("no queued requests.");
-        } else {
-            process_dnsservice_error(update, err);
-        }
-    }
-}
-
-// When a host has no update in progress, and there is a client update ready to process, we need to analyze
-// the client update to see what work needs to be done.  This work is constructed as an translation from the
-// raw update sent by the client (host->clients) into a prepared update that can be used directly to
-// register the information with mDNSResponder.
-//
-// Normally a host will only have one prepared update in progress; however, if we lose our connection to
-// mDNSResponder, then we need to re-create the host advertisement.  If there was an update in progress when
-// this happened, we then need to reapply that as well.  In this case an update is constructed from the host, to
-// get the host into the intended state, and the in-progress update is pushed below that; when the host has
-// been re-created on the daemon, the pending update is popped back off the stack and restarted.
-static void
-prepare_update(adv_host_t *host, client_update_t *client_update)
-{
-    host_addr_t *addr;
-    int i, j;
-    service_instance_t *instance;
-    adv_record_vec_t *remove_addrs = NULL;
-    int num_remove_addrs = 0;
-    adv_record_vec_t *add_addrs = NULL;
-    int num_add_addrs = 0;
-    int num_update_instances = 0;
-    int num_add_instances = 0;
-    int num_remove_instances = 0;
-    int num_renew_instances = 0;
-    adv_instance_vec_t *update_instances = NULL, *add_instances = NULL;
-    adv_instance_vec_t *remove_instances = NULL, *renew_instances = NULL;
-    adv_update_t *update = NULL;
-
-    // Work to do:
-    // - Figure out what address records to add and what address records to delete.
-    // - Because we can only have one address record at a time currently, figure out which address record we want
-    // - If we already have an address record published, and it's the same, do nothing
-    //   - else if we already have an address record published, and it's changed to a different address, do an update
-    //   - else if we have a new address record, publish it
-    //   - else publish the key to hold the name
-    // - Go through the set of service instances, identifying deletes, changes and adds
-    //   - We don't currently allow deletes, but what that would look like would be an instance with no SRV or TXT
-    //     record.
-    //   - What about a delete that keeps the name but un-advertises the service?   How would we indicate that?
-    //     Maybe if there's no service PTR for the service?
-    //   - Changes means that the contents of the text record changed, or the contents of the SRV record
-    //     changed (but not the hostname) or both.
-    //   - New means that we don't have a service with that service instance name on the host (and we previously
-    //     eliminated the possibility that it exists on some other host).
-
-    // Allocate the update structure.
-    update = calloc(1, sizeof *update);
-    if (update == NULL) {
-        ERROR("no memory for update.");
-        goto fail;
-    }
-    RETAIN_HERE(update); // For the lifetime of this function
-
-    // The maximum number of addresses we could be deleting is all the ones the host currently has.
-    if (host->addresses == NULL || host->addresses->num == 0) {
-        num_remove_addrs = 0;
-        remove_addrs = NULL;
-    } else {
-        num_remove_addrs = host->addresses->num;
-        if (num_remove_addrs != 0) {
-            remove_addrs = adv_record_vec_create(num_remove_addrs);
-            // If we can't allocate space, just wait a bit.
-            if (remove_addrs == NULL) {
-                ERROR("no memory for remove_addrs");
-                goto fail;
-            }
-            remove_addrs->num = num_remove_addrs;
-        }
-    }
-
-    num_add_addrs = 0;
-    for (addr = client_update->host->addrs; addr != NULL; addr = addr->next) {
-        num_add_addrs++;
-    }
-    add_addrs = adv_record_vec_create(num_add_addrs);
-    if (add_addrs == NULL) {
-        ERROR("no memory for add_addrs");
-        goto fail;
-    }
-
-    // Copy all of the addresses in the update into add_addresses
-    num_add_addrs = 0;
-    for (addr = client_update->host->addrs; addr; addr = addr->next) {
-        bool add = true;
-        for (i = 0; i < num_add_addrs; i++) {
-            // If the client sends duplicate addresses, only add one of them.
-            if (add_addrs->vec[i] != NULL &&
-                add_addrs->vec[i]->rrtype == addr->rr.type &&
-                add_addrs->vec[i]->rdlen == (addr->rr.type == dns_rrtype_a ? 4 : 16) &&
-                !memcmp(add_addrs->vec[i]->rdata, (uint8_t *)&addr->rr.data, add_addrs->vec[i]->rdlen))
-            {
-                add = false;
-            }
-        }
-        if (add) {
-            adv_record_t *prepared_address = adv_record_create(addr->rr.type, addr->rr.type == dns_rrtype_a ? 4 : 16,
-                                                               (uint8_t *)&addr->rr.data, host);
-            if (prepared_address == NULL) {
-                ERROR("No memory for prepared address");
-                goto fail;
-            }
-            add_addrs->vec[num_add_addrs++] = prepared_address;
-        }
-    }
-    add_addrs->num = num_add_addrs;
-    for (i = 0; i < add_addrs->num; i++) {
-        if (add_addrs->vec[i] != NULL) {
-            add_addrs->vec[i]->update = update;
-            RETAIN_HERE(add_addrs->vec[i]->update);
-        }
-    }
-
-#ifdef DEBUG_HOST_RECORDS_VERBOSE
-    for (i = 0; i < 2; i++) {
-        for (j = 0; j < (i ? num_add_addrs : num_remove_addrs); j++) {
-            adv_record_t *address = i ? add_addrs->vec[j] : (host->addresses != NULL ? host->addresses->vec[j] : NULL);
-            if (address == NULL) {
-                INFO(PUB_S_SRP " before: %d NULL", i ? "add" : "rmv", j);
-            } else {
-                char foobuf[385], *foop = foobuf;
-                for (unsigned long k = 0; k < address->rdlen && k * 3 + 1 < sizeof(foobuf); k++) {
-                    snprintf(foop, 4, k ? ":%02x" : "%02x", address->rdata[k]);
-                    foop += k ? 3 : 2;
-                }
-                *foop = 0;
-                INFO(PUB_S_SRP " before: %d rrtype %d rdlen %d rdata " PRI_S_SRP, i ? "add" : "rmv", j,
-                     address->rrtype, address->rdlen, foobuf);
-            }
-        }
-    }
-#endif // DEBUG_HOST_RECORDS_VERBOSE
-
-    // For every host address, see if it's in add_addresses.   If it's not, it needs to be removed.
-    // If it is, it doesn't need to be added.
-    if (num_remove_addrs != 0) {
-        for (i = 0; i < num_remove_addrs; i++) {
-            if (host->addresses != NULL && host->addresses->vec[i] != NULL) {
-                remove_addrs->vec[i] = host->addresses->vec[i];
-                RETAIN_HERE(remove_addrs->vec[i]);
-            }
-            for (j = 0; j < num_add_addrs; j++) {
-                // If the address is present in both places, and has a valid registration, remove it from the list of
-                // addresses to add, and also remove it from the list of addresses to remove.  When we're done, all that
-                // will be remaining in the list to remove will be addresses that weren't present in the add list.
-                if (remove_addrs->vec[i] != NULL && add_addrs->vec[j] != NULL &&
-                    remove_addrs->vec[i]->rref != NULL && host->server_state != NULL &&
-                    (intptr_t)host->server_state->shared_registration_txn == remove_addrs->vec[i]->shared_txn &&
-                    add_addrs->vec[j]->rrtype == remove_addrs->vec[i]->rrtype &&
-                    add_addrs->vec[j]->rdlen == remove_addrs->vec[i]->rdlen &&
-                    !memcmp(add_addrs->vec[j]->rdata, remove_addrs->vec[i]->rdata, remove_addrs->vec[i]->rdlen))
-                {
-                    RELEASE_HERE(remove_addrs->vec[i], adv_record_finalize);
-                    remove_addrs->vec[i] = NULL;
-                    RELEASE_HERE(add_addrs->vec[j], adv_record_finalize);
-                    add_addrs->vec[j] = NULL;
-                }
-            }
-        }
-        remove_addrs->num = num_remove_addrs;
-    }
-
-#ifdef DEBUG_HOST_RECORDS_VERBOSE
-    for (i = 0; i < 2; i++) {
-        for (j = 0; j < (i ? num_add_addrs : num_remove_addrs); j++) {
-            adv_record_t *address = i ? add_addrs->vec[j] : (remove_addrs != NULL ? remove_addrs->vec[j] : NULL);
-            if (address == NULL) {
-                INFO(PUB_S_SRP "  after: %d NULL", i ? "add" : "rmv", j);
-            } else {
-                char foobuf[385], *foop = foobuf;
-                for (unsigned long k = 0; k < address->rdlen && k * 3 + 1 < sizeof(foobuf); k++) {
-                    snprintf(foop, 4, k ? ":%02x" : "%02x", address->rdata[k]);
-                    foop += k ? 3 : 2;
-                }
-                *foop = 0;
-                INFO(PUB_S_SRP "  after: %d rrtype %d rdlen %d rdata " PRI_S_SRP, i ? "add" : "rmv", j,
-                     address->rrtype, address->rdlen, foobuf);
-            }
-        }
-    }
-#endif // DEBUG_HOST_RECORDS_VERBOSE
-
-    // Make a key record
-    if (host->key_record == NULL) {
-        update->key = adv_record_create(dns_rrtype_key, host->key_rdlen, host->key_rdata, host);
-        if (update->key == NULL) {
-            ERROR("no memory for key record");
-            goto fail;
-        }
-        update->key->update = update;
-        RETAIN_HERE(update->key->update);
-    }
-
-    // We can never update more instances than currently exist for this host.
-    num_update_instances = host->instances->num;
-    num_remove_instances = host->instances->num;
-    num_renew_instances = host->instances->num;
-
-    update_instances = adv_instance_vec_create(num_update_instances);
-    if (update_instances == NULL) {
-        ERROR("no memory for update_instances");
-        goto fail;
-    }
-    update_instances->num = num_update_instances;
-
-    remove_instances = adv_instance_vec_create(num_remove_instances);
-    if (remove_instances == NULL) {
-        ERROR("no memory for remove_instances");
-        goto fail;
-    }
-    remove_instances->num = num_remove_instances;
-
-    renew_instances = adv_instance_vec_create(num_renew_instances);
-    if (renew_instances == NULL) {
-        ERROR("no memory for renew_instances");
-        goto fail;
-    }
-    renew_instances->num = num_renew_instances;
-
-    // Handle removes. Service instance removes have to remove the whole service instance, not some subset.
-    for (delete_t *dp = client_update->removes; dp; dp = dp->next) {
-        // Removes can be for services or service instances. Because we're acting as an
-        // Advertising Proxy and not a regular name server, we don't track service instances,
-        // and so we don't need to match them here. This if statement checks to see if the
-        // name could possibly be a service instance name followed by a service type. We
-        // can then extract the putative service instance name and service type and compare;
-        // if they match, they are in fact those things, and if they don't, we don't care.
-        if (dp->name != NULL && dp->name->next != NULL && dp->name->next->next != NULL) {
-            char instance_name[DNS_MAX_LABEL_SIZE_ESCAPED + 1];
-            char service_type[DNS_MAX_LABEL_SIZE_ESCAPED + 2];
-
-            dns_name_print_to_limit(dp->name, dp->name->next, instance_name, sizeof(instance_name));
-            dns_name_print_to_limit(dp->name->next, dp->name->next->next->next, service_type, sizeof(service_type));
-
-            for (i = 0; i < host->instances->num; i++) {
-                adv_instance_t *remove_instance = host->instances->vec[i];
-                if (remove_instance != NULL) {
-                    if (!strcmp(instance_name, remove_instance->instance_name) &&
-                        service_types_equal(service_type, remove_instance->service_type))
-                    {
-                        remove_instances->vec[i] = remove_instance;
-                        RETAIN_HERE(remove_instances->vec[i]);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    // The number of instances to add can be as many as there are instances in the update.
-    num_add_instances = 0;
-    for (instance = client_update->instances; instance; instance = instance->next) {
-        num_add_instances++;
-    }
-    add_instances = adv_instance_vec_create(num_add_instances);
-    if (add_instances == NULL) {
-        ERROR("prepare_update: no memory for add_instances");
-        goto fail;
-    }
-
-    // Convert all of the instances in the client update to adv_instance_t structures for easy comparison.
-    // Any that are unchanged will have to be freed--oh well.
-    i = 0;
-    for (instance = client_update->instances; instance != NULL; instance = instance->next) {
-        adv_instance_t *prepared_instance = adv_instance_create(instance, host, update);
-        if (prepared_instance == NULL) {
-            // prepare_instance logs.
-            goto fail;
-        }
-        if (i >= num_add_instances) {
-            FAULT("while preparing client update instances, i >= num_add_instances");
-            RELEASE_HERE(prepared_instance, adv_instance_finalize);
-            prepared_instance = NULL;
-            goto fail;
-        }
-        add_instances->vec[i++] = prepared_instance;
-    }
-    add_instances->num = i;
-
-    // The instances in the update are now in add_instances.  If they are updates, move them to update_instances.  If
-    // they are unchanged, free them and null them out, and remember the current instance in renew_instances.  If they
-    // are adds, leave them.
-    for (i = 0; i < num_add_instances; i++) {
-        adv_instance_t *add_instance = add_instances->vec[i];
-
-        if (add_instance != NULL) {
-            for (j = 0; j < host->instances->num; j++) {
-                adv_instance_t *host_instance = host->instances->vec[j];
-
-                // See if the instance names match.
-                if (host_instance != NULL &&
-                    !strcmp(add_instance->instance_name, host_instance->instance_name) &&
-                    !strcmp(add_instance->service_type, host_instance->service_type))
-                {
-                    // If the rdata is the same, and it's not deleted, it's not an add or an update.
-                    if (!host_instance->removed && add_instance->txt_length == host_instance->txt_length &&
-                        add_instance->port == host_instance->port &&
-                        (add_instance->txt_length == 0 ||
-                         !memcmp(add_instance->txt_data, host_instance->txt_data, add_instance->txt_length)))
-                    {
-                        RELEASE_HERE(add_instances->vec[i], adv_instance_finalize);
-                        add_instances->vec[i] = NULL;
-                        renew_instances->vec[j] = host_instance;
-                        RETAIN_HERE(host_instance);
-                        renew_instances->vec[j]->update = update;
-                        RETAIN_HERE(renew_instances->vec[j]->update);
-                        INFO(PRI_S_SRP "." PRI_S_SRP " renewed for host " PRI_S_SRP,
-                             host_instance->instance_name, host_instance->service_type, host->name);
-                    } else {
-                        update_instances->vec[j] = add_instance;
-                        RETAIN_HERE(update_instances->vec[j]);
-                        RELEASE_HERE(add_instances->vec[i], adv_instance_finalize);
-                        add_instances->vec[i] = NULL;
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-    // At this point we have figured out all the work we need to do, so hang it off an update structure.
-    update->host = host;
-    RETAIN_HERE(update->host);
-    update->client = client_update;
-    update->remove_addresses = remove_addrs;
-    update->add_addresses = add_addrs;
-    update->remove_instances = remove_instances;
-    update->add_instances = add_instances;
-    update->update_instances = update_instances;
-    update->renew_instances = renew_instances;
-    update->host_lease = client_update->host_lease;
-    update->key_lease = client_update->key_lease;
-
-    host->update = update;
-    RETAIN_HERE(host->update);
-    RELEASE_HERE(update, adv_update_finalize);
-    update = NULL;
-
-    start_host_update(host);
-    return;
-
-fail:
-    if (remove_addrs != NULL) {
-        // Addresses in remove_addrs are owned by the host and don't need to be freed.
-        RELEASE_HERE(remove_addrs, adv_record_vec_finalize);
-        remove_addrs = NULL;
-    }
-    if (add_addrs != NULL) {
-        RELEASE_HERE(add_addrs, adv_record_vec_finalize);
-        add_addrs = NULL;
-    }
-    if (add_instances != NULL) {
-        RELEASE_HERE(add_instances, adv_instance_vec_finalize);
-        add_instances = NULL;
-    }
-    if (remove_instances != NULL) {
-        RELEASE_HERE(remove_instances, adv_instance_vec_finalize);
-        remove_instances = NULL;
-    }
-    if (update_instances != NULL) {
-        RELEASE_HERE(update_instances, adv_instance_vec_finalize);
-        update_instances = NULL;
-    }
-    if (update) {
-        RELEASE_HERE(update, adv_update_finalize);
-    }
-}
-
-typedef enum { missed, match, conflict } instance_outcome_t;
-static instance_outcome_t
-compare_instance(adv_instance_t *instance,
-                 dns_host_description_t *new_host, adv_host_t *host,
-                 char *instance_name, char *service_type)
-{
-    if (instance == NULL) {
-        return missed;
-    }
-    if (host->removed) {
-        return missed;
-    }
-    if (!strcmp(instance_name, instance->instance_name) && service_types_equal(service_type, instance->service_type)) {
-        if (!dns_names_equal_text(new_host->name, host->name)) {
-            return conflict;
-        }
-        return match;
-    }
-    return missed;
-}
-
-bool
-srp_update_start(comm_t *connection, srp_server_t *server_state, srpl_connection_t *srpl_connection, dns_message_t *parsed_message, message_t *raw_message,
-                 dns_host_description_t *new_host, service_instance_t *instances, service_t *services,
-                 delete_t *removes, dns_name_t *update_zone, uint32_t lease_time, uint32_t key_lease_time,
-                 uint32_t serial_number, bool found_serial)
-{
-    adv_host_t *host, **p_hosts = NULL;
-    char pres_name[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-    service_instance_t *new_instance;
-    instance_outcome_t outcome = missed;
-    client_update_t *client_update;
-    char instance_name[DNS_MAX_LABEL_SIZE_ESCAPED + 1];
-    char service_type[DNS_MAX_LABEL_SIZE_ESCAPED * 2 + 2];
-    uint32_t key_id = 0;
-    char new_host_name[DNS_MAX_NAME_SIZE_ESCAPED + 1];
-    host_addr_t *addr;
-    const bool remove = lease_time == 0;
-    const char *updatestr = lease_time == 0 ? "remove" : "update";
-    delete_t *dp;
-    dns_name_print(new_host->name, new_host_name, sizeof new_host_name);
-
-    // Compute a checksum on the key, ignoring up to three bytes at the end.
-    for (unsigned i = 0; i < new_host->key->data.key.len; i += 4) {
-        key_id += ((new_host->key->data.key.key[i] << 24) | (new_host->key->data.key.key[i + 1] << 16) |
-                   (new_host->key->data.key.key[i + 2] << 8) | (new_host->key->data.key.key[i + 3]));
-    }
-
-    // Log the update info.
-    if (found_serial) {
-        INFO("host update for " PRI_S_SRP ", key id %" PRIx32 ", serial number %" PRIu32,
-             new_host_name, key_id, serial_number);
-    } else {
-        INFO("host update for " PRI_S_SRP ", key id %" PRIx32, new_host_name, key_id);
-    }
-    for (addr = new_host->addrs; addr != NULL; addr = addr->next) {
-        if (addr->rr.type == dns_rrtype_a) {
-            IPv4_ADDR_GEN_SRP(&addr->rr.data.a.s_addr, addr_buf);
-            INFO("host " PUB_S_SRP " for " PRI_S_SRP ", address " PRI_IPv4_ADDR_SRP, updatestr,
-                 new_host_name, IPv4_ADDR_PARAM_SRP(&addr->rr.data.a.s_addr, addr_buf));
-        } else {
-            SEGMENTED_IPv6_ADDR_GEN_SRP(addr->rr.data.aaaa.s6_addr, addr_buf);
-            INFO("host " PUB_S_SRP " for " PRI_S_SRP ", address " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                 updatestr, new_host_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(addr->rr.data.aaaa.s6_addr, addr_buf));
-        }
-    }
-    for (new_instance = instances; new_instance != NULL; new_instance = new_instance->next) {
-        extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, new_instance);
-        INFO("host " PUB_S_SRP " for " PRI_S_SRP ", instance name " PRI_S_SRP ", type " PRI_S_SRP
-             ", port %d", updatestr, new_host_name, instance_name, service_type,
-             new_instance->srv != NULL ? new_instance->srv->data.srv.port : -1);
-    }
-
-    // Look for matching service instance names.   A service instance name that matches, but has a different
-    // hostname, means that there is a conflict.   We have to look through all the entries; the presence of
-    // a matching hostname doesn't mean we are done UNLESS there's a matching service instance name pointing
-    // to that hostname.
-    for (host = server_state->hosts; host; host = host->next) {
-        // If a host has been removed, it won't have any instances to compare against. Later on, if we find that
-        // there is no matching host for this update, we look through the host list again and remove the
-        // "removed" host if it has the same name, so we don't need to do anything further here.
-        if (host->removed) {
-            continue;
-        }
-        // We need to look for matches both in the registered instances for this registration, and also in
-        // the list of new instances, in case we get a duplicate update while a previous update is in progress.
-        for (new_instance = instances; new_instance; new_instance = new_instance->next) {
-            extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, new_instance);
-
-            // First check for a match or conflict in the host itself.
-            for (int i = 0; i < host->instances->num; i++) {
-                outcome = compare_instance(host->instances->vec[i], new_host, host,
-                                           instance_name, service_type);
-                if (outcome != missed) {
-                    goto found_something;
-                }
-            }
-
-            // Then look for the same thing in any subsequent updates that have been baked.
-            if (host->update != NULL) {
-                if (host->update->add_instances != NULL) {
-                    for (int i = 0; i < host->update->add_instances->num; i++) {
-                        outcome = compare_instance(host->update->add_instances->vec[i], new_host, host,
-                                                   instance_name, service_type);
-                        if (outcome != missed) {
-                            goto found_something;
-                        }
-                    }
-                }
-            }
-        }
-    }
-found_something:
-    if (outcome == conflict) {
-        ERROR("service instance name " PRI_S_SRP "/" PRI_S_SRP " already pointing to host "
-              PRI_S_SRP ", not host " PRI_S_SRP, instance_name, service_type, host->name, new_host_name);
-        advertise_finished(NULL, host->name,
-                           server_state, srpl_connection, connection, raw_message, dns_rcode_yxdomain, NULL);
-        goto cleanup;
-    }
-
-    // We may have received removes for individual records. In this case, we need to make sure they only remove
-    // records that have been added to the host that matches.
-    for (adv_host_t *rhp = server_state->hosts; rhp != NULL; rhp = rhp->next) {
-        if (rhp->removed) {
-            continue;
-        }
-
-        // Look for removes that conflict
-        for (dp = removes; dp != NULL; dp = dp->next) {
-            // We only need to do this for service instance names. We don't really know what is and isn't a
-            // service instance name, but if it /could/ be a service instance name, we compare; if it matches,
-            // it is a service instance name, and if not, no problem.
-            if (dp->name != NULL && dp->name->next != NULL && dp->name->next->next != NULL) {
-                dns_name_print_to_limit(dp->name, dp->name->next, instance_name, sizeof(instance_name));
-                dns_name_print_to_limit(dp->name->next, dp->name->next->next->next, service_type, sizeof(service_type));
-
-                // See if the delete deletes an instance on the host
-                for (int i = 0; i < rhp->instances->num; i++) {
-                    adv_instance_t *instance = rhp->instances->vec[i];
-                    if (instance != NULL) {
-                        if (!strcmp(instance_name, instance->instance_name) &&
-                            service_types_equal(service_type, instance->service_type))
-                        {
-                            if (!strcmp(new_host_name, rhp->name)) {
-                                ERROR("remove for " PRI_S_SRP "." PRI_S_SRP " matches instance on host " PRI_S_SRP,
-                                      instance_name, service_type, rhp->name);
-                                dp->consumed = true;
-                            } else {
-                                ERROR("remove for " PRI_S_SRP "." PRI_S_SRP " conflicts with instance on host " PRI_S_SRP,
-                                      instance_name, service_type, rhp->name);
-                                advertise_finished(NULL, rhp->name, server_state, srpl_connection,
-                                                   connection, raw_message, dns_rcode_formerr, NULL);
-                                goto cleanup;
-                            }
-                        }
-                    }
-                }
-
-                // See if the remove removes an instance on an update on the host
-                if (rhp->update) {
-                    if (rhp->update->add_instances != NULL) {
-                        for (int i = 0; i < rhp->update->add_instances->num; i++) {
-                            adv_instance_t *instance = rhp->update->add_instances->vec[i];
-                            if (instance != NULL) {
-                                if (!strcmp(instance_name, instance->instance_name) &&
-                                    service_types_equal(service_type, instance->service_type))
-                                {
-                                    if (!strcmp(new_host_name, rhp->name)) {
-                                        dp->consumed = true;
-                                    } else {
-                                        ERROR("remove for " PRI_S_SRP " conflicts with instance on update to host " PRI_S_SRP,
-                                              instance->instance_name, rhp->name);
-                                        advertise_finished(NULL, rhp->name, server_state, srpl_connection,
-                                                           connection, raw_message, dns_rcode_formerr, NULL);
-                                        goto cleanup;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Log any unmatched deletes, but we don't consider these to be errors.
-    for (dp = removes; dp != NULL; dp = dp->next) {
-        if (!dp->consumed) {
-            DNS_NAME_GEN_SRP(dp->name, name_buf);
-            INFO("remove for " PRI_DNS_NAME_SRP " doesn't match any instance on any host.",
-                 DNS_NAME_PARAM_SRP(dp->name, name_buf));
-        }
-    }
-
-    // If we fall off the end looking for a matching service instance, there isn't a matching
-    // service instance, but there may be a matching host, so look for that.
-    if (outcome == missed) {
-        // Search for the new hostname in the list of hosts, which is sorted.
-        for (p_hosts = &server_state->hosts; *p_hosts; p_hosts = &host->next) {
-            host = *p_hosts;
-            int comparison = strcasecmp(new_host_name, host->name);
-            if (comparison == 0) {
-                // If we get an update for a host that was removed, and it's not also a remove,
-                // remove the host entry that's marking the remove. If this is a remove, just flag
-                // it as a miss.
-                if (host->removed) {
-                    outcome = missed;
-                    if (remove) {
-                        break;
-                    }
-                    *p_hosts = host->next;
-                    host_invalidate(host);
-                    RELEASE_HERE(host, adv_host_finalize);
-                    host = NULL;
-                    break;
-                }
-                if (key_id == host->key_id && dns_keys_rdata_equal(new_host->key, &host->key)) {
-                    outcome = match;
-                    break;
-                }
-                ERROR("update for host " PRI_S_SRP " has key id %" PRIx32
-                      " which doesn't match host key id %" PRIx32 ".",
-                      host->name, key_id, host->key_id);
-                advertise_finished(NULL, host->name, server_state, srpl_connection,
-                                   connection, raw_message, dns_rcode_yxdomain, NULL);
-                goto cleanup;
-            } else if (comparison < 0) {
-                break;
-            }
-        }
-    } else {
-        if (key_id != host->key_id || !dns_keys_rdata_equal(new_host->key, &host->key)) {
-            ERROR("new host with name " PRI_S_SRP " and key id %" PRIx32
-                  " conflicts with existing host " PRI_S_SRP " with key id %" PRIx32,
-                  new_host_name, key_id, host->name, host->key_id);
-            advertise_finished(NULL, host->name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_yxdomain, NULL);
-            goto cleanup;
-        }
-    }
-
-    // If we didn't find a matching host, we can make a new one.   When we create it, it just has
-    // a name and no records.  The update that we then construct will have the missing records.
-    // We don't want to do this for a remove, obviously.
-    if (outcome == missed) {
-        if (remove) {
-            ERROR("Remove for host " PRI_S_SRP " which doesn't exist.", new_host_name);
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_noerror, NULL);
-            goto cleanup;
-        }
-
-        host = calloc(1, sizeof *host);
-        if (host == NULL) {
-            ERROR("no memory for host data structure.");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            goto cleanup;
-        }
-        RETAIN_HERE(host);
-        host->server_state = server_state;
-        host->instances = adv_instance_vec_create(0);
-        if (host->instances == NULL) {
-            ERROR("no memory for host instance vector.");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            RELEASE_HERE(host, adv_host_finalize);
-            host = NULL;
-            goto cleanup;
-        }
-        host->addresses = adv_record_vec_create(0);
-        if (host->addresses == NULL) {
-            ERROR("no memory for host address vector.");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            RELEASE_HERE(host, adv_host_finalize);
-            host = NULL;
-            goto cleanup;
-        }
-
-        host->retry_wakeup = ioloop_wakeup_create();
-        if (host->retry_wakeup != NULL) {
-            host->lease_wakeup = ioloop_wakeup_create();
-        }
-        if (host->lease_wakeup == NULL) {
-            ERROR("no memory for wake event on host");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            RELEASE_HERE(host, adv_host_finalize);
-            host = NULL;
-            goto cleanup;
-        }
-        dns_name_print(new_host->name, pres_name, sizeof pres_name);
-        host->name = strdup(pres_name);
-        if (host->name == NULL) {
-            RELEASE_HERE(host, adv_host_finalize);
-            host = NULL;
-            ERROR("no memory for hostname.");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            goto cleanup;
-        }
-        host->key = *new_host->key;
-#ifndef __clang_analyzer__
-        // Normally this would be invalid, but we never use the name of the key record.
-        host->key.name = NULL;
-#endif
-        host->key_rdlen = new_host->key->data.key.len + 4;
-        host->key_rdata = malloc(host->key_rdlen);
-        if (host->key_rdata == NULL) {
-            RELEASE_HERE(host, adv_host_finalize);
-            host = NULL;
-            ERROR("no memory for host key.");
-            advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                               connection, raw_message, dns_rcode_servfail, NULL);
-            goto cleanup;
-        }
-        memcpy(host->key_rdata, &new_host->key->data.key.flags, 2);
-        host->key_rdata[2] = new_host->key->data.key.protocol;
-        host->key_rdata[3] = new_host->key->data.key.algorithm;
-        memcpy(&host->key_rdata[4], new_host->key->data.key.key, new_host->key->data.key.len);
-        host->key.data.key.key = &host->key_rdata[4];
-        host->key_id = key_id;
-
-        // Insert this in the list where it would have sorted.  The if test is because the optimizer doesn't notice that
-        // p_hosts can never be null here--it will always be pointing to the end of the list of hosts if we get here.
-        if (p_hosts != NULL) {
-            host->next = *p_hosts;
-            *p_hosts = host;
-        }
-        p_hosts = NULL;
-    }
-
-    // If we are already updating this host, either this is a retransmission, or it's a new transaction. In the case
-    // of a retransmission, we need to keep doing the work we've been asked to do, and hopefully we'll reply before the
-    // client gives up. In the case of a new request, we aren't ready for it yet; the client really shouldn't have sent
-    // it so quickly, but if it's behaving correctly, we should be done with the current update before it retransmits,
-    // so we can safely ignore it. If we're getting a replication update, it can't be newer than the current update.
-    // So we can ignore it--we'll send a replication update when we're done processing the client update.
-    if (host->update != NULL) {
-        INFO("dropping retransmission of in-progress update for host " PRI_S_SRP, host->name);
-#if SRP_FEATURE_REPLICATION
-        srp_replication_advertise_finished(host, host->name, server_state, srpl_connection,
-                                           connection, dns_rcode_servfail);
-#endif
-    cleanup:
-        srp_update_free_parts(instances, NULL, services, removes, new_host);
-        dns_message_free(parsed_message);
-        return true;
-    }
-
-    // If this is a remove, remove the host registrations and mark the host removed. We keep it around until the
-    // lease expires to prevent replication accidentally re-adding a removed host as a result of a bad timing
-    // coincidence.
-    if (remove) {
-        host_invalidate(host);
-        // We need to propagate the remove message.
-        if (host->message != NULL) {
-            ioloop_message_release(host->message);
-        }
-        host->message = raw_message;
-        ioloop_message_retain(host->message);
-        advertise_finished(host, new_host_name, server_state, srpl_connection,
-                           connection, raw_message, dns_rcode_noerror, NULL);
-        goto cleanup;
-    }
-
-    // At this point we have an update and a host to which to apply it.  We may already be doing an earlier
-    // update, or not.  Create a client update structure to hold the communication, so that when we are done,
-    // we can respond.
-    client_update = calloc(1, sizeof *client_update);
-    if (client_update == NULL) {
-        ERROR("no memory for host data structure.");
-        advertise_finished(NULL, new_host_name, server_state, srpl_connection,
-                           connection, raw_message, dns_rcode_servfail, NULL);
-        goto cleanup;
-    }
-
-    if (outcome == missed) {
-        INFO("New host " PRI_S_SRP ", key id %" PRIx32 , host->name, host->key_id);
-    } else {
-        if (host->registered_name != host->name) {
-            INFO("Renewing host " PRI_S_SRP ", alias " PRI_S_SRP ", key id %" PRIx32,
-                 host->name, host->registered_name, host->key_id);
-        } else {
-            INFO("Renewing host " PRI_S_SRP ", key id %" PRIx32, host->name, host->key_id);
-        }
-    }
-
-    if (host->registered_name == NULL) {
-        host->registered_name = host->name;
-    }
-
-    if (connection != NULL) {
-        client_update->connection = connection;
-        ioloop_comm_retain(client_update->connection);
-    }
-    client_update->parsed_message = parsed_message;
-    client_update->message = raw_message;
-    ioloop_message_retain(client_update->message);
-    client_update->host = new_host;
-    client_update->instances = instances;
-    client_update->services = services;
-    client_update->removes = removes;
-    client_update->update_zone = update_zone;
-    if (lease_time < server_state->max_lease_time) {
-        if (lease_time < server_state->min_lease_time) {
-            client_update->host_lease = server_state->min_lease_time;
-        } else {
-            client_update->host_lease = lease_time;
-        }
-    } else {
-        client_update->host_lease = server_state->max_lease_time;
-    }
-    if (key_lease_time < server_state->max_lease_time * 7) {
-        client_update->key_lease = key_lease_time;
-    } else {
-        client_update->key_lease = server_state->max_lease_time * 7;
-    }
-    client_update->serial_number = serial_number;
-    client_update->serial_sent = found_serial;
-
-#if SRP_FEATURE_REPLICATION
-    if (srpl_connection != NULL) {
-        host->srpl_connection = srpl_connection;
-        srpl_connection_retain(host->srpl_connection);
-    }
-#endif // SRP_FEATURE_REPLICATION
-
-    // Apply the update.
-    prepare_update(host, client_update);
-    return true;
-}
-
-void
-srp_mdns_flush(srp_server_t *server_state)
-{
-    adv_host_t *host, *host_next;
-
-    INFO("flushing all host entries.");
-    for (host = server_state->hosts; host; host = host_next) {
-        INFO("Flushing services and host entry for " PRI_S_SRP " (" PRI_S_SRP ")",
-             host->name, host->registered_name);
-        // Get rid of the updates before calling delete_host, which will fail if update is not NULL.
-        if (host->update != NULL) {
-            update_failed(host->update, dns_rcode_refused, false);
-        }
-        host_next = host->next;
-        host_remove(host);
-        RELEASE_HERE(host, adv_host_finalize);
-    }
-    server_state->hosts = NULL;
-}
-
-static void
-usage(void)
-{
-    ERROR("srp-mdns-proxy [--max-lease-time <seconds>] [--min-lease-time <seconds>] [--log-stderr]");
-    ERROR("               [--enable-replication | --disable-replication]");
-#if SRP_FEATURE_NAT64
-    ERROR("               [--enable-nat64 | --disable-nat64]");
-#endif
-    exit(1);
-}
-
-srp_server_t *
-server_state_create(const char *name, int interface_index, int max_lease_time, int min_lease_time)
-{
-    srp_server_t *server_state = calloc(1, sizeof(*server_state));
-    if (server_state == NULL || (server_state->name = strdup(name)) == NULL) {
-        ERROR("no memory for server state");
-        free(server_state);
-        return NULL;
-    }
-    server_state->advertise_interface = kDNSServiceInterfaceIndexAny;
-    server_state->max_lease_time = max_lease_time;
-    server_state->min_lease_time = min_lease_time;
-    server_state->advertise_interface = interface_index;
-    return server_state;
-}
-
-int
-main(int argc, char **argv)
-{
-    int i;
-    char *end;
-    int log_stderr = false;
-    srp_server_t *server_state = server_state_create("srp-mdns-proxy", kDNSServiceInterfaceIndexAny,
-                                                     3600 * 27, // max lease time one day plus 20%
-                                                     30);       // min lease time 30 seconds
-    if (server_state == NULL) {
-        return 1;
-    }
-
-    server_state->srp_replication_enabled = true;
-#  if SRP_FEATURE_NAT64
-    server_state->srp_nat64_enabled = true;
-#  endif
-
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "--max-lease-time")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            server_state->max_lease_time = (uint32_t)strtoul(argv[i + 1], &end, 10);
-            if (end == argv[i + 1] || end[0] != 0) {
-                usage();
-            }
-            i++;
-        } else if (!strcmp(argv[i], "--min-lease-time")) {
-            if (i + 1 == argc) {
-                usage();
-            }
-            server_state->min_lease_time = (uint32_t)strtoul(argv[i + 1], &end, 10);
-            if (end == argv[i + 1] || end[0] != 0) {
-                usage();
-            }
-            i++;
-        } else if (!strcmp(argv[i], "--log-stderr")) {
-            log_stderr = true;
-        } else if (!strcmp(argv[i], "--enable-replication")) {
-            server_state->srp_replication_enabled = true;
-        } else if (!strcmp(argv[i], "--disable-replication")) {
-            server_state->srp_replication_enabled = false;
-#if SRP_FEATURE_NAT64
-        } else if (!strcmp(argv[i], "--enable-nat64")) {
-            server_state->srp_nat64_enabled = true;
-        } else if (!strcmp(argv[i], "--disable-nat64")) {
-            server_state->srp_nat64_enabled = false;
-#endif
-        } else {
-            usage();
-        }
-    }
-
-    // Setup log category for srp-mdns-prox and dnssd-proxy.
-    OPENLOG("srp-mdns-proxy", log_stderr);
-
-    INFO("--------------------------------"
-         "srp-mdns-proxy starting, compiled on " PUB_S_SRP ", " PUB_S_SRP
-         "--------------------------------", __DATE__, __TIME__);
-
-    if (!ioloop_init()) {
-        return 1;
-    }
-
-    server_state->route_state = route_state_create(server_state, "srp-mdns-proxy");
-    if (server_state->route_state == NULL) {
-        return 1;
-    }
-
-    server_state->shared_registration_txn = dnssd_txn_create_shared();
-    if (server_state->shared_registration_txn == NULL) {
-        return 1;
-    }
-
-#if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-    if (!init_dnssd_proxy()) {
-        ERROR("main: failed to setup dnssd-proxy");
-        return 1;
-    }
-#endif // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
-
-#if STUB_ROUTER
-    if (!start_icmp_listener()) {
-        return 1;
-    }
-#endif
-
-    infrastructure_network_startup(server_state);
-
-    if (adv_ctl_init(server_state) != kDNSServiceErr_NoError) {
-        ERROR("Can't start advertising proxy control server.");
-        return 1;
-    }
-
-    // We require one open file per service and one per instance.
-    struct rlimit limits;
-    if (getrlimit(RLIMIT_NOFILE, &limits) < 0) {
-        ERROR("getrlimit failed: " PUB_S_SRP, strerror(errno));
-        return 1;
-    }
-
-    if (limits.rlim_cur < 1024) {
-        if (limits.rlim_max < 1024) {
-            INFO("file descriptor hard limit is %llu", (unsigned long long)limits.rlim_max);
-            if (limits.rlim_cur != limits.rlim_max) {
-                limits.rlim_cur = limits.rlim_max;
-            }
-        } else {
-            limits.rlim_cur = 1024;
-        }
-        if (setrlimit(RLIMIT_NOFILE, &limits) < 0) {
-            ERROR("setrlimit failed: " PUB_S_SRP, strerror(errno));
-        }
-    }
-
-    // Set up the ULA early just in case we get an early registration.
-    route_ula_setup(server_state->route_state);
-    srp_proxy_init("local");
-
-#if SRP_FEATURE_REPLICATION
-	if (server_state->srp_replication_enabled) {
-        srpl_startup(server_state);
-    }
-#endif // SRP_FEATURE_REPLICATION
-
-#if SRP_FEATURE_NAT64
-    if (server_state->srp_nat64_enabled) {
-        nat64_startup(dispatch_get_main_queue());
-    }
-#endif // SRP_FEATURE_NAT64
-
-    ioloop();
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-mdns-proxy.h b/ServiceRegistration/srp-mdns-proxy.h
deleted file mode 100644
index 75d380f..0000000
--- a/ServiceRegistration/srp-mdns-proxy.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/* srp-mdns-proxy.h
- *
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains structure definitions used by the SRP Advertising Proxy.
- */
-
-#ifndef __SRP_MDNS_PROXY_H__
-#define __SRP_MDNS_PROXY_H__ 1
-
-#include <stddef.h> // For ptrdiff_t
-#include "ioloop-common.h" // for service_connection_t
-
-typedef struct adv_instance adv_instance_t;
-typedef struct adv_record_registration adv_record_t;
-typedef struct adv_host adv_host_t;
-typedef struct adv_update adv_update_t;
-typedef struct client_update client_update_t;
-typedef struct adv_instance_vec adv_instance_vec_t;
-typedef struct adv_record_vec adv_record_vec_t;
-typedef struct srpl_connection srpl_connection_t;
-typedef struct srp_server_state srp_server_t;
-typedef struct route_state route_state_t;
-typedef struct srp_wanted_state srp_wanted_state_t; // private
-typedef struct srp_xpc_client srp_xpc_client_t;     // private
-typedef struct srpl_domain srpl_domain_t;           // private
-
-// Server internal state
-struct srp_server_state {
-    char *NULLABLE name;
-    adv_host_t *NULLABLE hosts;
-    dnssd_txn_t *NULLABLE shared_registration_txn;
-    dnssd_txn_t *NULLABLE srpl_advertise_txn;
-    srpl_domain_t *NULLABLE srpl_domains;
-    route_state_t *NULLABLE route_state;
-    io_t *NULLABLE adv_ctl_listener;
-    wakeup_t *NULLABLE srpl_register_wakeup;
-    wakeup_t *NULLABLE srpl_browse_wakeup;
-    uint64_t server_id; // SRP replication server ID
-    struct in6_addr ula_prefix;
-    int advertise_interface;
-
-
-    uint32_t max_lease_time;
-    uint32_t min_lease_time; // thirty seconds
-
-    bool srp_replication_enabled;
-#if SRP_FEATURE_NAT64
-    bool srp_nat64_enabled;
-#endif
-};
-
-struct adv_instance {
-    int ref_count;
-    dnssd_txn_t *NULLABLE txn;           // The dnssd_txn_t that was created from the shared connection.
-    intptr_t shared_txn;                 // The shared txn on which the txn for this instance's registration was created
-    adv_host_t *NULLABLE host;           // Host to which this service instance belongs
-    adv_update_t *NULLABLE update;       // Ongoing update that currently owns this instance, if any.
-    char *NONNULL instance_name;         // Single label instance name (future: service instance FQDN)
-    char *NONNULL service_type;          // Two label service type (e.g., _ipps._tcp)
-    int port;                            // Port on which service can be found.
-    char *NULLABLE txt_data;             // Contents of txt record
-    uint16_t txt_length;                 // length of txt record contents
-    message_t *NULLABLE message;         // Message that produces the current value of this instance
-    ptrdiff_t recent_message;            // Most recent message (never dereference--this is for comparison only).
-    int64_t lease_expiry;                // Time when lease expires, relative to ioloop_timenow().
-    bool removed;                        // True if this instance is being kept around for replication.
-    bool update_pending;                 // True if we got a conflict while updating and are waiting to try again
-};
-
-// A record registration
-struct adv_record_registration {
-    int ref_count;
-    DNSRecordRef NULLABLE rref;            // The RecordRef we get back from DNSServiceRegisterRecord().
-    adv_host_t *NULLABLE host;             // The host object to which this record refers.
-    intptr_t shared_txn;                   // The shared transaction on which this record was registered.
-    adv_update_t *NULLABLE update;         // The ongoing update, if any
-    uint8_t *NULLABLE rdata;
-    uint16_t rrtype;                       // For hosts, always A or AAAA, for instances always TXT, PTR or SRV.
-    uint16_t rdlen;                        // Length of the RR
-    bool update_pending;                   // True if we are updating this record and haven't gotten a response yet.
-};
-
-struct adv_host {
-    int ref_count;
-    srp_server_t *NULLABLE server_state;   // Server state to which this host belongs.
-    wakeup_t *NONNULL retry_wakeup;        // Wakeup for retry when we run into a temporary failure
-    wakeup_t *NONNULL lease_wakeup;        // Wakeup at least expiry time
-    service_connection_t *NULLABLE conn;   // Connection handler to mDNSResponder that shares DNSServiceRef with others.
-    adv_host_t *NULLABLE next;             // Hosts are maintained in a linked list.
-    adv_update_t *NULLABLE update;         // Update to this host, if one is being done
-    char *NONNULL name;                    // Name of host (without domain)
-    char *NULLABLE registered_name;        // The name that is registered, which may be different due to mDNS conflict
-    message_t *NULLABLE message;           // Most recent successful SRP update for this host
-    srpl_connection_t *NULLABLE srpl_connection; // SRP replication server that is currently updating this host.
-    int name_serial;                       // The number we are using to disambiguate the name.
-    adv_record_vec_t *NULLABLE addresses;  // One or more address records
-    adv_record_t *NULLABLE key_record;     // Key record, if we registered that.
-    adv_instance_vec_t *NULLABLE instances; // Zero or more service instances.
-
-    dns_rr_t key;                          // The key data represented as an RR; key->name is NULL.
-    uint32_t key_id;                       // A possibly-unique id that is computed across the key for brevity in
-                                           // debugging
-    int retry_interval;                    // Interval to wait before attempting to re-register after the daemon has
-                                           // died.
-    time_t update_time;                    // Time when the update completed.
-    uint64_t update_server_id;             // Server ID from server that sent the update
-    uint64_t server_stable_id;             // Stable ID of server that got update from client (we're using server ULA).
-    uint16_t key_rdlen;                    // Length of key
-    uint8_t *NULLABLE key_rdata;           // Raw KEY rdata, suitable for DNSServiceRegisterRecord().
-    uint32_t lease_interval;               // Interval for address lease
-    uint32_t key_lease;                    // Interval for key lease
-    uint32_t serial_number;                // Client's serial number
-    bool have_serial_number;               // True if we have received or generate a serial number.
-    int64_t lease_expiry;                  // Time when lease expires, relative to ioloop_timenow().
-    bool removed;                          // True if this host has been removed (and is being kept for replication)
-
-    // True if we have a pending late conflict resolution. If we get a conflict after the update for the
-    // host registration has expired, and there happens to be another update in progress, then we want
-    // to defer the host registration.
-    bool update_pending;
-};
-
-struct adv_update {
-    int ref_count;
-
-    adv_host_t *NULLABLE host;              // Host being updated
-
-    // Ordinarily NULL, but may be non-NULL if we lost the server during an update and had
-    // to construct an update to re-add the host.
-    adv_update_t *NULLABLE next;
-
-    // Connection state, if applicable, of the client request that produced this update.
-    client_update_t *NULLABLE client;
-    int num_outstanding_updates;   // Total count updates that have been issued but not yet confirmed.
-
-    // Addresses to apply to the host.  At present only one address is ever advertised, but we remember all the
-    // addresses that were registered.
-    adv_record_vec_t *NULLABLE remove_addresses;
-    adv_record_vec_t *NULLABLE add_addresses;
-
-    // If non-null, this update is changing the advertised address of the host to the referenced address.
-    adv_record_t *NULLABLE key;
-
-    // The set of instances from the update that already exist but have changed.
-    // This array mirrors the array of instances configured on the host; entries to be updated
-    // are non-NULL, entries that don't need updated are NULL.
-    adv_instance_vec_t *NONNULL update_instances;
-
-    // The set of instances that exist and need to be removed.
-    adv_instance_vec_t *NONNULL remove_instances;
-
-    // The set of instances that exist and were renewed
-    adv_instance_vec_t *NONNULL renew_instances;
-
-    // The set of instances that need to be added.
-    adv_instance_vec_t *NONNULL add_instances;
-
-    // Outstanding instance updates
-    int num_instances_started;
-    int num_instances_completed;
-
-    // Outstanding record updates
-    int num_records_started;
-    int num_records_completed;
-
-    // Lease intervals for host entry and key entry.
-    uint32_t host_lease, key_lease;
-
-    // If nonzero, this is an explicit expiry time for the lease, because the update is restoring
-    // a host after a server restart, or else renaming a host after a late name conflict. In this
-    // case, we do not want to extend the lease--just get the host registration right.
-    int64_t lease_expiry;
-
-    // True if we are registering the key to hold the hostname.
-    bool registering_key;
-};
-
-struct adv_instance_vec {
-    int ref_count;
-    int num;
-    adv_instance_t * NULLABLE *NONNULL vec;
-};
-
-struct adv_record_vec {
-    int ref_count;
-    int num;
-    adv_record_t * NULLABLE *NONNULL vec;
-};
-
-struct client_update {
-    client_update_t *NULLABLE next;
-    comm_t *NONNULL connection;               // Connection on which in-process update was received.
-    dns_message_t *NONNULL parsed_message;    // Message that triggered the update.
-    message_t *NONNULL message;               // Message that triggered the update.
-
-    dns_host_description_t *NONNULL host;     // Host data parsed from message
-    service_instance_t *NULLABLE instances;   // Service instances parsed from message
-    service_t *NONNULL services;              // Services parsed from message
-    delete_t *NULLABLE removes;               // Removes parsed from message
-    dns_name_t *NONNULL update_zone;          // Zone being updated
-    uint32_t host_lease, key_lease;           // Lease intervals for host entry and key entry.
-    uint32_t serial_number;                   // Serial number sent by client, if one was sent
-    bool serial_sent;                         // True if serial number was sent.
-};
-
-// Exported functions.
-#define srp_adv_host_release(host) srp_adv_host_release_(host, __FILE__, __LINE__)
-void srp_adv_host_release_(adv_host_t *NONNULL host, const char *NONNULL file, int line);
-#define srp_adv_host_retain(host) srp_adv_host_retain_(host, __FILE__, __LINE__)
-void srp_adv_host_retain_(adv_host_t *NONNULL host, const char *NONNULL file, int line);
-#define srp_adv_host_copy(server_state, name) srp_adv_host_copy_(server_state, name, __FILE__, __LINE__)
-adv_host_t *NULLABLE srp_adv_host_copy_(srp_server_t *NONNULL server_state, dns_name_t *NONNULL name, const char *NONNULL file, int line);
-bool srp_adv_host_is_homekit_accessory(srp_server_t *NONNULL server_state, addr_t *NONNULL address);
-int srp_current_valid_host_count(srp_server_t *NONNULL server_state);
-int srp_hosts_to_array(srp_server_t *NONNULL server_state, adv_host_t *NONNULL *NULLABLE host_array, int max_hosts);
-bool srp_adv_host_valid(adv_host_t *NONNULL host);
-srp_server_t *NULLABLE server_state_create(const char *NONNULL name, int interface_index, int max_lease_time, int min_lease_time);
-#endif // __SRP_MDNS_PROXY_H__
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-parse.c b/ServiceRegistration/srp-parse.c
deleted file mode 100644
index d7c85e3..0000000
--- a/ServiceRegistration/srp-parse.c
+++ /dev/null
@@ -1,953 +0,0 @@
-/* srp-parse.c
- *
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains support routines for the DNSSD SRP update and mDNS proxies.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <dns_sd.h>
-#include <inttypes.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dnssd-proxy.h"
-#include "srp-gw.h"
-#include "config-parse.h"
-#include "srp-proxy.h"
-
-static dns_name_t *service_update_zone; // The zone to update when we receive an update for default.service.arpa.
-
-// Free the data structures into which the SRP update was parsed.   The pointers to the various DNS objects that these
-// structures point to are owned by the parsed DNS message, and so these do not need to be freed here.
-void
-srp_update_free_parts(service_instance_t *service_instances, service_instance_t *added_instances,
-                      service_t *services, delete_t *removes, dns_host_description_t *host_description)
-{
-    service_instance_t *sip;
-    service_t *sp;
-    delete_t *dp;
-
-    for (sip = service_instances; sip; ) {
-        service_instance_t *next = sip->next;
-        free(sip);
-        sip = next;
-    }
-    for (sip = added_instances; sip; ) {
-        service_instance_t *next = sip->next;
-        free(sip);
-        sip = next;
-    }
-    for (sp = services; sp; ) {
-        service_t *next = sp->next;
-        free(sp);
-        sp = next;
-    }
-    for (dp = removes; dp != NULL; ) {
-        delete_t *next = dp->next;
-        free(dp);
-        dp = next;
-    }
-    if (host_description != NULL) {
-        host_addr_t *host_addr, *next;
-        for (host_addr = host_description->addrs; host_addr; host_addr = next) {
-            next = host_addr->next;
-            free(host_addr);
-        }
-        free(host_description);
-    }
-}
-
-static bool
-add_host_addr(host_addr_t **dest, dns_rr_t *rr)
-{
-    host_addr_t *addr = calloc(1, sizeof *addr);
-    if (addr == NULL) {
-        ERROR("add_host_addr: no memory for record");
-        return false;
-    }
-
-    while (*dest) {
-        dest = &(*dest)->next;
-    }
-    *dest = addr;
-    addr->rr = *rr;
-    return true;
-}
-
-static bool
-replace_zone_name(dns_name_t **nzp_in, dns_name_t *uzp, dns_name_t *replacement_zone)
-{
-    dns_name_t **nzp = nzp_in;
-    while (*nzp != NULL && *nzp != uzp) {
-        nzp = &((*nzp)->next);
-    }
-    if (*nzp == NULL) {
-        ERROR("replace_zone: dns_name_subdomain_of returned bogus pointer.");
-        return false;
-    }
-
-    // Free the suffix we're replacing
-    dns_name_free(*nzp);
-
-    // Replace it.
-    *nzp = dns_name_copy(replacement_zone);
-    if (*nzp == NULL) {
-        ERROR("replace_zone_name: no memory for replacement zone");
-        return false;
-    }
-    return true;
-}
-
-// We call advertise_finished when a client request has finished, successfully or otherwise.
-static void
-send_fail_response(comm_t *connection, message_t *message, int rcode)
-{
-    struct iovec iov;
-    dns_wire_t response;
-
-    INFO("rcode = " PUB_S_SRP, dns_rcode_name(rcode));
-    memset(&response, 0, DNS_HEADER_SIZE);
-    response.id = message->wire.id;
-    response.bitfield = message->wire.bitfield;
-    dns_rcode_set(&response, rcode);
-    dns_qr_set(&response, dns_qr_response);
-
-    iov.iov_base = &response;
-    iov.iov_len = DNS_HEADER_SIZE;
-
-    ioloop_send_message(connection, message, &iov, 1);
-}
-
-static int
-make_delete(delete_t **delete_list, delete_t **delete_out, dns_rr_t *rr, dns_name_t *update_zone)
-{
-    int status = dns_rcode_noerror;
-    delete_t *dp, **dpp;
-
-    for (dpp = delete_list; *dpp;) {
-        dp = *dpp;
-        if (dns_names_equal(dp->name, rr->name)) {
-            DNS_NAME_GEN_SRP(rr->name, name_buf);
-            ERROR("two deletes for the same name: " PRI_DNS_NAME_SRP,
-                  DNS_NAME_PARAM_SRP(rr->name, name_buf));
-            return dns_rcode_formerr;
-        }
-        dpp = &dp->next;
-    }
-    dp = calloc(1, sizeof *dp);
-    if (!dp) {
-        ERROR("no memory.");
-        return dns_rcode_servfail;
-    }
-    // Add to the deletes list
-    *dpp = dp;
-
-    // Make sure the name is a subdomain of the zone being updated.
-    dp->zone = dns_name_subdomain_of(rr->name, update_zone);
-    if (dp->zone == NULL) {
-        DNS_NAME_GEN_SRP(update_zone, update_zone_buf);
-        DNS_NAME_GEN_SRP(rr->name, name_buf);
-        ERROR("delete for record not in update zone " PRI_DNS_NAME_SRP ": " PRI_DNS_NAME_SRP,
-              DNS_NAME_PARAM_SRP(update_zone, update_zone_buf), DNS_NAME_PARAM_SRP(rr->name, name_buf));
-        status = dns_rcode_formerr;
-        goto out;
-    }
-    dp->name = rr->name;
-    if (delete_out != NULL) {
-        *delete_out = dp;
-    }
-out:
-    if (status != dns_rcode_noerror) {
-        free(dp);
-    }
-    return status;
-}
-
-// Find a delete in the delete list that has target as its target.
-static delete_t *
-srp_find_delete(delete_t *deletes, dns_rr_t *target)
-{
-    for (delete_t *dp = deletes; dp; dp = dp->next) {
-        if (dns_names_equal(dp->name, target->name)) {
-            return dp;
-        }
-    }
-    return NULL;
-}
-
-bool
-srp_evaluate(comm_t *connection, srp_server_t *server_state, srpl_connection_t *srpl_connection,
-             dns_message_t *message, message_t *raw_message)
-{
-    unsigned i;
-    dns_host_description_t *host_description = NULL;
-    delete_t *deletes = NULL, *dp, **dpp = NULL, **rpp = NULL, *removes = NULL;
-    service_instance_t *service_instances = NULL, *sip, **sipp = &service_instances;
-    service_t *services = NULL, *sp, **spp = &services;
-    dns_rr_t *signature;
-    bool ret = false;
-    struct timeval now;
-    dns_name_t *update_zone, *replacement_zone;
-    dns_name_t *uzp;
-    dns_rr_t *key = NULL;
-    dns_rr_t **keys = NULL;
-    unsigned num_keys = 0;
-    unsigned max_keys = 1;
-    bool found_key = false;
-    uint32_t lease_time, key_lease_time, serial_number;
-    dns_edns0_t *edns0;
-    int rcode = dns_rcode_servfail;
-    bool found_lease = false;
-    bool found_serial = false;
-    char namebuf1[DNS_MAX_NAME_SIZE], namebuf2[DNS_MAX_NAME_SIZE];
-
-    // Update requires a single SOA record as the question
-    if (message->qdcount != 1) {
-        ERROR("update received with qdcount > 1");
-        return false;
-    }
-
-    // Update should contain zero answers.
-    if (message->ancount != 0) {
-        ERROR("update received with ancount > 0");
-        return false;
-    }
-
-    if (message->questions[0].type != dns_rrtype_soa) {
-        ERROR("update received with rrtype %d instead of SOA in question section.",
-              message->questions[0].type);
-        return false;
-    }
-
-    update_zone = message->questions[0].name;
-    if (service_update_zone != NULL && dns_names_equal_text(update_zone, "default.service.arpa.")) {
-        INFO(PRI_S_SRP " is in default.service.arpa, using replacement zone: " PUB_S_SRP,
-             dns_name_print(update_zone, namebuf2, sizeof(namebuf2)),
-             dns_name_print(service_update_zone, namebuf1, sizeof(namebuf1)));
-        replacement_zone = service_update_zone;
-    } else {
-        INFO(PRI_S_SRP " is not in default.service.arpa, or no replacement zone (%p)",
-             dns_name_print(update_zone, namebuf2, sizeof(namebuf2)), service_update_zone);
-        replacement_zone = NULL;
-    }
-
-    // Scan over the authority RRs; do the delete consistency check.  We can't do other consistency checks
-    // because we can't assume a particular order to the records other than that deletes have to come before
-    // adds.
-    for (i = 0; i < message->nscount; i++) {
-        dns_rr_t *rr = &message->authority[i];
-
-        // If this is a delete for all the RRs on a name, record it in the list of deletes.
-        if (rr->type == dns_rrtype_any && rr->qclass == dns_qclass_any && rr->ttl == 0) {
-            int status = make_delete(&deletes, NULL, rr, update_zone);
-            if (status != dns_rcode_noerror) {
-                rcode = status;
-                goto out;
-            }
-        }
-
-        // The update should really only contain one key, but it's allowed for keys to appear on
-        // service instance names as well, since that's what will be stored in the zone.   So if
-        // we get one key, we'll assume it's a host key until we're done scanning, and then check.
-        // If we get more than one, we allocate a buffer and store all the keys so that we can
-        // check them all later.
-        else if (rr->type == dns_rrtype_key) {
-            if (num_keys < 1) {
-                key = rr;
-                num_keys++;
-            } else {
-                if (num_keys == 1) {
-                    // We can't have more keys than there are authority records left, plus
-                    // one for the key we already have, so allocate a buffer that large.
-                    max_keys = message->nscount - i + 1;
-                    keys = calloc(max_keys, sizeof *keys);
-                    if (keys == NULL) {
-                        ERROR("no memory");
-                        goto out;
-                    }
-                    keys[0] = key;
-                }
-                if (num_keys >= max_keys) {
-                    ERROR("coding error in key allocation");
-                    goto out;
-                }
-                keys[num_keys++] = rr;
-            }
-        }
-
-        // Otherwise if it's an A or AAAA record, it's part of a hostname entry.
-        else if (rr->type == dns_rrtype_a || rr->type == dns_rrtype_aaaa) {
-            // Allocate the hostname record
-            if (!host_description) {
-                host_description = calloc(1, sizeof *host_description);
-                if (!host_description) {
-                    ERROR("no memory");
-                    goto out;
-                }
-            }
-
-            // Make sure it's preceded by a deletion of all the RRs on the name.
-            if (!host_description->delete) {
-                dp = srp_find_delete(deletes, rr);
-                if (dp == NULL) {
-                    DNS_NAME_GEN_SRP(rr->name, name_buf);
-                    ERROR("ADD for hostname " PRI_DNS_NAME_SRP " without a preceding delete.",
-                          DNS_NAME_PARAM_SRP(rr->name, name_buf));
-                    rcode = dns_rcode_formerr;
-                    goto out;
-                }
-                host_description->delete = dp;
-                host_description->name = dp->name;
-                dp->consumed = true; // This delete is accounted for.
-
-                // In principle, we should be checking this name to see that it's a subdomain of the update
-                // zone.  However, it turns out we don't need to, because the /delete/ has to be a subdomain
-                // of the update zone, and we won't find that delete if it's not present.
-            }
-
-            if (rr->type == dns_rrtype_a || rr->type == dns_rrtype_aaaa) {
-                if (!add_host_addr(&host_description->addrs, rr)) {
-                    goto out;
-                }
-            }
-        }
-
-        // Otherwise if it's an SRV entry, that should be a service instance name.
-        else if (rr->type == dns_rrtype_srv || rr->type == dns_rrtype_txt) {
-            // Should be a delete that precedes this service instance.
-            dp = srp_find_delete(deletes, rr);
-            if (dp == NULL) {
-                DNS_NAME_GEN_SRP(rr->name, name_buf);
-                ERROR("ADD for service instance not preceded by delete: " PRI_DNS_NAME_SRP,
-                      DNS_NAME_PARAM_SRP(rr->name, name_buf));
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            for (sip = service_instances; sip; sip = sip->next) {
-                if (dns_names_equal(sip->name, rr->name)) {
-                    break;
-                }
-            }
-            if (!sip) {
-                sip = calloc(1, sizeof *sip);
-                if (sip == NULL) {
-                    ERROR("no memory");
-                    goto out;
-                }
-                sip->delete = dp;
-                dp->consumed = true;
-                sip->name = dp->name;
-                // Add to the service instances list
-                *sipp = sip;
-                sipp = &sip->next;
-            }
-            if (rr->type == dns_rrtype_srv) {
-                if (sip->srv != NULL) {
-                    DNS_NAME_GEN_SRP(rr->name, name_buf);
-                    ERROR("more than one SRV rr received for service instance: " PRI_DNS_NAME_SRP,
-                          DNS_NAME_PARAM_SRP(rr->name, name_buf));
-                    rcode = dns_rcode_formerr;
-                    goto out;
-                }
-                sip->srv = rr;
-            } else if (rr->type == dns_rrtype_txt) {
-                if (sip->txt != NULL) {
-                    DNS_NAME_GEN_SRP(rr->name, name_buf);
-                    ERROR("more than one TXT rr received for service instance: " PRI_DNS_NAME_SRP,
-                          DNS_NAME_PARAM_SRP(rr->name, name_buf));
-                    rcode = dns_rcode_formerr;
-                    goto out;
-                }
-                sip->txt = rr;
-            }
-        }
-
-        // Otherwise if it's a PTR entry, that should be a service name
-        else if (rr->type == dns_rrtype_ptr) {
-            service_t *base_type = NULL;
-
-            // See if the service is a subtype. If it is, it should be preceded in the list of RRs in
-            // the update by a PTR record for the base service type. E.g., if there is a PTR for
-            // _foo._sub._ipps._tcp.default.service.arpa, there should, earlier in the SRP update,
-            // be a PTR for _ipps._tcp.default.service.arpa. Both the base type and the subtype PTR
-            // records must have the same target.
-            if (rr->name != NULL &&
-                rr->name->next != NULL && rr->name->next->next != NULL && !strcmp(rr->name->next->data, "_sub"))
-            {
-                dns_name_t *base_type_name = rr->name->next->next;
-                for (base_type = services; base_type != NULL; base_type = base_type->next) {
-                    if (!dns_names_equal(base_type->rr->data.ptr.name, rr->data.ptr.name)) {
-                        continue;
-                    }
-                    if (dns_names_equal(base_type->rr->name, base_type_name)) {
-                        break;
-                    }
-                }
-                if (base_type == NULL) {
-                    DNS_NAME_GEN_SRP(rr->name, name_buf);
-                    DNS_NAME_GEN_SRP(rr->data.ptr.name, target_name_buf);
-                    ERROR("service subtype " PRI_DNS_NAME_SRP " for " PRI_DNS_NAME_SRP
-                          " has no preceding base type ", DNS_NAME_PARAM_SRP(rr->name, name_buf),
-                          DNS_NAME_PARAM_SRP(rr->data.ptr.name, target_name_buf));
-                    rcode = dns_rcode_formerr;
-                    goto out;
-                }
-            }
-
-            // If qclass is none and ttl is zero, this is a delete specific RR from RRset, not an add RR to RRset.
-            if (rr->qclass == dns_qclass_none && rr->ttl == 0) {
-                int status = make_delete(&deletes, &dp, rr, update_zone);
-                if (status != dns_rcode_noerror) {
-                    rcode = status;
-                    goto out;
-                }
-            } else {
-                sp = calloc(1, sizeof *sp);
-                if (sp == NULL) {
-                    ERROR("no memory");
-                    goto out;
-                }
-
-                // Add to the services list
-                *spp = sp;
-                spp = &sp->next;
-                sp->rr = rr;
-                if (base_type != NULL) {
-                    sp->base_type = base_type;
-                } else {
-                    sp->base_type = sp;
-                }
-
-                // Make sure the service name is in the update zone.
-                sp->zone = dns_name_subdomain_of(sp->rr->name, update_zone);
-                if (sp->zone == NULL) {
-                    DNS_NAME_GEN_SRP(rr->name, name_buf);
-                    DNS_NAME_GEN_SRP(rr->data.ptr.name, data_name_buf);
-                    ERROR("service name " PRI_DNS_NAME_SRP " for " PRI_DNS_NAME_SRP
-                          " is not in the update zone", DNS_NAME_PARAM_SRP(rr->name, name_buf),
-                          DNS_NAME_PARAM_SRP(rr->data.ptr.name, data_name_buf));
-                    rcode = dns_rcode_formerr;
-                    goto out;
-                }
-            }
-        }
-
-        // Otherwise it's not a valid update
-        else {
-            DNS_NAME_GEN_SRP(rr->name, name_buf);
-            ERROR("unexpected rrtype %d on " PRI_DNS_NAME_SRP " in update.", rr->type,
-                  DNS_NAME_PARAM_SRP(rr->name, name_buf));
-            rcode = dns_rcode_formerr;
-            goto out;
-        }
-    }
-
-    // Now that we've scanned the whole update, do the consistency checks for updates that might
-    // not have come in order.
-
-    // Get the lease time. We need this to differentiate between a mass host deletion and an add.
-    lease_time = 3600;
-    key_lease_time = 604800;
-    serial_number = 0;
-    for (edns0 = message->edns0; edns0; edns0 = edns0->next) {
-        if (edns0->type == dns_opt_update_lease) {
-            unsigned off = 0;
-            if (edns0->length != 4 && edns0->length != 8) {
-                ERROR("edns0 update-lease option length bogus: %d", edns0->length);
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            dns_u32_parse(edns0->data, edns0->length, &off, &lease_time);
-            if (edns0->length == 8) {
-                dns_u32_parse(edns0->data, edns0->length, &off, &key_lease_time);
-            } else {
-                key_lease_time = 7 * lease_time;
-            }
-            found_lease = true;
-        } else if (edns0->type == dns_opt_srp_serial) {
-            unsigned off = 0;
-            if (edns0->length != 4) {
-                ERROR("edns0 srp serial number length bogus: %d", edns0->length);
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            dns_u32_parse(edns0->data, edns0->length, &off, &serial_number);
-            found_serial = true;
-        }
-    }
-
-    // If we don't yet have a host description, but this is a delete of the entire host registration (lease_time == 0) and
-    // we do have a delete record and a key record for the host, create a host description with no addresses here.
-    if (host_description == NULL && lease_time == 0) {
-        // If we get here and we have a key, then that suggests that this SRP update is a host remove with a KEY RR to
-        // authenticate it (and possibly leave behind).
-        if (key != NULL) {
-            dp = srp_find_delete(deletes, key);
-            if (dp != NULL) {
-                host_description = calloc(1, sizeof *host_description);
-                if (host_description == NULL) {
-                    ERROR("no memory");
-                    goto out;
-                }
-                host_description->delete = dp;
-                host_description->name = dp->name;
-                dp->consumed = true; // This delete is accounted for.
-            }
-        }
-    }
-    // Make sure there's a host description.
-    if (!host_description) {
-        ERROR("SRP update does not include a host description.");
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-
-    // Make sure that each service add references a service instance that's in the same update.
-    for (sp = services; sp; sp = sp->next) {
-        // A service instance can never point to a service subtype--it has to point to the base type.
-        if (sp->base_type != sp) {
-            continue;
-        }
-        for (sip = service_instances; sip; sip = sip->next) {
-            if (dns_names_equal(sip->name, sp->rr->data.ptr.name)) {
-                // Note that we have already verified that there is only one service instance
-                // with this name, so this could only ever happen once in this loop even without
-                // the break statement.
-                sip->service = sp;
-                sip->num_instances++;
-                break;
-            }
-        }
-        // If this service doesn't point to a service instance that's in the update, then the
-        // update fails validation.
-        if (sip == NULL) {
-            DNS_NAME_GEN_SRP(sp->rr->name, name_buf);
-            ERROR("service points to an instance that's not included: " PRI_DNS_NAME_SRP,
-                  DNS_NAME_PARAM_SRP(sp->rr->name, name_buf));
-            rcode = dns_rcode_formerr;
-            goto out;
-        }
-    }
-
-    for (sip = service_instances; sip; sip = sip->next) {
-        // For each service instance, make sure that at least one service references it
-        if (sip->num_instances == 0) {
-            DNS_NAME_GEN_SRP(sip->name, name_buf);
-            ERROR("service instance update for " PRI_DNS_NAME_SRP
-                  " is not referenced by a service update.", DNS_NAME_PARAM_SRP(sip->name, name_buf));
-            rcode = dns_rcode_formerr;
-            goto out;
-        }
-
-        // For each service instance, make sure that it references the host description
-        if (dns_names_equal(host_description->name, sip->srv->data.srv.name)) {
-            sip->host = host_description;
-            host_description->num_instances++;
-        }
-    }
-
-    // Make sure that at least one service instance references the host description, unless the update is deleting the host address records.
-#ifdef REJECT_HOST_WITHOUT_SERVICES
-    if (host_description->num_instances == 0 && host_description->addrs != NULL) {
-        DNS_NAME_GEN_SRP(host_description->name, name_buf);
-        ERROR("host description " PRI_DNS_NAME_SRP " is not referenced by any service instances.",
-              DNS_NAME_PARAM_SRP(host_description->name, name_buf));
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-
-    // Make sure the host description has at least one address record, unless we're deleting the host.
-    if (host_description->addrs == NULL && host_description->num_instances != 0 && lease_time != 0) {
-        DNS_NAME_GEN_SRP(host_description->name, name_buf);
-        ERROR("host description " PRI_DNS_NAME_SRP " doesn't contain any IP addresses, but services are being added.",
-              DNS_NAME_PARAM_SRP(host_description->name, name_buf));
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-#endif
-
-    for (i = 0; i < num_keys; i++) {
-        // If this isn't the only key, make sure it's got the same contents as the other keys.
-        if (i > 0) {
-            if (!dns_keys_rdata_equal(key, keys[i])) {
-                ERROR("more than one key presented");
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            // This is a hack so that if num_keys == 1, we don't have to allocate keys[].
-            // At the bottom of this if statement, key is always the key we are looking at.
-            key = keys[i];
-        }
-        // If there is a key, and the host description doesn't currently have a key, check
-        // there first since that's the default.
-        if (host_description->key == NULL && dns_names_equal(key->name, host_description->name)) {
-            host_description->key = key;
-            found_key = true;
-        } else {
-            for (sip = service_instances; sip != NULL; sip = sip->next) {
-                if (dns_names_equal(sip->name, key->name)) {
-                    found_key = true;
-                    break;
-                }
-            }
-        }
-        if (!found_key) {
-            DNS_NAME_GEN_SRP(key->name, key_name_buf);
-            ERROR("key present for name " PRI_DNS_NAME_SRP
-                  " which is neither a host nor an instance name.", DNS_NAME_PARAM_SRP(key->name, key_name_buf));
-            rcode = dns_rcode_formerr;
-            goto out;
-        }
-    }
-    if (keys != NULL) {
-        free(keys);
-        keys = NULL;
-    }
-
-    // And make sure it has a key record
-    if (host_description->key == NULL) {
-        DNS_NAME_GEN_SRP(host_description->name, host_name_buf);
-        ERROR("host description " PRI_DNS_NAME_SRP " doesn't contain a key.",
-              DNS_NAME_PARAM_SRP(host_description->name, host_name_buf));
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-
-    // Find any deletes that weren't consumed. These will be presumed to be removes of service instances previously
-    // registered. These can't be validated here--we have to actually go look at the database.
-    dpp = &deletes;
-    rpp = &removes;
-    while (*dpp) {
-        dp = *dpp;
-        if (!dp->consumed) {
-            DNS_NAME_GEN_SRP(dp->name, delete_name_buf);
-            INFO("delete for presumably previously-registered instance which is being withdrawn: " PRI_DNS_NAME_SRP,
-                  DNS_NAME_PARAM_SRP(dp->name, delete_name_buf));
-            *rpp = dp;
-            rpp = &dp->next;
-            *dpp = dp->next;
-            dp->next = NULL;
-        } else {
-            dpp = &dp->next;
-        }
-    }
-
-    // The signature should be the last thing in the additional section.   Even if the signature
-    // is valid, if it's not at the end we reject it.   Note that we are just checking for SIG(0)
-    // so if we don't find what we're looking for, we forward it to the DNS auth server which
-    // will either accept or reject it.
-    if (message->arcount < 1) {
-        ERROR("signature not present");
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-    signature = &message->additional[message->arcount -1];
-    if (signature->type != dns_rrtype_sig) {
-        ERROR("signature is not at the end or is not present");
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-
-    // Make sure that the signer name is the hostname.   If it's not, it could be a legitimate
-    // update with a different key, but it's not an SRP update, so we pass it on.
-    if (!dns_names_equal(signature->data.sig.signer, host_description->name)) {
-        DNS_NAME_GEN_SRP(signature->data.sig.signer, signer_name_buf);
-        DNS_NAME_GEN_SRP(host_description->name, host_name_buf);
-        ERROR("signer " PRI_DNS_NAME_SRP " doesn't match host " PRI_DNS_NAME_SRP,
-              DNS_NAME_PARAM_SRP(signature->data.sig.signer, signer_name_buf),
-              DNS_NAME_PARAM_SRP(host_description->name, host_name_buf));
-        rcode = dns_rcode_formerr;
-        goto out;
-    }
-
-    // Make sure we're in the time limit for the signature.   Zeroes for the inception and expiry times
-    // mean the host that send this doesn't have a working clock.   One being zero and the other not isn't
-    // valid unless it's 1970.
-    if (signature->data.sig.inception != 0 || signature->data.sig.expiry != 0) {
-        if (raw_message->received_time != 0) {
-            now.tv_sec = raw_message->received_time;
-            now.tv_usec = 0;
-        } else {
-            gettimeofday(&now, NULL);
-        }
-        // The sender does the bracketing, so we can just do a simple comparison.
-        if ((uint32_t)(now.tv_sec & UINT32_MAX) > signature->data.sig.expiry ||
-            (uint32_t)(now.tv_sec & UINT32_MAX) < signature->data.sig.inception) {
-            ERROR("signature is not timely: %lu < %lu < %lu does not hold",
-                  (unsigned long)signature->data.sig.inception, (unsigned long)now.tv_sec,
-                  (unsigned long)signature->data.sig.expiry);
-            goto badsig;
-        }
-    }
-
-    // Now that we have the key, we can validate the signature.   If the signature doesn't validate,
-    // there is no need to pass the message on.
-    if (!srp_sig0_verify(&raw_message->wire, host_description->key, signature)) {
-        ERROR("signature is not valid");
-        goto badsig;
-    }
-
-    // Now that we have validated the SRP message, go through and fix up all instances of
-    // *default.service.arpa to use the replacement zone, if this update is for
-    // default.services.arpa and there is a replacement zone.
-    if (replacement_zone != NULL) {
-        // All of the service instances and the host use the name from the delete, so if
-        // we update these, the names for those are taken care of.   We already found the
-        // zone for which the delete is a subdomain, so we can just replace it without
-        // finding it again.
-        for (dp = deletes; dp; dp = dp->next) {
-            replace_zone_name(&dp->name, dp->zone, replacement_zone);
-        }
-
-        // All services have PTR records, which point to names.   Both the service name and the
-        // PTR name have to be fixed up.
-        for (sp = services; sp; sp = sp->next) {
-            replace_zone_name(&sp->rr->name, sp->zone, replacement_zone);
-            uzp = dns_name_subdomain_of(sp->rr->data.ptr.name, update_zone);
-            // We already validated that the PTR record points to something in the zone, so this
-            // if condition should always be false.
-            if (uzp == NULL) {
-                ERROR("service PTR record zone match fail!!");
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            replace_zone_name(&sp->rr->data.ptr.name, uzp, replacement_zone);
-        }
-
-        // All service instances have SRV records, which point to names.  The service instance
-        // name is already fixed up, because it's the same as the delete, but the name in the
-        // SRV record must also be fixed.
-        for (sip = service_instances; sip; sip = sip->next) {
-            uzp = dns_name_subdomain_of(sip->srv->data.srv.name, update_zone);
-            // We already validated that the SRV record points to something in the zone, so this
-            // if condition should always be false.
-            if (uzp == NULL) {
-                ERROR("service instance SRV record zone match fail!!");
-                rcode = dns_rcode_formerr;
-                goto out;
-            }
-            replace_zone_name(&sip->srv->data.srv.name, uzp, replacement_zone);
-        }
-
-        // We shouldn't need to replace the hostname zone because it's actually pointing to
-        // the name of a delete.
-    }
-
-    // Start the update.
-    DNS_NAME_GEN_SRP(host_description->name, host_description_name_buf);
-    INFO("update for " PRI_DNS_NAME_SRP " xid %x validates, lease time %d%s, serial %" PRIu32 "%s.",
-         DNS_NAME_PARAM_SRP(host_description->name, host_description_name_buf), raw_message->wire.id,
-         lease_time, found_lease ? " (found)" : "", serial_number, found_serial ? " (found)" : " (not sent)");
-    rcode = dns_rcode_noerror;
-    ret = srp_update_start(connection, server_state, srpl_connection, message, raw_message, host_description, service_instances,
-                           services, removes, replacement_zone == NULL ? update_zone : replacement_zone,
-                           lease_time, key_lease_time, serial_number, found_serial);
-    if (ret) {
-        goto success;
-    }
-    ERROR("update start failed");
-    goto out;
-
-badsig:
-    // True means it was intended for us, and shouldn't be forwarded.
-    ret = true;
-    // We're not actually going to return this; it simply indicates that we aren't sending a fail response.
-    rcode = dns_rcode_noerror;
-    // Because we're saying this is ours, we have to free the parsed message.
-    dns_message_free(message);
-
-out:
-    // free everything we allocated but (it turns out) aren't going to use
-    if (keys != NULL) {
-        free(keys);
-    }
-    srp_update_free_parts(service_instances, NULL, services, removes, host_description);
-
-success:
-    // No matter how we get out of this, we free the delete structures that weren't dangling removes,
-    // because they are not used to do the update.
-    for (dp = deletes; dp; ) {
-        delete_t *next = dp->next;
-        free(dp);
-        dp = next;
-    }
-
-    if (ret == true && rcode != dns_rcode_noerror) {
-        if (connection != NULL) {
-            send_fail_response(connection, raw_message, rcode);
-        }
-    }
-    return ret;
-}
-
-bool
-srp_dns_evaluate(comm_t *connection, srp_server_t *server_state, srpl_connection_t *srpl_connection, message_t *message)
-{
-    dns_message_t *parsed_message;
-
-    // Drop incoming responses--we're a server, so we only accept queries.
-    if (dns_qr_get(&message->wire) == dns_qr_response) {
-        ERROR("dns_evaluate: received a message that was a DNS response: %d", dns_opcode_get(&message->wire));
-        return false;
-    }
-
-    // Forward incoming messages that are queries but not updates.
-    // XXX do this later--for now we operate only as a translator, not a proxy.
-    if (dns_opcode_get(&message->wire) != dns_opcode_update) {
-        if (connection != NULL) {
-            send_fail_response(connection, message, dns_rcode_refused);
-        }
-        ERROR("dns_evaluate: received a message that was not a DNS update: %d", dns_opcode_get(&message->wire));
-        return false;
-    }
-
-    // Parse the UPDATE message.
-    if (!dns_wire_parse(&parsed_message, &message->wire, message->length, false)) {
-        if (connection != NULL) {
-            send_fail_response(connection, message, dns_rcode_servfail);
-        }
-        ERROR("dns_wire_parse failed.");
-        return false;
-    }
-
-    // We need the wire message to validate the signature...
-    if (!srp_evaluate(connection, server_state, srpl_connection, parsed_message, message)) {
-        // The message wasn't invalid, but wasn't an SRP message.
-        dns_message_free(parsed_message);
-        // dns_forward(connection)
-        if (connection != NULL) {
-            send_fail_response(connection, message, dns_rcode_refused);
-        }
-        return false;
-    }
-    return true;
-}
-
-void
-dns_input(comm_t *comm, message_t *message, void *context)
-{
-    (void)context;
-    srp_dns_evaluate(comm, context, NULL, message);
-}
-
-struct srp_proxy_listener_state {
-    comm_t *NULLABLE tcp_listener;
-    comm_t *NULLABLE tls_listener;
-    comm_t *NULLABLE udp_listener;
-};
-
-void
-srp_proxy_listener_cancel(srp_proxy_listener_state_t *listener_state)
-{
-    if (listener_state->tcp_listener != NULL) {
-        ioloop_listener_cancel(listener_state->tcp_listener);
-        ioloop_listener_release(listener_state->tcp_listener);
-    }
-    if (listener_state->tls_listener != NULL) {
-        ioloop_listener_cancel(listener_state->tls_listener);
-        ioloop_listener_release(listener_state->tls_listener);
-    }
-    if (listener_state->udp_listener != NULL) {
-        ioloop_listener_cancel(listener_state->udp_listener);
-        ioloop_listener_release(listener_state->udp_listener);
-    }
-    free(listener_state);
-}
-
-srp_proxy_listener_state_t *
-srp_proxy_listen(uint16_t *avoid_ports, int num_avoid_ports, ready_callback_t ready, srp_server_t *server_state)
-{
-#if SRP_STREAM_LISTENER_ENABLED
-    uint16_t tcp_listen_port;
-#ifndef EXCLUDE_TLS
-    uint16_t tls_listen_port;
-#endif
-#endif
-    srp_proxy_listener_state_t *listeners = calloc(1, sizeof *listeners);
-    if (listeners == NULL) {
-        ERROR("srp_proxy_listen: no memory for listeners structure.");
-        return NULL;
-    }
-    (void)avoid_ports;
-    (void)num_avoid_ports;
-
-#if SRP_STREAM_LISTENER_ENABLED
-    tcp_listen_port = 53;
-    tls_listen_port = 853;
-#endif
-
-    // Set up listeners
-    // XXX UDP listeners should bind to interface addresses, not INADDR_ANY.
-    listeners->udp_listener = ioloop_listener_create(false, false, avoid_ports,
-                                                     num_avoid_ports, NULL, NULL, "UDP listener", dns_input,
-                                                     NULL, NULL, ready, NULL, NULL, server_state);
-    if (listeners->udp_listener == NULL) {
-        srp_proxy_listener_cancel(listeners);
-        ERROR("UDP listener: fail.");
-        return 0;
-    }
-#ifdef SRP_STREAM_LISTENER_ENABLED
-    listeners->tcp_listener = ioloop_listener_create(true, false, NULL, 0, NULL, NULL,
-                                                     "TCP listener", dns_input, NULL, NULL, ready, NULL, NULL, server_state);
-    if (listeners->tcp_listener == NULL) {
-        srp_proxy_listener_cancel(listeners);
-        ERROR("TCP listener: fail.");
-        return 0;
-    }
-#ifndef EXCLUDE_TLS
-    listeners->tls_listener = ioloop_listener_create(true, true, NULL, 0, NULL, NULL,
-                                                     "TLS listener", dns_input, NULL, NULL, ready, NULL, NULL, server_state);
-    if (listeners->tls_listener == NULL) {
-        srp_proxy_listener_cancel(listeners);
-        ERROR("TLS listener: fail.");
-        return 0;
-    }
-#endif
-#endif
-
-    return listeners;
-}
-
-void
-srp_proxy_init(const char *update_zone)
-{
-    // For now, hardcoded, should be configurable
-    if (service_update_zone != NULL) {
-        dns_name_free(service_update_zone);
-    }
-    service_update_zone = dns_pres_name_parse(update_zone);
-
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-proxy.h b/ServiceRegistration/srp-proxy.h
deleted file mode 100644
index 9737310..0000000
--- a/ServiceRegistration/srp-proxy.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* srp-proxy.h
- *
- * Copyright (c) 2018-2021 Apple 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
- *
- *     https://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.
- *
- * Service Registration Protocol common definitions.
- */
-
-#ifndef __SRP_PROXY_H
-#define __SRP_PROXY_H
-
-typedef struct srp_proxy_listener_state srp_proxy_listener_state_t;
-typedef struct srp_server_state srp_server_t;
-typedef struct srpl_connection srpl_connection_t;
-
-void srp_proxy_listener_cancel(srp_proxy_listener_state_t *NONNULL listener_state);
-srp_proxy_listener_state_t *NULLABLE srp_proxy_listen(uint16_t *NULLABLE avoid_ports, int num_avoid_ports,
-                                                      ready_callback_t NULLABLE ready,
-                                                      srp_server_t *NONNULL server_state);
-void srp_proxy_init(const char *NONNULL update_zone);
-bool srp_evaluate(comm_t *NONNULL comm, srp_server_t *NULLABLE server_state,
-                  srpl_connection_t *NULLABLE srpl_connection,
-                  dns_message_t *NONNULL message, message_t *NONNULL raw_message);
-bool srp_update_start(comm_t *NONNULL connection, srp_server_t *NULLABLE server_state,
-                      srpl_connection_t *NULLABLE srpl_connection,
-                      dns_message_t *NONNULL parsed_message, message_t *NONNULL raw_message,
-                      dns_host_description_t *NONNULL new_host, service_instance_t *NONNULL instances,
-                      service_t *NONNULL services, delete_t *NULLABLE removes, dns_name_t *NONNULL update_zone,
-                      uint32_t lease_time, uint32_t key_lease_time, uint32_t serial_number, bool found_serial);
-void srp_update_free_parts(service_instance_t *NULLABLE service_instances, service_instance_t *NULLABLE added_instances,
-                           service_t *NULLABLE services, delete_t *NULLABLE removes,
-                           dns_host_description_t *NULLABLE host_description);
-void srp_update_free(update_t *NONNULL update);
-
-
-// Provided
-void dns_input(comm_t *NONNULL comm, message_t *NONNULL message, void *NULLABLE context);
-void srp_mdns_flush(srp_server_t *NONNULL server_state);
-bool srp_dns_evaluate(comm_t *NULLABLE connection, srp_server_t *NULLABLE server_state,
-                      srpl_connection_t *NULLABLE srpl_connection, message_t *NONNULL message);
-#endif // __SRP_PROXY_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-replication.c b/ServiceRegistration/srp-replication.c
deleted file mode 100644
index 532e084..0000000
--- a/ServiceRegistration/srp-replication.c
+++ /dev/null
@@ -1,4120 +0,0 @@
-/* srp-replication.c
- *
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains an implementation of SRP Replication, which allows two or more
- * SRP servers to cooperatively maintain an SRP registration dataset.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dns_sd.h>
-#include <net/if.h>
-#include <inttypes.h>
-#include <sys/resource.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "dnssd-proxy.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "config-parse.h"
-#include "cti-services.h"
-#include "route.h"
-#define DNSMessageHeader dns_wire_t
-#include "dso.h"
-#include "dso-utils.h"
-
-#if SRP_FEATURE_REPLICATION
-#include "srp-replication.h"
-
-static char *current_thread_domain_name;
-static unclaimed_connection_t *unclaimed_connections;
-
-#define srpl_event_content_type_set(event, content_type) \
-    srpl_event_content_type_set_(event, content_type, __FILE__, __LINE__)
-static bool srpl_event_content_type_set_(srpl_event_t *event,
-                                         srpl_event_content_type_t content_type, const char *file, int line);
-static srpl_state_t srpl_connection_drop_state_delay(srpl_instance_t *instance,
-                                                     srpl_connection_t *srpl_connection, int delay);
-static srpl_state_t srpl_connection_drop_state(srpl_instance_t *instance, srpl_connection_t *srpl_connection);
-static void srpl_disconnect(srpl_connection_t *srpl_connection);
-static void srpl_connection_discontinue(srpl_connection_t *srpl_connection);
-static void srpl_connection_next_state(srpl_connection_t *srpl_connection, srpl_state_t state);
-static void srpl_event_initialize(srpl_event_t *event, srpl_event_type_t event_type);
-static void srpl_event_deliver(srpl_connection_t *srpl_connection, srpl_event_t *event);
-static void srpl_domain_advertise(srp_server_t *server_state);
-static void srpl_connection_finalize(srpl_connection_t *srpl_connection);
-static void srpl_instance_reconnect(void *context);
-static bool srpl_domain_browse_start(srpl_domain_t *domain);
-static const char *srpl_state_name(srpl_state_t state);
-
-#ifdef DEBUG
-#define STATE_DEBUGGING_ABORT() abort();
-#else
-#define STATE_DEBUGGING_ABORT()
-#endif
-
-// Return continuous time, if provided by O.S., otherwise unadjusted time.
-time_t srpl_time(void)
-{
-#ifdef CLOCK_BOOTTIME
-    // CLOCK_BOOTTIME is a Linux-specific constant that indicates a monotonic time that includes time asleep
-    const int clockid = CLOCK_BOOTTIME;
-#elif defined(CLOCK_MONOTONIC_RAW)
-    // On MacOS, CLOCK_MONOTONIC_RAW is a monotonic time that includes time asleep and is not adjusted.
-    // According to the man page, CLOCK_MONOTONIC on MacOS violates the POSIX spec in that it can be adjusted.
-    const int clockid = CLOCK_MONOTONIC_RAW;
-#else
-    // On other Posix systems, CLOCK_MONOTONIC should be the right thing, at least according to the POSIX spec.
-    const int clockid = CLOCK_MONOTONIC;
-#endif
-    struct timespec tm;
-    clock_gettime(clockid, &tm);
-
-    // We are only accurate to the second.
-    return tm.tv_sec;
-}
-
-//
-// 1. Enumerate all SRP servers that are participating in synchronization on infrastructure: This is done by looking up
-//    NS records for <thread-network-name>.thread.home.arpa with the ForceMulticast flag set so that we use mDNS to
-//    discover them.
-
-// 2. For each identified server that is not this server, look up A and AAAA records for the server's hostname.
-
-// 3. Maintain a state object with the list of IP addresses and an index to the current server being tried.
-
-// 4. Try to connect to the first address on the list -> connection management state machine:
-
-//   * When we have established an outgoing connection to a server, generate a random 64-bit unsigned number and send a
-//     SRPLSession DSO message using that number as the server ID.
-
-//   * When we receive an SRPLSession DSO message, see if we have an outgoing connection from the same server
-//     for which we've sent a server ID. If so, and if the server id we received is less than the one we sent,
-//     terminate the outgoing connection. If the server ids are equal, generate a new server id for the outgoing
-//     connection and send another session establishment message.
-//
-//   * When we receive an acknowledgement to our SRPLSession DSO message, see if we have an incoming
-//     connection from the same server from which we've received a server id. If the server id we received is less
-//     than the one we sent, terminate the outgoing connection. If the server ids are equal, generate a new random
-//     number for the outgoing connection and send another session establishment message.
-//
-//   * When a connection from a server is terminated, see if we have an established outgoing connection with that
-//     server.  If not, attempt to connect to the next address we have for that server.
-//
-//   * When our connection to a server is terminated or fails, and there is no established incoming connection from that
-//     server, attempt to connect to the next address we have for that server.
-//
-//   * When the NS record for a server goes away, drop any outgoing connection to that server and discontinue trying to
-//     connect to it.
-//
-// 5. When we have established a session, meaning that we either got an acknowledgment to a SRPLSession DSO
-//    message that we sent and _didn't_ drop the connection, or we got an SRPLSession DSO message on an
-//    incoming connection with a lower server id than the outgoing connection, we begin the synchronization process.
-//
-//    * Immediately following session establishment, we generate a list of candidate hosts to send to the other server
-//      from our internal list of SRP hosts (clients). Every non-expired host entry goes into the candidate list.
-//
-//    * Then, if we are the originator, we sent an SRPLSendCandidates message.
-//
-//    * If we are the recipient, we wait for an SRPLSendCandidates message.
-//
-//    * When we receive an SRPLSendCandidates message, we iterate across the candidates list, for each
-//      candidate sending an SRPLCandidate message containing the host key, current time, and last message
-//      received times, in seconds since the epoch. When we come to the end of the candidates list, we send an
-//      acknowledgement to the SRPLSendCandidates message and discard the candidates list.
-//
-//    * When we receive an SRPLCandidate message, we look in our own candidate list, if there is one, to see
-//      if the host key is present in the candidates list. If it is not present, or if it is present and the received
-//      time from the SRPLCandidate message is later than the time we have recorded in our own candidate
-//      list, we send an SRPLCandidateRequest message with the host key from the SRPLCandidate
-//      message.
-//
-//    * When we receive an SRPLCandidateRequest message, we send an SRPLHost message which
-//      encapsulates the SRP update for the host and includes the timestamp when we received the SRP update from that
-//      host, which may have changed since we sent the SRPLCandidate message.
-//
-//    * When we receive an SRPLHost message, we look in our list of hosts (SRP clients) for a matching
-//      host. If no such host exists, or if it exists and the timestamp is less than the timestamp in the
-//      SRPLHost message, we process the SRP update from the SRPLHost message and mark the host as
-//      "not received locally."  In other words, this message was not received directly from an SRP client, but rather
-//      indirectly through our SRP replication partner. Note that this message cannot be assumed to be syntactically
-//      correct and must be treated like any other data received from the network. If we are sent an invalid message,
-//      this is an indication that our partner is broken in some way, since it should have validated the message before
-//      accepting it.
-//
-//    * Whenever the SRP engine applies an SRP update from a host, it also delivers that update to each replication
-//      server state engine.
-//
-//      * That replication server state engine first checks to see if it is connected to its partner; if not, no action
-//        is taken.
-//
-//      * It then checks to see if there is a candidate list.
-//        * If so, it checks to see if the host implicated in the update is already on the candidate list.
-//          * If so, it updates that candidate's update time.
-//          * If not, it adds the host to the end of the candidate list.
-//        * If not, it sends an SRPLCandidate message to the other replication server, with the host
-//          key and new timestamp.
-//
-// 6. When there is more than one SRP server participating in replication, only one server should advertise using
-//    mDNS. All other servers should only advertise using DNS and DNS Push (SRP scalability feature). The SRP server
-//    with the lowest numbered server ID is the one that acts as an advertising proxy for SRP. In practice this means
-//    that if we have the lowest server ID of all the SRP servers we are connected to, we advertise mDNS. If two servers
-//    on the same link can't connect to each other, they probably can't see each others' multicasts, so this is the
-//    right outcome.
-
-static bool
-ip_addresses_equal(const addr_t *a, const addr_t *b)
-{
-    return (a->sa.sa_family == b->sa.sa_family &&
-            ((a->sa.sa_family == AF_INET && !memcmp(&a->sin.sin_addr, &b->sin.sin_addr, 4)) ||
-             (a->sa.sa_family == AF_INET6 && !memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, 16))));
-}
-
-#define ADDR_NAME_LOGGER(log_type, address, preamble, conjunction, number, fullname, interfaceIndex)            \
-    if ((address)->sa.sa_family == AF_INET6) {                                                                  \
-        SEGMENTED_IPv6_ADDR_GEN_SRP(&(address)->sin6.sin6_addr, rdata_buf);                                     \
-        log_type(PUB_S_SRP PRI_SEGMENTED_IPv6_ADDR_SRP PUB_S_SRP PRI_S_SRP PUB_S_SRP "%d", preamble,            \
-                 SEGMENTED_IPv6_ADDR_PARAM_SRP(&(address)->sin6.sin6_addr, rdata_buf),                          \
-                 conjunction, fullname, number, interfaceIndex);                                                \
-    } else {                                                                                                    \
-        IPv4_ADDR_GEN_SRP(&(address)->sin.sin_addr, rdata_buf);                                                 \
-        log_type(PUB_S_SRP PRI_IPv4_ADDR_SRP PUB_S_SRP PRI_S_SRP PUB_S_SRP "%d", preamble,                      \
-                 IPv4_ADDR_PARAM_SRP(&(address)->sin.sin_addr, rdata_buf),                                      \
-                 conjunction, fullname, number, interfaceIndex);                                                \
-    }
-
-static void
-address_query_callback(DNSServiceRef UNUSED sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
-                       DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass,
-                       uint16_t rdlen, const void *rdata, uint32_t UNUSED ttl, void *context)
-{
-    address_query_t *address = context;
-    addr_t addr;
-    int i, j;
-    if (errorCode != kDNSServiceErr_NoError) {
-        ERROR("address resolution for " PRI_S_SRP " failed with %d", fullname, errorCode);
-        address->change_callback(address->context, NULL, false, errorCode);
-        return;
-    }
-    if (rrclass != dns_qclass_in || ((rrtype != dns_rrtype_a || rdlen != 4) &&
-                                     (rrtype != dns_rrtype_aaaa || rdlen != 16))) {
-        ERROR("Invalid response record type (%d) or class (%d) provided for " PRI_S_SRP, rrtype, rrclass, fullname);
-        return;
-    }
-
-    memset(&addr, 0, sizeof(addr));
-    if (rrtype == dns_rrtype_a) {
-#ifndef NOT_HAVE_SA_LEN
-        addr.sa.sa_len = sizeof(struct sockaddr_in);
-#endif
-        addr.sa.sa_family = AF_INET;
-        memcpy(&addr.sin.sin_addr, rdata, rdlen);
-        if (IN_LINKLOCAL(addr.sin.sin_addr.s_addr)) {
-            ADDR_NAME_LOGGER(INFO, &addr, "Skipping link-local address ", " received for instance ", " index ",
-                             fullname, interfaceIndex);
-            return;
-        }
-    } else {
-#ifndef NOT_HAVE_SA_LEN
-        addr.sa.sa_len = sizeof(struct sockaddr_in6);
-#endif
-        addr.sa.sa_family = AF_INET6;
-        memcpy(&addr.sin6.sin6_addr, rdata, rdlen);
-        if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr)) {
-            ADDR_NAME_LOGGER(INFO, &addr, "Skipping link-local address ", " received for instance ", " index ",
-                             fullname, interfaceIndex);
-            return;
-        }
-    }
-
-    for (i = 0, j = 0; i < address->num_addresses; i++) {
-        // Already in the list?
-        if (!memcmp(&address->addresses[i], &addr, sizeof(addr))) {
-            if (flags & kDNSServiceFlagsAdd) {
-                if (address->address_interface[i] == interfaceIndex) {
-                    ADDR_NAME_LOGGER(INFO, &addr, "Duplicate address ", " received for instance ", " index ",
-                                                fullname, interfaceIndex);
-                }
-                return;
-            } else {
-                ADDR_NAME_LOGGER(INFO, &addr, "Removing address ", " from instance ", " index ",
-                                            fullname, interfaceIndex);
-
-                // If we're removing an address, we keep going through the array copying down.
-                if (address->cur_address >= i) {
-                    address->cur_address--;
-                }
-            }
-        } else {
-            // Copy down.
-            if (i != j) {
-                address->addresses[j] = address->addresses[i];
-                address->address_interface[j] = address->address_interface[i];
-            }
-            j++;
-        }
-    }
-    if (flags & kDNSServiceFlagsAdd) {
-        if (i == ADDRESS_QUERY_MAX_ADDRESSES) {
-            ADDR_NAME_LOGGER(ERROR, &addr, "No room for address ", " received for ", " index ",
-                                         fullname, interfaceIndex);
-            return;
-        }
-        ADDR_NAME_LOGGER(INFO, &addr, "Adding address ", " to ", " index ", fullname, interfaceIndex);
-
-        address->addresses[i] = addr;
-        address->address_interface[i] = interfaceIndex;
-        address->num_addresses++;
-        address->change_callback(address->context, &address->addresses[i], true, kDNSServiceErr_NoError);
-    } else {
-        if (i == j) {
-            ADDR_NAME_LOGGER(ERROR, &addr, "Remove for unknown address ", " received for ", " index ",
-                               fullname, interfaceIndex);
-            return;
-        } else {
-            address->num_addresses--;
-            address->change_callback(address->context, &addr, false, kDNSServiceErr_NoError);
-        }
-    }
-}
-
-static void
-address_query_finalize(void *context)
-{
-    address_query_t *address = context;
-    free(address->hostname);
-    free(address);
-}
-
-static void
-address_query_cancel(address_query_t *address)
-{
-    if (address->a_query != NULL) {
-        ioloop_dnssd_txn_cancel(address->a_query);
-        ioloop_dnssd_txn_release(address->a_query);
-        address->a_query = NULL;
-    }
-    if (address->aaaa_query != NULL) {
-        ioloop_dnssd_txn_cancel(address->aaaa_query);
-        ioloop_dnssd_txn_release(address->aaaa_query);
-        address->aaaa_query = NULL;
-    }
-
-    // Have whatever holds a reference to the address query let go of it.
-    if (address->cancel_callback != NULL && address->context != NULL) {
-        address->cancel_callback(address->context);
-        address->context = NULL;
-        address->cancel_callback = NULL;
-    }
-}
-
-static void
-address_query_txn_fail(void *context, int err)
-{
-    address_query_t *address = context;
-    ERROR("address query " PRI_S_SRP " i/o failure: %d", address->hostname, err);
-    address_query_cancel(address);
-}
-
-static void
-address_query_context_release(void *context)
-{
-    address_query_t *address = context;
-    RELEASE_HERE(address, address_query_finalize);
-}
-
-static address_query_t *
-address_query_create(const char *hostname, void *context, address_change_callback_t change_callback,
-                     address_query_cancel_callback_t cancel_callback)
-{
-    address_query_t *address = calloc(1, sizeof(*address));
-    DNSServiceRef sdref;
-    dnssd_txn_t **txn;
-
-    require_action_quiet(address != NULL, exit_no_free, ERROR("No memory for address query."));
-    RETAIN_HERE(address); // We return a retained object, or free it.
-    address->hostname = strdup(hostname);
-    require_action_quiet(address->hostname != NULL, exit, ERROR("No memory for address query hostname."));
-
-    for (int i = 0; i < 2; i++) {
-        int ret = DNSServiceQueryRecord(&sdref, kDNSServiceFlagsForceMulticast | kDNSServiceFlagsLongLivedQuery,
-                                        kDNSServiceInterfaceIndexAny, hostname, (i
-                                                                                 ? kDNSServiceType_A
-                                                                                 : kDNSServiceType_AAAA),
-                                        kDNSServiceClass_IN, address_query_callback, address);
-        require_action_quiet(ret == kDNSServiceErr_NoError, exit,
-                             ERROR("Unable to resolve instance hostname " PRI_S_SRP " addresses: %d",
-                                   hostname, ret));
-
-        txn = i ? &address->a_query : &address->aaaa_query;
-        *txn = ioloop_dnssd_txn_add(sdref, address, address_query_context_release, address_query_txn_fail);
-        require_action_quiet(*txn != NULL, exit,
-                             ERROR("Unable to set up ioloop transaction for " PRI_S_SRP " query on " THREAD_BROWSING_DOMAIN,
-                                   hostname);
-                             DNSServiceRefDeallocate(sdref));
-        RETAIN_HERE(address); // For the QueryRecord context
-    }
-    address->change_callback = change_callback;
-    address->cancel_callback = cancel_callback;
-    address->context = context;
-    address->cur_address = -1;
-    return address;
-
-exit:
-    RELEASE_HERE(address, address_query_finalize);
-    address = NULL;
-
-exit_no_free:
-    return address;
-}
-
-static void
-srpl_domain_finalize(srpl_domain_t *domain)
-{
-    free(domain->name);
-    if (domain->query != NULL) {
-        ioloop_dnssd_txn_cancel(domain->query);
-        ioloop_dnssd_txn_release(domain->query);
-    }
-    free(domain);
-}
-
-static void
-srpl_instance_finalize(srpl_instance_t *instance)
-{
-    if (instance->resolve_txn != NULL) {
-        ioloop_dnssd_txn_cancel(instance->resolve_txn);
-        ioloop_dnssd_txn_release(instance->resolve_txn);
-        instance->resolve_txn = NULL;
-    }
-    if (instance->domain != NULL) {
-        RELEASE_HERE(instance->domain, srpl_domain_finalize);
-    }
-    free(instance->instance_name);
-    free(instance->name);
-    if (instance->incoming != NULL) {
-        srpl_connection_discontinue(instance->incoming);
-        RELEASE_HERE(instance->incoming, srpl_connection_finalize);
-    }
-    if (instance->outgoing != NULL) {
-        srpl_connection_discontinue(instance->outgoing);
-        RELEASE_HERE(instance->outgoing, srpl_connection_finalize);
-    }
-    if (instance->address_query != NULL) {
-        address_query_cancel(instance->address_query);
-        RELEASE_HERE(instance->address_query, address_query_finalize);
-    }
-    if (instance->discontinue_timeout != NULL) {
-        ioloop_cancel_wake_event(instance->discontinue_timeout);
-        ioloop_wakeup_release(instance->discontinue_timeout);
-        instance->discontinue_timeout = NULL;
-    }
-    if (instance->reconnect_timeout != NULL) {
-        ioloop_cancel_wake_event(instance->reconnect_timeout);
-        ioloop_wakeup_release(instance->reconnect_timeout);
-        instance->reconnect_timeout = NULL;
-    }
-    free(instance);
-}
-
-#define srpl_connection_message_set(srpl_connection, message) \
-    srpl_connection_message_set_(srpl_connection, message, __FILE__, __LINE__)
-static void
-srpl_connection_message_set_(srpl_connection_t *srpl_connection, message_t *message, const char *file, int line)
-{
-    if (srpl_connection->message != NULL) {
-        ioloop_message_release_(srpl_connection->message, file, line);
-        srpl_connection->message = NULL;
-    }
-    if (message != NULL) {
-        srpl_connection->message = message;
-        ioloop_message_retain_(srpl_connection->message, file, line);
-    }
-}
-
-static message_t *
-srpl_connection_message_get(srpl_connection_t *srpl_connection)
-{
-    return srpl_connection->message;
-}
-
-#define srpl_candidate_free(candidate) srpl_candidate_free_(candidate, __FILE__, __LINE__)
-static void
-srpl_candidate_free_(srpl_candidate_t *candidate, const char *file, int line)
-{
-    if (candidate != NULL) {
-        if (candidate->name != NULL) {
-            dns_name_free(candidate->name);
-            candidate->name = NULL;
-        }
-        if (candidate->message != NULL) {
-            ioloop_message_release_(candidate->message, file, line);
-            candidate->message = NULL;
-        }
-        if (candidate->host != NULL) {
-            srp_adv_host_release_(candidate->host, file, line);
-            candidate->host = NULL;
-        }
-        free(candidate);
-    }
-}
-
-static void
-srpl_connection_candidates_free(srpl_connection_t *srpl_connection)
-{
-    if (srpl_connection->candidates == NULL) {
-        goto out;
-    }
-    for (int i = 0; i < srpl_connection->num_candidates; i++) {
-        if (srpl_connection->candidates[i] != NULL) {
-            srp_adv_host_release(srpl_connection->candidates[i]);
-        }
-    }
-    free(srpl_connection->candidates);
-    srpl_connection->candidates = NULL;
-out:
-    srpl_connection->num_candidates = srpl_connection->current_candidate = 0;
-    return;
-}
-
-static void
-srpl_srp_client_update_queue_free(srpl_connection_t *srpl_connection)
-{
-    srpl_srp_client_queue_entry_t **cp = &srpl_connection->client_update_queue;
-    while (*cp) {
-        srpl_srp_client_queue_entry_t *entry = *cp;
-        srp_adv_host_release(entry->host);
-        *cp = entry->next;
-        free(entry);
-    }
-}
-
-static void
-srpl_connection_candidate_set(srpl_connection_t *srpl_connection, srpl_candidate_t *candidate)
-{
-    if (srpl_connection->candidate != NULL) {
-        srpl_candidate_free(srpl_connection->candidate);
-    }
-    srpl_connection->candidate = candidate;
-}
-
-static void
-srpl_host_update_parts_free(srpl_host_update_t *update)
-{
-    if (update->message != NULL) {
-        ioloop_message_release(update->message);
-        update->message = NULL;
-    }
-    if (update->hostname != NULL) {
-        dns_name_free(update->hostname);
-        update->hostname = NULL;
-    }
-}
-
-// Free up any temporarily retained or allocated objects on the connection (i.e., not the name).
-static void
-srpl_connection_reset(srpl_connection_t *srpl_connection)
-{
-    srpl_connection->candidates_not_generated = true;
-    srpl_connection->database_synchronized = false;
-    srpl_host_update_parts_free(&srpl_connection->stashed_host);
-    srpl_connection_message_set(srpl_connection, NULL);
-    if (srpl_connection->candidate != NULL) {
-        srpl_candidate_free(srpl_connection->candidate);
-        srpl_connection->candidate = NULL;
-    }
-    srpl_connection_candidates_free(srpl_connection);
-    srpl_srp_client_update_queue_free(srpl_connection);
-}
-
-static void
-srpl_connection_finalize(srpl_connection_t *srpl_connection)
-{
-    if (srpl_connection->instance) {
-        RELEASE_HERE(srpl_connection->instance, srpl_instance_finalize);
-        srpl_connection->instance = NULL;
-    }
-    if (srpl_connection->connection != NULL) {
-        ioloop_comm_release(srpl_connection->connection);
-        srpl_connection->connection = NULL;
-    }
-    if (srpl_connection->reconnect_wakeup != NULL) {
-        ioloop_cancel_wake_event(srpl_connection->reconnect_wakeup);
-        srpl_connection->reconnect_wakeup = NULL;
-    }
-    free(srpl_connection->name);
-    srpl_connection_reset(srpl_connection);
-    free(srpl_connection);
-}
-
-void
-srpl_connection_release_(srpl_connection_t *srpl_connection, const char *file, int line)
-{
-    RELEASE(srpl_connection, srpl_connection_finalize);
-}
-
-void
-srpl_connection_retain_(srpl_connection_t *srpl_connection, const char *file, int line)
-{
-    RETAIN(srpl_connection);
-}
-
-static srpl_connection_t *
-srpl_connection_create(srpl_instance_t *instance, bool outgoing)
-{
-    srpl_connection_t *srpl_connection = calloc(1, sizeof (*srpl_connection));
-    size_t srpl_connection_name_length;
-    if (outgoing) {
-        srpl_connection_name_length = strlen(instance->instance_name) + 2;
-    } else {
-        srpl_connection_name_length = strlen(instance->instance_name) + 2;
-    }
-    srpl_connection->name = malloc(srpl_connection_name_length);
-    if (srpl_connection->name == NULL) {
-        free(srpl_connection);
-        return NULL;
-    }
-    snprintf(srpl_connection->name, srpl_connection_name_length, "%s%s", outgoing ? ">" : "<", instance->instance_name);
-    srpl_connection->is_server = !outgoing;
-    srpl_connection->instance = instance;
-    RETAIN_HERE(instance);
-    RETAIN_HERE(srpl_connection);
-    return srpl_connection;
-}
-
-static void
-srpl_connection_context_release(void *context)
-{
-    srpl_connection_t *srpl_connection = context;
-
-    RELEASE_HERE(srpl_connection, srpl_connection_finalize);
-}
-
-static void
-srpl_instance_context_release(void *context)
-{
-    srpl_instance_t *instance = context;
-
-    RELEASE_HERE(instance, srpl_instance_finalize);
-}
-
-static void
-srpl_instance_discontinue_timeout(void *context)
-{
-    srpl_instance_t **sp = NULL, *instance = context;
-
-    INFO("discontinuing instance " PRI_S_SRP, instance->instance_name);
-    for (sp = &instance->domain->instances; *sp; sp = &(*sp)->next) {
-        if (*sp == instance) {
-            *sp = instance->next;
-            break;
-        }
-    }
-    if (instance->discontinue_timeout != NULL) {
-        ioloop_cancel_wake_event(instance->discontinue_timeout);
-        ioloop_wakeup_release(instance->discontinue_timeout);
-        instance->discontinue_timeout = NULL;
-    }
-    if (instance->address_query != NULL) {
-        address_query_cancel(instance->address_query);
-        RELEASE_HERE(instance->address_query, address_query_finalize);
-        instance->address_query = NULL;
-    }
-    for (int i = 0; i < 2; i++) {
-        srpl_connection_t **cp = i ? &instance->incoming : &instance->outgoing;
-        srpl_connection_t *srpl_connection = *cp;
-        *cp = NULL;
-        if (srpl_connection == NULL) {
-            continue;
-        }
-        RELEASE_HERE(srpl_connection->instance, srpl_instance_finalize);
-        srpl_connection->instance = NULL;
-        if (srpl_connection->connection != NULL) {
-            srpl_connection_discontinue(srpl_connection);
-        }
-        // The instance no longer has a reference to the srpl_connection object.
-        RELEASE_HERE(srpl_connection, srpl_connection_finalize);
-    }
-    if (instance->resolve_txn != NULL) {
-        ioloop_dnssd_txn_cancel(instance->resolve_txn);
-        ioloop_dnssd_txn_release(instance->resolve_txn);
-        instance->resolve_txn = NULL;
-    }
-    RELEASE_HERE(instance, srpl_instance_finalize);
-}
-
-static void
-srpl_instance_discontinue(srpl_instance_t *instance)
-{
-    // Already discontinuing.
-    if (instance->discontinuing) {
-        INFO("Replication service instance " PRI_S_SRP " went away, already discontinuing", instance->instance_name);
-        return;
-    }
-    if (instance->num_copies > 0) {
-        INFO("Replication service instance " PRI_S_SRP " went away, %d still left", instance->name, instance->num_copies);
-        return;
-    }
-    INFO("Replication service instance " PRI_S_SRP " went away, none left, discontinuing", instance->instance_name);
-    instance->discontinuing = true;
-
-    // DNSServiceResolve doesn't give us the kDNSServiceFlagAdd flag--apparently it's assumed that we know the
-    // service was removed because we get a remove on the browse. So we need to restart the resolve if the
-    // instance comes back, rather than continuing to use the old resolve transaction.
-    if (instance->resolve_txn != NULL) {
-        ioloop_dnssd_txn_cancel(instance->resolve_txn);
-        ioloop_dnssd_txn_release(instance->resolve_txn);
-        instance->resolve_txn = NULL;
-    }
-
-    // It's not uncommon for a name to drop and then come back immediately. Wait 30s before
-    // discontinuing the instance.
-    if (instance->discontinue_timeout == NULL) {
-        instance->discontinue_timeout = ioloop_wakeup_create();
-        // Oh well.
-        if (instance->discontinue_timeout == NULL) {
-            srpl_instance_discontinue_timeout(instance);
-            return;
-        }
-    }
-    RETAIN_HERE(instance);
-    ioloop_add_wake_event(instance->discontinue_timeout, instance, srpl_instance_discontinue_timeout, srpl_instance_context_release, 30 * 1000);
-}
-
-void
-srpl_disable(srp_server_t *server_state)
-{
-    srpl_domain_t *domain;
-    srpl_instance_t *instance, *next;
-
-    for (domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (instance = domain->instances; instance != NULL; instance = next) {
-            next = instance->next;
-            srpl_instance_discontinue_timeout(instance);
-        }
-        if (domain->query != NULL) {
-            ioloop_dnssd_txn_cancel(domain->query);
-            ioloop_dnssd_txn_release(domain->query);
-            domain->query = NULL;
-        }
-    }
-    if (server_state->srpl_advertise_txn != NULL) {
-        ioloop_dnssd_txn_cancel(server_state->srpl_advertise_txn);
-        ioloop_dnssd_txn_release(server_state->srpl_advertise_txn);
-        server_state->srpl_advertise_txn = NULL;
-    }
-    server_state->srp_replication_enabled = false;
-}
-
-void
-srpl_drop_srpl_connection(srp_server_t *NONNULL server_state)
-{
-    for (srpl_domain_t *domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (srpl_instance_t *instance = domain->instances; instance != NULL; instance = instance->next) {
-            if (instance->incoming != NULL && instance->incoming->state > srpl_state_disconnect_wait) {
-                srpl_connection_discontinue(instance->incoming);
-            }
-            if (instance->outgoing != NULL && instance->outgoing->state > srpl_state_disconnect_wait) {
-                srpl_connection_discontinue(instance->outgoing);
-            }
-        }
-    }
-}
-
-void
-srpl_undrop_srpl_connection(srp_server_t *NONNULL server_state)
-{
-    for (srpl_domain_t *domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (srpl_instance_t *instance = domain->instances; instance != NULL; instance = instance->next) {
-            srpl_instance_reconnect(instance);
-        }
-    }
-}
-
-void
-srpl_drop_srpl_advertisement(srp_server_t *NONNULL server_state)
-{
-    if (server_state->srpl_advertise_txn != NULL) {
-        ioloop_dnssd_txn_cancel(server_state->srpl_advertise_txn);
-        ioloop_dnssd_txn_release(server_state->srpl_advertise_txn);
-        server_state->srpl_advertise_txn = NULL;
-    }
-}
-
-void
-srpl_undrop_srpl_advertisement(srp_server_t *NONNULL server_state)
-{
-    srpl_domain_advertise(server_state);
-}
-
-
-// Copy from into to, and then NULL out the host pointer in from, which is not refcounted, so that we don't get a
-// double free later. Add a reference to the message, since it is refcounted.
-static void
-srpl_host_update_steal_parts(srpl_host_update_t *to, srpl_host_update_t *from)
-{
-    *to = *from;
-    ioloop_message_retain(to->message);
-    from->hostname = NULL;
-}
-
-static bool
-srpl_event_content_type_set_(srpl_event_t *event, srpl_event_content_type_t content_type, const char *file, int line)
-{
-    switch(event->content_type) {
-    case srpl_event_content_type_none:
-    case srpl_event_content_type_address:
-    case srpl_event_content_type_server_id:
-    case srpl_event_content_type_candidate_disposition:
-    case srpl_event_content_type_rcode:
-    case srpl_event_content_type_client_result: // pointers owned by caller
-    case srpl_event_content_type_advertise_finished_result:
-        break;
-
-    case srpl_event_content_type_candidate:
-        if (event->content.candidate != NULL) {
-            srpl_candidate_free_(event->content.candidate, file, line);
-            event->content.candidate = NULL;
-        }
-        break;
-    case srpl_event_content_type_host_update:
-        srpl_host_update_parts_free(&event->content.host_update);
-        break;
-    }
-    memset(&event->content, 0, sizeof(event->content));
-    if (content_type == srpl_event_content_type_candidate) {
-        event->content.candidate = calloc(1, sizeof(srpl_candidate_t));
-        if (event->content.candidate == NULL) {
-            return false;
-        }
-    }
-    event->content_type = content_type;
-    return true;
-}
-
-// Return true if the client connection to us is functional.
-static bool
-srpl_incoming_connection_is_active(srpl_instance_t *instance)
-{
-    if (instance == NULL || instance->incoming == NULL) {
-        return false;
-    }
-    switch(instance->incoming->state) {
-    case srpl_state_session_message_wait:
-        return false;
-    default:
-        return true;
-    }
-}
-
-static void
-srpl_disconnected_callback(comm_t *UNUSED comm, void *context, int UNUSED error)
-{
-    srpl_connection_t *srpl_connection = context;
-
-    // No matter what state we are in, if we are disconnected, we can't continue with the existing connection.
-    // Either we need to make a new connection, or go idle.
-
-    srpl_instance_t *instance = srpl_connection->instance;
-
-    // The connection would still be holding a reference; once that reference is released, if there's no instance
-    // holding a reference, the srp_connection will be finalized.
-    if (srpl_connection->connection != NULL) {
-        comm_t *connection = srpl_connection->connection;
-        srpl_connection->connection = NULL;
-        ioloop_comm_release(connection);
-    }
-
-    // If there's no instance, this connection just needs to go away (and presumably has).
-    if (instance == NULL) {
-        return;
-    }
-
-    // Because instance is still holding a reference to srpl_connection, it's safe to keep using srpl_connection.
-
-    // For server connections, we just dispose of the connection--the client is responsible for reconnecting
-    if (srpl_connection->is_server) {
-        instance->incoming = NULL;
-        srpl_connection->instance = NULL;
-        RELEASE_HERE(srpl_connection, srpl_connection_finalize);
-#ifndef __clang_analyzer__
-        RELEASE_HERE(instance, srpl_instance_finalize);
-#endif
-        return;
-    }
-
-    // If the connection is in the disconnect_wait state, deliver an event.
-    if (srpl_connection->state == srpl_state_disconnect_wait) {
-        srpl_event_t event;
-        srpl_event_initialize(&event, srpl_event_disconnected);
-        srpl_event_deliver(srpl_connection, &event);
-        return;
-    }
-
-    // Clear old data from connection.
-    srpl_connection_reset(srpl_connection);
-
-    // For outgoing connections, we only need to reconnect if we don't have a confirmed incoming connection.
-    if (srpl_incoming_connection_is_active(instance)) {
-        INFO(PRI_S_SRP ": disconnect received, we have an active incoming connection, going idle.",
-             srpl_connection->name);
-        srpl_connection_next_state(srpl_connection, srpl_state_idle);
-    } else {
-        INFO(PRI_S_SRP ": disconnect received, reconnecting.", srpl_connection->name);
-        srpl_connection_next_state(srpl_connection, srpl_state_next_address_get);
-    }
-}
-
-static bool
-srpl_dso_message_setup(dso_state_t *dso, dso_message_t *state, dns_towire_state_t *towire, uint8_t *buffer,
-                       size_t buffer_size, message_t *message, bool response, int rcode, void *context)
-{
-    if (buffer_size < DNS_HEADER_SIZE) {
-        ERROR("internal: invalid buffer size %zd", buffer_size);
-        return false;
-    }
-
-    dso_make_message(state, buffer, buffer_size, dso, false, response, response ? message->wire.id : 0, rcode, context);
-    memset(towire, 0, sizeof(*towire));
-    towire->p = &buffer[DNS_HEADER_SIZE];
-    towire->lim = towire->p + (buffer_size - DNS_HEADER_SIZE);
-    towire->message = (dns_wire_t *)buffer;
-    return true;
-}
-
-static srp_server_t *
-srpl_connection_server_state(srpl_connection_t *srpl_connection)
-{
-    if (srpl_connection->instance == NULL || srpl_connection->instance->domain == NULL) {
-        INFO("connection has no server_state %p.", srpl_connection->instance);
-        return NULL;
-    }
-    return srpl_connection->instance->domain->server_state;
-}
-
-static bool
-srpl_session_message_send(srpl_connection_t *srpl_connection, bool response)
-{
-    uint8_t dsobuf[SRPL_SESSION_MESSAGE_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return false;
-    }
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire, dsobuf, sizeof(dsobuf),
-                                srpl_connection_message_get(srpl_connection), response, 0, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLSession);
-    dns_rdlength_begin(&towire);
-    dns_u64_to_wire(&towire, server_state->server_id);
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLSession " PUB_S_SRP ", id %" PRIx64, srpl_connection->name,
-         response ? "response" : "message", server_state->server_id);
-    return true;
-}
-
-static bool
-srpl_send_candidates_message_send(srpl_connection_t *srpl_connection, bool response)
-{
-    uint8_t dsobuf[SRPL_SEND_CANDIDATES_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire, dsobuf, sizeof(dsobuf),
-                                srpl_connection_message_get(srpl_connection), response, 0, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLSendCandidates);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLSendCandidates " PUB_S_SRP, srpl_connection->name, response ? "response" : "query");
-    return true;
-}
-
-static bool
-srpl_candidate_message_send(srpl_connection_t *srpl_connection, adv_host_t *host)
-{
-    uint8_t dsobuf[SRPL_CANDIDATE_MESSAGE_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire,
-                                dsobuf, sizeof(dsobuf), NULL, false, 0, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLCandidate);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLHostname);
-    dns_rdlength_begin(&towire);
-    dns_full_name_to_wire(NULL, &towire, host->name);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLTimeOffset);
-    dns_rdlength_begin(&towire);
-    dns_u32_to_wire(&towire, (uint32_t)(srpl_time() - host->update_time));
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLKeyID);
-    dns_rdlength_begin(&towire);
-    dns_u32_to_wire(&towire, host->key_id);
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLCandidate message on connection.", srpl_connection->name);
-    return true;
-}
-
-static bool
-srpl_candidate_response_send(srpl_connection_t *srpl_connection, dso_message_types_t response_type)
-{
-    uint8_t dsobuf[SRPL_CANDIDATE_RESPONSE_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire, dsobuf, sizeof(dsobuf),
-                                srpl_connection_message_get(srpl_connection), true, 0, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLCandidate);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, response_type);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLCandidate response on connection.", srpl_connection->name);
-    return true;
-}
-
-static bool
-srpl_host_message_send(srpl_connection_t *srpl_connection, adv_host_t *host)
-{
-    uint8_t dsobuf[SRPL_HOST_MESSAGE_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov[2];
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire,
-                                dsobuf, sizeof(dsobuf), NULL, false, 0, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLHost);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLHostname);
-    dns_rdlength_begin(&towire);
-    dns_full_name_to_wire(NULL, &towire, host->name);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLTimeOffset);
-    dns_rdlength_begin(&towire);
-    dns_u32_to_wire(&towire, (uint32_t)(srpl_time() - host->update_time));
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLServerStableID);
-    dns_rdlength_begin(&towire);
-    dns_u64_to_wire(&towire, host->server_stable_id);
-    dns_rdlength_end(&towire);
-    dns_u16_to_wire(&towire, kDSOType_SRPLHostMessage);
-    dns_u16_to_wire(&towire, host->message->length);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov[0].iov_len = towire.p - dsobuf;
-    iov[0].iov_base = dsobuf;
-    iov[1].iov_len = host->message->length;
-    iov[1].iov_base = &host->message->wire;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), iov, 2);
-
-    INFO(PRI_S_SRP " sent SRPLHost message %02x%02x " PRI_S_SRP " stable ID %" PRIx64,
-         srpl_connection->name, message.buf[0], message.buf[1], host->name, host->server_stable_id);
-    return true;
-}
-
-
-static bool
-srpl_host_response_send(srpl_connection_t *srpl_connection, int rcode)
-{
-    uint8_t dsobuf[SRPL_HOST_RESPONSE_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire, dsobuf, sizeof(dsobuf),
-                                srpl_connection_message_get(srpl_connection), true, rcode, srpl_connection)) {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_SRPLHost);
-    dns_rdlength_begin(&towire);
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLHost response %02x%02x rcode %d on connection.",
-         srpl_connection->name, message.buf[0], message.buf[1], rcode);
-    return true;
-}
-
-static bool
-srpl_retry_delay_send(srpl_connection_t *srpl_connection, uint32_t delay)
-{
-    uint8_t dsobuf[SRPL_RETRY_DELAY_LENGTH];
-    dns_towire_state_t towire;
-    dso_message_t message;
-    struct iovec iov;
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return false;
-    }
-
-    // If this isn't a server, there's no benefit to sending retry delay.
-    if (!srpl_connection->is_server) {
-        return true;
-    }
-
-    if (!srpl_dso_message_setup(srpl_connection->dso, &message, &towire, dsobuf, sizeof(dsobuf),
-                                srpl_connection_message_get(srpl_connection), true, dns_rcode_noerror, srpl_connection))
-    {
-        return false;
-    }
-    dns_u16_to_wire(&towire, kDSOType_RetryDelay);
-    dns_rdlength_begin(&towire);
-    dns_u32_to_wire(&towire, delay); // One hour.
-    dns_rdlength_end(&towire);
-    if (towire.error) {
-        ERROR("ran out of message space at " PUB_S_SRP ", :%d", __FILE__, towire.line);
-        return false;
-    }
-    memset(&iov, 0, sizeof(iov));
-    iov.iov_len = towire.p - dsobuf;
-    iov.iov_base = dsobuf;
-    ioloop_send_message(srpl_connection->connection, srpl_connection_message_get(srpl_connection), &iov, 1);
-
-    INFO(PRI_S_SRP " sent SRPLHost response, id %" PRIx64, srpl_connection->name, server_state->server_id);
-    return true;
-}
-static bool
-srpl_find_dso_additionals(srpl_connection_t *srpl_connection, dso_state_t *dso,
-                          const dso_message_types_t *additionals, bool *required, const char **names, int *indices,
-                          int num, int min_additls, int max_additls, const char *message_name, void *context,
-                          bool (*iterator)(int index, const uint8_t *buf, unsigned *offp, uint16_t len, void *context))
-{
-    int ret = true;
-    int count = 0;
-
-    for (int j = 0; j < num; j++) {
-        indices[j] = -1;
-    }
-    for (int i = 0; i < dso->num_additls; i++) {
-        bool found = false;
-        for (int j = 0; j < num; j++) {
-            if (dso->additl[i].opcode == additionals[j]) {
-                if (indices[j] != -1) {
-                    ERROR(PRI_S_SRP ": duplicate " PUB_S_SRP " for " PUB_S_SRP ".",
-                          srpl_connection->name, names[j], message_name);
-                    ret = false;
-                    continue;
-                }
-                indices[j] = i;
-                unsigned offp = 0;
-                if (!iterator(j, dso->additl[i].payload, &offp, dso->additl[i].length, context) ||
-                    offp != dso->additl[i].length) {
-                    ERROR(PRI_S_SRP ": invalid " PUB_S_SRP " for " PUB_S_SRP ".",
-                          srpl_connection->name, names[j], message_name);
-                    found = true; // So we don't complain later.
-                    count++;
-                    ret = false;
-                } else {
-                    found = true;
-                    count++;
-                }
-            }
-        }
-        if (!found) {
-            ERROR(PRI_S_SRP ": unexpected opcode %x for " PUB_S_SRP ".",
-                  srpl_connection->name, dso->additl[i].opcode, message_name);
-            ret = false;
-        }
-    }
-    for (int j = 0; j < num; j++) {
-        if (required[j] && indices[j] == -1) {
-            ERROR(PRI_S_SRP ": missing " PUB_S_SRP " for " PUB_S_SRP ".",
-                  srpl_connection->name, names[j], message_name);
-            ret = false;
-        }
-    }
-    if (count < min_additls) {
-        ERROR(PRI_S_SRP ": not enough additional TLVs (%d) for " PUB_S_SRP ".",
-              srpl_connection->name, count, message_name);
-        ret = false;
-    } else if (count > max_additls) {
-        ERROR(PRI_S_SRP ": too many additional TLVs (%d) for " PUB_S_SRP ".",
-              srpl_connection->name, count, message_name);
-        ret = false;
-    }
-    return ret;
-}
-
-static void
-srpl_connection_discontinue(srpl_connection_t *srpl_connection)
-{
-    srpl_connection->candidates_not_generated = true;
-    srpl_connection_reset(srpl_connection);
-    srpl_connection_next_state(srpl_connection, srpl_state_disconnect);
-}
-
-static bool
-srpl_session_message_parse(srpl_connection_t *srpl_connection,
-                           srpl_event_t *event, dso_state_t *dso, const char *message_name)
-{
-    if (dso->primary.length != 8) {
-        ERROR(PRI_S_SRP ": invalid DSO Primary length %d for " PUB_S_SRP ".",
-              srpl_connection->name, dso->primary.length, message_name);
-        return false;
-    } else {
-        unsigned offp = 0;
-        srpl_event_content_type_set(event, srpl_event_content_type_server_id);
-        if (!dns_u64_parse(dso->primary.payload, 8, &offp, &event->content.server_id)) {
-            // This should be un-possible.
-            ERROR(PRI_S_SRP ": invalid DSO Primary server id in " PRI_S_SRP ".",
-                  srpl_connection->name, message_name);
-            return false;
-        }
-
-        INFO(PRI_S_SRP " received " PUB_S_SRP ", id %" PRIx64,
-             srpl_connection->name, message_name, event->content.server_id);
-        return true;
-    }
-}
-
-static void
-srpl_session_message(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso)
-{
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_session_message_received);
-
-    if (!srpl_session_message_parse(srpl_connection, &event, dso, "SRPLSession message")) {
-        srpl_disconnect(srpl_connection);
-        return;
-    }
-    srpl_connection_message_set(srpl_connection, message);
-    srpl_event_deliver(srpl_connection, &event);
-}
-
-static void
-srpl_session_response(srpl_connection_t *srpl_connection, dso_state_t *dso)
-{
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_session_response_received);
-    if (!srpl_session_message_parse(srpl_connection, &event, dso, "SRPLSession response")) {
-        srpl_disconnect(srpl_connection);
-        return;
-    }
-    srpl_event_deliver(srpl_connection, &event);
-}
-
-static bool
-srpl_send_candidates_message_parse(srpl_connection_t *srpl_connection, dso_state_t *dso, const char *message_name)
-{
-    if (dso->primary.length != 0) {
-        ERROR(PRI_S_SRP ": invalid DSO Primary length %d for " PUB_S_SRP ".",
-              srpl_connection->name, dso->primary.length, message_name);
-        srpl_disconnect(srpl_connection);
-        return false;
-    }
-    return true;
-}
-
-static void
-srpl_send_candidates_message(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso)
-{
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_send_candidates_message_received);
-
-    if (srpl_send_candidates_message_parse(srpl_connection, dso, "SRPLSendCandidates message")) {
-        INFO(PRI_S_SRP " received SRPLSendCandidates query", srpl_connection->name);
-
-        srpl_connection_message_set(srpl_connection, message);
-        srpl_event_deliver(srpl_connection, &event);
-        return;
-    }
-}
-
-static void
-srpl_send_candidates_response(srpl_connection_t *srpl_connection, dso_state_t *dso)
-{
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_send_candidates_response_received);
-
-    if (srpl_send_candidates_message_parse(srpl_connection, dso, "SRPLSendCandidates message")) {
-        INFO(PRI_S_SRP " received SRPLSendCandidates response", srpl_connection->name);
-        srpl_event_deliver(srpl_connection, &event);
-        return;
-    }
-}
-
-static bool
-srpl_candidate_message_parse_in(int index, const uint8_t *buffer, unsigned *offp, uint16_t length, void *context)
-{
-    srpl_candidate_t *candidate = context;
-
-    switch(index) {
-    case 0:
-        return dns_name_parse(&candidate->name, buffer, length, offp, length);
-    case 1:
-        return dns_u32_parse(buffer, length, offp, &candidate->update_offset);
-    case 2:
-        return dns_u32_parse(buffer, length, offp, &candidate->key_id);
-    }
-    return false;
-}
-
-static void
-srpl_candidate_message(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso)
-{
-    const char *names[3] = { "Candidate Name", "Time Offset", "Key ID" };
-    dso_message_types_t additionals[3] = { kDSOType_SRPLHostname, kDSOType_SRPLTimeOffset, kDSOType_SRPLKeyID };
-    bool required[3] = { true, true, true };
-    int indices[3];
-
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_candidate_received);
-    if (!srpl_event_content_type_set(&event, srpl_event_content_type_candidate) ||
-        !srpl_find_dso_additionals(srpl_connection, dso, additionals,
-                                   required, names, indices, 3, 3, 3, "SRPLCandidate message",
-                                   event.content.candidate, srpl_candidate_message_parse_in)) {
-        goto fail;
-    }
-
-    srpl_connection_message_set(srpl_connection, message);
-    event.content.candidate->update_time = srpl_time() - event.content.candidate->update_offset;
-    srpl_event_deliver(srpl_connection, &event);
-    srpl_event_content_type_set(&event, srpl_event_content_type_none);
-    return;
-
-fail:
-    srpl_disconnect(srpl_connection);
-}
-
-static bool
-srpl_candidate_response_parse_in(int index,
-                                 const uint8_t *UNUSED buffer, unsigned *offp, uint16_t length, void *context)
-{
-    srpl_candidate_disposition_t *candidate_disposition = context;
-
-    if (length != 0) {
-        return false;
-    }
-
-    switch(index) {
-    case 0:
-        *candidate_disposition = srpl_candidate_yes;
-        break;
-    case 1:
-        *candidate_disposition = srpl_candidate_no;
-        break;
-    case 2:
-        *candidate_disposition = srpl_candidate_conflict;
-        break;
-    }
-    *offp = 0;
-    return true;
-}
-
-static void
-srpl_candidate_response(srpl_connection_t *srpl_connection, dso_state_t *dso)
-{
-    const char *names[3] = { "Candidate Yes", "Candidate No", "Conflict" };
-    dso_message_types_t additionals[3] = { kDSOType_SRPLCandidateYes, kDSOType_SRPLCandidateNo, kDSOType_SRPLConflict };
-    bool required[3] = { false, false, false };
-    int indices[3];
-    srpl_event_t event;
-
-    srpl_event_initialize(&event, srpl_event_candidate_response_received);
-    srpl_event_content_type_set(&event, srpl_event_content_type_candidate_disposition);
-    if (!srpl_find_dso_additionals(srpl_connection, dso, additionals,
-                                   required, names, indices, 3, 1, 1, "SRPLCandidate reply",
-                                   &event.content.disposition, srpl_candidate_response_parse_in)) {
-        goto fail;
-    }
-    srpl_event_deliver(srpl_connection, &event);
-    return;
-
-fail:
-    srpl_disconnect(srpl_connection);
-}
-
-static bool
-srpl_host_message_parse_in(int index, const uint8_t *buffer, unsigned *offp, uint16_t length, void *context)
-{
-    srpl_host_update_t *update = context;
-
-    switch(index) {
-    case 0:
-        return dns_name_parse(&update->hostname, buffer, length, offp, length);
-    case 1:
-        return dns_u32_parse(buffer, length, offp, &update->update_offset);
-    case 2:
-        update->message = ioloop_message_create(length);
-        if (update->message == NULL) {
-            return false;
-        }
-        memcpy(&update->message->wire, buffer, length);
-        *offp = length;
-        return true;
-    case 3:
-        return dns_u64_parse(buffer, length, offp, &update->server_stable_id);
-    }
-    return false;
-}
-
-static void
-srpl_host_message(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso)
-{
-    if (dso->primary.length != 0) {
-        ERROR(PRI_S_SRP ": invalid DSO Primary length %d for SRPLHost message.",
-              srpl_connection->name, dso->primary.length);
-        goto fail;
-    } else {
-        const char *names[4] = { "Host Name", "Time Offset", "Host Message", "Server Stable ID" };
-        dso_message_types_t additionals[4] = { kDSOType_SRPLHostname, kDSOType_SRPLTimeOffset, kDSOType_SRPLHostMessage,
-            kDSOType_SRPLServerStableID };
-        bool required[4] = { true, true, true, false };
-        int indices[4];
-        srpl_event_t event;
-
-        // Parse host message
-        srpl_event_initialize(&event, srpl_event_host_message_received);
-        srpl_event_content_type_set(&event, srpl_event_content_type_host_update);
-        if (!srpl_find_dso_additionals(srpl_connection, dso, additionals,
-                                       required, names, indices, 4, 3, 4, "SRPLHost message",
-                                       &event.content.host_update, srpl_host_message_parse_in)) {
-            goto fail;
-        }
-        DNS_NAME_GEN_SRP(event.content.host_update.hostname, hostname_buf);
-        INFO(PRI_S_SRP " received SRPLHost message %x for " PRI_DNS_NAME_SRP " server stable ID %" PRIx64,
-             srpl_connection->name, ntohs(message->wire.id),
-             DNS_NAME_PARAM_SRP(event.content.host_update.hostname, hostname_buf),
-             event.content.host_update.server_stable_id);
-        event.content.host_update.update_time =
-            srpl_time() - event.content.host_update.update_offset;
-        event.content.host_update.message->received_time = event.content.host_update.update_time;
-        srpl_connection_message_set(srpl_connection, message);
-        srpl_event_deliver(srpl_connection, &event);
-        srpl_event_content_type_set(&event, srpl_event_content_type_none);
-    }
-    return;
-fail:
-    INFO(PRI_S_SRP " received invalid SRPLHost message %x", srpl_connection->name, ntohs(message->wire.id));
-    srpl_disconnect(srpl_connection);
-    return;
-}
-
-static void
-srpl_host_response(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso)
-{
-    if (dso->primary.length != 0) {
-        ERROR(PRI_S_SRP ": invalid DSO Primary length %d for SRPLHost response.",
-              srpl_connection->name, dso->primary.length);
-        srpl_disconnect(srpl_connection);
-        return;
-    } else {
-        srpl_event_t event;
-        INFO(PRI_S_SRP " received SRPLHost response %x", srpl_connection->name, ntohs(message->wire.id));
-        srpl_event_initialize(&event, srpl_event_host_response_received);
-        srpl_event_content_type_set(&event, srpl_event_content_type_rcode);
-        event.content.rcode = dns_rcode_get(&message->wire);
-        srpl_event_deliver(srpl_connection, &event);
-        srpl_event_content_type_set(&event, srpl_event_content_type_none);
-        return;
-    }
-}
-
-static void
-srpl_dso_retry_delay(srpl_connection_t *srpl_connection, int reconnect_delay)
-{
-    if (srpl_connection->instance == NULL) {
-        // If there's no instance, we're already disconnecting.
-        INFO(PRI_S_SRP ": no instance", srpl_connection->name);
-        return;
-    }
-
-    // Set things up to reconnect later.
-    srpl_connection_drop_state_delay(srpl_connection->instance, srpl_connection, reconnect_delay);
-
-    // Drop the connection
-    srpl_connection_discontinue(srpl_connection);
-}
-
-static void
-srpl_dso_message(srpl_connection_t *srpl_connection, message_t *message, dso_state_t *dso, bool response)
-{
-    switch(dso->primary.opcode) {
-    case kDSOType_SRPLSession:
-        if (response) {
-            srpl_session_response(srpl_connection, dso);
-        } else {
-            srpl_session_message(srpl_connection, message, dso);
-        }
-        break;
-
-    case kDSOType_SRPLSendCandidates:
-        if (response) {
-            srpl_send_candidates_response(srpl_connection, dso);
-        } else {
-            srpl_send_candidates_message(srpl_connection, message, dso);
-        }
-        break;
-
-    case kDSOType_SRPLCandidate:
-        if (response) {
-            srpl_candidate_response(srpl_connection, dso);
-        } else {
-            srpl_candidate_message(srpl_connection, message, dso);
-        }
-        break;
-
-    case kDSOType_SRPLHost:
-        if (response) {
-            srpl_host_response(srpl_connection, message, dso);
-        } else {
-            srpl_host_message(srpl_connection, message, dso);
-        }
-        break;
-
-    default:
-        INFO("unexpected primary TLV %d", dso->primary.opcode);
-        dso_simple_response(srpl_connection->connection, NULL, &message->wire, dns_rcode_dsotypeni);
-        break;
-    }
-
-}
-
-static void
-srpl_unclaimed_finalize(unclaimed_connection_t *unclaimed)
-{
-    if (unclaimed->wakeup_timeout != NULL) {
-        ioloop_wakeup_release(unclaimed->wakeup_timeout);
-        unclaimed->wakeup_timeout = NULL;
-    }
-    if (unclaimed->message != NULL) {
-        ioloop_message_release(unclaimed->message);
-    }
-    free(unclaimed);
-}
-
-static void
-srpl_unclaimed_cancel(unclaimed_connection_t *unclaimed)
-{
-    unclaimed_connection_t **up;
-    bool found = false;
-
-    // Remove it from the list if it's on the list
-    for (up = &unclaimed_connections; *up != NULL; up = &(*up)->next) {
-        if (*up == unclaimed) {
-            *up = unclaimed->next;
-            found = true;
-            break;
-        }
-    }
-    ERROR("unclaimed connection " PRI_S_SRP " (%p) removed",
-          unclaimed->connection == NULL ? "<NULL>" : unclaimed->connection->name, unclaimed);
-
-    if (unclaimed->dso != NULL) {
-        dso_state_cancel(unclaimed->dso);
-        unclaimed->dso = NULL;
-    }
-    if (unclaimed->wakeup_timeout != NULL) {
-        ioloop_cancel_wake_event(unclaimed->wakeup_timeout);
-        ioloop_wakeup_release(unclaimed->wakeup_timeout);
-        unclaimed->wakeup_timeout = NULL;
-    }
-    if (unclaimed->message != NULL) {
-        ioloop_message_release(unclaimed->message);
-        unclaimed->message = NULL;
-    }
-    if (unclaimed->connection) {
-        ioloop_comm_cancel(unclaimed->connection);
-        ioloop_comm_release(unclaimed->connection);
-        unclaimed->connection = NULL;
-    }
-    // If we removed it from the list, release the reference.
-    if (found) {
-        RELEASE_HERE(unclaimed, srpl_unclaimed_finalize);
-    }
-    return;
-}
-
-static void
-srpl_unclaimed_dispose_callback(void *context)
-{
-    unclaimed_connection_t *unclaimed = context;
-    INFO("unclaimed connection " PRI_S_SRP " (%p) timed out", unclaimed->connection->name, unclaimed);
-    srpl_unclaimed_cancel(unclaimed);
-}
-
-static void
-srpl_unclaimed_disconnect_callback(comm_t *connection, void *context, int err)
-{
-    unclaimed_connection_t *unclaimed = context;
-    INFO("unclaimed connection " PRI_S_SRP " (%p) disconnected (error code %d)", connection->name, unclaimed, err);
-    srpl_unclaimed_cancel(unclaimed);
-}
-
-static void
-srpl_unclaimed_datagram_callback(comm_t *comm, message_t *message, void *context)
-{
-    unclaimed_connection_t *unclaimed = context;
-    INFO("unclaimed connection " PRI_S_SRP " (%p) received unexpected message type %d",
-         comm->name, unclaimed, dns_opcode_get(&message->wire));
-    srpl_unclaimed_cancel(unclaimed);
-}
-
-static void
-srpl_unclaimed_context_release(void *context)
-{
-    unclaimed_connection_t *unclaimed = context;
-    INFO("unclaimed connection %p context released", unclaimed);
-    RELEASE_HERE(unclaimed, srpl_unclaimed_finalize);
-}
-
-static void
-srpl_add_unclaimed_server(comm_t *connection, message_t *message, dso_state_t *dso, srp_server_t *server_state)
-{
-    unclaimed_connection_t **up, *unclaimed = calloc(1, sizeof(*unclaimed));
-    if (unclaimed == NULL) {
-        ERROR("no memory to hold on to unclaimed " PRI_S_SRP, connection->name);
-        dso_state_cancel(dso);
-    } else {
-        RETAIN_HERE(unclaimed);
-        unclaimed->wakeup_timeout = ioloop_wakeup_create();
-        // We want to reclaim the unclaimed connection after two minutes, if no matching advertisement has yet
-        // been found.
-        if (unclaimed->wakeup_timeout) {
-            ioloop_add_wake_event(unclaimed->wakeup_timeout, unclaimed,
-                                  srpl_unclaimed_dispose_callback, NULL, 120 * MSEC_PER_SEC);
-        } else {
-            ERROR("Unable to add wakeup event for unclaimed " PRI_S_SRP, connection->name);
-        }
-        unclaimed->dso = dso;
-        unclaimed->message = message;
-        unclaimed->server_state = server_state;
-        ioloop_message_retain(message);
-        unclaimed->connection = connection;
-        unclaimed->address = connection->address;
-        ioloop_comm_retain(unclaimed->connection);
-
-        // We shouldn't get any further datagrams before a connection is established.
-        connection->datagram_callback = srpl_unclaimed_datagram_callback;
-        ioloop_comm_context_set(connection, unclaimed, srpl_unclaimed_context_release);
-        RETAIN_HERE(unclaimed); // connection holds a reference.
-
-        // If we get a disconnect, we have to handle that.
-        ioloop_comm_disconnect_callback_set(connection, srpl_unclaimed_disconnect_callback);
-
-        // Find the end of the list.
-        for (up = &unclaimed_connections; *up != NULL; up = &(*up)->next) {
-        }
-        *up = unclaimed;
-    }
-}
-
-static void
-srpl_instance_dso_event_callback(void *context, void *event_context, dso_state_t *dso, dso_event_type_t eventType)
-{
-    message_t *message;
-    dso_query_receive_context_t *response_context;
-    dso_disconnect_context_t *disconnect_context;
-
-    switch(eventType)
-    {
-    case kDSOEventType_DNSMessage:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Message (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DNSResponse:
-        // We shouldn't get here because we already handled any DNS messages
-        message = event_context;
-        INFO("DNS Response (opcode=%d) received from " PRI_S_SRP, dns_opcode_get(&message->wire),
-             dso->remote_name);
-        break;
-    case kDSOEventType_DSOMessage:
-        INFO("DSO Message (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        message = event_context;
-        srpl_dso_message((srpl_connection_t *)context, message, dso, false);
-        break;
-    case kDSOEventType_DSOResponse:
-        INFO("DSO Response (Primary TLV=%d) received from " PRI_S_SRP,
-               dso->primary.opcode, dso->remote_name);
-        response_context = event_context;
-        message = response_context->message_context;
-        srpl_dso_message((srpl_connection_t *)context, message, dso, true);
-        break;
-
-    case kDSOEventType_Finalize:
-        INFO("Finalize");
-        break;
-
-    case kDSOEventType_Connected:
-        INFO("Connected to " PRI_S_SRP, dso->remote_name);
-        break;
-
-    case kDSOEventType_ConnectFailed:
-        INFO("Connection to " PRI_S_SRP " failed", dso->remote_name);
-        break;
-
-    case kDSOEventType_Disconnected:
-        INFO("Connection to " PRI_S_SRP " disconnected", dso->remote_name);
-        break;
-    case kDSOEventType_ShouldReconnect:
-        INFO("Connection to " PRI_S_SRP " should reconnect (not for a server)", dso->remote_name);
-        break;
-    case kDSOEventType_Inactive:
-        INFO("Inactivity timer went off, closing connection.");
-        break;
-    case kDSOEventType_Keepalive:
-        INFO("should send a keepalive now.");
-        break;
-    case kDSOEventType_KeepaliveRcvd:
-        INFO("keepalive received.");
-        break;
-    case kDSOEventType_RetryDelay:
-        disconnect_context = event_context;
-        INFO("retry delay received, %d seconds", disconnect_context->reconnect_delay);
-        srpl_dso_retry_delay(context, disconnect_context->reconnect_delay);
-        break;
-    }
-}
-
-static void
-srpl_datagram_callback(comm_t *comm, message_t *message, void *context)
-{
-    srpl_connection_t *srpl_connection = context;
-    srpl_instance_t *instance = srpl_connection->instance;
-
-    // If this is a DSO message, see if we have a session yet.
-    switch(dns_opcode_get(&message->wire)) {
-    case dns_opcode_dso:
-        if (srpl_connection->dso == NULL) {
-            INFO("dso message received with no DSO object on instance " PRI_S_SRP, instance->instance_name);
-            srpl_disconnect(srpl_connection);
-            return;
-        }
-        dso_message_received(srpl_connection->dso, (uint8_t *)&message->wire, message->length, message);
-        return;
-        break;
-    }
-    INFO("datagram on connection " PRI_S_SRP " not handled, type = %d.",
-         comm->name, dns_opcode_get(&message->wire));
-}
-
-static void
-srpl_associate_incoming_with_instance(comm_t *connection, message_t *message,
-                                      dso_state_t *dso, srpl_instance_t *instance)
-{
-    srpl_connection_t *srpl_connection = srpl_connection_create(instance, false);
-    if (srpl_connection == NULL) {
-        ioloop_comm_cancel(connection);
-        return;
-    }
-    instance->incoming = srpl_connection; // Retained via create/copy rule.
-    srpl_connection->connection = connection;
-    ioloop_comm_retain(srpl_connection->connection);
-    srpl_connection->dso = dso;
-    srpl_connection->instance = instance;
-    srpl_connection->connected_address = connection->address;
-    srpl_connection->state = srpl_state_session_message_wait;
-    dso_set_event_context(dso, srpl_connection);
-    dso_set_event_callback(dso, srpl_instance_dso_event_callback);
-    connection->datagram_callback = srpl_datagram_callback;
-    connection->disconnected = srpl_disconnected_callback;
-    ioloop_comm_context_set(connection, srpl_connection, srpl_connection_context_release);
-    RETAIN_HERE(srpl_connection); // the connection has a reference.
-    srpl_connection_next_state(srpl_connection, srpl_state_session_message_wait);
-    srpl_instance_dso_event_callback(srpl_connection, message, dso, kDSOEventType_DSOMessage);
-}
-
-void
-srpl_dso_server_message(comm_t *connection, message_t *message, dso_state_t *dso, srp_server_t *server_state)
-{
-    srpl_domain_t *domain;
-    srpl_instance_t *instance;
-    address_query_t *address;
-    int i;
-
-    // Figure out from which instance this connection originated
-    for (domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (instance = domain->instances; instance != NULL; instance = instance->next) {
-            address = instance->address_query;
-            if (address == NULL) {
-                continue;
-            }
-            for (i = 0; i < address->num_addresses; i++) {
-                if (ip_addresses_equal(&connection->address, &address->addresses[i])) {
-                    INFO("SRP Replication connection received from " PRI_S_SRP " on " PRI_S_SRP,
-                         address->hostname, connection->name);
-                    srpl_associate_incoming_with_instance(connection, message, dso, instance);
-                    return;
-                }
-            }
-        }
-    }
-
-    INFO("incoming SRP Replication server connection from unrecognized server " PRI_S_SRP, connection->name);
-    srpl_add_unclaimed_server(connection, message, dso, server_state);
-}
-
-static void
-srpl_connected(comm_t *connection, void *context)
-{
-    srpl_connection_t *srpl_connection = context;
-
-    INFO(PRI_S_SRP " connected", connection->name);
-    connection->dso = dso_state_create(false, 1, connection->name, srpl_instance_dso_event_callback,
-                                       srpl_connection, NULL, connection);
-    if (connection->dso == NULL) {
-        ERROR(PRI_S_SRP " can't create dso state object.", srpl_connection->name);
-        srpl_disconnect(srpl_connection);
-        return;
-    }
-    srpl_connection->dso = connection->dso;
-
-    // Generate an event indicating that we've been connected
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_connected);
-    srpl_event_deliver(srpl_connection, &event);
-}
-
-static bool
-srpl_connection_connect(srpl_connection_t *srpl_connection)
-{
-    if (srpl_connection->instance == NULL) {
-        ERROR(PRI_S_SRP ": no instance to connect to", srpl_connection->name);
-        return false;
-    }
-    int to_port = srpl_connection->instance->outgoing_port;
-    if (srpl_connection->connected_address.sa.sa_family == AF_INET) {
-        srpl_connection->connected_address.sin.sin_port = htons(to_port);
-    } else {
-        srpl_connection->connected_address.sin6.sin6_port = htons(to_port);
-    }
-    srpl_connection->connection = ioloop_connection_create(&srpl_connection->connected_address,
-                                                           // tls, stream, stable, opportunistic
-                                                             true,   true,   true, true,
-                                                           srpl_datagram_callback, srpl_connected,
-                                                           srpl_disconnected_callback, srpl_connection_context_release,
-                                                           srpl_connection);
-    if (srpl_connection->connection == NULL) {
-        ADDR_NAME_LOGGER(ERROR, &srpl_connection->connected_address, "can't create connection to address ",
-                         " for srpl connection ", " port ", srpl_connection->name, to_port);
-        return false;
-    }
-    ADDR_NAME_LOGGER(INFO, &srpl_connection->connected_address, "connecting to address ", " for instance ", " port ",
-                      srpl_connection->name, to_port);
-    RETAIN_HERE(srpl_connection); // For the connection's reference
-    return true;
-}
-
-static void
-srpl_instance_is_me(srpl_instance_t *instance, const char *ifname, const addr_t *address)
-{
-    instance->is_me = true;
-    if (ifname != NULL) {
-        INFO(PRI_S_SRP "/" PUB_S_SRP ": name server for instance " PRI_S_SRP " is me.", instance->name, ifname, instance->instance_name);
-    } else if (address != NULL) {
-        ADDR_NAME_LOGGER(INFO, address, "", " instance ", " is me. ", instance->name, 0);
-    } else {
-        ERROR("srpl_instance_is_me with null ifname and address!");
-        return;
-    }
-
-    // When we create the instance, we start an outgoing connection; when we discover that this is a connection
-    // to me, we can discontinue that outgoing connection.
-    if (instance->outgoing) {
-        srpl_connection_discontinue(instance->outgoing);
-    }
-}
-
-static bool
-srpl_my_address_check(const addr_t *address)
-{
-    static interface_address_state_t *ifaddrs = NULL;
-    interface_address_state_t *ifa;
-    static time_t last_fetch = 0;
-    // Update the interface address list every sixty seconds, but only if we're asked to check an address.
-    const time_t now = srpl_time();
-    if (now - last_fetch > 60) {
-        last_fetch = now;
-        ioloop_map_interface_addresses_here(&ifaddrs, NULL, NULL, NULL);
-    }
-    // See if there's a match.
-    for (ifa = ifaddrs; ifa; ifa = ifa->next) {
-        if (ip_addresses_equal(address, &ifa->addr)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static void
-srpl_instance_address_callback(void *context, addr_t *address, bool added, int err)
-{
-    srpl_instance_t *instance = context;
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("service instance address resolution for " PRI_S_SRP " failed with %d", instance->name, err);
-        if (instance->address_query) {
-            address_query_cancel(instance->address_query);
-            instance->address_query = NULL;
-        }
-        return;
-    }
-    if (added) {
-        unclaimed_connection_t **up = &unclaimed_connections;
-        while (*up != NULL) {
-            unclaimed_connection_t *unclaimed = *up;
-            if (ip_addresses_equal(address, &unclaimed->address)) {
-                INFO("Unclaimed connection " PRI_S_SRP " matches new address for " PRI_S_SRP, unclaimed->dso->remote_name,
-                     instance->name);
-                srpl_associate_incoming_with_instance(unclaimed->connection,
-                                                      unclaimed->message, unclaimed->dso, instance);
-                unclaimed->dso = NULL;
-                // srpl_associate_incoming_with_instance retains unclaimed->connection. srpl_unclaimed_cancel would
-                // release it, but it also cancels it, which we don't want, so release it and NULL it out now.
-                ioloop_comm_release(unclaimed->connection);
-                unclaimed->connection = NULL;
-                srpl_unclaimed_cancel(unclaimed);
-                break;
-            } else {
-                if (unclaimed->address.sa.sa_family == AF_INET6) {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(&unclaimed->address.sin6.sin6_addr, rdata_buf);
-                    INFO("Unclaimed connection address is: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(&unclaimed->address.sin6.sin6_addr, rdata_buf));
-                } else {
-                    IPv4_ADDR_GEN_SRP(&unclaimed->address.sin.sin_addr, rdata_buf);
-                    INFO("Unclaimed connection address is: " PRI_IPv4_ADDR_SRP,
-                         IPv4_ADDR_PARAM_SRP(&unclaimed->address.sin.sin_addr, rdata_buf));
-                }
-                if (address->sa.sa_family == AF_INET6) {
-                    SEGMENTED_IPv6_ADDR_GEN_SRP(&address->sin6.sin6_addr, rdata_buf);
-                    INFO("Unclaimed connection address is: " PRI_SEGMENTED_IPv6_ADDR_SRP,
-                         SEGMENTED_IPv6_ADDR_PARAM_SRP(&address->sin6.sin6_addr, rdata_buf));
-                } else {
-                    IPv4_ADDR_GEN_SRP(&address->sin.sin_addr, rdata_buf);
-                    INFO("Unclaimed connection address is: " PRI_IPv4_ADDR_SRP,
-                         IPv4_ADDR_PARAM_SRP(&address->sin.sin_addr, rdata_buf));
-                }
-                INFO("Unclaimed connection " PRI_S_SRP " does not match new address for " PRI_S_SRP, unclaimed->dso->remote_name,
-                     instance->name);
-                up = &(*up)->next;
-            }
-        }
-
-        if (srpl_my_address_check(address)) {
-            srpl_instance_is_me(instance, NULL, address);
-        }
-
-        // Generate an event indicating that we have a new address.
-        else if (instance->outgoing != NULL) {
-            srpl_event_t event;
-            srpl_event_initialize(&event, srpl_event_address_add);
-            srpl_event_deliver(instance->outgoing, &event);
-        }
-    } else {
-        srpl_event_t event;
-        srpl_event_initialize(&event, srpl_event_address_remove);
-
-        // Generate an event indicating that an address has been removed.
-        if (!instance->is_me) {
-            if (instance->incoming != NULL) {
-                srpl_event_deliver(instance->incoming, &event);
-            }
-            if (instance->outgoing != NULL) {
-                srpl_event_deliver(instance->outgoing, &event);
-            }
-        }
-    }
-}
-
-static void
-srpl_instance_add(const char *hostname, const char *instance_name,
-                  const char *ifname, srpl_domain_t *domain, srpl_instance_t *instance,
-                  bool have_server_id, uint64_t advertised_server_id)
-{
-    srpl_instance_t **sp;
-
-    // Find the instance on the instance list for this domain.
-    for (sp = &domain->instances; *sp != NULL; sp = &(*sp)->next) {
-        if (instance == *sp) {
-            break;
-        }
-    }
-
-    if (*sp == NULL) {
-        INFO("instance " PRI_S_SRP " for " PRI_S_SRP "/" PUB_S_SRP " " PUB_S_SRP "id %" PRIx64 " no longer on list",
-             instance_name != NULL ? instance_name : "<NULL>", hostname, ifname, have_server_id ? "" : "!", advertised_server_id);
-        if (instance->resolve_txn != NULL) {
-            ioloop_dnssd_txn_cancel(instance->resolve_txn);
-            ioloop_dnssd_txn_release(instance->resolve_txn);
-            instance->resolve_txn = NULL;
-        }
-        return;
-    }
-
-    INFO("instance " PRI_S_SRP " for " PRI_S_SRP "/" PUB_S_SRP " " PUB_S_SRP "id %" PRIx64 " " PUB_S_SRP "found",
-         instance_name != NULL ? instance_name : "<NULL>", hostname, ifname, have_server_id ? "" : "!", advertised_server_id,
-         *sp == NULL ? "!" : "");
-
-
-    // If the hostname changed, we need to restart the address query.
-    if (instance->name == NULL || strcmp(instance->name, hostname)) {
-        if (instance->address_query != NULL) {
-            address_query_cancel(instance->address_query);
-            instance->address_query = NULL;
-        }
-
-        if (instance->name != NULL) {
-            INFO("name server name change from " PRI_S_SRP " to " PRI_S_SRP " for " PRI_S_SRP "/" PUB_S_SRP " in domain " PRI_S_SRP,
-                 instance->name, hostname, instance_name == NULL ? "<NULL>" : instance_name, ifname, domain->name);
-        } else {
-            INFO("new name server " PRI_S_SRP " for " PRI_S_SRP "/" PUB_S_SRP " in domain " PRI_S_SRP,
-                 hostname, instance_name == NULL ? "<NULL>" : instance_name, ifname, domain->name);
-        }
-
-        char *new_name = strdup(hostname);
-        if (new_name == NULL) {
-            // This should never happen, and if it does there's actually no clean way to recover from it.  This approach
-            // will result in no crash, and since we don't start an address query in this case, we will just wind up in
-            // a quiescent state for this replication peer until something changes.
-            ERROR("no memory for instance name.");
-            return;
-        } else {
-            free(instance->name);
-            instance->name = new_name;
-        }
-        // The instance may be connected. It's possible its IP address hasn't changed. If it has changed, we should
-        // get a disconnect due to a connection timeout or (if something else got the same address, a reset) if for
-        // no other reason, and then we'll try to reconnect, so this should be harmless.
-    }
-
-    // The address query can be NULL either because we only just created the instance, or because the instance name changed (e.g.
-    // as the result of a hostname conflict).
-    if (instance->address_query == NULL) {
-        instance->address_query = address_query_create(instance->name, instance,
-                                                       srpl_instance_address_callback,
-                                                       srpl_instance_context_release);
-        if (instance->address_query == NULL) {
-            INFO("unable to create address query");
-        } else {
-            RETAIN_HERE(instance); // retain for the address query.
-        }
-    }
-
-    if (instance->outgoing == NULL && !instance->is_me) {
-        instance->outgoing = srpl_connection_create(instance, true);
-        srpl_connection_next_state(instance->outgoing, srpl_state_disconnected);
-    }
-    instance->num_copies++;
-
-    // If this add changed the server ID, we may want to re-attempt a connect.
-    if (have_server_id && (!instance->have_server_id || instance->server_id != advertised_server_id)) {
-        instance->have_server_id = true;
-        instance->server_id = advertised_server_id;
-        if (instance->outgoing != NULL && instance->outgoing->state == srpl_state_idle) {
-            srpl_connection_next_state(instance->outgoing, srpl_state_disconnected);
-        }
-    }
-}
-
-static void
-srpl_resolve_callback(DNSServiceRef UNUSED sdRef, DNSServiceFlags UNUSED flags, uint32_t interfaceIndex,
-                      DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
-                      uint16_t UNUSED txtLen, const unsigned char *UNUSED txtRecord, void *context)
-{
-    char ifname[IFNAMSIZ];
-    srpl_instance_t *instance = context;
-    srpl_domain_t *domain = instance->domain;
-    const char *domain_name;
-    uint8_t domain_len;
-    const char *server_id_string;
-    uint8_t server_id_string_len;
-    char server_id_buf[INT64_HEX_STRING_MAX];
-    uint64_t advertised_server_id = 0;
-    bool have_server_id = false;
-
-    if (errorCode != kDNSServiceErr_NoError) {
-        ERROR("resolve for " PRI_S_SRP " failed with %d", fullname, errorCode);
-        return;
-    }
-
-    domain_name = TXTRecordGetValuePtr(txtLen, txtRecord, "domain", &domain_len);
-    if (domain_name == NULL) {
-        INFO("resolve for " PRI_S_SRP " succeeded, but there is no domain name.", fullname);
-        return;
-    }
-
-    if (domain_len != strlen(domain->name) || memcmp(domain_name, domain->name, domain_len)) {
-        const char *domain_print;
-        char *domain_terminated = malloc(domain_len + 1);
-        if (domain_terminated == NULL) {
-            domain_print = "<no memory for domain name>";
-        } else {
-            memcpy(domain_terminated, domain_name, domain_len);
-            domain_terminated[domain_len] = 0;
-            domain_print = domain_terminated;
-        }
-        INFO("domain (" PRI_S_SRP ") for " PRI_S_SRP " doesn't match expected domain " PRI_S_SRP,
-             domain_print, fullname, domain->name);
-        free(domain_terminated);
-        return;
-    }
-    if (strcmp(domain->name, current_thread_domain_name)) {
-        INFO("discovered srpl instance is not for current thread domain, so not setting up replication.");
-        return;
-    }
-
-    INFO("server " PRI_S_SRP " for " PRI_S_SRP, fullname, domain->name);
-
-    server_id_string = TXTRecordGetValuePtr(txtLen, txtRecord, "server-id", &server_id_string_len);
-    if (server_id_string != NULL && server_id_string_len < INT64_HEX_STRING_MAX) {
-        char *endptr, *nulptr;
-        unsigned long long num;
-        memcpy(server_id_buf, server_id_string, server_id_string_len);
-        nulptr = &server_id_buf[server_id_string_len];
-        *nulptr = '\0';
-        num = strtoull(server_id_buf, &endptr, 16);
-        // On current architectures, unsigned long long and uint64_t are the same size, but we should have a check here
-        // just in case, because the standard doesn't guarantee that this will be true.
-        // If endptr == nulptr, that means we converted the entire buffer and didn't run into a NUL in the middle of it
-        // somewhere.
-        if (num < UINT64_MAX && endptr == nulptr) {
-            advertised_server_id = num;
-            have_server_id = true;
-        }
-    }
-
-    instance->outgoing_port = ntohs(port);
-
-    if (if_indextoname(interfaceIndex, ifname) == NULL) {
-        snprintf(ifname, sizeof(ifname), "%d", interfaceIndex);
-    }
-
-    srpl_instance_add(hosttarget, fullname, ifname, instance->domain, instance, have_server_id, advertised_server_id);
-}
-
-static void
-srpl_browse_restart(void *context)
-{
-    srpl_domain_t *domain = context;
-    ERROR("restarting browse on domain " PRI_S_SRP, domain->name);
-    srpl_domain_browse_start(domain);
-}
-
-static void
-srpl_browse_callback(DNSServiceRef UNUSED sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
-                     DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
-                     const char *replyDomain, void *context)
-{
-    DNSServiceRef sdref;
-    srpl_domain_t *domain = context;
-    if (errorCode != kDNSServiceErr_NoError) {
-        ERROR("browse on domain " PRI_S_SRP " failed with %d", domain->name, errorCode);
-        if (domain->query != NULL) {
-            ioloop_dnssd_txn_cancel(domain->query);
-            ioloop_dnssd_txn_release(domain->query);
-            domain->query = NULL;
-        }
-
-        // Get rid of all instances on the domain, because we aren't going to get remove events for them.
-        // If we start a new browse and get add events while the connections are still up, this will
-        // have no effect.
-        for (srpl_instance_t *instance = domain->instances; instance; instance = instance->next) {
-            INFO("_srpl-tls._tcp service instance " PRI_S_SRP " went away.", instance->instance_name);
-            instance->num_copies = 0;
-            srpl_instance_discontinue(instance);
-        }
-
-        if (domain->server_state->srpl_browse_wakeup == NULL) {
-            domain->server_state->srpl_browse_wakeup = ioloop_wakeup_create();
-        }
-        if (domain->server_state->srpl_browse_wakeup != NULL) {
-            ioloop_add_wake_event(domain->server_state->srpl_browse_wakeup,
-                                  domain, srpl_browse_restart, NULL, 1000);
-        }
-        return;
-    }
-
-    char instance_name[kDNSServiceMaxDomainName];
-    DNSServiceConstructFullName(instance_name, serviceName, regtype, replyDomain);
-
-    if (flags & kDNSServiceFlagsAdd) {
-        srpl_instance_t *instance = NULL, **sp;
-        // See if we already have an instance going; if so, just increment the number of copies of the instance that we've found.
-        for (sp = &domain->instances; *sp; sp = &(*sp)->next) {
-            instance = *sp;
-            if (!strcmp(instance->instance_name, instance_name)) {
-                if (instance->resolve_txn != NULL) {
-                    instance->num_copies++;
-                    INFO("duplicate add for " PRI_S_SRP, instance_name);
-                    return;
-                }
-                // In this case the instance went away and came back, so instance->resolve_txn is NULL, but the instance still exists.
-                INFO(PRI_S_SRP " went away but came back.", instance_name);
-                break;
-            }
-        }
-
-        if (*sp == NULL) {
-            instance = calloc(1, sizeof(*instance));
-            if (instance == NULL) {
-                ERROR("no memory for instance" PRI_S_SRP, instance_name);
-                return;
-            }
-            // This retain is for the instance list on the domain.
-            RETAIN_HERE(instance);
-            instance->domain = domain;
-            RETAIN_HERE(instance->domain);
-
-            instance->instance_name = strdup(instance_name);
-            if (instance->instance_name == NULL) {
-                ERROR("no memory for instance " PRI_S_SRP, instance_name);
-                RELEASE_HERE(instance, srpl_instance_finalize);
-                return;
-            }
-        }
-
-        int err = DNSServiceResolve(&sdref, 0, interfaceIndex,
-                                    serviceName, regtype, replyDomain, srpl_resolve_callback, instance);
-        if (err != kDNSServiceErr_NoError) {
-            ERROR("unable to resolve " PRI_S_SRP ": code %d", instance_name, err);
-            RELEASE_HERE(instance, srpl_instance_finalize);
-            return;
-        }
-        instance->resolve_txn = ioloop_dnssd_txn_add(sdref, instance, srpl_instance_context_release, NULL);
-        if (instance->resolve_txn == NULL) {
-            ERROR("unable to allocate dnssd_txn_t for " PRI_S_SRP, instance_name);
-            DNSServiceRefDeallocate(sdref);
-            return;
-        }
-        // Retain for the dnssd_txn.
-        RETAIN_HERE(instance);
-        INFO("resolving " PRI_S_SRP, instance_name);
-
-        // If we have a discontinue timer going, cancel it.
-        if (instance->discontinue_timeout != NULL) {
-            if (instance->discontinuing) {
-                INFO("discontinue on instance " PRI_S_SRP " canceled.", instance->name);
-                ioloop_cancel_wake_event(instance->discontinue_timeout);
-                instance->discontinuing = false;
-            }
-        }
-
-        // If we created a new instance object, put it at the end of the list.
-        // The instance is already retained when it's allocated.
-        if (*sp == NULL) {
-            *sp = instance;
-        }
-    } else {
-        INFO("_srpl-tls._tcp service instance " PRI_S_SRP " went away.", instance_name);
-        for (srpl_instance_t *instance = domain->instances; instance; instance = instance->next) {
-            if (!strcmp(instance->instance_name, instance_name)) {
-                instance->num_copies--;
-                srpl_instance_discontinue(instance);
-                break;
-            }
-        }
-    }
-}
-
-static void
-srpl_domain_context_release(void *context)
-{
-    srpl_domain_t *domain = context;
-    RELEASE_HERE(domain, srpl_domain_finalize);
-}
-
-static void
-srpl_dnssd_txn_fail(void *context, int err)
-{
-    srpl_domain_t *domain = context;
-    ERROR("service browse " PRI_S_SRP " i/o failure: %d", domain->name, err);
-}
-
-static bool
-srpl_domain_browse_start(srpl_domain_t *domain)
-{
-    int ret;
-    DNSServiceRef sdref;
-
-    INFO("starting browse on _srpl-tls._tcp");
-    // Look for an NS record for the specified domain using mDNS, not DNS.
-    ret = DNSServiceBrowse(&sdref, kDNSServiceFlagsLongLivedQuery,
-                           kDNSServiceInterfaceIndexAny, "_srpl-tls._tcp", NULL, srpl_browse_callback, domain);
-    if (ret != kDNSServiceErr_NoError) {
-        ERROR("Unable to query for NS records for " PRI_S_SRP, domain->name);
-        return false;
-    }
-    domain->query = ioloop_dnssd_txn_add(sdref, srpl_domain_context_release, NULL, srpl_dnssd_txn_fail);
-    if (domain->query == NULL) {
-        ERROR("Unable to set up ioloop transaction for NS query on " PRI_S_SRP, domain->name);
-        DNSServiceRefDeallocate(sdref);
-        return false;
-    }
-    return true;
-}
-
-static void
-srpl_domain_add(srp_server_t *server_state, const char *domain_name)
-{
-    srpl_domain_t **dp, *domain;
-
-    // Find the domain, if it's already there.
-    for (dp = &server_state->srpl_domains; *dp; dp = &(*dp)->next) {
-        domain = *dp;
-        if (!strcasecmp(domain->name, domain_name)) {
-            break;
-        }
-    }
-
-    // If not there, make it.
-    if (*dp == NULL) {
-        domain = calloc(1, sizeof(*domain));
-        if (domain == NULL || (domain->name = strdup(domain_name)) == NULL) {
-            ERROR("Unable to allocate replication structure for domain " PRI_S_SRP, domain_name);
-            free(domain);
-            return;
-        }
-        *dp = domain;
-        // Hold a reference for the domain list
-        RETAIN_HERE(domain);
-        INFO("New service replication browsing domain: " PRI_S_SRP, domain->name);
-    } else {
-        ERROR("Unexpected duplicate replication domain: " PRI_S_SRP, domain_name);
-        return;
-    }
-
-    // Start a browse on the domain.
-    if (!srpl_domain_browse_start(domain)) {
-        return;
-    }
-    domain->server_state = server_state;
-    RETAIN_HERE(domain);
-}
-
-static void
-srpl_domain_rename(const char *current_name, const char *new_name)
-{
-    ERROR("replication domain " PRI_S_SRP " renamed to " PRI_S_SRP ", not currently handled.", current_name, new_name);
-}
-
-// Note that when this is implemented, it has the potential to return new thread domain names more than once, so
-// in principle we need to change the name of the domain we are advertising.
-static cti_status_t
-cti_get_thread_network_name(void *context, cti_tunnel_reply_t NONNULL callback,
-                            run_context_t NULLABLE UNUSED client_queue)
-{
-    callback(context, "openthread", kCTIStatus_NoError);
-    return kCTIStatus_NoError;
-}
-
-//
-// Event apply functions, print functions, and state actions, generally in order
-//
-
-static bool
-event_is_message(srpl_event_t *event)
-{
-    switch(event->event_type) {
-    case srpl_event_invalid:
-    case srpl_event_address_add:
-    case srpl_event_address_remove:
-    case srpl_event_server_disconnect:
-    case srpl_event_reconnect_timer_expiry:
-    case srpl_event_disconnected:
-    case srpl_event_connected:
-    case srpl_event_advertise_finished:
-    case srpl_event_srp_client_update_finished:
-        return false;
-
-    case srpl_event_session_response_received:
-    case srpl_event_send_candidates_response_received:
-    case srpl_event_candidate_received:
-    case srpl_event_host_message_received:
-    case srpl_event_candidate_response_received:
-    case srpl_event_host_response_received:
-    case srpl_event_session_message_received:
-    case srpl_event_send_candidates_message_received:
-        return true;
-    }
-    return false;
-}
-
-// States that require an instance (most states). We also validate the chain up to the server state, because
-// it's possible for that to go away and yet still for one last event to arrive, at least in principle.
-#define REQUIRE_SRPL_INSTANCE(srpl_connection)                                                              \
-    do {                                                                                                    \
-        if ((srpl_connection)->instance == NULL || (srpl_connection)->instance->domain == NULL ||           \
-            (srpl_connection)->instance->domain->server_state == NULL) {                                    \
-            ERROR(PRI_S_SRP ": no instance in state " PUB_S_SRP, srpl_connection->name,                     \
-                  srpl_connection->state_name);                                                             \
-            return srpl_state_invalid;                                                                      \
-        }                                                                                                   \
-    } while(false)
-
-// For states that never receive events.
-#define REQUIRE_SRPL_EVENT_NULL(srpl_connection, event)                                      \
-    do {                                                                                     \
-        if ((event) != NULL) {                                                               \
-            ERROR(PRI_S_SRP ": received unexpected " PUB_S_SRP " event in state " PUB_S_SRP, \
-                  srpl_connection->name, event->name, srpl_connection->state_name);          \
-            return srpl_state_invalid;                                                       \
-        }                                                                                    \
-    } while (false)
-
-// Announce that we have entered a state that takes no events
-#define STATE_ANNOUNCE_NO_EVENTS(srpl_connection)                                                          \
-    do {                                                                                                   \
-        INFO(PRI_S_SRP ": entering state " PUB_S_SRP, srpl_connection->name, srpl_connection->state_name); \
-    } while (false)
-
-// Announce that we have entered a state that takes no events
-#define STATE_ANNOUNCE_NO_EVENTS_NAME(connection, fqdn)                                                    \
-    do {                                                                                                   \
-        char hostname[kDNSServiceMaxDomainName];                                                           \
-        dns_name_print(fqdn, hostname, sizeof(hostname));                                                  \
-        INFO(PRI_S_SRP ": entering state " PUB_S_SRP " with host " PRI_S_SRP,                              \
-            connection->name, connection->state_name, hostname);                                           \
-    } while (false)
-
-// Announce that we have entered a state that takes no events
-#define STATE_ANNOUNCE(srpl_connection, event)                                                       \
-    do {                                                                                             \
-        if (event != NULL)  {                                                                        \
-            INFO(PRI_S_SRP ": event " PUB_S_SRP " received in state " PUB_S_SRP,                     \
-                 srpl_connection->name, event->name, srpl_connection->state_name);                   \
-        } else {                                                                                     \
-            INFO(PRI_S_SRP ": entering state " PUB_S_SRP,                                            \
-            srpl_connection->name, srpl_connection->state_name);                                     \
-        }                                                                                            \
-    } while (false)
-
-#define UNEXPECTED_EVENT_MAIN(srpl_connection, event, bad)                             \
-    do {                                                                               \
-        if (event_is_message(event)) {                                                 \
-            INFO(PRI_S_SRP ": invalid event " PUB_S_SRP " in state " PUB_S_SRP,        \
-                 (srpl_connection)->name, (event)->name, srpl_connection->state_name); \
-            return bad;                                                                \
-        }                                                                              \
-        INFO(PRI_S_SRP ": unexpected event " PUB_S_SRP " in state " PUB_S_SRP,         \
-            (srpl_connection)->name, (event)->name,                                    \
-             srpl_connection->state_name);                                             \
-        return srpl_state_invalid;                                                     \
-    } while (false)
-
-// UNEXPECTED_EVENT flags the response as bad on a protocol level, triggering a retry delay
-// UNEXPECTED_EVENT_NO_ERROR doesn't.
-#define UNEXPECTED_EVENT(srpl_connection, event) UNEXPECTED_EVENT_MAIN(srpl_connection, event, srpl_state_invalid)
-#define UNEXPECTED_EVENT_NO_ERROR(srpl_connection, event) \
-    UNEXPECTED_EVENT_MAIN(srpl_connection, event, srpl_connection_drop_state(srpl_connection->instance, srpl_connection))
-
-static void
-srpl_instance_reconnect(void *context)
-{
-    srpl_instance_t *instance = context;
-    srpl_event_t event;
-
-    // If we have a new connection, no need to reconnect.
-    if (instance->incoming != NULL && instance->incoming->state != srpl_state_idle) {
-        INFO(PRI_S_SRP ": we now have a valid connection.", instance->name);
-        return;
-    }
-    // We shouldn't have an outgoing connection.
-    if (instance->outgoing != NULL && instance->outgoing->state != srpl_state_idle) {
-        FAULT(PRI_S_SRP ": got to srpl_instance_reconnect with a non-idle (" PUB_S_SRP ") outgoing connection.",
-              instance->name, srpl_state_name(instance->outgoing->state));
-        return;
-    }
-
-    // We don't get rid of the outgoing connection when it's idle, so we shouldn't be able to get here.
-    if (instance->outgoing == NULL) {
-        FAULT(PRI_S_SRP "instance->outgoing is NULL!", instance->name);
-        return;
-    }
-
-    // Trigger a reconnect.
-    srpl_event_initialize(&event, srpl_event_reconnect_timer_expiry);
-    srpl_event_deliver(instance->outgoing, &event);
-}
-
-static srpl_state_t
-srpl_connection_drop_state_delay(srpl_instance_t *instance, srpl_connection_t *srpl_connection, int delay)
-{
-    // Schedule a reconnect.
-    if (instance->reconnect_timeout == NULL) {
-        instance->reconnect_timeout = ioloop_wakeup_create();
-    }
-    if (instance->reconnect_timeout == NULL) {
-        FAULT(PRI_S_SRP "disconnecting, but can't reconnect!", srpl_connection->name);
-    } else {
-        RETAIN_HERE(instance);
-        ioloop_add_wake_event(instance->reconnect_timeout,
-                              instance, srpl_instance_reconnect, srpl_instance_context_release, delay * MSEC_PER_SEC);
-    }
-
-    if (srpl_connection == instance->incoming) {
-        srpl_connection->retry_delay = delay;
-        return srpl_state_retry_delay_send;
-    } else {
-        return srpl_state_disconnect;
-    }
-}
-
-static srpl_state_t
-srpl_connection_drop_state(srpl_instance_t *instance, srpl_connection_t *srpl_connection)
-{
-    if (instance == NULL) {
-        return srpl_state_disconnect;
-    } else {
-        return srpl_connection_drop_state_delay(instance, srpl_connection, 300);
-    }
-}
-
-// Call when there's a protocol error, so that we don't start reconnecting over and over.
-static void
-srpl_disconnect(srpl_connection_t *srpl_connection)
-{
-    const int delay = 300; // five minutes
-    srpl_instance_t *instance = srpl_connection->instance;
-    if (instance != NULL) {
-        srpl_state_t state = srpl_connection_drop_state_delay(instance, srpl_connection, delay);
-        if (state == srpl_state_retry_delay_send) {
-            srpl_retry_delay_send(srpl_connection, delay);
-        }
-    }
-    srpl_connection_discontinue(srpl_connection);
-}
-
-// We arrive at the disconnected state when there is no connection to make, or no need to make a connection.
-// This state takes no action, but waits for events. If we get an add event and we don't have a viable incoming
-// connection, we go to the next_address_get event.
-static srpl_state_t
-srpl_disconnected_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_address_add) {
-        return srpl_state_next_address_get;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// This state takes the action of looking for an address to try. This can have three outcomes:
-//
-// * No addresses available: go to the disconnected state
-// * End of address list: go to the reconnect_wait state
-// * Address found: got to the connect state
-
-static srpl_state_t
-srpl_next_address_get_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    address_query_t *address_query = NULL;
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-
-    address_query = srpl_connection->instance->address_query;
-
-    // Get the next address
-    // Return an event, one of "next address", "end of address list" or "no addresses"
-    if (address_query == NULL || address_query->num_addresses == 0) {
-        return srpl_state_disconnected;
-    } else {
-        // Go to the next address, if there is a next address.
-        if (address_query->cur_address == address_query->num_addresses ||
-            ++address_query->cur_address == address_query->num_addresses)
-        {
-            address_query->cur_address = -1;
-            return srpl_state_reconnect_wait;
-        } else {
-            memcpy(&srpl_connection->connected_address,
-                   &address_query->addresses[address_query->cur_address], sizeof(addr_t));
-            return srpl_state_connect;
-        }
-    }
-}
-
-// This state takes the action of connecting to the connection's current address, which is expected to have
-// been set. This can have two outcomes:
-//
-// * The connect attempt fails immediately: go to the next_address_get state
-// * The connection attempt is in progress: go to the connecting state
-static srpl_state_t
-srpl_connect_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-
-    // Connect to the address from the event.
-    if (!srpl_connection_connect(srpl_connection)) {
-        return srpl_state_next_address_get;
-    } else {
-        return srpl_state_connecting;
-    }
-}
-
-// We reach this state when we are disconnected and don't need to reconnect because we have an active server
-// connection. If we get a server disconnect here, then we go to the next_address_get state.
-static srpl_state_t
-srpl_idle_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events
-    } else if (event->event_type == srpl_event_server_disconnect ||
-               event->event_type == srpl_event_reconnect_timer_expiry)
-    {
-        INFO(PRI_S_SRP ": event " PUB_S_SRP " received in state " PUB_S_SRP,
-             srpl_connection->name, event->name, srpl_connection->state_name);
-        return srpl_state_next_address_get;
-    } else {
-        // We don't log unhandled events in the idle state because it creates a lot of noise.
-        return srpl_state_invalid;
-    }
-}
-
-// We've received a timeout event on the reconnect timer. Generate a reconnect_timeout event and send it to the
-// connection.
-static void
-srpl_connection_reconnect_timeout(void *context)
-{
-    srpl_connection_t *srpl_connection = context;
-    srpl_event_t event;
-    srpl_event_initialize(&event, srpl_event_reconnect_timer_expiry);
-    srpl_event_deliver(srpl_connection, &event);
-}
-
-// We reach the set_reconnect_timer state when we have tried to connect to all the known addresses.  Once we have set a
-// timer, we wait for events. If we get a reconnect_timeout event, we go to the next_address_get state. If we get an
-// add_adress event, we cancel the retransmit timer and go to the next_address_get state.
-static srpl_state_t
-srpl_reconnect_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        // Create a reconnect timer on the srpl_connection_t
-        if (srpl_connection->reconnect_wakeup == NULL) {
-            srpl_connection->reconnect_wakeup = ioloop_wakeup_create();
-            if (srpl_connection->reconnect_wakeup == NULL) {
-                ERROR("no memory for reconnect_wakeup for service instance " PRI_S_SRP, srpl_connection->name);
-                return srpl_state_invalid;
-            }
-        } else {
-            ioloop_cancel_wake_event(srpl_connection->reconnect_wakeup);
-        }
-        ioloop_add_wake_event(srpl_connection->reconnect_wakeup, srpl_connection, srpl_connection_reconnect_timeout,
-                              srpl_connection_context_release, 60 * 1000);
-        RETAIN_HERE(srpl_connection); // the timer has a reference.
-        return srpl_state_invalid;
-    }
-    if (event->event_type == srpl_event_reconnect_timer_expiry) {
-        return srpl_state_next_address_get;
-    } else if (event->event_type == srpl_event_address_add) {
-        ioloop_cancel_wake_event(srpl_connection->reconnect_wakeup);
-        return srpl_state_next_address_get;
-    }
-    UNEXPECTED_EVENT(srpl_connection, event);
-}
-
-// We get to this state when the remote end has sent something bogus; in this case we send a retry_delay message to
-// tell the client not to reconnect for a while.
-static srpl_state_t
-srpl_retry_delay_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    srpl_retry_delay_send(srpl_connection, srpl_connection->retry_delay);
-    return srpl_state_disconnect;
-}
-
-// We go to the disconnect state when the connection needs to be dropped either because we lost the session ID
-// coin toss or something's gone wrong. In either case, we do not attempt to reconnect--we either go to the idle state
-// or the disconnect_wait state, depending on whether or not the connection has already been closed.
-static srpl_state_t
-srpl_disconnect_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // Any ongoing state needs to be discarded.
-    srpl_connection_reset(srpl_connection);
-
-    // Disconnect the srpl_connection_t
-    if (srpl_connection->connection == NULL) {
-        return srpl_state_idle;
-    }
-    ioloop_comm_cancel(srpl_connection->connection);
-    return srpl_state_disconnect_wait;
-}
-
-// We enter disconnect_wait when we are waiting for a disconnect event after cancelling a connection.
-// There is no action for this event. The only event we are interested in is the disconnect event.
-static srpl_state_t
-srpl_disconnect_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    STATE_ANNOUNCE(srpl_connection, event);
-    if (event == NULL) {
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_disconnected) {
-        return srpl_state_idle;
-    } else {
-        UNEXPECTED_EVENT_NO_ERROR(srpl_connection, event);
-    }
-    return srpl_state_invalid;
-}
-
-// We enter the connecting state when we've attempted a connection to some address.
-// This state has no action. If a connected event is received, we move to the connected state.
-// If a disconnected event is received, we move to the next_address_get state.
-static srpl_state_t
-srpl_connecting_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    STATE_ANNOUNCE(srpl_connection, event);
-    if (event == NULL) {
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_disconnected) {
-        return srpl_state_idle;
-    } else if (event->event_type == srpl_event_connected) {
-        return srpl_state_server_id_send;
-    } else {
-        UNEXPECTED_EVENT_NO_ERROR(srpl_connection, event);
-    }
-    return srpl_state_invalid;
-}
-
-// This state sends a server id and then goes to server_id_response_wait, unless the send failed, in which
-// case it goes to the disconnect state.
-static srpl_state_t
-srpl_server_id_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // Send a server id message
-    // Now we say hello.
-    if (!srpl_session_message_send(srpl_connection, false)) {
-        return srpl_state_disconnect;
-    }
-    return srpl_state_server_id_response_wait;
-}
-
-// This state waits for a session response with the remote server ID.
-// When the response arrives, it goes to the send_candidates_send state.
-static srpl_state_t
-srpl_server_id_response_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    STATE_ANNOUNCE(srpl_connection, event);
-    if (event == NULL) {
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_session_response_received) {
-        srpl_connection->remote_server_id = event->content.server_id;
-        return srpl_state_send_candidates_send;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-    return srpl_state_invalid;
-}
-
-// When evaluating the incoming ID, we've decided to continue (called by srpl_evaluate_incoming_id_action).
-static srpl_state_t
-srpl_evaluate_incoming_continue(srpl_connection_t *srpl_connection)
-{
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return srpl_state_invalid;
-    }
-
-    INFO(PRI_S_SRP ": our server id %" PRIx64 " < remote server id %" PRIx64,
-         srpl_connection->name, server_state->server_id, srpl_connection->remote_server_id);
-    if (srpl_connection->is_server) {
-        return srpl_state_session_response_send;
-    } else {
-        return srpl_state_send_candidates_send;
-    }
-}
-
-// When evaluating the incoming ID, we've decided to disconnect (called by srpl_evaluate_incoming_id_action).
-static srpl_state_t
-srpl_evaluate_incoming_disconnect(srpl_connection_t *srpl_connection, bool bad)
-{
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return srpl_state_invalid;
-    }
-    INFO(PRI_S_SRP ": our server id %" PRIx64 " > remote server id %" PRIx64,
-         srpl_connection->name, server_state->server_id, srpl_connection->remote_server_id);
-    if (srpl_connection->instance->is_me) {
-        return srpl_evaluate_incoming_continue(srpl_connection);
-    } else {
-        if (bad) {
-            // bad is set if the server send back the same ID we sent, which means it's misbehaving.
-            return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-        }
-        return srpl_state_disconnect;
-    }
-}
-
-// This state's action is to evaluate the server ID that we received. If ours is greater than theirs,
-// a server connection generated a new ID; a client connection disconnects.
-static srpl_state_t
-srpl_server_id_evaluate_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return srpl_state_invalid;
-    }
-
-    // Compare the server id we received to our own
-    // Return one of "outgoing id equal", "outgoing id less" or "outgoing id more"
-    if (server_state->server_id > srpl_connection->remote_server_id) {
-        return srpl_evaluate_incoming_disconnect(srpl_connection, false);
-    } else if (server_state->server_id < srpl_connection->remote_server_id) {
-        return srpl_evaluate_incoming_continue(srpl_connection);
-    } else {
-        INFO(PRI_S_SRP ": our server id %" PRIx64 " == remote server id %" PRIx64,
-             srpl_connection->name, server_state->server_id, srpl_connection->remote_server_id);
-        if (srpl_connection->is_server) {
-            return srpl_state_server_id_regenerate;
-        } else {
-            return srpl_evaluate_incoming_disconnect(srpl_connection, true);
-        }
-    }
-}
-
-// This state's action is to regenerate the server ID, and then go back to evaluate_incoming_id.
-static srpl_state_t
-srpl_server_id_regenerate_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-    srp_server_t *server_state = srpl_connection_server_state(srpl_connection);
-    if (server_state == NULL) {
-        return srpl_state_invalid;
-    }
-
-    // Generate a new server id
-    server_state->server_id = srp_random64();
-    INFO(PRI_S_SRP ": new server id %" PRIx64, srpl_connection->name, server_state->server_id);
-
-    // Re-advertise the domain with the new server ID.
-    srpl_domain_advertise(srpl_connection->instance->domain->server_state);
-
-    // return the server id in a "new server id" event.
-    return srpl_state_server_id_evaluate;
-}
-
-// This state's action is to send the "send candidates" message, and then go to the send_candidates_wait state.
-static srpl_state_t
-srpl_send_candidates_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // Send "send candidates" message
-    // Return no event
-    srpl_send_candidates_message_send(srpl_connection, false);
-    return srpl_state_send_candidates_wait;
-}
-
-// Used by srpl_send_candidates_wait_action and srpl_host_wait_action
-static srpl_state_t
-srpl_send_candidates_wait_event_process(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    if (event->event_type == srpl_event_send_candidates_response_received) {
-        if (srpl_connection->is_server) {
-            srpl_connection->database_synchronized = true;
-            return srpl_state_ready;
-        } else {
-            return srpl_state_send_candidates_message_wait;
-        }
-    } else if (event->event_type == srpl_event_candidate_received) {
-        srpl_connection_candidate_set(srpl_connection, event->content.candidate);
-        event->content.candidate = NULL; // steal!
-        return srpl_state_candidate_check;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// We reach this state after having sent a "send candidates" message, so we can in principle get either a
-// "candidate" message or a "send candidates" response here, leading either to send_candidates check or one
-// of two states depending on whether this connection is an incoming or outgoing connection. Outgoing
-// connections send the "send candidates" message first, so when they get a "send candidates" reply, they
-// need to wait for a "send candidates" message from the remote. Incoming connections send the "send candidates"
-// message last, so when they get the "send candidates" reply, the database sync is done and it's time to
-// just deal with ongoing updates. In this case we go to the check_for_srp_client_updates state, which
-// looks to see if any updates came in from SRP clients while we were syncing the databases.
-static srpl_state_t
-srpl_send_candidates_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    }
-    return srpl_send_candidates_wait_event_process(srpl_connection, event);
-}
-
-static srpl_candidate_disposition_t
-srpl_candidate_host_check(srpl_connection_t *srpl_connection, adv_host_t *host)
-{
-    // Evaluate candidate
-    // Return "host candidate wanted" or "host candidate not wanted" event
-    if (host == NULL) {
-        INFO("host is NULL, answer is yes.");
-        return srpl_candidate_yes;
-    } else {
-        if (host->removed) {
-            INFO("host is removed, answer is yes.");
-            return srpl_candidate_yes;
-        } else if (host->key_id != srpl_connection->candidate->key_id) {
-            INFO("host key conflict (%x vs %x), answer is conflict.", host->key_id, srpl_connection->candidate->key_id);
-            return srpl_candidate_conflict;
-        } else {
-            // We allow for a bit of jitter. Bear in mind that candidates only happen on startup, so
-            // even if a previous run of the SRP server on this device was responsible for registering
-            // the candidate, we don't have it, so we still need it.
-            if (host->update_time - srpl_connection->candidate->update_time > SRPL_UPDATE_JITTER_WINDOW) {
-                INFO("host update time %" PRId64 " candidate update time %" PRId64 ", answer is no.",
-                     (int64_t)host->update_time, (int64_t)srpl_connection->candidate->update_time);
-                return srpl_candidate_no;
-            } else {
-                INFO("host update time %" PRId64 " candidate update time %" PRId64 ", answer is yes.",
-                     (int64_t)host->update_time, (int64_t)srpl_connection->candidate->update_time);
-                return srpl_candidate_yes;
-            }
-        }
-    }
-}
-
-// We enter this state after we've received a "candidate" message, and check to see if we want the host the candidate
-// represents. We then send an appropriate response.
-static srpl_state_t
-srpl_candidate_check_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS_NAME(srpl_connection, srpl_connection->candidate->name);
-
-    adv_host_t *host = srp_adv_host_copy(srpl_connection->instance->domain->server_state,
-                                         srpl_connection->candidate->name);
-    srpl_candidate_disposition_t disposition = srpl_candidate_host_check(srpl_connection, host);
-    if (host != NULL) {
-        srp_adv_host_release(host);
-    }
-    switch(disposition) {
-    case srpl_candidate_yes:
-        srpl_candidate_response_send(srpl_connection, kDSOType_SRPLCandidateYes);
-        return srpl_state_candidate_host_wait;
-    case srpl_candidate_no:
-        srpl_candidate_response_send(srpl_connection, kDSOType_SRPLCandidateNo);
-        return srpl_state_send_candidates_wait;
-    case srpl_candidate_conflict:
-        srpl_candidate_response_send(srpl_connection, kDSOType_SRPLConflict);
-        return srpl_state_send_candidates_wait;
-    }
-    return srpl_state_invalid;
-}
-
-// In candidate_host_send_wait, we take no action and wait for events. We're hoping for a "host" message, leading to
-// candidate_host_prepare. We could also receive a "candidate" message, leading to candidate_received, or a "send
-// candidates" reply, leading to candidate_reply_received.
-
-static srpl_state_t
-srpl_candidate_host_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_host_message_received) {
-        // Copy the update information, retain what's refcounted, and free what's not on the event.
-        srpl_host_update_steal_parts(&srpl_connection->stashed_host, &event->content.host_update);
-        return srpl_state_candidate_host_prepare;
-    } else {
-        return srpl_send_candidates_wait_event_process(srpl_connection, event);
-    }
-}
-
-// Here we want to see if we can do an immediate update; if so, we go to candidate_host_re_evaluate; otherwise
-// we go to candidate_host_contention_wait
-static srpl_state_t
-srpl_candidate_host_prepare_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS_NAME(srpl_connection, srpl_connection->candidate->name);
-
-    // Apply the host from the event to the current host list
-    // Return no event
-    adv_host_t *host = srp_adv_host_copy(srpl_connection->instance->domain->server_state,
-                                         srpl_connection->candidate->name);
-    if (host == NULL) {
-        // If we don't have this host, we can apply the update immediately.
-        return srpl_state_candidate_host_apply;
-    }
-    if (host->srpl_connection != NULL || host->update != NULL) {
-        // We are processing an update from a different srpl server or a client.
-        INFO(PRI_S_SRP ": host->srpl_connection = %p  host->update=%p--going into contention",
-             srpl_connection->name, host->srpl_connection, host->update);
-        srp_adv_host_release(host);
-        return srpl_state_candidate_host_contention_wait;
-    } else {
-        srpl_connection->candidate->host = host;
-        return srpl_state_candidate_host_re_evaluate;
-    }
-}
-
-static adv_host_t *
-srpl_client_update_matches(dns_name_t *hostname, srpl_event_t *event)
-{
-    adv_host_t *host = event->content.client_result.host;
-    if (event->content.client_result.rcode == dns_rcode_noerror && dns_names_equal_text(hostname, host->name)) {
-        INFO("returning host " PRI_S_SRP, host->name);
-        return host;
-    }
-    char name[kDNSServiceMaxDomainName];
-    dns_name_print(hostname, name, sizeof(name));
-    INFO("returning NULL: rcode = " PUB_S_SRP "  hostname = " PRI_S_SRP "  host->name = " PRI_S_SRP,
-         dns_rcode_name(event->content.client_result.rcode), name, host->name);
-    return NULL;
-}
-
-// and wait for a srp_client_update_finished event for the host, which
-// will trigger us to move to candidate_host_re_evaluate.
-static srpl_state_t
-srpl_candidate_host_contention_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_srp_client_update_finished) {
-        adv_host_t *host = srpl_client_update_matches(srpl_connection->candidate->name, event);
-        if (host != NULL) {
-            srpl_connection->candidate->host = host;
-            srp_adv_host_retain(srpl_connection->candidate->host);
-            return srpl_state_candidate_host_re_evaluate;
-        }
-        return srpl_state_invalid; // Keep waiting
-    } else if (event->event_type == srpl_event_advertise_finished) {
-        // See if this is an event on the host we were waiting for.
-        if (event->content.advertise_finished.hostname != NULL &&
-            dns_names_equal_text(srpl_connection->candidate->name, event->content.advertise_finished.hostname))
-        {
-            return srpl_state_candidate_host_re_evaluate;
-        }
-        return srpl_state_invalid;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// At this point we've either waited for the host to no longer be in contention, or else it wasn't in contention.
-// There was a time gap between when we sent the candidate response and when the host message arrived, so an update
-// may have arrived locally for that SRP client. We therefore re-evaluate at this point.
-static srpl_state_t
-srpl_candidate_host_re_evaluate_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS_NAME(srpl_connection, srpl_connection->candidate->name);
-
-    adv_host_t *host = srpl_connection->candidate->host;
-    // The host we retained may have become invalid; if so, discard it
-    if (host != NULL && !srp_adv_host_valid(host)) {
-        srp_adv_host_release(srpl_connection->candidate->host);
-        srpl_connection->candidate->host = host = NULL;
-    }
-    // If it was invalidated, or if we got here directly, look up the host by name
-    if (host == NULL) {
-        host = srp_adv_host_copy(srpl_connection->instance->domain->server_state,
-                                 srpl_connection->candidate->name);
-        srpl_connection->candidate->host = host;
-    }
-    // It's possible that the host is gone; in this case we definitely want the update.
-    if (host == NULL) {
-        return srpl_state_candidate_host_apply;
-    }
-
-    // At this point we know that the host we were looking for is valid. Now check to see if we still want to apply it.
-    srpl_state_t ret = srpl_state_invalid;
-    srpl_candidate_disposition_t disposition = srpl_candidate_host_check(srpl_connection, host);
-    switch(disposition) {
-    case srpl_candidate_yes:
-        ret = srpl_state_candidate_host_apply;
-        break;
-    case srpl_candidate_no:
-        // This happens if we got a candidate and wanted it, but then got an SRP update on that candidate while waiting
-        // for events. In this case, there's no real problem, and the successful update should trigger an update to be
-        // sent to the remote.
-        srpl_host_response_send(srpl_connection, dns_rcode_noerror);
-        ret = srpl_state_send_candidates_wait;
-        break;
-    case srpl_candidate_conflict:
-        srpl_host_response_send(srpl_connection, dns_rcode_yxdomain);
-        ret = srpl_state_send_candidates_wait;
-        break;
-    }
-    return ret;
-}
-
-static bool
-srpl_connection_host_apply(srpl_connection_t *srpl_connection)
-{
-    if (!srp_dns_evaluate(NULL, srpl_connection->instance->domain->server_state,
-                          srpl_connection, srpl_connection->stashed_host.message)) {
-        srpl_host_response_send(srpl_connection, dns_rcode_formerr);
-        return false;
-    }
-    return true;
-}
-
-// At this point we know there is no contention on the host, and we want to update it, so start the update by passing the
-// host message to dns_evaluate.
-static srpl_state_t
-srpl_candidate_host_apply_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    // Apply the host from the event to the current host list
-    // Return no event
-    // Note that we set host->srpl_connection _after_ we call dns_evaluate. This ensures that any "advertise_finished"
-    // calls that are done during the call to dns_evaluate do not deliver an event here.
-    if (event == NULL) {
-        if (!srpl_connection_host_apply(srpl_connection)) {
-            return srpl_state_send_candidates_wait;
-        }
-        return srpl_state_candidate_host_apply_wait;
-    } else if (event->event_type == srpl_event_advertise_finished) {
-        // This shouldn't be possible anymore, but I'm putting a FAULT in here in case I'm mistaken.
-        FAULT(PRI_S_SRP ": advertise_finished event!", srpl_connection->name);
-        return srpl_state_invalid;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// Called by the SRP server when an advertise has finished for an update recevied on a connection.
-static void
-srpl_deferred_advertise_finished_event_deliver(void *context)
-{
-    srpl_event_t *event = context;
-    srp_server_t *server_state = event->content.advertise_finished.server_state;
-
-    for (srpl_domain_t *domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (srpl_instance_t *instance = domain->instances; instance != NULL; instance = instance->next) {
-            if (instance->outgoing != NULL) {
-                srpl_event_deliver(instance->outgoing, event);
-            }
-            if (instance->incoming != NULL) {
-                srpl_event_deliver(instance->incoming, event);
-            }
-        }
-    }
-
-    free(event->content.advertise_finished.hostname);
-    free(event);
-}
-
-// Send an advertise_finished event for the specified hostname to all connections. Because this is called from
-// advertise_finished, we do not want any state machine to advance immediately, so we defer delivery of this
-// event until the next time we return to the main event loop.
-void
-srpl_advertise_finished_event_send(char *hostname, int rcode, srp_server_t *server_state)
-{
-    srpl_event_t *event = calloc(1, sizeof(*event));
-    if (event == NULL) {
-        ERROR("No memory to defer advertise_finished event for " PUB_S_SRP, hostname);
-        return;
-    }
-
-    srpl_event_initialize(event, srpl_event_advertise_finished);
-    event->content.advertise_finished.rcode = rcode;
-    event->content.advertise_finished.hostname = strdup(hostname);
-    event->content.advertise_finished.server_state = server_state;
-    if (event->content.advertise_finished.hostname == NULL) {
-        INFO(PRI_S_SRP ": no memory for hostname", hostname);
-        free(event);
-        return;
-    }
-    ioloop_run_async(srpl_deferred_advertise_finished_event_deliver, event);
-}
-
-
-// We enter this state to wait for the application of a host update to complete.
-// We exit the state for the send_candidates_wait state when we receive an advertise_finished event.
-// Additionally when we receive an advertise_finished event we send a "host" response with the rcode
-// returned in the advertise_finished event.
-static srpl_state_t
-srpl_candidate_host_apply_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_advertise_finished) {
-        srpl_host_response_send(srpl_connection, event->content.advertise_finished.rcode);
-        srpl_host_update_parts_free(&srpl_connection->stashed_host);
-        return srpl_state_send_candidates_wait;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// This marks the end of states that occur as a result of sending a "send candidates" message.
-// This marks the beginning of states that occur as a result of receiving a send_candidates message.
-
-// We have received a "send candidates" message; the action is to create a candidates list.
-static srpl_state_t
-srpl_send_candidates_received_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    int num_candidates;
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // Make sure we don't have a candidate list.
-    if (srpl_connection->candidates != NULL) {
-        srpl_connection_candidates_free(srpl_connection);
-        srpl_connection->candidates = NULL;
-        // Just in case we exit due to a failure...
-        srpl_connection->num_candidates = 0;
-        srpl_connection->current_candidate = -1;
-    }
-    // Generate a list of candidates from the current host list.
-    // Return no event
-    srp_server_t *server_state = srpl_connection->instance->domain->server_state;
-    num_candidates = srp_current_valid_host_count(server_state);
-    if (num_candidates > 0) {
-        adv_host_t **candidates = calloc(num_candidates, sizeof(*candidates));
-        int copied_candidates;
-        if (candidates == NULL) {
-            ERROR("unable to allocate candidates list.");
-            return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-        }
-        copied_candidates = srp_hosts_to_array(server_state, candidates, num_candidates);
-        if (copied_candidates > num_candidates) {
-            FAULT("copied_candidates %d > num_candidates %d",
-                  copied_candidates, num_candidates);
-            return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-        }
-        if (num_candidates != copied_candidates) {
-            INFO("srp_hosts_to_array returned the wrong number of hosts: copied_candidates %d > num_candidates %d",
-                 copied_candidates, num_candidates);
-            num_candidates = copied_candidates;
-        }
-        srpl_connection->candidates = candidates;
-    }
-    srpl_connection->candidates_not_generated = false;
-    srpl_connection->num_candidates = num_candidates;
-    srpl_connection->current_candidate = -1;
-    return srpl_state_send_candidates_remaining_check;
-}
-
-// See if there are candidates remaining; if not, send "send candidates" response.
-static srpl_state_t
-srpl_candidates_remaining_check_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // Get the next candidate out of the candidate list
-    // Return "no candidates left" or "next candidate"
-    if (srpl_connection->current_candidate + 1 < srpl_connection->num_candidates) {
-        srpl_connection->current_candidate++;
-        return srpl_state_next_candidate_send;
-    } else {
-        return srpl_state_send_candidates_response_send;
-    }
-}
-
-// Send the next candidate.
-static srpl_state_t
-srpl_next_candidate_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    srpl_candidate_message_send(srpl_connection, srpl_connection->candidates[srpl_connection->current_candidate]);
-    return srpl_state_next_candidate_send_wait;
-}
-
-// Wait for a "candidate" response.
-static srpl_state_t
-srpl_next_candidate_send_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_candidate_response_received) {
-        switch (event->content.disposition) {
-        case srpl_candidate_yes:
-            return srpl_state_candidate_host_send;
-        case srpl_candidate_no:
-        case srpl_candidate_conflict:
-            return srpl_state_send_candidates_remaining_check;
-        }
-        return srpl_state_invalid;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// Send the host for the candidate.
-static srpl_state_t
-srpl_candidate_host_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    // It's possible that the host that we put on the candidates list has become invalid. If so, just go back and send
-    // the next candidate (or finish).
-    adv_host_t *host = srpl_connection->candidates[srpl_connection->current_candidate];
-    if (!srp_adv_host_valid(host) || host->message == NULL) {
-        return srpl_state_send_candidates_remaining_check;
-    }
-    srpl_host_message_send(srpl_connection, host);
-    return srpl_state_candidate_host_response_wait;
-}
-
-// Wait for a "host" response.
-static srpl_state_t
-srpl_candidate_host_response_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_host_response_received) {
-        // The only failure case we care about is a conflict, and we don't have a way to handle that, so just
-        // continue without checking the status.
-        return srpl_state_send_candidates_remaining_check;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// At this point we're done sending candidates, so we send a "send candidates" response.
-static srpl_state_t
-srpl_send_candidates_response_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    srpl_send_candidates_message_send(srpl_connection, true);
-    // When the server has sent its candidate response, it's immediately ready to send a "send candidate" message
-    // When the client has sent its candidate response, the database synchronization is done on the client.
-    if (srpl_connection->is_server) {
-        return srpl_state_send_candidates_send;
-    } else {
-        srpl_connection->database_synchronized = true;
-        return srpl_state_ready;
-    }
-}
-
-// The ready state is where we land when there's no remaining work to do. We wait for events, and when we get one,
-// we handle it, ultimately returning to this state.
-static srpl_state_t
-srpl_ready_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        // Whenever we newly land in this state, see if there is an unsent client update at the head of the
-        // queue, and if so, send it.
-        if (srpl_connection->client_update_queue != NULL && !srpl_connection->client_update_queue->sent) {
-            adv_host_t *host = srpl_connection->client_update_queue->host;
-            if (host == NULL || host->name == NULL) {
-                INFO(PRI_S_SRP ": we have an update to send for bogus host %p.", srpl_connection->name, host);
-            } else {
-                INFO(PRI_S_SRP ": we have an update to send for host " PRI_S_SRP, srpl_connection->name,
-                     srpl_connection->client_update_queue->host->name);
-            }
-            return srpl_state_srp_client_update_send;
-        } else {
-            if (srpl_connection->client_update_queue != NULL) {
-                adv_host_t *host = srpl_connection->client_update_queue->host;
-                if (host == NULL || host->name == NULL) {
-                    INFO(PRI_S_SRP ": there is anupdate that's marked sent for bogus host %p.",
-                         srpl_connection->name, host);
-                } else {
-                    INFO(PRI_S_SRP ": there is an update on the queue that's marked sent for host " PRI_S_SRP,
-                         srpl_connection->name, host->name);
-                }
-            } else {
-                INFO(PRI_S_SRP ": the client update queue is empty.", srpl_connection->name);
-            }
-        }
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_host_message_received) {
-        if (srpl_connection->stashed_host.message != NULL) {
-            FAULT(PRI_S_SRP ": stashed host present but host message received", srpl_connection->name);
-            return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-        }
-        // Copy the update information, retain what's refcounted, and NULL out what's not, on the event.
-        srpl_host_update_steal_parts(&srpl_connection->stashed_host, &event->content.host_update);
-        return srpl_state_stashed_host_check;
-    } else if (event->event_type == srpl_event_host_response_received) {
-        return srpl_state_srp_client_ack_evaluate;
-    } else if (event->event_type == srpl_event_advertise_finished) {
-        if (srpl_connection->stashed_host.hostname != NULL &&
-            event->content.advertise_finished.hostname != NULL &&
-            dns_names_equal_text(srpl_connection->stashed_host.hostname, event->content.advertise_finished.hostname))
-        {
-            srpl_connection->stashed_host.rcode = event->content.advertise_finished.rcode;
-            return srpl_state_stashed_host_finished;
-        }
-        return srpl_state_invalid;
-    } else if (event->event_type == srpl_event_srp_client_update_finished) {
-        // When we receive a client update in ready state, we just need to re-run the state's action.
-        return srpl_state_ready;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// We get here when there is at least one client update queued up to send
-static srpl_state_t
-srpl_srp_client_update_send_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    srpl_srp_client_queue_entry_t *update = srpl_connection->client_update_queue;
-    if (update != NULL) {
-        // If the host has a message, send it. Note that this host may well be removed, but if it had been removed
-        // through a lease expiry we wouldn't have got here, because the host object would have been removed from
-        // the list. So if it has a message attached to it, that means that either it's been removed explicitly by
-        // the client, which we need to propagate, or else it is still valid, and so we need to propagate the most
-        // recent update we got.
-        if (update->host->message != NULL) {
-            srpl_host_message_send(srpl_connection, update->host);
-            update->sent = true;
-        } else {
-            ERROR(PRI_S_SRP ": no host message to send for host " PRI_S_SRP ".",
-                  srpl_connection->name, update->host->name);
-
-            // We're not going to send this update, so take it off the queue.
-            srpl_connection->client_update_queue = update->next;
-            srp_adv_host_release(update->host);
-            free(update);
-        }
-    }
-    return srpl_state_ready;
-}
-
-// We go here when we get a "host" response; all we do is remove the host from the top of the queue.
-static srpl_state_t
-srpl_srp_client_ack_evaluate_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    if (srpl_connection->client_update_queue == NULL) {
-        FAULT(PRI_S_SRP ": update queue empty in ready, but host_response_received event received.",
-              srpl_connection->name);
-        return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-    }
-    if (!srpl_connection->client_update_queue->sent) {
-        FAULT(PRI_S_SRP ": top of update queue not sent, but host_response_received event received.",
-              srpl_connection->name);
-        return srpl_connection_drop_state(srpl_connection->instance, srpl_connection);
-    }
-    srpl_srp_client_queue_entry_t *finished_update = srpl_connection->client_update_queue;
-    srpl_connection->client_update_queue = finished_update->next;
-    if (finished_update->host != NULL) {
-        srp_adv_host_release(finished_update->host);
-    }
-    free(finished_update);
-    return srpl_state_ready;
-}
-
-// We go here when we get a "host" message
-static srpl_state_t
-srpl_stashed_host_check_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS_NAME(srpl_connection, srpl_connection->stashed_host.hostname);
-
-    adv_host_t *host = srp_adv_host_copy(srpl_connection->instance->domain->server_state,
-                                         srpl_connection->stashed_host.hostname);
-    // No contention...
-    if (host == NULL) {
-        INFO("applying host because it doesn't exist locally.");
-        return srpl_state_stashed_host_apply;
-    } else if (host->update == NULL && host->srpl_connection == NULL) {
-        INFO("applying host because there's no contention.");
-        srp_adv_host_release(host);
-        return srpl_state_stashed_host_apply;
-    } else {
-        INFO("not applying host because there is contention. host->update %p   host->srpl_connection: %p",
-             host->update, host->srpl_connection);
-    }
-    srp_adv_host_release(host);
-    return srpl_state_ready; // Wait for something to happen
-}
-
-// We go here when we have a stashed host to apply.
-static srpl_state_t
-srpl_stashed_host_apply_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        if (!srpl_connection_host_apply(srpl_connection)) {
-            srpl_connection->stashed_host.rcode = dns_rcode_servfail;
-            return srpl_state_stashed_host_finished;
-        }
-        return srpl_state_ready; // Wait for something to happen
-    } else if (event->event_type == srpl_event_advertise_finished) {
-        // This shouldn't be possible anymore, but I'm putting a FAULT in here in case I'm mistaken.
-        FAULT(PRI_S_SRP ": advertise_finished event!", srpl_connection->name);
-        return srpl_state_invalid;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// We go here when a host update advertise finishes.
-static srpl_state_t
-srpl_stashed_host_finished_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    if (srpl_connection->stashed_host.hostname == NULL) {
-        FAULT(PRI_S_SRP ": stashed host not present, but advertise_finished event received.", srpl_connection->name);
-        return srpl_state_ready;
-    }
-    srpl_host_response_send(srpl_connection, srpl_connection->stashed_host.rcode);
-    srpl_host_update_parts_free(&srpl_connection->stashed_host);
-    return srpl_state_ready;
-}
-
-// We land here immediately after a server connection is received.
-static srpl_state_t
-srpl_session_message_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_session_message_received) {
-        srpl_connection->remote_server_id = event->content.server_id;
-        return srpl_state_server_id_evaluate;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// Send a server id response
-static srpl_state_t
-srpl_session_response_send(srpl_connection_t *UNUSED srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_EVENT_NULL(srpl_connection, event);
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE_NO_EVENTS(srpl_connection);
-
-    if (!srpl_session_message_send(srpl_connection, true)) {
-        return srpl_state_disconnect;
-    }
-    return srpl_state_send_candidates_message_wait;
-}
-
-// We land here immediately after a server connection is received.
-static srpl_state_t
-srpl_send_candidates_message_wait_action(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    REQUIRE_SRPL_INSTANCE(srpl_connection);
-    STATE_ANNOUNCE(srpl_connection, event);
-
-    if (event == NULL) {
-        return srpl_state_invalid; // Wait for events.
-    } else if (event->event_type == srpl_event_send_candidates_message_received) {
-        return srpl_state_send_candidates_received;
-    } else {
-        UNEXPECTED_EVENT(srpl_connection, event);
-    }
-}
-
-// Check to see if host is on the list of remaining candidates to send. If so, no need to do anything--it'll go out soon.
-static bool
-srpl_reschedule_candidate(srpl_connection_t *srpl_connection, adv_host_t *host)
-{
-    // We don't need to queue new updates if we haven't yet generated a candidates list.
-    if (srpl_connection->candidates_not_generated) {
-        INFO("returning true because we haven't generated candidates.");
-        return true;
-    }
-    if (srpl_connection->candidates == NULL) {
-        INFO("returning false because we have no candidates.");
-        return false;
-    }
-    for (int i = srpl_connection->current_candidate + 1; i < srpl_connection->num_candidates; i++) {
-        if (srpl_connection->candidates[i] == host) {
-            INFO("returning true because the host is on the candidate list.");
-            return true;
-        }
-    }
-    INFO("returning false because the host is not on the candidate list.");
-    return false;
-}
-
-static void
-srpl_queue_srp_client_update(srpl_connection_t *srpl_connection, adv_host_t *host)
-{
-    srpl_srp_client_queue_entry_t *new_entry, **qp;
-    // Find the end of the queue
-    for (qp = &srpl_connection->client_update_queue; *qp; qp = &(*qp)->next) {
-        srpl_srp_client_queue_entry_t *entry = *qp;
-        // No need to re-queue if we're already on the queue
-        if (!entry->sent && entry->host == host) {
-            INFO("host " PRI_S_SRP " is already on the update queue for connection " PRI_S_SRP,
-                 host->name, srpl_connection->name);
-            return;
-        }
-    }
-    new_entry = calloc(1, sizeof(*new_entry));
-    if (new_entry == NULL) {
-        ERROR(PRI_S_SRP ": no memory to queue SRP client update.", srpl_connection->name);
-        return;
-    }
-    INFO("adding host " PRI_S_SRP " to the update queue for connection " PRI_S_SRP, host->name, srpl_connection->name);
-    new_entry->host = host;
-    srp_adv_host_retain(new_entry->host);
-    *qp = new_entry;
-}
-
-// Client update events are interesting in two cases. First, we might have received a host update for a
-// host that was in contention when the update was received; in this case, we want to now apply the update,
-// assuming that the contention is no longer present (it's possible that there are multiple sources of
-// contention).
-//
-// The second case is where a client update succeeded; in this case we want to send that update to all of
-// the remotes.
-//
-// We do not receive this event when an update that was triggered by an SRP Replication update; in that
-// case we get an "apply finished" event instead of a "client update finished" event.
-static void
-srpl_srp_client_update_send_event_to_connection(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    if (event->content.client_result.rcode == dns_rcode_noerror) {
-        adv_host_t *host = event->content.client_result.host;
-        if (!srpl_reschedule_candidate(srpl_connection, host)) {
-            srpl_queue_srp_client_update(srpl_connection, host);
-        }
-    }
-    srpl_event_deliver(srpl_connection, event);
-}
-
-static void
-srpl_deferred_srp_client_update_finished_event_deliver(void *context)
-{
-    srpl_event_t *event = context;
-    srp_server_t *server_state = event->content.client_result.host->server_state;
-    if (server_state == NULL) {
-        FAULT("server state is NULL."); // this can't currently happen, because we just finished updating the host.
-        goto out;
-    }
-    for (srpl_domain_t *domain = server_state->srpl_domains; domain != NULL; domain = domain->next) {
-        for (srpl_instance_t *instance = domain->instances; instance != NULL; instance = instance->next) {
-            if (instance->outgoing != NULL) {
-                srpl_srp_client_update_send_event_to_connection(instance->outgoing, event);
-            }
-            if (instance->incoming != NULL) {
-                srpl_srp_client_update_send_event_to_connection(instance->incoming, event);
-            }
-        }
-    }
-out:
-    srp_adv_host_release(event->content.client_result.host);
-    free(event);
-}
-
-// When an SRP client update finished, we need to deliver an event to all connections indicating that this has
-// occurred. This event must be delivered from the main run loop, to avoid starting an update before advertise_finish
-// has completed its work.
-void
-srpl_srp_client_update_finished_event_send(adv_host_t *host, int rcode)
-{
-    srpl_event_t *event;
-    event = malloc(sizeof(*event));
-    if (event == NULL) {
-        FAULT(PRI_S_SRP ": unable to allocate memory to defer event", host->name);
-        return;
-    }
-    srpl_event_initialize(event, srpl_event_srp_client_update_finished);
-    srpl_event_content_type_set(event, srpl_event_content_type_client_result);
-    event->content.client_result.host = host;
-    srp_adv_host_retain(event->content.client_result.host);
-    event->content.client_result.rcode = rcode;
-    ioloop_run_async(srpl_deferred_srp_client_update_finished_event_deliver, event);
-}
-
-typedef struct {
-    srpl_state_t state;
-    char *name;
-    srpl_action_t action;
-} srpl_connection_state_t;
-
-#define STATE_NAME_DECL(name) srpl_state_##name, #name
-static srpl_connection_state_t srpl_connection_states[] = {
-    { STATE_NAME_DECL(invalid),                              NULL },
-    { STATE_NAME_DECL(disconnected),                         srpl_disconnected_action },
-    { STATE_NAME_DECL(next_address_get),                     srpl_next_address_get_action },
-    { STATE_NAME_DECL(connect),                              srpl_connect_action },
-    { STATE_NAME_DECL(idle),                                 srpl_idle_action },
-    { STATE_NAME_DECL(reconnect_wait),                       srpl_reconnect_wait_action },
-    { STATE_NAME_DECL(retry_delay_send),                     srpl_retry_delay_send_action },
-    { STATE_NAME_DECL(disconnect),                           srpl_disconnect_action },
-    { STATE_NAME_DECL(disconnect_wait),                      srpl_disconnect_wait_action },
-    { STATE_NAME_DECL(connecting),                           srpl_connecting_action },
-    { STATE_NAME_DECL(server_id_send),                       srpl_server_id_send_action },
-    { STATE_NAME_DECL(server_id_response_wait),              srpl_server_id_response_wait_action },
-    { STATE_NAME_DECL(server_id_evaluate),                   srpl_server_id_evaluate_action },
-    { STATE_NAME_DECL(server_id_regenerate),                 srpl_server_id_regenerate_action },
-
-    // Here we are the endpoint that has send the "send candidates message" and we are cycling through the candidates
-    // we receive until we get a "send candidates" reply.
-
-    { STATE_NAME_DECL(send_candidates_send),                 srpl_send_candidates_send_action },
-    { STATE_NAME_DECL(send_candidates_wait),                 srpl_send_candidates_wait_action },
-
-    // Got a "candidate" message, need to check it and send the right reply.
-    { STATE_NAME_DECL(candidate_check),                      srpl_candidate_check_action },
-
-    // At this point we've send a candidate reply, so we're waiting for a host message. It's possible that the host
-    // went away in the interim, in which case we will get a "candidate" message or a "send candidate" reply.
-
-    { STATE_NAME_DECL(candidate_host_wait),                  srpl_candidate_host_wait_action },
-    { STATE_NAME_DECL(candidate_host_prepare),               srpl_candidate_host_prepare_action },
-    { STATE_NAME_DECL(candidate_host_contention_wait),       srpl_candidate_host_contention_wait_action },
-    { STATE_NAME_DECL(candidate_host_re_evaluate),           srpl_candidate_host_re_evaluate_action },
-
-    // Here we've gotten the host message (the SRP message), and need to apply it and send a response
-    { STATE_NAME_DECL(candidate_host_apply),                 srpl_candidate_host_apply_action },
-    { STATE_NAME_DECL(candidate_host_apply_wait),            srpl_candidate_host_apply_wait_action },
-
-    // We've received a "send candidates" message. Make a list of candidates to send, and then start sending them.
-    { STATE_NAME_DECL(send_candidates_received),             srpl_send_candidates_received_action },
-    // See if there are any candidates left to send; if not, go to send_candidates_response_send
-    { STATE_NAME_DECL(send_candidates_remaining_check),      srpl_candidates_remaining_check_action },
-    // Send a "candidate" message for the next candidate
-    { STATE_NAME_DECL(next_candidate_send),                  srpl_next_candidate_send_action },
-    // Wait for a response to the "candidate" message
-    { STATE_NAME_DECL(next_candidate_send_wait),             srpl_next_candidate_send_wait_action },
-    // The candidate requested, so send its host info
-    { STATE_NAME_DECL(candidate_host_send),                  srpl_candidate_host_send_action },
-    // We're waiting for the remote to acknowledge the host update
-    { STATE_NAME_DECL(candidate_host_response_wait),         srpl_candidate_host_response_wait_action },
-
-    // When we've run out of candidates to send, we send the candidates response.
-    { STATE_NAME_DECL(send_candidates_response_send),        srpl_send_candidates_response_send_action },
-
-    // This is the quiescent state for servers and clients after session establishment database sync.
-    // Waiting for updates received locally, or updates sent by remote
-    { STATE_NAME_DECL(ready),                                srpl_ready_action },
-    // An update was received locally
-    { STATE_NAME_DECL(srp_client_update_send),               srpl_srp_client_update_send_action },
-    // We've gotten an ack
-    { STATE_NAME_DECL(srp_client_ack_evaluate),              srpl_srp_client_ack_evaluate_action },
-    // See if we have an update from the remote that we stashed because it arrived while we were sending one
-    { STATE_NAME_DECL(stashed_host_check),                   srpl_stashed_host_check_action },
-    // Apply a stashed update (which may have been stashed in the ready state or the client_update_ack_wait state
-    { STATE_NAME_DECL(stashed_host_apply),                   srpl_stashed_host_apply_action },
-    // A stashed update finished; check the results
-    { STATE_NAME_DECL(stashed_host_finished),                srpl_stashed_host_finished_action },
-
-    // Initial startup state for server
-    { STATE_NAME_DECL(session_message_wait),                 srpl_session_message_wait_action },
-    // Send a response once we've figured out that we're going to continue
-    { STATE_NAME_DECL(session_response_send),                srpl_session_response_send },
-    // Wait for a "send candidates" message.
-    { STATE_NAME_DECL(send_candidates_message_wait),         srpl_send_candidates_message_wait_action },
-};
-#define SRPL_NUM_CONNECTION_STATES (sizeof(srpl_connection_states) / sizeof(srpl_connection_state_t))
-
-static srpl_connection_state_t *
-srpl_state_get(srpl_state_t state)
-{
-    static bool once = false;
-    if (!once) {
-        for (unsigned i = 0; i < SRPL_NUM_CONNECTION_STATES; i++) {
-            if (srpl_connection_states[i].state != (srpl_state_t)i) {
-                ERROR("srpl connection state %d doesn't match " PUB_S_SRP, i, srpl_connection_states[i].name);
-                STATE_DEBUGGING_ABORT();
-                return NULL;
-            }
-        }
-        once = true;
-    }
-    if (state < 0 || state > SRPL_NUM_CONNECTION_STATES) {
-        STATE_DEBUGGING_ABORT();
-        return NULL;
-    }
-    return &srpl_connection_states[state];
-}
-
-static void
-srpl_connection_next_state(srpl_connection_t *srpl_connection, srpl_state_t state)
-{
-    srpl_state_t next_state = state;
-
-    do {
-        srpl_connection_state_t *new_state = srpl_state_get(next_state);
-
-        if (new_state == NULL) {
-            ERROR(PRI_S_SRP " next state is invalid: %d", srpl_connection->name, next_state);
-            STATE_DEBUGGING_ABORT();
-            return;
-        }
-        srpl_connection->state = next_state;
-        srpl_connection->state_name = new_state->name;
-        srpl_action_t action = new_state->action;
-        if (action != NULL) {
-            next_state = action(srpl_connection, NULL);
-        }
-    } while (next_state != srpl_state_invalid);
-}
-
-//
-// Event functions
-//
-
-typedef struct {
-    srpl_event_type_t event_type;
-    char *name;
-} srpl_event_configuration_t;
-
-#define EVENT_NAME_DECL(name) { srpl_event_##name, #name }
-
-srpl_event_configuration_t srpl_event_configurations[] = {
-    EVENT_NAME_DECL(invalid),
-    EVENT_NAME_DECL(address_add),
-    EVENT_NAME_DECL(address_remove),
-    EVENT_NAME_DECL(server_disconnect),
-    EVENT_NAME_DECL(reconnect_timer_expiry),
-    EVENT_NAME_DECL(disconnected),
-    EVENT_NAME_DECL(connected),
-    EVENT_NAME_DECL(session_response_received),
-    EVENT_NAME_DECL(send_candidates_response_received),
-    EVENT_NAME_DECL(candidate_received),
-    EVENT_NAME_DECL(host_message_received),
-    EVENT_NAME_DECL(srp_client_update_finished),
-    EVENT_NAME_DECL(advertise_finished),
-    EVENT_NAME_DECL(candidate_response_received),
-    EVENT_NAME_DECL(host_response_received),
-    EVENT_NAME_DECL(session_message_received),
-    EVENT_NAME_DECL(send_candidates_message_received),
-};
-#define SRPL_NUM_EVENT_TYPES (sizeof(srpl_event_configurations) / sizeof(srpl_event_configuration_t))
-
-static srpl_event_configuration_t *
-srpl_event_configuration_get(srpl_event_type_t event)
-{
-    static bool once = false;
-    if (!once) {
-        for (unsigned i = 0; i < SRPL_NUM_EVENT_TYPES; i++) {
-            if (srpl_event_configurations[i].event_type != (srpl_event_type_t)i) {
-                ERROR("srpl connection event %d doesn't match " PUB_S_SRP, i, srpl_event_configurations[i].name);
-                STATE_DEBUGGING_ABORT();
-                return NULL;
-            }
-        }
-        once = true;
-    }
-    if (event < 0 || event > SRPL_NUM_EVENT_TYPES) {
-        STATE_DEBUGGING_ABORT();
-        return NULL;
-    }
-    return &srpl_event_configurations[event];
-}
-
-static const char *
-srpl_state_name(srpl_state_t state)
-{
-    for (unsigned i = 0; i < SRPL_NUM_CONNECTION_STATES; i++) {
-        if (srpl_connection_states[i].state == state) {
-            return srpl_connection_states[i].name;
-        }
-    }
-    return "unknown state";
-}
-
-static void
-srpl_event_initialize(srpl_event_t *event, srpl_event_type_t event_type)
-{
-    memset(event, 0, sizeof(*event));
-    srpl_event_configuration_t *event_config = srpl_event_configuration_get(event_type);
-    if (event_config == NULL) {
-        ERROR("invalid event type %d", event_type);
-        STATE_DEBUGGING_ABORT();
-        return;
-    }
-    event->event_type = event_type;
-    event->name = event_config->name;
-}
-
-static void
-srpl_event_deliver(srpl_connection_t *srpl_connection, srpl_event_t *event)
-{
-    srpl_connection_state_t *state = srpl_state_get(srpl_connection->state);
-    if (state == NULL) {
-        ERROR(PRI_S_SRP ": event " PUB_S_SRP " received in invalid state %d",
-              srpl_connection->name, event->name, srpl_connection->state);
-        STATE_DEBUGGING_ABORT();
-        return;
-    }
-    if (state->action == NULL) {
-        FAULT(PRI_S_SRP": event " PUB_S_SRP " received in state " PUB_S_SRP " with NULL action",
-              srpl_connection->name, event->name, state->name);
-        return;
-    }
-    srpl_state_t next_state = state->action(srpl_connection, event);
-    if (next_state != srpl_state_invalid) {
-        srpl_connection_next_state(srpl_connection, next_state);
-    }
-}
-
-static void
-srpl_re_register(void *context)
-{
-    INFO("re-registering SRPL service");
-    srpl_domain_advertise(context);
-}
-
-static void
-srpl_register_completion(DNSServiceRef UNUSED sdref, DNSServiceFlags UNUSED flags, DNSServiceErrorType error_code,
-                         const char *name, const char *regtype, const char *domain, void *context)
-{
-    srp_server_t *server_state = context;
-
-    if (error_code != kDNSServiceErr_NoError) {
-        ERROR("unable to advertise _srpl-tls._tcp service: %d", error_code);
-        if (server_state->srpl_register_wakeup == NULL) {
-            server_state->srpl_register_wakeup = ioloop_wakeup_create();
-        }
-        if (server_state->srpl_register_wakeup != NULL) {
-            // Try registering again in one second.
-            ioloop_add_wake_event(server_state->srpl_register_wakeup, server_state, srpl_re_register, NULL, 1000);
-        }
-        return;
-    }
-    INFO("registered SRP Replication instance name " PRI_S_SRP "." PUB_S_SRP "." PRI_S_SRP, name, regtype, domain);
-}
-
-static void
-srpl_domain_advertise(srp_server_t *server_state)
-{
-    DNSServiceRef sdref = NULL;
-    TXTRecordRef txt_record;
-    char server_id_buf[INT64_HEX_STRING_MAX];
-
-    TXTRecordCreate(&txt_record, 0, NULL);
-
-    int err = TXTRecordSetValue(&txt_record, "domain", strlen(current_thread_domain_name), current_thread_domain_name);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("unable to set domain in TXT record for _srpl-tls._tcp to " PRI_S_SRP, current_thread_domain_name);
-        goto exit;
-    }
-
-    snprintf(server_id_buf, sizeof(server_id_buf), "%" PRIx64, server_state->server_id);
-    err = TXTRecordSetValue(&txt_record, "server-id", strlen(server_id_buf), server_id_buf);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("unable to set server-id in TXT record for _srpl-tls._tcp to " PUB_S_SRP, server_id_buf);
-        goto exit;
-    }
-
-    // If there is already a registration, get rid of it
-    if (server_state->srpl_advertise_txn != NULL) {
-        ioloop_dnssd_txn_cancel(server_state->srpl_advertise_txn);
-        ioloop_dnssd_txn_release(server_state->srpl_advertise_txn);
-        server_state->srpl_advertise_txn = NULL;
-    }
-
-    err = DNSServiceRegister(&sdref, kDNSServiceFlagsUnique,
-                             kDNSServiceInterfaceIndexAny, NULL, "_srpl-tls._tcp", NULL,
-                             NULL, htons(853), TXTRecordGetLength(&txt_record), TXTRecordGetBytesPtr(&txt_record),
-                             srpl_register_completion, server_state);
-    if (err != kDNSServiceErr_NoError) {
-        ERROR("unable to advertise _srpl-tls._tcp service");
-        goto exit;
-    }
-    server_state->srpl_advertise_txn = ioloop_dnssd_txn_add(sdref, NULL, NULL, NULL);
-    if (server_state->srpl_advertise_txn == NULL) {
-        ERROR("unable to set up a dnssd_txn_t for _srpl-tls._tcp advertisement.");
-        goto exit;
-    }
-    sdref = NULL; // srpl_advertise_txn holds the reference.
-exit:
-    if (sdref != NULL) {
-        DNSServiceRefDeallocate(sdref);
-    }
-    TXTRecordDeallocate(&txt_record);
-    return;
-}
-
-static void
-srpl_thread_network_name_callback(void *NULLABLE context, const char *NULLABLE thread_network_name, cti_status_t status)
-{
-    size_t thread_domain_size;
-    char domain_buf[kDNSServiceMaxDomainName];
-    char *new_thread_domain_name;
-    srp_server_t *server_state = context;
-
-    if (thread_network_name == NULL || status != kCTIStatus_NoError) {
-        ERROR("unable to get thread network name.");
-        return;
-    }
-    thread_domain_size = snprintf(domain_buf, sizeof(domain_buf),
-                                  "%s.%s", thread_network_name, SRP_THREAD_DOMAIN);
-    if (thread_domain_size < 0 || thread_domain_size >= sizeof (domain_buf) ||
-        (new_thread_domain_name = strdup(domain_buf)) == NULL)
-    {
-        ERROR("no memory for new thread network name: " PRI_S_SRP, thread_network_name);
-        return;
-    }
-
-    if (current_thread_domain_name != NULL) {
-        srpl_domain_rename(current_thread_domain_name, new_thread_domain_name);
-    }
-    srpl_domain_add(server_state, new_thread_domain_name);
-    free(current_thread_domain_name);
-    current_thread_domain_name = new_thread_domain_name;
-
-    srpl_domain_advertise(server_state);
-}
-
-void
-srpl_startup(srp_server_t *server_state)
-{
-    server_state->server_id = srp_random64();
-    INFO("server id = %" PRIx64, server_state->server_id);
-    cti_get_thread_network_name(server_state, srpl_thread_network_name_callback, NULL);
-}
-#endif // SRP_FEATURE_REPLICATION
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-replication.h b/ServiceRegistration/srp-replication.h
deleted file mode 100644
index a0b541f..0000000
--- a/ServiceRegistration/srp-replication.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/* srp-replication.h
- *
- * Copyright (c) 2020-2022 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.
- *
- * This file contains structure definitions and external definitions for the SRP Replication code.
- */
-
-#ifndef __SRP_REPLICATION_H__
-#define __SRP_REPLICATION_H__
-
-// States: each state has a function, which bears the name of the state. The function takes an
-//         srpl_connection_t and an srpl_event_t. The function is called once on entering the
-//         state, once on leaving the state, and once whenever an event arrives while in the state.
-//
-//         Whenever this function is called, it returns a next state. If the next state is
-//         "invalid," that means that there is no state change.
-//
-// Events: Events can be triggered by connection activities, e.g. connect, disconnect, add_address, etc.
-//         They can also be triggered by the arrival of messages on connections.
-//         They can also be triggered by happenings on the srp server.
-//         Events are never sent by state actions.
-//         Each event has a single function which sends the event. That function may in some cases force
-//         a state change (e.g., a disconnect event). This is the exception, not the rule. Events are
-//         otherwise handled by the state action function for the current state.
-//
-// In some cases, an event that's expected to be delivered asynchronously arrives synchronously because
-// no asynchronous action was required. In this case, the action that can trigger this synchronous event
-// has to also handle the event. Since the event is normally expected to be delivered asynchronously,
-// the right solution in this case is to queue the event for later delivery.
-//
-// An example of this pattern is in srpl_advertise_finished_event_defer. Because events are normally automatic
-// variables, any event that needs to be deferred has to be allocated and its contents (if any) copied. The
-// srpl_connection_t is stashed on the event; srpl_deferred_event_deliver is then called asynchronously to deliver the
-// event, release the reference to the srpl_connection_t, and free the event data structure.
-
-enum srpl_state {
-    srpl_state_invalid = 0,  // Only as a return value, means do not move to a new state
-
-    // Connection-related states
-    srpl_state_disconnected,
-    srpl_state_next_address_get,
-    srpl_state_connect,
-    srpl_state_idle,
-    srpl_state_reconnect_wait,
-    srpl_state_retry_delay_send,
-    srpl_state_disconnect,
-    srpl_state_disconnect_wait,
-    srpl_state_connecting,
-
-    // Session establishment
-    srpl_state_server_id_send,
-    srpl_state_server_id_response_wait,
-    srpl_state_server_id_evaluate,
-    srpl_state_server_id_regenerate,
-
-    // Requesting and getting remote candidate list
-    srpl_state_send_candidates_send,
-    srpl_state_send_candidates_wait,
-
-    // Waiting for candidate to arrive
-    srpl_state_candidate_check,
-
-    // Waiting for a host to arrive after requesting it
-    srpl_state_candidate_host_wait,
-    srpl_state_candidate_host_prepare,
-    srpl_state_candidate_host_contention_wait,
-    srpl_state_candidate_host_re_evaluate,
-    srpl_state_candidate_host_apply,
-    srpl_state_candidate_host_apply_wait,
-
-    // Getting request for candidate list and sending them.
-    srpl_state_send_candidates_received,
-    srpl_state_send_candidates_remaining_check,
-    srpl_state_next_candidate_send,
-    srpl_state_next_candidate_send_wait,
-    srpl_state_candidate_host_send,
-    srpl_state_candidate_host_response_wait,
-
-    // When we're done sending candidates
-    srpl_state_send_candidates_response_send,
-
-    // Ready states
-    srpl_state_ready,
-    srpl_state_srp_client_update_send,
-    srpl_state_srp_client_ack_evaluate,
-    srpl_state_stashed_host_check,
-    srpl_state_stashed_host_apply,
-    srpl_state_stashed_host_finished,
-
-    // States for connections received by this server
-    srpl_state_session_message_wait,
-    srpl_state_session_response_send,
-    srpl_state_send_candidates_message_wait,
-};
-
-enum srpl_event_type {
-    srpl_event_invalid = 0,
-    srpl_event_address_add,
-    srpl_event_address_remove,
-    srpl_event_server_disconnect,
-    srpl_event_reconnect_timer_expiry,
-    srpl_event_disconnected,
-    srpl_event_connected,
-    srpl_event_session_response_received,
-    srpl_event_send_candidates_response_received,
-    srpl_event_candidate_received,
-    srpl_event_host_message_received,
-    srpl_event_srp_client_update_finished,
-    srpl_event_advertise_finished,
-    srpl_event_candidate_response_received,
-    srpl_event_host_response_received,
-    srpl_event_session_message_received,
-    srpl_event_send_candidates_message_received,
-};
-enum srpl_candidate_disposition { srpl_candidate_yes, srpl_candidate_no, srpl_candidate_conflict };
-
-typedef struct srpl_connection srpl_connection_t;
-typedef struct srpl_instance srpl_instance_t;
-typedef struct srpl_domain srpl_domain_t;
-typedef struct address_query address_query_t;
-typedef struct unclaimed_connection unclaimed_connection_t;
-typedef enum srpl_state srpl_state_t;
-typedef enum srpl_event_type srpl_event_type_t;
-typedef struct srpl_event srpl_event_t;
-typedef struct srpl_candidate srpl_candidate_t;
-typedef enum srpl_candidate_disposition srpl_candidate_disposition_t;
-typedef struct srpl_srp_client_queue_entry srpl_srp_client_queue_entry_t;
-typedef struct srpl_srp_client_update_result srpl_srp_client_update_result_t;
-typedef struct srpl_host_update srpl_host_update_t;
-typedef struct srpl_advertise_finished_result srpl_advertise_finished_result_t;
-
-typedef void (*address_change_callback_t)(void *NULLABLE context, addr_t *NULLABLE address, bool added, int err);
-typedef void (*address_query_cancel_callback_t)(void *NULLABLE context);
-typedef enum {
-    address_query_next_address_gotten, // success
-    address_query_next_address_empty,  // no addresses at all
-    address_query_cycle_complete       // all addresses have been tried
-} address_query_result_t;
-
-#define ADDRESS_QUERY_MAX_ADDRESSES 20
-struct address_query {
-    int ref_count;
-    dnssd_txn_t *NULLABLE aaaa_query, *NULLABLE a_query;
-    addr_t addresses[ADDRESS_QUERY_MAX_ADDRESSES]; // If there are more than this many viable addresses, too bad?
-    uint32_t address_interface[ADDRESS_QUERY_MAX_ADDRESSES];
-    int num_addresses, cur_address;
-    address_change_callback_t NULLABLE change_callback;
-    address_query_cancel_callback_t NULLABLE cancel_callback;
-    void *NULLABLE context;
-    char *NONNULL hostname;
-};
-
-struct srpl_candidate {
-    dns_label_t *NULLABLE name;
-    uint32_t key_id;                 // key id from adv_host_t
-    uint32_t update_offset;          // Offset in seconds before the time candidate message was sent that update was received.
-    time_t update_time;              // the time of registration received from remote
-    time_t local_time;               // our time of registration when we fetched the host
-    message_t *NULLABLE message;     // The SRP message.
-    adv_host_t *NULLABLE host;       // the host, when it's been fetched
-};
-
-struct srpl_advertise_finished_result {
-    char *NULLABLE hostname;
-    srp_server_t *NULLABLE server_state;
-    int rcode;
-};
-
-typedef enum {
-    srpl_event_content_type_none = 0,
-    srpl_event_content_type_address,
-    srpl_event_content_type_server_id,
-    srpl_event_content_type_candidate,
-    srpl_event_content_type_rcode,
-    srpl_event_content_type_candidate_disposition,
-    srpl_event_content_type_host_update,
-    srpl_event_content_type_client_result,
-    srpl_event_content_type_advertise_finished_result,
-} srpl_event_content_type_t;
-
-typedef srpl_state_t (*srpl_action_t)(srpl_connection_t *NONNULL connection, srpl_event_t *NULLABLE event);
-
-struct srpl_srp_client_update_result {
-    adv_host_t *NONNULL host;
-    int rcode;
-};
-
-struct srpl_host_update {
-    message_t *NULLABLE message;
-    uint64_t server_stable_id;
-    uint32_t update_offset;
-    time_t update_time;
-    dns_name_t *NULLABLE hostname;
-    int rcode;
-};
-
-struct srpl_event {
-    char *NONNULL name;
-    srpl_event_content_type_t content_type;
-    union {
-        addr_t address;
-        uint64_t server_id;
-        srpl_srp_client_update_result_t client_result;
-        srpl_candidate_t *NULLABLE candidate;
-        int rcode;
-        srpl_candidate_disposition_t disposition;
-        srpl_host_update_t host_update;
-        srpl_advertise_finished_result_t advertise_finished;
-    } content;
-    message_t *NULLABLE message;
-    srpl_event_type_t event_type;
-    srpl_connection_t *NULLABLE srpl_connection; // if the event's been deferred, otherwise ALWAYS NULL.
-};
-
-struct srpl_srp_client_queue_entry {
-    srpl_srp_client_queue_entry_t *NULLABLE next;
-    adv_host_t *NONNULL host;
-    bool sent;
-};
-
-struct srpl_connection {
-    int ref_count;
-    uint64_t remote_server_id;
-    char *NONNULL name;
-    char *NONNULL state_name;
-    comm_t *NULLABLE connection;
-    addr_t connected_address;
-    srpl_candidate_t *NULLABLE candidate;
-    dso_state_t *NULLABLE dso;
-    srpl_instance_t *NULLABLE instance;
-    wakeup_t *NULLABLE reconnect_wakeup;
-    message_t *NULLABLE message;
-    adv_host_t *NULLABLE *NULLABLE candidates;
-    srpl_host_update_t stashed_host;
-    srpl_srp_client_queue_entry_t *NULLABLE client_update_queue;
-    int num_candidates;
-    int current_candidate;
-    int retry_delay; // How long to send when we send a retry_delay message
-    srpl_state_t state, next_state;
-    bool is_server;
-    bool database_synchronized;
-    bool candidates_not_generated; // If this is true, we haven't generated a candidates list yet.
-};
-
-struct srpl_instance {
-    int ref_count;
-    dnssd_txn_t *NULLABLE resolve_txn;
-    srpl_instance_t *NULLABLE next;
-    srpl_domain_t *NONNULL domain;
-    char *NULLABLE name;
-    char *NULLABLE instance_name;
-    srpl_connection_t *NULLABLE incoming, *NULLABLE outgoing;
-    address_query_t *NULLABLE address_query;
-    wakeup_t *NULLABLE discontinue_timeout;
-    wakeup_t *NULLABLE reconnect_timeout;
-    uint64_t server_id;
-    uint16_t outgoing_port;
-    int num_copies;     // Tracks adds and deletes from the DNSServiceBrowse for this instance.
-    bool discontinuing; // True if we are in the process of discontinuing this instance.
-    bool is_me;
-    bool have_server_id;
-};
-
-struct srpl_domain {
-    int ref_count;
-    srpl_domain_t *NULLABLE next;
-    char *NONNULL name;
-    srpl_instance_t *NULLABLE instances;
-    dnssd_txn_t *NULLABLE query;
-    srp_server_t *NULLABLE server_state;
-};
-
-struct unclaimed_connection {
-    int ref_count;
-    unclaimed_connection_t *NULLABLE next;
-    wakeup_t *NULLABLE wakeup_timeout;
-    dso_state_t *NULLABLE dso;
-    message_t *NULLABLE message;
-    comm_t *NULLABLE connection;
-    srp_server_t *NULLABLE server_state;
-    addr_t address;
-};
-
-#define SRP_THREAD_DOMAIN "thread.home.arpa."
-
-#define DSO_TLV_HEADER_SIZE 4 // opcode (u16) + length (u16)
-#define DSO_MESSAGE_MIN_LENGTH DNS_HEADER_SIZE + DSO_TLV_HEADER_SIZE + 1
-
-
-#define SRPL_RETRY_DELAY_LENGTH        DSO_MESSAGE_MIN_LENGTH + sizeof(uint32_t)
-#define SRPL_SESSION_MESSAGE_LENGTH    DSO_MESSAGE_MIN_LENGTH + sizeof(uint64_t) // DSO header + 8 byte session ID
-#define SRPL_SEND_CANDIDATES_LENGTH    DSO_MESSAGE_MIN_LENGTH
-#define SRPL_CANDIDATE_MESSAGE_LENGTH  (DSO_MESSAGE_MIN_LENGTH + \
-                                        DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \
-                                        sizeof(uint32_t) + DSO_TLV_HEADER_SIZE + \
-                                        sizeof(uint32_t) + DSO_TLV_HEADER_SIZE)
-#define SRPL_CANDIDATE_RESPONSE_LENGTH DSO_MESSAGE_MIN_LENGTH + DSO_TLV_HEADER_SIZE
-#define SRPL_HOST_MESSAGE_LENGTH  (DSO_MESSAGE_MIN_LENGTH + \
-                                   DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \
-                                   sizeof(uint32_t) + DSO_TLV_HEADER_SIZE + \
-                                   sizeof(uint32_t) + DSO_TLV_HEADER_SIZE)
-#define SRPL_HOST_RESPONSE_LENGTH      DSO_MESSAGE_MIN_LENGTH
-
-#define SRPL_UPDATE_JITTER_WINDOW 10
-
-// Exported functions...
-time_t srpl_time(void);
-void srpl_startup(srp_server_t *NONNULL srp_server);
-void srpl_disable(srp_server_t *NONNULL srp_server);
-void srpl_drop_srpl_connection(srp_server_t *NONNULL srp_server);
-void srpl_undrop_srpl_connection(srp_server_t *NONNULL srp_server);
-void srpl_drop_srpl_advertisement(srp_server_t *NONNULL srp_server);
-void srpl_undrop_srpl_advertisement(srp_server_t *NONNULL srp_server);
-void srpl_dso_server_message(comm_t *NONNULL connection, message_t *NULLABLE message, dso_state_t *NONNULL dso,
-                             srp_server_t *NONNULL server_state);
-void srpl_advertise_finished_event_send(char *NONNULL host, int rcode, srp_server_t *NONNULL server_state);
-void srpl_srp_client_update_finished_event_send(adv_host_t *NONNULL host, int rcode);
-#define srpl_connection_release(connection) srpl_connection_release_(connection, __FILE__, __LINE__)
-void srpl_connection_release_(srpl_connection_t *NONNULL srpl_connection, const char *NONNULL file, int line);
-#define srpl_connection_retain(connection) srpl_connection_retain_(connection, __FILE__, __LINE__)
-void srpl_connection_retain_(srpl_connection_t *NONNULL srpl_connection, const char *NONNULL file, int line);
-#endif // __SRP_REPLICATION_H__
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 120
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-thread.c b/ServiceRegistration/srp-thread.c
deleted file mode 100644
index 784057b..0000000
--- a/ServiceRegistration/srp-thread.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/* srp-thread.c
- *
- * Copyright (c) 2019-2020 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.
- *
- * srp host API implementation for Thread accessories using OpenThread.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include <openthread/ip6.h>
-#include <openthread/instance.h>
-#include <openthread/thread.h>
-#include <openthread/joiner.h>
-#include <openthread/message.h>
-#include <openthread/udp.h>
-#include <openthread/platform/time.h>
-#include <openthread/platform/settings.h>
-
-
-#include "app_scheduler.h"
-#include "app_timer.h"
-#include "srp.h"
-#include "srp-thread.h"
-#include "srp-api.h"
-#include "dns_sd.h"
-#include "HAPPlatformRandomNumber.h"
-#include "dns-msg.h"
-#include "dns_sd.h"
-#include "srp-crypto.h"
-
-APP_TIMER_DEF(m_srp_timer);
-#define HAPTIME_FREQUENCY 1000ULL
-
-const char *key_filename = "srp.key";
-
-#define SRP_IO_CONTEXT_MAGIC 0xFEEDFACEFADEBEEFULL  // BEES!   Everybody gets BEES!
-typedef struct io_context io_context_t;
-
-struct io_context {
-    uint64_t magic_cookie1;
-    io_context_t *next;
-    HAPTime wakeup_time;
-    void *NONNULL srp_context;
-    otSockAddr sockaddr;
-    otUdpSocket sock;
-    srp_wakeup_callback_t wakeup_callback;
-    srp_datagram_callback_t datagram_callback;
-    bool sock_active;
-    uint64_t magic_cookie2;
-} *io_contexts;
-
-static otInstance *otThreadInstance;
-
-static int
-validate_io_context(io_context_t **dest, void *src)
-{
-    io_context_t *context = src;
-    if (context->magic_cookie1 == SRP_IO_CONTEXT_MAGIC &&
-        context->magic_cookie2 == SRP_IO_CONTEXT_MAGIC)
-    {
-        *dest = context;
-        return kDNSServiceErr_NoError;
-    }
-    return kDNSServiceErr_BadState;
-}
-
-void
-datagram_callback(void *context, otMessage *message, const otMessageInfo *messageInfo)
-{
-    static uint8_t *buf;
-    const int buf_len = 1500;
-    int length;
-    io_context_t *io_context;
-    if (validate_io_context(&io_context, context) == kDNSServiceErr_NoError) {
-        if (buf == NULL) {
-            buf = malloc(buf_len);
-            if (buf == NULL) {
-                INFO("No memory for read buffer");
-                return;
-            }
-        }
-
-        DEBUG("%d bytes received", otMessageGetLength(message) - otMessageGetOffset(message));
-        length = otMessageRead(message, otMessageGetOffset(message), buf, buf_len - 1);
-        io_context->datagram_callback(io_context->srp_context, buf, length);
-    }
-}
-
-static void wakeup_callback(void *context);
-
-static void
-note_wakeup(const char *what, void *at, uint64_t when)
-{
-#ifdef VERBOSE_DEBUG_MESSAGES
-    int microseconds = (int)(when % HAPTIME_FREQUENCY);
-    HAPTime seconds = when / HAPTIME_FREQUENCY;
-    int minute = (int)((seconds / 60) % 60);
-    int hour = (int)((seconds / 3600) % (7 * 24));
-    int second = (int)(seconds % 60);
-
-    DEBUG(PUB_S_SRP " %p at %llu %d:%d:%d.%d", what, at, when, hour, minute, second, microseconds);
-#endif
-}
-
-static void
-compute_wakeup_time(HAPTime now)
-{
-    io_context_t *io_context;
-    HAPTime next = 0;
-    uint32_t err;
-
-    for (io_context = io_contexts; io_context; io_context = io_context->next) {
-        if (next == 0 || (io_context->wakeup_time != 0 && io_context->wakeup_time < next)) {
-            next = io_context->wakeup_time;
-        }
-    }
-
-    // If we don't have a wakeup to schedule, wake up anyway in ten seconds.
-    if (next == 0) {
-        next = now + 10 * HAPTIME_FREQUENCY;
-    }
-    note_wakeup("next wakeup", NULL, next);
-    if (next != 0) {
-        int milliseconds;
-        if (next <= now) {
-            milliseconds = 1;
-        } else {
-            milliseconds = (int)((next - now) / (HAPTIME_FREQUENCY / 1000));
-        }
-        err = app_timer_start(m_srp_timer, APP_TIMER_TICKS(milliseconds), NULL);
-        if (err != 0) {
-            ERROR("app_timer_start returned %lu", err);
-        }
-    }
-}
-
-static void
-wakeup_callback(void *context)
-{
-    io_context_t *io_context;
-    HAPTime now = HAPPlatformClockGetCurrent(), next = 0;
-    bool more;
-
-    note_wakeup("     wakeup", NULL, now);
-    do {
-        more = false;
-        for (io_context = io_contexts; io_context; io_context = io_context->next) {
-            if (io_context->wakeup_time != 0 && io_context->wakeup_time < now) {
-                more = true;
-                note_wakeup("io wakeup", io_context, io_context->wakeup_time);
-                io_context->wakeup_time = 0;
-                io_context->wakeup_callback(io_context->srp_context);
-                break;
-            }
-            note_wakeup("no wakeup", io_context, io_context->wakeup_time);
-            if (next == 0 || (io_context->wakeup_time != 0 && io_context->wakeup_time < next))
-            {
-                next = io_context->wakeup_time;
-            }
-        }
-    } while (more);
-    compute_wakeup_time(now);
-}
-
-int
-srp_deactivate_udp_context(void *host_context, void *in_context)
-{
-    io_context_t *io_context, **p_io_contexts;
-    int err;
-
-    err = validate_io_context(&io_context, in_context);
-    if (err == kDNSServiceErr_NoError) {
-        for (p_io_contexts = &io_contexts; *p_io_contexts; p_io_contexts = &(*p_io_contexts)->next) {
-            if (*p_io_contexts == io_context) {
-                break;
-            }
-        }
-        // If we don't find it on the list, something is wrong.
-        if (*p_io_contexts == NULL) {
-            return kDNSServiceErr_Invalid;
-        }
-        *p_io_contexts = io_context->next;
-        io_context->wakeup_time = 0;
-        if (io_context->sock_active) {
-            otUdpClose(&io_context->sock);
-        }
-        free(io_context);
-    }
-    return err;
-}
-
-int
-srp_connect_udp(void *context, const uint8_t *port, uint16_t address_type, const uint8_t *address, uint16_t addrlen)
-{
-    io_context_t *io_context;
-    int err, oterr;
-
-    err = validate_io_context(&io_context, context);
-
-    if (err == kDNSServiceErr_NoError) {
-        if (address_type != dns_rrtype_aaaa || addrlen != 16) {
-            ERROR("srp_make_udp_context: invalid address");
-            return kDNSServiceErr_Invalid;
-        }
-        memcpy(&io_context->sockaddr.mAddress, address, 16);
-        memcpy(&io_context->sockaddr.mPort, port, 2);
-#ifdef OT_NETIF_INTERFACE_ID_THREAD
-        io_context->sockaddr.mScopeId = OT_NETIF_INTERFACE_ID_THREAD;
-#endif
-
-        oterr = otUdpOpen(otThreadInstance, &io_context->sock, datagram_callback, io_context);
-        if (oterr != OT_ERROR_NONE) {
-            ERROR("srp_make_udp_context: otUdpOpen returned %d", oterr);
-            return kDNSServiceErr_Unknown;
-        }
-
-        oterr = otUdpConnect(&io_context->sock, &io_context->sockaddr);
-        if (oterr != OT_ERROR_NONE) {
-            otUdpClose(&io_context->sock);
-            ERROR("srp_make_udp_context: otUdpConnect returned %d", oterr);
-            return kDNSServiceErr_Unknown;
-        }
-        io_context->sock_active = true;
-        err = kDNSServiceErr_NoError;
-    }
-    return err;
-}
-
-int
-srp_disconnect_udp(void *context)
-{
-    io_context_t *io_context;
-    int err;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError && io_context->sock_active) {
-        otUdpClose(&io_context->sock);
-        io_context->sock_active = false;
-    }
-    return err;
-}
-
-int
-srp_make_udp_context(void *host_context, void **p_context, srp_datagram_callback_t callback, void *context)
-{
-    io_context_t *io_context = calloc(1, sizeof *io_context);
-    if (io_context == NULL) {
-        ERROR("srp_make_udp_context: no memory");
-        return kDNSServiceErr_NoMemory;
-    }
-    io_context->magic_cookie1 = io_context->magic_cookie2 = SRP_IO_CONTEXT_MAGIC;
-    io_context->datagram_callback = callback;
-    io_context->srp_context = context;
-
-    *p_context = io_context;
-    io_context->next = io_contexts;
-    io_contexts = io_context;
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_set_wakeup(void *host_context, void *context, int milliseconds, srp_wakeup_callback_t callback)
-{
-    int err;
-    io_context_t *io_context;
-    HAPTime now;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        now = HAPPlatformClockGetCurrent();
-        io_context->wakeup_time = now + milliseconds * (HAPTIME_FREQUENCY / 1000);
-        io_context->wakeup_callback = callback;
-        INFO("%llu (%llu + %dms)", io_context->wakeup_time, now, milliseconds);
-        compute_wakeup_time(now);
-    }
-    return err;
-}
-
-int
-srp_cancel_wakeup(void *host_context, void *context)
-{
-    int err;
-    io_context_t *io_context;
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        io_context->wakeup_time = 0;
-    }
-    return err;
-}
-
-int
-srp_send_datagram(void *host_context, void *context, void *payload, size_t message_length)
-{
-    int err;
-    io_context_t *io_context;
-    otError       error;
-    otMessageInfo messageInfo;
-    otMessage *   message = NULL;
-    uint8_t *ap;
-
-#ifdef VERBOSE_DEBUG_MESSAGES
-    int i, j;
-    char buf[80], *bufp;
-    char *hexdigits = "01234567689abcdef";
-    uint8_t *msg = payload;
-#endif // VERBOSE_DEBUG_MESSAGES
-
-    err = validate_io_context(&io_context, context);
-    if (err == kDNSServiceErr_NoError) {
-        memset(&messageInfo, 0, sizeof(messageInfo));
-#ifdef OT_NETIF_INTERFACE_ID_THREAD
-        messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD;
-#endif
-        messageInfo.mPeerPort    = io_context->sockaddr.mPort;
-        messageInfo.mPeerAddr    = io_context->sockaddr.mAddress;
-        ap = (uint8_t *)&io_context->sockaddr.mAddress;
-        SEGMENTED_IPv6_ADDR_GEN_SRP(ap, ap_buf);
-        INFO("Sending to " PRI_SEGMENTED_IPv6_ADDR_SRP " port %d", SEGMENTED_IPv6_ADDR_PARAM_SRP(ap, ap_buf),
-             io_context->sockaddr.mPort);
-#ifdef VERBOSE_DEBUG_MESSAGES
-        for (i = 0; i < message_length; i += 32) {
-            bufp = buf;
-            for (j = 0; bufp < buf + sizeof buf && i + j < message_length; j++) {
-                *bufp++ = hexdigits[msg[i + j] >> 4];
-                if (bufp < buf + sizeof buf) {
-                    *bufp++ = hexdigits[msg[i + j] % 15];
-                }
-                if (bufp < buf + sizeof buf && (j & 1) == 1) {
-                    *bufp++ = ' ';
-                }
-            }
-            *bufp = 0;
-            DEBUG(PUB_S_SRP, buf);
-        }
-#endif
-
-        message = otUdpNewMessage(otThreadInstance, NULL);
-        if (message == NULL) {
-            ERROR("srp_send_datagram: otUdpNewMessage returned NULL");
-            return kDNSServiceErr_NoMemory;
-        }
-
-        error = otMessageAppend(message, payload, message_length);
-        if (error != OT_ERROR_NONE) {
-            ERROR("srp_send_datagram: otMessageAppend returned %d", error);
-            return kDNSServiceErr_NoMemory;
-        }
-
-        error = otUdpSend(&io_context->sock, message, &messageInfo);
-        if (error != OT_ERROR_NONE) {
-            ERROR("srp_send_datagram: otUdpSend returned %d", error);
-            return kDNSServiceErr_Unknown;
-        }
-    }
-    return err;
-}
-
-#define KEY_ID 1000
-int
-srp_load_key_data(void *host_context, const char *key_name,
-                  uint8_t *buffer, uint16_t *length, uint16_t buffer_size)
-{
-#ifndef DEBUG_CONFLICTS
-    otError err;
-    uint16_t rlength = buffer_size;
-    // Note that at present we ignore the key name: we are only going to have one host key on an
-    // accessory.
-    err = otPlatSettingsGet(otThreadInstance, KEY_ID, 0, buffer, &rlength);
-    if (err != OT_ERROR_NONE) {
-        *length = 0;
-        return kDNSServiceErr_NoSuchKey;
-    }
-    *length = rlength;
-    return kDNSServiceErr_NoError;
-#else
-        return kDNSServiceErr_NoSuchKey;
-#endif
-}
-
-int
-srp_store_key_data(void *host_context, const char *name, uint8_t *buffer, uint16_t length)
-{
-    otError err;
-    err = otPlatSettingsAdd(otThreadInstance, KEY_ID, buffer, length);
-    if (err != OT_ERROR_NONE) {
-        ERROR("Unable to store key (length %d): %d", length, err);
-        return kDNSServiceErr_Unknown;
-    }
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_reset_key(const char *name, void *host_context)
-{
-    otPlatSettingsDelete(otThreadInstance, KEY_ID);
-}
-
-void
-register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
-                  const char *name, const char *regtype, const char *domain, void *context)
-{
-    INFO("Register Reply: %ld " PRI_S_SRP " " PRI_S_SRP " " PRI_S_SRP "\n", errorCode, name == NULL ? "<NULL>" : name,
-         regtype == NULL ? "<NULL>" : regtype, domain == NULL ? "<NULL>" : domain);
-}
-
-void
-conflict_callback(const char *hostname)
-{
-    ERROR("Host name conflict: %s", hostname);
-}
-
-int
-srp_thread_init(otInstance *instance)
-{
-    uint32_t app_err;
-    DEBUG("In srp_thread_init().");
-    otThreadInstance = instance;
-    srp_host_init(otThreadInstance);
-
-    app_err = app_timer_create(&m_srp_timer, APP_TIMER_MODE_SINGLE_SHOT, wakeup_callback);
-    if (app_err != 0) {
-        ERROR("app_timer_create returned %lu", app_err);
-        return kDNSServiceErr_Unknown;
-    }
-    return kDNSServiceErr_NoError;
-}
-
-int
-srp_thread_shutdown(otInstance *instance)
-{
-    INFO("In srp_thread_shutdown().");
-    uint32_t app_err;
-    app_err = app_timer_stop(m_srp_timer);
-    if (app_err != 0) {
-        ERROR("app_timer_stop returned %lu", app_err);
-        return kDNSServiceErr_Unknown;
-    }
-    return kDNSServiceErr_NoError;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-thread.h b/ServiceRegistration/srp-thread.h
deleted file mode 100644
index 7c898df..0000000
--- a/ServiceRegistration/srp-thread.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* srp-thread.c
- *
- * Copyright (c) 2019-2020 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.
- *
- * srp host API implementation for Posix using ioloop primitives.
- */
-
-#include <openthread/ip6.h>
-
-int srp_thread_init(otInstance* instance);
-int srp_thread_shutdown(otInstance* instance);
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp-tls.h b/ServiceRegistration/srp-tls.h
deleted file mode 100644
index 7c12470..0000000
--- a/ServiceRegistration/srp-tls.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* srp-tls.h
- *
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- *
- * TLS Shim definitions.   These entry points should in principle work for any TLS
- * library, with the addition of a single shim file, for example tls-mbedtls.c.
- */
-
-#ifndef __SRP_TLS_H
-#define __SRP_TLS_H
-// Anonymous key structure, depends on the target.
-typedef struct srp_key srp_key_t;
-
-#ifdef SRP_CRYPTO_MBEDTLS_INTERNAL
-#include <mbedtls/certs.h>
-#include <mbedtls/x509.h>
-#include <mbedtls/ssl.h>
-
-struct tls_context {
-    struct mbedtls_ssl_context context;
-    enum { handshake_in_progress, handshake_complete } state;
-};
-#endif // SRP_CRYPTO_MBEDTLS_INTERNAL
-#ifdef SRP_CRYPTO_MACOS
-#include "tls-macos.h"
-#endif
-
-// tls_*.c:
-bool srp_tls_init(void);
-bool srp_tls_client_init(void);
-bool srp_tls_server_init(const char *NULLABLE cacert_file,
-			 const char *NULLABLE srvcrt_file, const char *NULLABLE server_key_file);
-bool srp_tls_accept_setup(comm_t *NONNULL comm);
-bool srp_tls_listen_callback(comm_t *NONNULL comm);
-bool srp_tls_connect_callback(comm_t *NONNULL comm);
-ssize_t srp_tls_read(comm_t *NONNULL comm, unsigned char *NONNULL buf, size_t max);
-void srp_tls_context_free(comm_t *NONNULL comm);
-ssize_t srp_tls_write(comm_t *NONNULL comm, struct iovec *NONNULL iov, int iov_len);
-
-/*!
- *  @brief
- *      Configure TLS with the identity.
- *
- *  @param context
- *      Context passed to this function to let it finish the configuration process.
- *
- *  @discussion
- *      This function can only be called after srp_tls_init() is called to fetch the necessary identity.
- *
- */
-void
-srp_tls_configure(void *NULLABLE context);
-
-/*!
- *  @brief
- *      Gets the remaining valid time for the TLS certificate that is initialized by <code>srp_tls_init()</code>.
- *
- *  @result
- *      The remaining time valid time before TLS certificate expires.
- *
- *  @discussion
- *      <code>srp_tls_init()</code> has to be called to initialize the TLS certificate before calling this function.
- */
-uint32_t
-srp_tls_get_next_rotation_time(void);
-
-/*!
- *  @brief
- *      Destroy the TLS certificate that is initialized by <code>srp_tls_init()</code>.
- *
- *  @discussion
- *      <code>srp_tls_init()</code> has to be called to initialize the TLS certificate before calling this function.
- */
-void
-srp_tls_dispose(void);
-
-/*!
- *  @brief
- *      Schedule a wake up event so that the TLS certificate that is expiring
- *      soon can be replaced with a newer one.
- *
- *  @param tls_listener_wakeup
- *      The pointer to the tls_listener_wakeup context that can be used to
- *      schedule a wakeup event.
- *
- *  @param tls_listener_to_rotate
- *      The TLS listener object created before that needs to be rotated.
- *
- *  @discussion
- *      The TLS rotation time is controlled by
- *      <code>TLS_CERTIFICATE_VALID_PERIOD_SECS</code>.
- */
-void
-schedule_tls_certificate_rotation(wakeup_t * NULLABLE * NONNULL tls_listener_wakeup,
-	comm_t * NONNULL tls_listener_to_rotate);
-
-#endif // __SRP_TLS_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/srp.h b/ServiceRegistration/srp.h
deleted file mode 100644
index c769848..0000000
--- a/ServiceRegistration/srp.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/* srp.h
- *
- * Copyright (c) 2018 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.
- *
- * Service Registration Protocol common definitions
- */
-
-#ifndef __SRP_H
-#define __SRP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include <stdbool.h>
-#ifdef POSIX_BUILD
-#include <limits.h>
-#include <sys/param.h>
-#endif
-#ifdef MALLOC_DEBUG_LOGGING
-#  define MDNS_NO_STRICT 1
-#endif
-
-#include "srp-features.h"           // for feature flags
-
-#ifdef __clang__
-#define NULLABLE _Nullable
-#define NONNULL _Nonnull
-#define UNUSED __unused
-#else
-#define NULLABLE
-#define NONNULL
-#define UNUSED __attribute__((unused))
-#ifdef POSIX_BUILD
-#else
-#define SRP_CRYPTO_MBEDTLS 1
-#endif // POSIX_BUILD
-#endif
-
-#define INT64_HEX_STRING_MAX 17     // Maximum size of an int64_t printed as hex, including NUL termination
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#endif
-//======================================================================================================================
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
-#include "srp-log.h"                // For log functions
-
-#ifdef DEBUG_VERBOSE
-#ifdef __clang__
-#define FILE_TRIM(x) (strrchr(x, '/') + 1)
-#else
-#define FILE_TRIM(x) (x)
-#endif
-
-#ifdef __clang_analyzer__
-#define RELEASE_BASE(x, finalize, file, line) \
-    finalize(x)
-#else
-#define RELEASE_BASE(x, finalize, file, line)                                 \
-    do {                                                                      \
-        if ((x)->ref_count == 0) {                                            \
-            FAULT("ALLOC: release after finalize at %2.2d: %p (%10s): %s:%d", \
-                  (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line);   \
-        } else {                                                              \
-            INFO("ALLOC: release at %2.2d: %p (%10s): %s:%d",                 \
-                 (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line);    \
-            --(x)->ref_count;                                                 \
-            if ((x)->ref_count == 0) {                                        \
-                INFO("ALLOC:      finalize: %p (%10s): %s:%d",                \
-                     (void *)(x), # x, FILE_TRIM(file), line);                \
-                finalize(x);                                                  \
-            }                                                                 \
-        }                                                                     \
-    } while (0)
-#endif // __clang_analyzer__
-#define RETAIN_BASE(x, file, line)                                            \
-    do {                                                                      \
-        INFO("ALLOC:  retain at %2.2d: %p (%10s): %s:%d",                     \
-             (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line);        \
-        ++(x)->ref_count;                                                     \
-    } while (0)
-#define RELEASE(x, finalize) RELEASE_BASE(x, finalize, file, line)
-#define RETAIN(x) RETAIN_BASE(x, file, line)
-#define RELEASE_HERE(x, finalize) RELEASE_BASE(x, finalize, __FILE__, __LINE__)
-#define RETAIN_HERE(x) RETAIN_BASE(x, __FILE__, __LINE__)
-#else
-#ifdef __clang_analyzer__
-#define RELEASE(x, finalize) finalize(x)
-#define RELEASE_HERE(x, finalize) finalize(x)
-#define RETAIN(x)
-#define RETAIN_HERE(x)
-#else
-#define RELEASE(x, finalize) do {    \
-        if (--(x)->ref_count == 0) { \
-            finalize(x);             \
-            (void)file; (void)line;  \
-        }                            \
-    } while (0)
-#define RETAIN(x) do {          \
-        (x)->ref_count++;       \
-        (void)file; (void)line; \
-    } while (0)
-#define RELEASE_HERE(x, finalize) do {    \
-        if (--(x)->ref_count == 0) {      \
-            finalize(x);                  \
-        }                                 \
-    } while (0)
-#define RETAIN_HERE(x) ((x)->ref_count++)
-#endif
-#endif // DEBUG_VERBOSE
-
-#define THREAD_ENTERPRISE_NUMBER ((uint64_t)44970)
-#define THREAD_SRP_SERVER_OPTION 0x5d
-#define THREAD_PREF_ID_OPTION    0x9d
-
-#define IS_SRP_SERVICE(service) \
-    ((cti_service)->enterprise_number == THREAD_ENTERPRISE_NUMBER &&    \
-     (cti_service)->service_type == THREAD_SRP_SERVER_OPTION &&         \
-     (cti_service)->service_version == 1 &&                             \
-     (cti_service)->server_length == 18)
-#define IS_PREF_ID_SERVICE(service) \
-    ((cti_service)->enterprise_number == THREAD_ENTERPRISE_NUMBER &&    \
-     (cti_service)->service_type == THREAD_PREF_ID_OPTION &&            \
-     (cti_service)->service_version == 1 &&                             \
-     (cti_service)->server_length == 9)
-
-#ifdef MALLOC_DEBUG_LOGGING
-void *debug_malloc(size_t len, const char *file, int line);
-void *debug_calloc(size_t count, size_t len, const char *file, int line);
-char *debug_strdup(const char *s, const char *file, int line);
-void debug_free(void *p, const char *file, int line);
-
-#define malloc(x) debug_malloc(x, __FILE__, __LINE__)
-#define calloc(c, y) debug_calloc(c, y, __FILE__, __LINE__)
-#define strdup(s) debug_strdup(s, __FILE__, __LINE__)
-#define free(p) debug_free(p, __FILE__, __LINE__)
-#endif
-
-typedef struct srp_key srp_key_t;
-
-/*!
- *  @brief
- *      Check the required condition, if the required condition is not met go to the label specified.
- *
- *  @param ASSERTION
- *      The condition that must be met before continue.
- *
- *  @param EXCEPTION_LABEL
- *      The label to go to when the required condition ASSERTION is not met.
- *
- *  @param ACTION
- *      The extra action to take before go to the EXCEPTION_LABEL label when ASSERTION is not met.
- *
- *  @discussion
- *      Example:
- *      require_action_quiet(
- *          foo == NULL, // required to be true
- *          exit, // if not met goto label
- *          ret = -1;  ERROR("foo should not be NULL") // before exiting
- *      ) ;
- */
-#ifndef require_action_quiet
-    #define require_action_quiet(ASSERTION, EXCEPTION_LABEL, ACTION)    \
-        do {                                                            \
-            if (__builtin_expect(!(ASSERTION), 0))                      \
-            {                                                           \
-                {                                                       \
-                    ACTION;                                             \
-                }                                                       \
-                goto EXCEPTION_LABEL;                                   \
-            }                                                           \
-        } while(0)
-#endif // #ifndef require_action
-
-#ifndef require_quiet
-    #define require_quiet(ASSERTION, EXCEPTION_LABEL)                   \
-        do {                                                            \
-            if (__builtin_expect(!(ASSERTION), 0))                      \
-            {                                                           \
-                goto EXCEPTION_LABEL;                                   \
-            }                                                           \
-        } while(0)
-#endif // #ifndef require_action
-
-/*!
- *  @brief
- *      Check the required condition, if the required condition is not met go to the label specified.
- *
- *  @param ASSERTION
- *      The condition that must be met before continue.
- *
- *  @param EXCEPTION_LABEL
- *      The label to go to when the required condition ASSERTION is not met.
- *
- *  @param ACTION
- *      The extra action to take before go to the EXCEPTION_LABEL label when ASSERTION is not met.
- *
- *  @discussion
- *      Example:
- *      require_action(
- *          foo == NULL, // required to be true
- *          exit, // if not met goto label
- *          ret = -1;  ERROR("foo should not be NULL") // before exiting
- *      ) ;
- */
-#ifndef require_action
-    #define require_action(ASSERTION, EXCEPTION_LABEL, ACTION)    \
-        do {                                                            \
-            if (__builtin_expect(!(ASSERTION), 0))                      \
-            {                                                           \
-                {                                                       \
-                    ACTION;                                             \
-                }                                                       \
-                goto EXCEPTION_LABEL;                                   \
-            }                                                           \
-        } while(0)
-#endif // #ifndef require_action
-
-/*!
- *  @brief
- *      Check the required condition, if the required condition is not met, do the ACTION. It is usually used as DEBUG macro.
- *
- *  @param ASSERTION
- *      The condition that must be met before continue.
- *
- *  @param ACTION
- *      The extra action to take when ASSERTION is not met.
- *
- *  @discussion
- *      Example:
- *      verify_action(
- *          foo == NULL, // required to be true
- *          ERROR("foo should not be NULL")  // action to take if required is false
- *      ) ;
- */
-#undef verify_action
-#define verify_action(ASSERTION, ACTION)                                \
-    if (__builtin_expect(!(ASSERTION), 0)) {                            \
-        ACTION;                                                         \
-    }                                                                   \
-    else do {} while (0)
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // __SRP_H
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/tls-macos.h b/ServiceRegistration/tls-macos.h
deleted file mode 100644
index 4e3d52d..0000000
--- a/ServiceRegistration/tls-macos.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* tls-macos.h
- *
- * Copyright (c) 2020-2021 Apple 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
- *
- *     https://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.
- *
- * Definitions for getting TLS certificate and setting TLS.
- */
-
-#ifndef __DNSSD_PROXY_TLS_APPLE_H__
-#define __DNSSD_PROXY_TLS_APPLE_H__
-
-#include <stdio.h>
-#include <Security/SecKey.h>
-#include <Network/Network.h>
-#include <CoreUtils/CoreUtils.h> // For OSStatus.
-
-//======================================================================================================================
-// MARK: - Structures
-
-typedef struct tls_config_context tls_config_context_t;
-struct tls_config_context {
-    nw_protocol_options_t tls_options;
-    dispatch_queue_t queue;
-};
-
-//======================================================================================================================
-// MARK: - Function Declarations
-
-/*!
- *  @brief
- *      Get identity (the combination of private key and certificate) from keychain, or generate a new one if there is no existing identity in keychain.
- *
- *  @result
- *      Returns true if identity is fetched successfully.
- *
- *  @discussion
- *      The certificate being generated is a self-signed one, which means there will be no CA to veriry this trustworthiness of certificate.
- */
-bool
-srp_tls_init(void);
-
-#endif /* #ifndef __DNSSD_PROXY_TLS_APPLE_H__ */
diff --git a/ServiceRegistration/tls-mbedtls.c b/ServiceRegistration/tls-mbedtls.c
deleted file mode 100644
index 2fc563d..0000000
--- a/ServiceRegistration/tls-mbedtls.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* tls-mbedtls.c
- *
- * Copyright (c) 2019-2021 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.
- *
- * DNS SIG(0) signature verification for DNSSD SRP using mbedtls.
- *
- * Provides functions for generating a public key validating context based on SIG(0) KEY RR data, and
- * validating a signature using a context generated with that public key.  Currently only ECDSASHA256 is
- * supported.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "srp.h"
-#define SRP_CRYPTO_MBEDTLS_INTERNAL
-#include "dns-msg.h"
-#include "srp-crypto.h"
-#include "ioloop.h"
-#include "srp-tls.h"
-
-// Context that is shared amongs all TLS connections, regardless of which server cert/key is in use.
-mbedtls_entropy_context entropy;
-mbedtls_ctr_drbg_context ctr_drbg;
-
-// For now, assume that we are using just one key and one server cert, plus the ca cert.  Consequently, we
-// can treat this as global state.  If wanted later, we could make this its own structure.
-mbedtls_x509_crt cacert_struct, *cacert = NULL;
-mbedtls_x509_crt srvcert_struct, *srvcert = NULL;
-mbedtls_pk_context srvkey;
-mbedtls_ssl_config tls_server_config;
-mbedtls_ssl_config tls_client_config;
-mbedtls_ssl_config tls_opportunistic_config;
-
-bool
-srp_tls_init(void)
-{
-    int status;
-
-    // Initialize the shared data structures.
-    mbedtls_x509_crt_init(&srvcert_struct);
-    mbedtls_pk_init(&srvkey);
-    mbedtls_entropy_init(&entropy);
-    mbedtls_ctr_drbg_init(&ctr_drbg);
-
-    status = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
-    if (status != 0) {
-        ERROR("Unable to seed RNG: %x", -status);
-        return false;
-    }
-    return true;
-}
-
-static bool
-mbedtls_config_init(mbedtls_ssl_config *config, int flags)
-{
-    int status = mbedtls_ssl_config_defaults(config, flags,
-                                             MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
-    if (status != 0) {
-        ERROR("Unable to set up default TLS config state: %x", -status);
-        return false;
-    }
-
-    mbedtls_ssl_conf_rng(config, mbedtls_ctr_drbg_random, &ctr_drbg);
-    return true;
-}
-
-void
-srp_tls_configure(void *const NULLABLE context)
-{
-}
-
-bool
-srp_tls_client_init(void)
-{
-    if (!mbedtls_config_init(&tls_client_config, MBEDTLS_SSL_IS_CLIENT)) {
-        return false;
-    }
-    if (!mbedtls_config_init(&tls_opportunistic_config, MBEDTLS_SSL_IS_CLIENT)) {
-        return false;
-    }
-    mbedtls_ssl_conf_authmode(&tls_opportunistic_config, MBEDTLS_SSL_VERIFY_OPTIONAL);
-    return true;
-}
-
-bool
-srp_tls_server_init(const char *cacert_file, const char *srvcert_file, const char *server_key_file)
-{
-    int status;
-
-    // Load the public key and cert
-    if (cacert_file != NULL) {
-        status = mbedtls_x509_crt_parse_file(&cacert_struct, cacert_file);
-        if (status != 0) {
-            ERROR("Unable to parse ca cert file: %x", -status);
-            return false;
-        }
-        cacert = &cacert_struct;
-    }
-
-    if (srvcert_file != NULL) {
-        status = mbedtls_x509_crt_parse_file(&srvcert_struct, srvcert_file);
-        if (status != 0) {
-            ERROR("Unable to parse server cert file: %x", -status);
-            return false;
-        }
-        srvcert = &srvcert_struct;
-        if (srvcert_struct.next && cacert != NULL) {
-            cacert = srvcert_struct.next;
-        }
-    }
-
-    if (server_key_file != NULL) {
-        status = mbedtls_pk_parse_keyfile(&srvkey, server_key_file, NULL);
-        if (status != 0) {
-            ERROR("Unable to parse server cert file: %x", -status);
-            return false;
-        }
-    }
-
-    if (!mbedtls_config_init(&tls_server_config, MBEDTLS_SSL_IS_SERVER)) {
-        return false;
-    }
-
-    if (cacert != NULL) {
-        mbedtls_ssl_conf_ca_chain(&tls_server_config, cacert, NULL);
-    }
-
-    status = mbedtls_ssl_conf_own_cert(&tls_server_config, srvcert, &srvkey);
-    if (status != 0) {
-        ERROR("Unable to configure own cert: %x", -status);
-        return false;
-    }
-    return true;
-}
-
-static int
-srp_tls_io_send(void *ctx, const unsigned char *buf, size_t len)
-{
-    ssize_t ret;
-    comm_t *comm = ctx;
-    ret = write(comm->io.fd, buf, len);
-    if (ret < 0) {
-        if (errno == EAGAIN) {
-            return MBEDTLS_ERR_SSL_WANT_WRITE;
-        } else {
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-    } else {
-        return (int)ret;
-    }
-}
-
-static int
-srp_tls_io_recv(void *ctx, unsigned char *buf, size_t max)
-{
-    ssize_t ret;
-    comm_t *comm = ctx;
-    ret = read(comm->io.fd, buf, max);
-    if (ret < 0) {
-        if (errno == EWOULDBLOCK || errno == EAGAIN) {
-            return MBEDTLS_ERR_SSL_WANT_READ;
-        } else {
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-    } else if (ret == 0) {
-        return MBEDTLS_ERR_SSL_CONN_EOF;
-    } else {
-        return (int)ret;
-    }
-}
-
-bool
-srp_tls_listen_callback(comm_t *comm)
-{
-    int status;
-
-    // Allocate the TLS config and state structures.
-    comm->tls_context = calloc(1, sizeof *comm->tls_context);
-    if (comm->tls_context == NULL) {
-        return false;
-    }
-    status = mbedtls_ssl_setup(&comm->tls_context->context, &tls_server_config);
-    if (status != 0) {
-        ERROR("Unable to set up TLS listener state: %x", -status);
-        return false;
-    }
-
-    // Set up the I/O functions.
-    mbedtls_ssl_set_bio(&comm->tls_context->context, comm, srp_tls_io_send, srp_tls_io_recv, NULL);
-
-    // Start the TLS handshake.
-    status = mbedtls_ssl_handshake(&comm->tls_context->context);
-    if (status != 0 && status != MBEDTLS_ERR_SSL_WANT_READ && status != MBEDTLS_ERR_SSL_WANT_WRITE) {
-        ERROR("TLS handshake failed: %x", -status);
-        srp_tls_context_free(comm);
-        ioloop_close(&comm->io);
-    }
-    return true;
-}
-
-bool
-srp_tls_connect_callback(comm_t *comm)
-{
-    int status;
-    mbedtls_ssl_config *config = comm->opportunistic ? &tls_opportunistic_config : &tls_client_config;
-    // Allocate the TLS config and state structures.
-    comm->tls_context = calloc(1, sizeof *comm->tls_context);
-    if (comm->tls_context == NULL) {
-        return false;
-    }
-    status = mbedtls_ssl_setup(&comm->tls_context->context, config);
-    if (status != 0) {
-        ERROR("Unable to set up TLS connect state: %x", -status);
-        return false;
-    }
-
-    // Set up the I/O functions.
-    mbedtls_ssl_set_bio(&comm->tls_context->context, comm, srp_tls_io_send, srp_tls_io_recv, NULL);
-
-    // Start the TLS handshake.
-    status = mbedtls_ssl_handshake(&comm->tls_context->context);
-    if (status != 0 && status != MBEDTLS_ERR_SSL_WANT_READ && status != MBEDTLS_ERR_SSL_WANT_WRITE) {
-        ERROR("TLS handshake failed: %x", -status);
-        srp_tls_context_free(comm);
-        return false;
-    }
-    if (status == MBEDTLS_ERR_SSL_WANT_READ) {
-        comm->tls_handshake_incomplete = true;
-    }
-    INFO(PRI_S_SRP ": TLS handshake progress %d", comm->name, -status);
-    return true;
-}
-
-ssize_t
-srp_tls_read(comm_t *comm, unsigned char *buf, size_t max)
-{
-    // If we aren't done with the TLS handshake, continue it.
-    if (comm->tls_handshake_incomplete) {
-        int status = mbedtls_ssl_handshake(&comm->tls_context->context);
-        if (status != 0 && status != MBEDTLS_ERR_SSL_WANT_READ && status != MBEDTLS_ERR_SSL_WANT_WRITE) {
-            ERROR("TLS handshake failed: %x", -status);
-            srp_tls_context_free(comm);
-            return -1;
-        }
-        if (status == 0) {
-            comm->tls_handshake_incomplete = false;
-            comm->connected(comm, comm->context);
-        }
-        INFO(PRI_S_SRP ": TLS handshake progress %d", comm->name, -status);
-        return 0;
-    }
-
-    // Otherwise, read application data.
-    int ret = mbedtls_ssl_read(&comm->tls_context->context, buf, max);
-    if (ret < 0) {
-        switch (ret) {
-        case MBEDTLS_ERR_SSL_WANT_READ:
-            return 0;
-        case MBEDTLS_ERR_SSL_WANT_WRITE:
-            ERROR("Got SSL want write in TLS read!");
-            // This means we got EWOULDBLOCK on a write operation.
-            // Not implemented yet, but the right way to handle this is probably to
-            // deselect read events until the socket is ready to write, then write,
-            // and then re-enable read events.   What we don't want is to keep calling
-            // read, because that will spin.
-            return 0;
-        case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-            ERROR("Got async in progress in TLS read!");
-            // No idea how to handle this yet.
-            return 0;
-#ifdef MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
-        case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
-            ERROR("Got crypto in progress in TLS read!");
-            // No idea how to handle this.
-            return 0;
-#endif
-        default:
-            ERROR("Unexpected response from SSL read: %x", -ret);
-            return -1;
-        }
-    } else {
-        // mbedtls returns 0 for EOF, just like read(), but we need a different signal,
-        // so we treat 0 as an error (for now).   In principle, we should get a notification
-        // when the remote end is done writing, so a clean close should be different than
-        // an abrupt close.
-        if (ret == 0) {
-            ERROR("mbedtls_ssl_read returned zero.");
-            return -1;
-        }
-        return ret;
-    }
-}
-
-void
-srp_tls_context_free(comm_t *comm)
-{
-    // Free any state that the TLS library allocated
-    mbedtls_ssl_free(&comm->tls_context->context);
-    // Free and forget the context data structure
-    free(comm->tls_context);
-    comm->tls_context = 0;
-}
-
-ssize_t
-srp_tls_write(comm_t *comm, struct iovec *iov, int iov_len)
-{
-    int ret;
-    int i;
-    int bytes_written = 0;
-    for (i = 0; i < iov_len; i++) {
-        ret = mbedtls_ssl_write(&comm->tls_context->context, iov[i].iov_base, iov[i].iov_len);
-        if (ret < 0) {
-            switch (ret) {
-            case MBEDTLS_ERR_SSL_WANT_READ:
-                return bytes_written;
-            case MBEDTLS_ERR_SSL_WANT_WRITE:
-                ERROR("Got SSL want write in TLS read!");
-                return bytes_written;
-            case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-                ERROR("Got async in progress in TLS read!");
-                return bytes_written;
-#ifdef MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
-            case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
-                ERROR("Got crypto in progress in TLS read!");
-                return bytes_written;
-#endif
-            default:
-                ERROR("Unexpected response from SSL read: %x", -ret);
-                return -1;
-            }
-        } else if (ret != iov[i].iov_len) {
-            return bytes_written + ret;
-        } else {
-            bytes_written += ret;
-        }
-    }
-    return bytes_written;
-}
-
-// Dummy function for now; should eventually fetch the TLS context to use for validating
-// a cert presented by a remote connection.
-void
-configure_tls(void *const NULLABLE UNUSED context)
-{
-}
-
-void
-schedule_tls_certificate_rotation(wakeup_t **const UNUSED tls_listener_wakeup,
-	comm_t *const UNUSED tls_listener_to_rotate)
-{
-    ;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/towire.c b/ServiceRegistration/towire.c
deleted file mode 100644
index 9e0be2f..0000000
--- a/ServiceRegistration/towire.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/* towire.c
- *
- * Copyright (c) 2018-2021 Apple, 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.
- *
- * DNS to-wire wire-format functions.
- *
- * These are really simple functions for constructing DNS messages in wire format.
- * The flow is that there is a transaction structure which contains pointers to both
- * a message output buffer and a response input buffer.   The structure is initialized,
- * and then the various wire format functions are called repeatedly to store data.
- * If an error occurs during this process, it's okay to just keep going, because the
- * error is recorded in the transaction; once all of the copy-in functions have been
- * called, the error status can be checked once at the end.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#ifndef THREAD_DEVKIT_ADK
-#include <arpa/inet.h>
-#endif
-#include <stdlib.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-
-#ifndef NO_CLOCK
-#include <sys/time.h>
-#endif
-
-static int
-dns_parse_label(const char *cur, const char *NONNULL *NONNULL nextp, uint8_t *NONNULL lenp, uint8_t *NONNULL buf,
-                ssize_t max)
-{
-    const char *end;
-    int tlen;
-    const char *s;
-    uint8_t *t;
-
-    end = strchr(cur, '.');
-    if (end == NULL) {
-        end = cur + strlen(cur);
-        if (end == cur) {
-            *lenp = 0;
-            *nextp = NULL;
-            return 0;
-        }
-        *nextp = NULL;
-    } else {
-        if (end == cur) {
-            return EINVAL;
-        }
-        *nextp = end + 1;
-    }
-
-    // Figure out the length of the label after escapes have been converted.
-    tlen = 0;
-    for (s = cur; s < end; s++) {
-        if (*s == '\\') {
-            if (s + 4 <= end) {
-                tlen++;
-                s += 3;
-            } else {
-                tlen++;
-            }
-        } else {
-            tlen++;
-        }
-    }
-
-    // Is there no space?
-
-    if (tlen >= max) {
-        return ENOBUFS;
-    }
-
-    // Is the label too long?
-    if (end - cur > DNS_MAX_LABEL_SIZE) {
-        return ENAMETOOLONG;
-    }
-
-    // Store the label length
-    *lenp = (uint8_t)(tlen);
-
-    // Store the label.
-    t = buf;
-    for (s = cur; s < end; s++) {
-        if (*s == '\\') {
-            if (s + 4 <= end) {
-                int v0 = s[1] - '0';
-                int v1 = s[2] - '0';
-                int v2 = s[3] - '0';
-                int val = v0 * 100 + v1 * 10 + v2;
-                if (val < 255) {
-                    *t++ = (uint8_t)val;
-                    s += 3;
-                } else {
-                    return EINVAL;
-                }
-            } else {
-                return EINVAL;
-            }
-        } else {
-            *t++ = (uint8_t)*s;
-        }
-    }
-    return 0;
-}
-
-// Convert a name to wire format.   Does not store the root label (0) at the end.   Does not support binary labels.
-void
-dns_name_to_wire_(dns_name_pointer_t *NULLABLE r_pointer, dns_towire_state_t *NONNULL txn,
-                  const char *NONNULL name, int line)
-{
-    const char *next, *cur;
-    int status;
-    dns_name_pointer_t np;
-
-    if (!txn->error) {
-        memset(&np, 0, sizeof np);
-        np.message_start = (uint8_t *)txn->message;
-        np.name_start = txn->p;
-
-        cur = name;
-        do {
-            // Note that nothing is stored through txn->p until dns_name_parse has verified that
-            // there is space in the buffer for the label as well as the length.
-            status = dns_parse_label(cur, &next, txn->p, txn->p + 1, txn->lim - txn->p - 1);
-            if (status) {
-                if (status == ENOBUFS) {
-                    txn->truncated = true;
-                }
-                txn->error = (unsigned)status;
-                txn->line = line;
-                return;
-            }
-
-            // Don't use the root label if it was parsed.
-            if (*txn->p != 0) {
-                np.num_labels++;
-                np.length += 1 + *txn->p;
-                txn->p = txn->p + *txn->p + 1;
-                cur = next;
-            }
-        } while (next != NULL);
-
-        if (np.length > DNS_MAX_NAME_SIZE) {
-            txn->error = ENAMETOOLONG;
-            txn->line = line;
-            return;
-        }
-        if (r_pointer != NULL) {
-            *r_pointer = np;
-        }
-    }
-}
-
-// Like dns_name_to_wire, but includes the root label at the end.
-void
-dns_full_name_to_wire_(dns_name_pointer_t *NULLABLE r_pointer, dns_towire_state_t *NONNULL txn,
-                       const char *NONNULL name, int line)
-{
-    dns_name_pointer_t np;
-    if (!txn->error) {
-        memset(&np, 0, sizeof np);
-        dns_name_to_wire(&np, txn, name);
-        if (!txn->error) {
-            if (txn->p + 1 >= txn->lim) {
-                txn->error = ENOBUFS;
-                txn->truncated = true;
-                txn->line = line;
-                return;
-            }
-            *txn->p++ = 0;
-            np.num_labels++;
-            np.length += 1;
-            if (np.length > DNS_MAX_NAME_SIZE) {
-                txn->error = ENAMETOOLONG;
-                txn->line = line;
-                return;
-            }
-            if (r_pointer) {
-                *r_pointer = np;
-            }
-        }
-    }
-}
-
-// Store a pointer to a name that's already in the message.
-void
-dns_pointer_to_wire_(dns_name_pointer_t *NULLABLE r_pointer, dns_towire_state_t *NONNULL txn,
-                     dns_name_pointer_t *NONNULL pointer, int line)
-{
-    if (!txn->error) {
-        uint16_t offset = (uint16_t)(pointer->name_start - pointer->message_start);
-        if (offset > DNS_MAX_POINTER) {
-            txn->error = ETOOMANYREFS;
-            txn->line = line;
-            return;
-        }
-        if (txn->p + 2 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = 0xc0 | (offset >> 8);
-        *txn->p++ = offset & 0xff;
-        if (r_pointer) {
-            r_pointer->num_labels += pointer->num_labels;
-            r_pointer->length += pointer->length + 1;
-            if (r_pointer->length > DNS_MAX_NAME_SIZE) {
-                txn->error = ENAMETOOLONG;
-                txn->line = line;
-                return;
-            }
-        }
-    }
-}
-
-void
-dns_u8_to_wire_(dns_towire_state_t *NONNULL txn, uint8_t val, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 1 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = val;
-    }
-}
-
-// Store a 16-bit integer in network byte order
-void
-dns_u16_to_wire_(dns_towire_state_t *NONNULL txn, uint16_t val, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 2 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = val >> 8;
-        *txn->p++ = val & 0xff;
-    }
-}
-
-void
-dns_u32_to_wire_(dns_towire_state_t *NONNULL txn, uint32_t val, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 4 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = val >> 24;
-        *txn->p++ = (val >> 16) & 0xff;
-        *txn->p++ = (val >> 8) & 0xff;
-        *txn->p++ = val & 0xff;
-    }
-}
-
-void
-dns_u64_to_wire_(dns_towire_state_t *NONNULL txn, uint64_t val, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 8 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = val >> 56;
-        *txn->p++ = (val >> 48) & 0xff;
-        *txn->p++ = (val >> 40) & 0xff;
-        *txn->p++ = (val >> 32) & 0xff;
-        *txn->p++ = (val >> 24) & 0xff;
-        *txn->p++ = (val >> 16) & 0xff;
-        *txn->p++ = (val >> 8) & 0xff;
-        *txn->p++ = val & 0xff;
-    }
-}
-
-void
-dns_ttl_to_wire_(dns_towire_state_t *NONNULL txn, int32_t val, int line)
-{
-    if (!txn->error) {
-        dns_u32_to_wire_(txn, (uint32_t)val, line);
-    }
-}
-
-void
-dns_rdlength_begin_(dns_towire_state_t *NONNULL txn, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 2 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        if (txn->p_rdlength != NULL) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        txn->p_rdlength = txn->p;
-        txn->p += 2;
-    }
-}
-
-void
-dns_rdlength_end_(dns_towire_state_t *NONNULL txn, int line)
-{
-    ssize_t rdlength;
-    if (!txn->error) {
-        if (txn->p_rdlength == NULL) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        rdlength = txn->p - txn->p_rdlength - 2;
-        txn->p_rdlength[0] = (uint8_t)(rdlength >> 8);
-        txn->p_rdlength[1] = (uint8_t)(rdlength & 0xff);
-        txn->p_rdlength = NULL;
-    }
-}
-
-#ifndef THREAD_DEVKIT_ADK
-void
-dns_rdata_a_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL ip_address, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 4 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        if (!inet_pton(AF_INET, ip_address, txn->p)) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        txn->p += 4;
-    }
-}
-
-void
-dns_rdata_aaaa_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL ip_address, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 16 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        if (!inet_pton(AF_INET6, ip_address, txn->p)) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        txn->p += 16;
-    }
-}
-#endif
-
-uint16_t
-dns_rdata_key_to_wire_(dns_towire_state_t *NONNULL txn, unsigned key_type, unsigned name_type,
-                       uint8_t signatory, srp_key_t *key, int line)
-{
-    size_t key_len = srp_pubkey_length(key), copied_len;
-    uint8_t *rdata = txn->p;
-    uint32_t key_tag;
-    int i;
-    ssize_t rdlen;
-
-    if (!txn->error) {
-        if (key_type > 3 || name_type > 3 || signatory > 15) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return 0;
-        }
-        if (txn->p + key_len + 4 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return 0;
-        }
-        *txn->p++ = (uint8_t)((key_type << 6) | name_type);
-        *txn->p++ = signatory;
-        *txn->p++ = 3; // protocol type is always 3
-        *txn->p++ = srp_key_algorithm(key);
-        copied_len = srp_pubkey_copy(txn->p, key_len, key);
-        if (copied_len == 0) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return 0;
-        }
-        txn->p += key_len;
-    }
-    rdlen = txn->p - rdata;
-
-    // Compute the key tag
-    key_tag = 0;
-    for (i = 0; i < rdlen; i++) {
-        key_tag += (i & 1) ? rdata[i] : (uint16_t)(rdata[i] << 8);
-    }
-    key_tag += (key_tag >> 16) & 0xFFFF;
-    return (uint16_t)(key_tag & 0xFFFF);
-}
-
-void
-dns_rdata_txt_to_wire_(dns_towire_state_t *NONNULL txn, const char *NONNULL txt_record, int line)
-{
-    if (!txn->error) {
-        size_t len = strlen(txt_record);
-        if (txn->p + len + 1 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        if (len > 255) {
-            txn->error = ENAMETOOLONG;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = (uint8_t)len;
-        memcpy(txn->p, txt_record, len);
-        txn->p += len;
-    }
-}
-
-void
-dns_rdata_raw_data_to_wire_(dns_towire_state_t *NONNULL txn, const void *NONNULL raw_data, size_t length, int line)
-{
-    if (!txn->error) {
-        if (txn->p + length > txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        memcpy(txn->p, raw_data, length);
-        txn->p += length;
-    }
-}
-
-void
-dns_edns0_header_to_wire_(dns_towire_state_t *NONNULL txn, uint16_t mtu, uint8_t xrcode, uint8_t version, bool DO, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 9 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = 0; // root label
-        dns_u16_to_wire(txn, dns_rrtype_opt);
-        dns_u16_to_wire(txn, mtu);
-        *txn->p++ = xrcode;
-        *txn->p++ = version;
-        *txn->p++ = DO ? 1 << 7 : 0; // flags (usb)
-        *txn->p++ = 0;       // flags (lsb, mbz)
-    }
-}
-
-void
-dns_edns0_option_begin_(dns_towire_state_t *NONNULL txn, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 2 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        if (txn->p_opt != NULL) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        txn->p_opt = txn->p;
-        txn->p += 2;
-    }
-}
-
-void
-dns_edns0_option_end_(dns_towire_state_t *NONNULL txn, int line)
-{
-    ssize_t opt_length;
-    if (!txn->error) {
-        if (txn->p_opt == NULL) {
-            txn->error = EINVAL;
-            txn->line = line;
-            return;
-        }
-        opt_length = txn->p - txn->p_opt - 2;
-        txn->p_opt[0] = (uint8_t)(opt_length >> 8);
-        txn->p_opt[1] = opt_length & 0xff;
-        txn->p_opt = NULL;
-    }
-}
-
-void
-dns_sig0_signature_to_wire_(dns_towire_state_t *NONNULL txn, srp_key_t *key, uint16_t key_tag,
-                            dns_name_pointer_t *NONNULL signer, const char *NONNULL signer_hostname,
-                            const char *NONNULL signer_domain, int line)
-{
-    size_t siglen = srp_signature_length(key);
-    uint8_t *start, *p_signer, *p_signature, *rrstart = txn->p;
-#ifndef NO_CLOCK
-    struct timeval now;
-#endif
-
-    // 1 name (root)
-    // 2 type (SIG)
-    // 2 class (255) ANY
-    // 4 TTL (0)
-    // 18 SIG RDATA up to signer name
-    // 2 signer name (always a pointer)
-    // 29 bytes so far
-    // signature data (depends on algorithm, e.g. 64 for ECDSASHA256)
-    // so e.g. 93 bytes total
-
-    if (!txn->error) {
-        dns_u8_to_wire(txn, 0);	// root label
-        dns_u16_to_wire(txn, dns_rrtype_sig);
-        dns_u16_to_wire(txn, dns_qclass_any); // class
-        dns_ttl_to_wire(txn, 0); // SIG RR TTL
-        dns_rdlength_begin(txn);
-        start = txn->p;
-        dns_u16_to_wire(txn, 0); // type = 0 for transaction signature
-        dns_u8_to_wire(txn, srp_key_algorithm(key));
-        dns_u8_to_wire(txn, 0); // labels field doesn't apply for transaction signature
-        dns_ttl_to_wire(txn, 0); // original ttl doesn't apply
-#ifndef NO_CLOCK
-        gettimeofday(&now, NULL);
-        uint32_t sec = (uint32_t)now.tv_sec;
-        // In te extraordinarily unlikely event that time_t has rolled over
-        if (sec < 300) {
-#endif
-            dns_u32_to_wire(txn, 0); // Indicate that we have no clock: set expiry and inception times to zero
-            dns_u32_to_wire(txn, 0);
-#ifndef NO_CLOCK
-        } else {
-            dns_u32_to_wire(txn, sec + 300); // signature expiration time is five minutes from now
-            dns_u32_to_wire(txn, sec - 300); // signature inception time, five minutes in the past
-        }
-#endif
-        dns_u16_to_wire(txn, key_tag);
-
-        p_signer = txn->p;
-        // We store the name in uncompressed form because that's what we have to sign
-        if (signer_hostname != NULL) {
-            dns_name_to_wire(NULL, txn, signer_hostname);
-        }
-        dns_full_name_to_wire(NULL, txn, signer_domain);
-        // And that means we're going to have to copy the signature back earlier in the packet.
-        p_signature = txn->p;
-
-        // Sign the message, signature RRDATA (less signature) first.
-        if (!srp_sign(txn->p, siglen, (uint8_t *)txn->message, (size_t)(rrstart - (uint8_t *)txn->message),
-                      start, (size_t)(txn->p - start), key)) {
-            txn->error = true;
-            txn->line = __LINE__;
-        } else {
-            // Now that it's signed, back up and store the pointer to the name, because we're trying
-            // to be as compact as possible.
-            txn->p = p_signer;
-            dns_pointer_to_wire(NULL, txn, signer); // Pointer to the owner name the key is attached to
-            // And move the signature earlier in the packet.
-            memmove(txn->p, p_signature, siglen);
-
-            txn->p += siglen;
-            dns_rdlength_end(txn);
-        }
-
-        if (txn->error) {
-            txn->outer_line = line;
-        }
-    }
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/verify-macos.c b/ServiceRegistration/verify-macos.c
deleted file mode 100644
index b7c0534..0000000
--- a/ServiceRegistration/verify-macos.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/* verify_macos.c
- *
- * Copyright (c) 2019 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.
- *
- * DNS SIG(0) signature verification for DNSSD SRP using MacOS Security Framework.
- *
- * Provides functions for generating a public key validating context based on SIG(0) KEY RR data, and
- * validating a signature using a context generated with that public key.  Currently only ECDSASHA256 is
- * supported.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <AssertMacros.h>
-
-#include "srp.h"
-#define SRP_CRYPTO_MACOS_INTERNAL
-#include "dns-msg.h"
-#include "srp-crypto.h"
-
-//======================================================================================================================
-
-static SecKeyRef
-create_public_sec_key(const dns_rr_t *const key_record);
-
-static CFDataRef
-create_data_to_verify(dns_wire_t *const message, const dns_rr_t *const signature);
-
-bool
-srp_sig0_verify(dns_wire_t *message, dns_rr_t *key, dns_rr_t *signature)
-{
-    bool valid = false;
-    CFErrorRef cf_error = NULL;
-    SecKeyRef public_key = NULL;
-    CFDataRef data_to_verify_cfdata = NULL;
-    CFDataRef sig_to_match_cfdata = NULL;
-
-    // The algorithm in KEY and SIG(0) has to match.
-    require_action_quiet(key->data.key.algorithm == signature->data.sig.algorithm, exit,
-                         ERROR("KEY algorithm does not match the SIG(0) algorithm - "
-                               "KEY algorithm: %u, SIG(0) algorithm: %u",
-                               key->data.key.algorithm, signature->data.sig.algorithm));
-
-    // The only supported algorithm now is ECDSA Curve P-256 with SHA-256.
-    require_action_quiet(signature->data.sig.algorithm == dnssec_keytype_ecdsa, exit,
-                         ERROR("Unsupported KEY algorithm - KEY algorithm: %u", signature->data.sig.algorithm));
-
-    // The key size should always be ECDSA_KEY_SIZE since only ECDSA Curve P-256 with SHA-256 is used now.
-    require_action_quiet(key->data.key.len == ECDSA_KEY_SIZE, exit,
-                         ERROR("Invalid KEY length - KEY len: %d", key->data.key.len));
-
-    // The signature size should always be ECDSA_SHA256_SIG_SIZE, since only ECDSA Curve P-256 with SHA-256 is used now.
-    require_action_quiet(signature->data.sig.len == ECDSA_SHA256_SIG_SIZE, exit,
-                         ERROR("Invalid SIG(0) length - SIG(0) length: %d", signature->data.sig.len));
-
-    // Get SecKeyRef given the KEY data.
-    public_key = create_public_sec_key(key);
-    require_action_quiet(public_key != NULL, exit, ERROR("Failed to create public_key"));
-
-    // Create signature to check.
-    sig_to_match_cfdata = CFDataCreate(kCFAllocatorDefault, signature->data.sig.signature, signature->data.sig.len);
-    require_action_quiet(sig_to_match_cfdata != NULL, exit,
-                         ERROR("CFDataCreate failed when creating sig_to_match_cfdata"));
-
-    // Reconstruct the data (the digest of the raw data) that is signed by SIG(0).
-    data_to_verify_cfdata = create_data_to_verify(message, signature);
-    require_action_quiet(data_to_verify_cfdata != NULL, exit, ERROR("Failed to data_to_verify_cfdata"));
-
-    // Set the corresponding SecKeyAlgorithm for SecKeyVerifySignature.
-    SecKeyAlgorithm verify_algorithm;
-    switch (key->data.key.algorithm) {
-        case dnssec_keytype_ecdsa:
-            verify_algorithm = kSecKeyAlgorithmECDSASignatureRFC4754;
-            break;
-
-        default:
-            FAULT("Unsupported KEY algorithm - KEY algorithm: %u", key->data.key.algorithm);
-            goto exit;
-    }
-
-    // Validate the signature.
-    valid = SecKeyVerifySignature(public_key, verify_algorithm, data_to_verify_cfdata, sig_to_match_cfdata, &cf_error);
-    if (!valid) {
-        CFStringRef error_cfstring = CFErrorCopyDescription(cf_error);
-        ERROR("SecKeyVerifySignature failed to validate - Error Description: %@", error_cfstring);
-        CFRelease(error_cfstring);
-        CFRelease(cf_error);
-        cf_error = NULL;
-    }
-
-exit:
-    if (data_to_verify_cfdata != NULL) {
-        CFRelease(data_to_verify_cfdata);
-    }
-    if (sig_to_match_cfdata != NULL) {
-        CFRelease(sig_to_match_cfdata);
-    }
-    if (public_key != NULL) {
-        CFRelease(public_key);
-    }
-
-    return valid;
-}
-
-static SecKeyRef
-create_public_sec_key(const dns_rr_t *const key_record)
-{
-    SecKeyRef key_ref = NULL;
-    CFErrorRef cf_error = NULL;
-    if (key_record->data.key.algorithm == dnssec_keytype_ecdsa){
-        uint8_t four = 4;
-        const void *public_key_options_keys[] = {kSecAttrKeyType, kSecAttrKeyClass};
-        const void *public_key_options_values[] = {kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClassPublic};
-        CFMutableDataRef public_key_cfdata = NULL;
-        CFDictionaryRef public_key_options = NULL;
-
-        // The format of the public key data is 04 | X | Y
-        public_key_cfdata = CFDataCreateMutable(kCFAllocatorDefault, 1 + key_record->data.key.len);
-        require_action_quiet(public_key_cfdata != NULL, ecdsa_exit,
-                             ERROR("CFDataCreateMutable failed when creating public key CFMutableDataRef"));
-        CFDataAppendBytes(public_key_cfdata, &four, sizeof(four));
-        CFDataAppendBytes(public_key_cfdata, key_record->data.key.key, key_record->data.key.len);
-
-        public_key_options = CFDictionaryCreate(kCFAllocatorDefault, public_key_options_keys, public_key_options_values,
-                                                sizeof(public_key_options_keys) / sizeof(void *),
-                                                &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        require_action_quiet(public_key_options != NULL, ecdsa_exit,
-                             ERROR("CFDictionaryCreate failed when creating public key options CFDictionaryRef"));
-
-        key_ref = SecKeyCreateWithData(public_key_cfdata, public_key_options, &cf_error);
-        require_action_quiet(key_ref != NULL, ecdsa_exit,
-                             ERROR("SecKeyCreateWithData failed when creating public key SecKeyRef"));
-
-    ecdsa_exit:
-        if (public_key_cfdata != NULL) {
-            CFRelease(public_key_cfdata);
-        }
-        if (public_key_options != NULL) {
-            CFRelease(public_key_options);
-        }
-    } else {
-        key_ref = NULL;
-    }
-
-    if (cf_error != NULL) {
-        CFRelease(cf_error);
-        cf_error = NULL;
-    }
-    return key_ref;
-}
-
-static CFDataRef
-create_data_to_verify(dns_wire_t *const message, const dns_rr_t *const signature)
-{
-    bool encounter_error;
-    CFDataRef data_to_verify_cfdata = NULL;
-    uint8_t *canonical_signer_name = NULL;
-    uint8_t digest[ECDSA_SHA256_HASH_SIZE];
-
-    // Right now, the only supported KEY algorithm is ECDSAP256.
-    require_action_quiet(signature->data.sig.algorithm == dnssec_keytype_ecdsa, exit, encounter_error = true;
-        FAULT("Unsupported SIG(0) algorithm - SIG(0) algorithm: %u", signature->data.sig.algorithm));
-
-    CC_SHA256_CTX cc_digest_context;
-    CC_SHA256_Init(&cc_digest_context);
-
-    // data to be hashed = (SIG(0) RDATA without signature field) + (request - SIG(0)).
-
-    // (SIG(0) RDATA without signature field) = SIG(0) fields without signer name + canonical signer name.
-    // Copy SIG(0) fields without signer name.
-    CC_SHA256_Update(&cc_digest_context, &message->data[signature->data.sig.start + SIG_HEADERLEN], SIG_STATIC_RDLEN);
-
-    // Construct and copy canonical signer name.
-    size_t canonical_signer_name_length = dns_name_wire_length(signature->data.sig.signer);
-    // CC_SHA256_Update only accepts CC_LONG type (which is uint32_t) length parameter, so we need to check if the
-    // canonical_signer_name_length has invalid value.
-    require_action_quiet(canonical_signer_name_length <= MAXDOMNAMELEN, exit, encounter_error = true;
-        FAULT("Invalid signer name length - signer name length: %zu", canonical_signer_name_length));
-
-    canonical_signer_name = malloc(canonical_signer_name_length);
-    require_action_quiet(canonical_signer_name != NULL, exit, encounter_error = true;
-                         ERROR("malloc failed when allocating memory - for canonical_signer_name, len: %lu",
-                               canonical_signer_name_length));
-
-    bool convert_fail = !dns_name_to_wire_canonical(canonical_signer_name, canonical_signer_name_length,
-                                                    signature->data.sig.signer);
-    require_action_quiet(!convert_fail, exit, encounter_error = true;
-                         ERROR("Failed to write canonical name - canonical_signer_name_length: %lu",
-                               canonical_signer_name_length));
-
-    CC_SHA256_Update(&cc_digest_context, canonical_signer_name, (CC_LONG)canonical_signer_name_length);
-
-    // Copy (request - SIG(0)).
-    // The authority response count is before the counts have been adjusted for the inclusion of the SIG(0).
-    message->arcount = htons(ntohs(message->arcount) - 1);
-    CC_SHA256_Update(&cc_digest_context, (uint8_t *)message, offsetof(dns_wire_t, data) + signature->data.sig.start);
-    // Recover the count after copying.
-    message->arcount = htons(ntohs(message->arcount) + 1);
-
-    // Generate the final digest.
-    CC_SHA256_Final(digest, &cc_digest_context);
-
-    // Create CFDataRef.
-    data_to_verify_cfdata = CFDataCreate(kCFAllocatorDefault, digest, sizeof(digest));
-    require_action_quiet(data_to_verify_cfdata != NULL, exit, encounter_error = true;
-                         ERROR("CFDataCreate failed when creating data_to_verify_cfdata"));
-
-    encounter_error = false;
-exit:
-    if (canonical_signer_name != NULL) {
-        free(canonical_signer_name);
-    }
-    if (encounter_error) {
-        if (data_to_verify_cfdata != NULL) {
-            CFRelease(data_to_verify_cfdata);
-        }
-    }
-    return data_to_verify_cfdata;
-}
-
-//======================================================================================================================
-
-#if SECTRANSFORM_AVAILABLE
-// Function to copy out the public key as binary data
-void
-srp_print_key(srp_key_t *key)
-{
-    SecTransformRef b64encoder;
-    CFDataRef key_data, public_key = NULL;
-    CFDataRef encoded;
-    const uint8_t *data;
-    CFErrorRef error = NULL;
-
-    key_data = SecKeyCopyExternalRepresentation(key->public, &error);
-    if (error == NULL) {
-        data = CFDataGetBytePtr(key_data);
-        public_key = CFDataCreateWithBytesNoCopy(NULL, data + 1,
-                                                 CFDataGetLength(key_data) - 1, kCFAllocatorNull);
-        if (public_key != NULL) {
-            b64encoder = SecEncodeTransformCreate(public_key, &error);
-            if (error == NULL) {
-                SecTransformSetAttribute(b64encoder, kSecTransformInputAttributeName, key, &error);
-                if (error == NULL) {
-                    encoded = SecTransformExecute(b64encoder, &error);
-                    if (error == NULL) {
-                        data = CFDataGetBytePtr(encoded);
-                        fputs("thread-demo.default.service.arpa. IN KEY 513 3 13 ", stdout);
-                        fwrite(data, CFDataGetLength(encoded), 1, stdout);
-                        putc('\n', stdout);
-                    }
-                    if (encoded != NULL) {
-                        CFRelease(encoded);
-                    }
-                }
-            }
-            if (b64encoder != NULL) {
-                CFRelease(b64encoder);
-            }
-            CFRelease(public_key);
-        }
-    }
-    if (key_data != NULL) {
-        CFRelease(key_data);
-    }
-}
-#endif // SECTRANSFORM_AVAILABLE
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/verify-mbedtls.c b/ServiceRegistration/verify-mbedtls.c
deleted file mode 100644
index a4a6655..0000000
--- a/ServiceRegistration/verify-mbedtls.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* verify_mbedtls.c
- *
- * Copyright (c) 2018 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.
- *
- * DNS SIG(0) signature verification for DNSSD SRP using mbedtls.
- *
- * Provides functions for generating a public key validating context based on SIG(0) KEY RR data, and
- * validating a signature using a context generated with that public key.  Currently only ECDSASHA256 is
- * supported.
- */
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "srp.h"
-#include "dns-msg.h"
-#include "srp-crypto.h"
-
-
-// Given a DNS message, a signature, and a public key, validate the message
-bool
-srp_sig0_verify(dns_wire_t *message, dns_rr_t *key, dns_rr_t *signature)
-{
-    mbedtls_ecp_point pubkey;
-    mbedtls_ecp_group group;
-    mbedtls_sha256_context sha;
-    int status;
-    char errbuf[128];
-    uint8_t hash[ECDSA_SHA256_HASH_SIZE];
-    mbedtls_mpi r, s;
-    uint8_t *rdata;
-    size_t rdlen;
-
-    // The key algorithm and the signature algorithm have to match or we can't validate the signature.
-    if (key->data.key.algorithm != signature->data.sig.algorithm) {
-        return false;
-    }
-
-    // Key must be the right length (DNS ECDSA KEY isn't compressed).
-    if (key->data.key.len != ECDSA_KEY_SIZE) {
-        return false;
-    }
-
-    // Currently only support ecdsa
-    if (signature->data.sig.algorithm != dnssec_keytype_ecdsa) {
-        return false;
-    }
-
-    // Make sure the signature is the right size.
-    if (signature->data.sig.len != ECDSA_SHA256_SIG_SIZE) {
-        return false;
-    }
-
-    // Take the KEY RR and turn it into a public key we can use to check the signature.
-    // Initialize the ECP group (SECP256).
-    mbedtls_ecp_point_init(&pubkey);
-    mbedtls_ecp_group_init(&group);
-    mbedtls_ecp_group_load(&group, MBEDTLS_ECP_DP_SECP256R1);
-    mbedtls_mpi_init(&r);
-    mbedtls_mpi_init(&s);
-    mbedtls_sha256_init(&sha);
-    memset(hash, 0, sizeof hash);
-
-    if ((status = mbedtls_mpi_read_binary(&pubkey.X, key->data.key.key, ECDSA_KEY_PART_SIZE)) != 0 ||
-        (status = mbedtls_mpi_read_binary(&pubkey.Y, key->data.key.key + ECDSA_KEY_PART_SIZE, ECDSA_KEY_PART_SIZE)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_mpi_read_binary: reading key: " PUB_S_SRP, errbuf);
-    }
-    mbedtls_mpi_lset(&pubkey.Z, 1);
-
-    if ((status = mbedtls_mpi_read_binary(&r, signature->data.sig.signature, ECDSA_SHA256_SIG_PART_SIZE)) != 0 ||
-        (status = mbedtls_mpi_read_binary(&s, signature->data.sig.signature + ECDSA_SHA256_SIG_PART_SIZE,
-                                          ECDSA_SHA256_SIG_PART_SIZE)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_mpi_read_binary: reading signature: " PUB_S_SRP, errbuf);
-    }
-
-    // The hash is across the message _before_ the SIG RR is added, so we have to decrement arcount before
- 	// computing it.
-    message->arcount = htons(ntohs(message->arcount) - 1);
-
-    // And the SIG RRDATA that we hash includes the canonical version of the name, not whatever bits
-    // are in the actual wire format message, so we have to just make a copy of it.
-    rdlen = SIG_STATIC_RDLEN + dns_name_wire_length(signature->data.sig.signer);
-    rdata = malloc(rdlen);
-    if (rdata == NULL) {
-        ERROR("no memory for SIG RR canonicalization");
-        return 0;
-    }
-    memcpy(rdata, &message->data[signature->data.sig.start + SIG_HEADERLEN], SIG_STATIC_RDLEN);
-    if (!dns_name_to_wire_canonical(rdata + SIG_STATIC_RDLEN, rdlen - SIG_STATIC_RDLEN,
-                                    signature->data.sig.signer)) {
-        // Should never happen.
-        ERROR("dns_name_wire_length and dns_name_to_wire_canonical got different lengths!");
-        return 0;
-    }
-
-    // First compute the hash across the SIG RR, then hash the message up to the SIG RR
-    if ((status = mbedtls_sha256_starts_ret(&sha, 0)) != 0 ||
-        (status = srp_mbedtls_sha256_update_ret("rdata", &sha, rdata, rdlen)) != 0 ||
-        (status = srp_mbedtls_sha256_update_ret("message", &sha, (uint8_t *)message,
-                                                signature->data.sig.start +
-                                                (sizeof *message) - DNS_DATA_SIZE)) != 0 ||
-        (status = srp_mbedtls_sha256_finish_ret(&sha, hash)) != 0) {
-        // Put it back
-        message->arcount = htons(ntohs(message->arcount) + 1);
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_sha_256 hash failed: " PUB_S_SRP, errbuf);
-        return 0;
-    }
-    message->arcount = htons(ntohs(message->arcount) + 1);
-    free(rdata);
-
-    // Now check the signature against the hash
-    status = mbedtls_ecdsa_verify(&group, hash, sizeof hash, &pubkey, &r, &s);
-    if (status != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_ecdsa_verify failed: " PUB_S_SRP, errbuf);
-        return 0;
-    }
-    return 1;
-}
-
-// Function to copy out the public key as binary data
-void
-srp_print_key(srp_key_t *key)
-{
-    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key->key);
-    char errbuf[64];
-    uint8_t buf[ECDSA_KEY_SIZE];
-    uint8_t b64buf[((ECDSA_KEY_SIZE * 4) / 3) + 6];
-    size_t b64len;
-    int status;
-
-    // Currently ECP only.
-    if ((status = mbedtls_mpi_write_binary(&ecp->Q.X, buf, ECDSA_KEY_PART_SIZE)) != 0 ||
-        (status = mbedtls_mpi_write_binary(&ecp->Q.Y, buf + ECDSA_KEY_PART_SIZE, ECDSA_KEY_PART_SIZE)) != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_mpi_write_binary: " PUB_S_SRP, errbuf);
-        return;
-    }
-
-    status = mbedtls_base64_encode(b64buf, sizeof b64buf, &b64len, buf, ECDSA_KEY_SIZE);
-    if (status != 0) {
-        mbedtls_strerror(status, errbuf, sizeof errbuf);
-        ERROR("mbedtls_mpi_write_binary: " PUB_S_SRP, errbuf);
-        return;
-    }
-    fputs("thread-demo.default.service.arpa. IN KEY 513 3 13 ", stdout);
-    fwrite(b64buf, b64len, 1, stdout);
-    putc('\n', stdout);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/ServiceRegistration/wireutils.c b/ServiceRegistration/wireutils.c
deleted file mode 100644
index e0d4e23..0000000
--- a/ServiceRegistration/wireutils.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/* wireutils.c
- *
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- *
- * DNS wire-format utility functions.
- *
- * Functions that are neither necessary for very simple DNS packet generation, nor required for parsing
- * a message, e.g. compression, name printing, etc.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "srp.h"
-#include "dns-msg.h"
-
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-
-#undef LogMsg
-#define LogMsg(...)
-
-// We need the compression routines from DNSCommon.c, but we can't link to it because that
-// pulls in a _lot_ of stuff we don't want.   The solution?   Define STANDALONE (this is done
-// in the Makefile, and include DNSCommon.c.
-//
-// The only functions that aren't excluded by STANDALONE are FindCompressionPointer and
-// putDomainNameAsLabels.
-
-#ifndef STANDALONE
-#define STANDALONE
-#endif
-#include "../mDNSCore/DNSCommon.c"
-
-void dns_name_free(dns_label_t *name)
-{
-    dns_label_t *next;
-    if (name == NULL) {
-        return;
-    }
-    next = name->next;
-    free(name);
-    if (next != NULL) {
-        return dns_name_free(next);
-    }
-}
-
-dns_name_t *
-dns_name_copy(dns_name_t *original)
-{
-    dns_name_t *ret = NULL, **cur = &ret;
-    dns_name_t *next;
-
-    for (next = original; next; next = next->next) {
-        *cur = calloc(1, 1 + next->len + (sizeof (dns_name_t)) - DNS_MAX_LABEL_SIZE);
-        if (*cur == NULL) {
-            if (ret != NULL) {
-                dns_name_free(ret);
-            }
-            return NULL;
-        }
-        if (next->len) {
-            memcpy((*cur)->data, next->data, next->len + 1);
-        }
-        (*cur)->len = next->len;
-        cur = &((*cur)->next);
-    }
-    return ret;
-}
-
-// Needed for TSIG (RFC2845).
-void
-dns_u48_to_wire_(dns_towire_state_t *NONNULL txn,
-                 uint64_t val, int line)
-{
-    if (!txn->error) {
-        if (txn->p + 6 >= txn->lim) {
-            txn->error = ENOBUFS;
-            txn->truncated = true;
-            txn->line = line;
-            return;
-        }
-        *txn->p++ = (val >> 40) & 0xff;
-        *txn->p++ = (val >> 32) & 0xff;
-        *txn->p++ = (val >> 24) & 0xff;
-        *txn->p++ = (val >> 16) & 0xff;
-        *txn->p++ = (val >> 8) & 0xff;
-        *txn->p++ = val & 0xff;
-    }
-}
-
-void
-dns_concatenate_name_to_wire_(dns_towire_state_t *towire, dns_name_t *labels_prefix, const char *prefix,
-                              const char *suffix, int line)
-{
-    dns_wire_t namebuf;
-    dns_towire_state_t namewire;
-    mDNSu8 *ret;
-    namebuf.data[0] = 0;
-
-    // Don't do all this work if we're already past an error.
-    if (towire->error) {
-        return;
-    }
-    memset(&namewire, 0, sizeof namewire);
-    namewire.message = &namebuf;
-    namewire.lim = &namebuf.data[DNS_DATA_SIZE];
-    namewire.p = namebuf.data;
-    if (prefix != NULL) {
-        dns_name_to_wire(NULL, &namewire, prefix);
-    } else if (labels_prefix != NULL) {
-        size_t bytes_written;
-
-        if (!namewire.error) {
-            bytes_written = (size_t)(namewire.lim - namewire.p);
-            if (bytes_written > INT16_MAX) {
-                towire->error = true;
-                towire->line = __LINE__;
-                return;
-            }
-            bytes_written = dns_name_to_wire_canonical(namewire.p, bytes_written, labels_prefix);
-            // This can never occur with a valid name.
-            if (bytes_written == 0) {
-                namewire.truncated = true;
-            } else {
-                namewire.p += bytes_written;
-            }
-        }
-    }
-    if (suffix != NULL) {
-        dns_full_name_to_wire(NULL, &namewire, suffix);
-    }
-    if (namewire.error) {
-        towire->truncated = namewire.truncated;
-        towire->error = namewire.error;
-        towire->line = line;
-    }
-
-    ret = putDomainNameAsLabels((DNSMessage *)towire->message, towire->p, towire->lim, (domainname *)namebuf.data);
-    if (ret == NULL) {
-        towire->error = ENOBUFS;
-        towire->truncated = true;
-        towire->line = line;
-        return;
-    }
-
-    // Shouldn't happen
-    if (ret > towire->lim) {
-        towire->error = ENOBUFS;
-        towire->truncated = true;
-        towire->line = line;
-    } else {
-        towire->p = ret;
-    }
-}
-
-// Convert a dns_name_t to presentation format.   Stop conversion at the specified limit.
-// A trailing dot is only written if a null label is present.
-const char *NONNULL
-dns_name_print_to_limit(dns_name_t *NONNULL name, dns_name_t *NULLABLE limit, char *buf, size_t bufmax)
-{
-    dns_label_t *lp;
-    size_t ix = 0;
-    size_t i;
-
-    // Copy the labels in one at a time, putting a dot between each one; if there isn't room
-    // in the buffer (shouldn't be the case), copy as much as will fit, leaving room for a NUL
-    // termination.
-    for (lp = name; lp != limit && lp != NULL; lp = lp->next) {
-        if (ix != 0) {
-            if (ix + 2 >= bufmax) {
-                break;
-            }
-            buf[ix++] = '.';
-        }
-        for (i = 0; i < lp->len; i++) {
-            if (isascii(lp->data[i]) && (lp->data[i] == ' ' || isprint(lp->data[i]))) {
-                if (ix + 2 >= bufmax) {
-                    break;
-                }
-                buf[ix++] = lp->data[i];
-            } else {
-                if (ix + 5 >= bufmax) {
-                    break;
-                }
-                buf[ix++] = '\\';
-                buf[ix++] = '0' + (lp->data[i] / 100);
-                buf[ix++] = '0' + (lp->data[i] /  10) % 10;
-                buf[ix++] = '0' + lp->data[i]         % 10;
-            }
-        }
-        if (i != lp->len) {
-            break;
-        }
-    }
-    buf[ix++] = 0;
-    return buf;
-}
-
-const char *NONNULL
-dns_name_print(dns_name_t *NONNULL name, char *buf, size_t bufmax)
-{
-    return dns_name_print_to_limit(name, NULL, buf, bufmax);
-}
-
-bool
-dns_labels_equal(const char *label1, const char *label2, size_t len)
-{
-    unsigned i;
-    for (i = 0; i < len; i++) {
-        if (isascii(label1[i]) && isascii(label2[i])) {
-            if (tolower(label1[i]) != tolower(label2[i])) {
-                return false;
-            }
-        }
-        else {
-            if (label1[i] != label2[i]) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-bool
-dns_names_equal(dns_label_t *NONNULL name1, dns_label_t *NONNULL name2)
-{
-    if (name1->len != name2->len) {
-        return false;
-    }
-    if (name1->len != 0 && !dns_labels_equal(name1->data, name2->data, name1->len) != 0) {
-        return false;
-    }
-    if (name1->next != NULL && name2->next != NULL) {
-        return dns_names_equal(name1->next, name2->next);
-    }
-    if (name1->next == NULL && name2->next == NULL) {
-        return true;
-    }
-    return false;
-}
-
-// Note that "foo.arpa" is not the same as "foo.arpa."
-bool
-dns_names_equal_text(dns_label_t *NONNULL name1, const char *NONNULL name2)
-{
-    const char *ndot;
-    const char *s, *t;
-    int tlen = 0;
-    ndot = strchr(name2, '.');
-    if (ndot == NULL) {
-        ndot = name2 + strlen(name2);
-    }
-    for (s = name2; s < ndot; s++) {
-        if (*s == '\\') {
-            if (s + 4 <= ndot) {
-                tlen++;
-                s += 3;
-            } else {
-                return false;  // An invalid name can't be equal to anything.
-            }
-        } else {
-            tlen++;
-        }
-    }
-    if (name1->len != tlen) {
-        return false;
-    }
-    if (name1->len != 0) {
-        t = name1->data;
-        for (s = name2; s < ndot; s++, t++) {
-            if (*s == '\\') { // already bounds checked
-                int v0 = s[1] - '0';
-                int v1 = s[2] - '0';
-                int v2 = s[3] - '0';
-                int val = v0 * 100 + v1 * 10 + v2;
-                if (val > 255) {
-                    return false;
-                } else if (isascii(*s) && isascii(*t)) {
-                    if (tolower(*s) != tolower(*t)) {
-                        return false;
-                    }
-                } else if (val != *t) {
-                    return false;
-                }
-                s += 3;
-            } else {
-                if (*s != *t) {
-                    return false;
-                }
-            }
-        }
-    }
-    if (name1->next != NULL && *ndot == '.') {
-        return dns_names_equal_text(name1->next, ndot + 1);
-    }
-    if (name1->next == NULL && *ndot == 0) {
-        return true;
-    }
-    return false;
-}
-
-// Find the length of a name in uncompressed wire format.
-static size_t
-dns_name_wire_length_in(dns_label_t *NONNULL name, size_t ret)
-{
-    // Root label.
-    if (name == NULL)
-        return ret;
-    return dns_name_wire_length_in(name->next, ret + name->len + 1);
-}
-
-size_t
-dns_name_wire_length(dns_label_t *NONNULL name)
-{
-    return dns_name_wire_length_in(name, 0);
-}
-
-// Copy a name we've parsed from a message out in canonical wire format so that we can
-// use it to verify a signature.   As above, not actually needed for copying to a message
-// we're going to send, since in that case we want to try to compress.
-static size_t
-dns_name_to_wire_canonical_in(uint8_t *NONNULL buf, size_t max, size_t ret, dns_label_t *NONNULL name)
-{
-    if (name == NULL) {
-        return ret;
-    }
-    if (max < name->len + 1) {
-        return 0;
-    }
-    *buf = name->len;
-    memcpy(buf + 1, name->data, name->len);
-    return dns_name_to_wire_canonical_in(buf + name->len + 1,
-                                         max - name->len - 1, ret + name->len + 1, name->next);
-}
-
-size_t
-dns_name_to_wire_canonical(uint8_t *NONNULL buf, size_t max, dns_label_t *NONNULL name)
-{
-    return dns_name_to_wire_canonical_in(buf, max, 0, name);
-}
-
-// Parse a NUL-terminated text string into a sequence of labels.
-dns_name_t *
-dns_pres_name_parse(const char *pname)
-{
-    const char *dot, *s, *label;
-    dns_label_t *next, *ret, **prev = &ret;
-    size_t len;
-    char *t;
-    char buf[DNS_MAX_LABEL_SIZE];
-    ret = NULL;
-
-    label = pname;
-    dot = strchr(label, '.');
-    while (true) {
-        if (dot == NULL) {
-            dot = label + strlen(label);
-        }
-        len = (size_t)(dot - label);
-        if (len > 0) {
-            t = buf;
-            for (s = label; s < dot; s++) {
-                if (*s == '\\') { // already bounds checked
-                    int v0 = s[1] - '0';
-                    int v1 = s[2] - '0';
-                    int v2 = s[3] - '0';
-                    int val = v0 * 100 + v1 * 10 + v2;
-                    if (val > 255) {
-                        goto fail;
-                    }
-                    s += 3;
-                    *t++ = (char)val;
-                } else {
-                    *t++ = *s;
-                }
-                if ((size_t)(t - buf) >= sizeof(buf)) {
-                    goto fail;
-                }
-            }
-            len = (size_t)(t - buf);
-        }
-        next = calloc(1, len + 1 + (sizeof *next) - DNS_MAX_LABEL_SIZE);
-        if (next == NULL) {
-            goto fail;
-        }
-        *prev = next;
-        prev = &next->next;
-        next->len = (uint8_t)len;
-        if (next->len > 0) {
-            memcpy(next->data, buf, next->len);
-        }
-        next->data[next->len] = 0;
-        if (dot[0] == '.' && len > 0) {
-            dot = dot + 1;
-        }
-        if (*dot == '\0') {
-            if (len > 0) {
-                label = dot;
-            } else {
-                break;
-            }
-        } else {
-            label = dot;
-            dot = strchr(label, '.');
-        }
-    }
-    return ret;
-
-fail:
-    if (ret) {
-        dns_name_free(ret);
-    }
-    return NULL;
-}
-
-// See if name is a subdomain of domain.   If so, return a pointer to the label in name
-// where the match to domain begins.
-dns_name_t *
-dns_name_subdomain_of(dns_name_t *name, dns_name_t *domain)
-{
-    int dnum = 0, nnum = 0;
-    dns_name_t *np, *dp;
-
-    for (dp = domain; dp; dp = dp->next) {
-        dnum++;
-    }
-    for (np = name; np; np = np->next) {
-        nnum++;
-    }
-    if (nnum < dnum) {
-        return NULL;
-    }
-    for (np = name; np; np = np->next) {
-        if (nnum-- == dnum) {
-            break;
-        }
-    }
-    if (np != NULL && dns_names_equal(np, domain)) {
-        return np;
-    }
-    return NULL;
-}
-
-const char *
-dns_rcode_name(int rcode)
-{
-    switch(rcode) {
-    case dns_rcode_noerror:
-        return "No Error";
-    case dns_rcode_formerr:
-        return "Format Error";
-    case dns_rcode_servfail:
-        return "Server Failure";
-    case dns_rcode_nxdomain:
-        return "Non-Existent Domain";
-    case dns_rcode_notimp:
-        return "Not Implemented";
-    case dns_rcode_refused:
-        return "Query Refused";
-    case dns_rcode_yxdomain:
-        return "Name Exists when it should not";
-    case dns_rcode_yxrrset:
-        return "RR Set Exists when it should not";
-    case dns_rcode_nxrrset:
-        return "RR Set that should exist does not";
-    case dns_rcode_notauth:
-        return "Not Authorized";
-    case dns_rcode_notzone:
-        return "Name not contained in zone";
-    case dns_rcode_dsotypeni:
-        return "DSO-Type Not Implemented";
-    case dns_rcode_badvers:
-        return "TSIG Signature Failure";
-    case dns_rcode_badkey:
-        return "Key not recognized";
-    case dns_rcode_badtime:
-        return "Signature out of time window";
-    case dns_rcode_badmode:
-        return "Bad TKEY Mode";
-    case dns_rcode_badname:
-        return "Duplicate key name";
-    case dns_rcode_badalg:
-        return "Algorithm not supported";
-    case dns_rcode_badtrunc:
-        return "Bad Truncation";
-    case dns_rcode_badcookie:
-        return "Bad/missing Server Cookie";
-    default:
-        return "Unknown rcode.";
-    }
-}
-
-bool
-dns_keys_rdata_equal(dns_rr_t *key1, dns_rr_t *key2)
-{
-    if ((key1->type == dns_rrtype_key && key2->type == dns_rrtype_key) &&
-        key1->data.key.flags == key2->data.key.flags &&
-        key1->data.key.protocol == key2->data.key.protocol &&
-        key1->data.key.algorithm == key2->data.key.algorithm &&
-        key1->data.key.len == key2->data.key.len &&
-        !memcmp(key1->data.key.key, key2->data.key.key, key1->data.key.len))
-    {
-        return true;
-    }
-    return false;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c
deleted file mode 100644
index 0d21608..0000000
--- a/mDNSCore/DNSCommon.c
+++ /dev/null
@@ -1,4823 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef STANDALONE
-// Set mDNS_InstantiateInlines to tell mDNSEmbeddedAPI.h to instantiate inline functions, if necessary
-#define mDNS_InstantiateInlines 1
-#include "DNSCommon.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec_obj_rr_ds.h"   // For dnssec_obj_rr_ds_t.
-#include "dnssec_mdns_core.h"   // For DNSSEC-related operation on mDNSCore structures.
-#include "rdata_parser.h"       // For DNSSEC-related records parsing.
-#include "base_encoding.h"      // For base64 encoding.
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-#include <os/lock.h> // For os_unfair_lock.
-#endif
-
-// 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 "array is too small to include a terminating null character" warning
-// -- domain labels have an initial length byte, not a terminating null character
-    #pragma warning(disable:4295)
-#endif
-
-// ***************************************************************************
-// MARK: - Program Constants
-
-#include "mdns_strict.h"
-
-mDNSexport const mDNSInterfaceID mDNSInterface_Any       = 0;
-mDNSexport const mDNSInterfaceID mDNSInterfaceMark       = (mDNSInterfaceID)-1;
-mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)-2;
-mDNSexport const mDNSInterfaceID mDNSInterface_P2P       = (mDNSInterfaceID)-3;
-mDNSexport const mDNSInterfaceID uDNSInterfaceMark       = (mDNSInterfaceID)-4;
-mDNSexport const mDNSInterfaceID mDNSInterface_BLE       = (mDNSInterfaceID)-5;
-
-// Note: Microsoft's proposed "Link Local Multicast Name Resolution Protocol" (LLMNR) is essentially a limited version of
-// Multicast DNS, using the same packet formats, naming syntax, and record types as Multicast DNS, but on a different UDP
-// port and multicast address, which means it won't interoperate with the existing installed base of Multicast DNS responders.
-// LLMNR uses IPv4 multicast address 224.0.0.252, IPv6 multicast address FF02::0001:0003, and UDP port 5355.
-// Uncomment the appropriate lines below to build a special Multicast DNS responder for testing interoperability
-// with Microsoft's LLMNR client code.
-
-#define   DiscardPortAsNumber               9
-#define   SSHPortAsNumber                  22
-#define   UnicastDNSPortAsNumber           53
-#define   SSDPPortAsNumber               1900
-#define   IPSECPortAsNumber              4500
-#define   NSIPCPortAsNumber              5030       // Port used for dnsextd to talk to local nameserver bound to loopback
-#define   NATPMPAnnouncementPortAsNumber 5350
-#define   NATPMPPortAsNumber             5351
-#define   DNSEXTPortAsNumber             5352       // Port used for end-to-end DNS operations like LLQ, Updates with Leases, etc.
-#define   MulticastDNSPortAsNumber       5353
-#define   LoopbackIPCPortAsNumber        5354
-//#define MulticastDNSPortAsNumber       5355		// LLMNR
-#define   PrivateDNSPortAsNumber         5533
-
-mDNSexport const mDNSIPPort DiscardPort            = { { DiscardPortAsNumber            >> 8, DiscardPortAsNumber            & 0xFF } };
-mDNSexport const mDNSIPPort SSHPort                = { { SSHPortAsNumber                >> 8, SSHPortAsNumber                & 0xFF } };
-mDNSexport const mDNSIPPort UnicastDNSPort         = { { UnicastDNSPortAsNumber         >> 8, UnicastDNSPortAsNumber         & 0xFF } };
-mDNSexport const mDNSIPPort SSDPPort               = { { SSDPPortAsNumber               >> 8, SSDPPortAsNumber               & 0xFF } };
-mDNSexport const mDNSIPPort IPSECPort              = { { IPSECPortAsNumber              >> 8, IPSECPortAsNumber              & 0xFF } };
-mDNSexport const mDNSIPPort NSIPCPort              = { { NSIPCPortAsNumber              >> 8, NSIPCPortAsNumber              & 0xFF } };
-mDNSexport const mDNSIPPort NATPMPAnnouncementPort = { { NATPMPAnnouncementPortAsNumber >> 8, NATPMPAnnouncementPortAsNumber & 0xFF } };
-mDNSexport const mDNSIPPort NATPMPPort             = { { NATPMPPortAsNumber             >> 8, NATPMPPortAsNumber             & 0xFF } };
-mDNSexport const mDNSIPPort DNSEXTPort             = { { DNSEXTPortAsNumber             >> 8, DNSEXTPortAsNumber             & 0xFF } };
-mDNSexport const mDNSIPPort MulticastDNSPort       = { { MulticastDNSPortAsNumber       >> 8, MulticastDNSPortAsNumber       & 0xFF } };
-mDNSexport const mDNSIPPort LoopbackIPCPort        = { { LoopbackIPCPortAsNumber        >> 8, LoopbackIPCPortAsNumber        & 0xFF } };
-mDNSexport const mDNSIPPort PrivateDNSPort         = { { PrivateDNSPortAsNumber         >> 8, PrivateDNSPortAsNumber         & 0xFF } };
-
-mDNSexport const OwnerOptData zeroOwner         = { 0, 0, { { 0 } }, { { 0 } }, { { 0 } } };
-
-mDNSexport const mDNSIPPort zeroIPPort        = { { 0 } };
-mDNSexport const mDNSv4Addr zerov4Addr        = { { 0 } };
-mDNSexport const mDNSv6Addr zerov6Addr        = { { 0 } };
-mDNSexport const mDNSEthAddr zeroEthAddr       = { { 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 } };
-mDNSexport const mDNSEthAddr onesEthAddr       = { { 255, 255, 255, 255, 255, 255 } };
-mDNSexport const mDNSAddr zeroAddr          = { mDNSAddrType_None, {{{ 0 }}} };
-
-mDNSexport const mDNSv4Addr AllDNSAdminGroup   = { { 239, 255, 255, 251 } };
-mDNSexport const mDNSv4Addr AllHosts_v4        = { { 224,   0,   0,   1 } };  // For NAT-PMP & PCP Annoucements
-mDNSexport const mDNSv6Addr AllHosts_v6        = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01 } };
-mDNSexport const mDNSv6Addr NDP_prefix         = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0xFF,0x00,0x00,0xFB } };  // FF02:0:0:0:0:1:FF00::/104
-mDNSexport const mDNSEthAddr AllHosts_v6_Eth    = { { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } };
-mDNSexport const mDNSAddr AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 251 } } } };
-//mDNSexport const mDNSAddr  AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 252 } } } }; // LLMNR
-mDNSexport const mDNSAddr AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } } } };
-//mDNSexport const mDNSAddr  AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x03 } } } }; // LLMNR
-
-mDNSexport const mDNSOpaque16 zeroID          = { { 0, 0 } };
-mDNSexport const mDNSOpaque16 onesID          = { { 255, 255 } };
-mDNSexport const mDNSOpaque16 QueryFlags      = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery,                0 } };
-mDNSexport const mDNSOpaque16 uQueryFlags     = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery | kDNSFlag0_RD, 0 } };
-mDNSexport const mDNSOpaque16 ResponseFlags   = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
-mDNSexport const mDNSOpaque16 UpdateReqFlags  = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update,                  0 } };
-mDNSexport const mDNSOpaque16 UpdateRespFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update,                  0 } };
-
-mDNSexport const mDNSOpaque64  zeroOpaque64     = { { 0 } };
-mDNSexport const mDNSOpaque128 zeroOpaque128    = { { 0 } };
-
-extern mDNS mDNSStorage;
-
-// ***************************************************************************
-// MARK: - General Utility Functions
-
-mDNSexport void CacheRecordSetResponseFlags(CacheRecord *const cr, const mDNSOpaque16 responseFlags)
-{
-    cr->responseFlags = responseFlags;
-    cr->resrec.rcode  = cr->responseFlags.b[1] & kDNSFlag1_RC_Mask;
-}
-
-mDNSexport void mDNSCoreResetRecord(mDNS *const m)
-{
-    m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
-    CacheRecordSetResponseFlags(&m->rec.r, zeroID);
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    MDNS_DISPOSE_DNSSEC_OBJ(m->rec.r.resrec.dnssec);
-#endif
-}
-
-// return true for RFC1918 private addresses
-mDNSexport mDNSBool mDNSv4AddrIsRFC1918(const mDNSv4Addr * const addr)
-{
-    return ((addr->b[0] == 10) ||                                 // 10/8 prefix
-            (addr->b[0] == 172 && (addr->b[1] & 0xF0) == 16) ||   // 172.16/12
-            (addr->b[0] == 192 && addr->b[1] == 168));            // 192.168/16
-}
-
-mDNSexport const char *DNSScopeToString(mDNSu32 scope)
-{
-    switch (scope)
-    {
-        case kScopeNone:
-            return "Unscoped";
-        case kScopeInterfaceID:
-            return "InterfaceScoped";
-        case kScopeServiceID:
-            return "ServiceScoped";
-        default:
-            return "Unknown";
-    }
-}
-
-mDNSexport void mDNSAddrMapIPv4toIPv6(mDNSv4Addr* in, mDNSv6Addr* out)
-{
-    out->l[0] = 0;
-    out->l[1] = 0;
-    out->w[4] = 0;
-    out->w[5] = 0xffff;
-    out->b[12] = in->b[0];
-    out->b[13] = in->b[1];
-    out->b[14] = in->b[2];
-    out->b[15] = in->b[3];
-}
-
-mDNSexport mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr* out)
-{
-    if (in->l[0] != 0 || in->l[1] != 0 || in->w[4] != 0 || in->w[5] != 0xffff)
-        return mDNSfalse;
-
-    out->NotAnInteger = in->l[3];
-    return mDNStrue;
-}
-
-mDNSexport NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf)
-{
-    while (intf && !intf->InterfaceActive) intf = intf->next;
-    return(intf);
-}
-
-mDNSexport mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf)
-{
-    const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
-    if (next) return(next->InterfaceID);else return(mDNSNULL);
-}
-
-mDNSexport mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id)
-{
-    mDNSu32 slot, used = 0;
-    CacheGroup *cg;
-    const CacheRecord *rr;
-    FORALL_CACHERECORDS(slot, cg, rr)
-    {
-        if (rr->resrec.InterfaceID == id)
-            used++;
-    }
-    return(used);
-}
-
-mDNSexport char *DNSTypeName(mDNSu16 rrtype)
-{
-    switch (rrtype)
-    {
-    case kDNSType_A:    return("Addr");
-    case kDNSType_NS:   return("NS");
-    case kDNSType_CNAME: return("CNAME");
-    case kDNSType_SOA:  return("SOA");
-    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 kDNSType_OPT:  return("OPT");
-    case kDNSType_NSEC: return("NSEC");
-    case kDNSType_NSEC3: return("NSEC3");
-    case kDNSType_NSEC3PARAM: return("NSEC3PARAM");
-    case kDNSType_TSIG: return("TSIG");
-    case kDNSType_RRSIG: return("RRSIG");
-    case kDNSType_DNSKEY: return("DNSKEY");
-    case kDNSType_DS: return("DS");
-    case kDNSType_SVCB: return("SVCB");
-    case kDNSType_HTTPS: return("HTTPS");
-    case kDNSType_TSR: return("TSR");
-    case kDNSQType_ANY: return("ANY");
-    default:            {
-        static char buffer[16];
-        mDNS_snprintf(buffer, sizeof(buffer), "TYPE%d", rrtype);
-        return(buffer);
-    }
-    }
-}
-
-mDNSexport const char *mStatusDescription(mStatus error)
-{
-    const char *error_description;
-    switch (error) {
-        case mStatus_NoError:
-            error_description = "mStatus_NoError";
-            break;
-        case mStatus_BadParamErr:
-            error_description = "mStatus_BadParamErr";
-            break;
-
-        default:
-            error_description = "mStatus_UnknownDescription";
-            break;
-    }
-
-    return error_description;
-}
-
-mDNSexport mDNSu32 swap32(mDNSu32 x)
-{
-    mDNSu8 *ptr = (mDNSu8 *)&x;
-    return (mDNSu32)((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
-}
-
-mDNSexport mDNSu16 swap16(mDNSu16 x)
-{
-    mDNSu8 *ptr = (mDNSu8 *)&x;
-    return (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
-}
-
-mDNSlocal void PrintTypeBitmap(const mDNSu8 *bmap, int bitmaplen, char *const buffer, mDNSu32 length)
-{
-    int win, wlen, type;
-
-    while (bitmaplen > 0)
-    {
-        int i;
-
-        if (bitmaplen < 3)
-        {
-            LogMsg("PrintTypeBitmap: malformed bitmap, bitmaplen %d short", bitmaplen);
-            break;
-        }
-
-        win = *bmap++;
-        wlen = *bmap++;
-        bitmaplen -= 2;
-        if (bitmaplen < wlen || wlen < 1 || wlen > 32)
-        {
-            LogInfo("PrintTypeBitmap: malformed nsec, bitmaplen %d wlen %d", bitmaplen, wlen);
-            break;
-        }
-        if (win < 0 || win >= 256)
-        {
-            LogInfo("PrintTypeBitmap: malformed nsec, bad window win %d", win);
-            break;
-        }
-        type = win * 256;
-        for (i = 0; i < wlen * 8; i++)
-        {
-            if (bmap[i>>3] & (128 >> (i&7)))
-                length += mDNS_snprintf(buffer+length, (MaxMsg - 1) - length, "%s ", DNSTypeName(type + i));
-        }
-        bmap += wlen;
-        bitmaplen -= wlen;
-    }
-}
-
-// Note slight bug: this code uses the rdlength from the ResourceRecord object, to display
-// the rdata from the RDataBody object. Sometimes this could be the wrong length -- but as
-// long as this routine is only used for debugging messages, it probably isn't a big problem.
-mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer)
-{
-    const RDataBody2 *const rd = (const RDataBody2 *)rd1;
-    #define RemSpc (MaxMsg-1-length)
-    char *ptr = buffer;
-    mDNSu32 length = mDNS_snprintf(buffer, MaxMsg-1, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype));
-    if (rr->RecordType == kDNSRecordTypePacketNegative) return(buffer);
-    if (!rr->rdlength && rr->rrtype != kDNSType_OPT) { mDNS_snprintf(buffer+length, RemSpc, "<< ZERO RDATA LENGTH >>"); return(buffer); }
-
-    switch (rr->rrtype)
-    {
-    case kDNSType_A:    mDNS_snprintf(buffer+length, RemSpc, "%.4a", &rd->ipv4);          break;
-
-    case kDNSType_NS:       // Same as PTR
-    case kDNSType_CNAME:    // Same as PTR
-    case kDNSType_PTR:  mDNS_snprintf(buffer+length, RemSpc, "%##s", rd->name.c);       break;
-
-    case kDNSType_SOA:  mDNS_snprintf(buffer+length, RemSpc, "%##s %##s %d %d %d %d %d",
-                                      rd->soa.mname.c, rd->soa.rname.c,
-                                      rd->soa.serial, rd->soa.refresh, rd->soa.retry, rd->soa.expire, rd->soa.min);
-        break;
-
-    case kDNSType_HINFO:    // Display this the same as TXT (show all constituent strings)
-    case kDNSType_TXT:  {
-        const mDNSu8 *t = rd->txt.c;
-        const mDNSu8 *const rdLimit = rd->data + rr->rdlength;
-        const char *separator = "";
-
-        while (t < rdLimit)
-        {
-            mDNSu32 characterStrLength = *t;
-            if (characterStrLength + 1 > (mDNSu32)(rdLimit - t)) // Character string goes out of boundary.
-            {
-                const mDNSu8 *const remainderStart = t + 1;
-                const mDNSu32 remainderLength = (mDNSu32)(rdLimit - remainderStart);
-                length += mDNS_snprintf(buffer + length, RemSpc, "%s%.*s<<OUT OF BOUNDARY CHARACTER STRING>>", separator,
-                    remainderLength, remainderStart);
-                (void)length; // Acknowledge "dead store" analyzer warning.
-                break;
-            }
-            length += mDNS_snprintf(buffer+length, RemSpc, "%s%.*s", separator, characterStrLength, t + 1);
-            separator = "¦";
-            t += 1 + characterStrLength;
-        }
-    }
-        break;
-
-    case kDNSType_AAAA: mDNS_snprintf(buffer+length, RemSpc, "%.16a", &rd->ipv6);       break;
-    case kDNSType_SRV:  mDNS_snprintf(buffer+length, RemSpc, "%u %u %u %##s",
-                                      rd->srv.priority, rd->srv.weight, mDNSVal16(rd->srv.port), rd->srv.target.c); break;
-    case kDNSType_TSR:  mDNS_snprintf(buffer+length, RemSpc, "%d", rd1->tsr_value);       break;
-
-    case kDNSType_OPT:  {
-        const rdataOPT *opt;
-        const rdataOPT *const end = (const rdataOPT *)&rd->data[rr->rdlength];
-        length += mDNS_snprintf(buffer+length, RemSpc, "Max %d", rr->rrclass);
-        for (opt = &rd->opt[0]; opt < end; opt++)
-        {
-            switch(opt->opt)
-            {
-            case kDNSOpt_LLQ:
-                length += mDNS_snprintf(buffer+length, RemSpc, " LLQ");
-                length += mDNS_snprintf(buffer+length, RemSpc, " Vers %d",     opt->u.llq.vers);
-                length += mDNS_snprintf(buffer+length, RemSpc, " Op %d",       opt->u.llq.llqOp);
-                length += mDNS_snprintf(buffer+length, RemSpc, " Err/Port %d", opt->u.llq.err);
-                length += mDNS_snprintf(buffer+length, RemSpc, " ID %08X%08X", opt->u.llq.id.l[0], opt->u.llq.id.l[1]);
-                length += mDNS_snprintf(buffer+length, RemSpc, " Lease %d",    opt->u.llq.llqlease);
-                break;
-            case kDNSOpt_Lease:
-                length += mDNS_snprintf(buffer+length, RemSpc, " Lease %d",    opt->u.updatelease);
-                break;
-            case kDNSOpt_Owner:
-                length += mDNS_snprintf(buffer+length, RemSpc, " Owner");
-                length += mDNS_snprintf(buffer+length, RemSpc, " Vers %d",     opt->u.owner.vers);
-                length += mDNS_snprintf(buffer+length, RemSpc, " Seq %3d", (mDNSu8)opt->u.owner.seq);                           // Display as unsigned
-                length += mDNS_snprintf(buffer+length, RemSpc, " MAC %.6a",    opt->u.owner.HMAC.b);
-                if (opt->optlen >= DNSOpt_OwnerData_ID_Wake_Space-4)
-                {
-                    length += mDNS_snprintf(buffer+length, RemSpc, " I-MAC %.6a", opt->u.owner.IMAC.b);
-                    if (opt->optlen > DNSOpt_OwnerData_ID_Wake_Space-4)
-                        length += mDNS_snprintf(buffer+length, RemSpc, " Password %.6a", opt->u.owner.password.b);
-                }
-                break;
-            case kDNSOpt_Trace:
-                length += mDNS_snprintf(buffer+length, RemSpc, " Trace");
-                length += mDNS_snprintf(buffer+length, RemSpc, " Platform %d",    opt->u.tracer.platf);
-                length += mDNS_snprintf(buffer+length, RemSpc, " mDNSVers %d",    opt->u.tracer.mDNSv);
-                break;
-            default:
-                length += mDNS_snprintf(buffer+length, RemSpc, " Unknown %d",  opt->opt);
-                break;
-            }
-        }
-    }
-    break;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    case kDNSType_DS: {
-        // See <https://datatracker.ietf.org/doc/html/rfc4034#section-5.3> for DS RR Presentation Format.
-
-        dnssec_error_t err;
-        dnssec_obj_rr_ds_t ds = mDNSNULL;
-        char *ds_rdata_description = mDNSNULL;
-
-        ds = dnssec_obj_rr_ds_create(rr->name->c, rr->rrclass, rr->rdata->u.data, rr->rdlength, false, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR)
-        {
-            goto ds_exit;
-        }
-
-        ds_rdata_description = dnssec_obj_rr_copy_rdata_rfc_description(ds, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR)
-        {
-            goto ds_exit;
-        }
-
-        mDNS_snprintf(buffer + length, RemSpc, "%s", ds_rdata_description);
-
-    ds_exit:
-        MDNS_DISPOSE_DNSSEC_OBJ(ds);
-        mDNSPlatformMemFree(ds_rdata_description);
-    }
-    break;
-
-    case kDNSType_RRSIG: {
-        // See <https://datatracker.ietf.org/doc/html/rfc4034#section-3.2> for RRSIG RR Presentation Format.
-
-        dnssec_error_t err;
-        dnssec_obj_rr_rrsig_t rrsig = NULL;
-        char *rrsig_rdata_description = mDNSNULL;
-
-        rrsig = dnssec_obj_rr_rrsig_create(rr->name->c, rr->rdata->u.data, rr->rdlength, false, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR) {
-            goto rrsig_exit;
-        }
-
-        rrsig_rdata_description = dnssec_obj_rr_copy_rdata_rfc_description(rrsig, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR)
-        {
-            goto rrsig_exit;
-        }
-
-        mDNS_snprintf(buffer + length, RemSpc, "%s", rrsig_rdata_description);
-
-    rrsig_exit:
-        MDNS_DISPOSE_DNSSEC_OBJ(rrsig);
-		mDNSPlatformMemFree(rrsig_rdata_description);
-    }
-    break;
-#endif
-
-    case kDNSType_NSEC: {
-        const domainname *next = (const domainname *)rd->data;
-        int len, bitmaplen;
-        const mDNSu8 *bmap;
-        len = DomainNameLength(next);
-        bitmaplen = rr->rdlength - len;
-        bmap = (const mDNSu8 *)((const mDNSu8 *)next + len);
-
-        if (UNICAST_NSEC(rr))
-            length += mDNS_snprintf(buffer+length, RemSpc, "%##s ", next->c);
-        PrintTypeBitmap(bmap, bitmaplen, buffer, length);
-
-    }
-    break;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    case kDNSType_DNSKEY: {
-        // See <https://datatracker.ietf.org/doc/html/rfc4034#section-2.2> for DNSKEY RR Presentation Format.
-
-        dnssec_error_t err;
-        dnssec_obj_rr_dnskey_t dnskey = mDNSNULL;
-        char *dnskey_rdata_description = mDNSNULL;
-
-        dnskey = dnssec_obj_rr_dnskey_create(rr->name->c, rr->rrclass, rr->rdata->u.data, rr->rdlength, false, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR) {
-            goto dnskey_exit;
-        }
-
-        dnskey_rdata_description = dnssec_obj_rr_copy_rdata_rfc_description(dnskey, &err);
-        if (err != DNSSEC_ERROR_NO_ERROR) {
-            goto dnskey_exit;
-        }
-
-        mDNS_snprintf(buffer + length, RemSpc, "%s", dnskey_rdata_description);
-
-    dnskey_exit:
-        MDNS_DISPOSE_DNSSEC_OBJ(dnskey);
-        mDNSPlatformMemFree(dnskey_rdata_description);
-    }
-    break;
-#endif
-
-    default:            mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %.*s", rr->rdlength, rr->rdlength, rd->data);
-        // Really should scan buffer to check if text is valid UTF-8 and only replace with dots if not
-        for (ptr = buffer; *ptr; ptr++) if (*ptr < ' ') *ptr = '.';
-        break;
-    }
-
-    return(buffer);
-}
-
-// See comments in mDNSEmbeddedAPI.h
-#if _PLATFORM_HAS_STRONG_PRNG_
-#define mDNSRandomNumber mDNSPlatformRandomNumber
-#else
-mDNSlocal mDNSu32 mDNSRandomFromSeed(mDNSu32 seed)
-{
-    return seed * 21 + 1;
-}
-
-mDNSlocal mDNSu32 mDNSMixRandomSeed(mDNSu32 seed, mDNSu8 iteration)
-{
-    return iteration ? mDNSMixRandomSeed(mDNSRandomFromSeed(seed), --iteration) : seed;
-}
-
-mDNSlocal mDNSu32 mDNSRandomNumber()
-{
-    static mDNSBool seeded = mDNSfalse;
-    static mDNSu32 seed = 0;
-    if (!seeded)
-    {
-        seed = mDNSMixRandomSeed(mDNSPlatformRandomSeed(), 100);
-        seeded = mDNStrue;
-    }
-    return (seed = mDNSRandomFromSeed(seed));
-}
-#endif // ! _PLATFORM_HAS_STRONG_PRNG_
-
-mDNSexport mDNSu32 mDNSRandom(mDNSu32 max)      // Returns pseudo-random result from zero to max inclusive
-{
-    mDNSu32 ret = 0;
-    mDNSu32 mask = 1;
-
-    while (mask < max) mask = (mask << 1) | 1;
-
-    do ret = mDNSRandomNumber() & mask;
-    while (ret > max);
-
-    return ret;
-}
-
-mDNSexport mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2)
-{
-    if (ip1->type == ip2->type)
-    {
-        switch (ip1->type)
-        {
-        case mDNSAddrType_None: return(mDNStrue);      // Empty addresses have no data and are therefore always equal
-        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)(mDNSSameIPv4Address(ip->ip.v4, AllDNSLinkGroup_v4.ip.v4));
-    case mDNSAddrType_IPv6: return (mDNSBool)(mDNSSameIPv6Address(ip->ip.v6, AllDNSLinkGroup_v6.ip.v6));
-    default: return(mDNSfalse);
-    }
-}
-
-mDNSexport mDNSu32 GetEffectiveTTL(const uDNS_LLQType LLQType, mDNSu32 ttl)      // TTL in seconds
-{
-    if      (LLQType == uDNS_LLQ_Entire) ttl = kLLQ_DefLease;
-    else if (LLQType == uDNS_LLQ_Events)
-    {
-        // If the TTL is -1 for uDNS LLQ event packet, that means "remove"
-        if (ttl == 0xFFFFFFFF) ttl = 0;
-        else ttl = kLLQ_DefLease;
-    }
-    else    // else not LLQ (standard uDNS response)
-    {
-        // The TTL is already capped to a maximum value in GetLargeResourceRecord, but just to be extra safe we
-        // also do this check here to make sure we can't get overflow below when we add a quarter to the TTL
-        if (ttl > 0x60000000UL / mDNSPlatformOneSecond) ttl = 0x60000000UL / mDNSPlatformOneSecond;
-
-        ttl = RRAdjustTTL(ttl);
-
-        // For mDNS, TTL zero means "delete this record"
-        // For uDNS, TTL zero means: this data is true at this moment, but don't cache it.
-        // For the sake of network efficiency, we impose a minimum effective TTL of 15 seconds.
-        // This means that we'll do our 80, 85, 90, 95% queries at 12.00, 12.75, 13.50, 14.25 seconds
-        // respectively, and then if we get no response, delete the record from the cache at 15 seconds.
-        // This gives the server up to three seconds to respond between when we send our 80% query at 12 seconds
-        // and when we delete the record at 15 seconds. Allowing cache lifetimes less than 15 seconds would
-        // (with the current code) result in the server having even less than three seconds to respond
-        // before we deleted the record and reported a "remove" event to any active questions.
-        // Furthermore, with the current code, if we were to allow a TTL of less than 2 seconds
-        // then things really break (e.g. we end up making a negative cache entry).
-        // In the future we may want to revisit this and consider properly supporting non-cached (TTL=0) uDNS answers.
-        if (ttl < 15) ttl = 15;
-    }
-
-    return ttl;
-}
-
-// ***************************************************************************
-// MARK: - Domain Name Utility Functions
-
-
-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)
-{
-    return(SameDomainNameBytes(d1->c, d2->c));
-}
-
-mDNSexport mDNSBool SameDomainNameBytes(const mDNSu8 *const d1, const mDNSu8 *const d2)
-{
-    const mDNSu8 *      a   = d1;
-    const mDNSu8 *      b   = d2;
-    const mDNSu8 *const max = d1 + MAX_DOMAIN_NAME; // Maximum that's valid
-
-    while (*a || *b)
-    {
-        if (a + 1 + *a >= max)
-        { debugf("Malformed domain name (more than 256 characters)"); return(mDNSfalse); }
-        if (!SameDomainLabel(a, b)) return(mDNSfalse);
-        a += 1 + *a;
-        b += 1 + *b;
-    }
-
-    return(mDNStrue);
-}
-
-mDNSexport mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2)
-{
-    mDNSu16 l1 = DomainNameLength(d1);
-    mDNSu16 l2 = DomainNameLength(d2);
-    return(l1 <= MAX_DOMAIN_NAME && l1 == l2 && mDNSPlatformMemSame(d1, d2, l1));
-}
-
-mDNSexport mDNSBool IsSubdomain(const domainname *const subdomain, const domainname *const domain)
-{
-    mDNSBool isSubdomain = mDNSfalse;
-    const int subdomainLabelCount = CountLabels(subdomain);
-    const int domainLabelCount = CountLabels(domain);
-
-    if (subdomainLabelCount >= domainLabelCount)
-    {
-        const domainname *const parentDomain = SkipLeadingLabels(subdomain, subdomainLabelCount - domainLabelCount);
-        isSubdomain = SameDomainName(parentDomain, domain);
-    }
-
-    return isSubdomain;
-}
-
-mDNSexport mDNSBool IsLocalDomain(const domainname *d)
-{
-    // Domains that are defined to be resolved via link-local multicast are:
-    // local., 254.169.in-addr.arpa., and {8,9,A,B}.E.F.ip6.arpa.
-    static const domainname *nL = (const domainname*)"\x5" "local";
-    static const domainname *nR = (const domainname*)"\x3" "254" "\x3" "169"         "\x7" "in-addr" "\x4" "arpa";
-    static const domainname *n8 = (const domainname*)"\x1" "8"   "\x1" "e" "\x1" "f" "\x3" "ip6"     "\x4" "arpa";
-    static const domainname *n9 = (const domainname*)"\x1" "9"   "\x1" "e" "\x1" "f" "\x3" "ip6"     "\x4" "arpa";
-    static const domainname *nA = (const domainname*)"\x1" "a"   "\x1" "e" "\x1" "f" "\x3" "ip6"     "\x4" "arpa";
-    static const domainname *nB = (const domainname*)"\x1" "b"   "\x1" "e" "\x1" "f" "\x3" "ip6"     "\x4" "arpa";
-
-    const domainname *d1, *d2, *d3, *d4, *d5;   // Top-level domain, second-level domain, etc.
-    d1 = d2 = d3 = d4 = d5 = mDNSNULL;
-    while (d->c[0])
-    {
-        d5 = d4; d4 = d3; d3 = d2; d2 = d1; d1 = d;
-        d = (const domainname*)(d->c + 1 + d->c[0]);
-    }
-
-    if (d1 && SameDomainName(d1, nL)) return(mDNStrue);
-    if (d4 && SameDomainName(d4, nR)) return(mDNStrue);
-    if (d5 && SameDomainName(d5, n8)) return(mDNStrue);
-    if (d5 && SameDomainName(d5, n9)) return(mDNStrue);
-    if (d5 && SameDomainName(d5, nA)) return(mDNStrue);
-    if (d5 && SameDomainName(d5, nB)) return(mDNStrue);
-    return(mDNSfalse);
-}
-
-mDNSexport mDNSBool IsRootDomain(const domainname *const d)
-{
-    return (d->c[0] == 0);
-}
-
-mDNSexport const mDNSu8 *LastLabel(const domainname *d)
-{
-    const mDNSu8 *p = d->c;
-    while (d->c[0])
-    {
-        p = d->c;
-        d = (const domainname*)(d->c + 1 + d->c[0]);
-    }
-    return(p);
-}
-
-// Returns length of a domain name INCLUDING the byte for the final null label
-// e.g. 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 256 (MAX_DOMAIN_NAME)
-// If the given domainname is invalid, result is 257 (MAX_DOMAIN_NAME+1)
-mDNSexport mDNSu16 DomainNameLengthLimit(const domainname *const name, const mDNSu8 *const limit)
-{
-    return(DomainNameBytesLength(name->c, limit));
-}
-
-mDNSexport mDNSu16 DomainNameBytesLength(const mDNSu8 *const name, const mDNSu8 *const limit)
-{
-    const mDNSu8 *src = name;
-    while ((!limit || (src < limit)) && src && (*src <= MAX_DOMAIN_LABEL))
-    {
-        if (*src == 0) return((mDNSu16)(src - name + 1));
-        src += 1 + *src;
-    }
-    return(MAX_DOMAIN_NAME+1);
-}
-
-mDNSexport mDNSu8 DomainLabelLength(const domainlabel *const label)
-{
-    return label->c[0];
-}
-
-// CompressedDomainNameLength returns the length of a domain name INCLUDING the byte
-// for the final null label, e.g. 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).
-mDNSexport 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((const domainname *)src, parent)) return((mDNSu16)(src - name->c + 2));
-        src += 1 + *src;
-        if (src - name->c >= MAX_DOMAIN_NAME) return(MAX_DOMAIN_NAME+1);
-    }
-    return((mDNSu16)(src - name->c + 1));
-}
-
-// CountLabels() returns number of labels in name, excluding final root label
-// (e.g. for "apple.com." CountLabels returns 2.)
-mDNSexport int CountLabels(const domainname *d)
-{
-    int count = 0;
-    const mDNSu8 *ptr;
-    for (ptr = d->c; *ptr; ptr = ptr + ptr[0] + 1) count++;
-    return count;
-}
-
-// SkipLeadingLabels skips over the first 'skip' labels in the domainname,
-// returning a pointer to the suffix with 'skip' labels removed.
-mDNSexport const domainname *SkipLeadingLabels(const domainname *d, int skip)
-{
-    while (skip > 0 && d->c[0]) { d = (const domainname *)(d->c + 1 + d->c[0]); skip--; }
-    return(d);
-}
-
-// 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 256 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 256 bytes)
-// AppendDNSNameString returns mDNSNULL.
-mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstring)
-{
-    const char   *     cstr = cstring;
-    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)
-    if (cstr[0] == '.' && cstr[1] == '\0') cstr++;                  // If the domain to be appended is root domain, skip it.
-    while (*cstr && ptr < lim)                                      // While more characters, and space to put them...
-    {
-        mDNSu8 *lengthbyte = ptr++;                                 // Record where the length is going to go
-        if (*cstr == '.') { LogMsg("AppendDNSNameString: Illegal empty label in name \"%s\"", cstring); return(mDNSNULL); }
-        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 == '\0') break;                           // If this is the end of the string, then break
-                c = (mDNSu8)*cstr++;                                // Assume we'll just take the next character
-                if (mDNSIsDigit(cstr[-1]) && mDNSIsDigit(cstr[0]) && mDNSIsDigit(cstr[1]))
-                {                                                   // If three decimal digits,
-                    int v0 = cstr[-1] - '0';                        // then interpret as three-digit decimal
-                    int v1 = cstr[ 0] - '0';
-                    int v2 = cstr[ 1] - '0';
-                    int val = v0 * 100 + v1 * 10 + v2;
-                    if (val <= 255) { c = (mDNSu8)val; cstr += 2; } // If valid three-digit decimal 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 256 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 256 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
-}
-
-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 MAX_ESCAPED_DOMAIN_NAME (1009 bytes)
-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
-
-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]);
-}
-
-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;
-    const char *errormsg;
-
-    // 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 *s0 = type->c;
-        if (s0[0] && s0[0] < 0x40)      // If legal first label (at least one character, and no more than 63)
-        {
-            const mDNSu8 * s1 = s0 + 1 + s0[0];
-            if (s1[0] && s1[0] < 0x40)  // and legal second label (at least one character, and no more than 63)
-            {
-                const mDNSu8 *s2 = s1 + 1 + s1[0];
-                if (s2[0] && s2[0] < 0x40 && s2[1+s2[0]] == 0)  // and we have three and only three labels
-                {
-                    static const mDNSu8 SubTypeLabel[5] = mDNSSubTypeLabel;
-                    src = s0;                                   // Copy the first label
-                    len = *src;
-                    for (i=0; i <= len;                      i++) *dst++ = *src++;
-                    for (i=0; i < (int)sizeof(SubTypeLabel); i++) *dst++ = SubTypeLabel[i];
-                    type = (const domainname *)s1;
-
-                    // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
-                    // For these queries, we retract the "._sub" we just added between the subtype and the main type
-                    // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
-                    if (SameDomainName((const domainname*)s0, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
-                        dst -= sizeof(SubTypeLabel);
-                }
-            }
-        }
-    }
-
-    if (name && name->c[0])
-    {
-        src = name->c;                                  // Put the service name into the domain name
-        len = *src;
-        if (len >= 0x40) { errormsg = "Service instance name too long"; 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 > 16)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Bad service type in " PRI_DM_LABEL "." PRI_DM_NAME PRI_DM_NAME" Application protocol name must be "
-            "underscore plus 1-15 characters. See <http://www.dns-sd.org/ServiceTypes.html>",
-            DM_LABEL_PARAM(name), DM_NAME_PARAM(type), DM_NAME_PARAM(domain));
-    }
-    if (len < 2 || len >= 0x40 || (len > 16 && !SameDomainName(domain, &localdomain))) return(mDNSNULL);
-    if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; }
-    for (i=2; i<=len; i++)
-    {
-        // Letters and digits are allowed anywhere
-        if (mDNSIsLetter(src[i]) || mDNSIsDigit(src[i])) continue;
-        // Hyphens are only allowed as interior characters
-        // Underscores are not supposed to be allowed at all, but for backwards compatibility with some old products we do allow them,
-        // with the same rule as hyphens
-        if ((src[i] == '-' || src[i] == '_') && i > 2 && i < len)
-        {
-            continue;
-        }
-        errormsg = "Application protocol name must contain only letters, digits, and hyphens";
-        goto fail;
-    }
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    len = *src;
-    if (!ValidTransportProtocol(src)) { errormsg = "Transport protocol name must be _udp or _tcp"; goto fail; }
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    if (*src) { errormsg = "Service type must have only two labels"; goto fail; }
-
-    *dst = 0;
-    if (!domain->c[0]) { errormsg = "Service domain must be non-empty"; goto fail; }
-    if (SameDomainName(domain, (const domainname*)"\x05" "local" "\x04" "arpa"))
-    { errormsg = "Illegal domain \"local.arpa.\" Use \"local.\" (or empty string)"; goto fail; }
-    dst = AppendDomainName(fqdn, domain);
-    if (!dst) { errormsg = "Service domain too long"; goto fail; }
-    return(dst);
-
-fail:
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "ConstructServiceName: " PUB_S ": " PRI_DM_LABEL "." PRI_DM_NAME PRI_DM_NAME , errormsg,
-        DM_LABEL_PARAM(name), DM_NAME_PARAM(type), DM_NAME_PARAM(domain));
-    return(mDNSNULL);
-}
-
-// A service name has the form: instance.application-protocol.transport-protocol.domain
-// DeconstructServiceName is currently fairly forgiving: It doesn't try to enforce character
-// set or length limits for the protocol names, and the final domain is allowed to be empty.
-// However, if the given FQDN doesn't contain at least three labels,
-// DeconstructServiceName will reject it and return mDNSfalse.
-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
-    len = *src;
-    if (!len)         { debugf("DeconstructServiceName: FQDN empty!");                             return(mDNSfalse); }
-    if (len >= 0x40)  { debugf("DeconstructServiceName: Instance name too long");                  return(mDNSfalse); }
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    dst = type->c;                                      // Extract the service type
-    len = *src;
-    if (!len)         { debugf("DeconstructServiceName: FQDN contains only one label!");           return(mDNSfalse); }
-    if (len >= 0x40)  { debugf("DeconstructServiceName: Application protocol name too long");      return(mDNSfalse); }
-    if (src[1] != '_') { debugf("DeconstructServiceName: No _ at start of application protocol");   return(mDNSfalse); }
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    len = *src;
-    if (!len)         { debugf("DeconstructServiceName: FQDN contains only two labels!");          return(mDNSfalse); }
-    if (!ValidTransportProtocol(src))
-    { debugf("DeconstructServiceName: Transport protocol must be _udp or _tcp"); return(mDNSfalse); }
-    for (i=0; i<=len; i++) *dst++ = *src++;
-    *dst++ = 0;                                         // Put terminator on the end of service type
-
-    dst = domain->c;                                    // Extract the service domain
-    while (*src)
-    {
-        len = *src;
-        if (len >= 0x40)
-        { debugf("DeconstructServiceName: Label in service domain too long"); return(mDNSfalse); }
-        if (src + 1 + len + 1 >= max)
-        { debugf("DeconstructServiceName: Total 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);
-}
-
-mDNSexport mStatus DNSNameToLowerCase(domainname *d, domainname *result)
-{
-    const mDNSu8 *a = d->c;
-    mDNSu8 *b = result->c;
-    const mDNSu8 *const max = d->c + MAX_DOMAIN_NAME;
-    int i, len;
-
-    while (*a)
-    {
-        if (a + 1 + *a >= max)
-        {
-            LogMsg("DNSNameToLowerCase: ERROR!! Malformed Domain name");
-            return mStatus_BadParamErr;
-        }
-        len = *a++;
-        *b++ = len;
-        for (i = 0; i < len; i++)
-        {
-            mDNSu8 ac = *a++;
-            if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
-            *b++ = ac;
-        }
-    }
-    *b = 0;
-
-    return mStatus_NoError;
-}
-
-// Notes on UTF-8:
-// 0xxxxxxx represents a 7-bit ASCII value from 0x00 to 0x7F
-// 10xxxxxx is a continuation byte of a multi-byte character
-// 110xxxxx is the first byte of a 2-byte character (11 effective bits; values 0x     80 - 0x     800-1)
-// 1110xxxx is the first byte of a 3-byte character (16 effective bits; values 0x    800 - 0x   10000-1)
-// 11110xxx is the first byte of a 4-byte character (21 effective bits; values 0x  10000 - 0x  200000-1)
-// 111110xx is the first byte of a 5-byte character (26 effective bits; values 0x 200000 - 0x 4000000-1)
-// 1111110x is the first byte of a 6-byte character (31 effective bits; values 0x4000000 - 0x80000000-1)
-//
-// UTF-16 surrogate pairs are used in UTF-16 to encode values larger than 0xFFFF.
-// Although UTF-16 surrogate pairs are not supposed to appear in legal UTF-8, we want to be defensive
-// about that too. (See <http://www.unicode.org/faq/utf_bom.html#34>, "What are surrogates?")
-// The first of pair is a UTF-16 value in the range 0xD800-0xDBFF (11101101 1010xxxx 10xxxxxx in UTF-8),
-// and the second    is a UTF-16 value in the range 0xDC00-0xDFFF (11101101 1011xxxx 10xxxxxx in UTF-8).
-
-mDNSexport mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max)
-{
-    if (length > max)
-    {
-        mDNSu8 c1 = string[max];                                        // First byte after cut point
-        mDNSu8 c2 = (max+1 < length) ? string[max+1] : (mDNSu8)0xB0;    // Second byte after cut point
-        length = max;   // Trim length down
-        while (length > 0)
-        {
-            // Check if the byte right after the chop point is a UTF-8 continuation byte,
-            // or if the character right after the chop point is the second of a UTF-16 surrogate pair.
-            // If so, then we continue to chop more bytes until we get to a legal chop point.
-            mDNSBool continuation    = ((c1 & 0xC0) == 0x80);
-            mDNSBool secondsurrogate = (c1 == 0xED && (c2 & 0xF0) == 0xB0);
-            if (!continuation && !secondsurrogate) break;
-            c2 = c1;
-            c1 = string[--length];
-        }
-        // Having truncated characters off the end of our string, also cut off any residual white space
-        while (length > 0 && string[length-1] <= ' ') length--;
-    }
-    return(length);
-}
-
-// 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.
-mDNSexport 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.
-mDNSexport 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).
-mDNSexport void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText)
-{
-    mDNSu32 divisor = 1, chars = 2; // Shortest possible RFC1034 name suffix is 2 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 (divisor < 0xFFFFFFFFUL/10 && val >= divisor * 10) { divisor *= 10; chars++; }
-
-    name->c[0] = (mDNSu8) TruncateUTF8ToLength(name->c+1, name->c[0], MAX_DOMAIN_LABEL - chars);
-
-    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);
-}
-
-// ***************************************************************************
-// MARK: - Resource Record Utility Functions
-
-// 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, AuthRecType artype, mDNSRecordCallback Callback, void *Context)
-{
-    //
-    // LocalOnly auth record can be created with LocalOnly InterfaceID or a valid InterfaceID.
-    // Most of the applications normally create with LocalOnly InterfaceID and we store them as
-    // such, so that we can deliver the response to questions that specify LocalOnly InterfaceID.
-    // LocalOnly resource records can also be created with valid InterfaceID which happens today
-    // when we create LocalOnly records for /etc/hosts.
-
-    if (InterfaceID == mDNSInterface_LocalOnly && artype != AuthRecordLocalOnly)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_SetupResourceRecord: ERROR!! Mismatch LocalOnly record InterfaceID %p called with artype %d",
-            InterfaceID, artype);
-    }
-    else if (InterfaceID == mDNSInterface_P2P && artype != AuthRecordP2P)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_SetupResourceRecord: ERROR!! Mismatch P2P record InterfaceID %p called with artype %d",
-            InterfaceID, artype);
-    }
-    else if (!InterfaceID && (artype == AuthRecordP2P || artype == AuthRecordLocalOnly))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_SetupResourceRecord: ERROR!! Mismatch InterfaceAny record InterfaceID %p called with artype %d",
-            InterfaceID, artype);
-    }
-
-    // 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 = DefaultTTLforRRType(rrtype);
-
-    // Field Group 1: The actual information pertaining to this resource record
-    rr->resrec.RecordType        = RecordType;
-    rr->resrec.InterfaceID       = InterfaceID;
-    rr->resrec.name              = &rr->namestorage;
-    rr->resrec.rrtype            = rrtype;
-    rr->resrec.rrclass           = kDNSClass_IN;
-    rr->resrec.rroriginalttl     = ttl;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    rr->resrec.dnsservice        = NULL;
-#else
-    rr->resrec.rDNSServer        = mDNSNULL;
-#endif
-//	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);
-    }
-
-    // Field Group 2: Persistent metadata for Authoritative Records
-    rr->Additional1       = mDNSNULL;
-    rr->Additional2       = mDNSNULL;
-    rr->DependentOn       = mDNSNULL;
-    rr->RRSet             = 0;
-    rr->RecordCallback    = Callback;
-    rr->RecordContext     = Context;
-
-    rr->AutoTarget        = Target_Manual;
-    rr->AllowRemoteQuery  = mDNSfalse;
-    rr->ForceMCast        = mDNSfalse;
-
-    rr->WakeUp            = zeroOwner;
-    rr->AddressProxy      = zeroAddr;
-    rr->TimeRcvd          = 0;
-    rr->TimeExpire        = 0;
-    rr->ARType            = artype;
-    rr->AuthFlags         = 0;
-
-    // Field Group 3: Transient state for Authoritative Records (set in mDNS_Register_internal)
-    // Field Group 4: Transient uDNS state for Authoritative Records (set in mDNS_Register_internal)
-
-    // For now, until the uDNS code is fully integrated, it's helpful to zero the uDNS state fields here too, just in case
-    // (e.g. uDNS_RegisterService short-circuits the usual mDNS_Register_internal record registration calls, so a bunch
-    // of fields don't get set up properly. In particular, if we don't zero rr->QueuedRData then the uDNS code crashes.)
-    rr->state             = regState_Zero;
-    rr->uselease          = 0;
-    rr->expire            = 0;
-    rr->Private           = 0;
-    rr->updateid          = zeroID;
-    rr->zone              = rr->resrec.name;
-    rr->nta               = mDNSNULL;
-    rr->tcp               = mDNSNULL;
-    rr->OrigRData         = 0;
-    rr->OrigRDLen         = 0;
-    rr->InFlightRData     = 0;
-    rr->InFlightRDLen     = 0;
-    rr->QueuedRData       = 0;
-    rr->QueuedRDLen       = 0;
-    mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
-    rr->SRVChanged = mDNSfalse;
-    rr->mState = mergeState_Zero;
-
-    rr->namestorage.c[0]  = 0;      // MUST be set by client before calling mDNS_Register()
-}
-
-mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
-                                   const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context)
-{
-    q->InterfaceID         = InterfaceID;
-    q->flags               = 0;
-    AssignDomainName(&q->qname, name);
-    q->qtype               = qtype;
-    q->qclass              = kDNSClass_IN;
-    q->LongLived           = mDNSfalse;
-    q->ExpectUnique        = (qtype != kDNSType_PTR);
-    q->ForceMCast          = mDNSfalse;
-    q->ReturnIntermed      = mDNSfalse;
-    q->SuppressUnusable    = mDNSfalse;
-    q->AppendSearchDomains = 0;
-    q->TimeoutQuestion     = 0;
-    q->WakeOnResolve       = 0;
-    q->UseBackgroundTraffic = mDNSfalse;
-    q->ProxyQuestion       = 0;
-    q->pid                 = mDNSPlatformGetPID();
-    q->euid                = 0;
-    q->BlockedByPolicy     = mDNSfalse;
-    q->ServiceID           = -1;
-    q->QuestionCallback    = callback;
-    q->QuestionContext     = context;
-}
-
-mDNSexport mDNSu32 RDataHashValue(const ResourceRecord *const rr)
-{
-    int len = rr->rdlength;
-    const RDataBody2 *const rdb = (RDataBody2 *)rr->rdata->u.data;
-    const mDNSu8 *ptr = rdb->data;
-    mDNSu32 sum = 0;
-
-    switch(rr->rrtype)
-    {
-    case kDNSType_NS:
-    case kDNSType_MD:
-    case kDNSType_MF:
-    case kDNSType_CNAME:
-    case kDNSType_MB:
-    case kDNSType_MG:
-    case kDNSType_MR:
-    case kDNSType_PTR:
-    case kDNSType_NSAP_PTR:
-    case kDNSType_DNAME: return DomainNameHashValue(&rdb->name);
-
-    case kDNSType_SOA:   return rdb->soa.serial  +
-               rdb->soa.refresh +
-               rdb->soa.retry   +
-               rdb->soa.expire  +
-               rdb->soa.min     +
-               DomainNameHashValue(&rdb->soa.mname) +
-               DomainNameHashValue(&rdb->soa.rname);
-
-    case kDNSType_MX:
-    case kDNSType_AFSDB:
-    case kDNSType_RT:
-    case kDNSType_KX:    return DomainNameHashValue(&rdb->mx.exchange);
-
-    case kDNSType_MINFO:
-    case kDNSType_RP:    return DomainNameHashValue(&rdb->rp.mbox)   + DomainNameHashValue(&rdb->rp.txt);
-
-    case kDNSType_PX:    return DomainNameHashValue(&rdb->px.map822) + DomainNameHashValue(&rdb->px.mapx400);
-
-    case kDNSType_SRV:   return DomainNameHashValue(&rdb->srv.target);
-
-    case kDNSType_OPT:   return 0;      // OPT is a pseudo-RR container structure; makes no sense to compare
-
-    case kDNSType_NSEC: {
-        int dlen;
-        dlen = DomainNameLength(&rdb->name);
-        sum = DomainNameHashValue(&rdb->name);
-        ptr += dlen;
-        len -= dlen;
-        fallthrough();
-        /* FALLTHROUGH */
-    }
-
-    default:
-    {
-        int i;
-        for (i=0; i+1 < len; i+=2)
-        {
-            sum += (((mDNSu32)(ptr[i])) << 8) | ptr[i+1];
-            sum = (sum<<3) | (sum>>29);
-        }
-        if (i < len)
-        {
-            sum += ((mDNSu32)(ptr[i])) << 8;
-        }
-        return(sum);
-    }
-    }
-}
-
-// r1 has to be a full ResourceRecord including rrtype and rdlength
-// r2 is just a bare RDataBody, which MUST be the same rrtype and rdlength as r1
-mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename)
-{
-    const RDataBody2 *const b1 = (RDataBody2 *)r1->rdata->u.data;
-    const RDataBody2 *const b2 = (const RDataBody2 *)r2;
-    switch(r1->rrtype)
-    {
-    case kDNSType_NS:
-    case kDNSType_MD:
-    case kDNSType_MF:
-    case kDNSType_CNAME:
-    case kDNSType_MB:
-    case kDNSType_MG:
-    case kDNSType_MR:
-    case kDNSType_PTR:
-    case kDNSType_NSAP_PTR:
-    case kDNSType_DNAME: return(SameDomainName(&b1->name, &b2->name));
-
-    case kDNSType_SOA:  return (mDNSBool)(   b1->soa.serial   == b2->soa.serial             &&
-                                             b1->soa.refresh  == b2->soa.refresh            &&
-                                             b1->soa.retry    == b2->soa.retry              &&
-                                             b1->soa.expire   == b2->soa.expire             &&
-                                             b1->soa.min      == b2->soa.min                &&
-                                             samename(&b1->soa.mname, &b2->soa.mname) &&
-                                             samename(&b1->soa.rname, &b2->soa.rname));
-
-    case kDNSType_MX:
-    case kDNSType_AFSDB:
-    case kDNSType_RT:
-    case kDNSType_KX:   return (mDNSBool)(   b1->mx.preference == b2->mx.preference &&
-                                             samename(&b1->mx.exchange, &b2->mx.exchange));
-
-    case kDNSType_MINFO:
-    case kDNSType_RP:   return (mDNSBool)(   samename(&b1->rp.mbox, &b2->rp.mbox) &&
-                                             samename(&b1->rp.txt,  &b2->rp.txt));
-
-    case kDNSType_PX:   return (mDNSBool)(   b1->px.preference == b2->px.preference          &&
-                                             samename(&b1->px.map822,  &b2->px.map822) &&
-                                             samename(&b1->px.mapx400, &b2->px.mapx400));
-
-    case kDNSType_SRV:  return (mDNSBool)(   b1->srv.priority == b2->srv.priority       &&
-                                             b1->srv.weight   == b2->srv.weight         &&
-                                             mDNSSameIPPort(b1->srv.port, b2->srv.port) &&
-                                             samename(&b1->srv.target, &b2->srv.target));
-
-    case kDNSType_OPT:  return mDNSfalse;       // OPT is a pseudo-RR container structure; makes no sense to compare
-    case kDNSType_NSEC: {
-        // If the "nxt" name changes in case, we want to delete the old
-        // and store just the new one. If the caller passes in SameDomainCS for "samename",
-        // we would return "false" when the only change between the two rdata is the case
-        // change in "nxt".
-        //
-        // Note: rdlength of both the RData are same (ensured by the caller) and hence we can
-        // use just r1->rdlength below
-
-        int dlen1 = DomainNameLength(&b1->name);
-        int dlen2 = DomainNameLength(&b2->name);
-        return (mDNSBool)(dlen1 == dlen2 &&
-                          samename(&b1->name, &b2->name) &&
-                          mDNSPlatformMemSame(b1->data + dlen1, b2->data + dlen2, r1->rdlength - dlen1));
-    }
-
-    default:            return(mDNSPlatformMemSame(b1->data, b2->data, r1->rdlength));
-    }
-}
-
-mDNSexport mDNSBool BitmapTypeCheck(const mDNSu8 *bmap, int bitmaplen, mDNSu16 type)
-{
-    int win, wlen;
-    int wintype;
-
-    // The window that this type belongs to. NSEC has 256 windows that
-    // comprises of 256 types.
-    wintype = type >> 8;
-
-    while (bitmaplen > 0)
-    {
-        if (bitmaplen < 3)
-        {
-            LogInfo("BitmapTypeCheck: malformed nsec, bitmaplen %d short", bitmaplen);
-            return mDNSfalse;
-        }
-
-        win = *bmap++;
-        wlen = *bmap++;
-        bitmaplen -= 2;
-        if (bitmaplen < wlen || wlen < 1 || wlen > 32)
-        {
-            LogInfo("BitmapTypeCheck: malformed nsec, bitmaplen %d wlen %d, win %d", bitmaplen, wlen, win);
-            return mDNSfalse;
-        }
-        if (win < 0 || win >= 256)
-        {
-            LogInfo("BitmapTypeCheck: malformed nsec, wlen %d", wlen);
-            return mDNSfalse;
-        }
-        if (win == wintype)
-        {
-            // First byte in the window serves 0 to 7, the next one serves 8 to 15 and so on.
-            // Calculate the right byte offset first.
-            int boff = (type & 0xff ) >> 3;
-            if (wlen <= boff)
-                return mDNSfalse;
-            // The last three bits values 0 to 7 corresponds to bit positions
-            // within the byte.
-            return (bmap[boff] & (0x80 >> (type & 7)));
-        }
-        else
-        {
-            // If the windows are ordered, then we could check to see
-            // if wintype > win and then return early.
-            bmap += wlen;
-            bitmaplen -= wlen;
-        }
-    }
-    return mDNSfalse;
-}
-
-// Don't call this function if the resource record is not NSEC. It will return false
-// which means that the type does not exist.
-mDNSexport mDNSBool RRAssertsExistence(const ResourceRecord *const rr, mDNSu16 type)
-{
-    const RDataBody2 *const rdb = (RDataBody2 *)rr->rdata->u.data;
-    const mDNSu8 *nsec = rdb->data;
-    int len, bitmaplen;
-    const mDNSu8 *bmap;
-
-    if (rr->rrtype != kDNSType_NSEC) return mDNSfalse;
-
-    len = DomainNameLength(&rdb->name);
-
-    bitmaplen = rr->rdlength - len;
-    bmap = nsec + len;
-    return (BitmapTypeCheck(bmap, bitmaplen, type));
-}
-
-// Don't call this function if the resource record is not NSEC. It will return false
-// which means that the type exists.
-mDNSexport mDNSBool RRAssertsNonexistence(const ResourceRecord *const rr, mDNSu16 type)
-{
-    if (rr->rrtype != kDNSType_NSEC) return mDNSfalse;
-
-    return !RRAssertsExistence(rr, type);
-}
-
-mDNSexport mDNSBool RRTypeAnswersQuestionType(const ResourceRecord *const rr, const mDNSu16 qtype,
-    const RRTypeAnswersQuestionTypeFlags flags)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // This checks if the record is what the question requires:
-    // 1. If the question does not enable DNSSEC, either "DNSSEC to be validated" nor "DNSSEC validated" record answers it.
-    // 2. If the question enables DNSSEC, and it is not a duplicate question, it needs both "DNSSEC to be validated" nor "DNSSEC validated" records:
-    //    a. Get "DNSSEC to be validated" to do DNSSEC validation.
-    //    b. Get "DNSSEC validated" to return to the client.
-    // 3. If the question enables DNSSEC, and it is a duplicate question, it only needs "DNSSEC validated" records:
-    //    a. Does not need "DNSSEC to be validated" because the non-duplicate question will do the validation.
-    //    b. Get "DNSSEC validated" to return to the client.
-    const mDNSBool requiresRRToValidate = ((flags & kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate) != 0);
-    const mDNSBool requiresValidatedRR = ((flags & kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRValidated) != 0);
-    if (!resource_record_answers_dnssec_question_request_type(rr, requiresRRToValidate, requiresValidatedRR))
-    {
-        return mDNSfalse;
-    }
-#else
-    (void) flags;
-#endif
-
-    // TSR should not answer any questions.
-    if (rr->rrtype == kDNSType_TSR)
-    {
-        return mDNSfalse;
-    }
-
-    // CNAME answers any questions, except negative CNAME. (this function is not responsible to check that)
-    if (rr->rrtype == kDNSType_CNAME)
-    {
-        return mDNStrue;
-    }
-
-    // The most usual case where the record type matches the question type.
-    if (rr->rrtype == qtype)
-    {
-        return mDNStrue;
-    }
-
-    // If question asks for any DNS record type, then any record type can answer this question.
-    if (qtype == kDNSQType_ANY)
-    {
-        return mDNStrue;
-    }
-
-    // If the mDNS NSEC record asserts the nonexistence of the question type, then it answers the question type
-    // negatively.
-    if (MULTICAST_NSEC(rr) && RRAssertsNonexistence(rr, qtype))
-    {
-        return mDNStrue;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // The type covered of RRSIG should match the non-duplicate DNSSEC question type, because RRSIG will be used by it
-    // to do DNSSEC validation.
-    if (resource_record_as_rrsig_answers_dnssec_question_type(rr, qtype))
-    {
-        return mDNStrue;
-    }
-#endif
-
-    return mDNSfalse;
-}
-
-// ResourceRecordAnswersQuestion returns mDNStrue if the given resource record is a valid answer to the given question.
-// SameNameRecordAnswersQuestion is the same, except it skips the expensive SameDomainName() call.
-// SameDomainName() is generally cheap when the names don't match, but expensive when they do match,
-// because it has to check all the way to the end of the names to be sure.
-// In cases where we know in advance that the names match it's especially advantageous to skip the
-// SameDomainName() call because that's precisely the time when it's most expensive and least useful.
-
-mDNSlocal mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, mDNSBool isAuthRecord, const DNSQuestion *const q)
-{
-    // LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records
-    // are handled in LocalOnlyRecordAnswersQuestion
-    if (LocalOnlyOrP2PInterface(rr->InterfaceID))
-    {
-        LogMsg("SameNameRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
-        return mDNSfalse;
-    }
-    if (q->Suppressed)
-        return mDNSfalse;
-
-    if (rr->InterfaceID &&
-        q->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
-        rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
-
-    // Resource record received via unicast, the resolver group ID should match ?
-    if (!isAuthRecord && !rr->InterfaceID)
-    {
-        if (mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (rr->dnsservice != q->dnsservice) return(mDNSfalse);
-#else
-        const mDNSu32 idr = rr->rDNSServer ? rr->rDNSServer->resGroupID : 0;
-        const mDNSu32 idq = q->qDNSServer ? q->qDNSServer->resGroupID : 0;
-        if (idr != idq) return(mDNSfalse);
-#endif
-    }
-
-    // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question
-    if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
-
-    // CNAME answers question of any type and a negative cache record should not prevent us from querying other
-    // valid types at the same name.
-    if (rr->rrtype == kDNSType_CNAME && rr->RecordType == kDNSRecordTypePacketNegative && rr->rrtype != q->qtype)
-         return mDNSfalse;
-
-    // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-    RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Primary DNSSEC requestor is the non-duplicate DNSSEC question that does the DNSSEC validation, therefore, it needs
-    // the "DNSSEC to be validated" record. (It is also DNSSEC requestor, see below)
-    if (dns_question_is_primary_dnssec_requestor(q))
-    {
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-    }
-    // DNSSEC requestor is the DNSSEC question that needs DNSSEC validated result.
-    if (dns_question_is_dnssec_requestor(q))
-    {
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRValidated;
-    }
-#endif
-
-    const mDNSBool typeMatches = RRTypeAnswersQuestionType(rr, q->qtype, flags);
-    if (!typeMatches)
-    {
-        return(mDNSfalse);
-    }
-
-    if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
-
-
-    return(mDNStrue);
-}
-
-mDNSexport mDNSBool SameNameCacheRecordAnswersQuestion(const CacheRecord *const cr, const DNSQuestion *const q)
-{
-    return SameNameRecordAnswersQuestion(&cr->resrec, mDNSfalse, q);
-}
-
-mDNSlocal mDNSBool RecordAnswersQuestion(const ResourceRecord *const rr, mDNSBool isAuthRecord, const DNSQuestion *const q)
-{
-    if (!SameNameRecordAnswersQuestion(rr, isAuthRecord, q))
-        return mDNSfalse;
-
-    return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
-}
-
-mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
-{
-    return RecordAnswersQuestion(rr, mDNSfalse, q);
-}
-
-mDNSexport mDNSBool AuthRecordAnswersQuestion(const AuthRecord *const ar, const DNSQuestion *const q)
-{
-    return RecordAnswersQuestion(&ar->resrec, mDNStrue, q);
-}
-
-mDNSexport mDNSBool CacheRecordAnswersQuestion(const CacheRecord *const cr, const DNSQuestion *const q)
-{
-    return RecordAnswersQuestion(&cr->resrec, mDNSfalse, q);
-}
-
-// We have a separate function to handle LocalOnly AuthRecords because they can be created with
-// a valid InterfaceID (e.g., scoped /etc/hosts) and can be used to answer unicast questions unlike
-// multicast resource records (which has a valid InterfaceID) which can't be used to answer
-// unicast questions. ResourceRecordAnswersQuestion/SameNameRecordAnswersQuestion can't tell whether
-// a resource record is multicast or LocalOnly by just looking at the ResourceRecord because
-// LocalOnly records are truly identified by ARType in the AuthRecord.  As P2P and LocalOnly record
-// are kept in the same hash table, we use the same function to make it easy for the callers when
-// they walk the hash table to answer LocalOnly/P2P questions
-//
-mDNSexport mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const ar, const DNSQuestion *const q)
-{
-    ResourceRecord *rr = &ar->resrec;
-
-    // mDNSInterface_Any questions can be answered with LocalOnly/P2P records in this function. AuthRecord_Any
-    // records are handled in ResourceRecordAnswersQuestion/SameNameRecordAnswersQuestion
-    if (RRAny(ar))
-    {
-        LogMsg("LocalOnlyRecordAnswersQuestion: ERROR!! called with regular AuthRecordAny %##s", rr->name->c);
-        return mDNSfalse;
-    }
-
-    // Questions with mDNSInterface_LocalOnly InterfaceID should be answered with all resource records that are
-    // *local* to the machine. These include resource records that have InterfaceID set to mDNSInterface_LocalOnly,
-    // mDNSInterface_Any and any other real InterfaceID. Hence, LocalOnly questions should not be checked against
-    // the InterfaceID in the resource record.
-
-    if (rr->InterfaceID &&
-        q->InterfaceID != mDNSInterface_LocalOnly &&
-        ((q->InterfaceID && rr->InterfaceID != q->InterfaceID) ||
-        (!q->InterfaceID && !LocalOnlyOrP2PInterface(rr->InterfaceID)))) return(mDNSfalse);
-
-    // Entries in /etc/hosts are added as LocalOnly resource records. The LocalOnly resource records
-    // may have a scope e.g., fe80::1%en0. The question may be scoped or not: the InterfaceID may be set
-    // to mDNSInterface_Any, mDNSInterface_LocalOnly or a real InterfaceID (scoped).
-    //
-    // 1) Question: Any, LocalOnly Record: no scope. This question should be answered with this record.
-    //
-    // 2) Question: Any, LocalOnly Record: scoped.  This question should be answered with the record because
-    //    traditionally applications never specify scope e.g., getaddrinfo, but need to be able
-    //    to get to /etc/hosts entries.
-    //
-    // 3) Question: Scoped (LocalOnly or InterfaceID), LocalOnly Record: no scope. This is the inverse of (2).
-    //    If we register a LocalOnly record, we need to answer a LocalOnly question. If the /etc/hosts has a
-    //    non scoped entry, it may not make sense to answer a scoped question. But we can't tell these two
-    //    cases apart. As we currently answer LocalOnly question with LocalOnly record, we continue to do so.
-    //
-    // 4) Question: Scoped (LocalOnly or InterfaceID), LocalOnly Record: scoped. LocalOnly questions should be
-    //    answered with any resource record where as if it has a valid InterfaceID, the scope should match.
-    //
-    // (1) and (2) is bypassed because we check for a non-NULL InterfaceID above. For (3), the InterfaceID is NULL
-    // and hence bypassed above. For (4) we bypassed LocalOnly questions and checked the scope of the record
-    // against the question.
-    //
-    // For P2P, InterfaceIDs of the question and the record should match.
-
-    // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
-    // LocalOnly authoritative answers are exempt. LocalOnly authoritative answers are used for /etc/host entries.
-    // We don't want a local process to be able to create a fake LocalOnly address record for "www.bigbank.com" which would then
-    // cause other applications (e.g. Safari) to connect to the wrong address. The rpc to register records filters out records
-    // with names that don't end in local and have mDNSInterface_LocalOnly set.
-    //
-    // Note: The check is bypassed for LocalOnly and for P2P it is not needed as only .local records are registered and for
-    // a question to match its names, it also has to end in .local and that question can't be a unicast question (See
-    // Question_uDNS macro and its usage). As P2P does not enforce .local only registrations we still make this check
-    // and also makes it future proof.
-
-    if (ar->ARType != AuthRecordLocalOnly && rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // No local only record can answer DNSSEC question.
-    if (dns_question_is_dnssec_requestor(q))
-    {
-        return mDNSfalse;
-    }
-#endif
-
-    // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-    RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-    const mDNSBool typeMatches = RRTypeAnswersQuestionType(rr, q->qtype, flags);
-    if (!typeMatches)
-    {
-        return mDNSfalse;
-    }
-
-    if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
-
-    return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
-}
-
-mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const AuthRecord *const ar, const DNSQuestion *const q)
-{
-    const ResourceRecord *const rr = &ar->resrec;
-    // LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records
-    // are handled in LocalOnlyRecordAnswersQuestion
-    if (LocalOnlyOrP2PInterface(rr->InterfaceID))
-    {
-        LogMsg("AnyTypeRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
-        return mDNSfalse;
-    }
-    if (rr->InterfaceID &&
-        q->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
-        rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
-
-    // Resource record received via unicast, the resolver group ID should match ?
-    // Note that Auth Records are normally setup with NULL InterfaceID and
-    // both the DNSServers are assumed to be NULL in that case
-    if (!rr->InterfaceID)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (rr->dnsservice != q->dnsservice) return(mDNSfalse);
-#else
-        const mDNSu32 idr = rr->rDNSServer ? rr->rDNSServer->resGroupID : 0;
-        const mDNSu32 idq = q->qDNSServer ? q->qDNSServer->resGroupID : 0;
-        if (idr != idq) return(mDNSfalse);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        if (!mDNSPlatformValidRecordForInterface(ar, q->InterfaceID)) return(mDNSfalse);
-#endif
-    }
-
-    // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question
-    if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
-
-    if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
-
-    return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
-}
-
-// This is called with both unicast resource record and multicast resource record. The question that
-// received the unicast response could be the regular unicast response from a DNS server or a response
-// to a mDNS QU query. The main reason we need this function is that we can't compare DNSServers between the
-// question and the resource record because the resource record is not completely initialized in
-// mDNSCoreReceiveResponse when this function is called.
-mDNSexport mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q)
-{
-    if (q->Suppressed)
-        return mDNSfalse;
-
-    // For resource records created using multicast, the InterfaceIDs have to match
-    if (rr->InterfaceID &&
-        q->InterfaceID && rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
-
-    // If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
-    if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
-
-    // RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-    RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Thus routine is only used for the records received from internet. Right now, we will not receive DNSSEC validated
-    // record from wire (ODoH will probably give us validated records in the future?). Therefore, we only need to check
-    // if the record answers primary DNSSEC requestor and can be used for validation.
-    if (dns_question_is_primary_dnssec_requestor(q))
-    {
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-    }
-#endif
-
-    const mDNSBool typeMatches = RRTypeAnswersQuestionType(rr, q->qtype, flags);
-    if (!typeMatches)
-    {
-        return(mDNSfalse);
-    }
-
-    if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
-
-    return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
-}
-
-mDNSexport mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate)
-{
-    const RDataBody2 *const rd = (RDataBody2 *)rr->rdata->u.data;
-    const domainname *const name = estimate ? rr->name : mDNSNULL;
-    if (rr->rrclass == kDNSQClass_ANY) return(rr->rdlength);    // Used in update packets to mean "Delete An RRset" (RFC 2136)
-    else switch (rr->rrtype)
-        {
-        case kDNSType_A:    return(sizeof(rd->ipv4));
-
-        case kDNSType_NS:
-        case kDNSType_CNAME:
-        case kDNSType_PTR:
-        case kDNSType_DNAME: return(CompressedDomainNameLength(&rd->name, name));
-
-        case kDNSType_SOA:  return (mDNSu16)(CompressedDomainNameLength(&rd->soa.mname, name) +
-                                             CompressedDomainNameLength(&rd->soa.rname, name) +
-                                             5 * sizeof(mDNSOpaque32));
-
-        case kDNSType_NULL:
-        case kDNSType_TSIG:
-        case kDNSType_TXT:
-        case kDNSType_X25:
-        case kDNSType_ISDN:
-        case kDNSType_LOC:
-        case kDNSType_DHCID: return(rr->rdlength); // Not self-describing, so have to just trust rdlength
-
-        case kDNSType_HINFO: return (mDNSu16)(2 + (int)rd->data[0] + (int)rd->data[1 + (int)rd->data[0]]);
-
-        case kDNSType_MX:
-        case kDNSType_AFSDB:
-        case kDNSType_RT:
-        case kDNSType_KX:   return (mDNSu16)(2 + CompressedDomainNameLength(&rd->mx.exchange, name));
-
-        case kDNSType_MINFO:
-        case kDNSType_RP:   return (mDNSu16)(CompressedDomainNameLength(&rd->rp.mbox, name) +
-                                             CompressedDomainNameLength(&rd->rp.txt, name));
-
-        case kDNSType_PX:   return (mDNSu16)(2 + CompressedDomainNameLength(&rd->px.map822, name) +
-                                             CompressedDomainNameLength(&rd->px.mapx400, name));
-
-        case kDNSType_AAAA: return(sizeof(rd->ipv6));
-
-        case kDNSType_SRV:  return (mDNSu16)(6 + CompressedDomainNameLength(&rd->srv.target, name));
-
-        case kDNSType_OPT:  return(rr->rdlength);
-
-        case kDNSType_NSEC:
-        {
-            const domainname *const next = (const domainname *)rd->data;
-            const int dlen = DomainNameLength(next);
-            if (MULTICAST_NSEC(rr))
-            {
-                return (mDNSu16)((estimate ? 2 : dlen) + rr->rdlength - dlen);
-            }
-            else
-            {
-                // Unicast NSEC does not do name compression. Therefore, we can return `rdlength` directly.
-                // See [RFC 4034 4.1.1.](https://datatracker.ietf.org/doc/html/rfc4034#section-4.1.1).
-                return rr->rdlength;
-            }
-        }
-
-        case kDNSType_TSR: return(sizeof(rd->tsr_value));
-
-        default:            debugf("Warning! Don't know how to get length of resource type %d", rr->rrtype);
-            return(rr->rdlength);
-        }
-}
-
-// When a local client registers (or updates) a record, we use this routine to do some simple validation checks
-// to help reduce the risk of bogus malformed data on the network
-mDNSexport 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 = DomainNameLengthLimit(&rd->u.name, rd->u.data + rdlength);
-        return(len <= MAX_DOMAIN_NAME && rdlength == len);
-
-    case kDNSType_HINFO:    // Same as TXT (roughly)
-    case kDNSType_MINFO:    // Same as TXT (roughly)
-    case kDNSType_TXT:  if (!rdlength) return(mDNSfalse);     // TXT record has to be at least one byte (RFC 1035)
-        {
-            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:       // Must be at least two-byte preference, plus domainname
-                            // Call to DomainNameLengthLimit() implicitly enforces both requirements for us
-        len = DomainNameLengthLimit(&rd->u.mx.exchange, rd->u.data + rdlength);
-        return(len <= MAX_DOMAIN_NAME && rdlength == 2+len);
-
-    case kDNSType_SRV:      // Must be at least priority+weight+port, plus domainname
-                            // Call to DomainNameLengthLimit() implicitly enforces both requirements for us
-        len = DomainNameLengthLimit(&rd->u.srv.target, rd->u.data + rdlength);
-        return(len <= MAX_DOMAIN_NAME && rdlength == 6+len);
-
-    //case kDNSType_NSEC not checked
-
-    default:            return(mDNStrue);       // Allow all other types without checking
-    }
-}
-
-// ***************************************************************************
-// MARK: - DNS Message Creation Functions
-
-mDNSexport 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;
-}
-
-#endif // !STANDALONE
-
-mDNSexport 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);
-}
-
-// 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
-mDNSexport 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;
-
-    if (!ptr) { LogMsg("putDomainNameAsLabels %##s ptr is null", name->c); return(mDNSNULL); }
-
-    if (!*np)       // If just writing one-byte root label, make sure we have space for that
-    {
-        if (ptr >= limit) return(mDNSNULL);
-    }
-    else            // else, loop through writing labels and/or a compression offset
-    {
-        do  {
-            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 256 bytes long, including the final trailing root label.
-            // Suppose np is now at name->c[249], and we're about to write our last non-null label ("local").
-            // We know that max will be at name->c[256]
-            // 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 256 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 256 bytes)", name->c); return(mDNSNULL); }
-
-            if (base) pointer = FindCompressionPointer(base, searchlimit, np);
-            if (pointer)                    // Use a compression pointer if we can
-            {
-                const mDNSu16 offset = (mDNSu16)(pointer - base);
-                if (ptr+2 > limit) return(mDNSNULL);    // If we don't have two bytes of space left, give up
-                *ptr++ = (mDNSu8)(0xC0 | (offset >> 8));
-                *ptr++ = (mDNSu8)(        offset &  0xFF);
-                return(ptr);
-            }
-            else                            // Else copy one label and try again
-            {
-                int i;
-                mDNSu8 len = *np++;
-                // If we don't at least have enough space for this label *plus* a terminating zero on the end, give up
-                if (ptr + 1 + len >= limit) return(mDNSNULL);
-                *ptr++ = len;
-                for (i=0; i<len; i++) *ptr++ = *np++;
-            }
-        } while (*np);                      // While we've got characters remaining in the name, continue
-    }
-
-    *ptr++ = 0;     // Put the final root label
-    return(ptr);
-}
-
-#ifndef STANDALONE
-
-mDNSlocal mDNSu8 *putVal16(mDNSu8 *ptr, mDNSu16 val)
-{
-    ptr[0] = (mDNSu8)((val >> 8 ) & 0xFF);
-    ptr[1] = (mDNSu8)((val      ) & 0xFF);
-    return ptr + sizeof(mDNSOpaque16);
-}
-
-mDNSlocal mDNSu8 *putVal32(mDNSu8 *ptr, mDNSu32 val)
-{
-    ptr[0] = (mDNSu8)((val >> 24) & 0xFF);
-    ptr[1] = (mDNSu8)((val >> 16) & 0xFF);
-    ptr[2] = (mDNSu8)((val >>  8) & 0xFF);
-    ptr[3] = (mDNSu8)((val      ) & 0xFF);
-    return ptr + sizeof(mDNSu32);
-}
-
-// Copy the RDATA information. The actual in memory storage for the data might be bigger than what the rdlength
-// says. Hence, the only way to copy out the data from a resource record is to use putRData.
-// msg points to the message we're building (pass mDNSNULL for "msg" if we don't want to use compression pointers)
-mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr)
-{
-    const RDataBody2 *const rdb = (RDataBody2 *)rr->rdata->u.data;
-    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++ = rdb->ipv4.b[0];
-        *ptr++ = rdb->ipv4.b[1];
-        *ptr++ = rdb->ipv4.b[2];
-        *ptr++ = rdb->ipv4.b[3];
-        return(ptr);
-
-    case kDNSType_NS:
-    case kDNSType_CNAME:
-    case kDNSType_PTR:
-    case kDNSType_DNAME: return(putDomainNameAsLabels(msg, ptr, limit, &rdb->name));
-
-    case kDNSType_SOA:  ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->soa.mname);
-        if (!ptr) return(mDNSNULL);
-        ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->soa.rname);
-        if (!ptr || ptr + 20 > limit) return(mDNSNULL);
-        ptr = putVal32(ptr, rdb->soa.serial);
-        ptr = putVal32(ptr, rdb->soa.refresh);
-        ptr = putVal32(ptr, rdb->soa.retry);
-        ptr = putVal32(ptr, rdb->soa.expire);
-        ptr = putVal32(ptr, rdb->soa.min);
-        return(ptr);
-
-    case kDNSType_NULL:
-    case kDNSType_HINFO:
-    case kDNSType_TSIG:
-    case kDNSType_TXT:
-    case kDNSType_X25:
-    case kDNSType_ISDN:
-    case kDNSType_LOC:
-    case kDNSType_DHCID: if (ptr + rr->rdlength > limit) return(mDNSNULL);
-        mDNSPlatformMemCopy(ptr, rdb->data, rr->rdlength);
-        return(ptr + rr->rdlength);
-
-    case kDNSType_MX:
-    case kDNSType_AFSDB:
-    case kDNSType_RT:
-    case kDNSType_KX:   if (ptr + 3 > limit) return(mDNSNULL);
-        ptr = putVal16(ptr, rdb->mx.preference);
-        return(putDomainNameAsLabels(msg, ptr, limit, &rdb->mx.exchange));
-
-    case kDNSType_RP:   ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->rp.mbox);
-        if (!ptr) return(mDNSNULL);
-        ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->rp.txt);
-        return(ptr);
-
-    case kDNSType_PX:   if (ptr + 5 > limit) return(mDNSNULL);
-        ptr = putVal16(ptr, rdb->px.preference);
-        ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->px.map822);
-        if (!ptr) return(mDNSNULL);
-        ptr = putDomainNameAsLabels(msg, ptr, limit, &rdb->px.mapx400);
-        return(ptr);
-
-    case kDNSType_AAAA: if (rr->rdlength != sizeof(rdb->ipv6))
-        { debugf("putRData: Illegal length %d for kDNSType_AAAA", rr->rdlength); return(mDNSNULL); }
-        if (ptr + sizeof(rdb->ipv6) > limit) return(mDNSNULL);
-        mDNSPlatformMemCopy(ptr, &rdb->ipv6, sizeof(rdb->ipv6));
-        return(ptr + sizeof(rdb->ipv6));
-
-    case kDNSType_SRV:  if (ptr + 7 > limit) return(mDNSNULL);
-        *ptr++ = (mDNSu8)(rdb->srv.priority >> 8);
-        *ptr++ = (mDNSu8)(rdb->srv.priority &  0xFF);
-        *ptr++ = (mDNSu8)(rdb->srv.weight   >> 8);
-        *ptr++ = (mDNSu8)(rdb->srv.weight   &  0xFF);
-        *ptr++ = rdb->srv.port.b[0];
-        *ptr++ = rdb->srv.port.b[1];
-        return(putDomainNameAsLabels(msg, ptr, limit, &rdb->srv.target));
-
-    case kDNSType_TSR:  {
-            // tsr timestamp on wire is relative time since received.
-            mDNSs32 tsr_relative = mDNSPlatformContinuousTimeSeconds() - rdb->tsr_value;
-            ptr = putVal32(ptr, tsr_relative);
-            return(ptr);
-        }
-
-    case kDNSType_OPT:  {
-        int len = 0;
-        const rdataOPT *opt;
-        const rdataOPT *const end = (const rdataOPT *)&rr->rdata->u.data[rr->rdlength];
-        for (opt = &rr->rdata->u.opt[0]; opt < end; opt++) 
-            len += DNSOpt_Data_Space(opt);
-        if (ptr + len > limit) 
-        { 
-            LogMsg("ERROR: putOptRData - out of space"); 
-            return mDNSNULL; 
-        }
-        for (opt = &rr->rdata->u.opt[0]; opt < end; opt++)
-        {
-            const int space = DNSOpt_Data_Space(opt);
-            ptr = putVal16(ptr, opt->opt);
-            ptr = putVal16(ptr, (mDNSu16)space - 4);
-            switch (opt->opt)
-            {
-            case kDNSOpt_LLQ:
-                ptr = putVal16(ptr, opt->u.llq.vers);
-                ptr = putVal16(ptr, opt->u.llq.llqOp);
-                ptr = putVal16(ptr, opt->u.llq.err);
-                mDNSPlatformMemCopy(ptr, opt->u.llq.id.b, 8);                          // 8-byte id
-                ptr += 8;
-                ptr = putVal32(ptr, opt->u.llq.llqlease);
-                break;
-            case kDNSOpt_Lease:
-                ptr = putVal32(ptr, opt->u.updatelease);
-                break;
-            case kDNSOpt_Owner:
-                *ptr++ = opt->u.owner.vers;
-                *ptr++ = opt->u.owner.seq;
-                mDNSPlatformMemCopy(ptr, opt->u.owner.HMAC.b, 6);                          // 6-byte Host identifier
-                ptr += 6;
-                if (space >= DNSOpt_OwnerData_ID_Wake_Space)
-                {
-                    mDNSPlatformMemCopy(ptr, opt->u.owner.IMAC.b, 6);                           // 6-byte interface MAC
-                    ptr += 6;
-                    if (space > DNSOpt_OwnerData_ID_Wake_Space)
-                    {
-                        mDNSPlatformMemCopy(ptr, opt->u.owner.password.b, space - DNSOpt_OwnerData_ID_Wake_Space);
-                        ptr += space - DNSOpt_OwnerData_ID_Wake_Space;
-                    }
-                }
-                break;
-            case kDNSOpt_Trace:
-                *ptr++ = opt->u.tracer.platf;
-                ptr    = putVal32(ptr, opt->u.tracer.mDNSv);
-                break;
-            }
-        }
-        return ptr;
-    }
-
-    case kDNSType_NSEC: {
-        // For NSEC records, rdlength represents the exact number of bytes
-        // of in memory storage.
-        const mDNSu8 *nsec = (const mDNSu8 *)rdb->data;
-        const domainname *name = (const domainname *)nsec;
-        const int dlen = DomainNameLength(name);
-        nsec += dlen;
-        // This function is called when we are sending a NSEC record as part of mDNS,
-        // or to copy the data to any other buffer needed which could be a mDNS or uDNS
-        // NSEC record. The only time compression is used that when we are sending it
-        // in mDNS (indicated by non-NULL "msg") and hence we handle mDNS case
-        // separately.
-        if (MULTICAST_NSEC(rr))
-        {
-            mDNSu8 *save = ptr;
-            int i, j, wlen;
-            wlen = *(nsec + 1);
-            nsec += 2;                     // Skip the window number and len
-
-            // For our simplified use of NSEC synthetic records:
-            //
-            // nextname is always the record's own name,
-            // the block number is always 0,
-            // the count byte is a value in the range 1-32,
-            // followed by the 1-32 data bytes
-            //
-            // Note: When we send the NSEC record in mDNS, the window size is set to 32.
-            // We need to find out what the last non-NULL byte is.  If we are copying out
-            // from an RDATA, we have the right length. As we need to handle both the case,
-            // we loop to find the right value instead of blindly using len to copy.
-
-            for (i=wlen; i>0; i--) if (nsec[i-1]) break;
-
-            ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
-            if (!ptr) { LogInfo("putRData: Can't put name, Length %d, record %##s", limit - save, rr->name->c); return(mDNSNULL); }
-            if (i)                          // Only put a block if at least one type exists for this name
-            {
-                if (ptr + 2 + i > limit) { LogInfo("putRData: Can't put window, Length %d, i %d, record %##s", limit - ptr, i, rr->name->c); return(mDNSNULL); }
-                *ptr++ = 0;
-                *ptr++ = (mDNSu8)i;
-                for (j=0; j<i; j++) *ptr++ = nsec[j];
-            }
-            return ptr;
-        }
-        else
-        {
-            int win, wlen;
-            int len = rr->rdlength - dlen;
-
-            // Sanity check whether the bitmap is good
-            while (len)
-            {
-                if (len < 3)
-                { LogMsg("putRData: invalid length %d", len); return mDNSNULL; }
-
-                win = *nsec++;
-                wlen = *nsec++;
-                len -= 2;
-                if (len < wlen || wlen < 1 || wlen > 32)
-                { LogMsg("putRData: invalid window length %d", wlen); return mDNSNULL; }
-                if (win < 0 || win >= 256)
-                { LogMsg("putRData: invalid window %d", win); return mDNSNULL; }
-
-                nsec += wlen;
-                len -= wlen;
-            }
-            if (ptr + rr->rdlength > limit) { LogMsg("putRData: NSEC rdlength beyond limit %##s (%s), ptr %p, rdlength %d, limit %p", rr->name->c, DNSTypeName(rr->rrtype), ptr, rr->rdlength, limit); return(mDNSNULL);}
-
-            // No compression allowed for "nxt", just copy the data.
-            mDNSPlatformMemCopy(ptr, rdb->data, rr->rdlength);
-            return(ptr + rr->rdlength);
-        }
-    }
-
-    default:            debugf("putRData: Warning! Writing unknown resource type %d as raw data", rr->rrtype);
-        if (ptr + rr->rdlength > limit) return(mDNSNULL);
-        mDNSPlatformMemCopy(ptr, rdb->data, rr->rdlength);
-        return(ptr + rr->rdlength);
-    }
-}
-
-#define IsUnicastUpdate(X) (!mDNSOpaque16IsZero((X)->h.id) && ((X)->h.flags.b[0] & kDNSFlag0_OP_Mask) == kDNSFlag0_OP_Update)
-
-mDNSexport mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count,
-    const ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit)
-{
-    mDNSu8 *endofrdata;
-    mDNSu16 actualLength;
-    // When sending SRV to conventional DNS server (i.e. in DNS update requests) we should not do name compression on the rdata (RFC 2782)
-    const DNSMessage *const rdatacompressionbase = (IsUnicastUpdate(msg) && rr->rrtype == kDNSType_SRV) ? mDNSNULL : msg;
-
-    if (rr->RecordType == kDNSRecordTypeUnregistered)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "Attempt to put kDNSRecordTypeUnregistered " PRI_DM_NAME " (" PUB_S ")",
-            DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype));
-        return(ptr);
-    }
-
-    if (!ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "Pointer to message is NULL while filling resource record " PRI_DM_NAME " (" PUB_S ")",
-            DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype));
-        return(mDNSNULL);
-    }
-
-    ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
-    // If we're out-of-space, return mDNSNULL
-    if (!ptr || ptr + 10 >= limit)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-            "Can't put more names into current message, will possibly put it into the next message - "
-            "name: " PRI_DM_NAME " (" PUB_S "), remaining space: %ld",
-            DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype), (long)(limit - ptr));
-        return(mDNSNULL);
-    }
-    ptr[0] = (mDNSu8)(rr->rrtype  >> 8);
-    ptr[1] = (mDNSu8)(rr->rrtype  &  0xFF);
-    ptr[2] = (mDNSu8)(rr->rrclass >> 8);
-    ptr[3] = (mDNSu8)(rr->rrclass &  0xFF);
-    ptr[4] = (mDNSu8)((ttl >> 24) &  0xFF);
-    ptr[5] = (mDNSu8)((ttl >> 16) &  0xFF);
-    ptr[6] = (mDNSu8)((ttl >>  8) &  0xFF);
-    ptr[7] = (mDNSu8)( ttl        &  0xFF);
-    // ptr[8] and ptr[9] filled in *after* we find out how much space the rdata takes
-
-    endofrdata = putRData(rdatacompressionbase, ptr+10, limit, rr);
-    if (!endofrdata)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-            "Can't put more rdata into current message, will possibly put it into the next message - "
-            "name: " PRI_DM_NAME " (" PUB_S "), remaining space: %ld",
-            DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype), (long)(limit - ptr - 10));
-        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 &  0xFF);
-
-    if (count)
-    {
-        (*count)++;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "No target count to update for " PRI_DM_NAME " (" PUB_S ")",
-            DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype));
-    }
-    return(endofrdata);
-}
-
-mDNSlocal mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, mDNSu16 *count, const AuthRecord *rr)
-{
-    ptr = putDomainNameAsLabels(msg, ptr, limit, rr->resrec.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  &  0xFF);
-    ptr[2] = (mDNSu8)(rr->resrec.rrclass >> 8);             // Put class
-    ptr[3] = (mDNSu8)(rr->resrec.rrclass &  0xFF);
-    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);
-}
-
-mDNSexport 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  &  0xFF);
-    ptr[2] = (mDNSu8)(rrclass >> 8);
-    ptr[3] = (mDNSu8)(rrclass &  0xFF);
-    msg->h.numQuestions++;
-    return(ptr+4);
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass)
-{
-    ptr = putDomainNameAsLabels(msg, ptr, limit, zone);
-    if (!ptr || ptr + 4 > limit) return mDNSNULL;       // If we're out-of-space, return NULL
-    *ptr++ = (mDNSu8)(kDNSType_SOA  >> 8);
-    *ptr++ = (mDNSu8)(kDNSType_SOA  &  0xFF);
-    *ptr++ = zoneClass.b[0];
-    *ptr++ = zoneClass.b[1];
-    msg->h.mDNS_numZones++;
-    return ptr;
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end)
-{
-    AuthRecord prereq;
-    mDNS_SetupResourceRecord(&prereq, mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
-    AssignDomainName(&prereq.namestorage, name);
-    prereq.resrec.rrtype = kDNSQType_ANY;
-    prereq.resrec.rrclass = kDNSClass_NONE;
-    return putEmptyResourceRecord(msg, ptr, end, &msg->h.mDNS_numPrereqs, &prereq);
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr)
-{
-    // deletion: specify record w/ TTL 0, class NONE
-    const mDNSu16 origclass = rr->rrclass;
-    rr->rrclass = kDNSClass_NONE;
-    ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.mDNS_numUpdates, rr, 0);
-    rr->rrclass = origclass;
-    return ptr;
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit)
-{
-    // deletion: specify record w/ TTL 0, class NONE
-    const mDNSu16 origclass = rr->rrclass;
-    rr->rrclass = kDNSClass_NONE;
-    ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.mDNS_numUpdates, rr, 0, limit);
-    rr->rrclass = origclass;
-    return ptr;
-}
-
-mDNSexport mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit)
-{
-    mDNSu16 class = kDNSQClass_ANY;
-
-    ptr = putDomainNameAsLabels(msg, ptr, limit, name);
-    if (!ptr || ptr + 10 >= limit) return mDNSNULL; // If we're out-of-space, return mDNSNULL
-    ptr[0] = (mDNSu8)(rrtype  >> 8);
-    ptr[1] = (mDNSu8)(rrtype  &  0xFF);
-    ptr[2] = (mDNSu8)(class >> 8);
-    ptr[3] = (mDNSu8)(class &  0xFF);
-    ptr[4] = ptr[5] = ptr[6] = ptr[7] = 0; // zero ttl
-    ptr[8] = ptr[9] = 0; // zero rdlength/rdata
-
-    msg->h.mDNS_numUpdates++;
-    return ptr + 10;
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name)
-{
-    const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
-    mDNSu16 class = kDNSQClass_ANY;
-    mDNSu16 rrtype = kDNSQType_ANY;
-
-    ptr = putDomainNameAsLabels(msg, ptr, limit, name);
-    if (!ptr || ptr + 10 >= limit) return mDNSNULL; // If we're out-of-space, return mDNSNULL
-    ptr[0] = (mDNSu8)(rrtype >> 8);
-    ptr[1] = (mDNSu8)(rrtype &  0xFF);
-    ptr[2] = (mDNSu8)(class >> 8);
-    ptr[3] = (mDNSu8)(class &  0xFF);
-    ptr[4] = ptr[5] = ptr[6] = ptr[7] = 0; // zero ttl
-    ptr[8] = ptr[9] = 0; // zero rdlength/rdata
-
-    msg->h.mDNS_numUpdates++;
-    return ptr + 10;
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease)
-{
-    AuthRecord rr;
-    mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-    rr.resrec.rrclass    = NormalMaxDNSMessageData;
-    rr.resrec.rdlength   = sizeof(rdataOPT);    // One option in this OPT record
-    rr.resrec.rdestimate = sizeof(rdataOPT);
-    rr.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
-    rr.resrec.rdata->u.opt[0].u.updatelease = lease;
-    ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0);
-    if (!ptr) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; }
-    return ptr;
-}
-
-// for dynamic updates
-mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit)
-{
-    AuthRecord rr;
-    mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-    rr.resrec.rrclass    = NormalMaxDNSMessageData;
-    rr.resrec.rdlength   = sizeof(rdataOPT);    // One option in this OPT record
-    rr.resrec.rdestimate = sizeof(rdataOPT);
-    rr.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
-    rr.resrec.rdata->u.opt[0].u.updatelease = lease;
-    ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0, limit);
-    if (!ptr) { LogMsg("ERROR: putUpdateLeaseWithLimit - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
-    return ptr;
-}
-
-// ***************************************************************************
-// MARK: - DNS Message Parsing Functions
-
-mDNSexport 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);
-}
-
-mDNSexport 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  = target ? DomainNameHashValue(target) : RDataHashValue(rr);
-}
-
-mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end)
-{
-    mDNSu16 total = 0;
-
-    if (ptr < (const 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 256 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:  if (ptr + 1 > end)                          // Skip the two-byte name compression pointer.
-            { debugf("skipDomainName: Malformed compression pointer (overruns packet end)"); return(mDNSNULL); }
-            return(ptr + 1);
-        }
-    }
-}
-
-// Routine to fetch an FQDN from the DNS message, following compression pointers if necessary.
-mDNSexport 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 < (const 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
-    {
-		int i;
-		mDNSu16 offset;
-        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)
-        {
-
-        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 256 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:  if (ptr >= end)
-            { debugf("getDomainName: Malformed compression label (overruns packet end)"); return(mDNSNULL); }
-            offset = (mDNSu16)((((mDNSu16)(len & 0x3F)) << 8) | *ptr++);
-            if (!nextbyte) nextbyte = ptr;              // Record where we got to before we started following pointers
-            ptr = (const mDNSu8 *)msg + offset;
-            if (ptr < (const 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);
-}
-
-mDNSexport 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);
-}
-
-// Sanity check whether the NSEC/NSEC3 bitmap is good
-mDNSlocal const mDNSu8 *SanityCheckBitMap(const mDNSu8 *bmap, const mDNSu8 *end, int len)
-{
-    int win, wlen;
-
-    while (bmap < end)
-    {
-        if (len < 3)
-        {
-            LogInfo("SanityCheckBitMap: invalid length %d", len);
-            return mDNSNULL;
-        }
-
-        win = *bmap++;
-        wlen = *bmap++;
-        len -= 2;
-        if (len < wlen || wlen < 1 || wlen > 32)
-        {
-            LogInfo("SanityCheckBitMap: invalid window length %d", wlen);
-            return mDNSNULL;
-        }
-        if (win < 0 || win >= 256)
-        {
-            LogInfo("SanityCheckBitMap: invalid window %d", win);
-            return mDNSNULL;
-        }
-
-        bmap += wlen;
-        len -= wlen;
-    }
-    return (const mDNSu8 *)bmap;
-}
-
-mDNSlocal mDNSBool AssignDomainNameWithLimit(domainname *const dst, const domainname *src, const mDNSu8 *const end)
-{
-    const mDNSu32 len = DomainNameLengthLimit(src, end);
-    if ((len >= 1) && (len <= MAX_DOMAIN_NAME))
-    {
-        mDNSPlatformMemCopy(dst->c, src->c, len);
-        return mDNStrue;
-    }
-    else
-    {
-        dst->c[0] = 0;
-        return mDNSfalse;
-    }
-}
-
-// This function is called with "msg" when we receive a DNS message and needs to parse a single resource record
-// pointed to by "ptr". Some resource records like SOA, SRV are converted to host order and also expanded
-// (domainnames are expanded to 256 bytes) when stored in memory.
-//
-// This function can also be called with "NULL" msg to parse a single resource record pointed to by ptr.
-// The caller can do this only if the names in the resource records are not compressed and validity of the
-// resource record has already been done before.
-mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end, ResourceRecord *const rr,
-    const mDNSu16 rdlength)
-{
-    RDataBody2 *const rdb = (RDataBody2 *)&rr->rdata->u;
-
-    switch (rr->rrtype)
-    {
-    case kDNSType_A:
-        if (rdlength != sizeof(mDNSv4Addr))
-            goto fail;
-        rdb->ipv4.b[0] = ptr[0];
-        rdb->ipv4.b[1] = ptr[1];
-        rdb->ipv4.b[2] = ptr[2];
-        rdb->ipv4.b[3] = ptr[3];
-        break;
-
-    case kDNSType_NS:
-    case kDNSType_MD:
-    case kDNSType_MF:
-    case kDNSType_CNAME:
-    case kDNSType_MB:
-    case kDNSType_MG:
-    case kDNSType_MR:
-    case kDNSType_PTR:
-    case kDNSType_NSAP_PTR:
-    case kDNSType_DNAME:
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->name);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->name, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->name);
-        }
-        if (ptr != end)
-        {
-            debugf("SetRData: Malformed CNAME/PTR RDATA name");
-            goto fail;
-        }
-        break;
-
-    case kDNSType_SOA:
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->soa.mname);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->soa.mname, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->soa.mname);
-        }
-        if (!ptr)
-        {
-            debugf("SetRData: Malformed SOA RDATA mname");
-            goto fail;
-        }
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->soa.rname);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->soa.rname, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->soa.rname);
-        }
-        if (!ptr)
-        {
-            debugf("SetRData: Malformed SOA RDATA rname");
-            goto fail;
-        }
-        if (ptr + 0x14 != end)
-        {
-            debugf("SetRData: Malformed SOA RDATA");
-            goto fail;
-        }
-        rdb->soa.serial  = (mDNSs32) ((mDNSs32)ptr[0x00] << 24 | (mDNSs32)ptr[0x01] << 16 | (mDNSs32)ptr[0x02] << 8 | ptr[0x03]);
-        rdb->soa.refresh = (mDNSu32) ((mDNSu32)ptr[0x04] << 24 | (mDNSu32)ptr[0x05] << 16 | (mDNSu32)ptr[0x06] << 8 | ptr[0x07]);
-        rdb->soa.retry   = (mDNSu32) ((mDNSu32)ptr[0x08] << 24 | (mDNSu32)ptr[0x09] << 16 | (mDNSu32)ptr[0x0A] << 8 | ptr[0x0B]);
-        rdb->soa.expire  = (mDNSu32) ((mDNSu32)ptr[0x0C] << 24 | (mDNSu32)ptr[0x0D] << 16 | (mDNSu32)ptr[0x0E] << 8 | ptr[0x0F]);
-        rdb->soa.min     = (mDNSu32) ((mDNSu32)ptr[0x10] << 24 | (mDNSu32)ptr[0x11] << 16 | (mDNSu32)ptr[0x12] << 8 | ptr[0x13]);
-        break;
-
-    case kDNSType_HINFO:
-    // See https://tools.ietf.org/html/rfc1035#section-3.3.2 for HINFO RDATA format.
-    {
-        // HINFO should contain RDATA.
-        if (end <= ptr || rdlength != (mDNSu32)(end - ptr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "SetRData: Malformed HINFO RDATA - invalid RDATA length: %u", rdlength);
-            goto fail;
-        }
-
-        const mDNSu8 *currentPtr = ptr;
-        // CPU character string length should be less than the RDATA length.
-        mDNSu32 cpuCharacterStrLength = currentPtr[0];
-        if (1 + cpuCharacterStrLength >= (mDNSu32)(end - currentPtr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "SetRData: Malformed HINFO RDATA - CPU character string goes out of boundary");
-            goto fail;
-        }
-        currentPtr += 1 + cpuCharacterStrLength;
-
-        // OS character string should end at the RDATA ending.
-        mDNSu32 osCharacterStrLength = currentPtr[0];
-        if (1 + osCharacterStrLength != (mDNSu32)(end - currentPtr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "SetRData: Malformed HINFO RDATA - OS character string does not end at the RDATA ending");
-            goto fail;
-        }
-
-        // Copy the validated RDATA.
-        rr->rdlength = rdlength;
-        mDNSPlatformMemCopy(rdb->data, ptr, rdlength);
-        break;
-    }
-    case kDNSType_NULL:
-    case kDNSType_TXT:
-    case kDNSType_X25:
-    case kDNSType_ISDN:
-    case kDNSType_LOC:
-    case kDNSType_DHCID:
-	case kDNSType_SVCB:
-	case kDNSType_HTTPS:
-        rr->rdlength = rdlength;
-        mDNSPlatformMemCopy(rdb->data, ptr, rdlength);
-        break;
-
-    case kDNSType_MX:
-    case kDNSType_AFSDB:
-    case kDNSType_RT:
-    case kDNSType_KX:
-        // Preference + domainname
-        if (rdlength < 3)
-            goto fail;
-        rdb->mx.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-        ptr += 2;
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->mx.exchange);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->mx.exchange, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->mx.exchange);
-        }
-        if (ptr != end)
-        {
-            debugf("SetRData: Malformed MX name");
-            goto fail;
-        }
-        break;
-
-    case kDNSType_MINFO:
-    case kDNSType_RP:
-        // Domainname + domainname
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->rp.mbox);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->rp.mbox, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->rp.mbox);
-        }
-        if (!ptr)
-        {
-            debugf("SetRData: Malformed RP mbox");
-            goto fail;
-        }
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->rp.txt);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->rp.txt, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->rp.txt);
-        }
-        if (ptr != end)
-        {
-            debugf("SetRData: Malformed RP txt");
-            goto fail;
-        }
-        break;
-
-    case kDNSType_PX:
-        // Preference + domainname + domainname
-        if (rdlength < 4)
-            goto fail;
-        rdb->px.preference = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-        ptr += 2;
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->px.map822);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->px.map822, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->px.map822);
-        }
-        if (!ptr)
-        {
-            debugf("SetRData: Malformed PX map822");
-            goto fail;
-        }
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->px.mapx400);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->px.mapx400, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->px.mapx400);
-        }
-        if (ptr != end)
-        {
-            debugf("SetRData: Malformed PX mapx400");
-            goto fail;
-        }
-        break;
-
-    case kDNSType_AAAA:
-        if (rdlength != sizeof(mDNSv6Addr))
-            goto fail;
-        mDNSPlatformMemCopy(&rdb->ipv6, ptr, sizeof(rdb->ipv6));
-        break;
-
-    case kDNSType_SRV:
-        // Priority + weight + port + domainname
-        if (rdlength < 7)
-            goto fail;
-        rdb->srv.priority = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-        rdb->srv.weight   = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-        rdb->srv.port.b[0] = ptr[4];
-        rdb->srv.port.b[1] = ptr[5];
-        ptr += 6;
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &rdb->srv.target);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&rdb->srv.target, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&rdb->srv.target);
-        }
-        if (ptr != end)
-        {
-            debugf("SetRData: Malformed SRV RDATA name");
-            goto fail;
-        }
-        break;
-
-    case kDNSType_NAPTR:
-    {
-        int savelen, len;
-        domainname name;
-        mDNSu32 namelen;
-        const mDNSu8 *orig = ptr;
-
-        // Make sure the data is parseable and within the limits.
-        //
-        // Fixed length: Order, preference (4 bytes)
-        // Variable length: flags, service, regexp, domainname
-
-        if (rdlength < 8)
-            goto fail;
-        // Order, preference.
-        ptr += 4;
-        // Parse flags, Service and Regexp
-        // length in the first byte does not include the length byte itself
-        len = *ptr + 1;
-        ptr += len;
-        if (ptr >= end)
-        {
-            LogInfo("SetRData: Malformed NAPTR flags");
-            goto fail;
-        }
-
-        // Service
-        len = *ptr + 1;
-        ptr += len;
-        if (ptr >= end)
-        {
-            LogInfo("SetRData: Malformed NAPTR service");
-            goto fail;
-        }
-
-        // Regexp
-        len = *ptr + 1;
-        ptr += len;
-        if (ptr >= end)
-        {
-            LogInfo("SetRData: Malformed NAPTR regexp");
-            goto fail;
-        }
-
-        savelen = (int)(ptr - orig);
-
-        // RFC 2915 states that name compression is not allowed for this field. But RFC 3597
-        // states that for NAPTR we should decompress. We make sure that we store the full
-        // name rather than the compressed name
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &name);
-            namelen = DomainNameLength(&name);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&name, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            namelen = DomainNameLength(&name);
-            ptr += namelen;
-        }
-        if (ptr != end)
-        {
-            LogInfo("SetRData: Malformed NAPTR RDATA name");
-            goto fail;
-        }
-
-        rr->rdlength = savelen + namelen;
-        // The uncompressed size should not exceed the limits
-        if (rr->rdlength > MaximumRDSize)
-        {
-            LogInfo("SetRData: Malformed NAPTR rdlength %d, rr->rdlength %d, "
-                    "bmaplen %d, name %##s", rdlength, rr->rdlength, name.c);
-            goto fail;
-        }
-        mDNSPlatformMemCopy(rdb->data, orig, savelen);
-        mDNSPlatformMemCopy(rdb->data + savelen, name.c, namelen);
-        break;
-    }
-    case kDNSType_OPT:  {
-        const mDNSu8 * const dataend = &rr->rdata->u.data[rr->rdata->MaxRDLength];
-        rdataOPT *opt = rr->rdata->u.opt;
-        rr->rdlength = 0;
-        while ((ptr < end) && ((dataend - ((const mDNSu8 *)opt)) >= ((mDNSs32)sizeof(*opt))))
-        {
-            const rdataOPT *const currentopt = opt;
-            if (ptr + 4 > end) { LogInfo("SetRData: OPT RDATA ptr + 4 > end"); goto fail; }
-            opt->opt    = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-            opt->optlen = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-            ptr += 4;
-            if (ptr + opt->optlen > end) { LogInfo("SetRData: ptr + opt->optlen > end"); goto fail; }
-            switch (opt->opt)
-            {
-            case kDNSOpt_LLQ:
-                if (opt->optlen == DNSOpt_LLQData_Space - 4)
-                {
-                    opt->u.llq.vers  = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-                    opt->u.llq.llqOp = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-                    opt->u.llq.err   = (mDNSu16)((mDNSu16)ptr[4] <<  8 | ptr[5]);
-                    mDNSPlatformMemCopy(opt->u.llq.id.b, ptr+6, 8);
-                    opt->u.llq.llqlease = (mDNSu32) ((mDNSu32)ptr[14] << 24 | (mDNSu32)ptr[15] << 16 | (mDNSu32)ptr[16] << 8 | ptr[17]);
-                    if (opt->u.llq.llqlease > 0x70000000UL / mDNSPlatformOneSecond)
-                        opt->u.llq.llqlease = 0x70000000UL / mDNSPlatformOneSecond;
-                    opt++;
-                }
-                break;
-            case kDNSOpt_Lease:
-                if (opt->optlen == DNSOpt_LeaseData_Space - 4)
-                {
-                    opt->u.updatelease = (mDNSu32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
-                    if (opt->u.updatelease > 0x70000000UL / mDNSPlatformOneSecond)
-                        opt->u.updatelease = 0x70000000UL / mDNSPlatformOneSecond;
-                    opt++;
-                }
-                break;
-            case kDNSOpt_Owner:
-                if (ValidOwnerLength(opt->optlen))
-                {
-                    opt->u.owner.vers = ptr[0];
-                    opt->u.owner.seq  = ptr[1];
-                    mDNSPlatformMemCopy(opt->u.owner.HMAC.b, ptr+2, 6);                         // 6-byte MAC address
-                    mDNSPlatformMemCopy(opt->u.owner.IMAC.b, ptr+2, 6);                         // 6-byte MAC address
-                    opt->u.owner.password = zeroEthAddr;
-                    if (opt->optlen >= DNSOpt_OwnerData_ID_Wake_Space-4)
-                    {
-                        mDNSPlatformMemCopy(opt->u.owner.IMAC.b, ptr+8, 6);                     // 6-byte MAC address
-                        // This mDNSPlatformMemCopy is safe because the ValidOwnerLength(opt->optlen) check above
-                        // ensures that opt->optlen is no more than DNSOpt_OwnerData_ID_Wake_PW6_Space - 4
-                        if (opt->optlen > DNSOpt_OwnerData_ID_Wake_Space-4)
-                            mDNSPlatformMemCopy(opt->u.owner.password.b, ptr+14, opt->optlen - (DNSOpt_OwnerData_ID_Wake_Space-4));
-                    }
-                    opt++;
-                }
-                break;
-            case kDNSOpt_Trace:
-                if (opt->optlen == DNSOpt_TraceData_Space - 4)
-                {
-                    opt->u.tracer.platf   = ptr[0];
-                    opt->u.tracer.mDNSv   = (mDNSu32) ((mDNSu32)ptr[1] << 24 | (mDNSu32)ptr[2] << 16 | (mDNSu32)ptr[3] << 8 | ptr[4]);
-                    opt++;
-                }
-                else
-                {
-                    opt->u.tracer.platf   = 0xFF;
-                    opt->u.tracer.mDNSv   = 0xFFFFFFFF;
-                    opt++;
-                }
-                break;
-            }
-            ptr += currentopt->optlen;
-        }
-        rr->rdlength = (mDNSu16)((mDNSu8*)opt - rr->rdata->u.data);
-        if (ptr != end) { LogInfo("SetRData: Malformed OptRdata"); goto fail; }
-        break;
-    }
-
-    case kDNSType_NSEC: {
-        domainname name;
-        int len = rdlength;
-        int bmaplen, dlen;
-        const mDNSu8 *orig = ptr;
-        const mDNSu8 *bmap;
-
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &name);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&name, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&name);
-        }
-        if (!ptr)
-        {
-            LogInfo("SetRData: Malformed NSEC nextname");
-            goto fail;
-        }
-
-        dlen = DomainNameLength(&name);
-
-        // Multicast NSECs use name compression for this field unlike the unicast case which
-        // does not use compression. And multicast case always succeeds in compression. So,
-        // the rdlength includes only the compressed space in that case. So, can't
-        // use the DomainNameLength of name to reduce the length here.
-        len -= (ptr - orig);
-        bmaplen = len;                  // Save the length of the bitmap
-        bmap = ptr;
-        ptr = SanityCheckBitMap(bmap, end, len);
-        if (!ptr)
-            goto fail;
-        if (ptr != end)
-        {
-            LogInfo("SetRData: Malformed NSEC length not right");
-            goto fail;
-        }
-
-        // Initialize the right length here. When we call SetNewRData below which in turn calls
-        // GetRDLength and for NSEC case, it assumes that rdlength is intitialized
-        rr->rdlength = DomainNameLength(&name) + bmaplen;
-
-        // Do we have space after the name expansion ?
-        if (rr->rdlength > MaximumRDSize)
-        {
-            LogInfo("SetRData: Malformed NSEC rdlength %d, rr->rdlength %d, "
-                    "bmaplen %d, name %##s", rdlength, rr->rdlength, name.c);
-            goto fail;
-        }
-        AssignDomainName(&rdb->name, &name);
-        mDNSPlatformMemCopy(rdb->data + dlen, bmap, bmaplen);
-        break;
-    }
-    case kDNSType_TKEY:
-    case kDNSType_TSIG:
-    {
-        domainname name;
-        int dlen, rlen;
-
-        // The name should not be compressed. But we take the conservative approach
-        // and uncompress the name before we store it.
-        if (msg)
-        {
-            ptr = getDomainName(msg, ptr, end, &name);
-        }
-        else
-        {
-            if (!AssignDomainNameWithLimit(&name, (const domainname *)ptr, end))
-            {
-                goto fail;
-            }
-            ptr += DomainNameLength(&name);
-        }
-        if (!ptr || ptr >= end)
-        {
-            LogInfo("SetRData: Malformed name for TSIG/TKEY type %d", rr->rrtype);
-            goto fail;
-        }
-        dlen = DomainNameLength(&name);
-        rlen = (int)(end - ptr);
-        rr->rdlength = dlen + rlen;
-        if (rr->rdlength > MaximumRDSize)
-        {
-            LogInfo("SetRData: Malformed TSIG/TKEY rdlength %d, rr->rdlength %d, "
-                    "bmaplen %d, name %##s", rdlength, rr->rdlength, name.c);
-            goto fail;
-        }
-        AssignDomainName(&rdb->name, &name);
-        mDNSPlatformMemCopy(rdb->data + dlen, ptr, rlen);
-        break;
-    }
-    case kDNSType_TSR:
-    {
-        rdb->tsr_value  = (mDNSs32) ((mDNSu32)ptr[0] << 24 | (mDNSu32)ptr[1] << 16 | (mDNSu32)ptr[2] << 8 | ptr[3]);
-        break;
-    }
-    default:
-        debugf("SetRData: Warning! Reading resource type %d (%s) as opaque data",
-               rr->rrtype, DNSTypeName(rr->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->rdlength = rdlength;
-        mDNSPlatformMemCopy(rdb->data, ptr, rdlength);
-        break;
-    }
-    return mDNStrue;
-fail:
-    return mDNSfalse;
-}
-
-mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *ptr,
-                                                const mDNSu8 *end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr)
-{
-    CacheRecord *const rr = &largecr->r;
-    mDNSu16 pktrdlength;
-    mDNSu32 maxttl = (!InterfaceID) ? mDNSMaximumUnicastTTLSeconds : mDNSMaximumMulticastTTLSeconds;
-
-    if (largecr == &m->rec && m->rec.r.resrec.RecordType)
-        LogFatalError("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
-
-    rr->next              = mDNSNULL;
-    rr->resrec.name       = &largecr->namestorage;
-
-    rr->NextInKAList      = mDNSNULL;
-    rr->TimeRcvd          = m ? m->timenow : 0;
-    rr->DelayDelivery     = 0;
-    rr->NextRequiredQuery = m ? m->timenow : 0;     // Will be updated to the real value when we call SetNextCacheCheckTimeForRecord()
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-    rr->LastCachedAnswerTime = 0;
-#endif
-    rr->CRActiveQuestion  = mDNSNULL;
-    rr->UnansweredQueries = 0;
-    rr->LastUnansweredTime= 0;
-    rr->NextInCFList      = mDNSNULL;
-
-    rr->resrec.InterfaceID       = InterfaceID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_forget(&rr->resrec.dnsservice);
-#else
-    rr->resrec.rDNSServer = mDNSNULL;
-#endif
-
-    ptr = getDomainName(msg, ptr, end, &largecr->namestorage);      // Will bail out correctly if ptr is NULL
-    if (!ptr) { debugf("GetLargeResourceRecord: Malformed RR name"); return(mDNSNULL); }
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-
-    if (ptr + 10 > end) { debugf("GetLargeResourceRecord: 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 > maxttl && (mDNSs32)rr->resrec.rroriginalttl != -1)
-        rr->resrec.rroriginalttl = maxttl;
-    // 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 mDNS record has cache-flush bit set, we mark it unique
-    // For uDNS records, all are implicitly deemed unique (a single DNS server is always authoritative for the entire RRSet)
-    if (ptr[2] & (kDNSClass_UniqueRRSet >> 8) || !InterfaceID)
-        RecordType |= kDNSRecordTypePacketUniqueMask;
-    ptr += 10;
-    if (ptr + pktrdlength > end) { debugf("GetLargeResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); }
-    end = ptr + pktrdlength;        // Adjust end to indicate the end of the rdata for this resource record
-
-    rr->resrec.rdata = (RData*)&rr->smallrdatastorage;
-    rr->resrec.rdata->MaxRDLength = MaximumRDSize;
-
-    if (pktrdlength > MaximumRDSize)
-    {
-        LogInfo("GetLargeResourceRecord: %s rdata size (%d) exceeds storage (%d)",
-                DNSTypeName(rr->resrec.rrtype), pktrdlength, rr->resrec.rdata->MaxRDLength);
-        goto fail;
-    }
-
-    if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name->c);
-
-    // IMPORTANT: Any record type we understand and unpack into a structure containing domainnames needs to have corresponding
-    // cases in SameRDataBody() and RDataHashValue() to do a semantic comparison (or checksum) of the structure instead of a blind
-    // bitwise memory compare (or sum). This is because a domainname is a fixed size structure holding variable-length data.
-    // Any bytes past the logical end of the name are undefined, and a blind bitwise memory compare may indicate that
-    // two domainnames are different when semantically they are the same name and it's only the unused bytes that differ.
-    if (rr->resrec.rrclass == kDNSQClass_ANY && pktrdlength == 0)   // Used in update packets to mean "Delete An RRset" (RFC 2136)
-        rr->resrec.rdlength = 0;
-    else if (!SetRData(msg, ptr, end, &rr->resrec, pktrdlength))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "GetLargeResourceRecord: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
-            DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-        goto fail;
-    }
-
-    SetNewRData(&rr->resrec, mDNSNULL, 0);      // Sets rdlength, rdestimate, rdatahash for us
-
-    // Success! Now fill in RecordType to show this record contains valid data
-    rr->resrec.RecordType = RecordType;
-    return(end);
-
-fail:
-    // If we were unable to parse the rdata in this record, we indicate that by
-    // returing a 'kDNSRecordTypePacketNegative' record with rdlength set to zero
-    rr->resrec.RecordType = kDNSRecordTypePacketNegative;
-    rr->resrec.rdlength   = 0;
-    rr->resrec.rdestimate = 0;
-    rr->resrec.rdatahash  = 0;
-    return(end);
-}
-
-mDNSexport 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);
-}
-
-mDNSexport const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
-                                     DNSQuestion *question)
-{
-    mDNSPlatformMemZero(question, sizeof(*question));
-    question->InterfaceID = InterfaceID;
-    if (!InterfaceID) question->TargetQID = onesID; // In DNSQuestions we use TargetQID as the indicator of whether it's unicast or multicast
-    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);
-}
-
-mDNSexport 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);
-}
-
-mDNSexport 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);
-}
-
-mDNSexport const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end)
-{
-    int i;
-    const mDNSu8 *ptr = LocateAuthorities(msg, end);
-    for (i = 0; i < msg->h.numAuthorities; i++) ptr = skipResourceRecord(msg, ptr, end);
-    return (ptr);
-}
-
-mDNSexport const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize)
-{
-    int i;
-    const mDNSu8 *ptr = LocateAdditionals(msg, end);
-
-    // Locate the OPT record.
-    // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response."
-    // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section,
-    // but not necessarily the *last* entry in the Additional Section.
-    for (i = 0; ptr && i < msg->h.numAdditionals; i++)
-    {
-        if (ptr + DNSOpt_Header_Space + minsize <= end &&   // Make sure we have 11+minsize bytes of data
-            ptr[0] == 0                                &&   // Name must be root label
-            ptr[1] == (kDNSType_OPT >> 8  )            &&   // rrtype OPT
-            ptr[2] == (kDNSType_OPT & 0xFF)            &&
-            ((mDNSu16)ptr[9] << 8 | (mDNSu16)ptr[10]) >= (mDNSu16)minsize)
-            return(ptr);
-        else
-            ptr = skipResourceRecord(msg, ptr, end);
-    }
-    return(mDNSNULL);
-}
-
-// On success, GetLLQOptData returns pointer to storage within shared "m->rec";
-// it is caller's responsibilty to clear m->rec.r.resrec.RecordType after use
-// Note: An OPT RDataBody actually contains one or more variable-length rdataOPT objects packed together
-// The code that currently calls this assumes there's only one, instead of iterating through the set
-mDNSexport const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end)
-{
-    const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LLQData_Space);
-    if (ptr)
-    {
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-        if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative) return(&m->rec.r.resrec.rdata->u.opt[0]);
-    }
-    return(mDNSNULL);
-}
-
-// Get the lease life of records in a dynamic update
-mDNSexport mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease)
-{
-    const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
-    if (ptr)
-    {
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-        if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT)
-        {
-            const rdataOPT *o;
-            const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
-            for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
-                if (o->opt == kDNSOpt_Lease)
-                {
-                    *lease = o->u.updatelease;
-                    mDNSCoreResetRecord(m);
-                    return mDNStrue;
-                }
-        }
-        mDNSCoreResetRecord(m);
-    }
-    return mDNSfalse;
-}
-
-#define DNS_OP_Name(X) (                              \
-        (X) == kDNSFlag0_OP_StdQuery ? ""         :       \
-        (X) == kDNSFlag0_OP_Iquery   ? "Iquery "  :       \
-        (X) == kDNSFlag0_OP_Status   ? "Status "  :       \
-        (X) == kDNSFlag0_OP_Unused3  ? "Unused3 " :       \
-        (X) == kDNSFlag0_OP_Notify   ? "Notify "  :       \
-        (X) == kDNSFlag0_OP_Update   ? "Update "  :       \
-        (X) == kDNSFlag0_OP_DSO      ? "DSO "  : "?? " )
-
-#define DNS_RC_Name(X) (                             \
-        (X) == kDNSFlag1_RC_NoErr     ? "NoErr"    :      \
-        (X) == kDNSFlag1_RC_FormErr   ? "FormErr"  :      \
-        (X) == kDNSFlag1_RC_ServFail  ? "ServFail" :      \
-        (X) == kDNSFlag1_RC_NXDomain  ? "NXDomain" :      \
-        (X) == kDNSFlag1_RC_NotImpl   ? "NotImpl"  :      \
-        (X) == kDNSFlag1_RC_Refused   ? "Refused"  :      \
-        (X) == kDNSFlag1_RC_YXDomain  ? "YXDomain" :      \
-        (X) == kDNSFlag1_RC_YXRRSet   ? "YXRRSet"  :      \
-        (X) == kDNSFlag1_RC_NXRRSet   ? "NXRRSet"  :      \
-        (X) == kDNSFlag1_RC_NotAuth   ? "NotAuth"  :      \
-        (X) == kDNSFlag1_RC_NotZone   ? "NotZone"  :      \
-        (X) == kDNSFlag1_RC_DSOTypeNI ? "DSOTypeNI" : "??" )
-
-mDNSexport void mDNS_snprintf_add(char **ptr, const char *lim, const char *fmt, ...)
-{
-    va_list args;
-    mDNSu32 buflen, n;
-    char *const dst = *ptr;
-
-    buflen = (mDNSu32)(lim - dst);
-    if (buflen > 0)
-    {
-        va_start(args, fmt);
-        n = mDNS_vsnprintf(dst, buflen, fmt, args);
-        va_end(args);
-        *ptr = dst + n;
-    }
-}
-
-#define DNSTypeString(X) (((X) == kDNSType_A) ? "A" : DNSTypeName(X))
-
-#define ReadField16(PTR) ((mDNSu16)((((mDNSu16)((const mDNSu8 *)(PTR))[0]) << 8) | ((mDNSu16)((const mDNSu8 *)(PTR))[1])))
-#define ReadField32(PTR) \
-    ((mDNSu32)( \
-        (((mDNSu32)((const mDNSu8 *)(PTR))[0]) << 24) | \
-        (((mDNSu32)((const mDNSu8 *)(PTR))[1]) << 16) | \
-        (((mDNSu32)((const mDNSu8 *)(PTR))[2]) <<  8) | \
-         ((mDNSu32)((const mDNSu8 *)(PTR))[3])))
-
-mDNSlocal void DNSMessageDumpToLog(const DNSMessage *const msg, const mDNSu8 *const end)
-{
-    domainname *name = mDNSNULL;
-    const mDNSu8 *ptr = msg->data;
-    domainname nameStorage[2];
-
-    char questions[512];
-    questions[0] = '\0';
-    char *questions_dst = questions;
-    const char *const questions_lim = &questions[512];
-    for (mDNSu32 i = 0; i < msg->h.numQuestions; i++)
-    {
-        mDNSu16 qtype, qclass;
-
-        name = &nameStorage[0];
-        ptr = getDomainName(msg, ptr, end, name);
-        if (!ptr) goto exit;
-
-        if ((end - ptr) < 4) goto exit;
-        qtype  = ReadField16(&ptr[0]);
-        qclass = ReadField16(&ptr[2]);
-        ptr += 4;
-
-        mDNS_snprintf_add(&questions_dst, questions_lim, " %##s %s", name->c, DNSTypeString(qtype));
-        if (qclass != kDNSClass_IN) mDNS_snprintf_add(&questions_dst, questions_lim, "/%u", qclass);
-        mDNS_snprintf_add(&questions_dst, questions_lim, "?");
-    }
-
-    char rrs[512];
-    rrs[0] = '\0';
-    char *rrs_dst = rrs;
-    const char *const rrs_lim = &rrs[512];
-    const mDNSu32 rrcount = msg->h.numAnswers + msg->h.numAuthorities + msg->h.numAdditionals;
-    for (mDNSu32 i = 0; i < rrcount; i++)
-    {
-        mDNSu16 rrtype, rrclass, rdlength;
-        mDNSu32 ttl;
-        int handled;
-        const mDNSu8 *rdata;
-        const domainname *const previousName = name;
-
-        name = &nameStorage[(name == &nameStorage[0]) ? 1 : 0];
-        ptr = getDomainName(msg, ptr, end, name);
-        if (!ptr) goto exit;
-
-        if ((end - ptr) < 10) goto exit;
-        rrtype   = ReadField16(&ptr[0]);
-        rrclass  = ReadField16(&ptr[2]);
-        ttl      = ReadField32(&ptr[4]);
-        rdlength = ReadField16(&ptr[8]);
-        ptr += 10;
-
-        if ((end - ptr) < rdlength) goto exit;
-        rdata = ptr;
-
-        if (i > 0) mDNS_snprintf_add(&rrs_dst, rrs_lim, ",");
-        if (!previousName || !SameDomainName(name, previousName)) mDNS_snprintf_add(&rrs_dst, rrs_lim, " %##s", name);
-
-        mDNS_snprintf_add(&rrs_dst, rrs_lim, " %s", DNSTypeString(rrtype));
-        if (rrclass != kDNSClass_IN) mDNS_snprintf_add(&rrs_dst, rrs_lim, "/%u", rrclass);
-        mDNS_snprintf_add(&rrs_dst, rrs_lim, " ");
-
-        handled = mDNSfalse;
-        switch (rrtype)
-        {
-            case kDNSType_A:
-                if (rdlength == 4)
-                {
-                    mDNS_snprintf_add(&rrs_dst, rrs_lim, "%.4a", rdata);
-                    handled = mDNStrue;
-                }
-                break;
-
-            case kDNSType_AAAA:
-                if (rdlength == 16)
-                {
-                    mDNS_snprintf_add(&rrs_dst, rrs_lim, "%.16a", rdata);
-                    handled = mDNStrue;
-                }
-                break;
-
-            case kDNSType_CNAME:
-                ptr = getDomainName(msg, rdata, end, name);
-                if (!ptr) goto exit;
-
-                mDNS_snprintf_add(&rrs_dst, rrs_lim, "%##s", name);
-                handled = mDNStrue;
-                break;
-
-            case kDNSType_SOA:
-            {
-                mDNSu32 serial, refresh, retry, expire, minimum;
-                domainname *const mname = &nameStorage[0];
-                domainname *const rname = &nameStorage[1];
-                name = mDNSNULL;
-
-                ptr = getDomainName(msg, rdata, end, mname);
-                if (!ptr) goto exit;
-
-                ptr = getDomainName(msg, ptr, end, rname);
-                if (!ptr) goto exit;
-
-                if ((end - ptr) < 20) goto exit;
-                serial  = ReadField32(&ptr[0]);
-                refresh = ReadField32(&ptr[4]);
-                retry   = ReadField32(&ptr[8]);
-                expire  = ReadField32(&ptr[12]);
-                minimum = ReadField32(&ptr[16]);
-
-                mDNS_snprintf_add(&rrs_dst, rrs_lim, "%##s %##s %lu %lu %lu %lu %lu", mname, rname, (unsigned long)serial,
-                                  (unsigned long)refresh, (unsigned long)retry, (unsigned long)expire, (unsigned long)minimum);
-
-                handled = mDNStrue;
-                break;
-            }
-
-            default:
-                break;
-        }
-        if (!handled) mDNS_snprintf_add(&rrs_dst, rrs_lim, "RDATA[%u]: %.*H", rdlength, rdlength, rdata);
-        mDNS_snprintf_add(&rrs_dst, rrs_lim, " (%lu)", (unsigned long)ttl);
-        ptr = rdata + rdlength;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[Q%u] DNS " PUB_S PUB_S " (%lu) (flags %02X%02X) RCODE: " PUB_S " (%d)" PUB_S PUB_S PUB_S PUB_S PUB_S PUB_S ":"
-        PRI_S " %u/%u/%u " PRI_S,
-        mDNSVal16(msg->h.id),
-        DNS_OP_Name(msg->h.flags.b[0] & kDNSFlag0_OP_Mask),
-        (msg->h.flags.b[0] & kDNSFlag0_QR_Response) ? "Response" : "Query",
-        (unsigned long)(end - (const mDNSu8 *)msg),
-        msg->h.flags.b[0], msg->h.flags.b[1],
-        DNS_RC_Name(msg->h.flags.b[1] & kDNSFlag1_RC_Mask),
-        msg->h.flags.b[1] & kDNSFlag1_RC_Mask,
-        (msg->h.flags.b[0] & kDNSFlag0_AA) ? " AA" : "",
-        (msg->h.flags.b[0] & kDNSFlag0_TC) ? " TC" : "",
-        (msg->h.flags.b[0] & kDNSFlag0_RD) ? " RD" : "",
-        (msg->h.flags.b[1] & kDNSFlag1_RA) ? " RA" : "",
-        (msg->h.flags.b[1] & kDNSFlag1_AD) ? " AD" : "",
-        (msg->h.flags.b[1] & kDNSFlag1_CD) ? " CD" : "",
-        questions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, rrs);
-
-exit:
-    return;
-}
-
-// Note: DumpPacket expects the packet header fields in host byte order, not network byte order
-mDNSexport void DumpPacket(mStatus status, mDNSBool sent, const char *transport,
-    const mDNSAddr *srcaddr, mDNSIPPort srcport,const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg,
-    const mDNSu8 *const end, mDNSInterfaceID interfaceID)
-{
-    const mDNSAddr zeroIPv4Addr = { mDNSAddrType_IPv4, {{{ 0 }}} };
-    char action[32];
-    const char* interfaceName = "interface";
-
-    if (!status) mDNS_snprintf(action, sizeof(action), sent ? "Sent" : "Received");
-    else         mDNS_snprintf(action, sizeof(action), "ERROR %d %sing", status, sent ? "Send" : "Receiv");
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    interfaceName = InterfaceNameForID(&mDNSStorage, interfaceID);
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[Q%u] " PUB_S " " PUB_S " DNS Message %lu bytes from " PRI_IP_ADDR ":%d to " PRI_IP_ADDR ":%d via " PUB_S " (%p)",
-        mDNSVal16(msg->h.id), action, transport, (unsigned long)(end - (const mDNSu8 *)msg),
-        srcaddr ? srcaddr : &zeroIPv4Addr, mDNSVal16(srcport), dstaddr ? dstaddr : &zeroIPv4Addr, mDNSVal16(dstport),
-        interfaceName, interfaceID);
-    DNSMessageDumpToLog(msg, end);
-}
-
-// ***************************************************************************
-// MARK: - Packet Sending Functions
-
-// Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.)
-struct TCPSocket_struct { mDNSIPPort port; TCPSocketFlags flags; /* ... */ };
-// Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.)
-struct UDPSocket_struct { mDNSIPPort     port;  /* ... */ };
-
-// Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which
-// is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible.
-mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
-                                      mDNSInterfaceID InterfaceID, TCPSocket *tcpSrc, UDPSocket *udpSrc, const mDNSAddr *dst,
-                                      mDNSIPPort dstport, DomainAuthInfo *authInfo, mDNSBool useBackgroundTrafficClass)
-{
-    mStatus status = mStatus_NoError;
-    const mDNSu16 numAdditionals = msg->h.numAdditionals;
-
-
-    // Zero-length message data is okay (e.g. for a DNS Update ack, where all we need is an ID and an error code
-    if (end < msg->data || end - msg->data > AbsoluteMaxDNSMessageData)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSSendDNSMessage: invalid message %p %p %ld", msg->data, end, end - msg->data);
-        return mStatus_BadParamErr;
-    }
-
-    // Put all the integer values in IETF byte-order (MSB first, LSB second)
-    SwapDNSHeaderBytes(msg);
-
-    if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0);    // DNSDigest_SignMessage operates on message in network byte order
-
-#if defined(DEBUG) && DEBUG
-    if (authInfo && end)
-    {
-        // If this is a debug build, every time when we sign the response, use the verifying function to ensure that
-        // both functions work correctly.
-        DNSDigest_VerifyMessage_Verify(msg, end, authInfo);
-    }
-#endif
-
-    if (!end)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSSendDNSMessage: DNSDigest_SignMessage failed");
-        status = mStatus_NoMemoryErr;
-    }
-    else
-    {
-        // Send the packet on the wire
-        if (!tcpSrc)
-            status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, udpSrc, dst, dstport, useBackgroundTrafficClass);
-        else
-        {
-            mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg);
-            mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) };
-            char *buf;
-            long nsent;
-
-            // Try to send them in one packet if we can allocate enough memory
-            buf = (char *) mDNSPlatformMemAllocate(msglen + 2);
-            if (buf)
-            {
-                buf[0] = lenbuf[0];
-                buf[1] = lenbuf[1];
-                mDNSPlatformMemCopy(buf+2, msg, msglen);
-                nsent = mDNSPlatformWriteTCP(tcpSrc, buf, msglen+2);
-                if (nsent != (msglen + 2))
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSSendDNSMessage: write message failed %ld/%d", nsent, msglen);
-                    status = mStatus_ConnFailed;
-                }
-                mDNSPlatformMemFree(buf);
-            }
-            else
-            {
-                nsent = mDNSPlatformWriteTCP(tcpSrc, (char*)lenbuf, 2);
-                if (nsent != 2)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSSendDNSMessage: write msg length failed %ld/%d", nsent, 2);
-                    status = mStatus_ConnFailed;
-                }
-                else
-                {
-                    nsent = mDNSPlatformWriteTCP(tcpSrc, (char *)msg, msglen);
-                    if (nsent != msglen)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSSendDNSMessage: write msg body failed %ld/%d", nsent, msglen);
-                        status = mStatus_ConnFailed;
-                    }
-                }
-            }
-        }
-    }
-
-    // Swap the integer values back the way they were (remember that numAdditionals may have been changed by putHINFO and/or SignMessage)
-    SwapDNSHeaderBytes(msg);
-
-    // Dump the packet with the HINFO and TSIG
-    mDNSBool dumpMessage = mDNSfalse;
-    if (mDNS_PacketLoggingEnabled)
-    {
-        // Dump non-mDNS messages, which have non-zero message IDs.
-        dumpMessage = !mDNSOpaque16IsZero(msg->h.id);
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-        // Also dump mDNS messages that are sent to an address that isn't an mDNS multicast address.
-        dumpMessage = dumpMessage || (dst && !mDNSAddrIsDNSMulticast(dst) && mDNSSameIPPort(dstport, MulticastDNSPort));
-#endif
-    }
-
-    if (dumpMessage)
-    {
-        char *transport = "UDP";
-        mDNSIPPort portNumber = udpSrc ? udpSrc->port : MulticastDNSPort;
-        if (tcpSrc)
-        {
-            if (tcpSrc->flags)
-                transport = "TLS";
-            else
-                transport = "TCP";
-            portNumber = tcpSrc->port;
-        }
-        DumpPacket(status, mDNStrue, transport, mDNSNULL, portNumber, dst, dstport, msg, end, InterfaceID);
-    }
-
-    // put the number of additionals back the way it was
-    msg->h.numAdditionals = numAdditionals;
-
-    return(status);
-}
-
-// ***************************************************************************
-// MARK: - RR List Management & Task Management
-
-mDNSexport void mDNS_VerifyLockState(const char *const operation, const mDNSBool checkIfLockHeld,
-    const mDNSu32 mDNS_busy, const mDNSu32 mDNS_reentrancy, const char *const functionName, const mDNSu32 lineNumber)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-    static os_unfair_lock logLock = OS_UNFAIR_LOCK_INIT;
-#endif
-    static const char *lastLockOperator = mDNSNULL; // The name of the function that succeeded in doing lock operation last time.
-    static mDNSu32 lineNumberlastLockOperator = 0; // The line number in the source code when this function gets called last time.
-
-#define CRASH_ON_LOCK_ERROR 0
-#if (CRASH_ON_LOCK_ERROR)
-    // When CRASH_ON_LOCK_ERROR is set to 1, if we encounter lock error, we will make mDNSResponder crash immediately
-    // to let the bug to be identified easily.
-    mDNSBool lockErrorEncountered = mDNSfalse;
-#endif
-
-    if (checkIfLockHeld)
-    {
-        // If the lock is held by the caller, then the number of times that the lock has been grabbed should be one more
-        // than the number of times that the lock has been dropped, so that only one lock is currently being held.
-        if (mDNS_busy > mDNS_reentrancy + 1)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "Lock failure: Check Lock, lock was grabbed by multiple callers - "
-                "caller: " PUB_S " at line %u, last successful lock holder: " PUB_S " at line %u, "
-                "mDNS_busy (%u) != mDNS_reentrancy (%u).", functionName, lineNumber, lastLockOperator,
-                lineNumberlastLockOperator, mDNS_busy, mDNS_reentrancy);
-        #if (CRASH_ON_LOCK_ERROR)
-            lockErrorEncountered = mDNStrue;
-        #endif
-        }
-        else if (mDNS_busy < mDNS_reentrancy + 1)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "Lock failure: Check Lock, last lock dropper dropped the lock before grabbing it - "
-                "caller: " PUB_S " at line %u, last lock dropper: " PUB_S " at line %u, "
-                "mDNS_busy (%u) != mDNS_reentrancy (%u).", functionName, lineNumber, lastLockOperator,
-                lineNumberlastLockOperator, mDNS_busy, mDNS_reentrancy);
-        #if (CRASH_ON_LOCK_ERROR)
-            lockErrorEncountered = mDNStrue;
-        #endif
-        }
-    }
-    else
-    {
-        // In non-critical section:
-        // The number of times that the lock has been grabbed should be equal to the number of times that the lock has
-        // been dropped, which means, no one is currently holding the real lock.
-        if (mDNS_busy == mDNS_reentrancy)
-        {
-            switch (operation[0])
-            {
-                case 'L': // "Lock" (it is paired with "Unlock")
-                case 'D': // "Drop Lock" (it is paired with "Reclaim Lock")
-                    // Add new lock state, and we need to remember who succeeds in doing the operation because it might
-                    // lead to invalid lock state.
-                #if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-                    os_unfair_lock_lock(&logLock);
-                #endif
-                    lastLockOperator = functionName;
-                    lineNumberlastLockOperator = lineNumber;
-                #if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-                    os_unfair_lock_unlock(&logLock);
-                #endif
-                    break;
-
-                case 'U': // "Unlock"
-                case 'R': // "Reclaim Lock"
-                    // Remove the previous lock state, and we can remove the name and the line number that has been
-                    // saved.
-                #if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-                    os_unfair_lock_lock(&logLock);
-                #endif
-                    lastLockOperator = mDNSNULL;
-                    lineNumberlastLockOperator = 0;
-                #if MDNSRESPONDER_SUPPORTS(APPLE, OS_UNFAIR_LOCK)
-                    os_unfair_lock_unlock(&logLock);
-                #endif
-                case 'C': // "Check Lock"
-                    // "Check Lock" operation will never change the lock state, so no need to take a note for that.
-                    break;
-
-                default:
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Invalid lock operation - " PUB_S, operation);
-                    break;
-            }
-        }
-        else if (mDNS_busy > mDNS_reentrancy)
-        {
-            // If mDNS_busy is greater than mDNS_reentrancy, there is someone who has grabbed the lock. This is invalid
-            // in a critical section.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "Lock failure: " PUB_S ", last lock holder still holds the lock - "
-                "caller: " PUB_S " at line %u, last successful lock holder: " PUB_S " at line %u, "
-                "mDNS_busy (%u) != mDNS_reentrancy (%u).", operation, functionName, lineNumber, lastLockOperator,
-                lineNumberlastLockOperator, mDNS_busy, mDNS_reentrancy);
-        #if (CRASH_ON_LOCK_ERROR)
-            lockErrorEncountered = mDNStrue;
-        #endif
-        }
-        else // m->mDNS_busy < m->mDNS_reentrancy
-        {
-            // If mDNS_busy is less than mDNS_reentrancy, something bad happens, because no one should drop the lock
-            // before grabbing it successfully. This should never heppen.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "Lock failure: " PUB_S ", last lock dropper dropped the lock before grabbing it - "
-                "caller: " PUB_S " at line %u, last lock dropper: " PUB_S " at line %u, "
-                "mDNS_busy (%u) != mDNS_reentrancy (%u).", operation, functionName, lineNumber, lastLockOperator,
-                lineNumberlastLockOperator, mDNS_busy, mDNS_reentrancy);
-        #if (CRASH_ON_LOCK_ERROR)
-            lockErrorEncountered = mDNStrue;
-        #endif
-        }
-    }
-
-#if (CRASH_ON_LOCK_ERROR)
-    if (lockErrorEncountered)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                  "Encounter lock error, make mDNSResponder crash immediately.");
-        assert(0);
-    }
-#endif
-}
-
-mDNSexport void mDNS_Lock_(mDNS *const m, const char *const functionName, const mDNSu32 lineNumber)
-{
-    // 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
-    mDNS_VerifyLockState("Lock", mDNSfalse, m->mDNS_busy, m->mDNS_reentrancy, functionName, lineNumber);
-
-    // 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)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, PUB_S ": mDNS_Lock: m->timenow already set (%u/%u)",
-                functionName, m->timenow, mDNS_TimeNow_NoLock(m));
-        }
-
-        m->timenow = mDNS_TimeNow_NoLock(m);
-        if (m->timenow == 0) m->timenow = 1;
-    }
-    else if (m->timenow == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            PUB_S ": mDNS_Lock: m->mDNS_busy is %u but m->timenow not set", functionName, m->mDNS_busy);
-
-        m->timenow = mDNS_TimeNow_NoLock(m);
-        if (m->timenow == 0) m->timenow = 1;
-    }
-
-    if (m->timenow_last - m->timenow > 0)
-    {
-        m->timenow_adjust += m->timenow_last - m->timenow;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            PUB_S ": mDNSPlatformRawTime went backwards by %d ticks; setting correction factor to %d",
-            functionName, 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 AuthRecord *AnyLocalRecordReady(const mDNS *const m)
-{
-    AuthRecord *rr;
-    for (rr = m->NewLocalRecords; rr; rr = rr->next)
-        if (LocalRecordReady(rr)) return rr;
-    return mDNSNULL;
-}
-
-mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
-{
-    mDNSs32 e = m->timenow + FutureTime;
-    if (m->mDNSPlatformStatus != mStatus_NoError) return(e);
-    if (m->NewQuestions)
-    {
-        if (m->NewQuestions->DelayAnswering) e = m->NewQuestions->DelayAnswering;
-        else return(m->timenow);
-    }
-    if (m->NewLocalOnlyQuestions) return(m->timenow);
-    if (m->NewLocalRecords && AnyLocalRecordReady(m)) return(m->timenow);
-    if (m->NewLocalOnlyRecords) return(m->timenow);
-    if (m->SPSProxyListChanged) return(m->timenow);
-    if (m->LocalRemoveEvents) return(m->timenow);
-
-#ifndef UNICAST_DISABLED
-    if (e - m->NextuDNSEvent         > 0) e = m->NextuDNSEvent;
-    if (e - m->NextScheduledNATOp    > 0) e = m->NextScheduledNATOp;
-    if (m->NextSRVUpdate && e - m->NextSRVUpdate > 0) e = m->NextSRVUpdate;
-#endif
-
-    if (e - m->NextCacheCheck        > 0) e = m->NextCacheCheck;
-    if (e - m->NextScheduledSPS      > 0) e = m->NextScheduledSPS;
-    if (e - m->NextScheduledKA       > 0) e = m->NextScheduledKA;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    if (m->NextBonjourDisableTime && (e - m->NextBonjourDisableTime > 0)) e = m->NextBonjourDisableTime;
-#endif
-
-    // Check if it is time to stop domain enumeration.
-    for (const DomainEnumerationOp *op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        // Iterate over all types of domain enumeration.
-        for (mDNSu32 type = 0; type < mDNS_DomainTypeMaxCount; type++)
-        {
-            if (op->enumerations[type] == mDNSNULL)
-            {
-                continue;
-            }
-
-            // Only check the domain enumeration that starts the stopping process.
-            if (op->enumerations[type]->state != DomainEnumerationState_StopInProgress)
-            {
-                continue;
-            }
-
-            if (e - op->enumerations[type]->nextStopTime > 0)
-            {
-                e = op->enumerations[type]->nextStopTime;
-            }
-        }
-    }
-
-    // NextScheduledSPRetry only valid when DelaySleep not set
-    if (!m->DelaySleep && m->SleepLimit && e - m->NextScheduledSPRetry > 0) e = m->NextScheduledSPRetry;
-    if (m->DelaySleep && e - m->DelaySleep > 0) e = m->DelaySleep;
-
-    if (m->SuppressQueries)
-    {
-        if (e - m->SuppressQueries       > 0) e = m->SuppressQueries;
-    }
-    else
-    {
-        if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
-        if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
-    }
-    if (m->SuppressResponses)
-    {
-        if (e - m->SuppressResponses     > 0) e = m->SuppressResponses;
-    }
-    else
-    {
-        if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
-    }
-    if (e - m->NextScheduledStopTime > 0) e = m->NextScheduledStopTime;
-
-    if (m->NextBLEServiceTime && (e - m->NextBLEServiceTime > 0)) e = m->NextBLEServiceTime;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (m->NextUpdateDNSSECValidatedCache && (e - m->NextUpdateDNSSECValidatedCache > 0))
-    {
-        e = m->NextUpdateDNSSECValidatedCache;
-    }
-#endif
-
-    return(e);
-}
-
-#define LogTSE TSE++,LogMsg
-
-mDNSexport void ShowTaskSchedulingError(mDNS *const m)
-{
-    int TSE = 0;
-    AuthRecord *rr;
-    mDNS_Lock(m);
-
-    LogMsg("Task Scheduling Error: *** Continuously busy for more than a second");
-
-    // Note: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent above
-
-    if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
-        LogTSE("Task Scheduling Error: NewQuestion %##s (%s)",
-               m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
-
-    if (m->NewLocalOnlyQuestions)
-        LogTSE("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
-               m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
-
-    if (m->NewLocalRecords)
-    {
-        rr = AnyLocalRecordReady(m);
-        if (rr) LogTSE("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr));
-    }
-
-    if (m->NewLocalOnlyRecords) LogTSE("Task Scheduling Error: NewLocalOnlyRecords");
-
-    if (m->SPSProxyListChanged) LogTSE("Task Scheduling Error: SPSProxyListChanged");
-
-    if (m->LocalRemoveEvents) LogTSE("Task Scheduling Error: LocalRemoveEvents");
-
-#ifndef UNICAST_DISABLED
-    if (m->timenow - m->NextuDNSEvent         >= 0)
-        LogTSE("Task Scheduling Error: m->NextuDNSEvent %d",         m->timenow - m->NextuDNSEvent);
-    if (m->timenow - m->NextScheduledNATOp    >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledNATOp %d",    m->timenow - m->NextScheduledNATOp);
-    if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0)
-        LogTSE("Task Scheduling Error: m->NextSRVUpdate %d",         m->timenow - m->NextSRVUpdate);
-#endif
-
-    if (m->timenow - m->NextCacheCheck        >= 0)
-        LogTSE("Task Scheduling Error: m->NextCacheCheck %d",        m->timenow - m->NextCacheCheck);
-    if (m->timenow - m->NextScheduledSPS      >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledSPS %d",      m->timenow - m->NextScheduledSPS);
-    if (m->timenow - m->NextScheduledKA       >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledKA %d",      m->timenow - m->NextScheduledKA);
-    if (!m->DelaySleep && m->SleepLimit && m->timenow - m->NextScheduledSPRetry >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledSPRetry %d",  m->timenow - m->NextScheduledSPRetry);
-    if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
-        LogTSE("Task Scheduling Error: m->DelaySleep %d",            m->timenow - m->DelaySleep);
-
-    if (m->SuppressQueries && m->timenow - m->SuppressQueries >= 0)
-        LogTSE("Task Scheduling Error: m->SuppressQueries %d",       m->timenow - m->SuppressQueries);
-    if (m->SuppressResponses && m->timenow - m->SuppressResponses >= 0)
-        LogTSE("Task Scheduling Error: m->SuppressResponses %d",     m->timenow - m->SuppressResponses);
-    if (m->timenow - m->NextScheduledQuery    >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledQuery %d",    m->timenow - m->NextScheduledQuery);
-    if (m->timenow - m->NextScheduledProbe    >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledProbe %d",    m->timenow - m->NextScheduledProbe);
-    if (m->timenow - m->NextScheduledResponse >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
-    if (m->timenow - m->NextScheduledStopTime >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledStopTime %d", m->timenow - m->NextScheduledStopTime);
-
-    if (m->timenow - m->NextScheduledEvent    >= 0)
-        LogTSE("Task Scheduling Error: m->NextScheduledEvent %d",    m->timenow - m->NextScheduledEvent);
-
-    if (m->NetworkChanged && m->timenow - m->NetworkChanged >= 0)
-        LogTSE("Task Scheduling Error: NetworkChanged %d",           m->timenow - m->NetworkChanged);
-
-    if (!TSE) LogMsg("Task Scheduling Error: *** No likely causes identified");
-    else LogMsg("Task Scheduling Error: *** %d potential cause%s identified (significant only if the same cause consistently appears)", TSE, TSE > 1 ? "s" : "");
-
-    mDNS_Unlock(m);
-}
-
-mDNSexport void mDNS_Unlock_(mDNS *const m, const char *const functionName, const mDNSu32 lineNumber)
-{
-    // Decrement mDNS_busy
-    m->mDNS_busy--;
-
-    // Check for locking failures
-    mDNS_VerifyLockState("Unlock", mDNSfalse, m->mDNS_busy, m->mDNS_reentrancy, functionName, lineNumber);
-
-    // 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);
-        if (m->timenow == 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, PUB_S ": mDNS_Unlock: ERROR! m->timenow aready zero",
-                      functionName);
-        }
-        m->timenow = 0;
-    }
-
-    // MUST release the platform lock LAST!
-    mDNSPlatformUnlock(m);
-}
-
-// ***************************************************************************
-// MARK: - Specialized mDNS version of vsnprintf
-
-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 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-#define kHexDigitsLowercase "0123456789abcdef"
-#define kHexDigitsUppercase "0123456789ABCDEF";
-
-mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg)
-{
-    mDNSu32 nwritten = 0;
-    int c;
-    if (buflen == 0) return(0);
-    buflen--;       // Pre-reserve one space in the buffer for the terminating null
-    if (buflen == 0) goto exit;
-
-    for (c = *fmt; c != '\0'; c = (c != '\0') ? *++fmt : c)
-    {
-        unsigned long n;
-        int hexdump = mDNSfalse;
-		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_Size 300
-            char mDNS_VACB[mDNS_VACB_Size];
-            #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
-            {
-            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
-                {
-                    s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                    if (F.altForm)
-                    {
-                        const mDNSAddr *const ip = (const mDNSAddr *)a;
-                        switch (ip->type)
-                        {
-                        case mDNSAddrType_IPv4: F.precision =  4; a = (unsigned char *)&ip->ip.v4; break;
-                        case mDNSAddrType_IPv6: F.precision = 16; a = (unsigned char *)&ip->ip.v6; break;
-                        default:
-                            if (ip->type == mDNSAddrType_None)
-                            {
-                                i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "<<UNSPECIFIED IP ADDRESS>>");
-                            }
-                            else
-                            {
-                                i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB),
-                                    "<<ERROR: %%#a used with unsupported type: %d>>", ip->type);
-                            }
-                            F.precision = 0;
-                            break;
-                        }
-                    }
-                    if (!F.altForm || (F.precision != 0))
-                    {
-                        switch (F.precision)
-                        {
-                        case  4: i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "%d.%d.%d.%d",
-                                                   a[0], a[1], a[2], a[3]); break;
-                        case  6: i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X",
-                                                   a[0], a[1], a[2], a[3], a[4], a[5]); break;
-                        case 16: {
-                            // Print IPv6 addresses according to RFC 5952, A Recommendation for IPv6 Address Text
-                            // Representation. See <https://tools.ietf.org/html/rfc5952>.
-
-                            int idx, runLen = 0, runStart = 0, maxRunLen = 0, maxRunStart = 0, maxRunEnd;
-
-                            // Find the leftmost longest run of consecutive zero hextets.
-                            for (idx = 0; idx < 8; ++idx)
-                            {
-                                const unsigned int hextet = (a[idx * 2] << 8) | a[(idx * 2) + 1];
-                                if (hextet == 0)
-                                {
-                                    if (runLen++ == 0) runStart = idx;
-                                    if (runLen > maxRunLen)
-                                    {
-                                        maxRunStart = runStart;
-                                        maxRunLen   = runLen;
-                                    }
-                                }
-                                else
-                                {
-                                    // If the number of remaining hextets is less than or equal to the length of the longest
-                                    // run so far, then we've found the leftmost longest run.
-                                    if ((8 - (idx + 1)) <= maxRunLen) break;
-                                    runLen = 0;
-                                }
-                            }
-
-                            // Compress the leftmost longest run of two or more consecutive zero hextets as "::".
-                            // For each reminaing hextet, suppress zeros leading up to the least-significant nibble, which
-                            // is always written, even if it's zero. Because of this requirement, it's easier to write the
-                            // IPv6 address in reverse. Also, write a colon separator before each hextet except for the
-                            // first one.
-                            s = mDNS_VACB_Lim;
-                            maxRunEnd = (maxRunLen >= 2) ? (maxRunStart + maxRunLen - 1) : -1;
-                            for (idx = 7; idx >= 0; --idx)
-                            {
-                                if (idx == maxRunEnd)
-                                {
-                                    if (idx == 7) *--s = ':';
-                                    idx = maxRunStart;
-                                    *--s = ':';
-                                }
-                                else
-                                {
-                                    unsigned int hextet = (a[idx * 2] << 8) | a[(idx * 2) + 1];
-                                    do {
-                                        *--s = kHexDigitsLowercase[hextet % 16];
-                                        hextet /= 16;
-                                    } while (hextet);
-                                    if (idx > 0) *--s = ':';
-                                }
-                            }
-                            i = (unsigned int)(mDNS_VACB_Lim - s);
-                        }
-                        break;
-
-                        default: i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "%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 = sizeof(void*) * 2;                // 8 characters on 32-bit; 16 characters on 64-bit
-                fallthrough();
-            case 'X':  digits = kHexDigitsUppercase;
-                goto hexadecimal;
-            case 'x':  digits = kHexDigitsLowercase;
-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';
-#ifndef FUZZING // Pascal strings aren't supported for fuzzing
-                if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; }
-#endif
-                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: i=0;
-                        if (!F.havePrecision)                               // C string
-                            while (s[i]) i++;
-                        else
-                        {
-                            while ((i < F.precision) && s[i]) i++;
-                            // Make sure we don't truncate in the middle of a UTF-8 character
-                            // If last character we got was any kind of UTF-8 multi-byte character,
-                            // then see if we have to back up.
-                            // This is not as easy as the similar checks below, because
-                            // here we can't assume it's safe to examine the *next* byte, so we
-                            // have to confine ourselves to working only backwards in the string.
-                            j = i;                      // Record where we got to
-                            // Now, back up until we find first non-continuation-char
-                            while (i>0 && (s[i-1] & 0xC0) == 0x80) i--;
-                            // Now s[i-1] is the first non-continuation-char
-                            // and (j-i) is the number of continuation-chars we found
-                            if (i>0 && (s[i-1] & 0xC0) == 0xC0)                 // If we found a start-char
-                            {
-                                i--;                        // Tentatively eliminate this start-char as well
-                                // Now (j-i) is the number of characters we're considering eliminating.
-                                // To be legal UTF-8, the start-char must contain (j-i) one-bits,
-                                // followed by a zero bit. If we shift it right by (7-(j-i)) bits
-                                // (with sign extension) then the result has to be 0xFE.
-                                // If this is right, then we reinstate the tentatively eliminated bytes.
-                                if (((j-i) < 7) && (((s[i] >> (7-(j-i))) & 0xFF) == 0xFE)) i = j;
-                            }
-                        }
-                        break;
-#ifndef FUZZING // Pascal strings aren't supported for fuzzing
-                    case 1: i = (unsigned char) *s++; break;                // Pascal string
-#endif
-                    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)
-                        {
-                            char buf[63*4+1];
-                            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; }
-                            // Need to use ConvertDomainLabelToCString to do proper escaping here,
-                            // so it's clear what's a literal dot and what's a label separator
-                            ConvertDomainLabelToCString((domainlabel*)a, buf);
-                            s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "%s.", buf);
-                            a += 1 + *a;
-                        }
-                        i = (mDNSu32)(s - mDNS_VACB);
-                        s = mDNS_VACB;                  // Reset s back to the start of the buffer
-                        break;
-                    }
-                    }
-                // Make sure we don't truncate in the middle of a UTF-8 character (see similar comment below)
-                if (F.havePrecision && i > F.precision)
-                { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--;}
-                break;
-
-            case 'H': {
-                    s = va_arg(arg, char *);
-                    hexdump = mDNStrue;
-                }
-                break;
-
-#ifndef FUZZING
-            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;
-#endif
-
-            default:    s = mDNS_VACB;
-                i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "<<UNKNOWN FORMAT CONVERSION CODE %%%c>>", mDNSIsPrintASCII(c) ? c : ' ');
-                break;
-
-            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 (hexdump)
-            {
-#ifndef FUZZING
-                char *dst = sbuffer;
-                const char *const lim = &sbuffer[buflen - nwritten];
-                if (F.havePrecision)
-                {
-                    for (i = 0; (i < F.precision) && (dst < lim); i++)
-                    {
-                        const unsigned int b = (unsigned int) *s++;
-                        if (i > 0)     *dst++ = ' ';
-                        if (dst < lim) *dst++ = kHexDigitsLowercase[(b >> 4) & 0xF];
-                        if (dst < lim) *dst++ = kHexDigitsLowercase[ b       & 0xF];
-                    }
-                }
-                i = (unsigned int)(dst - sbuffer);
-                sbuffer = dst;
-#endif
-            }
-            else
-            {
-                // Make sure we don't truncate in the middle of a UTF-8 character.
-                // Note: s[i] is the first eliminated character; i.e. the next character *after* the last character of the
-                // allowed output. If s[i] is a UTF-8 continuation character, then we've cut a unicode character in half,
-                // so back up 'i' until s[i] is no longer a UTF-8 continuation character. (if the input was proprly
-                // formed, s[i] will now be the UTF-8 start character of the multi-byte character we just eliminated).
-                if (i > buflen - nwritten)
-                { 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:
-    *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 !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport mDNSu32 mDNS_GetNextResolverGroupID(void)
-{
-    static mDNSu32 lastID = 0;
-    if (++lastID == 0) lastID = 1; // Valid resolver group IDs are non-zero.
-    return(lastID);
-}
-#endif
-
-#define kReverseIPv6Domain  ((const domainname *) "\x3" "ip6" "\x4" "arpa")
-
-mDNSexport mDNSBool GetReverseIPv6Addr(const domainname *name, mDNSu8 outIPv6[16])
-{
-    const mDNSu8 *      ptr;
-    int                 i;
-    mDNSu8              ipv6[16];
-
-    // If the name is of the form "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.", where each x
-    // is a hex digit, then the sequence of 32 hex digit labels represents the nibbles of an IPv6 address in reverse order.
-    // See <https://tools.ietf.org/html/rfc3596#section-2.5>.
-
-    ptr = name->c;
-    for (i = 0; i < 32; i++)
-    {
-        unsigned int c, nibble;
-        const int j = 15 - (i / 2);
-        if (*ptr++ != 1) return (mDNSfalse);                    // If this label's length is not 1, then fail.
-        c = *ptr++;                                             // Get label byte.
-        if (     (c >= '0') && (c <= '9')) nibble =  c - '0';   // If it's a hex digit, get its numeric value.
-        else if ((c >= 'a') && (c <= 'f')) nibble = (c - 'a') + 10;
-        else if ((c >= 'A') && (c <= 'F')) nibble = (c - 'A') + 10;
-        else                               return (mDNSfalse);  // Otherwise, fail.
-        if ((i % 2) == 0)
-        {
-            ipv6[j] = (mDNSu8)nibble;
-        }
-        else
-        {
-            ipv6[j] |= (mDNSu8)(nibble << 4);
-        }
-    }
-
-    // The rest of the name needs to be "ip6.arpa.". If it isn't, fail.
-
-    if (!SameDomainName((const domainname *)ptr, kReverseIPv6Domain)) return (mDNSfalse);
-    if (outIPv6) mDNSPlatformMemCopy(outIPv6, ipv6, 16);
-    return (mDNStrue);
-}
-#endif // !STANDALONE
diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h
deleted file mode 100644
index 271c129..0000000
--- a/mDNSCore/DNSCommon.h
+++ /dev/null
@@ -1,409 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __DNSCOMMON_H_
-#define __DNSCOMMON_H_
-
-#include "mDNSEmbeddedAPI.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec_mdns_core.h"
-#endif
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-//*************************************************************************************************************
-// Macros
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// ***************************************************************************
-// MARK: - DNS Protocol Constants
-
-typedef enum
-{
-    kDNSFlag0_QR_Mask        = 0x80,    // Query or response?
-    kDNSFlag0_QR_Query       = 0x00,
-    kDNSFlag0_QR_Response    = 0x80,
-
-    kDNSFlag0_OP_Mask        = 0xF << 3, // Operation type
-    kDNSFlag0_OP_StdQuery    = 0x0 << 3,
-    kDNSFlag0_OP_Iquery      = 0x1 << 3,
-    kDNSFlag0_OP_Status      = 0x2 << 3,
-    kDNSFlag0_OP_Unused3     = 0x3 << 3,
-    kDNSFlag0_OP_Notify      = 0x4 << 3,
-    kDNSFlag0_OP_Update      = 0x5 << 3,
-    kDNSFlag0_OP_DSO         = 0x6 << 3,
-
-    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_Mask     = 0x0F,       // Response code
-    kDNSFlag1_RC_NoErr    = 0x00,
-    kDNSFlag1_RC_FormErr  = 0x01,
-    kDNSFlag1_RC_ServFail = 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,
-	kDNSFlag1_RC_DSOTypeNI = 0x0B
-} DNS_Flags;
-
-typedef enum
-{
-    TSIG_ErrBadSig  = 16,
-    TSIG_ErrBadKey  = 17,
-    TSIG_ErrBadTime = 18
-} TSIG_ErrorCode;
-
-
-// ***************************************************************************
-// MARK: - General Utility Functions
-
-extern NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf);
-extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf);
-
-extern mDNSu32 mDNSRandom(mDNSu32 max);     // Returns pseudo-random result from zero to max inclusive
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern mDNSu32 mDNS_GetNextResolverGroupID(void);
-#endif
-
-// ***************************************************************************
-// MARK: - Domain Name Utility Functions
-
-#define mDNSSubTypeLabel   "\x04_sub"
-
-#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))
-#define mDNSIsPrintASCII(X) (((X) >= 32) && ((X) <= 126))
-    
-// We believe we have adequate safeguards to protect against cache poisoning.
-// In the event that someone does find a workable cache poisoning attack, we want to limit the lifetime of the poisoned entry.
-// We set the maximum allowable TTL to one hour.
-// With the 25% correction factor to avoid the DNS Zeno's paradox bug, that gives us an actual maximum lifetime of 75 minutes.
-
-#define mDNSMaximumMulticastTTLSeconds  (mDNSu32)4500
-#define mDNSMaximumUnicastTTLSeconds    (mDNSu32)3600
-
-// Adjustment factor to avoid race condition (used for unicast cache entries) :
-// Suppose real record has TTL of 3600, and our local caching server has held it for 3500 seconds, so it returns an aged TTL of 100.
-// If we do our normal refresh at 80% of the TTL, our local caching server will return 20 seconds, so we'll do another
-// 80% refresh after 16 seconds, and then the server will return 4 seconds, and so on, in the fashion of Zeno's paradox.
-// To avoid this, we extend the record's effective TTL to give it a little extra grace period.
-// We adjust the 100 second TTL to 127. This means that when we do our 80% query after 102 seconds,
-// the cached copy at our local caching server will already have expired, so the server will be forced
-// to fetch a fresh copy from the authoritative server, and then return a fresh record with the full TTL of 3600 seconds.
-
-#define RRAdjustTTL(ttl) ((ttl) + ((ttl)/4) + 2)
-#define RRUnadjustedTTL(ttl) ((((ttl) - 2) * 4) / 5)
-
-typedef enum
-{
-    uDNS_LLQ_Not = 0,   // Normal uDNS answer: Flush any stale records from cache, and respect record TTL
-    uDNS_LLQ_Ignore,    // LLQ initial challenge packet: ignore -- has no useful records for us
-    uDNS_LLQ_Entire,    // LLQ initial set of answers: Flush any stale records from cache, but assume TTL is 2 x LLQ refresh interval
-    uDNS_LLQ_Events     // LLQ event packet: don't flush cache; assume TTL is 2 x LLQ refresh interval
-} uDNS_LLQType;
-
-extern mDNSu32 GetEffectiveTTL(uDNS_LLQType LLQType, mDNSu32 ttl);
-
-#define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
-
-extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
-extern int CountLabels(const domainname *d);
-extern const domainname *SkipLeadingLabels(const domainname *d, int skip);
-
-extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
-extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
-extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
-extern void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText);
-#define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
-
-extern mDNSBool IsSubdomain(const domainname *const subdomain, const domainname *const domain);
-
-// ***************************************************************************
-// MARK: - Resource Record Utility Functions
-
-// IdenticalResourceRecord returns true if two resources records have
-// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
-
-// IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check,
-// which is at its most expensive and least useful in cases where we know in advance that the names match
-
-// Note: The dominant use of IdenticalResourceRecord is from ProcessQuery(), handling known-answer lists. In this case
-// it's common to have a whole bunch or records with exactly the same name (e.g. "_http._tcp.local") but different RDATA.
-// The SameDomainName() check is expensive when the names match, and in this case *all* the names match, so we
-// used to waste a lot of CPU time verifying that the names match, only then to find that the RDATA is different.
-// We observed mDNSResponder spending 30% of its total CPU time on this single task alone.
-// By swapping the checks so that we check the RDATA first, we can quickly detect when it's different
-// (99% of the time) and then bail out before we waste time on the expensive SameDomainName() check.
-
-extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename);
-
-static inline mDNSBool IdenticalSameNameRecord(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-    return
-    (
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Other than the ordinary non-DNSSEC records, there are two types of DNSSEC records:
-        // 1. DNSSEC to be validated: Records that come from DNSSEC-enabled response (with DNSSEC OK/Checking Disabled bits set).
-        // 2. DNSSEC validated: Records that come from the "DNSSEC to be validated" records, and has passed the DNSSEC validation.
-        // Only the records that have the same type can be compared.
-         (resource_records_have_same_dnssec_rr_category(r1, r2))     &&
-    #endif
-         r1->rrtype         == r2->rrtype       &&
-         r1->rrclass        == r2->rrclass      &&
-         r1->rdlength       == r2->rdlength     &&
-         r1->rdatahash      == r2->rdatahash    &&
-         SameRDataBody(r1, &r2->rdata->u, SameDomainName)
-    );
-}
-
-static inline mDNSBool IdenticalResourceRecord(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-    return
-    (
-        r1->namehash == r2->namehash        &&
-        IdenticalSameNameRecord(r1, r2)     &&
-        SameDomainName(r1->name, r2->name)
-    );
-}
-
-// A given RRType answers a QuestionType if RRType is CNAME, or types match, or QuestionType is ANY,
-// or the RRType is NSEC and positively asserts the nonexistence of the type being requested from multicast,
-// or the question requires the corresponding DNSSEC RRs,
-// or the RRType is RRSIG that covers the the type being requested.
-
-typedef mDNSu32 RRTypeAnswersQuestionTypeFlags;
-#define kRRTypeAnswersQuestionTypeFlagsNone 0
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#define kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate   (1U << 0)   // Use this flag to indicate that question needs "DNSSEC to be validated" records to do validation.
-#define kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRValidated    (1U << 1)   // Use this flag to indicate that question needs "DNSSEC validated" records to return to the client.
-#endif
-extern mDNSBool RRTypeAnswersQuestionType(const ResourceRecord *rr, mDNSu16 qtype, RRTypeAnswersQuestionTypeFlags flags);
-
-// Unicast NSEC records have the NSEC bit set whereas the multicast NSEC ones don't
-#define UNICAST_NSEC(rr) ((rr)->rrtype == kDNSType_NSEC && RRAssertsExistence((rr), kDNSType_NSEC))
-#define MULTICAST_NSEC(rr) ((rr)->rrtype == kDNSType_NSEC && RRAssertsNonexistence((rr), kDNSType_NSEC))
-
-extern mDNSu32 RDataHashValue(const ResourceRecord *const rr);
-extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename);
-extern mDNSBool SameNameCacheRecordAnswersQuestion(const CacheRecord *const cr, const DNSQuestion *const q);
-extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool AuthRecordAnswersQuestion(const AuthRecord *const ar, const DNSQuestion *const q);
-extern mDNSBool CacheRecordAnswersQuestion(const CacheRecord *const cr, const DNSQuestion *const q);
-extern mDNSBool AnyTypeRecordAnswersQuestion (const AuthRecord *const ar, const DNSQuestion *const q);
-extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q);
-extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
-extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
-extern mStatus DNSNameToLowerCase(domainname *d, domainname *result);
-
-#define GetRRDomainNameTarget(RR) (                                                                          \
-        ((RR)->rrtype == kDNSType_NS || (RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_DNAME) ? &(RR)->rdata->u.name        : \
-        ((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT  || (RR)->rrtype == kDNSType_KX   ) ? &(RR)->rdata->u.mx.exchange : \
-        ((RR)->rrtype == kDNSType_SRV                                  ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
-
-#define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique)
-
-// ***************************************************************************
-// MARK: - DNS Message Creation Functions
-
-extern void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags);
-extern const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname);
-extern mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name);
-extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr);
-
-// 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
-
-#define AllowedRRSpace(msg) (((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData)
-
-extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, const ResourceRecord *rr,
-    mDNSu32 ttl, const mDNSu8 *limit);
-
-#define PutResourceRecordTTL(msg, ptr, count, rr, ttl) \
-    PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AllowedRRSpace(msg))
-
-#define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) \
-    PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AbsoluteMaxDNSMessageData)
-
-#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
-
-// The PutRR_OS variants assume a local variable 'm', put build the packet at m->omsg,
-// and assume local variables 'OwnerRecordSpace' & 'TraceRecordSpace' indicating how many bytes (if any) to reserve to add an OWNER/TRACER option at the end
-#define PutRR_OS_TTL(ptr, count, rr, ttl) \
-    PutResourceRecordTTLWithLimit(&m->omsg, (ptr), (count), (rr), (ttl), m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace)
-
-#define PutRR_OS(P, C, RR) PutRR_OS_TTL((P), (C), (RR), (RR)->rroriginalttl)
-
-extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
-extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
-extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end);
-extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
-extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit);
-extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit);
-extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
-extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease);
-extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit);
-
-extern int baseEncode(char *buffer, int blen, const mDNSu8 *data, int len, int encAlg);
-extern void NSEC3Parse(const ResourceRecord *const rr, mDNSu8 **salt, int *hashLength, mDNSu8 **nxtName, int *bitmaplen, mDNSu8 **bitmap);
-
-// ***************************************************************************
-// MARK: - DNS Message Parsing Functions
-
-#define HashSlotFromNameHash(X) ((X) % CACHE_HASH_SLOTS)
-extern mDNSu32 DomainNameHashValue(const domainname *const name);
-extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
-extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end);
-extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end,
-                                   domainname *const name);
-extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
-extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr,
-                                            const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr);
-extern mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end, ResourceRecord *rr,
-    mDNSu16 rdlength);
-extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
-extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
-                                 DNSQuestion *question);
-extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end);
-extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end);
-extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
-extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize);
-extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end);
-extern mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease);
-extern void DumpPacket(mStatus status, mDNSBool sent, const char *transport, const mDNSAddr *srcaddr, mDNSIPPort srcport,
-    const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end,
-    mDNSInterfaceID interfaceID);
-extern mDNSBool RRAssertsNonexistence(const ResourceRecord *const rr, mDNSu16 type);
-extern mDNSBool RRAssertsExistence(const ResourceRecord *const rr, mDNSu16 type);
-extern mDNSBool BitmapTypeCheck(const mDNSu8 *bmap, int bitmaplen, mDNSu16 type);
-
-extern mDNSu16 swap16(mDNSu16 x);
-extern mDNSu32 swap32(mDNSu32 x);
-
-extern mDNSBool GetReverseIPv6Addr(const domainname *inQName, mDNSu8 outIPv6[16]);
-
-// ***************************************************************************
-// MARK: - Packet Sending Functions
-extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
-                                  mDNSInterfaceID InterfaceID, TCPSocket *tcpSrc, UDPSocket *udpSrc, const mDNSAddr *dst,
-                                  mDNSIPPort dstport, DomainAuthInfo *authInfo, mDNSBool useBackgroundTrafficClass);
-
-// ***************************************************************************
-// MARK: - RR List Management & Task Management
-
-extern void ShowTaskSchedulingError(mDNS *const m);
-
-/*!
- *  @brief
- *      Check if the locking state is valid or not by comparing the values of <code> mDNS_busy</code> and <code> mDNS_reentrancy</code>, and it also
- *      remembers the last function (with the source file line number) that succeeds in doing lock operation including "Lock", "Unlock", "Drop", "Reclaim". If any
- *      invalid lock state is detected, an error message with the function name of the last successful lock operator will be printed to help debug.
- *
- *  @param operation
- *      A text description of the lock operation that would be finished after(or before) this lock state checking, possible values are "Lock", "Unlock",
- *      "Drop Lock", "Reclaim Lock" and "Check Lock".
- *
- *  @param checkIfLockHeld
- *      A boolean value to indicate if the caller wants to check if it currently holds the lock. If the lock is not held or the lock state is invalid, an error message will
- *      be printed.
- *
- *  @param mDNS_busy
- *      The mDNS_busy value getting from the mDNS_struct object, its value indicates how many times the lock have been grabbed. Note that the caller can grab
- *      the lock and drop it before the user callback to allow the callback to grab the lock again. There should be only one who has grabbed the lock while not
- *      dropping it.
- *
- *  @param mDNS_reentrancy
- *      The mDNS_reentrancy getting from the mDNS_struct object, its value indicates how many times the lock have been dropped before callback after being
- *      grabbed by others. In other words, it indicates the depth of callback stack.
- *
- *  @param functionName
- *      The name of the function that calls <code>mDNS_VerifyLockState()</code>.
- *
- *  @param lineNumber
- *      The line number in the source code file where <code>mDNS_VerifyLockState()</code> gets called.
- *
- *  @discussion
- *      This function is called whenever mDNSResponder enters/exits the critical section to help avoid the lock-related bug when mDNSResponder is compiled
- *      with multi-thread support. On all Apple platforms, we have only two threads, one is the main queue for the main event loop, the other one is the K queue for
- *      the network configuration event, so we can almost treat mDNSResponder on Apple platform as a single-thread daemon. Such locking issues do not
- *      always happen because the lock cannot be grabbed twice by different process in a single-thread process. However, mDNSResponder core code should
- *      not assume that single-thread model is always available, and it should be aware of the possible locking race condition and avoid those.
- *      <code>mDNS_VerifyLockState()</code> is created to check the state of the lock and make sure the lock is operated correctly even on a single-thread
- *      environment. When it detects any possible lock inconsistency, it will print a log message with the last successful lock operator's name and the line number,
- *      to help debug the lock-related bugs.
- *
- */
-void mDNS_VerifyLockState(const char *operation, mDNSBool checkIfLockHeld,
-    mDNSu32 mDNS_busy, mDNSu32 mDNS_reentrancy, const char *functionName, mDNSu32 lineNumber);
-
-extern void mDNS_Lock_(mDNS *m, const char *functionname, mDNSu32 lineNumber);
-extern void mDNS_Unlock_(mDNS *m, const char *functionname, mDNSu32 lineNumber);
-
-#if defined(_WIN32)
- #define __func__ __FUNCTION__
-#endif
-
-#define mDNS_Lock(X) mDNS_Lock_((X), __func__, __LINE__)
-
-#define mDNS_Unlock(X) mDNS_Unlock_((X), __func__, __LINE__)
-
-#define mDNS_CheckLock(X) mDNS_VerifyLockState("Check Lock", mDNStrue, (X)->mDNS_busy, (X)->mDNS_reentrancy,   \
-                                               __func__, __LINE__)
-
-#define mDNS_DropLockBeforeCallback()                                                                               \
-    do                                                                                                              \
-    {                                                                                                               \
-        m->mDNS_reentrancy++;                                                                                       \
-        mDNS_VerifyLockState("Drop Lock", mDNSfalse, m->mDNS_busy, m->mDNS_reentrancy, __func__, __LINE__);         \
-    } while (mDNSfalse)
-
-#define mDNS_ReclaimLockAfterCallback()                                                                             \
-    do                                                                                                              \
-    {                                                                                                               \
-        mDNS_VerifyLockState("Reclaim Lock", mDNSfalse, m->mDNS_busy, m->mDNS_reentrancy, __func__, __LINE__);      \
-        m->mDNS_reentrancy--;                                                                                       \
-    } while (mDNSfalse)
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif // __DNSCOMMON_H_
diff --git a/mDNSCore/DNSDigest.c b/mDNSCore/DNSDigest.c
deleted file mode 100644
index 42e37db..0000000
--- a/mDNSCore/DNSDigest.c
+++ /dev/null
@@ -1,1983 +0,0 @@
-/*
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-#include <CommonCrypto/CommonHMAC.h>
-#endif
-#include "mdns_strict.h"
-
-// 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)
-#endif
-
-
-// ***************************************************************************
-// MARK: - Byte Swapping Functions
-
-mDNSlocal mDNSu16 NToH16(mDNSu8 * bytes)
-{
-    return (mDNSu16)((mDNSu16)bytes[0] << 8 | (mDNSu16)bytes[1]);
-}
-
-mDNSlocal mDNSu32 NToH32(mDNSu8 * bytes)
-{
-    return (mDNSu32)((mDNSu32) bytes[0] << 24 | (mDNSu32) bytes[1] << 16 | (mDNSu32) bytes[2] << 8 | (mDNSu32)bytes[3]);
-}
-
-// ***************************************************************************
-// MARK: - MD5 Hash Functions
-
-
-/* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
- * The following changes have been made to the original sources:
- *    replaced CC_LONG w/ mDNSu32
- *    replaced CC_MD5* with MD5*
- *    replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
- *    removed extern decls for MD5_Init/Update/Final from CommonDigest.h
- *    removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
- *
- * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
- * to aid in platform-specific optimizations and debugging.
- * Sources originally distributed under the following license headers:
- * CommonDigest.h - APSL
- *
- * md32_Common.h
- * ====================================================================
- * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * md5_dgst.c, md5_locl.h
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- *
- */
-
-//from CommonDigest.h
-
-
-
-// from openssl/md5.h
-
-#define MD5_CBLOCK  64
-#define MD5_LBLOCK  (MD5_CBLOCK/4)
-//#define MD5_DIGEST_LENGTH 16
-
-void MD5_Transform(MD5_CTX *c, const unsigned char *b);
-
-// From md5_locl.h
-
-#ifndef MD5_LONG_LOG2
-#define MD5_LONG_LOG2 2 /* default to 32 bits */
-#endif
-
-#ifdef MD5_ASM
-# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
-#  define md5_block_host_order md5_block_asm_host_order
-# elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
-void md5_block_asm_data_order_aligned (MD5_CTX *c, const mDNSu32 *p,int num);
-#  define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
-# endif
-#endif
-
-void md5_block_host_order (MD5_CTX *c, const void *p,int num);
-void md5_block_data_order (MD5_CTX *c, const void *p,int num);
-
-#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
-/*
- * *_block_host_order is expected to handle aligned data while
- * *_block_data_order - unaligned. As algorithm and host (x86)
- * are in this case of the same "endianness" these two are
- * otherwise indistinguishable. But normally you don't want to
- * call the same function because unaligned access in places
- * where alignment is expected is usually a "Bad Thing". Indeed,
- * on RISCs you get punished with BUS ERROR signal or *severe*
- * performance degradation. Intel CPUs are in turn perfectly
- * capable of loading unaligned data without such drastic side
- * effect. Yes, they say it's slower than aligned load, but no
- * exception is generated and therefore performance degradation
- * is *incomparable* with RISCs. What we should weight here is
- * costs of unaligned access against costs of aligning data.
- * According to my measurements allowing unaligned access results
- * in ~9% performance improvement on Pentium II operating at
- * 266MHz. I won't be surprised if the difference will be higher
- * on faster systems:-)
- *
- *				<appro@fy.chalmers.se>
- */
-#define md5_block_data_order md5_block_host_order
-#endif
-
-#define DATA_ORDER_IS_LITTLE_ENDIAN
-
-#define HASH_LONG       mDNSu32
-#define HASH_LONG_LOG2  MD5_LONG_LOG2
-#define HASH_CTX        MD5_CTX
-#define HASH_CBLOCK     MD5_CBLOCK
-#define HASH_LBLOCK     MD5_LBLOCK
-
-#define HASH_UPDATE     MD5_Update
-#define HASH_TRANSFORM  MD5_Transform
-#define HASH_FINAL      MD5_Final
-
-#define HASH_MAKE_STRING(c,s)   do {    \
-        unsigned long ll;       \
-        ll=(c)->A; HOST_l2c(ll,(s));    \
-        ll=(c)->B; HOST_l2c(ll,(s));    \
-        ll=(c)->C; HOST_l2c(ll,(s));    \
-        ll=(c)->D; HOST_l2c(ll,(s));    \
-} while (0)
-#define HASH_BLOCK_HOST_ORDER   md5_block_host_order
-#if !defined(L_ENDIAN) || defined(md5_block_data_order)
-#define HASH_BLOCK_DATA_ORDER   md5_block_data_order
-/*
- * Little-endians (Intel and Alpha) feel better without this.
- * It looks like memcpy does better job than generic
- * md5_block_data_order on copying-n-aligning input data.
- * But frankly speaking I didn't expect such result on Alpha.
- * On the other hand I've got this with egcs-1.0.2 and if
- * program is compiled with another (better?) compiler it
- * might turn out other way around.
- *
- *				<appro@fy.chalmers.se>
- */
-#endif
-
-
-// from md32_common.h
-
-/*
- * This is a generic 32 bit "collector" for message digest algorithms.
- * Whenever needed it collects input character stream into chunks of
- * 32 bit values and invokes a block function that performs actual hash
- * calculations.
- *
- * Porting guide.
- *
- * Obligatory macros:
- *
- * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
- *	this macro defines byte order of input stream.
- * HASH_CBLOCK
- *	size of a unit chunk HASH_BLOCK operates on.
- * HASH_LONG
- *	has to be at lest 32 bit wide, if it's wider, then
- *	HASH_LONG_LOG2 *has to* be defined along
- * HASH_CTX
- *	context structure that at least contains following
- *	members:
- *		typedef struct {
- *			...
- *			HASH_LONG	Nl,Nh;
- *			HASH_LONG	data[HASH_LBLOCK];
- *			int		num;
- *			...
- *			} HASH_CTX;
- * HASH_UPDATE
- *	name of "Update" function, implemented here.
- * HASH_TRANSFORM
- *	name of "Transform" function, implemented here.
- * HASH_FINAL
- *	name of "Final" function, implemented here.
- * HASH_BLOCK_HOST_ORDER
- *	name of "block" function treating *aligned* input message
- *	in host byte order, implemented externally.
- * HASH_BLOCK_DATA_ORDER
- *	name of "block" function treating *unaligned* input message
- *	in original (data) byte order, implemented externally (it
- *	actually is optional if data and host are of the same
- *	"endianess").
- * HASH_MAKE_STRING
- *	macro convering context variables to an ASCII hash string.
- *
- * Optional macros:
- *
- * B_ENDIAN or L_ENDIAN
- *	defines host byte-order.
- * HASH_LONG_LOG2
- *	defaults to 2 if not states otherwise.
- * HASH_LBLOCK
- *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
- * HASH_BLOCK_DATA_ORDER_ALIGNED
- *	alternative "block" function capable of treating
- *	aligned input message in original (data) order,
- *	implemented externally.
- *
- * MD5 example:
- *
- *	#define DATA_ORDER_IS_LITTLE_ENDIAN
- *
- *	#define HASH_LONG		mDNSu32
- *	#define HASH_LONG_LOG2	mDNSu32_LOG2
- *	#define HASH_CTX		MD5_CTX
- *	#define HASH_CBLOCK		MD5_CBLOCK
- *	#define HASH_LBLOCK		MD5_LBLOCK
- *	#define HASH_UPDATE		MD5_Update
- *	#define HASH_TRANSFORM		MD5_Transform
- *	#define HASH_FINAL		MD5_Final
- *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
- *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
- *
- *					<appro@fy.chalmers.se>
- */
-
-#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-#error "DATA_ORDER must be defined!"
-#endif
-
-#ifndef HASH_CBLOCK
-#error "HASH_CBLOCK must be defined!"
-#endif
-#ifndef HASH_LONG
-#error "HASH_LONG must be defined!"
-#endif
-#ifndef HASH_CTX
-#error "HASH_CTX must be defined!"
-#endif
-
-#ifndef HASH_UPDATE
-#error "HASH_UPDATE must be defined!"
-#endif
-#ifndef HASH_TRANSFORM
-#error "HASH_TRANSFORM must be defined!"
-#endif
-#ifndef HASH_FINAL
-#error "HASH_FINAL must be defined!"
-#endif
-
-#ifndef HASH_BLOCK_HOST_ORDER
-#error "HASH_BLOCK_HOST_ORDER must be defined!"
-#endif
-
-#if 0
-/*
- * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
- * isn't defined.
- */
-#ifndef HASH_BLOCK_DATA_ORDER
-#error "HASH_BLOCK_DATA_ORDER must be defined!"
-#endif
-#endif
-
-#ifndef HASH_LBLOCK
-#define HASH_LBLOCK (HASH_CBLOCK/4)
-#endif
-
-#ifndef HASH_LONG_LOG2
-#define HASH_LONG_LOG2  2
-#endif
-
-/*
- * Engage compiler specific rotate intrinsic function if available.
- */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-#endif
-#undef ROTATE
-#ifndef PEDANTIC
-# if 0 /* defined(_MSC_VER) */
-#  define ROTATE(a,n)   _lrotl(a,n)
-# elif defined(__MWERKS__)
-#  if defined(__POWERPC__)
-#   define ROTATE(a,n)  (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
-#  elif defined(__MC68K__)
-/* Motorola specific tweak. <appro@fy.chalmers.se> */
-#   define ROTATE(a,n)  (n<24 ? __rol(a,n) : __ror(a,32-n))
-#  else
-#   define ROTATE(a,n)  __rol(a,n)
-#  endif
-# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-/*
- * Some GNU C inline assembler templates. Note that these are
- * rotates by *constant* number of bits! But that's exactly
- * what we need here...
- *
- *                  <appro@fy.chalmers.se>
- */
-/*
- * LLVM is more strict about compatibility of types between input & output constraints,
- * but we want these to be rotations of 32 bits, not 64, so we explicitly drop the
- * most significant bytes by casting to an unsigned int.
- */
-#  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
-#   define ROTATE(a,n)  ({ register unsigned int ret;   \
-                           asm (           \
-                               "roll %1,%0"        \
-                               : "=r" (ret)     \
-                               : "I" (n), "0" ((unsigned int)a)  \
-                               : "cc");        \
-                           ret;             \
-                         })
-#  elif defined(__powerpc) || defined(__ppc)
-#   define ROTATE(a,n)  ({ register unsigned int ret;   \
-                           asm (           \
-                               "rlwinm %0,%1,%2,0,31"  \
-                               : "=r" (ret)     \
-                               : "r" (a), "I" (n));  \
-                           ret;             \
-                         })
-#  endif
-# endif
-
-/*
- * Engage compiler specific "fetch in reverse byte order"
- * intrinsic function if available.
- */
-# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-/* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
-#  if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
-#   define BE_FETCH32(a)    ({ register unsigned int l=(a); \
-                               asm (           \
-                                   "bswapl %0"     \
-                                   : "=r" (l) : "0" (l));    \
-                               l;                \
-                             })
-#  elif defined(__powerpc)
-#   define LE_FETCH32(a)    ({ register unsigned int l; \
-                               asm (           \
-                                   "lwbrx %0,0,%1"     \
-                                   : "=r" (l)       \
-                                   : "r" (a));      \
-                               l;               \
-                             })
-
-#  elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
-#  define LE_FETCH32(a) ({ register unsigned int l;     \
-                           asm (               \
-                               "lda [%1]#ASI_PRIMARY_LITTLE,%0" \
-                               : "=r" (l)           \
-                               : "r" (a));          \
-                           l;                   \
-                         })
-#  endif
-# endif
-#endif /* PEDANTIC */
-
-#if HASH_LONG_LOG2==2   /* Engage only if sizeof(HASH_LONG)== 4 */
-/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
-#ifdef ROTATE
-/* 5 instructions with rotate instruction, else 9 */
-#define REVERSE_FETCH32(a,l)    (                   \
-        l=*(const HASH_LONG *)(a),              \
-        ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))  \
-        )
-#else
-/* 6 instructions with rotate instruction, else 8 */
-#define REVERSE_FETCH32(a,l)    (               \
-        l=*(const HASH_LONG *)(a),          \
-        l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),    \
-        ROTATE(l,16)                    \
-        )
-/*
- * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
- * It's rewritten as above for two reasons:
- *	- RISCs aren't good at long constants and have to explicitely
- *	  compose 'em with several (well, usually 2) instructions in a
- *	  register before performing the actual operation and (as you
- *	  already realized:-) having same constant should inspire the
- *	  compiler to permanently allocate the only register for it;
- *	- most modern CPUs have two ALUs, but usually only one has
- *	  circuitry for shifts:-( this minor tweak inspires compiler
- *	  to schedule shift instructions in a better way...
- *
- *				<appro@fy.chalmers.se>
- */
-#endif
-#endif
-
-#ifndef ROTATE
-#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
-#endif
-
-/*
- * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
- * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
- * and host are of the same "endianess". It's possible to mask
- * this with blank #define HASH_BLOCK_DATA_ORDER though...
- *
- *				<appro@fy.chalmers.se>
- */
-#if defined(B_ENDIAN)
-#  if defined(DATA_ORDER_IS_BIG_ENDIAN)
-#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
-#      define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
-#    endif
-#  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-#    ifndef HOST_FETCH32
-#      ifdef LE_FETCH32
-#        define HOST_FETCH32(p,l)   LE_FETCH32(p)
-#      elif defined(REVERSE_FETCH32)
-#        define HOST_FETCH32(p,l)   REVERSE_FETCH32(p,l)
-#      endif
-#    endif
-#  endif
-#elif defined(L_ENDIAN)
-#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
-#      define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
-#    endif
-#  elif defined(DATA_ORDER_IS_BIG_ENDIAN)
-#    ifndef HOST_FETCH32
-#      ifdef BE_FETCH32
-#        define HOST_FETCH32(p,l)   BE_FETCH32(p)
-#      elif defined(REVERSE_FETCH32)
-#        define HOST_FETCH32(p,l)   REVERSE_FETCH32(p,l)
-#      endif
-#    endif
-#  endif
-#endif
-
-#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
-#ifndef HASH_BLOCK_DATA_ORDER
-#error "HASH_BLOCK_DATA_ORDER must be defined!"
-#endif
-#endif
-
-// None of the invocations of the following macros actually use the result,
-// so cast them to void to avoid any compiler warnings/errors about not using
-// the result (e.g. when using clang).
-// If the resultant values need to be used at some point, these must be changed.
-#define HOST_c2l(c,l) ((void)_HOST_c2l(c,l))
-#define HOST_l2c(l,c) ((void)_HOST_l2c(l,c))
-
-#if defined(DATA_ORDER_IS_BIG_ENDIAN)
-
-#define _HOST_c2l(c,l)  (l =(((unsigned long)(*((c)++)))<<24),      \
-                         l|=(((unsigned long)(*((c)++)))<<16),      \
-                         l|=(((unsigned long)(*((c)++)))<< 8),      \
-                         l|=(((unsigned long)(*((c)++)))    ),      \
-                         l)
-#define HOST_p_c2l(c,l,n)   {                       \
-        switch (n) {                                \
-        case 0: l =((unsigned long)(*((c)++)))<<24; \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*((c)++)))<<16; \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*((c)++)))<< 8; \
-            fallthrough();                          \
-        case 3: l|=((unsigned long)(*((c)++)));     \
-        } }
-#define HOST_p_c2l_p(c,l,sc,len) {                  \
-        switch (sc) {                               \
-        case 0: l =((unsigned long)(*((c)++)))<<24; \
-            if (--len == 0) break;                  \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*((c)++)))<<16; \
-            if (--len == 0) break;                  \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*((c)++)))<< 8; \
-        } }
-/* NOTE the pointer is not incremented at the end of this */
-#define HOST_c2l_p(c,l,n)   {                       \
-        l=0; (c)+=n;                                \
-        switch (n) {                                \
-        case 3: l =((unsigned long)(*(--(c))))<< 8; \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*(--(c))))<<16; \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*(--(c))))<<24; \
-        } }
-#define _HOST_l2c(l,c)  (*((c)++)=(unsigned char)(((l)>>24)&0xff),  \
-                         *((c)++)=(unsigned char)(((l)>>16)&0xff),  \
-                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),  \
-                         *((c)++)=(unsigned char)(((l)    )&0xff),  \
-                         l)
-
-#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-
-#define _HOST_c2l(c,l)  (l =(((unsigned long)(*((c)++)))    ),      \
-                         l|=(((unsigned long)(*((c)++)))<< 8),      \
-                         l|=(((unsigned long)(*((c)++)))<<16),      \
-                         l|=(((unsigned long)(*((c)++)))<<24),      \
-                         l)
-#define HOST_p_c2l(c,l,n)   {                       \
-        switch (n) {                                \
-        case 0: l =((unsigned long)(*((c)++)));     \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*((c)++)))<< 8; \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*((c)++)))<<16; \
-            fallthrough();                          \
-        case 3: l|=((unsigned long)(*((c)++)))<<24; \
-        } }
-#define HOST_p_c2l_p(c,l,sc,len) {                  \
-        switch (sc) {                               \
-        case 0: l =((unsigned long)(*((c)++)));     \
-            if (--len == 0) break;                  \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*((c)++)))<< 8; \
-            if (--len == 0) break;                  \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*((c)++)))<<16; \
-        } }
-/* NOTE the pointer is not incremented at the end of this */
-#define HOST_c2l_p(c,l,n)   {                       \
-        l=0; (c)+=n;                                \
-        switch (n) {                                \
-        case 3: l =((unsigned long)(*(--(c))))<<16; \
-            fallthrough();                          \
-        case 2: l|=((unsigned long)(*(--(c))))<< 8; \
-            fallthrough();                          \
-        case 1: l|=((unsigned long)(*(--(c))));     \
-        } }
-#define _HOST_l2c(l,c)  (*((c)++)=(unsigned char)(((l)    )&0xff),  \
-                         *((c)++)=(unsigned char)(((l)>> 8)&0xff),  \
-                         *((c)++)=(unsigned char)(((l)>>16)&0xff),  \
-                         *((c)++)=(unsigned char)(((l)>>24)&0xff),  \
-                         l)
-
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-/*
- * Time for some action:-)
- */
-
-int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
-{
-    const unsigned char *data=(const unsigned char *)data_;
-    const unsigned char * const data_end=(const unsigned char *)data_ + len;
-    register HASH_LONG * p;
-    register unsigned long l;
-    int sw,sc,ew,ec;
-
-    if (len==0) return 1;
-
-    l=(c->Nl+(len<<3))&0xffffffffL;
-    /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
-     * Wei Dai <weidai@eskimo.com> for pointing it out. */
-    if (l < c->Nl) /* overflow */
-        c->Nh++;
-    c->Nh+=(len>>29);
-    c->Nl=l;
-
-    if (c->num != 0)
-    {
-        p=c->data;
-        sw=c->num>>2;
-        sc=c->num&0x03;
-
-        if ((c->num+len) >= HASH_CBLOCK)
-        {
-            l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
-            for (; (sw < HASH_LBLOCK) && ((data_end - data) >= 4); sw++)
-            {
-                HOST_c2l(data,l); p[sw]=l;
-            }
-            HASH_BLOCK_HOST_ORDER (c,p,1);
-            len-=(HASH_CBLOCK-c->num);
-            c->num=0;
-            /* drop through and do the rest */
-        }
-        else
-        {
-            c->num+=len;
-            if ((sc+len) < 4) /* ugly, add char's to a word */
-            {
-                l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
-            }
-            else
-            {
-                ew=(c->num>>2);
-                ec=(c->num&0x03);
-                if (sc)
-                    l=p[sw];
-                HOST_p_c2l(data,l,sc);
-                p[sw++]=l;
-                for (; (sw < ew) && ((data_end - data) >= 4); sw++)
-                {
-                    HOST_c2l(data,l); p[sw]=l;
-                }
-                if (ec)
-                {
-                    HOST_c2l_p(data,l,ec); p[sw]=l;
-                }
-            }
-            return 1;
-        }
-    }
-
-    sw=(int)(len/HASH_CBLOCK);
-    if (sw > 0)
-    {
-#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
-        /*
-         * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
-         * only if sizeof(HASH_LONG)==4.
-         */
-        if ((((unsigned long)data)%4) == 0)
-        {
-            /* data is properly aligned so that we can cast it: */
-            HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
-            sw*=HASH_CBLOCK;
-            data+=sw;
-            len-=sw;
-        }
-        else
-#if !defined(HASH_BLOCK_DATA_ORDER)
-            while (sw--)
-            {
-                mDNSPlatformMemCopy(p=c->data,data,HASH_CBLOCK);
-                HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
-                data+=HASH_CBLOCK;
-                len-=HASH_CBLOCK;
-            }
-#endif
-#endif
-#if defined(HASH_BLOCK_DATA_ORDER)
-        {
-            HASH_BLOCK_DATA_ORDER(c,data,sw);
-            sw*=HASH_CBLOCK;
-            data+=sw;
-            len-=sw;
-        }
-#endif
-    }
-
-    if (len!=0)
-    {
-        p = c->data;
-        c->num = (int)len;
-        ew=(int)(len>>2);   /* words to copy */
-        ec=(int)(len&0x03);
-        for (; ew && ((data_end - data) >= 4); ew--,p++)
-        {
-            HOST_c2l(data,l); *p=l;
-        }
-        HOST_c2l_p(data,l,ec);
-        *p=l;
-    }
-    return 1;
-}
-
-
-void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
-{
-#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
-    if ((((unsigned long)data)%4) == 0)
-        /* data is properly aligned so that we can cast it: */
-        HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
-    else
-#if !defined(HASH_BLOCK_DATA_ORDER)
-    {
-        mDNSPlatformMemCopy(c->data,data,HASH_CBLOCK);
-        HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
-    }
-#endif
-#endif
-#if defined(HASH_BLOCK_DATA_ORDER)
-    HASH_BLOCK_DATA_ORDER (c,data,1);
-#endif
-}
-
-
-int HASH_FINAL (unsigned char *md, HASH_CTX *c)
-{
-    register HASH_LONG *p;
-    register unsigned long l;
-    register int i,j;
-    static const unsigned char end[4]={0x80,0x00,0x00,0x00};
-    const unsigned char *cp=end;
-
-    /* c->num should definitly have room for at least one more byte. */
-    p=c->data;
-    i=c->num>>2;
-    j=c->num&0x03;
-
-#if 0
-    /* purify often complains about the following line as an
-     * Uninitialized Memory Read.  While this can be true, the
-     * following p_c2l macro will reset l when that case is true.
-     * This is because j&0x03 contains the number of 'valid' bytes
-     * already in p[i].  If and only if j&0x03 == 0, the UMR will
-     * occur but this is also the only time p_c2l will do
-     * l= *(cp++) instead of l|= *(cp++)
-     * Many thanks to Alex Tang <altitude@cic.net> for pickup this
-     * 'potential bug' */
-#ifdef PURIFY
-    if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
-#endif
-    l=p[i];
-#else
-    l = (j==0) ? 0 : p[i];
-#endif
-    HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
-
-    if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
-    {
-        if (i<HASH_LBLOCK) p[i]=0;
-        HASH_BLOCK_HOST_ORDER (c,p,1);
-        i=0;
-    }
-    for (; i<(HASH_LBLOCK-2); i++)
-        p[i]=0;
-
-#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
-    p[HASH_LBLOCK-2]=c->Nh;
-    p[HASH_LBLOCK-1]=c->Nl;
-#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
-    p[HASH_LBLOCK-2]=c->Nl;
-    p[HASH_LBLOCK-1]=c->Nh;
-#endif
-    HASH_BLOCK_HOST_ORDER (c,p,1);
-
-#ifndef HASH_MAKE_STRING
-#error "HASH_MAKE_STRING must be defined!"
-#else
-    HASH_MAKE_STRING(c,md);
-#endif
-
-    c->num=0;
-    /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
-     * but I'm not worried :-)
-       OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
-     */
-    return 1;
-}
-
-#ifndef MD32_REG_T
-#define MD32_REG_T long
-/*
- * This comment was originaly written for MD5, which is why it
- * discusses A-D. But it basically applies to all 32-bit digests,
- * which is why it was moved to common header file.
- *
- * In case you wonder why A-D are declared as long and not
- * as mDNSu32. Doing so results in slight performance
- * boost on LP64 architectures. The catch is we don't
- * really care if 32 MSBs of a 64-bit register get polluted
- * with eventual overflows as we *save* only 32 LSBs in
- * *either* case. Now declaring 'em long excuses the compiler
- * from keeping 32 MSBs zeroed resulting in 13% performance
- * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
- * Well, to be honest it should say that this *prevents*
- * performance degradation.
- *				<appro@fy.chalmers.se>
- * Apparently there're LP64 compilers that generate better
- * code if A-D are declared int. Most notably GCC-x86_64
- * generates better code.
- *				<appro@fy.chalmers.se>
- */
-#endif
-
-
-// from md5_locl.h (continued)
-
-/*
- #define	F(x,y,z)	(((x) & (y))  |  ((~(x)) & (z)))
- #define	G(x,y,z)	(((x) & (z))  |  ((y) & (~(z))))
- */
-
-/* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
- * simplified to the code below.  Wei attributes these optimizations
- * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
- */
-#define F(b,c,d)    ((((c) ^ (d)) & (b)) ^ (d))
-#define G(b,c,d)    ((((b) ^ (c)) & (d)) ^ (c))
-#define H(b,c,d)    ((b) ^ (c) ^ (d))
-#define I(b,c,d)    (((~(d)) | (b)) ^ (c))
-
-#define R0(a,b,c,d,k,s,t) { \
-        a+=((k)+(t)+F((b),(c),(d))); \
-        a=ROTATE(a,s); \
-        a+=b; }; \
-
-#define R1(a,b,c,d,k,s,t) { \
-        a+=((k)+(t)+G((b),(c),(d))); \
-        a=ROTATE(a,s); \
-        a+=b; };
-
-#define R2(a,b,c,d,k,s,t) { \
-        a+=((k)+(t)+H((b),(c),(d))); \
-        a=ROTATE(a,s); \
-        a+=b; };
-
-#define R3(a,b,c,d,k,s,t) { \
-        a+=((k)+(t)+I((b),(c),(d))); \
-        a=ROTATE(a,s); \
-        a+=b; };
-
-// from md5_dgst.c
-
-
-/* Implemented from RFC1321 The MD5 Message-Digest Algorithm
- */
-
-#define INIT_DATA_A (unsigned long)0x67452301L
-#define INIT_DATA_B (unsigned long)0xefcdab89L
-#define INIT_DATA_C (unsigned long)0x98badcfeL
-#define INIT_DATA_D (unsigned long)0x10325476L
-
-int MD5_Init(MD5_CTX *c)
-{
-    c->A=INIT_DATA_A;
-    c->B=INIT_DATA_B;
-    c->C=INIT_DATA_C;
-    c->D=INIT_DATA_D;
-    c->Nl=0;
-    c->Nh=0;
-    c->num=0;
-    return 1;
-}
-
-#ifndef md5_block_host_order
-void md5_block_host_order (MD5_CTX *c, const void *data, int num)
-{
-    const mDNSu32 *X=(const mDNSu32 *)data;
-    register unsigned MD32_REG_T A,B,C,D;
-
-    A=c->A;
-    B=c->B;
-    C=c->C;
-    D=c->D;
-
-    for (; num--; X+=HASH_LBLOCK)
-    {
-        /* Round 0 */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#endif
-#ifdef __clang__
-#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
-#pragma GCC diagnostic ignored "-Wgnu-statement-expression"
-#endif
-        R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
-        R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
-        R0(C,D,A,B,X[ 2],17,0x242070dbL);
-        R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
-        R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
-        R0(D,A,B,C,X[ 5],12,0x4787c62aL);
-        R0(C,D,A,B,X[ 6],17,0xa8304613L);
-        R0(B,C,D,A,X[ 7],22,0xfd469501L);
-        R0(A,B,C,D,X[ 8], 7,0x698098d8L);
-        R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
-        R0(C,D,A,B,X[10],17,0xffff5bb1L);
-        R0(B,C,D,A,X[11],22,0x895cd7beL);
-        R0(A,B,C,D,X[12], 7,0x6b901122L);
-        R0(D,A,B,C,X[13],12,0xfd987193L);
-        R0(C,D,A,B,X[14],17,0xa679438eL);
-        R0(B,C,D,A,X[15],22,0x49b40821L);
-        /* Round 1 */
-        R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
-        R1(D,A,B,C,X[ 6], 9,0xc040b340L);
-        R1(C,D,A,B,X[11],14,0x265e5a51L);
-        R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
-        R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
-        R1(D,A,B,C,X[10], 9,0x02441453L);
-        R1(C,D,A,B,X[15],14,0xd8a1e681L);
-        R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
-        R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
-        R1(D,A,B,C,X[14], 9,0xc33707d6L);
-        R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
-        R1(B,C,D,A,X[ 8],20,0x455a14edL);
-        R1(A,B,C,D,X[13], 5,0xa9e3e905L);
-        R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
-        R1(C,D,A,B,X[ 7],14,0x676f02d9L);
-        R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
-        /* Round 2 */
-        R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
-        R2(D,A,B,C,X[ 8],11,0x8771f681L);
-        R2(C,D,A,B,X[11],16,0x6d9d6122L);
-        R2(B,C,D,A,X[14],23,0xfde5380cL);
-        R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
-        R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
-        R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
-        R2(B,C,D,A,X[10],23,0xbebfbc70L);
-        R2(A,B,C,D,X[13], 4,0x289b7ec6L);
-        R2(D,A,B,C,X[ 0],11,0xeaa127faL);
-        R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
-        R2(B,C,D,A,X[ 6],23,0x04881d05L);
-        R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
-        R2(D,A,B,C,X[12],11,0xe6db99e5L);
-        R2(C,D,A,B,X[15],16,0x1fa27cf8L);
-        R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
-        /* Round 3 */
-        R3(A,B,C,D,X[ 0], 6,0xf4292244L);
-        R3(D,A,B,C,X[ 7],10,0x432aff97L);
-        R3(C,D,A,B,X[14],15,0xab9423a7L);
-        R3(B,C,D,A,X[ 5],21,0xfc93a039L);
-        R3(A,B,C,D,X[12], 6,0x655b59c3L);
-        R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
-        R3(C,D,A,B,X[10],15,0xffeff47dL);
-        R3(B,C,D,A,X[ 1],21,0x85845dd1L);
-        R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
-        R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
-        R3(C,D,A,B,X[ 6],15,0xa3014314L);
-        R3(B,C,D,A,X[13],21,0x4e0811a1L);
-        R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
-        R3(D,A,B,C,X[11],10,0xbd3af235L);
-        R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
-        R3(B,C,D,A,X[ 9],21,0xeb86d391L);
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-        A = c->A += A;
-        B = c->B += B;
-        C = c->C += C;
-        D = c->D += D;
-    }
-}
-#endif
-
-#ifndef md5_block_data_order
-#ifdef X
-#undef X
-#endif
-void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
-{
-    const unsigned char *data=data_;
-    register unsigned MD32_REG_T A,B,C,D,l;
-#ifndef MD32_XARRAY
-    /* See comment in crypto/sha/sha_locl.h for details. */
-    unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
-                        XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
-# define X(i)   XX ## i
-#else
-    mDNSu32 XX[MD5_LBLOCK];
-# define X(i)   XX[i]
-#endif
-
-    A=c->A;
-    B=c->B;
-    C=c->C;
-    D=c->D;
-
-#if defined(__clang_analyzer__)
-    // Get rid of false positive analyzer warning.
-    for (const unsigned char *_ptr = data; _ptr < &data[num * HASH_CBLOCK]; ++_ptr) {}
-#endif
-    for (; num--;)
-    {
-        HOST_c2l(data,l); X( 0)=l;      HOST_c2l(data,l); X( 1)=l;
-        /* Round 0 */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#endif
-#ifdef __clang__
-#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
-#pragma GCC diagnostic ignored "-Wgnu-statement-expression"
-#endif
-        R0(A,B,C,D,X( 0), 7,0xd76aa478L);   HOST_c2l(data,l); X( 2)=l;
-        R0(D,A,B,C,X( 1),12,0xe8c7b756L);   HOST_c2l(data,l); X( 3)=l;
-        R0(C,D,A,B,X( 2),17,0x242070dbL);   HOST_c2l(data,l); X( 4)=l;
-        R0(B,C,D,A,X( 3),22,0xc1bdceeeL);   HOST_c2l(data,l); X( 5)=l;
-        R0(A,B,C,D,X( 4), 7,0xf57c0fafL);   HOST_c2l(data,l); X( 6)=l;
-        R0(D,A,B,C,X( 5),12,0x4787c62aL);   HOST_c2l(data,l); X( 7)=l;
-        R0(C,D,A,B,X( 6),17,0xa8304613L);   HOST_c2l(data,l); X( 8)=l;
-        R0(B,C,D,A,X( 7),22,0xfd469501L);   HOST_c2l(data,l); X( 9)=l;
-        R0(A,B,C,D,X( 8), 7,0x698098d8L);   HOST_c2l(data,l); X(10)=l;
-        R0(D,A,B,C,X( 9),12,0x8b44f7afL);   HOST_c2l(data,l); X(11)=l;
-        R0(C,D,A,B,X(10),17,0xffff5bb1L);   HOST_c2l(data,l); X(12)=l;
-        R0(B,C,D,A,X(11),22,0x895cd7beL);   HOST_c2l(data,l); X(13)=l;
-        R0(A,B,C,D,X(12), 7,0x6b901122L);   HOST_c2l(data,l); X(14)=l;
-        R0(D,A,B,C,X(13),12,0xfd987193L);   HOST_c2l(data,l); X(15)=l;
-        R0(C,D,A,B,X(14),17,0xa679438eL);
-        R0(B,C,D,A,X(15),22,0x49b40821L);
-        /* Round 1 */
-        R1(A,B,C,D,X( 1), 5,0xf61e2562L);
-        R1(D,A,B,C,X( 6), 9,0xc040b340L);
-        R1(C,D,A,B,X(11),14,0x265e5a51L);
-        R1(B,C,D,A,X( 0),20,0xe9b6c7aaL);
-        R1(A,B,C,D,X( 5), 5,0xd62f105dL);
-        R1(D,A,B,C,X(10), 9,0x02441453L);
-        R1(C,D,A,B,X(15),14,0xd8a1e681L);
-        R1(B,C,D,A,X( 4),20,0xe7d3fbc8L);
-        R1(A,B,C,D,X( 9), 5,0x21e1cde6L);
-        R1(D,A,B,C,X(14), 9,0xc33707d6L);
-        R1(C,D,A,B,X( 3),14,0xf4d50d87L);
-        R1(B,C,D,A,X( 8),20,0x455a14edL);
-        R1(A,B,C,D,X(13), 5,0xa9e3e905L);
-        R1(D,A,B,C,X( 2), 9,0xfcefa3f8L);
-        R1(C,D,A,B,X( 7),14,0x676f02d9L);
-        R1(B,C,D,A,X(12),20,0x8d2a4c8aL);
-        /* Round 2 */
-        R2(A,B,C,D,X( 5), 4,0xfffa3942L);
-        R2(D,A,B,C,X( 8),11,0x8771f681L);
-        R2(C,D,A,B,X(11),16,0x6d9d6122L);
-        R2(B,C,D,A,X(14),23,0xfde5380cL);
-        R2(A,B,C,D,X( 1), 4,0xa4beea44L);
-        R2(D,A,B,C,X( 4),11,0x4bdecfa9L);
-        R2(C,D,A,B,X( 7),16,0xf6bb4b60L);
-        R2(B,C,D,A,X(10),23,0xbebfbc70L);
-        R2(A,B,C,D,X(13), 4,0x289b7ec6L);
-        R2(D,A,B,C,X( 0),11,0xeaa127faL);
-        R2(C,D,A,B,X( 3),16,0xd4ef3085L);
-        R2(B,C,D,A,X( 6),23,0x04881d05L);
-        R2(A,B,C,D,X( 9), 4,0xd9d4d039L);
-        R2(D,A,B,C,X(12),11,0xe6db99e5L);
-        R2(C,D,A,B,X(15),16,0x1fa27cf8L);
-        R2(B,C,D,A,X( 2),23,0xc4ac5665L);
-        /* Round 3 */
-        R3(A,B,C,D,X( 0), 6,0xf4292244L);
-        R3(D,A,B,C,X( 7),10,0x432aff97L);
-        R3(C,D,A,B,X(14),15,0xab9423a7L);
-        R3(B,C,D,A,X( 5),21,0xfc93a039L);
-        R3(A,B,C,D,X(12), 6,0x655b59c3L);
-        R3(D,A,B,C,X( 3),10,0x8f0ccc92L);
-        R3(C,D,A,B,X(10),15,0xffeff47dL);
-        R3(B,C,D,A,X( 1),21,0x85845dd1L);
-        R3(A,B,C,D,X( 8), 6,0x6fa87e4fL);
-        R3(D,A,B,C,X(15),10,0xfe2ce6e0L);
-        R3(C,D,A,B,X( 6),15,0xa3014314L);
-        R3(B,C,D,A,X(13),21,0x4e0811a1L);
-        R3(A,B,C,D,X( 4), 6,0xf7537e82L);
-        R3(D,A,B,C,X(11),10,0xbd3af235L);
-        R3(C,D,A,B,X( 2),15,0x2ad7d2bbL);
-        R3(B,C,D,A,X( 9),21,0xeb86d391L);
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-        A = c->A += A;
-        B = c->B += B;
-        C = c->C += C;
-        D = c->D += D;
-    }
-}
-#endif
-
-
-// ***************************************************************************
-// MARK: - base64 -> binary conversion
-
-static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-
-#define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
-
-mDNSlocal const char *mDNSstrchr(const char *s, int c)
-{
-    while (1)
-    {
-        if (c == *s) return s;
-        if (!*s) return mDNSNULL;
-        s++;
-    }
-}
-
-// skips all whitespace anywhere.
-// converts characters, four at a time, starting at (or after)
-// src from base - 64 numbers into three 8 bit bytes in the target area.
-// it returns the number of data bytes stored at the target, or -1 on error.
-// adapted from BIND sources
-
-mDNSlocal mDNSs32 DNSDigest_Base64ToBin(const char *src, mDNSu8 *target, mDNSu32 targsize)
-{
-    int tarindex, state, ch;
-    const char *pos;
-
-    state = 0;
-    tarindex = 0;
-
-    while ((ch = *src++) != '\0') {
-        if (mDNSisspace(ch))    /* Skip whitespace anywhere. */
-            continue;
-
-        if (ch == Pad64)
-            break;
-
-        pos = mDNSstrchr(Base64, ch);
-        if (pos == 0)       /* A non-base64 character. */
-            return (-1);
-
-        switch (state) {
-        case 0:
-            if (target) {
-                if ((mDNSu32)tarindex >= targsize)
-                    return (-1);
-                target[tarindex] = (mDNSu8)((pos - Base64) << 2);
-            }
-            state = 1;
-            break;
-        case 1:
-            if (target) {
-                if ((mDNSu32)tarindex + 1 >= targsize)
-                    return (-1);
-                target[tarindex]   |=  (pos - Base64) >> 4;
-                target[tarindex+1]  = (mDNSu8)(((pos - Base64) & 0x0f) << 4);
-            }
-            tarindex++;
-            state = 2;
-            break;
-        case 2:
-            if (target) {
-                if ((mDNSu32)tarindex + 1 >= targsize)
-                    return (-1);
-                target[tarindex]   |=  (pos - Base64) >> 2;
-                target[tarindex+1]  = (mDNSu8)(((pos - Base64) & 0x03) << 6);
-            }
-            tarindex++;
-            state = 3;
-            break;
-        case 3:
-            if (target) {
-                if ((mDNSu32)tarindex >= targsize)
-                    return (-1);
-                target[tarindex] |= (pos - Base64);
-            }
-            tarindex++;
-            state = 0;
-            break;
-        default:
-            return -1;
-        }
-    }
-
-    /*
-     * We are done decoding Base-64 chars.  Let's see if we ended
-     * on a byte boundary, and/or with erroneous trailing characters.
-     */
-
-    if (ch == Pad64) {      /* We got a pad char. */
-        ch = *src++;        /* Skip it, get next. */
-        switch (state) {
-        case 0:     /* Invalid = in first position */
-        case 1:     /* Invalid = in second position */
-            return (-1);
-
-        case 2:     /* Valid, means one byte of info */
-            /* Skip any number of spaces. */
-            for ((void)mDNSNULL; ch != '\0'; ch = *src++)
-                if (!mDNSisspace(ch))
-                    break;
-            /* Make sure there is another trailing = sign. */
-            if (ch != Pad64)
-                return (-1);
-            ch = *src++;        /* Skip the = */
-        /* Fall through to "single trailing =" case. */
-        /* FALLTHROUGH */
-
-        case 3:     /* Valid, means two bytes of info */
-            /*
-             * We know this char is an =.  Is there anything but
-             * whitespace after it?
-             */
-            for ((void)mDNSNULL; ch != '\0'; ch = *src++)
-                if (!mDNSisspace(ch))
-                    return (-1);
-
-            /*
-             * Now make sure for cases 2 and 3 that the "extra"
-             * bits that slopped past the last full byte were
-             * zeros.  If we don't check them, they become a
-             * subliminal channel.
-             */
-            if (target && target[tarindex] != 0)
-                return (-1);
-        }
-    } else {
-        /*
-         * We ended by seeing the end of the string.  Make sure we
-         * have no partial bytes lying around.
-         */
-        if (state != 0)
-            return (-1);
-    }
-
-    return (tarindex);
-}
-
-
-// ***************************************************************************
-// MARK: - API exported to mDNS Core
-
-// TSIG HMAC names from <https://datatracker.ietf.org/doc/html/rfc8945#section-6>
-// Currently, we do not support the truncated algorithms listed by the link above.
-
-#define kHMAC_MD5_AlgName    ((const domainname *)"\x8" "hmac-md5" "\x7" "sig-alg" "\x3" "reg" "\x3" "int")
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-
-#define kHMAC_None_AlgName      ((const domainname *)"\xC" "hmac-invalid")
-#define kHMAC_SHA1_AlgName      ((const domainname *)"\x9" "hmac-sha1")
-#define kHMAC_SHA224_AlgName    ((const domainname *)"\xB" "hmac-sha224")
-#define kHMAC_SHA256_AlgName    ((const domainname *)"\xB" "hmac-sha256")
-#define kHMAC_SHA384_AlgName    ((const domainname *)"\xB" "hmac-sha384")
-#define kHMAC_SHA512_AlgName    ((const domainname *)"\xB" "hmac-sha512")
-
-// Since each HMAC algorithm has the most secure key length, we use the key length to determine which HMAC algorithm
-// should be used.
-mDNSlocal DNSDigest_HMACAlgorithm DNSDigest_GetHMACAlgorithmFromKeyLengthInBytes(const mDNSu32 length)
-{
-    switch (length) {
-        case kDNSDigest_HMACMD5_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_MD5;
-        case kDNSDigest_HMACSHA1_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_SHA1;
-        case kDNSDigest_HMACSHA224_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_SHA224;
-        case kDNSDigest_HMACSHA256_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_SHA256;
-        case kDNSDigest_HMACSHA384_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_SHA384;
-        case kDNSDigest_HMACSHA512_KeyLengthInBytes:
-            return kDNSDigest_HMACAlg_SHA512;
-        default:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Invalid HMAC key length, unable to get algorithm type"
-                " - key length: %u", length);
-            return kDNSDigest_HMACAlg_None;
-    }
-}
-
-// Convert DNSDigest_HMACAlgorithm to CCHmacAlgorithm that is used by CoreCrypto.
-mDNSlocal CCHmacAlgorithm DNSDigest_GetCCHmacAlgorithm(const DNSDigest_HMACAlgorithm algorithm)
-{
-    switch (algorithm) {
-        case kDNSDigest_HMACAlg_None:
-            return kCCHmacAlgSHA512;
-        case kDNSDigest_HMACAlg_MD5:
-            return kCCHmacAlgMD5;
-        case kDNSDigest_HMACAlg_SHA1:
-            return kCCHmacAlgSHA1;
-        case kDNSDigest_HMACAlg_SHA224:
-            return kCCHmacAlgSHA224;
-        case kDNSDigest_HMACAlg_SHA256:
-            return kCCHmacAlgSHA256;
-        case kDNSDigest_HMACAlg_SHA384:
-            return kCCHmacAlgSHA384;
-        case kDNSDigest_HMACAlg_SHA512:
-            return kCCHmacAlgSHA512;
-    }
-}
-
-// Get the signature output length of each algorithm.
-mDNSlocal mDNSu16 DNSDigest_GetHMACOutputLength(const DNSDigest_HMACAlgorithm algorithm)
-{
-    switch (algorithm) {
-        case kDNSDigest_HMACAlg_None:
-            return 0;
-        case kDNSDigest_HMACAlg_MD5:
-            return kDNSDigest_HMACMD5_OutputLengthInBytes;
-        case kDNSDigest_HMACAlg_SHA1:
-            return kDNSDigest_HMACSHA1_OutputLengthInBytes;
-        case kDNSDigest_HMACAlg_SHA224:
-            return kDNSDigest_HMACSHA224_OutputLengthInBytes;
-        case kDNSDigest_HMACAlg_SHA256:
-            return kDNSDigest_HMACSHA256_OutputLengthInBytes;
-        case kDNSDigest_HMACAlg_SHA384:
-            return kDNSDigest_HMACSHA384_OutputLengthInBytes;
-        case kDNSDigest_HMACAlg_SHA512:
-            return kDNSDigest_HMACSHA512_OutputLengthInBytes;
-    }
-}
-
-// Get the domain name format algorithm identifier for the given algorithm.
-mDNSlocal const domainname *DNSDigest_GetHMACName(const DNSDigest_HMACAlgorithm algorithm)
-{
-    switch (algorithm) {
-        case kDNSDigest_HMACAlg_None:
-            return kHMAC_None_AlgName;
-        case kDNSDigest_HMACAlg_MD5:
-            return kHMAC_MD5_AlgName;
-        case kDNSDigest_HMACAlg_SHA1:
-            return kHMAC_SHA1_AlgName;
-        case kDNSDigest_HMACAlg_SHA224:
-            return kHMAC_SHA224_AlgName;
-        case kDNSDigest_HMACAlg_SHA256:
-            return kHMAC_SHA256_AlgName;
-        case kDNSDigest_HMACAlg_SHA384:
-            return kHMAC_SHA384_AlgName;
-        case kDNSDigest_HMACAlg_SHA512:
-            return kHMAC_SHA512_AlgName;
-    }
-}
-
-// Get the algorithm enum given the domain name format algorithm identifier.
-mDNSlocal DNSDigest_HMACAlgorithm DNSDigest_GetHMACAlgorithmFromName(const domainname *const algorithmName)
-{
-    if (algorithmName == mDNSNULL)
-    {
-        return kDNSDigest_HMACAlg_None;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_MD5_AlgName))
-    {
-        return kDNSDigest_HMACAlg_MD5;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_SHA1_AlgName))
-    {
-        return kDNSDigest_HMACAlg_SHA1;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_SHA224_AlgName))
-    {
-        return kDNSDigest_HMACAlg_SHA224;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_SHA256_AlgName))
-    {
-        return kDNSDigest_HMACAlg_SHA256;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_SHA384_AlgName))
-    {
-        return kDNSDigest_HMACAlg_SHA384;
-    }
-    else if (SameDomainName(algorithmName, kHMAC_SHA512_AlgName))
-    {
-        return kDNSDigest_HMACAlg_SHA512;
-    }
-    else
-    {
-        return kDNSDigest_HMACAlg_None;
-    }
-}
-
-#else // MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-
-// Constants
-#define HMAC_IPAD   0x36
-#define HMAC_OPAD   0x5c
-#define MD5_LEN     16
-
-// Adapted from Appendix, RFC 2104
-mDNSlocal void DNSDigest_ConstructHMACKey(DomainAuthInfo *info, const mDNSu8 *key, mDNSu32 len)
-{
-    MD5_CTX k;
-    mDNSu8 buf[MD5_LEN];
-    int i;
-
-    // If key is longer than HMAC_LEN reset it to MD5(key)
-    if (len > HMAC_LEN)
-    {
-        MD5_Init(&k);
-        MD5_Update(&k, key, len);
-        MD5_Final(buf, &k);
-        key = buf;
-        len = MD5_LEN;
-    }
-
-    // store key in pads
-    mDNSPlatformMemZero(info->keydata_ipad, HMAC_LEN);
-    mDNSPlatformMemZero(info->keydata_opad, HMAC_LEN);
-    mDNSPlatformMemCopy(info->keydata_ipad, key, len);
-    mDNSPlatformMemCopy(info->keydata_opad, key, len);
-
-    // XOR key with ipad and opad values
-    for (i = 0; i < HMAC_LEN; i++)
-    {
-        info->keydata_ipad[i] ^= HMAC_IPAD;
-        info->keydata_opad[i] ^= HMAC_OPAD;
-    }
-
-}
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-
-mDNSexport mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key)
-{
-    mDNSu8 keybuf[1024];
-    mDNSs32 keylen = DNSDigest_Base64ToBin(b64key, keybuf, sizeof(keybuf));
-    if (keylen < 0) return(keylen);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    info->key_len = (mDNSu32)keylen;
-    info->algorithm = DNSDigest_GetHMACAlgorithmFromKeyLengthInBytes(info->key_len);
-    if (info->algorithm == kDNSDigest_HMACAlg_None)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "Invalid HMAC secret key length, should be 16(HMAC MD5), 20(HMAC SHA1), 28(HMAC SHA224), 32(HMAC SHA256), 48(HMAC SHA384) or 64(HMAC SHA512)"
-            " - actual length: %u", info->key_len);
-        return -1;
-    }
-
-    if (sizeof(info->key) < (size_t)keylen)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Key is too long, unable to save it in the buffer - "
-            "buffer length: %zu, actual key length: %d", sizeof(info->key), keylen);
-        return -1;
-    }
-    memcpy(info->key, keybuf, keylen);
-#else
-    DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
-#endif
-
-    return(keylen);
-}
-
-mDNSexport void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode)
-{
-    AuthRecord tsig;
-    mDNSu8  *rdata, *const countPtr = (mDNSu8 *)&msg->h.numAdditionals; // Get existing numAdditionals value
-    mDNSu32 utc32;
-    mDNSu8 utc48[6];
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    mDNSu8 digest[kDNSDigest_HMACOutputLengthInBytesMAX];
-#else
-    mDNSu8 digest[MD5_LEN];
-#endif
-    mDNSu8 *ptr = *end;
-    mDNSu32 len;
-    mDNSOpaque16 buf;
-    mDNSu16 numAdditionals = (mDNSu16)((mDNSu16)countPtr[0] << 8 | countPtr[1]);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    const DNSDigest_HMACAlgorithm algorithm = info->algorithm;
-    CCHmacContext hmacContext;
-#else
-    MD5_CTX c;
-#endif
-
-    // Initialize HMAC context.
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacInit(&hmacContext, DNSDigest_GetCCHmacAlgorithm(algorithm), info->key, info->key_len);
-#else
-    // Init MD5 context, digest inner key pad and message
-    MD5_Init(&c);
-    MD5_Update(&c, info->keydata_ipad, HMAC_LEN);
-#endif
-
-    // Digest the entire DNS message.
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, (mDNSu8 *)msg, (size_t)(*end - (mDNSu8 *)msg));
-#else
-    MD5_Update(&c, (mDNSu8 *)msg, (unsigned long)(*end - (mDNSu8 *)msg));
-#endif
-
-    // Construct TSIG RR, digesting variables as apporpriate
-    mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-
-    // key name
-    AssignDomainName(&tsig.namestorage, &info->keyname);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, info->keyname.c, DomainNameLength(&info->keyname));
-#else
-    MD5_Update(&c, info->keyname.c, DomainNameLength(&info->keyname));
-#endif
-
-    // class
-    tsig.resrec.rrclass = kDNSQClass_ANY;
-    buf = mDNSOpaque16fromIntVal(kDNSQClass_ANY);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
-#endif
-
-    // ttl
-    tsig.resrec.rroriginalttl = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
-#else
-    MD5_Update(&c, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
-#endif
-
-    // alg name
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    const domainname *const algorithmName = DNSDigest_GetHMACName(algorithm);
-#else
-    const domainname *const algorithmName = kHMAC_MD5_AlgName;
-#endif
-
-    AssignDomainName(&tsig.resrec.rdata->u.name, algorithmName);
-    len = DomainNameLength(algorithmName);
-    rdata = tsig.resrec.rdata->u.data + len;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, (mDNSu8 *)algorithmName, len);
-#else
-    MD5_Update(&c, (mDNSu8 *)algorithmName, len);
-#endif
-
-    // time
-    // get UTC (universal time), convert to 48-bit unsigned in network byte order
-    utc32 = (mDNSu32)mDNSPlatformUTC();
-    if (utc32 == (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); *end = mDNSNULL; }
-    utc48[0] = 0;
-    utc48[1] = 0;
-    utc48[2] = (mDNSu8)((utc32 >> 24) & 0xff);
-    utc48[3] = (mDNSu8)((utc32 >> 16) & 0xff);
-    utc48[4] = (mDNSu8)((utc32 >>  8) & 0xff);
-    utc48[5] = (mDNSu8)( utc32        & 0xff);
-
-    mDNSPlatformMemCopy(rdata, utc48, 6);
-    rdata += 6;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, utc48, 6);
-#else
-    MD5_Update(&c, utc48, 6);
-#endif
-
-    // 300 sec is fudge recommended in RFC 2485
-    rdata[0] = (mDNSu8)((300 >> 8)  & 0xff);
-    rdata[1] = (mDNSu8)( 300        & 0xff);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, rdata, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, rdata, sizeof(mDNSOpaque16));
-#endif
-    rdata += sizeof(mDNSOpaque16);
-
-    // digest error (tcode) and other data len (zero) - we'll add them to the rdata later
-    buf.b[0] = (mDNSu8)((tcode >> 8) & 0xff);
-    buf.b[1] = (mDNSu8)( tcode       & 0xff);
-
-    // error code
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
-#endif
-
-    // other data len
-    buf.NotAnInteger = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
-#endif
-
-    mDNSu16 digestLen = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacFinal(&hmacContext, digest);
-    digestLen = DNSDigest_GetHMACOutputLength(algorithm);
-#else
-    // finish the message & tsig var hash
-    MD5_Final(digest, &c);
-
-    // perform outer MD5 (outer key pad, inner digest)
-    MD5_Init(&c);
-    MD5_Update(&c, info->keydata_opad, HMAC_LEN);
-    MD5_Update(&c, digest, MD5_LEN);
-    MD5_Final(digest, &c);
-    digestLen = MD5_LEN;
-#endif
-
-    // set remaining rdata fields
-    rdata[0] = (mDNSu8)((digestLen >> 8)  & 0xff);
-    rdata[1] = (mDNSu8)( digestLen        & 0xff);
-    rdata += sizeof(mDNSOpaque16);
-    mDNSPlatformMemCopy(rdata, digest, digestLen);                        // MAC
-    rdata += digestLen;
-    rdata[0] = msg->h.id.b[0];                                            // original ID
-    rdata[1] = msg->h.id.b[1];
-    rdata[2] = (mDNSu8)((tcode >> 8) & 0xff);
-    rdata[3] = (mDNSu8)( tcode       & 0xff);
-    rdata[4] = 0;                                                         // other data len
-    rdata[5] = 0;
-    rdata += 6;
-
-    tsig.resrec.rdlength = (mDNSu16)(rdata - tsig.resrec.rdata->u.data);
-    *end = PutResourceRecordTTLJumbo(msg, ptr, &numAdditionals, &tsig.resrec, 0);
-    if (!*end) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); *end = mDNSNULL; return; }
-
-    // Write back updated numAdditionals value
-    countPtr[0] = (mDNSu8)(numAdditionals >> 8);
-    countPtr[1] = (mDNSu8)(numAdditionals &  0xFF);
-}
-
-mDNSexport mDNSBool DNSDigest_VerifyMessage(const DNSMessage *const msg, const mDNSu8 *const end,
-    const LargeCacheRecord *const lcr, const DomainAuthInfo *const info, mDNSu16 *const rcode, mDNSu16 *const tcode)
-{
-    mDNSu8          *   ptr = (mDNSu8*) &lcr->r.resrec.rdata->u.data;
-    mDNSs32 now;
-    mDNSs32 then;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    mDNSu8 thisDigest[kDNSDigest_HMACOutputLengthInBytesMAX];
-    mDNSu8 thatDigest[kDNSDigest_HMACOutputLengthInBytesMAX];
-#else
-    mDNSu8 thisDigest[MD5_LEN];
-    mDNSu8 thatDigest[MD5_LEN];
-#endif
-    mDNSOpaque16 buf;
-    mDNSu8 utc48[6];
-    mDNSs32 delta;
-    mDNSu16 fudge;
-    domainname      *   algo;
-    mDNSBool ok = mDNSfalse;
-
-    // We only support HMAC-MD5 for now
-
-    algo = (domainname*) ptr;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    const DNSDigest_HMACAlgorithm algorithm = DNSDigest_GetHMACAlgorithmFromName(algo);
-    CCHmacContext hmacContext;
-    if (algorithm == kDNSDigest_HMACAlg_None || algorithm != info->algorithm)
-#else
-    MD5_CTX c;
-    if (!SameDomainName(algo, kHMAC_MD5_AlgName))
-#endif
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "TSIG algorithm not supported - "
-            "algorithm name: " PUB_DM_NAME, DM_NAME_PARAM(algo));
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadKey;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    ptr += DomainNameLength(algo);
-
-    // Check the times
-
-    now = mDNSPlatformUTC();
-    if (now == -1)
-    {
-        LogMsg("ERROR: DNSDigest_VerifyMessage - mDNSPlatformUTC returned bad time -1");
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadTime;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    // Get the 48 bit time field, skipping over the first word
-
-    utc48[0] = *ptr++;
-    utc48[1] = *ptr++;
-    utc48[2] = *ptr++;
-    utc48[3] = *ptr++;
-    utc48[4] = *ptr++;
-    utc48[5] = *ptr++;
-
-    then  = (mDNSs32)NToH32(utc48 + sizeof(mDNSu16));
-
-    fudge = NToH16(ptr);
-
-    ptr += sizeof(mDNSu16);
-
-    delta = (now > then) ? now - then : then - now;
-
-    if (delta > fudge)
-    {
-        LogMsg("ERROR: DNSDigest_VerifyMessage - time skew > %d", fudge);
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadTime;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    // MAC size
-
-    const mDNSu16 hmacLength = NToH16(ptr);
-    ptr += sizeof(mDNSu16);
-
-    // MAC
-
-    mDNSPlatformMemCopy(thatDigest, ptr, hmacLength);
-
-    // Initialize HMAC context.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacInit(&hmacContext, DNSDigest_GetCCHmacAlgorithm(algorithm), info->key, info->key_len);
-#else
-    // Init MD5 context, digest inner key pad and message
-    MD5_Init(&c);
-    MD5_Update(&c, info->keydata_ipad, HMAC_LEN);
-#endif
-
-    // Digest the entire DNS message.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, (mDNSu8 *)msg, (size_t)(end - (mDNSu8 *)msg));
-#else
-    MD5_Update(&c, (mDNSu8*) msg, (unsigned long)(end - (mDNSu8*) msg));
-#endif
-
-    // Key name
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, lcr->r.resrec.name->c, DomainNameLength(lcr->r.resrec.name));
-#else
-    MD5_Update(&c, lcr->r.resrec.name->c, DomainNameLength(lcr->r.resrec.name));
-#endif
-
-    // Class name
-
-    buf = mDNSOpaque16fromIntVal(lcr->r.resrec.rrclass);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
-#endif
-
-    // TTL
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, (mDNSu8 *) &lcr->r.resrec.rroriginalttl, sizeof(lcr->r.resrec.rroriginalttl));
-#else
-    MD5_Update(&c, (mDNSu8*) &lcr->r.resrec.rroriginalttl, sizeof(lcr->r.resrec.rroriginalttl));
-#endif
-
-    // Algorithm
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, algo->c, DomainNameLength(algo));
-#else
-    MD5_Update(&c, algo->c, DomainNameLength(algo));
-#endif
-
-    // Time
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, utc48, 6);
-#else
-    MD5_Update(&c, utc48, 6);
-#endif
-
-    // Fudge
-
-    buf = mDNSOpaque16fromIntVal(fudge);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16));
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
-#endif
-
-    // Digest error and other data len (both zero) - we'll add them to the rdata later
-
-    buf.NotAnInteger = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16)); // error
-    CCHmacUpdate(&hmacContext, buf.b, sizeof(mDNSOpaque16)); // other data len
-#else
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // error
-    MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // other data len
-#endif
-
-    // Get the HMAC output.
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    mDNSu16 digestLen = 0;
-    CCHmacFinal(&hmacContext, thisDigest);
-    digestLen = DNSDigest_GetHMACOutputLength(algorithm);
-#else
-    // Finish the message & tsig var hash
-
-    MD5_Final(thisDigest, &c);
-
-    // perform outer MD5 (outer key pad, inner digest)
-
-    MD5_Init(&c);
-    MD5_Update(&c, info->keydata_opad, HMAC_LEN);
-    MD5_Update(&c, thisDigest, MD5_LEN);
-    MD5_Final(thisDigest, &c);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    // The MAC must be verified by comparing the computed and expected values using timingsafe_bcmp. Other comparison
-    // functions (e.g. memcmp) must not be used as they may be vulnerable to practical timing attacks, leading to MAC
-    // forgery.
-    if (timingsafe_bcmp(thisDigest, thatDigest, digestLen))
-#else
-    if (!mDNSPlatformMemSame(thisDigest, thatDigest, MD5_LEN))
-#endif
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "DNSDigest_VerifyMessage - bad signature");
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadSig;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    // set remaining rdata fields
-    ok = mDNStrue;
-
-exit:
-
-    return ok;
-}
-
-#if defined(DEBUG) && DEBUG
-
-// This function is used for debug purpose to ensure that the signature generated by DNSDigest_SignMessage can be
-// authenticated by DNSDigest_VerifyMessage.
-mDNSexport void DNSDigest_VerifyMessage_Verify(DNSMessage *const msg, const mDNSu8 *const end,
-    const DomainAuthInfo *const authInfo)
-{
-    // Convert from network byte order to host byte order.
-    SwapDNSHeaderBytes(msg);
-
-    // Locate the TSIG record in the additional section.
-    mDNSBool verified;
-    if (!msg->h.numAdditionals)
-    {
-        verified = mDNSfalse;
-        goto exit;
-    }
-
-    const mDNSu8 *ptr = LocateAdditionals(msg, end);
-    if (!ptr)
-    {
-        verified = mDNSfalse;
-        goto exit;
-    }
-
-    const mDNSu8 *lastPtr = mDNSNULL;
-    LargeCacheRecord lcr = {0};
-    mDNSBool hasTSIGAtLast = mDNSfalse;
-    for (mDNSu32 i = 0; i < msg->h.numAdditionals; i++)
-    {
-        lastPtr = ptr;
-        ptr = GetLargeResourceRecord(mDNSNULL, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
-        if (!ptr)
-        {
-            verified = mDNSfalse;
-            goto exit;
-        }
-
-        if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG &&
-            i == msg->h.numAdditionals - 1)
-        {
-            hasTSIGAtLast = mDNStrue;
-        }
-    }
-
-    if (!hasTSIGAtLast)
-    {
-        verified = mDNSfalse;
-        goto exit;
-    }
-
-    // Before doing verification, decrement the additional count by 1 (added by the TSIG record)
-    // Also go back to network byte order.
-    msg->h.numAdditionals--;
-    SwapDNSHeaderBytes(msg);
-
-    mDNSu16 rcode;
-    mDNSu16 tcode;
-    verified = DNSDigest_VerifyMessage(msg, lastPtr, &lcr, authInfo, &rcode, &tcode);
-
-    // Undo the operation above.
-    SwapDNSHeaderBytes(msg);
-    msg->h.numAdditionals++;
-
-exit:
-    if (!verified)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Failed to verify that DNSDigest_VerifyMessage works.");
-    }
-    SwapDNSHeaderBytes(msg);
-}
-
-#endif // defined(DEBUG) && DEBUG
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c
deleted file mode 100644
index 6697958..0000000
--- a/mDNSCore/mDNS.c
+++ /dev/null
@@ -1,17643 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- *
- * 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 compile 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).
- */
-
-#include "DNSCommon.h"                  // Defines general DNS utility routines
-
-#include "mdns_strict.h"
-
-#include "uDNS.h"                       // Defines entry points into unicast-specific routines
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-#include "D2D.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-#include <bsm/libbsm.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-#include "SymptomReporter.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-#include "resolved_cache.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-// 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 "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
-
-#include "dns_sd.h" // for kDNSServiceFlags* definitions
-#include "dns_sd_internal.h"
-
-
-#ifndef MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-#define MDNS_LOG_ANSWER_SUPPRESSION_TIMES 0
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-#include <WebFilterDNS/WebFilterDNS.h>
-
-WCFConnection *WCFConnectionNew(void) __attribute__((weak_import));
-void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-#include "DNS64.h"
-#endif
-
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-#include "discover_resolver.h" // For resolver_discovery_process().
-#include "tls-keychain.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-#include "system_utilities.h" // For is_apple_internal_build().
-#endif
-
-// Forward declarations
-extern mDNS mDNSStorage; // NOLINT(misc-uninitialized-record-variable): Initialized by mDNS_InitStorage().
-mDNSlocal void BeginSleepProcessing(mDNS *const m);
-mDNSlocal void RetrySPSRegistrations(mDNS *const m);
-mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
-#endif
-mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q);
-mDNSlocal void mDNS_SendKeepalives(mDNS *const m);
-mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth,
-                                         mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win);
-
-typedef mDNSu32 DeadvertiseFlags;
-#define kDeadvertiseFlag_NormalHostname (1U << 0)
-#define kDeadvertiseFlag_RandHostname   (1U << 1)
-#define kDeadvertiseFlag_All            (kDeadvertiseFlag_NormalHostname | kDeadvertiseFlag_RandHostname)
-
-mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set, DeadvertiseFlags flags);
-mDNSlocal void AdvertiseInterfaceIfNeeded(mDNS *const m, NetworkInterfaceInfo *set);
-mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-typedef mdns_dns_service_t DNSServRef;
-#else
-typedef DNSServer *DNSServRef;
-#endif
-
-mDNSlocal void MakeNegativeCacheRecord(mDNS *m, CacheRecord *cr, const domainname *name, mDNSu32 namehash, mDNSu16 rrtype,
-    mDNSu16 rrclass, mDNSu32 ttl, mDNSInterfaceID InterfaceID, DNSServRef dnsserv, mDNSOpaque16 responseFlags);
-
-mDNSlocal mStatus mDNS_SetUpDomainEnumeration(mDNS *m, DomainEnumerationOp *op, mDNS_DomainType type);
-
-// ***************************************************************************
-// MARK: - Program Constants
-
-// To Turn OFF mDNS_Tracer set MDNS_TRACER to 0 or undef it
-#define MDNS_TRACER 1
-
-// Any records bigger than this are considered 'large' records
-#define SmallRecordLimit 1024
-
-#define kMaxUpdateCredits 10
-#define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
-
-// define special NR_AnswerTo values
-#define NR_AnswerMulticast  (mDNSu8*)~0
-#define NR_AnswerUnicast    (mDNSu8*)~1
-
-// Question default timeout values
-#define DEFAULT_MCAST_TIMEOUT       5
-#define DEFAULT_LO_OR_P2P_TIMEOUT   5
-
-// The code (see SendQueries() and BuildQuestion()) needs to have the
-// RequestUnicast value set to a value one greater than the number of times you want the query
-// sent with the "request unicast response" (QU) bit set.
-#define SET_QU_IN_FIRST_QUERY   2
-#define kDefaultRequestUnicastCount SET_QU_IN_FIRST_QUERY
-
-// The time needed to offload records to a sleep proxy after powerd sends the kIOMessageSystemWillSleep notification
-#define DARK_WAKE_DELAY_SLEEP  5
-#define kDarkWakeDelaySleep    (mDNSPlatformOneSecond * DARK_WAKE_DELAY_SLEEP)
-
-// RFC 6762 defines Passive Observation Of Failures (POOF)
-//
-//    A host observes the multicast queries issued by the other hosts on
-//    the network.  One of the major benefits of also sending responses
-//    using multicast is that it allows all hosts to see the responses
-//    (or lack thereof) to those queries.
-//
-//    If a host sees queries, for which a record in its cache would be
-//    expected to be given as an answer in a multicast response, but no
-//    such answer is seen, then the host may take this as an indication
-//    that the record may no longer be valid.
-//
-//    After seeing two or more of these queries, and seeing no multicast
-//    response containing the expected answer within ten seconds, then even
-//    though its TTL may indicate that it is not yet due to expire, that
-//    record SHOULD be flushed from the cache.
-//
-// <https://tools.ietf.org/html/rfc6762#section-10.5>
-
-#define POOF_ENABLED 1
-
-mDNSexport const char *const mDNS_DomainTypeNames[] =
-{
-    "b._dns-sd._udp.",      // Browse
-    "db._dns-sd._udp.",     // Default Browse
-    "lb._dns-sd._udp.",     // Automatic Browse
-    "r._dns-sd._udp.",      // Registration
-    "dr._dns-sd._udp."      // Default Registration
-};
-
-#ifdef UNICAST_DISABLED
-#define uDNS_IsActiveQuery(q, u) mDNSfalse
-#endif
-
-// ***************************************************************************
-// MARK: - General Utility Functions
-
-#if MDNS_MALLOC_DEBUGGING
-// When doing memory allocation debugging, this function traverses all lists in the mDNS query
-// structures and caches and checks each entry in the list to make sure it's still good.
-mDNSlocal void mDNS_ValidateLists(void *context)
-{
-    mDNS *m = context;
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    mDNSu32 NumAllInterfaceRecords   = 0;
-    mDNSu32 NumAllInterfaceQuestions = 0;
-#endif
-
-    // Check core mDNS lists
-    AuthRecord                  *rr;
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-            LogMemCorruption("ResourceRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
-        if (rr->resrec.name != &rr->namestorage)
-            LogMemCorruption("ResourceRecords list: %p name %p does not point to namestorage %p %##s",
-                             rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c);
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-        if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
-#endif
-    }
-
-    for (rr = m->DuplicateRecords; rr; rr=rr->next)
-    {
-        if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-            LogMemCorruption("DuplicateRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-        if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
-#endif
-    }
-
-    rr = m->NewLocalRecords;
-    if (rr)
-        if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-            LogMemCorruption("NewLocalRecords: %p is garbage (%X)", rr, rr->resrec.RecordType);
-
-    rr = m->CurrentRecord;
-    if (rr)
-        if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
-            LogMemCorruption("CurrentRecord: %p is garbage (%X)", rr, rr->resrec.RecordType);
-
-    DNSQuestion                 *q;
-    for (q = m->Questions; q; q=q->next)
-    {
-        if (q->next == (DNSQuestion*)~0 || q->ThisQInterval == (mDNSs32) ~0)
-            LogMemCorruption("Questions list: %p is garbage (%lX %p)", q, q->ThisQInterval, q->next);
-        if (q->DuplicateOf && q->LocalSocket)
-            LogMemCorruption("Questions list: Duplicate Question %p should not have LocalSocket set %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-        if (!LocalOnlyOrP2PInterface(q->InterfaceID) && mDNSOpaque16IsZero(q->TargetQID))
-            NumAllInterfaceQuestions++;
-#endif
-    }
-
-    CacheGroup                  *cg;
-    CacheRecord                 *cr;
-    mDNSu32 slot;
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
-            LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType);
-        if (cr->CRActiveQuestion)
-        {
-            for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break;
-            if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr));
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    if (m->NumAllInterfaceRecords != NumAllInterfaceRecords)
-    	LogMemCorruption("NumAllInterfaceRecords is %d should be %d", m->NumAllInterfaceRecords, NumAllInterfaceRecords);
-
-    if (m->NumAllInterfaceQuestions != NumAllInterfaceQuestions)
-    	LogMemCorruption("NumAllInterfaceQuestions is %d should be %d", m->NumAllInterfaceQuestions, NumAllInterfaceQuestions);
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-}
-#endif // MDNS_MALLOC_DEBUGGING
-
-// Returns true if this is a  unique, authoritative LocalOnly record that answers questions of type
-// A, AAAA , CNAME, or PTR.  The caller should answer the question with this record and not send out
-// the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true.
-// Main use is to handle /etc/hosts records and the LocalOnly PTR records created for localhost.
-#define UniqueLocalOnlyRecord(rr) ((rr)->ARType == AuthRecordLocalOnly && \
-                                        (rr)->resrec.RecordType & kDNSRecordTypeUniqueMask && \
-                                        ((rr)->resrec.rrtype == kDNSType_A || (rr)->resrec.rrtype == kDNSType_AAAA || \
-                                         (rr)->resrec.rrtype == kDNSType_CNAME || \
-                                         (rr)->resrec.rrtype == kDNSType_PTR))
-
-mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q)
-{
-    mDNS_CheckLock(m);
-
-    if (m->NextScheduledStopTime - q->StopTime > 0)
-        m->NextScheduledStopTime = q->StopTime;
-}
-
-mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
-{
-    mDNS_CheckLock(m);
-
-    if (ActiveQuestion(q))
-    {
-        // Depending on whether this is a multicast or unicast question we want to set either:
-        // m->NextScheduledQuery = NextQSendTime(q) or
-        // m->NextuDNSEvent      = NextQSendTime(q)
-        mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent;
-        if (*timer - NextQSendTime(q) > 0)
-            *timer = NextQSendTime(q);
-    }
-}
-
-mDNSlocal void ReleaseAuthEntity(AuthHash *r, AuthEntity *e)
-{
-#if MDNS_MALLOC_DEBUGGING >= 1
-    unsigned int i;
-    for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
-#endif
-    e->next = r->rrauth_free;
-    r->rrauth_free = e;
-    r->rrauth_totalused--;
-}
-
-mDNSlocal void ReleaseAuthGroup(AuthHash *r, AuthGroup **cp)
-{
-    AuthEntity *e = (AuthEntity *)(*cp);
-    LogMsg("ReleaseAuthGroup:  Releasing AuthGroup %##s", (*cp)->name->c);
-    if ((*cp)->rrauth_tail != &(*cp)->members)
-        LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrauth_tail != &(*cp)->members)");
-    if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
-    (*cp)->name = mDNSNULL;
-    *cp = (*cp)->next;          // Cut record from list
-    ReleaseAuthEntity(r, e);
-}
-
-mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const PreserveAG)
-{
-    AuthEntity *e = mDNSNULL;
-
-    if (r->rrauth_lock) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
-    r->rrauth_lock = 1;
-
-    if (!r->rrauth_free)
-    {
-        // We allocate just one AuthEntity at a time because we need to be able
-        // free them all individually which normally happens when we parse /etc/hosts into
-        // AuthHash where we add the "new" entries and discard (free) the already added
-        // entries. If we allocate as chunks, we can't free them individually.
-        AuthEntity *storage = (AuthEntity *) mDNSPlatformMemAllocateClear(sizeof(*storage));
-        storage->next = mDNSNULL;
-        r->rrauth_free = storage;
-    }
-
-    // If we still have no free records, recycle all the records we can.
-    // Enumerating the entire auth is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
-    if (!r->rrauth_free)
-    {
-        mDNSu32 oldtotalused = r->rrauth_totalused;
-        mDNSu32 slot;
-        for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        {
-            AuthGroup **cp = &r->rrauth_hash[slot];
-            while (*cp)
-            {
-                if ((*cp)->members || (*cp)==PreserveAG) cp=&(*cp)->next;
-                else ReleaseAuthGroup(r, cp);
-            }
-        }
-        LogInfo("GetAuthEntity: Recycled %d records to reduce auth cache from %d to %d",
-                oldtotalused - r->rrauth_totalused, oldtotalused, r->rrauth_totalused);
-    }
-
-    if (r->rrauth_free) // If there are records in the free list, take one
-    {
-        e = r->rrauth_free;
-        r->rrauth_free = e->next;
-        if (++r->rrauth_totalused >= r->rrauth_report)
-        {
-            LogInfo("RR Auth now using %ld objects", r->rrauth_totalused);
-            if      (r->rrauth_report <  100) r->rrauth_report += 10;
-            else if (r->rrauth_report < 1000) r->rrauth_report += 100;
-            else r->rrauth_report += 1000;
-        }
-        mDNSPlatformMemZero(e, sizeof(*e));
-    }
-
-    r->rrauth_lock = 0;
-
-    return(e);
-}
-
-mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name)
-{
-    AuthGroup *ag;
-    const mDNSu32 slot = namehash % AUTH_HASH_SLOTS;
-
-    for (ag = r->rrauth_hash[slot]; ag; ag=ag->next)
-        if (ag->namehash == namehash && SameDomainName(ag->name, name))
-            break;
-    return(ag);
-}
-
-mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr)
-{
-    return(AuthGroupForName(r, rr->namehash, rr->name));
-}
-
-mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr)
-{
-    mDNSu16 namelen = DomainNameLength(rr->name);
-    AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL);
-    const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS;
-    if (!ag)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetAuthGroup: Failed to allocate memory for " PRI_DM_NAME, DM_NAME_PARAM(rr->name));
-        return(mDNSNULL);
-    }
-    ag->next         = r->rrauth_hash[slot];
-    ag->namehash     = rr->namehash;
-    ag->members      = mDNSNULL;
-    ag->rrauth_tail  = &ag->members;
-    ag->NewLocalOnlyRecords = mDNSNULL;
-    if (namelen > sizeof(ag->namestorage))
-        ag->name = (domainname *) mDNSPlatformMemAllocate(namelen);
-    else
-        ag->name = (domainname*)ag->namestorage;
-    if (!ag->name)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetAuthGroup: Failed to allocate name storage for " PRI_DM_NAME, DM_NAME_PARAM(rr->name));
-        ReleaseAuthEntity(r, (AuthEntity*)ag);
-        return(mDNSNULL);
-    }
-    AssignDomainName(ag->name, rr->name);
-
-    if (AuthGroupForRecord(r, rr))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetAuthGroup: Already have AuthGroup for " PRI_DM_NAME, DM_NAME_PARAM(rr->name));
-    }
-    r->rrauth_hash[slot] = ag;
-    if (AuthGroupForRecord(r, rr) != ag)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetAuthGroup: Not finding AuthGroup for " PRI_DM_NAME, DM_NAME_PARAM(rr->name));
-    }
-
-    return(ag);
-}
-
-// Returns the AuthGroup in which the AuthRecord was inserted
-mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
-{
-    AuthGroup *ag;
-
-    (void)m;
-    ag = AuthGroupForRecord(r, &rr->resrec);
-    if (!ag) ag = GetAuthGroup(r, &rr->resrec);   // If we don't have a AuthGroup for this name, make one now
-    if (ag)
-    {
-        *(ag->rrauth_tail) = rr;                // Append this record to tail of cache slot list
-        ag->rrauth_tail = &(rr->next);          // Advance tail pointer
-    }
-    return ag;
-}
-
-mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
-{
-    AuthGroup *a;
-    AuthRecord **rp;
-
-    a = AuthGroupForRecord(r, &rr->resrec);
-    if (!a)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "RemoveAuthRecord: ERROR!! AuthGroup not found for " PRI_S, ARDisplayString(m, rr));
-        return mDNSNULL;
-    }
-    rp = &a->members;
-    while (*rp)
-    {
-        if (*rp != rr)
-            rp=&(*rp)->next;
-        else
-        {
-            // We don't break here, so that we can set the tail below without tracking "prev" pointers
-
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "RemoveAuthRecord: removing auth record " PRI_S " from table", ARDisplayString(m, rr));
-            *rp = (*rp)->next;          // Cut record from list
-        }
-    }
-    // TBD: If there are no more members, release authgroup ?
-    a->rrauth_tail = rp;
-    return a;
-}
-
-mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name)
-{
-    CacheGroup *cg;
-    mDNSu32    slot = HashSlotFromNameHash(namehash);
-    for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
-        if (cg->namehash == namehash && SameDomainName(cg->name, name))
-            break;
-    return(cg);
-}
-
-mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr)
-{
-    return(CacheGroupForName(m, rr->namehash, rr->name));
-}
-
-mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
-{
-    NetworkInterfaceInfo *intf;
-
-    if (addr->type == mDNSAddrType_IPv4)
-    {
-        // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception
-        if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
-        for (intf = m->HostInterfaces; intf; intf = intf->next)
-            if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
-                if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
-                    return(mDNStrue);
-    }
-
-    if (addr->type == mDNSAddrType_IPv6)
-    {
-        if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue);
-        for (intf = m->HostInterfaces; intf; intf = intf->next)
-            if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
-                if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
-                    (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
-                    (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
-                    (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
-                        return(mDNStrue);
-    }
-
-    return(mDNSfalse);
-}
-
-mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfo *intf = m->HostInterfaces;
-    while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
-    return(intf);
-}
-
-mDNSlocal NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfo *intf;
-
-    if (!InterfaceID)
-        return mDNSNULL;
-
-    // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and
-    // we still want to find the first IPv4 Link-Local interface
-    for (intf = m->HostInterfaces; intf; intf = intf->next)
-    {
-        if (intf->InterfaceID == InterfaceID &&
-            intf->ip.type == mDNSAddrType_IPv4 && mDNSv4AddressIsLinkLocal(&intf->ip.ip.v4))
-        {
-            debugf("FirstIPv4LLInterfaceForID: found LL interface with address %.4a", &intf->ip.ip.v4);
-            return intf;
-        }
-    }
-    return (mDNSNULL);
-}
-
-mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
-    return(intf ? intf->ifname : mDNSNULL);
-}
-
-mDNSlocal mDNSBool FollowCNAME(const DNSQuestion *const q, const ResourceRecord *const rr, const QC_result qcResult)
-{
-    // Do not follow CNAME if it is a remove event.
-    if (qcResult == QC_rmv)
-    {
-        return mDNSfalse;
-    }
-
-    // Do not follow CNAME if the question asks for CNAME record.
-    if (q->qtype == kDNSType_CNAME)
-    {
-        return mDNSfalse;
-    }
-
-    // Do not follow CNAME if the record is not a CNAME record.
-    if (rr->rrtype != kDNSType_CNAME)
-    {
-        return mDNSfalse;
-    }
-
-    // Do not follow CNAME if the record is a negative record, which means CNAME does not exist.
-    if (rr->RecordType == kDNSRecordTypePacketNegative)
-    {
-        return mDNSfalse;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Only follow the CNAME if:
-    // 1. The question is not DNSSEC question, or
-    // 2. The question is DNSSEC question and the CNAME being followed has been validated by DNSSEC.
-    // So that we can ensure only the secure CNAME can be followed.
-    if (!resource_record_as_cname_should_be_followed(rr, q))
-    {
-        return mDNSfalse;
-    }
-#endif
-
-    return mDNStrue;
-}
-
-// Caller should hold the lock
-mDNSlocal void GenerateNegativeResponseEx(mDNS *const m, const mDNSInterfaceID InterfaceID, const QC_result qc,
-    const mDNSOpaque16 responseFlags)
-{
-    DNSQuestion *q;
-    if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; }
-    q = m->CurrentQuestion;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] GenerateNegativeResponse: Generating negative response for question "
-        PRI_DM_NAME " (" PUB_S ")", q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-        DNSTypeName(q->qtype));
-
-    MakeNegativeCacheRecordForQuestion(m, &m->rec.r, q, 60, InterfaceID, responseFlags);
-
-    // We need to force the response through in the following cases
-    //
-    //  a) SuppressUnusable questions that are suppressed
-    //  b) Append search domains and retry the question
-    //
-    // The question may not have set Intermediates in which case we don't deliver negative responses. So, to force
-    // through we use "QC_forceresponse".
-    AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, qc);
-    if (m->CurrentQuestion == q) { q->ThisQInterval = 0; }              // Deactivate this question
-    // Don't touch the question after this
-    mDNSCoreResetRecord(m);
-}
-#define GenerateNegativeResponse(M, INTERFACE_ID, QC) GenerateNegativeResponseEx(M, INTERFACE_ID, QC, zeroID)
-
-mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr)
-{
-    const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name);
-    if (q->CNAMEReferrals >= 10 || selfref)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] AnswerQuestionByFollowingCNAME: %p " PRI_DM_NAME " (" PUB_S
-            ")  NOT following CNAME referral %d" PUB_S " for " PRI_S, q->request_id, mDNSVal16(q->TargetQID), q,
-            DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "",
-            RRDisplayString(m, rr));
-
-    }
-    else
-    {
-        UDPSocket *sock = q->LocalSocket;
-        mDNSOpaque16 id = q->TargetQID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-        uDNSMetrics metrics;
-#endif
-
-        q->LocalSocket = mDNSNULL;
-
-        // The SameDomainName check above is to ignore bogus CNAME records that point right back at
-        // themselves. Without that check we can get into a case where we have two duplicate questions,
-        // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals
-        // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because
-        // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates
-        // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals
-        // for either of them. This is not a problem for CNAME loops of two or more records because in
-        // those cases the newly re-appended question A has a different target name and therefore cannot be
-        // a duplicate of any other question ('B') which was itself a duplicate of the previous question A.
-
-        // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
-        // and track CNAMEs coming and going, we should really create a subordinate query here,
-        // which we would subsequently cancel and retract if the CNAME referral record were removed.
-        // In reality this is such a corner case we'll ignore it until someone actually needs it.
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] AnswerQuestionByFollowingCNAME: %p " PRI_DM_NAME
-            " (" PUB_S ") following CNAME referral %d for " PRI_S, q->request_id, mDNSVal16(q->TargetQID), q,
-            DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr));
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-        metrics = q->metrics;
-        // The metrics will be transplanted to the restarted question, so zero out the old copy instead of using
-        // uDNSMetricsClear(), which will free any pointers to allocated memory.
-        mDNSPlatformMemZero(&q->metrics, sizeof(q->metrics));
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        mdns_querier_t querier = mDNSNULL;
-        const mDNSBool handleRestart = !mDNSOpaque16IsZero(q->TargetQID);
-        if (handleRestart)
-        {
-            querier = Querier_HandlePreCNAMERestart(q);
-        }
-#endif
-        mDNS_StopQuery_internal(m, q);                              // Stop old query
-        AssignDomainName(&q->qname, &rr->rdata->u.name);            // Update qname
-        q->qnamehash = DomainNameHashValue(&q->qname);              // and namehash
-        // If a unicast query results in a CNAME that points to a .local, we need to re-try
-        // this as unicast. Setting the mDNSInterface_Unicast tells mDNS_StartQuery_internal
-        // to try this as unicast query even though it is a .local name
-        if (!mDNSOpaque16IsZero(q->TargetQID) && IsLocalDomain(&q->qname))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] AnswerQuestionByFollowingCNAME: Resolving a .local CNAME %p " PRI_DM_NAME
-                " (" PUB_S ") Record " PRI_S, q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname),
-                DNSTypeName(q->qtype), RRDisplayString(m, rr));
-            q->IsUnicastDotLocal = mDNStrue;
-        }
-        q->CNAMEReferrals += 1;                                     // Increment value before calling mDNS_StartQuery_internal
-        const mDNSu32 c = q->CNAMEReferrals;                        // Stash a copy of the new q->CNAMEReferrals value
-        mDNS_StartQuery_internal(m, q);                             // start new query
-        // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal,
-        // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
-        q->CNAMEReferrals = c;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-        q->metrics = metrics;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (handleRestart)
-        {
-            Querier_HandlePostCNAMERestart(q, querier);
-        }
-        mdns_forget(&querier);
-#endif
-        if (sock)
-        {
-            // If our new query is a duplicate, then it can't have a socket of its own, so we have to close the one we saved.
-            if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
-            else
-            {
-                // Transplant the old socket into the new question, and copy the query ID across too.
-                // No need to close the old q->LocalSocket value because it won't have been created yet (they're made lazily on-demand).
-                q->LocalSocket = sock;
-                q->TargetQID = id;
-            }
-        }
-    }
-}
-
-#ifdef USE_LIBIDN
-
-#include <unicode/uidna.h>
-
-#define DEBUG_PUNYCODE 0
-
-mDNSlocal mDNSu8 *PunycodeConvert(const mDNSu8 *const src, mDNSu8 *const dst, const mDNSu8 *const end)
-{
-    UErrorCode errorCode = U_ZERO_ERROR;
-    UIDNAInfo info = UIDNA_INFO_INITIALIZER;
-    UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE, &errorCode);
-    int32_t len = uidna_nameToASCII_UTF8(uts46, (const char *)src+1, src[0], (char *)dst+1, (int32_t)(end-(dst+1)), &info, &errorCode);
-    uidna_close(uts46);
-    #if DEBUG_PUNYCODE
-    if (errorCode) LogMsg("uidna_nameToASCII_UTF8(%##s) failed errorCode %d", src, errorCode);
-    if (info.errors) LogMsg("uidna_nameToASCII_UTF8(%##s) failed info.errors 0x%08X", src, info.errors);
-    if (len > MAX_DOMAIN_LABEL) LogMsg("uidna_nameToASCII_UTF8(%##s) result too long %d", src, len);
-    #endif
-    if (errorCode || info.errors || len > MAX_DOMAIN_LABEL) return mDNSNULL;
-    *dst = (mDNSu8)len;
-    return(dst + 1 + len);
-}
-
-mDNSlocal mDNSBool IsHighASCIILabel(const mDNSu8 *d)
-{
-    int i;
-    for (i=1; i<=d[0]; i++) if (d[i] & 0x80) return mDNStrue;
-    return mDNSfalse;
-}
-
-mDNSlocal const mDNSu8 *FindLastHighASCIILabel(const domainname *const d)
-{
-    const mDNSu8 *ptr = d->c;
-    const mDNSu8 *ans = mDNSNULL;
-    while (ptr[0])
-    {
-        const mDNSu8 *const next = ptr + 1 + ptr[0];
-        if (ptr[0] > MAX_DOMAIN_LABEL || next >= d->c + MAX_DOMAIN_NAME) return mDNSNULL;
-        if (IsHighASCIILabel(ptr)) ans = ptr;
-        ptr = next;
-    }
-    return ans;
-}
-
-mDNSlocal mDNSBool PerformNextPunycodeConversion(const DNSQuestion *const q, domainname *const newname)
-{
-    const mDNSu8 *h = FindLastHighASCIILabel(&q->qname);
-    #if DEBUG_PUNYCODE
-    LogMsg("PerformNextPunycodeConversion: %##s (%s) Last High-ASCII Label %##s", q->qname.c, DNSTypeName(q->qtype), h);
-    #endif
-    if (!h) return mDNSfalse;  // There are no high-ascii labels to convert
-
-    mDNSu8 *const dst = PunycodeConvert(h, newname->c + (h - q->qname.c), newname->c + MAX_DOMAIN_NAME);
-    if (!dst)
-        return mDNSfalse;  // The label was not convertible to Punycode
-    else
-    {
-        // If Punycode conversion of final eligible label was successful, copy the rest of the domainname
-        const mDNSu8 *const src = h + 1 + h[0];
-        const mDNSu8 remainder  = DomainNameLength((const domainname*)src);
-        if (dst + remainder > newname->c + MAX_DOMAIN_NAME) return mDNSfalse;  // Name too long -- cannot be converted to Punycode
-
-        mDNSPlatformMemCopy(newname->c, q->qname.c, (mDNSu32)(h - q->qname.c));  // Fill in the leading part
-        mDNSPlatformMemCopy(dst, src, remainder);                     // Fill in the trailing part
-        #if DEBUG_PUNYCODE
-        LogMsg("PerformNextPunycodeConversion: %##s converted to %##s", q->qname.c, newname->c);
-        #endif
-        return mDNStrue;
-    }
-}
-
-#endif // USE_LIBIDN
-
-// For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord
-// Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not
-mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
-{
-    DNSQuestion *q = m->CurrentQuestion;
-    mDNSBool followcname;
-
-    if (!q)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "AnswerLocalQuestionWithLocalAuthRecord: ERROR!! CurrentQuestion NULL while answering with " PUB_S,
-            ARDisplayString(m, rr));
-        return;
-    }
-
-    followcname = FollowCNAME(q, &rr->resrec, AddRecord);
-
-    // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique
-    if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering " PUB_S " event for local record type %X "
-            PRI_S, AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr));
-        return;
-    }
-
-    // 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->AnsweredLocalQ = mDNStrue;
-    mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-    if (q->QuestionCallback)
-    {
-        q->CurrentAnswers += AddRecord ? 1 : -1;
-        if (UniqueLocalOnlyRecord(rr))
-        {
-            if (!followcname || q->ReturnIntermed)
-            {
-                // Don't send this packet on the wire as we answered from /etc/hosts
-                q->ThisQInterval = 0;
-                q->LOAddressAnswers += AddRecord ? 1 : -1;
-                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
-            }
-            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-            // The callback above could have caused the question to stop. Detect that
-            // using m->CurrentQuestion
-            if (followcname && m->CurrentQuestion == q)
-                AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
-            return;
-        }
-        else
-        {
-            q->QuestionCallback(m, q, &rr->resrec, AddRecord);
-        }
-    }
-    mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-}
-
-mDNSlocal void AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *ar, QC_result AddRecord)
-{
-    if (m->CurrentQuestion)
-        LogMsg("AnswerInterfaceAnyQuestionsWithLocalAuthRecord: ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-    {
-        mDNSBool answered;
-        DNSQuestion *q = m->CurrentQuestion;
-        if (RRAny(ar))
-            answered = AuthRecordAnswersQuestion(ar, q);
-        else
-            answered = LocalOnlyRecordAnswersQuestion(ar, q);
-        if (answered)
-            AnswerLocalQuestionWithLocalAuthRecord(m, ar, AddRecord);       // MUST NOT dereference q again
-        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-// When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord()
-// delivers the appropriate add/remove events to listening questions:
-// 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate,
-//    stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
-// 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though
-//    our main question list, delivering answers to mDNSInterface_Any questions as appropriate,
-//    stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion().
-//
-// AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(),
-// and by mDNS_Deregister_internal()
-
-mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *ar, QC_result AddRecord)
-{
-    if (m->CurrentQuestion)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: " PRI_DM_NAME
-            " (" PUB_S ")", DM_NAME_PARAM(&m->CurrentQuestion->qname), DNSTypeName(m->CurrentQuestion->qtype));
-    }
-
-    m->CurrentQuestion = m->LocalOnlyQuestions;
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
-    {
-        mDNSBool answered;
-        DNSQuestion *q = m->CurrentQuestion;
-        // We are called with both LocalOnly/P2P record or a regular AuthRecord
-        if (RRAny(ar))
-            answered = AuthRecordAnswersQuestion(ar, q);
-        else
-            answered = LocalOnlyRecordAnswersQuestion(ar, q);
-        if (answered)
-            AnswerLocalQuestionWithLocalAuthRecord(m, ar, AddRecord);           // MUST NOT dereference q again
-        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-            m->CurrentQuestion = q->next;
-    }
-
-    m->CurrentQuestion = mDNSNULL;
-
-    // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions
-    if (ar->ARType == AuthRecordLocalOnly || ar->ARType == AuthRecordP2P)
-        AnswerInterfaceAnyQuestionsWithLocalAuthRecord(m, ar, AddRecord);
-
-}
-
-// ***************************************************************************
-// MARK: - Resource Record Utility Functions
-
-#define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
-
-mDNSlocal mDNSBool ResourceRecordIsValidAnswer(const AuthRecord *const rr)
-{
-    if ((rr->resrec.RecordType & kDNSRecordTypeActiveMask) && rr->resrec.rrtype != kDNSType_TSR &&
-        ((rr->Additional1 == mDNSNULL) || (rr->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) &&
-        ((rr->Additional2 == mDNSNULL) || (rr->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) &&
-        ((rr->DependentOn == mDNSNULL) || (rr->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask)))
-    {
-        return mDNStrue;
-    }
-    else
-    {
-        return mDNSfalse;
-    }
-}
-
-mDNSlocal mDNSBool IsInterfaceValidForAuthRecord(const AuthRecord *const rr, const mDNSInterfaceID InterfaceID)
-{
-    if (rr->resrec.InterfaceID == mDNSInterface_Any)
-    {
-        return mDNSPlatformValidRecordForInterface(rr, InterfaceID);
-    }
-    else
-    {
-        return ((rr->resrec.InterfaceID == InterfaceID) ? mDNStrue : mDNSfalse);
-    }
-}
-
-mDNSlocal mDNSBool ResourceRecordIsValidInterfaceAnswer(const AuthRecord *const rr, const mDNSInterfaceID interfaceID)
-{
-    return ((IsInterfaceValidForAuthRecord(rr, interfaceID) && ResourceRecordIsValidAnswer(rr)) ? mDNStrue : mDNSfalse);
-}
-
-#define DefaultProbeCountForTypeUnique ((mDNSu8)3)
-#define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
-
-// Parameters for handling probing conflicts
-#define kMaxAllowedMCastProbingConflicts 1                     // Maximum number of conflicts to allow from mcast messages.
-#define kProbingConflictPauseDuration    mDNSPlatformOneSecond // Duration of probing pause after an allowed mcast conflict.
-
-// See RFC 6762: "8.3 Announcing"
-// "The Multicast DNS responder MUST send at least two unsolicited responses, one second apart."
-// Send 4, which is really 8 since we send on both IPv4 and IPv6.
-#define InitialAnnounceCount ((mDNSu8)4)
-
-// For goodbye packets we set the count to 3, and for wakeups we set it to 18
-// (which will be up to 15 wakeup attempts over the course of 30 seconds,
-// and then if the machine fails to wake, 3 goodbye packets).
-#define GoodbyeCount ((mDNSu8)3)
-#define WakeupCount ((mDNSu8)18)
-#define MAX_PROBE_RESTARTS ((mDNSu8)20)
-#define MAX_GHOST_TIME ((mDNSs32)((60*60*24*7)*mDNSPlatformOneSecond))  //  One week
-
-// Number of wakeups we send if WakeOnResolve is set in the question
-#define InitialWakeOnResolveCount ((mDNSu8)3)
-
-// 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) &kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \
-                                            (X) &kDNSRecordTypeUnique           ? DefaultProbeIntervalForTypeUnique    : \
-                                            (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0)
-
-#define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
-mDNSexport mDNSs32 RRExpireTime(const CacheRecord *const cr)
-{
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    return cr->DNSPushSubscribed ? (mDNSStorage.timenow + FutureTime) : (cr->TimeRcvd + TicksTTL(cr));
-#else
-    return cr->TimeRcvd + TicksTTL(cr);
-#endif
-}
-
-// ResourceRecordNameClassInterfaceMatch returns true if two resource records have the same InterfaceID, class and name.
-mDNSlocal mDNSBool ResourceRecordNameClassInterfaceMatch(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-    if (!r1 || !r2)
-    {
-        return mDNSfalse;
-    }
-    if (r1->InterfaceID && r2->InterfaceID && r1->InterfaceID != r2->InterfaceID)
-    {
-        return mDNSfalse;
-    }
-    return (mDNSBool)(r1->rrclass  == r2->rrclass && r1->namehash == r2->namehash && SameDomainName(r1->name, r2->name));
-}
-
-// 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
-
-// SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
-
-#define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
-
-mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
-{
-    if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
-    if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
-    return ResourceRecordNameClassInterfaceMatch(&r1->resrec, &r2->resrec);
-}
-
-// PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
-// authoratative record is unique (as opposed to shared). For unique records, we are supposed to have
-// complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
-// In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
-// so a response of any type should match, even if it is not actually the type the client plans to use.
-
-// For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
-// and require the rrtypes to match for the rdata to be considered potentially conflicting
-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 & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
-        if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
-    if ((authrr->resrec.InterfaceID == mDNSInterface_Any) &&
-        !mDNSPlatformValidRecordForInterface(authrr, pktrr->resrec.InterfaceID)) return(mDNSfalse);
-    return (mDNSBool)(
-               pktrr->resrec.rrclass == authrr->resrec.rrclass &&
-               pktrr->resrec.namehash == authrr->resrec.namehash &&
-               SameDomainName(pktrr->resrec.name, authrr->resrec.name));
-}
-
-// CacheRecord *ka 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 void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
-{
-    if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-    {
-        if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetNextAnnounceProbeTime: ProbeCount %d Next in %d " PRI_S,
-                rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d",
-                m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow);
-        }
-        if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-            m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
-        // Some defensive code:
-        // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow
-        // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen.
-        // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero
-        if (m->NextScheduledProbe - m->timenow < 0)
-            m->NextScheduledProbe = m->timenow;
-    }
-    else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering))
-    {
-        if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-            m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
-    }
-}
-
-mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
-{
-    // For reverse-mapping Sleep Proxy PTR records, probe interval is one second
-    rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-
-    // * If this is a record type that's going to probe, then we use the m->SuppressProbes time.
-    // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other
-    //   records that are going to probe, then we 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 "interval / 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 it's not going to probe and m->SuppressProbes is not already set then we should announce immediately.
-
-    if (rr->ProbeCount)
-    {
-        rr->ProbingConflictCount = 0;
-        // 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)
-        {
-            // To allow us to aggregate probes when a group of services are registered together,
-            // the first probe is delayed by a random delay in the range 1/8 to 1/4 second.
-            // This means the common-case behaviour is:
-            // randomized wait; probe
-            // 1/4 second wait; probe
-            // 1/4 second wait; probe
-            // 1/4 second wait; announce (i.e. service is normally announced 7/8 to 1 second after being registered)
-            m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
-
-            // 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 = NonZeroTime(m->NextScheduledProbe);
-            if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
-                m->SuppressProbes = m->timenow;
-
-            // 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 = NonZeroTime(m->NextScheduledQuery);
-            if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
-                m->SuppressProbes = m->timenow;
-
-            // except... don't expect to be able to send before the m->SuppressQueries timer fires
-            if (m->SuppressQueries && ((m->SuppressProbes - m->SuppressQueries) < 0))
-            {
-                m->SuppressProbes = NonZeroTime(m->SuppressQueries);
-            }
-            if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d "
-                    "m->NextScheduledQuery %d m->SuppressQueries %d %d",
-                    m->SuppressProbes - m->timenow, m->NextScheduledProbe - m->timenow,
-                    m->NextScheduledQuery - m->timenow, m->SuppressQueries, m->SuppressQueries - m->timenow);
-                m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
-            }
-        }
-        rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
-    }
-    // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so
-    // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value.
-    else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0))
-        rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
-    else
-        rr->LastAPTime = m->timenow - rr->ThisAPInterval;
-
-    // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
-    // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
-    // After three probes one second apart with no answer, we conclude the client is now sleeping
-    // and we can begin broadcasting our announcements to take over ownership of that IP address.
-    // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
-    // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
-    if (rr->AddressProxy.type)
-        rr->LastAPTime = m->timenow;
-
-    // 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;
-
-    SetNextAnnounceProbeTime(m, rr);
-}
-
-mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr)
-{
-    const domainname *target;
-    if (rr->AutoTarget)
-    {
-        rr->AutoTarget = Target_AutoHostAndNATMAP;
-    }
-
-    target = GetServiceTarget(m, rr);
-    if (!target || target->c[0] == 0)
-    {
-        // defer registration until we've got a target
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetUnicastTargetToHostName No target for " PRI_S, ARDisplayString(m, rr));
-        rr->state = regState_NoTarget;
-        return mDNSNULL;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetUnicastTargetToHostName target " PRI_DM_NAME " for resource record " PUB_S,
-            DM_NAME_PARAM(target), ARDisplayString(m,rr));
-        return target;
-    }
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-mDNSlocal mDNSBool AuthRecordIncludesOrIsAWDL(const AuthRecord *const ar)
-{
-    return ((AuthRecordIncludesAWDL(ar) || mDNSPlatformInterfaceIsAWDL(ar->resrec.InterfaceID)) ? mDNStrue : mDNSfalse);
-}
-#endif
-
-// Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
-// Eventually we should unify this with GetServiceTarget() in uDNS.c
-mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
-{
-    domainname *const target = GetRRDomainNameTarget(&rr->resrec);
-    const domainname *newname;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (AuthRecordIncludesOrIsAWDL(rr))
-    {
-        newname = &m->RandomizedHostname;
-    }
-    else
-#endif
-    {
-        newname = &m->MulticastHostname;
-    }
-    if (!target)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetTargetToHostName: Don't know how to set the target of rrtype " PUB_S,
-            DNSTypeName(rr->resrec.rrtype));
-    }
-
-    if (!(rr->ForceMCast || rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P || IsLocalDomain(&rr->namestorage)))
-    {
-        const domainname *const n = SetUnicastTargetToHostName(m, rr);
-        if (n) newname = n;
-        else { if (target) target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; }
-    }
-
-    if (target && SameDomainName(target, newname))
-        debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
-
-    if (target && !SameDomainName(target, newname))
-    {
-        AssignDomainName(target, newname);
-        SetNewRData(&rr->resrec, mDNSNULL, 0);      // Update rdlength, rdestimate, rdatahash
-
-        // 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->RequireGoodbye && 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));
-
-        rr->AnnounceCount  = InitialAnnounceCount;
-        rr->RequireGoodbye = mDNSfalse;
-        rr->ProbeRestartCount = 0;
-        InitializeLastAPTime(m, rr);
-    }
-}
-
-mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
-{
-    if (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;
-        mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-        rr->RecordCallback(m, rr, mStatus_NoError);
-        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-    }
-}
-
-mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
-{
-    // Make sure that we don't activate the SRV record and associated service records, if it is in
-    // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state.
-    // We should not activate any of the other reords (PTR, TXT) that are part of the service. When
-    // the target becomes available, the records will be reregistered.
-    if (rr->resrec.rrtype != kDNSType_SRV)
-    {
-        AuthRecord *srvRR = mDNSNULL;
-        if (rr->resrec.rrtype == kDNSType_PTR)
-            srvRR = rr->Additional1;
-        else if (rr->resrec.rrtype == kDNSType_TXT)
-            srvRR = rr->DependentOn;
-        if (srvRR)
-        {
-            if (srvRR->resrec.rrtype != kDNSType_SRV)
-            {
-                LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
-            }
-            else
-            {
-                LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)",
-                        ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
-                rr->state = srvRR->state;
-            }
-        }
-    }
-
-    if (rr->state == regState_NoTarget)
-    {
-        LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr));
-        return;
-    }
-    // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep,
-    // the service/record was being deregistered. In that case, we should not try to register again. For the cases where
-    // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it
-    // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went
-    // to sleep, then it is okay to start in Pending state as we will go back to NoTarget state if we don't have a target.
-    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-    {
-        LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state);
-        rr->state = regState_DeregPending;
-    }
-    else
-    {
-        LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state);
-        rr->state = regState_Pending;
-    }
-    rr->ProbingConflictCount = 0;
-    rr->LastConflictPktNum   = 0;
-    rr->ProbeRestartCount    = 0;
-    rr->ProbeCount           = 0;
-    rr->AnnounceCount        = 0;
-    rr->ThisAPInterval       = INIT_RECORD_REG_INTERVAL;
-    rr->LastAPTime           = m->timenow - rr->ThisAPInterval;
-    rr->expire               = 0; // Forget about all the leases, start fresh
-    rr->uselease             = mDNStrue;
-    rr->updateid             = zeroID;
-    rr->SRVChanged           = mDNSfalse;
-    rr->updateError          = mStatus_NoError;
-    // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core.
-    // The records might already be registered with the server and hence could have NAT state.
-    if (rr->NATinfo.clientContext)
-    {
-        mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-        rr->NATinfo.clientContext = mDNSNULL;
-    }
-    if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
-    if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
-    if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-        m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
-}
-
-// Two records qualify to be local duplicates if:
-// (a) the RecordTypes are the same, or
-// (b) one is Unique and the other Verified
-// (c) either is in the process of deregistering
-#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
-                        ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \
-                        ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering))
-
-#define RecordIsLocalDuplicate(A,B) \
-    ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(& (A)->resrec, & (B)->resrec))
-
-mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
-{
-    const AuthGroup *a;
-    AuthRecord *rp;
-
-    a = AuthGroupForRecord(r, &rr->resrec);
-    if (!a) return mDNSNULL;
-    rp = a->members;
-    while (rp)
-    {
-        if (!RecordIsLocalDuplicate(rp, rr))
-            rp = rp->next;
-        else
-        {
-            if (rp->resrec.RecordType == kDNSRecordTypeDeregistering)
-            {
-                rp->AnnounceCount = 0;
-                rp = rp->next;
-            }
-            else return rp;
-        }
-    }
-    return (mDNSNULL);
-}
-
-mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
-{
-    const AuthGroup *a;
-    const AuthRecord *rp;
-
-    a = AuthGroupForRecord(r, &rr->resrec);
-    if (!a) return mDNSfalse;
-    rp = a->members;
-    while (rp)
-    {
-        const uintptr_t s1 = rr->RRSet ? rr->RRSet : (uintptr_t)rr;
-        const uintptr_t s2 = rp->RRSet ? rp->RRSet : (uintptr_t)rp;
-        if (s1 != s2 && SameResourceRecordSignature(rp, rr) && !IdenticalSameNameRecord(&rp->resrec, &rr->resrec))
-            return mDNStrue;
-        else
-            rp = rp->next;
-    }
-    return (mDNSfalse);
-}
-
-// checks to see if "rr" is already present
-mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr)
-{
-    const AuthGroup *a;
-    AuthRecord *rp;
-
-    a = AuthGroupForRecord(r, &rr->resrec);
-    if (!a) return mDNSNULL;
-    rp = a->members;
-    while (rp)
-    {
-        if (rp != rr)
-            rp = rp->next;
-        else
-        {
-            return rp;
-        }
-    }
-    return (mDNSNULL);
-}
-
-mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
-{
-    if (RRLocalOnly(rr))
-    {
-        // A sanity check, this should be prevented in calling code.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DecrementAutoTargetServices: called for RRLocalOnly() record: " PUB_S, ARDisplayString(m, rr));
-        return;
-    }
-
-    if (!AuthRecord_uDNS(rr) && (rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHost))
-    {
-        NetworkInterfaceInfo *intf;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        DeadvertiseFlags flags     = 0; // DeadvertiseFlags for non-AWDL interfaces.
-        DeadvertiseFlags flagsAWDL = 0; // DeadvertiseFlags for AWDL interfaces.
-        if (AuthRecordIncludesOrIsAWDL(rr))
-        {
-            if (AuthRecordIncludesAWDL(rr))
-            {
-                m->AutoTargetAWDLIncludedCount--;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DecrementAutoTargetServices: AutoTargetAWDLIncludedCount %u Record " PRI_S,
-                    m->AutoTargetAWDLIncludedCount, ARDisplayString(m, rr));
-                if (m->AutoTargetAWDLIncludedCount == 0)
-                {
-                    flags |= kDeadvertiseFlag_RandHostname;
-                    if (m->AutoTargetAWDLOnlyCount == 0) flagsAWDL |= kDeadvertiseFlag_RandHostname;
-                }
-            }
-            else
-            {
-                m->AutoTargetAWDLOnlyCount--;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DecrementAutoTargetServices: AutoTargetAWDLOnlyCount %u Record " PRI_S,
-                    m->AutoTargetAWDLOnlyCount, ARDisplayString(m, rr));
-                if ((m->AutoTargetAWDLIncludedCount == 0) && (m->AutoTargetAWDLOnlyCount == 0))
-                {
-                    flagsAWDL |= kDeadvertiseFlag_RandHostname;
-                }
-            }
-            if (flags || flagsAWDL)
-            {
-                for (intf = m->HostInterfaces; intf; intf = intf->next)
-                {
-                    if (!intf->Advertise) continue;
-                    if (mDNSPlatformInterfaceIsAWDL(intf->InterfaceID))
-                    {
-                        if (flagsAWDL) DeadvertiseInterface(m, intf, flagsAWDL);
-                    }
-                    else
-                    {
-                        if (flags) DeadvertiseInterface(m, intf, flags);
-                    }
-                }
-            }
-            if ((m->AutoTargetAWDLIncludedCount == 0) && (m->AutoTargetAWDLOnlyCount == 0))
-            {
-                GetRandomUUIDLocalHostname(&m->RandomizedHostname);
-            }
-        }
-        else
-#endif
-        {
-            m->AutoTargetServices--;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DecrementAutoTargetServices: AutoTargetServices %u Record " PRI_S,
-                m->AutoTargetServices, ARDisplayString(m, rr));
-            if (m->AutoTargetServices == 0)
-            {
-                for (intf = m->HostInterfaces; intf; intf = intf->next)
-                {
-                    if (intf->Advertise) DeadvertiseInterface(m, intf, kDeadvertiseFlag_NormalHostname);
-                }
-            }
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    if (!AuthRecord_uDNS(rr))
-    {
-        if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
-            m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
-        m->NumAllInterfaceRecords--;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DecrementAutoTargetServices: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u " PRI_S,
-            m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
-    }
-#endif
-}
-
-mDNSlocal void AdvertiseNecessaryInterfaceRecords(mDNS *const m)
-{
-    NetworkInterfaceInfo *intf;
-    for (intf = m->HostInterfaces; intf; intf = intf->next)
-    {
-        if (intf->Advertise) AdvertiseInterfaceIfNeeded(m, intf);
-    }
-}
-
-mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
-{
-    mDNSBool enablingBonjour = mDNSfalse;
-
-    if (RRLocalOnly(rr))
-    {
-        // A sanity check, this should be prevented in calling code.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "IncrementAutoTargetServices: called for RRLocalOnly() record: " PRI_S, ARDisplayString(m, rr));
-        return;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    if (!AuthRecord_uDNS(rr))
-    {
-        m->NumAllInterfaceRecords++;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "IncrementAutoTargetServices: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u " PRI_S,
-            m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
-        if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
-        {
-            m->NextBonjourDisableTime = 0;
-            if (m->BonjourEnabled == 0)
-            {
-                // Enable Bonjour immediately by scheduling network changed processing where
-                // we will join the multicast group on each active interface.
-                m->BonjourEnabled = 1;
-                enablingBonjour = mDNStrue;
-                m->NetworkChanged = m->timenow;
-            }
-        }
-    }
-#endif
-
-    if (!AuthRecord_uDNS(rr) && (rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHost))
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        if (AuthRecordIncludesAWDL(rr))
-        {
-            m->AutoTargetAWDLIncludedCount++;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "IncrementAutoTargetServices: AutoTargetAWDLIncludedCount %u Record " PRI_S,
-                m->AutoTargetAWDLIncludedCount, ARDisplayString(m, rr));
-        }
-        else if (mDNSPlatformInterfaceIsAWDL(rr->resrec.InterfaceID))
-        {
-            m->AutoTargetAWDLOnlyCount++;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "IncrementAutoTargetServices: AutoTargetAWDLOnlyCount %u Record " PRI_S,
-                m->AutoTargetAWDLOnlyCount, ARDisplayString(m, rr));
-        }
-        else
-#endif
-        {
-            m->AutoTargetServices++;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "IncrementAutoTargetServices: AutoTargetServices %u Record " PRI_S,
-                m->AutoTargetServices, ARDisplayString(m, rr));
-        }
-        // If this is the first advertised service and we did not just enable Bonjour above, then
-        // advertise all the interface records.  If we did enable Bonjour above, the interface records will
-        // be advertised during the network changed processing scheduled above, so no need
-        // to do it here.
-        if (!enablingBonjour) AdvertiseNecessaryInterfaceRecords(m);
-    }
-}
-
-mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr)
-{
-    mDNSAddr     laddr = zeroAddr;
-    mDNSEthAddr  eth = zeroEthAddr;
-    mDNSIPPort   lport = zeroIPPort;
-    mDNSIPPort   rport = zeroIPPort;
-    mDNSu32      timeout = 0;
-    mDNSu32      seq = 0;
-    mDNSu32      ack = 0;
-    mDNSu16      win = 0;
-
-    if (mDNS_KeepaliveRecord(&rr->resrec))
-    {
-        mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, raddr, &eth, &seq, &ack, &lport, &rport, &win);
-        if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport))
-        {
-            LogMsg("getKeepaliveRaddr: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, raddr, rport.NotAnInteger);
-            return;
-        }
-    }
-}
-
-// Exported so uDNS.c can call this
-mDNSexport 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;
-
-    if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF " PRI_S, rr->resrec.rroriginalttl,
-            ARDisplayString(m, rr));
-        return(mStatus_BadParamErr);
-    }
-
-    if (!rr->resrec.RecordType)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: RecordType must be non-zero " PRI_S, ARDisplayString(m, rr));
-        return(mStatus_BadParamErr); }
-
-    if (m->ShutdownTime)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: Shutting down, can't register " PRI_S, ARDisplayString(m, rr));
-        return(mStatus_ServiceNotRunning);
-    }
-
-    if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
-    {
-        mDNSInterfaceID previousID = rr->resrec.InterfaceID;
-        if (rr->resrec.InterfaceID == mDNSInterface_Any || rr->resrec.InterfaceID == mDNSInterface_P2P)
-        {
-            rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
-            rr->ARType = AuthRecordLocalOnly;
-        }
-        if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
-        {
-            NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
-            if (intf && !intf->Advertise) { rr->resrec.InterfaceID = mDNSInterface_LocalOnly; rr->ARType = AuthRecordLocalOnly; }
-        }
-        if (rr->resrec.InterfaceID != previousID)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: Diverting record to local-only " PRI_S, ARDisplayString(m, rr));
-        }
-    }
-
-    if (RRLocalOnly(rr))
-    {
-        if (CheckAuthSameRecord(&m->rrauth, rr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: ERROR!! Tried to register LocalOnly AuthRecord %p "
-                PRI_DM_NAME " (" PUB_S ") that's already in the list",
-                rr, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-            return(mStatus_AlreadyRegistered);
-        }
-    }
-    else
-    {
-        while (*p && *p != rr) p=&(*p)->next;
-        if (*p)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p "
-                PRI_DM_NAME " (" PUB_S ") that's already in the list",
-                rr, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-            return(mStatus_AlreadyRegistered);
-        }
-    }
-
-    while (*d && *d != rr) d=&(*d)->next;
-    if (*d)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p "
-            PRI_DM_NAME " (" PUB_S ") that's already in the Duplicate list",
-            rr, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-        return(mStatus_AlreadyRegistered);
-    }
-
-    if (rr->DependentOn)
-    {
-        if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-            rr->resrec.RecordType =  kDNSRecordTypeVerified;
-        else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: ERROR! " PRI_DM_NAME " (" PUB_S
-                "): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique",
-                DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-            return(mStatus_Invalid);
-        }
-        if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique)))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: ERROR! " PRI_DM_NAME " (" PUB_S
-                "): rr->DependentOn->RecordType bad type %X",
-                DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
-            return(mStatus_Invalid);
-        }
-    }
-
-    rr->next = mDNSNULL;
-
-    // Field Group 1: The actual information pertaining to this resource record
-    // Set up by client prior to call
-
-    // Field Group 2: 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
-//  rr->AllowRemoteQuery  = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
-    // Make sure target is not uninitialized data, or we may crash writing debugging log messages
-    if (rr->AutoTarget && target) target->c[0] = 0;
-
-    // Field Group 3: Transient state for Authoritative Records
-    rr->Acknowledged      = mDNSfalse;
-    rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-    rr->ProbeRestartCount = 0;
-    rr->AnnounceCount     = InitialAnnounceCount;
-    rr->RequireGoodbye    = mDNSfalse;
-    rr->AnsweredLocalQ    = mDNSfalse;
-    rr->IncludeInProbe    = mDNSfalse;
-    rr->ImmedUnicast      = mDNSfalse;
-    rr->SendNSECNow       = mDNSNULL;
-    rr->ImmedAnswer       = mDNSNULL;
-    rr->ImmedAdditional   = mDNSNULL;
-    rr->SendRNow          = mDNSNULL;
-    rr->v4Requester       = zerov4Addr;
-    rr->v6Requester       = zerov6Addr;
-    rr->NextResponse      = mDNSNULL;
-    rr->NR_AnswerTo       = mDNSNULL;
-    rr->NR_AdditionalTo   = mDNSNULL;
-    if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
-//  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;
-
-    // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
-    if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
-
-    // Field Group 4: Transient uDNS state for Authoritative Records
-    rr->state             = regState_Zero;
-    rr->uselease          = 0;
-    rr->expire            = 0;
-    rr->Private           = 0;
-    rr->updateid          = zeroID;
-    rr->updateIntID       = zeroOpaque64;
-    rr->zone              = rr->resrec.name;
-    rr->nta               = mDNSNULL;
-    rr->tcp               = mDNSNULL;
-    rr->OrigRData         = 0;
-    rr->OrigRDLen         = 0;
-    rr->InFlightRData     = 0;
-    rr->InFlightRDLen     = 0;
-    rr->QueuedRData       = 0;
-    rr->QueuedRDLen       = 0;
-    //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
-    // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping
-    // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple
-    // times with different values if the external NAT port changes during the lifetime of the service registration.
-    //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
-
-//  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
-
-    // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
-    // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
-    // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
-    if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
-    // No need to announce or probe for the TSR record since it's an auxiliary record.
-    if (rr->resrec.rrtype == kDNSType_TSR)
-    {
-        rr->AnnounceCount = 0;
-        rr->ProbeCount = 0;
-    }
-
-    if (rr->AutoTarget)
-    {
-        SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
-#ifndef UNICAST_DISABLED
-        // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget
-        // In this case we leave the record half-formed in the list, and later we'll remove it from the list and re-add it properly.
-        if (rr->state == regState_NoTarget)
-        {
-            // Initialize the target so that we don't crash while logging etc.
-            domainname *tar = GetRRDomainNameTarget(&rr->resrec);
-            if (tar) tar->c[0] = 0;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: record " PUB_S " in NoTarget state", ARDisplayString(m, rr));
-        }
-#endif
-    }
-    else
-    {
-        rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
-        rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
-    }
-
-    if (!ValidateDomainName(rr->resrec.name))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Attempt to register record with invalid name: " PRI_S, ARDisplayString(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))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Attempt to register record with invalid rdata: " PRI_S, ARDisplayString(m, rr));
-        return(mStatus_Invalid);
-    }
-
-    rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
-    rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
-
-    if (RRLocalOnly(rr))
-    {
-        // If this is supposed to be unique, make sure we don't have any name conflicts.
-        // If we found a conflict, we may still want to insert the record in the list but mark it appropriately
-        // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more
-        // complications and not clear whether there are any benefits. See rdar:9304275 for details.
-        // Hence, just bail out.
-        // This comment is doesn’t make any sense. -- SC
-        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-        {
-            if (CheckAuthRecordConflict(&m->rrauth, rr))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: Name conflict " PRI_S " (%p), InterfaceID %p",
-                    ARDisplayString(m, rr), rr, rr->resrec.InterfaceID);
-                return mStatus_NameConflict;
-            }
-        }
-    }
-
-    // For uDNS records, we don't support duplicate checks at this time.
-#ifndef UNICAST_DISABLED
-    if (AuthRecord_uDNS(rr))
-    {
-        if (!m->NewLocalRecords) m->NewLocalRecords = rr;
-        // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new
-        // records to the list, so we now need to update p to advance to the new end to the list before appending our new record.
-        while (*p) p=&(*p)->next;
-        *p = rr;
-        if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
-        rr->ProbeCount    = 0;
-        rr->ProbeRestartCount = 0;
-        rr->AnnounceCount = 0;
-        if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr);
-        return(mStatus_NoError);            // <--- Note: For unicast records, code currently bails out at this point
-    }
-#endif
-
-    // Now that we've finished building our new record, make sure it's not identical to one we already have
-    if (RRLocalOnly(rr))
-    {
-        rr->ProbeCount    = 0;
-        rr->ProbeRestartCount = 0;
-        rr->AnnounceCount = 0;
-        r = CheckAuthIdenticalRecord(&m->rrauth, rr);
-    }
-    else
-    {
-        for (r = m->ResourceRecords; r; r=r->next)
-            if (RecordIsLocalDuplicate(r, rr))
-            {
-                if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0;
-                else break;
-            }
-    }
-
-    if (r)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: Adding to duplicate list " PRI_S, ARDisplayString(m,rr));
-        *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
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Register_internal: Adding to active record list " PRI_S, ARDisplayString(m,rr));
-        if (RRLocalOnly(rr))
-        {
-            AuthGroup *ag;
-            ag = InsertAuthRecord(m, &m->rrauth, rr);
-            if (ag && !ag->NewLocalOnlyRecords)
-            {
-                m->NewLocalOnlyRecords = mDNStrue;
-                ag->NewLocalOnlyRecords = rr;
-            }
-            // No probing for LocalOnly records; acknowledge them right away
-            if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
-            AcknowledgeRecord(m, rr);
-            return(mStatus_NoError);
-        }
-        else
-        {
-            if (!m->NewLocalRecords) m->NewLocalRecords = rr;
-            *p = rr;
-        }
-    }
-
-    if (!AuthRecord_uDNS(rr))   // This check is superfluous, given that for unicast records we (currently) bail out above
-    {
-        // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records.
-        IncrementAutoTargetServices(m, rr);
-
-        // For records that are not going to probe, acknowledge them right away
-        if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
-            AcknowledgeRecord(m, rr);
-
-        // Adding a record may affect whether or not we should sleep
-        mDNS_UpdateAllowSleep(m);
-    }
-
-    // If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host.
-    // This is used by the in-NIC proxy to send the keepalive packets.
-    if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
-    {
-        mDNSAddr raddr;
-        // Set the record type to known unique to prevent probing keep alive records.
-        // Also make sure we do not announce the keepalive records.
-       rr->resrec.RecordType = kDNSRecordTypeKnownUnique;
-       rr->AnnounceCount     = 0;
-       getKeepaliveRaddr(m, rr, &raddr);
-       // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an
-       // asynchronous task to update the resource record
-       mDNSPlatformGetRemoteMacAddr(&raddr);
-    }
-
-    return(mStatus_NoError);
-}
-
-mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
-{
-    m->ProbeFailTime = m->timenow;
-    m->NumFailedProbes++;
-    // If we've had fifteen or more probe failures, rate-limit to one every five seconds.
-    // If a bunch of hosts have all been configured with the same name, then they'll all
-    // conflict and run through the same series of names: name-2, name-3, name-4, etc.,
-    // up to name-10. After that they'll start adding random increments in the range 1-100,
-    // so they're more likely to branch out in the available namespace and settle on a set of
-    // unique names quickly. If after five more tries the host is still conflicting, then we
-    // may have a serious problem, so we start rate-limiting so we don't melt down the network.
-    if (m->NumFailedProbes >= 15)
-    {
-        m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Excessive name conflicts (%u) for " PRI_DM_NAME " (" PUB_S "); rate limiting in effect",
-            m->NumFailedProbes, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-    }
-}
-
-mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
-{
-    RData *OldRData = rr->resrec.rdata;
-    mDNSu16 OldRDLen = rr->resrec.rdlength;
-    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, OldRDLen);          // ... and let the client know
-}
-
-// 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.
-// Exported so uDNS.c can call this
-mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
-{
-    AuthRecord *r2;
-    mDNSu8 RecordType = rr->resrec.RecordType;
-    AuthRecord **p = &m->ResourceRecords;   // Find this record in our list of active records
-    mDNSBool dupList = mDNSfalse;
-    AuthRecord *tsr = mDNSNULL, *ar;
-    mDNSu32 count = 0;  // Count the number of records sharing the same name with the rr record other than TSR record.
-
-    for (ar = m->ResourceRecords; ar; ar = ar->next)
-    {
-        if (SameResourceRecordNameClassInterface(ar, rr))
-        {
-            if (ar->resrec.rrtype == kDNSType_TSR)
-            {
-                tsr = ar;
-            } else {
-                count++;
-            }
-        }
-    }
-    if (RRLocalOnly(rr))
-    {
-        AuthGroup *a;
-        AuthRecord **rp;
-
-        a = AuthGroupForRecord(&m->rrauth, &rr->resrec);
-        if (!a) return mDNSfalse;
-        rp = &a->members;
-        while (*rp && *rp != rr) rp=&(*rp)->next;
-        p = rp;
-    }
-    else
-    {
-        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
-        {
-            // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
-            // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
-            for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
-        }
-        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("mDNS_Register_internal: 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
-                if (RRLocalOnly(rr))
-                {
-                    dup->next = mDNSNULL;
-                    if (!InsertAuthRecord(m, &m->rrauth, dup))
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Deregister_internal: ERROR!! cannot insert " PRI_S, ARDisplayString(m, dup));
-                    }
-                }
-                else
-                {
-                    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->ProbeRestartCount = rr->ProbeRestartCount;
-                dup->AnnounceCount   = rr->AnnounceCount;
-                dup->RequireGoodbye  = rr->RequireGoodbye;
-                dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
-                dup->ImmedAnswer     = rr->ImmedAnswer;
-                dup->ImmedUnicast    = rr->ImmedUnicast;
-                dup->ImmedAdditional = rr->ImmedAdditional;
-                dup->v4Requester     = rr->v4Requester;
-                dup->v6Requester     = rr->v6Requester;
-                dup->ThisAPInterval  = rr->ThisAPInterval;
-                dup->LastAPTime      = rr->LastAPTime;
-                dup->LastMCTime      = rr->LastMCTime;
-                dup->LastMCInterface = rr->LastMCInterface;
-                dup->Private         = rr->Private;
-                dup->state           = rr->state;
-                rr->RequireGoodbye = mDNSfalse;
-                rr->AnsweredLocalQ = mDNSfalse;
-            }
-        }
-    }
-    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)
-        {
-            // Duplicate records are not used for sending wakeups or goodbyes. Hence, deregister them
-            // immediately. When there is a conflict, we deregister all the conflicting duplicate records
-            // also that have been marked above in this function. In that case, we come here and if we don't
-            // deregister (unilink from the DuplicateRecords list), we will be recursing infinitely. Hence,
-            // clear the HMAC which will cause it to deregister. See <rdar://problem/10380988> for
-            // details.
-            rr->WakeUp.HMAC    = zeroEthAddr;
-            rr->RequireGoodbye = mDNSfalse;
-            rr->resrec.RecordType = kDNSRecordTypeDeregistering;
-            dupList = mDNStrue;
-        }
-        if (*p) debugf("mDNS_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)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Deregister_internal: Record %p not found in list " PRI_S, rr, ARDisplayString(m,rr));
-        }
-        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 this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
-    // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv)" here, but that would not not be safe.
-    // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
-    // mechanism to cope with the client callback modifying the question list while that's happening.
-    // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
-    // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
-    // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other
-    // records, thereby invoking yet more callbacks, without limit.
-    // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending
-    // actual goodbye packets.
-
-#ifndef UNICAST_DISABLED
-    if (AuthRecord_uDNS(rr))
-    {
-        if (rr->RequireGoodbye)
-        {
-            if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
-            rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
-            m->LocalRemoveEvents     = mDNStrue;
-            uDNS_DeregisterRecord(m, rr);
-            // At this point unconditionally we bail out
-            // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
-            // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
-            // process and will complete asynchronously. Either way we don't need to do anything more here.
-            return(mStatus_NoError);
-        }
-        // Sometimes the records don't complete proper deregistration i.e., don't wait for a response
-        // from the server. In that case, if the records have been part of a group update, clear the
-        // state here.
-        rr->updateid = zeroID;
-
-        // We defer cleaning up NAT state only after sending goodbyes. This is important because
-        // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL.
-        // This happens today when we turn on/off interface where we get multiple network transitions
-        // and RestartRecordGetZoneData triggers re-registration of the resource records even though
-        // they may be in Registered state which causes NAT information to be setup multiple times. Defering
-        // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up
-        // NAT state here takes care of the case where we did not send goodbyes at all.
-        if (rr->NATinfo.clientContext)
-        {
-            mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-            rr->NATinfo.clientContext = mDNSNULL;
-        }
-        if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
-        if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
-    }
-#endif // UNICAST_DISABLED
-
-    if      (RecordType == kDNSRecordTypeUnregistered)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Deregister_internal: " PRI_S " already marked kDNSRecordTypeUnregistered",
-            ARDisplayString(m, rr));
-    }
-    else if (RecordType == kDNSRecordTypeDeregistering)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Deregister_internal: " PRI_S " already marked kDNSRecordTypeDeregistering",
-            ARDisplayString(m, rr));
-        return(mStatus_BadReferenceErr);
-    }
-
-    if (rr->WakeUp.HMAC.l[0] ||
-        (((RecordType == kDNSRecordTypeShared) || (rr->ARType == AuthRecordLocalOnly)) &&
-        (rr->RequireGoodbye || rr->AnsweredLocalQ)))
-    {
-        verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr));
-        rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
-        rr->resrec.rroriginalttl = 0;
-        rr->AnnounceCount        = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount;
-        rr->ThisAPInterval       = mDNSPlatformOneSecond * 2;
-        rr->LastAPTime           = m->timenow - rr->ThisAPInterval;
-        m->LocalRemoveEvents     = mDNStrue;
-        if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
-            m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
-    }
-    else
-    {
-        if (!dupList && RRLocalOnly(rr))
-        {
-            AuthGroup *ag = RemoveAuthRecord(m, &m->rrauth, rr);
-            if (ag->NewLocalOnlyRecords == rr) ag->NewLocalOnlyRecords = rr->next;
-        }
-        else
-        {
-            *p = rr->next;                  // Cut this record from the list
-            if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
-            DecrementAutoTargetServices(m, rr);
-        }
-        // If someone is about to look at this, bump the pointer forward
-        if (m->CurrentRecord   == rr) m->CurrentRecord   = rr->next;
-        rr->next = mDNSNULL;
-
-        verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
-        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) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
-
-
-        // 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.
-        if (drt != mDNS_Dereg_conflict)
-        {
-            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_Deregister_internal: callback with mStatus_MemFree for " PRI_S, ARDisplayString(m, rr));
-            if (rr->RecordCallback)
-                rr->RecordCallback(m, rr, mStatus_MemFree);         // MUST NOT touch rr after this
-            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-        }
-        else
-        {
-            RecordProbeFailure(m, rr);
-            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-            if (rr->RecordCallback)
-                rr->RecordCallback(m, rr, mStatus_NameConflict);    // MUST NOT touch rr after this
-            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-            // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
-            // Note that with all the client callbacks going on, by the time we get here all the
-            // records we marked may have been explicitly deregistered by the client anyway.
-            r2 = m->DuplicateRecords;
-            while (r2)
-            {
-                if (r2->ProbeCount != 0xFF)
-                {
-                    r2 = r2->next;
-                }
-                else
-                {
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-                    // See if this record was also registered with any D2D plugins.
-                    D2D_stop_advertising_record(r2);
-#endif
-                    mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict);
-                    // As this is a duplicate record, it will be unlinked from the list
-                    // immediately
-                    r2 = m->DuplicateRecords;
-                }
-            }
-        }
-    }
-    mDNS_UpdateAllowSleep(m);
-    // When same name TSR record is found and count is 1, this means that the last record sharing the same
-    // name with the TSR record was deregistered.  In this case, we should deregister the TSR record.
-    // Notice that if we call mDNS_Deregister_internal() to deregister the TSR record itself, count would be
-    // 0.
-    if (tsr && count == 1)
-    {
-        const RDataBody2 *const rdb = (RDataBody2 *)tsr->resrec.rdata->u.data;
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Removing orphaned TSR - name: " PRI_DM_NAME ", timestamp: %d",
-                  DM_NAME_PARAM(tsr->resrec.name), rdb->tsr_value);
-        if(mDNS_Deregister_internal(m, tsr, mDNS_Dereg_normal))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Failed to deregister orphaned TSR - name: " PRI_DM_NAME
-                      ", timestamp: %d", DM_NAME_PARAM(tsr->resrec.name), rdb->tsr_value);
-            freeL("Orphaned TSR AuthRecord mDNS_Deregister", tsr);
-        }
-    }
-    return(mStatus_NoError);
-}
-
-// ***************************************************************************
-// MARK: - Packet Sending Functions
-
-mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
-{
-    // Add the record if it hasn't already been added. Never add TSR records; these only appear in probes.
-    if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse && rr->resrec.rrtype != kDNSType_TSR)
-    {
-        **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));
-    }
-}
-
-mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID)
-{
-    AuthRecord *rr2;
-    if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask)
-    {
-        for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next)
-        {
-            if ((rr2->resrec.namehash == additional->resrec.namehash) &&
-                (rr2->resrec.rrtype   == additional->resrec.rrtype) &&
-                (rr2 != additional) &&
-                (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) &&
-                (rr2->resrec.rrclass  == additional->resrec.rrclass) &&
-                ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&
-                SameDomainName(rr2->resrec.name, additional->resrec.name))
-            {
-                AddRecordToResponseList(nrpp, rr2, rr);
-            }
-        }
-    }
-}
-
-mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
-{
-    AuthRecord  *rr, *rr2;
-    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(nrpp, rr->Additional1, rr);
-            AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID);
-        }
-
-        if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
-        {
-            AddRecordToResponseList(nrpp, rr->Additional2, rr);
-            AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID);
-        }
-
-        // 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 (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
-                    ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
-                    rr->resrec.rdatahash == rr2->resrec.namehash &&         // ... whose name is the name of the SRV target
-                    SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
-                    AddRecordToResponseList(nrpp, rr2, rr);
-        }
-        else if (RRTypeIsAddressType(rr->resrec.rrtype))    // For A or AAAA, put counterpart as additional
-        {
-            for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                    // Scan list of resource records
-                if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
-                    ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
-                    rr->resrec.namehash == rr2->resrec.namehash &&              // ... and have the same name
-                    SameDomainName(rr->resrec.name, rr2->resrec.name))
-                    AddRecordToResponseList(nrpp, rr2, rr);
-        }
-        else if (rr->resrec.rrtype == kDNSType_PTR)         // For service PTR, see if we want to add DeviceInfo record
-        {
-            if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) &&
-                SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
-                AddRecordToResponseList(nrpp, &m->DeviceInfo, rr);
-        }
-    }
-}
-
-mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID)
-{
-    AuthRecord *rr;
-    AuthRecord  *ResponseRecords = mDNSNULL;
-    AuthRecord **nrp             = &ResponseRecords;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
-
-    // Make a list of all our records that need to be unicast to this destination
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        // If we find we can no longer unicast this answer, clear ImmedUnicast
-        if (rr->ImmedAnswer == mDNSInterfaceMark               ||
-            mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) ||
-            mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr)  )
-            rr->ImmedUnicast = mDNSfalse;
-
-        if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
-        {
-            if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
-                (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
-            {
-                rr->ImmedAnswer  = mDNSNULL;                // Clear the state fields
-                rr->ImmedUnicast = mDNSfalse;
-                rr->v4Requester  = zerov4Addr;
-                rr->v6Requester  = zerov6Addr;
-
-                // Only sent records registered for P2P over P2P interfaces
-                if (intf && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID))
-                {
-                    continue;
-                }
-
-                if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)   // rr->NR_AnswerTo
-                {
-                    rr->NR_AnswerTo = NR_AnswerMulticast;
-                    *nrp = rr;
-                    nrp = &rr->NextResponse;
-                }
-            }
-        }
-    }
-
-    AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
-
-    while (ResponseRecords)
-    {
-        mDNSu8 *responseptr = m->omsg.data;
-        mDNSu8 *newptr;
-        InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
-
-        // Put answers in the packet
-        while (ResponseRecords && ResponseRecords->NR_AnswerTo)
-        {
-            rr = ResponseRecords;
-            if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
-
-            newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec);
-
-            rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
-            if (!newptr && m->omsg.h.numAnswers)
-            {
-                break; // If packet full, send it now
-            }
-            if (newptr) responseptr = newptr;
-            ResponseRecords = rr->NextResponse;
-            rr->NextResponse    = mDNSNULL;
-            rr->NR_AnswerTo     = mDNSNULL;
-            rr->NR_AdditionalTo = mDNSNULL;
-            rr->RequireGoodbye  = mDNStrue;
-        }
-
-        // Add additionals, if there's space
-        while (ResponseRecords && !ResponseRecords->NR_AnswerTo)
-        {
-            rr = ResponseRecords;
-            if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
-            newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec);
-            rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
-
-            if (newptr) responseptr = newptr;
-            if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue;
-            else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark;
-            ResponseRecords = rr->NextResponse;
-            rr->NextResponse    = mDNSNULL;
-            rr->NR_AnswerTo     = mDNSNULL;
-            rr->NR_AdditionalTo = mDNSNULL;
-        }
-
-        if (m->omsg.h.numAnswers)
-            mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSfalse);
-    }
-}
-
-// CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list
-// and the client's mStatus_MemFree callback will have been invoked
-mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "CompleteDeregistration: called for Resource record " PRI_S, ARDisplayString(m, rr));
-    // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
-    // it should go ahead and immediately dispose of this registration
-    rr->resrec.RecordType = kDNSRecordTypeShared;
-    rr->RequireGoodbye    = mDNSfalse;
-    rr->WakeUp.HMAC       = zeroEthAddr;
-    if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); rr->AnsweredLocalQ = mDNSfalse; }
-    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);     // Don't touch rr after this
-}
-
-// DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately)
-// any deregistering records that remain in the m->ResourceRecords list.
-// 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)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DiscardDeregistrations ERROR m->CurrentRecord already set " PRI_S,
-            ARDisplayString(m, m->CurrentRecord));
-    }
-    m->CurrentRecord = m->ResourceRecords;
-
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rr = m->CurrentRecord;
-        if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-            CompleteDeregistration(m, rr);      // Don't touch rr after this
-        else
-            m->CurrentRecord = rr->next;
-    }
-}
-
-mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
-{
-    int i, val = 0;
-    if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
-    for (i=1; i<=src[0]; i++)
-    {
-        if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
-        val = val * 10 + src[i] - '0';
-    }
-    if (val > 255) return(mStatus_Invalid);
-    *dst = (mDNSu8)val;
-    return(mStatus_NoError);
-}
-
-mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
-{
-    int skip = CountLabels(name) - 6;
-    if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
-    if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
-        GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
-        GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
-        GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
-    a->type = mDNSAddrType_IPv4;
-    return(mStatus_NoError);
-}
-
-#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
-                    ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
-                    ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
-
-mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
-{
-    int i, h, l;
-    const domainname *n;
-
-    int skip = CountLabels(name) - 34;
-    if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; }
-
-    n = SkipLeadingLabels(name, skip);
-    for (i=0; i<16; i++)
-    {
-        if (n->c[0] != 1) return mStatus_Invalid;
-        l = HexVal(n->c[1]);
-        n = (const domainname *)(n->c + 2);
-
-        if (n->c[0] != 1) return mStatus_Invalid;
-        h = HexVal(n->c[1]);
-        n = (const domainname *)(n->c + 2);
-
-        if (l<0 || h<0) return mStatus_Invalid;
-        a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l);
-    }
-
-    a->type = mDNSAddrType_IPv6;
-    return(mStatus_NoError);
-}
-
-mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name)
-{
-    int skip = CountLabels(name) - 2;
-    if (skip >= 0)
-    {
-        const domainname *suffix = SkipLeadingLabels(name, skip);
-        if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4;
-        if (SameDomainName(suffix, (const domainname*)"\x3" "ip6"     "\x4" "arpa")) return mDNSAddrType_IPv6;
-    }
-    return(mDNSAddrType_None);
-}
-
-mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr,
-                       const mDNSv4Addr *const spa, const mDNSEthAddr *const tha, const mDNSv4Addr *const tpa, const mDNSEthAddr *const dst)
-{
-    int i;
-    mDNSu8 *ptr = m->omsg.data;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
-    if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
-
-    // 0x00 Destination address
-    for (i=0; i<6; i++) *ptr++ = dst->b[i];
-
-    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
-    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
-
-    // 0x0C ARP Ethertype (0x0806)
-    *ptr++ = 0x08; *ptr++ = 0x06;
-
-    // 0x0E ARP header
-    *ptr++ = 0x00; *ptr++ = 0x01;   // Hardware address space; Ethernet = 1
-    *ptr++ = 0x08; *ptr++ = 0x00;   // Protocol address space; IP = 0x0800
-    *ptr++ = 6;                     // Hardware address length
-    *ptr++ = 4;                     // Protocol address length
-    *ptr++ = 0x00; *ptr++ = op;     // opcode; Request = 1, Response = 2
-
-    // 0x16 Sender hardware address (our MAC address)
-    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
-
-    // 0x1C Sender protocol address
-    for (i=0; i<4; i++) *ptr++ = spa->b[i];
-
-    // 0x20 Target hardware address
-    for (i=0; i<6; i++) *ptr++ = tha->b[i];
-
-    // 0x26 Target protocol address
-    for (i=0; i<4; i++) *ptr++ = tpa->b[i];
-
-    // 0x2A Total ARP Packet length 42 bytes
-    mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
-}
-
-mDNSlocal mDNSu16 CheckSum(const void *const data, mDNSs32 length, mDNSu32 sum)
-{
-    const mDNSu16 *ptr = data;
-    while (length > 0) { length -= 2; sum += *ptr++; }
-    sum = (sum & 0xFFFF) + (sum >> 16);
-    sum = (sum & 0xFFFF) + (sum >> 16);
-    return(sum != 0xFFFF ? sum : 0);
-}
-
-mDNSlocal mDNSu16 IPv6CheckSum(const mDNSv6Addr *const src, const mDNSv6Addr *const dst, const mDNSu8 protocol, const void *const data, const mDNSu32 length)
-{
-    IPv6PseudoHeader ph;
-    ph.src = *src;
-    ph.dst = *dst;
-    ph.len.b[0] = length >> 24;
-    ph.len.b[1] = length >> 16;
-    ph.len.b[2] = length >> 8;
-    ph.len.b[3] = length;
-    ph.pro.b[0] = 0;
-    ph.pro.b[1] = 0;
-    ph.pro.b[2] = 0;
-    ph.pro.b[3] = protocol;
-    return CheckSum(&ph, sizeof(ph), CheckSum(data, length, 0));
-}
-
-mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const AuthRecord *const rr,
-                       const mDNSv6Addr *const spa, const mDNSEthAddr *const tha, const mDNSv6Addr *const tpa, const mDNSEthAddr *const dst)
-{
-    int i;
-    mDNSOpaque16 checksum;
-    mDNSu8 *ptr = m->omsg.data;
-    // Some recipient hosts seem to ignore Neighbor Solicitations if the IPv6-layer destination address is not the
-    // appropriate IPv6 solicited node multicast address, so we use that IPv6-layer destination address, even though
-    // at the Ethernet-layer we unicast the packet to the intended target, to avoid wasting network bandwidth.
-    const mDNSv6Addr mc = { { 0xFF,0x02,0x00,0x00, 0,0,0,0, 0,0,0,1, 0xFF,tpa->b[0xD],tpa->b[0xE],tpa->b[0xF] } };
-    const mDNSv6Addr *const v6dst = (op == NDP_Sol) ? &mc : tpa;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
-    if (!intf) { LogMsg("SendNDP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
-
-    // 0x00 Destination address
-    for (i=0; i<6; i++) *ptr++ = dst->b[i];
-    // Right now we only send Neighbor Solicitations to verify whether the host we're proxying for has gone to sleep yet.
-    // Since we know who we're looking for, we send it via Ethernet-layer unicast, rather than bothering every host on the
-    // link with a pointless link-layer multicast.
-    // Should we want to send traditional Neighbor Solicitations in the future, where we really don't know in advance what
-    // Ethernet-layer address we're looking for, we'll need to send to the appropriate Ethernet-layer multicast address:
-    // *ptr++ = 0x33;
-    // *ptr++ = 0x33;
-    // *ptr++ = 0xFF;
-    // *ptr++ = tpa->b[0xD];
-    // *ptr++ = tpa->b[0xE];
-    // *ptr++ = tpa->b[0xF];
-
-    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
-    for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
-
-    // 0x0C IPv6 Ethertype (0x86DD)
-    *ptr++ = 0x86; *ptr++ = 0xDD;
-
-    // 0x0E IPv6 header
-    *ptr++ = 0x60; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00;     // Version, Traffic Class, Flow Label
-    *ptr++ = 0x00; *ptr++ = 0x20;                                   // Length
-    *ptr++ = 0x3A;                                                  // Protocol == ICMPv6
-    *ptr++ = 0xFF;                                                  // Hop Limit
-
-    // 0x16 Sender IPv6 address
-    for (i=0; i<16; i++) *ptr++ = spa->b[i];
-
-    // 0x26 Destination IPv6 address
-    for (i=0; i<16; i++) *ptr++ = v6dst->b[i];
-
-    // 0x36 NDP header
-    *ptr++ = op;                    // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
-    *ptr++ = 0x00;                  // Code
-    *ptr++ = 0x00; *ptr++ = 0x00;   // Checksum placeholder (0x38, 0x39)
-    *ptr++ = flags;
-    *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00;
-
-    if (op == NDP_Sol)  // Neighbor Solicitation. The NDP "target" is the address we seek.
-    {
-        // 0x3E NDP target.
-        for (i=0; i<16; i++) *ptr++ = tpa->b[i];
-        // 0x4E Source Link-layer Address
-        // <http://www.ietf.org/rfc/rfc2461.txt>
-        // MUST NOT be included when the source IP address is the unspecified address.
-        // Otherwise, on link layers that have addresses this option MUST be included
-        // in multicast solicitations and SHOULD be included in unicast solicitations.
-        if (!mDNSIPv6AddressIsZero(*spa))
-        {
-            *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address
-            *ptr++ = 0x01;      // Option length 1 (in units of 8 octets)
-            for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
-        }
-    }
-    else            // Neighbor Advertisement. The NDP "target" is the address we're giving information about.
-    {
-        // 0x3E NDP target.
-        for (i=0; i<16; i++) *ptr++ = spa->b[i];
-        // 0x4E Target Link-layer Address
-        *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address
-        *ptr++ = 0x01;      // Option length 1 (in units of 8 octets)
-        for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i];
-    }
-
-    // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes
-    m->omsg.data[0x13] = ptr - &m->omsg.data[0x36];     // Compute actual length
-    checksum.NotAnInteger = ~IPv6CheckSum(spa, v6dst, 0x3A, &m->omsg.data[0x36], m->omsg.data[0x13]);
-    m->omsg.data[0x38] = checksum.b[0];
-    m->omsg.data[0x39] = checksum.b[1];
-
-    mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
-}
-
-mDNSlocal void SetupTracerOpt(const mDNS *const m, rdataOPT *const Trace)
-{
-    mDNSu32 DNS_VERS = _DNS_SD_H;
-    Trace->u.tracer.platf    = m->mDNS_plat;
-    Trace->u.tracer.mDNSv    = DNS_VERS;
-
-    Trace->opt              = kDNSOpt_Trace;
-    Trace->optlen           = DNSOpt_TraceData_Space - 4;
-}
-
-mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner)
-{
-    owner->u.owner.vers     = 0;
-    owner->u.owner.seq      = m->SleepSeqNum;
-    owner->u.owner.HMAC     = m->PrimaryMAC;
-    owner->u.owner.IMAC     = intf->MAC;
-    owner->u.owner.password = zeroEthAddr;
-
-    // Don't try to compute the optlen until *after* we've set up the data fields
-    // Right now the DNSOpt_Owner_Space macro does not depend on the owner->u.owner being set up correctly, but in the future it might
-    owner->opt              = kDNSOpt_Owner;
-    owner->optlen           = DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) - 4;
-}
-
-mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
-{
-    if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
-    else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
-}
-
-mDNSlocal mDNSBool ShouldSendGoodbyesBeforeSleep(mDNS *const m, const NetworkInterfaceInfo *intf, AuthRecord *rr)
-{
-    // If there are no sleep proxies, we set the state to SleepState_Sleeping explicitly
-    // and hence there is no need to check for Transfering state. But if we have sleep
-    // proxies and partially sending goodbyes for some records, we will be in Transfering
-    // state and hence need to make sure that we send goodbyes in that case too. Checking whether
-    // we are not awake handles both cases.
-    if ((rr->AuthFlags & AuthFlagsWakeOnly) && (m->SleepState != SleepState_Awake))
-    {
-        debugf("ShouldSendGoodbyesBeforeSleep: marking for goodbye", ARDisplayString(m, rr));
-        return mDNStrue;
-    }
-
-    if (m->SleepState != SleepState_Sleeping)
-        return mDNSfalse;
-
-    // If we are going to sleep and in SleepState_Sleeping, SendGoodbyes on the interface tell you
-    // whether you can send goodbyes or not.
-    if (!intf->SendGoodbyes)
-    {
-        debugf("ShouldSendGoodbyesBeforeSleep: not sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID);
-        return mDNSfalse;
-    }
-    else
-    {
-        debugf("ShouldSendGoodbyesBeforeSleep: sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID);
-        return mDNStrue;
-    }
-}
-
-// 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 + FutureTime;
-
-    if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
-
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-        if (rr->ImmedUnicast)
-        {
-            mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} };
-            mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} };
-            v4.ip.v4 = rr->v4Requester;
-            v6.ip.v6 = rr->v6Requester;
-            if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer);
-            if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer);
-            if (rr->ImmedUnicast)
-            {
-                LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr));
-                rr->ImmedUnicast = mDNSfalse;
-            }
-        }
-
-    // ***
-    // *** 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)
-    {
-        while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
-        if (TimeToAnnounceThisRecord(rr, m->timenow))
-        {
-            if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-            {
-                if (!rr->WakeUp.HMAC.l[0])
-                {
-                    if (rr->AnnounceCount) rr->ImmedAnswer = mDNSInterfaceMark;     // Send goodbye packet on all interfaces
-                }
-                else
-                {
-                    mDNSBool unicastOnly;
-                    LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                    unicastOnly = ((rr->AnnounceCount == WakeupCount) || (rr->AnnounceCount == WakeupCount - 1)) ? mDNStrue : mDNSfalse;
-                    SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password, unicastOnly);
-                    for (r2 = rr; r2; r2=r2->next)
-                        if ((r2->resrec.RecordType == kDNSRecordTypeDeregistering) && r2->AnnounceCount && (r2->resrec.InterfaceID == rr->resrec.InterfaceID) &&
-                            mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC))
-                        {
-                            // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original
-                            // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict.
-                            if (r2->AddressProxy.type == mDNSAddrType_IPv6 && r2->AnnounceCount == WakeupCount)
-                            {
-                                LogSPS("NDP Announcement %2d Releasing traffic for H-MAC %.6a I-MAC %.6a %s",
-                                       r2->AnnounceCount-3, &r2->WakeUp.HMAC, &r2->WakeUp.IMAC, ARDisplayString(m,r2));
-                                SendNDP(m, NDP_Adv, NDP_Override, r2, &r2->AddressProxy.ip.v6, &r2->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth);
-                            }
-                            r2->LastAPTime = m->timenow;
-                            // After 15 wakeups without success (maybe host has left the network) send three goodbyes instead
-                            if (--r2->AnnounceCount <= GoodbyeCount) r2->WakeUp.HMAC = zeroEthAddr;
-                        }
-                }
-            }
-            else if (ResourceRecordIsValidAnswer(rr))
-            {
-                if (rr->AddressProxy.type)
-                {
-                    if (!mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC))
-                    {
-                        rr->AnnounceCount--;
-                        rr->ThisAPInterval *= 2;
-                        rr->LastAPTime = m->timenow;
-                        if (rr->AddressProxy.type == mDNSAddrType_IPv4)
-                        {
-                            LogSPS("ARP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
-                                    rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
-                            SendARP(m, 1, rr, &rr->AddressProxy.ip.v4, &zeroEthAddr, &rr->AddressProxy.ip.v4, &onesEthAddr);
-                        }
-                        else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
-                        {
-                            LogSPS("NDP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
-                                    rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
-                            SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
-                        }
-                    }
-                }
-                else
-                {
-                    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) &&
-             !rr->AddressProxy.type &&                  // Don't include ARP Annoucements when considering which records to accelerate
-             ResourceRecordIsValidAnswer(rr)))
-            rr->ImmedAnswer = mDNSInterfaceMark;        // Send on all interfaces
-
-    // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals
-    // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
-    // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen)
-    // then all that means is that it won't get sent -- which would not be the end of the world.
-    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 (RRTypeIsAddressType(r2->resrec.rrtype) &&           // 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.rdatahash == 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->ImmedAdditional = r2->resrec.InterfaceID;       // ... then mark this address record for sending too
-        // We also make sure we send the DeviceInfo TXT record too, if necessary
-        // We check for RecordType == kDNSRecordTypeShared because we don't want to tag the
-        // DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering).
-        if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR)
-            if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
-            {
-                if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer;
-                else m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark;
-            }
-    }
-
-    // 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 ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
-                        (r2->ImmedAnswer != mDNSInterfaceMark) && (r2->ImmedAnswer != rr->ImmedAnswer) &&
-                        SameResourceRecordSignature(r2, rr) &&
-                        ((rr->ImmedAnswer == mDNSInterfaceMark) || IsInterfaceValidForAuthRecord(r2, rr->ImmedAnswer)))
-                    {
-                        r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
-                    }
-                }
-            }
-            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 ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
-                        (r2->ImmedAdditional != rr->ImmedAdditional) &&
-                        SameResourceRecordSignature(r2, rr) &&
-                        IsInterfaceValidForAuthRecord(r2, rr->ImmedAdditional))
-                    {
-                        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;
-            rr->ProbeRestartCount = 0;                  // Reset the probe restart count
-            // 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--;
-                if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
-                    rr->ThisAPInterval *= 2;
-                rr->LastAPTime = m->timenow;
-                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);
-        //if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr));
-    }
-
-    // ***
-    // *** 2. Loop through interface list, sending records as appropriate
-    // ***
-
-    while (intf)
-    {
-        int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
-        int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0;
-        int numDereg    = 0;
-        int numAnnounce = 0;
-        int numAnswer   = 0;
-        mDNSu8 *responseptr = m->omsg.data;
-        mDNSu8 *newptr;
-        InitializeDNSMessage(&m->omsg.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
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-        {
-
-            // Skip this interface if the record InterfaceID is *Any and the record is not
-            // appropriate for the interface type.
-            if ((rr->SendRNow == intf->InterfaceID) &&
-                ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID)))
-            {
-                rr->SendRNow = GetNextActiveInterfaceID(intf);
-            }
-            else if (rr->SendRNow == intf->InterfaceID)
-            {
-                RData  *OldRData    = rr->resrec.rdata;
-                mDNSu16 oldrdlength = rr->resrec.rdlength;
-                mDNSu8 active = (mDNSu8)
-                                (rr->resrec.RecordType != kDNSRecordTypeDeregistering && !ShouldSendGoodbyesBeforeSleep(m, intf, rr));
-                newptr = mDNSNULL;
-                if (rr->NewRData && active)
-                {
-                    // See if we should send a courtesy "goodbye" for the old data before we replace it.
-                    if (ResourceRecordIsValidAnswer(rr) && rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
-                    {
-                        newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
-                        if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
-                        else continue; // If this packet is already too full to hold the goodbye for this record, skip it for now and we'll retry later
-                    }
-                    SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
-                }
-
-                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                    rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
-                newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0);
-                rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
-                if (newptr)
-                {
-                    responseptr = newptr;
-                    rr->RequireGoodbye = active;
-                    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) numDereg++;
-                    else if (rr->LastAPTime == m->timenow) numAnnounce++;else numAnswer++;
-                }
-
-                if (rr->NewRData && active)
-                    SetNewRData(&rr->resrec, OldRData, oldrdlength);
-
-                // The first time through (pktcount==0), if this record is verified unique
-                // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
-                if (!pktcount && active && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
-                    rr->SendNSECNow = mDNSInterfaceMark;
-
-                if (newptr)     // If succeeded in sending, advance to next interface
-                {
-                    // 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)
-                if (ResourceRecordIsValidAnswer(rr))
-                {
-                    // If we have at least one answer already in the packet, then plan to add additionals too
-                    mDNSBool SendAdditional = (m->omsg.h.numAnswers > 0);
-
-                    // If we're not planning to send any additionals, but this record is a unique one, then
-                    // make sure we haven't already sent any other members of its RRSet -- if we have, then they
-                    // will have had the cache flush bit set, so now we need to finish the job and send the rest.
-                    if (!SendAdditional && (rr->resrec.RecordType & kDNSRecordTypeUniqueMask))
-                    {
-                        const AuthRecord *a;
-                        for (a = m->ResourceRecords; a; a=a->next)
-                            if (a->LastMCTime      == m->timenow &&
-                                a->LastMCInterface == intf->InterfaceID &&
-                                SameResourceRecordSignature(a, rr)) { SendAdditional = mDNStrue; break; }
-                    }
-                    if (!SendAdditional)                    // If we don't want to send this after all,
-                        rr->ImmedAdditional = mDNSNULL;     // then cancel its ImmedAdditional field
-                    else if (newptr)                        // Else, try to add it if we can
-                    {
-                        // The first time through (pktcount==0), if this record is verified unique
-                        // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
-                        if (!pktcount && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
-                            rr->SendNSECNow = mDNSInterfaceMark;
-
-                        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                            rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the cache flush bit so PutResourceRecord will set it
-                        newptr = PutRR_OS(newptr, &m->omsg.h.numAdditionals, &rr->resrec);
-                        rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;       // Make sure to clear cache flush bit back to normal state
-                        if (newptr)
-                        {
-                            responseptr = newptr;
-                            rr->ImmedAdditional = mDNSNULL;
-                            rr->RequireGoodbye = mDNStrue;
-                            // If we successfully put this additional record in the packet, we record LastMCTime & LastMCInterface.
-                            // This matters particularly in the case where we have more than one IPv6 (or IPv4) address, because otherwise,
-                            // when we see our own multicast with the cache flush bit set, if we haven't set LastMCTime, then we'll get
-                            // all concerned and re-announce our record again to make sure it doesn't get flushed from peer caches.
-                            rr->LastMCTime      = m->timenow;
-                            rr->LastMCInterface = intf->InterfaceID;
-                        }
-                    }
-                }
-
-        // Third Pass. Add NSEC records, if there's space.
-        // When we're generating an NSEC record in response to a specify query for that type
-        // (recognized by rr->SendNSECNow == intf->InterfaceID) we should really put the NSEC in the Answer Section,
-        // not Additional Section, but for now it's easier to handle both cases in this Additional Section loop here.
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-            if (rr->SendNSECNow == mDNSInterfaceMark || rr->SendNSECNow == intf->InterfaceID)
-            {
-                AuthRecord nsec;
-                int len;
-                mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-                nsec.resrec.rrclass |= kDNSClass_UniqueRRSet;
-                AssignDomainName(&nsec.namestorage, rr->resrec.name);
-                len = DomainNameLength(rr->resrec.name);
-                // We have a nxt name followed by window number, window length and a window bitmap
-                nsec.resrec.rdlength = len + 2 + NSEC_MCAST_WINDOW_SIZE;
-                if (nsec.resrec.rdlength <= StandardAuthRDSize)
-                {
-                    mDNSu8 *ptr = nsec.rdatastorage.u.data;
-                    mDNSPlatformMemZero(ptr, nsec.resrec.rdlength);
-                    AssignDomainName(&nsec.rdatastorage.u.name, rr->resrec.name);
-                    ptr += len;
-                    *ptr++ = 0; // window number
-                    *ptr++ = NSEC_MCAST_WINDOW_SIZE; // window length
-                    for (r2 = m->ResourceRecords; r2; r2=r2->next)
-                        if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr))
-                        {
-                            if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("SendResponses: Can't create NSEC for record %s", ARDisplayString(m, r2)); break; }
-                            else ptr[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7);
-                        }
-                    newptr = responseptr;
-                    if (!r2)    // If we successfully built our NSEC record, add it to the packet now
-                    {
-                        newptr = PutRR_OS(responseptr, &m->omsg.h.numAdditionals, &nsec.resrec);
-                        if (newptr) responseptr = newptr;
-                    }
-                }
-                else LogMsg("SendResponses: not enough space (%d)  in authrecord for nsec", nsec.resrec.rdlength);
-
-                // If we successfully put the NSEC record, clear the SendNSECNow flag
-                // If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record
-                if (newptr || rr->SendNSECNow == mDNSInterfaceMark)
-                {
-                    rr->SendNSECNow = mDNSNULL;
-                    // Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC
-                    for (r2 = rr->next; r2; r2=r2->next)
-                        if (SameResourceRecordNameClassInterface(r2, rr))
-                            if (r2->SendNSECNow == mDNSInterfaceMark || r2->SendNSECNow == intf->InterfaceID)
-                                r2->SendNSECNow = mDNSNULL;
-                }
-            }
-
-        if (m->omsg.h.numAnswers || m->omsg.h.numAdditionals)
-        {
-            // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet
-            if (OwnerRecordSpace || TraceRecordSpace)
-            {
-                AuthRecord opt;
-                mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-                opt.resrec.rrclass    = NormalMaxDNSMessageData;
-                opt.resrec.rdlength   = sizeof(rdataOPT);
-                opt.resrec.rdestimate = sizeof(rdataOPT);
-                if (OwnerRecordSpace && TraceRecordSpace)
-                {
-                    opt.resrec.rdlength   += sizeof(rdataOPT); // Two options in this OPT record
-                    opt.resrec.rdestimate += sizeof(rdataOPT);
-                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
-                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]);
-                }
-                else if (OwnerRecordSpace)
-                {
-                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
-                }
-                else if (TraceRecordSpace)
-                {
-                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
-                }
-                newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec);
-                if (newptr)
-                {
-                    responseptr = newptr;
-                }
-                else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1)
-                {
-                    LogInfo("SendResponses: No space in packet for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
-                            m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
-                }
-                else
-                {
-                    LogMsg("SendResponses: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
-                           m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
-                }
-            }
-
-            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",
-                   m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
-
-            if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSfalse);
-            if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSfalse);
-            // If shutting down, don't suppress responses so that goodbyes for auth records get sent without delay.
-            if (!m->SuppressResponses && !m->ShutdownTime)
-            {
-                m->SuppressResponses = NonZeroTime(m->timenow + ((mDNSPlatformOneSecond + 9) / 10));
-            }
-            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);
-            intf = next;
-            pktcount = 0;       // When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it
-        }
-    }
-
-    // ***
-    // *** 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 %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = m->ResourceRecords;
-    while (m->CurrentRecord)
-    {
-        rr = m->CurrentRecord;
-        m->CurrentRecord = rr->next;
-
-        if (rr->SendRNow)
-        {
-            if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
-                LogInfo("SendResponses: No active interface %d to send: %d %02X %s",
-                IIDPrintable(rr->SendRNow), IIDPrintable(rr->resrec.InterfaceID), rr->resrec.RecordType, ARDisplayString(m, rr));
-            rr->SendRNow = mDNSNULL;
-        }
-
-        if (rr->ImmedAnswer || rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-        {
-            if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
-
-            if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->AnnounceCount == 0)
-            {
-                // For Unicast, when we get the response from the server, we will call CompleteDeregistration
-                if (!AuthRecord_uDNS(rr)) CompleteDeregistration(m, rr);        // Don't touch rr after this
-            }
-            else
-            {
-                rr->ImmedAnswer  = mDNSNULL;
-                rr->ImmedUnicast = mDNSfalse;
-                rr->v4Requester  = zerov4Addr;
-                rr->v6Requester  = zerov6Addr;
-            }
-        }
-    }
-    verbosedebugf("SendResponses: Next in %ld 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
-// 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
-//    (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
-#define CacheCheckGracePeriod(CR) (                                                   \
-        ((CR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
-        ((CR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(CR)/50)            : \
-        ((CR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : \
-        ((CR)->resrec.rroriginalttl > 0                ) ? (mDNSPlatformOneSecond/10)   : 0)
-
-#define NextCacheCheckEvent(CR) ((CR)->NextRequiredQuery + CacheCheckGracePeriod(CR))
-
-mDNSexport void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event)
-{
-    if (m->rrcache_nextcheck[slot] - event > 0)
-        m->rrcache_nextcheck[slot] = event;
-    if (m->NextCacheCheck          - event > 0)
-        m->NextCacheCheck          = event;
-}
-
-// Note: MUST call SetNextCacheCheckTimeForRecord any time we change:
-// rr->TimeRcvd
-// rr->resrec.rroriginalttl
-// rr->UnansweredQueries
-// rr->CRActiveQuestion
-mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr)
-{
-    rr->NextRequiredQuery = RRExpireTime(rr);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Do not schedule the refresher query for DNSSEC-validated record, because its TTL is controlled by multiple
-    // records that might be already in the progress of refreshing.
-    // Set UnansweredQueries to MaxUnansweredQueries to avoid the expensive and unnecessary queries.
-    if (resource_record_is_dnssec_validated(&rr->resrec) && rr->UnansweredQueries != MaxUnansweredQueries)
-    {
-        rr->UnansweredQueries = MaxUnansweredQueries;
-    }
-#endif
-
-    // 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("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s",
-                      (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr));
-    }
-    ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(rr->resrec.namehash), NextCacheCheckEvent(rr));
-}
-
-#define kMinimumReconfirmTime                     ((mDNSu32)mDNSPlatformOneSecond *  5)
-#define kDefaultReconfirmTimeForWake              ((mDNSu32)mDNSPlatformOneSecond *  5)
-#define kDefaultReconfirmTimeForNoAnswer          ((mDNSu32)mDNSPlatformOneSecond *  5)
-
-// Delay before restarting questions on a flapping interface.
-#define kDefaultQueryDelayTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond *  3)
-// After kDefaultQueryDelayTimeForFlappingInterface seconds, allow enough time for up to three queries (0, 1, and 4 seconds)
-// plus three seconds for "response delay" before removing the reconfirmed records from the cache.
-#define kDefaultReconfirmTimeForFlappingInterface (kDefaultQueryDelayTimeForFlappingInterface + ((mDNSu32)mDNSPlatformOneSecond *  7))
-
-mDNSexport 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
-        // For all the reconfirmations in a given batch, we want to use the same random value
-        // so that the reconfirmation questions can be grouped into a single query packet
-        if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(FutureTime);
-        interval += m->RandomReconfirmDelay % ((interval/3) + 1);
-        rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
-        rr->resrec.rroriginalttl     = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
-        SetNextCacheCheckTimeForRecord(m, rr);
-    }
-    debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p",
-           RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion);
-    return(mStatus_NoError);
-}
-
-// 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, const NetworkInterfaceInfo *intf, DNSMessage *query, mDNSu8 **queryptr,
-                                 DNSQuestion *q, CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
-{
-    mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse;
-    mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
-    const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
-    mDNSu8 *newptr = putQuestion(query, *queryptr, limit - *answerforecast, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
-    if (!newptr)
-    {
-        debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return(mDNSfalse);
-    }
-    else
-    {
-        mDNSu32 forecast = *answerforecast;
-        const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-        CacheRecord *cr;
-        CacheRecord **ka = *kalistptrptr;   // Make a working copy of the pointer we're going to update
-
-        for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)             // If we have a resource record in our cache,
-            if (cr->resrec.InterfaceID == q->SendQNow &&                    // received on this interface
-                !(cr->resrec.RecordType & kDNSRecordTypeUniqueMask) &&      // which is a shared (i.e. not unique) record type
-                cr->NextInKAList == mDNSNULL && ka != &cr->NextInKAList &&  // which is not already in the known answer list
-                cr->resrec.rdlength <= SmallRecordLimit &&                  // which is small enough to sensibly fit in the packet
-                SameNameCacheRecordAnswersQuestion(cr, q) &&                // which answers our question
-                cr->TimeRcvd + TicksTTL(cr)/2 - m->timenow >                // and its half-way-to-expiry time is at least 1 second away
-                mDNSPlatformOneSecond)                                      // (also ensures we never include goodbye records with TTL=1)
-            {
-                // We don't want to include unique records in the Known Answer section. The Known Answer section
-                // is intended to suppress floods of shared-record replies from many other devices on the network.
-                // That concept really does not apply to unique records, and indeed if we do send a query for
-                // which we have a unique record already in our cache, then including that unique record as a
-                // Known Answer, so as to suppress the only answer we were expecting to get, makes little sense.
-
-                *ka = cr;   // Link this record into our known answer chain
-                ka = &cr->NextInKAList;
-                // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
-                forecast += 12 + cr->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)
-                {
-                    query->h.numQuestions--;
-                    debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d, total questions %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 *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; }
-                    return(mDNSfalse);      // Return false, so we'll try again in the next packet
-                }
-            }
-
-        // 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) q->ExpectUnicastResp = NonZeroTime(m->timenow);
-
-        for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)             // For every resource record in our cache,
-            if (cr->resrec.InterfaceID == q->SendQNow &&                    // received on this interface
-                cr->NextInKAList == mDNSNULL && ka != &cr->NextInKAList &&  // which is not in the known answer list
-                SameNameCacheRecordAnswersQuestion(cr, q))                  // which answers our question
-            {
-                cr->UnansweredQueries++;                                    // indicate that we're expecting a response
-                cr->LastUnansweredTime = m->timenow;
-                SetNextCacheCheckTimeForRecord(m, cr);
-            }
-
-        return(mDNStrue);
-    }
-}
-
-// When we have a query looking for a specified name, but there appear to be no answers with
-// that name, ReconfirmAntecedents() is called with depth=0 to start the reconfirmation process
-// for any records in our cache that reference the given name (e.g. PTR and SRV records).
-// For any such cache record we find, we also recursively call ReconfirmAntecedents() for *its* name.
-// We increment depth each time we recurse, to guard against possible infinite loops, with a limit of 5.
-// A typical reconfirmation scenario might go like this:
-// Depth 0: Name "myhost.local" has no address records
-// Depth 1: SRV "My Service._example._tcp.local." refers to "myhost.local"; may be stale
-// Depth 2: PTR "_example._tcp.local." refers to "My Service"; may be stale
-// Depth 3: PTR "_services._dns-sd._udp.local." refers to "_example._tcp.local."; may be stale
-// Currently depths 4 and 5 are not expected to occur; if we did get to depth 5 we'd reconfim any records we
-// found referring to the given name, but not recursively descend any further reconfirm *their* antecedents.
-mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSInterfaceID InterfaceID, const int depth)
-{
-    mDNSu32 slot;
-    const CacheGroup *cg;
-    CacheRecord *cr;
-    debugf("ReconfirmAntecedents (depth=%d) for %##s", depth, name->c);
-    if (!InterfaceID) return; // mDNS records have a non-zero InterfaceID. If InterfaceID is 0, then there's nothing to do.
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        const domainname *crtarget;
-        if (cr->resrec.InterfaceID != InterfaceID) continue; // Skip non-mDNS records and mDNS records from other interfaces.
-        if (cr->resrec.rdatahash != namehash)      continue; // Skip records whose rdata hash doesn't match the name hash.
-        crtarget = GetRRDomainNameTarget(&cr->resrec);
-        if (crtarget && SameDomainName(crtarget, name))
-        {
-            LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d, InterfaceID=%p) %s", depth, InterfaceID, CRDisplayString(m, cr));
-            mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-            if (depth < 5)
-                ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, InterfaceID, depth+1);
-        }
-    }
-}
-
-// If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents
-// we check if we have an address record for the same name. If we do have an IPv4 address for a given
-// name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure
-// to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
-mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
-{
-    CacheGroup *const cg = CacheGroupForName(m, namehash, name);
-    const CacheRecord *cr = cg ? cg->members : mDNSNULL;
-    while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
-    return(cr);
-}
-
-
-mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
-{
-#ifndef SPC_DISABLED
-    CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-    const CacheRecord *cr, *bestcr = mDNSNULL;
-    mDNSu32 bestmetric = 1000000;
-    for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-        if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6)                      // If record is PTR type, with long enough name,
-            if (cr != c0 && cr != c1)                                                           // that's not one we've seen before,
-                if (SameNameCacheRecordAnswersQuestion(cr, q))                                  // and answers our browse query,
-                    if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec))    // and is not our own advertised service...
-                    {
-                        mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
-                        if (bestmetric > metric) { bestmetric = metric; bestcr = cr; }
-                    }
-    return(bestcr);
-#else // SPC_DISABLED
-    (void) m;
-    (void) q;
-    (void) c0;
-    (void) c1;
-    (void) c1;
-    return mDNSNULL;
-#endif // SPC_DISABLED
-}
-
-mDNSlocal void CheckAndSwapSPS(const CacheRecord **sps1, const CacheRecord **sps2)
-{
-    const CacheRecord *swap_sps;
-    mDNSu32 metric1, metric2;
-
-    if (!(*sps1) || !(*sps2)) return;
-    metric1 = SPSMetric((*sps1)->resrec.rdata->u.name.c);
-    metric2 = SPSMetric((*sps2)->resrec.rdata->u.name.c);
-    if (!SPSFeatures((*sps1)->resrec.rdata->u.name.c) && SPSFeatures((*sps2)->resrec.rdata->u.name.c) && (metric2 >= metric1))
-    {
-        swap_sps = *sps1;
-        *sps1    = *sps2;
-        *sps2    = swap_sps;
-    }
-}
-
-mDNSlocal void ReorderSPSByFeature(const CacheRecord *sps[3])
-{
-    CheckAndSwapSPS(&sps[0], &sps[1]);
-    CheckAndSwapSPS(&sps[0], &sps[2]);
-    CheckAndSwapSPS(&sps[1], &sps[2]);
-}
-
-
-// Finds the three best Sleep Proxies we currently have in our cache
-mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3])
-{
-    sps[0] =                      FindSPSInCache1(m, q, mDNSNULL, mDNSNULL);
-    sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   mDNSNULL);
-    sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   sps[1]);
-
-    // SPS is already sorted by metric. We want to move the entries to the beginning of the array
-    // only if they have equally good metric and support features.
-    ReorderSPSByFeature(sps);
-}
-
-// 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 void 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;
-}
-
-mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q)
-{
-    int len, i, cnt;
-    mDNSInterfaceID InterfaceID = q->InterfaceID;
-    domainname *d = &q->qname;
-
-    // We can't send magic packets without knowing which interface to send it on.
-    if (InterfaceID == mDNSInterface_Any || LocalOnlyOrP2PInterface(InterfaceID))
-    {
-        LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c);
-        return;
-    }
-
-    // Split MAC@IPAddress and pass them separately
-    len = d->c[0];
-    cnt = 0;
-    for (i = 1; i < len; i++)
-    {
-        if (d->c[i] == '@')
-        {
-            char EthAddr[18];   // ethernet adddress : 12 bytes + 5 ":" + 1 NULL byte
-            char IPAddr[47];    // Max IP address len: 46 bytes (IPv6) + 1 NULL byte
-            if (cnt != 5)
-            {
-                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, cnt %d", q->qname.c, cnt);
-                return;
-            }
-            if ((i - 1) > (int) (sizeof(EthAddr) - 1))
-            {
-                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, length %d", q->qname.c, i - 1);
-                return;
-            }
-            if ((len - i) > (int)(sizeof(IPAddr) - 1))
-            {
-                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed IP address %##s, length %d", q->qname.c, len - i);
-                return;
-            }
-            mDNSPlatformMemCopy(EthAddr, &d->c[1], i - 1);
-            EthAddr[i - 1] = 0;
-            mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i);
-            IPAddr[len - i] = 0;
-            m->mDNSStats.WakeOnResolves++;
-            mDNSPlatformSendWakeupPacket(InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount);
-            return;
-        }
-        else if (d->c[i] == ':')
-            cnt++;
-    }
-    LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed WakeOnResolve name %##s", q->qname.c);
-}
-
-
-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;
-        const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-        const CacheRecord *cr;
-        for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)              // If we have a resource record in our cache,
-            if (cr->resrec.rdlength <= SmallRecordLimit &&                   // which is small enough to sensibly fit in the packet
-                SameNameCacheRecordAnswersQuestion(cr, q) &&                 // which answers our question
-                cr->TimeRcvd + TicksTTL(cr)/2 - m->timenow >= 0 &&           // and it is less than half-way to expiry
-                cr->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 + cr->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);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-mDNSlocal mDNSBool QuestionSendsMDNSQueriesViaUnicast(const DNSQuestion *const q)
-{
-    return (mDNSOpaque16IsZero(q->TargetQID) && mDNSAddressIsValidNonZero(&q->UnicastMDNSResolver));
-}
-#endif
-
-// 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)
-{
-    mDNSu32 slot;
-    CacheGroup *cg;
-    CacheRecord *cr;
-    AuthRecord *ar;
-    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
-
-    // 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
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
-        {
-            if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
-            {
-                debugf("Sending %d%% cache expiration query for %s", 80 + 5 * cr->UnansweredQueries, CRDisplayString(m, cr));
-                q = cr->CRActiveQuestion;
-                ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(cr)/20, cr->resrec.InterfaceID);
-                // For uDNS queries (TargetQID non-zero) we adjust LastQTime,
-                // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
-                if (!mDNSOpaque16IsZero(q->TargetQID))
-                {
-                    q->LastQTime = m->timenow - q->ThisQInterval;
-                    cr->UnansweredQueries++;
-                    m->mDNSStats.CacheRefreshQueries++;
-                }
-                else if (q->SendQNow == mDNSNULL)
-                {
-                    q->SendQNow = cr->resrec.InterfaceID;
-                }
-                else if (q->SendQNow != cr->resrec.InterfaceID)
-                {
-                    q->SendQNow = mDNSInterfaceMark;
-                }
-
-                // Indicate that this question was marked for sending
-                // to update an existing cached answer record.
-                // The browse throttling logic below uses this to determine
-                // if the query should be sent.
-                if (mDNSOpaque16IsZero(q->TargetQID))
-                    q->CachedAnswerNeedsUpdate = mDNStrue;
-            }
-        }
-    }
-
-    // Scan our list of questions to see which:
-    //     *WideArea*  queries need to be sent
-    //     *unicast*   queries need to be sent
-    //     *multicast* queries we're definitely going to send
-    if (m->CurrentQuestion)
-        LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-    {
-        q = m->CurrentQuestion;
-        if (mDNSOpaque16IsZero(q->TargetQID) && TimeToSendThisQuestion(q, m->timenow))
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-            if (QuestionSendsMDNSQueriesViaUnicast(q))
-            {
-                InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
-                const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
-                const mDNSu16 qclass = q->qclass | kDNSQClass_UnicastResponse;
-                mDNSu8 *const end = putQuestion(&m->omsg, m->omsg.data, limit, &q->qname, q->qtype, qclass);
-                mDNSSendDNSMessage(m, &m->omsg, end, q->InterfaceID, mDNSNULL, mDNSNULL, &q->UnicastMDNSResolver,
-                    MulticastDNSPort, mDNSNULL, q->UseBackgroundTraffic);
-                q->ThisQInterval    *= QuestionIntervalStep;
-                if (q->ThisQInterval > MaxQuestionInterval)
-                {
-                    q->ThisQInterval = MaxQuestionInterval;
-                }
-                q->LastQTime         = m->timenow;
-                q->LastQTxTime       = m->timenow;
-                q->RecentAnswerPkts  = 0;
-                q->SendQNow          = mDNSNULL;
-                q->ExpectUnicastResp = NonZeroTime(m->timenow);
-            }
-            else
-#endif
-            {
-                //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - NextQSendTime(q));
-                q->SendQNow = mDNSInterfaceMark;        // Mark this question for sending on all interfaces
-                if (maxExistingQuestionInterval < q->ThisQInterval)
-                    maxExistingQuestionInterval = q->ThisQInterval;
-            }
-        }
-        // If m->CurrentQuestion wasn't modified out from under us, advance it now
-        // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
-        // m->CurrentQuestion point to the right question
-        if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
-    }
-    while (m->CurrentQuestion)
-    {
-        LogInfo("SendQueries question loop 1: Skipping NewQuestion %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-        m->CurrentQuestion = m->CurrentQuestion->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-
-    // 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
-    // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
-    // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
-    // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
-    m->NextScheduledQuery = m->timenow + FutureTime;
-    for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-        const mDNSBool qIsNormalMDNS = mDNSOpaque16IsZero(q->TargetQID) && !QuestionSendsMDNSQueriesViaUnicast(q);
-#else
-        const mDNSBool qIsNormalMDNS = mDNSOpaque16IsZero(q->TargetQID);
-#endif
-        if (qIsNormalMDNS
-            && (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, then
-            // treat this as logically a repeat of the last transmission, without advancing the interval
-            if (m->timenow - (q->LastQTime + (q->ThisQInterval/2)) >= 0)
-            {
-                // If we have reached the answer threshold for this question,
-                // don't send it again until MaxQuestionInterval unless:
-                //  one of its cached answers needs to be refreshed,
-                //  or it's the initial query for a kDNSServiceFlagsThresholdFinder mode browse.
-                if (q->BrowseThreshold
-                    && (q->CurrentAnswers >= q->BrowseThreshold)
-                    && (q->CachedAnswerNeedsUpdate == mDNSfalse)
-                    && !((q->flags & kDNSServiceFlagsThresholdFinder) && (q->ThisQInterval == InitialQuestionInterval)))
-                {
-                    q->SendQNow = mDNSNULL;
-                    q->ThisQInterval = MaxQuestionInterval;
-                    q->LastQTime = m->timenow;
-                    q->RequestUnicast = 0;
-                    LogInfo("SendQueries: (%s) %##s reached threshold of %d answers",
-                         DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold);
-                }
-                else
-                {
-                    // Mark this question for sending on all interfaces
-                    q->SendQNow = mDNSInterfaceMark;
-                    q->ThisQInterval *= QuestionIntervalStep;
-                }
-
-                debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
-                       q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
-
-                if (q->ThisQInterval > MaxQuestionInterval)
-                {
-                    q->ThisQInterval = MaxQuestionInterval;
-                }
-                else if (mDNSOpaque16IsZero(q->TargetQID) && q->InterfaceID &&
-                         q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
-                         !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
-                {
-                    // Generally don't need to log this.
-                    // It's not especially noteworthy if a query finds no results -- this usually happens for domain
-                    // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
-                    // and when there simply happen to be no instances of the service the client is looking
-                    // for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
-                    debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
-                           q->qname.c, DNSTypeName(q->qtype));
-                    // Sending third query, and no answers yet; time to begin doubting the source
-                    ReconfirmAntecedents(m, &q->qname, q->qnamehash, q->InterfaceID, 0);
-                }
-            }
-
-            // 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->RecentAnswerPkts = 0;
-            if (q->RequestUnicast) q->RequestUnicast--;
-        }
-        // For all questions (not just the ones we're sending) check what the next scheduled event will be
-        // We don't need to consider NewQuestions here because for those we'll set m->NextScheduledQuery in AnswerNewQuestion
-        SetNextQueryTime(m,q);
-    }
-
-    // 2. Scan our authoritative RR list to see what probes we might need to send
-
-    m->NextScheduledProbe = m->timenow + FutureTime;
-
-    if (m->CurrentRecord)
-        LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = m->ResourceRecords;
-    while (m->CurrentRecord)
-    {
-        ar = m->CurrentRecord;
-        m->CurrentRecord = ar->next;
-        if (!AuthRecord_uDNS(ar) && ar->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 - (ar->LastAPTime + ar->ThisAPInterval) < 0)
-            {
-                SetNextAnnounceProbeTime(m, ar);
-            }
-            // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
-            else if (ar->ProbeCount)
-            {
-                if (ar->AddressProxy.type == mDNSAddrType_IPv4)
-                {
-                    // There's a problem here. If a host is waking up, and we probe to see if it responds, then
-                    // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
-                    // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
-                    // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
-                    // A similar concern may apply to the NDP Probe too. -- SC
-                    LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
-                    SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
-                }
-                else if (ar->AddressProxy.type == mDNSAddrType_IPv6)
-                {
-                    LogSPS("SendQueries NDP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
-                    // IPv6 source = zero
-                    // No target hardware address
-                    // IPv6 target address is address we're probing
-                    // Ethernet destination address is Ethernet interface address of the Sleep Proxy client we're probing
-                    SendNDP(m, NDP_Sol, 0, ar, &zerov6Addr, mDNSNULL, &ar->AddressProxy.ip.v6, &ar->WakeUp.IMAC);
-                }
-                // Mark for sending. (If no active interfaces, then don't even try.)
-                ar->SendRNow   = (!intf || ar->WakeUp.HMAC.l[0]) ? mDNSNULL : ar->resrec.InterfaceID ? ar->resrec.InterfaceID : intf->InterfaceID;
-                ar->LastAPTime = m->timenow;
-                // When we have a late conflict that resets a record to probing state we use a special marker value greater
-                // than DefaultProbeCountForTypeUnique. Here we detect that state and reset ar->ProbeCount back to the right value.
-                if (ar->ProbeCount > DefaultProbeCountForTypeUnique)
-                    ar->ProbeCount = DefaultProbeCountForTypeUnique;
-                ar->ProbeCount--;
-                SetNextAnnounceProbeTime(m, ar);
-                if (ar->ProbeCount == 0)
-                {
-                    // If this is the last probe for this record, then see if we have any matching records
-                    // on our duplicate list which should similarly have their ProbeCount cleared to zero...
-                    AuthRecord *r2;
-                    for (r2 = m->DuplicateRecords; r2; r2=r2->next)
-                        if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, ar))
-                            r2->ProbeCount = 0;
-                    // ... then acknowledge this record to the client.
-                    // We do this optimistically, just as we're about to send the third probe.
-                    // This helps clients that both advertise and browse, and want to filter themselves
-                    // from the browse results list, because it helps ensure that the registration
-                    // confirmation will be delivered 1/4 second *before* the browse "add" event.
-                    // A potential downside is that we could deliver a registration confirmation and then find out
-                    // moments later that there's a name conflict, but applications have to be prepared to handle
-                    // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
-                    if (!ar->Acknowledged) AcknowledgeRecord(m, ar);
-                }
-            }
-            // else, if it has now finished probing, move it to state Verified,
-            // and update m->NextScheduledResponse so it will be announced
-            else
-            {
-                if (!ar->Acknowledged) AcknowledgeRecord(m, ar);    // Defensive, just in case it got missed somehow
-                ar->resrec.RecordType     = kDNSRecordTypeVerified;
-                ar->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
-                ar->LastAPTime     = m->timenow - DefaultAnnounceIntervalForTypeUnique;
-                SetNextAnnounceProbeTime(m, ar);
-            }
-        }
-    }
-    m->CurrentRecord = m->DuplicateRecords;
-    while (m->CurrentRecord)
-    {
-        ar = m->CurrentRecord;
-        m->CurrentRecord = ar->next;
-        if (ar->resrec.RecordType == kDNSRecordTypeUnique && ar->ProbeCount == 0 && !ar->Acknowledged)
-            AcknowledgeRecord(m, ar);
-    }
-
-    // 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)
-    {
-        int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
-        int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0;
-        mDNSu8 *queryptr = m->omsg.data;
-        mDNSBool useBackgroundTrafficClass = mDNSfalse;    // set if we should use background traffic class
-
-        InitializeDNSMessage(&m->omsg.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 = OwnerRecordSpace + TraceRecordSpace;  // Start by assuming we'll need at least enough space to put the Owner+Tracer Option
-
-            // Put query questions in this packet
-            for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
-            {
-                if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID))
-                {
-                    mDNSBool Suppress = mDNSfalse;
-                    debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
-                           SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
-                           q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data);
-
-                    // If interface is P2P type, verify that query should be sent over it.
-                    if (!mDNSPlatformValidQuestionForInterface(q, intf))
-                    {
-                        q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-                    }
-                    // If we're suppressing this question, or we successfully put it, update its SendQNow state
-                    else if ((Suppress = SuppressOnThisInterface(q->DupSuppress, intf)) ||
-                        BuildQuestion(m, intf, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
-                    {
-                        if (Suppress)
-                            m->mDNSStats.DupQuerySuppressions++;
-
-                        q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-                        if (q->WakeOnResolveCount)
-                        {
-                            mDNSSendWakeOnResolve(m, q);
-                            q->WakeOnResolveCount--;
-                        }
-
-                        // use background traffic class if any included question requires it
-                        if (q->UseBackgroundTraffic)
-                        {
-                            useBackgroundTrafficClass = mDNStrue;
-                        }
-                    }
-                }
-            }
-
-            // Put probe questions in this packet
-            for (ar = m->ResourceRecords; ar; ar=ar->next)
-            {
-                if (ar->SendRNow != intf->InterfaceID)
-                    continue;
-
-                // If interface is a P2P variant, verify that the probe should be sent over it.
-                if (!mDNSPlatformValidRecordForInterface(ar, intf->InterfaceID))
-                {
-                    ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-                    ar->IncludeInProbe = mDNSfalse;
-                }
-                else
-                {
-                    mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse;
-                    mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
-                    const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
-                    // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
-                    mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate;
-                    AuthRecord *tsr = mDNSGetTSRRecord(m, ar);
-                    mDNSBool putProbe = mDNStrue;
-                    mDNSu16 qclass = ar->resrec.rrclass | ucbit;
-                    if (tsr && !tsr->IncludeInProbe)
-                    {
-                        AuthRecord *tmp = mDNSNULL;
-                        // tsr record: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (4)
-                        forecast += 16;
-                        // If tsr record is added to probe, also add other records with the same name
-                        for (tmp = m->ResourceRecords; tmp; tmp = tmp->next)
-                        {
-                            if (tmp->resrec.rrtype != kDNSType_TSR && SameResourceRecordNameClassInterface(ar, tmp))
-                            {
-                                // compressed name (2) type (2) class (2) TTL (4) rdlength (2) estimated rdata length
-                                forecast = forecast + 12 + tmp->resrec.rdestimate;
-                            }
-                        }
-                    }
-
-                    {// Determine if this probe question is already in packet's dns message
-                        const mDNSu8 *questionptr = m->omsg.data;
-                        DNSQuestion question;
-                        mDNSu16 n;
-                        for (n = 0; n < m->omsg.h.numQuestions && questionptr; n++)
-                        {
-                            questionptr = getQuestion(&m->omsg, questionptr, limit, mDNSInterface_Any, &question);
-                            if (questionptr && (question.qtype == kDNSQType_ANY) && (question.qclass == qclass) &&
-                                (question.qnamehash == ar->resrec.namehash) && SameDomainName(&question.qname, ar->resrec.name))
-                            {
-                                putProbe = mDNSfalse;  // set to false if already in message
-                                break;
-                            }
-                        }
-                    }
-
-                    if (putProbe)
-                    {
-                        mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, qclass);
-                        if (newptr)
-                        {
-                            queryptr       = newptr;
-                            answerforecast = forecast;
-                            ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-                            ar->IncludeInProbe = mDNStrue;
-                            if (tsr && tsr->IncludeInProbe == mDNSfalse)
-                            {
-                                AuthRecord *tmp = mDNSNULL;
-                                tsr->IncludeInProbe = mDNStrue;
-                                for (tmp = m->ResourceRecords; tmp; tmp = tmp->next)
-                                {
-                                    if (tmp->resrec.rrtype != kDNSType_TSR && SameResourceRecordNameClassInterface(ar, tmp))
-                                    {
-                                        tmp->IncludeInProbe = mDNStrue;
-                                    }
-                                }
-                            }
-                            verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d InterfaceID= %d %d %d",
-                                      ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount, ar->resrec.InterfaceID, ar->resrec.rdestimate, answerforecast);
-                        }
-                    }
-                    else
-                    {
-                        ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-                        ar->IncludeInProbe = mDNStrue;
-                    }
-                }
-            }
-        }
-
-        // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
-        while (KnownAnswerList)
-        {
-            CacheRecord *ka = KnownAnswerList;
-            mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
-            mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd,
-                                                           m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace - TraceRecordSpace);
-            if (newptr)
-            {
-                verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
-                              ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
-                queryptr = newptr;
-                KnownAnswerList = ka->NextInKAList;
-                ka->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 (m->omsg.h.numQuestions > 1)
-                    LogMsg("SendQueries:   Put %d answers; No more space for known answers", m->omsg.h.numAnswers);
-                m->omsg.h.flags.b[0] |= kDNSFlag0_TC;
-                break;
-            }
-        }
-
-        for (ar = m->ResourceRecords; ar; ar=ar->next)
-        {
-            if (ar->IncludeInProbe)
-            {
-                mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &ar->resrec);
-                ar->IncludeInProbe = mDNSfalse;
-                if (newptr) queryptr = newptr;
-                else LogMsg("SendQueries:   How did we fail to have space for the Update record %s", ARDisplayString(m,ar));
-            }
-        }
-
-        if (queryptr > m->omsg.data)
-        {
-            // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet
-            if (OwnerRecordSpace || TraceRecordSpace)
-            {
-                AuthRecord opt;
-                mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-                opt.resrec.rrclass    = NormalMaxDNSMessageData;
-                opt.resrec.rdlength   = sizeof(rdataOPT);
-                opt.resrec.rdestimate = sizeof(rdataOPT);
-                if (OwnerRecordSpace && TraceRecordSpace)
-                {
-                    opt.resrec.rdlength   += sizeof(rdataOPT);  // Two options in this OPT record
-                    opt.resrec.rdestimate += sizeof(rdataOPT);
-                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
-                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]);
-                }
-                else if (OwnerRecordSpace)
-                {
-                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
-                }
-                else if (TraceRecordSpace)
-                {
-                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
-                }
-                queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
-                                                         &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
-                if (!queryptr)
-                {
-                    LogMsg("SendQueries: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
-                           m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
-                }
-                if (queryptr > m->omsg.data + NormalMaxDNSMessageData)
-                {
-                    if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1)
-                        LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "",
-                                TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers,
-                                m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
-                }
-            }
-
-            if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1)
-                LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions);
-            debugf("SendQueries:   Sending %d Question%s %d Answer%s %d Update%s on %d (%s)",
-                   m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
-                   m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
-                   m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", IIDPrintable(intf->InterfaceID), intf->ifname);
-            if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, useBackgroundTrafficClass);
-            if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, useBackgroundTrafficClass);
-            if (!m->SuppressQueries) m->SuppressQueries = NonZeroTime(m->timenow + ((mDNSPlatformOneSecond + 9) / 10));
-            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);
-            intf = next;
-        }
-    }
-
-    // 4. Final housekeeping
-
-    // 4a. Debugging check: Make sure we announced all our records
-    for (ar = m->ResourceRecords; ar; ar=ar->next)
-        if (ar->SendRNow)
-        {
-            if (ar->ARType != AuthRecordLocalOnly && ar->ARType != AuthRecordP2P)
-                LogInfo("SendQueries: No active interface %d to send probe: %d %s",
-                        IIDPrintable(ar->SendRNow), IIDPrintable(ar->resrec.InterfaceID), ARDisplayString(m, ar));
-            ar->SendRNow = mDNSNULL;
-        }
-
-    // 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope
-    // that their interface which went away might come back again, the logic will want to send queries
-    // for those records, but we can't because their interface isn't here any more, so to keep the
-    // state machine ticking over we just pretend we did so.
-    // If the interface does not come back in time, the cache record will expire naturally
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
-        {
-            if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
-            {
-                cr->UnansweredQueries++;
-                cr->CRActiveQuestion->SendQNow = mDNSNULL;
-                SetNextCacheCheckTimeForRecord(m, cr);
-            }
-        }
-    }
-
-    // 4c. Debugging check: Make sure we sent all our planned questions
-    // Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions
-    // we legitimately couldn't send because the interface is no longer available
-    for (q = m->Questions; q; q=q->next)
-    {
-        if (q->SendQNow)
-        {
-            DNSQuestion *x;
-            for (x = m->NewQuestions; x; x=x->next) if (x == q) break;  // Check if this question is a NewQuestion
-            // There will not be an active interface for questions applied to mDNSInterface_BLE
-            // so don't log the warning in that case.
-            if (q->InterfaceID != mDNSInterface_BLE)
-                LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
-                        IIDPrintable(q->SendQNow), x ? "new" : "old", IIDPrintable(q->InterfaceID), q->qname.c, DNSTypeName(q->qtype));
-            q->SendQNow = mDNSNULL;
-        }
-        q->CachedAnswerNeedsUpdate = mDNSfalse;
-    }
-}
-
-// Get TSR record that has the same name as rr;
-// Return the TSR record if found, otherwise return NULL.
-mDNSexport AuthRecord *mDNSGetTSRRecord(mDNS *const m, const AuthRecord *const rr)
-{
-    AuthRecord *ar = mDNSNULL;
-    for (ar = m->ResourceRecords; ar; ar = ar->next)
-    {
-        if (ar->resrec.rrtype == kDNSType_TSR && SameResourceRecordNameClassInterface(ar, rr))
-        {
-            return ar;
-        }
-    }
-    return ar;
-}
-
-mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly)
-{
-    int i, j;
-
-    mDNSu8 *ptr = m->omsg.data;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
-    if (!intf)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SendARP: No interface with InterfaceID %p found", InterfaceID);
-        return;
-    }
-
-    // 0x00 Destination address
-    for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
-
-    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
-    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
-
-    // 0x0C Ethertype (0x0842)
-    *ptr++ = 0x08;
-    *ptr++ = 0x42;
-
-    // 0x0E Wakeup sync sequence
-    for (i=0; i<6; i++) *ptr++ = 0xFF;
-
-    // 0x14 Wakeup data
-    for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
-
-    // 0x74 Password
-    for (i=0; i<6; i++) *ptr++ = password->b[i];
-
-    mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
-
-    if (!unicastOnly)
-    {
-        // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
-        // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
-        // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
-        // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
-        // So, we send one of each, unicast first, then broadcast second.
-        for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
-        mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
-    }
-}
-
-// ***************************************************************************
-// MARK: - RR List Management & Task Management
-
-// Whenever a question is answered, reset its state so that we don't query
-// the network repeatedly. This happens first time when we answer the question and
-// and later when we refresh the cache.
-mDNSlocal void ResetQuestionState(mDNS *const m, DNSQuestion *q)
-{
-    q->LastQTime          = m->timenow;
-    q->LastQTxTime        = m->timenow;
-    q->RecentAnswerPkts   = 0;
-    q->ThisQInterval      = MaxQuestionInterval;
-    q->RequestUnicast     = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    q->NeedUpdatedQuerier = mDNSfalse;
-#else
-    // Reset unansweredQueries so that we don't penalize this server later when we
-    // start sending queries when the cache expires.
-    q->unansweredQueries  = 0;
-#endif
-    debugf("ResetQuestionState: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-}
-
-mDNSlocal void AdjustUnansweredQueries(mDNS *const m, CacheRecord *const rr)
-{
-    const mDNSs32 expireTime = RRExpireTime(rr);
-    const mDNSu32 interval = TicksTTL(rr) / 20; // Calculate 5% of the cache record's TTL.
-    mDNSu32 rem;
-
-    // If the record is expired or UnansweredQueries is already at the max, then return early.
-    if (((m->timenow - expireTime) >= 0) || (rr->UnansweredQueries >= MaxUnansweredQueries)) return;
-
-    if (interval == 0)
-    {
-        LogInfo("AdjustUnansweredQueries: WARNING: unusually small TTL (%d ticks) for %s", TicksTTL(rr), CRDisplayString(m, rr));
-        return;
-    }
-
-    // Calculate the number of whole 5% TTL intervals between now and expiration time.
-    rem = ((mDNSu32)(expireTime - m->timenow)) / interval;
-
-    // Calculate the expected number of remaining refresher queries.
-    // Refresher queries are sent at the start of the last MaxUnansweredQueries intervals.
-    if (rem > MaxUnansweredQueries) rem = MaxUnansweredQueries;
-
-    // If the current number of remaining refresher queries is greater than expected, then at least one refresher query time
-    // was missed. This can happen if the cache record didn't have an active question during any of the times at which
-    // refresher queries would have been sent if the cache record did have an active question. The cache record's
-    // UnansweredQueries count needs to be adjusted to avoid a burst of refresher queries being sent in an attempt to make up
-    // for lost time. UnansweredQueries is set to the number of queries that would have been sent had the cache record had an
-    // active question from the 80% point of its lifetime up to now, with one exception: if the number of expected remaining
-    // refresher queries is zero (because timenow is beyond the 95% point), then UnansweredQueries is set to
-    // MaxUnansweredQueries - 1 so that at least one refresher query is sent before the cache record expires.
-	// Note: The cast is safe because rem is never greater than MaxUnansweredQueries; the comparison has to be signed.
-    if ((MaxUnansweredQueries - rr->UnansweredQueries) > (mDNSs32)rem)
-    {
-        if (rem == 0) rem++;
-        rr->UnansweredQueries = (mDNSu8)(MaxUnansweredQueries - rem);
-    }
-}
-
-// Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
-// Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this.
-// In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
-// which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
-mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord)
-{
-    DNSQuestion *const q = m->CurrentQuestion;
-    const mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord);
-
-    verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s (%s) TTL %d %s",
-                  q->CurrentAnswers, AddRecord ? "Add" : "Rmv", MortalityDisplayString(rr->resrec.mortality),
-                  rr->resrec.rroriginalttl, CRDisplayString(m, rr));
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    // When a cache record is used to answer a question, check if we need to remember its private log level.
-    if (q->logPrivacyLevel == dnssd_log_privacy_level_private) // If the question enables private log redaction.
-    {
-        // default means that we have not remember any private log level, by default, this record will be printed in
-        // the state dump output.
-        if (rr->PrivacyLevel == CRLogPrivacyLevel_Default)
-        {
-            // Since this cache record is used to answer a question that enables private log redaction, it will be
-            // marked as private, and will be redacted in the state dump.
-            rr->PrivacyLevel = CRLogPrivacyLevel_Private;
-        }
-    }
-    else // q->logPrivacyLevel == dnssd_log_privacy_level_default // If the question does not enable private log redaction.
-    {
-        // If this cache record is used to answer a non-private question, it will be printed in the state dump.
-        rr->PrivacyLevel = CRLogPrivacyLevel_Public;
-    }
-#endif
-
-    // Normally we don't send out the unicast query if we have answered using our local only auth records e.g., /etc/hosts.
-    // But if the query for "A" record has a local answer but query for "AAAA" record has no local answer, we might
-    // send the AAAA query out which will come back with CNAME and will also answer the "A" query. To prevent that,
-    // we check to see if that query already has a unique local answer.
-    if (q->LOAddressAnswers)
-    {
-        LogInfo("AnswerCurrentQuestionWithResourceRecord: Question %p %##s (%s) not answering with record %s due to "
-                "LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr),
-                q->LOAddressAnswers);
-        return;
-    }
-
-    if (q->Suppressed && (AddRecord != QC_suppressed))
-    {
-        // If the query is suppressed, then we don't want to answer from the cache. But if this query is
-        // supposed to time out, we still want to callback the clients. We do this only for TimeoutQuestions
-        // that are timing out, which we know are answered with negative cache record when timing out.
-        if (!q->TimeoutQuestion || rr->resrec.RecordType != kDNSRecordTypePacketNegative || (m->timenow - q->StopTime < 0))
-            return;
-    }
-
-    //  Set the record to immortal if appropriate
-    if (AddRecord == QC_add && Question_uDNS(q) && rr->resrec.RecordType != kDNSRecordTypePacketNegative &&
-        q->allowExpired != AllowExpired_None && rr->resrec.mortality == Mortality_Mortal
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // For now, do not use optimistic DNS for DNSSEC response and DNSSEC question.
-        && !dns_question_is_dnssec_requestor(q) && !resource_record_is_dnssec_aware(&rr->resrec)
-    #endif
-        )
-    {
-        rr->resrec.mortality = Mortality_Immortal; // Update a non-expired cache record to immortal if appropriate
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname && !q->metrics.answered)
-    {
-        mDNSBool skipUpdate = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        mdns_resolver_type_t resolver_type = (!q->dnsservice) ? mdns_resolver_type_null : mdns_dns_service_get_resolver_type(q->dnsservice);
-        if (resolver_type == mdns_resolver_type_null)
-        {
-            skipUpdate = mDNStrue;
-        }
-#endif
-        if (!skipUpdate)
-        {
-            uint32_t         responseLatencyMs, querySendCount;
-            bool            isForCellular;
-            dns_transport_t transport;
-
-            querySendCount = q->metrics.querySendCount;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (q->querier)
-            {
-                querySendCount += mdns_querier_get_send_count(q->querier);
-            }
-            isForCellular = mdns_dns_service_interface_is_cellular(q->dnsservice);
-            transport = dnssd_analytics_dns_transport_for_resolver_type(resolver_type);
-#else
-            isForCellular = (q->qDNSServer && q->qDNSServer->isCell);
-            transport = dns_transport_Do53;
-#endif
-            if (querySendCount > 0 && q->metrics.firstQueryTime != 0)
-            {
-                responseLatencyMs = ((m->timenow - q->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
-                dnssd_analytics_update_dns_query_info(isForCellular, transport, q->qtype, querySendCount,
-                    responseLatencyMs, rr->resrec.RecordType != kDNSRecordTypePacketNegative);
-            }
-        }
-        q->metrics.answered = mDNStrue;
-    }
-#endif
-    // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
-    // may be called twice, once when the record is received, and again when it's time to notify local clients.
-    // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this.
-
-    if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q && rr->resrec.mortality != Mortality_Ghost)
-    {
-        debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion from %p to %p for cache record %s, CurrentAnswer %d",
-               rr->CRActiveQuestion, q, CRDisplayString(m,rr), q->CurrentAnswers);
-        if (!rr->CRActiveQuestion)
-        {
-            m->rrcache_active++;            // If not previously active, increment rrcache_active count
-            AdjustUnansweredQueries(m, rr); // Adjust UnansweredQueries in case the record missed out on refresher queries
-        }
-        rr->CRActiveQuestion = q;           // We know q is non-null
-        SetNextCacheCheckTimeForRecord(m, rr);
-    }
-
-    // If this is:
-    // (a) a no-cache add, where we've already done at least one 'QM' query, or
-    // (b) a normal add, where we have at least one unique-type answer,
-    // then there's no need to keep polling the network.
-    // (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.)
-    // We do this for mDNS questions and uDNS one-shot questions, but not for
-    // uDNS LongLived questions, because that would mess up our LLQ lease renewal timing.
-    if ((AddRecord == QC_addnocache && !q->RequestUnicast) ||
-        (AddRecord == QC_add && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))))
-        if (ActiveQuestion(q) && (mDNSOpaque16IsZero(q->TargetQID) || !q->LongLived))
-        {
-            ResetQuestionState(m, q);
-        }
-
-    if (rr->DelayDelivery) return;      // We'll come back later when CacheRecordDeferredAdd() calls us
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return.
-    if (!mDNSOpaque16IsZero(q->TargetQID) && DNS64StateMachine(m, q, &rr->resrec, AddRecord)) return;
-#endif
-
-#ifdef USE_LIBIDN
-    if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)  // If negative answer, check if we need to try Punycode conversion
-    {
-        domainname newname;
-        if (PerformNextPunycodeConversion(q, &newname))         // Itertative Punycode conversion succeeded, so reissue question with new name
-        {
-            UDPSocket *const sock = q->LocalSocket;             // Save old socket and transaction ID
-            const mDNSOpaque16 id = q->TargetQID;
-            q->LocalSocket = mDNSNULL;
-            mDNS_StopQuery_internal(m, q);                      // Stop old query
-            AssignDomainName(&q->qname, &newname);              // Update qname
-            q->qnamehash = DomainNameHashValue(&q->qname);      // and namehash
-            mDNS_StartQuery_internal(m, q);                     // Start new query
-
-            if (sock)                                           // Transplant saved socket, if appropriate
-            {
-                if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
-                else { q->LocalSocket = sock; q->TargetQID = id; }
-            }
-            return;                                             // All done for now; wait until we get the next answer
-        }
-    }
-#endif // USE_LIBIDN
-
-    // Only deliver negative answers if client has explicitly requested them except when we are forcing a negative response
-    // for the purpose of retrying search domains/timeout OR the question is suppressed
-    const mDNSBool answersQuestionNegativelyDirectly = (rr->resrec.RecordType == kDNSRecordTypePacketNegative);
-    const mDNSBool answersMDNSQuestionNegativelyIndirectly = (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype));
-    if (answersQuestionNegativelyDirectly || answersMDNSQuestionNegativelyIndirectly)
-    {
-        switch (AddRecord)
-        {
-            case QC_rmv:
-                // Do not deliver remove event for a negative record, because when it is deleted there must be a
-                // positive record that answers the question coming. The add event of the positive record will
-                // implicitly indicate the remove of the previously added negative record.
-            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                // However, if the question is the primary DNSSEC requestor that will validate the records with DNSSEC,
-                // always deliver the negative record because it contains the denial of existence records that could
-                // have changed.
-                if (dns_question_is_primary_dnssec_requestor(q))
-                {
-                    // answersMDNSQuestionNegativelyIndirectly should be false here.
-                    break;
-                }
-            #endif
-                return;
-            case QC_add:
-            case QC_addnocache:
-                if (!q->ReturnIntermed)
-                {
-                    // If the question does not want the intermediate result (for example, NXDomain or NoSuchRecord)
-                    // rather than the requested record, do not deliver the negative record.
-                    return;
-                }
-                break;
-            case QC_forceresponse:
-            case QC_suppressed:
-                // A negative response is forced to be delivered to the callback;
-                // Fall through.
-    #ifdef __clang__
-        #pragma clang diagnostic push
-        #pragma clang diagnostic ignored "-Wcovered-switch-default"
-    #endif
-            default:
-    #ifdef __clang__
-        #pragma clang diagnostic pop
-    #endif
-                break;
-        }
-    }
-
-    // For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that
-    if (q->QuestionCallback && (!followcname || q->ReturnIntermed))
-    {
-        mDNS_DropLockBeforeCallback();      // Allow client (and us) to legally make mDNS API calls
-        if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))
-        {
-            if (mDNSOpaque16IsZero(q->TargetQID))
-            {
-                CacheRecord neg;
-            #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                mDNSPlatformMemZero(&neg, sizeof(neg));
-            #endif
-                MakeNegativeCacheRecordForQuestion(m, &neg, q, 1, rr->resrec.InterfaceID, zeroID);
-                q->QuestionCallback(m, q, &neg.resrec, AddRecord);
-            }
-        }
-        else
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-            if (DNS64ShouldAnswerQuestion(q, &rr->resrec))
-            {
-                DNS64AnswerCurrentQuestion(m, &rr->resrec, AddRecord);
-            }
-            else
-#endif
-            {
-                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
-            }
-        }
-        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-    }
-    // Note: Proceed with caution after this point because client callback function
-    // invoked above is allowed to do anything, such as starting/stopping queries
-    // (including this one itself, or the next or previous query in the linked list),
-    // registering/deregistering records, starting/stopping NAT traversals, etc.
-
-    if (m->CurrentQuestion == q)
-    {
-        // If we get a CNAME back while we are validating the response (i.e., CNAME for DS, DNSKEY, RRSIG),
-        // don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated
-        // first before following it
-        if (followcname)  AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
-
-        // If we are returning expired RRs, then remember the first expired qname we we can start the query again
-        if (rr->resrec.mortality == Mortality_Ghost && !q->firstExpiredQname.c[0] && (q->allowExpired == AllowExpired_AllowExpiredAnswers) && rr->resrec.RecordType != kDNSRecordTypePacketNegative)
-        {
-            debugf("AnswerCurrentQuestionWithResourceRecord: Keeping track of domain for expired RR %s for question %p", CRDisplayString(m,rr), q);
-            // Note: question->qname is already changed at this point if following a CNAME
-            AssignDomainName(&q->firstExpiredQname, rr->resrec.name);           // Update firstExpiredQname
-        }
-    }
-}
-
-mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *cr)
-{
-    cr->DelayDelivery = 0;
-    if (m->CurrentQuestion)
-        LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-    {
-        DNSQuestion *q = m->CurrentQuestion;
-        if (CacheRecordAnswersQuestion(cr, q))
-            AnswerCurrentQuestionWithResourceRecord(m, cr, QC_add);
-        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-// Special values to pass to CheckForSoonToExpireRecordsEx() when the caller doesn't care about matching a cache
-// record's type or class.
-#define kCheckForSoonToExpireAnyType  -1
-#define kCheckForSoonToExpireAnyClass -1
-
-mDNSlocal mDNSs32 CheckForSoonToExpireRecordsEx(mDNS *const m, const domainname *const name, const mDNSu32 namehash,
-    const int rrtype, const int rrclass)
-{
-    const mDNSs32 threshold = m->timenow + mDNSPlatformOneSecond;  // See if there are any records expiring within one second
-    const mDNSs32 start     = m->timenow - 0x10000000;
-    mDNSs32 delay = start;
-    const CacheGroup *const cg = CacheGroupForName(m, namehash, name);
-    for (const CacheRecord *cr = cg ? cg->members : mDNSNULL; cr; cr = cr->next)
-    {
-        const ResourceRecord *const rr = &cr->resrec;
-        const mDNSBool typeMatch = (rrtype < 0) || (rrtype == kDNSQType_ANY) || (rr->rrtype == rrtype);
-        const mDNSBool classMatch = (rrclass < 0) || (rr->rrclass == rrclass);
-        if (typeMatch && classMatch)
-        {
-            // If we have a record that is about to expire within a second, then delay until after it's been deleted.
-            const mDNSs32 expireTime = RRExpireTime(cr);
-            if (((threshold - expireTime) >= 0) && ((expireTime - delay) > 0))
-            {
-                delay = expireTime;
-            }
-        }
-    }
-    if (delay - start > 0)
-        return(NonZeroTime(delay));
-    else
-        return(0);
-}
-
-mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
-{
-    return CheckForSoonToExpireRecordsEx(m, name, namehash, kCheckForSoonToExpireAnyType, kCheckForSoonToExpireAnyClass);
-}
-
-// CacheRecordAdd is only called from CreateNewCacheEntry, *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 AnswerCurrentQuestionWithResourceRecord 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 *cr)
-{
-    DNSQuestion *q;
-
-    // We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers
-    // counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion().
-    for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
-    {
-        if (CacheRecordAnswersQuestion(cr, 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 (q->LastAnswerPktNum != m->PktNum)
-            {
-                q->LastAnswerPktNum = m->PktNum;
-                if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 &&
-                    q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
-                {
-                    LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)",
-                           q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval);
-                    q->LastQTime      = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
-                    q->ThisQInterval  = InitialQuestionInterval;
-                    SetNextQueryTime(m,q);
-                }
-            }
-            verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", cr, cr->resrec.name->c,
-                          DNSTypeName(cr->resrec.rrtype), cr->resrec.rroriginalttl, cr->resrec.rDNSServer ?
-                          &cr->resrec.rDNSServer->addr : mDNSNULL, mDNSVal16(cr->resrec.rDNSServer ?
-                                                                             cr->resrec.rDNSServer->port : zeroIPPort), q);
-            q->CurrentAnswers++;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            q->unansweredQueries = 0;
-#endif
-            if (cr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
-            if (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
-            if (q->CurrentAnswers > 4000)
-            {
-                static int msgcount = 0;
-                if (msgcount++ < 10)
-                    LogMsg("CacheRecordAdd: %##s (%s) has %d answers; shedding records to resist DOS attack",
-                           q->qname.c, DNSTypeName(q->qtype), q->CurrentAnswers);
-                cr->resrec.rroriginalttl = 0;
-                cr->UnansweredQueries = MaxUnansweredQueries;
-            }
-        }
-    }
-
-    if (!cr->DelayDelivery)
-    {
-        if (m->CurrentQuestion)
-            LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-        m->CurrentQuestion = m->Questions;
-        while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-        {
-            q = m->CurrentQuestion;
-            if (CacheRecordAnswersQuestion(cr, q))
-                AnswerCurrentQuestionWithResourceRecord(m, cr, QC_add);
-            if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-                m->CurrentQuestion = q->next;
-        }
-        m->CurrentQuestion = mDNSNULL;
-    }
-
-    SetNextCacheCheckTimeForRecord(m, cr);
-}
-
-// NoCacheAnswer 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 from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique)
-// but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
-// way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
-// so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
-// Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord 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 NoCacheAnswer(mDNS *const m, CacheRecord *cr)
-{
-    LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c);
-    if (m->CurrentQuestion)
-        LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-    // We do this for *all* questions, not stopping when we get to m->NewQuestions,
-    // since we're not caching the record and we'll get no opportunity to do this later
-    while (m->CurrentQuestion)
-    {
-        DNSQuestion *q = m->CurrentQuestion;
-        if (CacheRecordAnswersQuestion(cr, q))
-            AnswerCurrentQuestionWithResourceRecord(m, cr, QC_addnocache);  // QC_addnocache means "don't expect remove events for this"
-        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute.
-// Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question.
-// 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.
-// cr is an existing cache CacheRecord that just expired and is being deleted
-// (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
-// Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord 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 *cr)
-{
-    if (m->CurrentQuestion)
-        LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-
-    // We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters
-    // will all still be zero because we haven't yet gone through the cache counting how many answers we have for them.
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-    {
-        DNSQuestion *q = m->CurrentQuestion;
-        // When a question enters suppressed state, we generate RMV events and generate a negative
-        // response. A cache may be present that answers this question e.g., cache entry generated
-        // before the question became suppressed. We need to skip the suppressed questions here as
-        // the RMV event has already been generated.
-        if (!q->Suppressed && CacheRecordAnswersQuestion(cr, q))
-        {
-            verbosedebugf("CacheRecordRmv %p %s", cr, CRDisplayString(m, cr));
-            q->FlappingInterface1 = mDNSNULL;
-            q->FlappingInterface2 = mDNSNULL;
-
-            if (q->CurrentAnswers == 0)
-            {
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                LogMsg("CacheRecordRmv ERROR!!: How can CurrentAnswers already be zero for %p %##s (%s) DNSServer %#a:%d",
-                       q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL,
-                       mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort));
-#endif
-            }
-            else
-            {
-                q->CurrentAnswers--;
-                if (cr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
-                if (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
-            }
-
-            // If we have dropped below the answer threshold for this mDNS question,
-            // restart the queries at InitialQuestionInterval.
-            if (mDNSOpaque16IsZero(q->TargetQID) && (q->BrowseThreshold > 0) && (q->CurrentAnswers < q->BrowseThreshold))
-            {
-                q->ThisQInterval = InitialQuestionInterval;
-                q->LastQTime     = m->timenow - q->ThisQInterval;
-                SetNextQueryTime(m,q);
-                LogInfo("CacheRecordRmv: (%s) %##s dropped below threshold of %d answers",
-                    DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold);
-            }
-
-            // Never generate "remove" events for negative results of the DNSSEC-unaware record.
-            mDNSBool generateRemoveEvents = (cr->resrec.rdata->MaxRDLength > 0);
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            // However, generate "remove" events for negative results of the record that is used for DNSSEC validation:
-            if (!generateRemoveEvents)
-            {
-                // 1. The to-be-validated negative record can contain denial of existence records that are being
-                // tracked by the DNSSEC callback.
-                if (resource_record_is_to_be_dnssec_validated(&cr->resrec))
-                {
-                    generateRemoveEvents = mDNStrue;
-                }
-                // 2. The DNSSEC secure negative record is currently being tracked by the DNSSEC callback.
-                else if (resource_record_is_dnssec_validated(&cr->resrec))
-                {
-                    generateRemoveEvents = (resource_record_get_validation_result(&cr->resrec) == dnssec_secure);
-                }
-
-                if (generateRemoveEvents)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_INFO, "[Q%u] Delivering RMV event for the negative record - "
-                        "rr type: " PUB_DNS_TYPE ", validated: " PUB_BOOL, mDNSVal16(q->TargetQID),
-                        DNS_TYPE_PARAM(cr->resrec.rrtype), BOOL_PARAM(resource_record_is_dnssec_validated(&cr->resrec)));
-                }
-            }
-        #endif
-
-            if (generateRemoveEvents)
-            {
-                if ((q->CurrentAnswers == 0) && mDNSOpaque16IsZero(q->TargetQID))
-                {
-                    LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
-                            q->qname.c, DNSTypeName(q->qtype));
-                    ReconfirmAntecedents(m, &q->qname, q->qnamehash, cr->resrec.InterfaceID, 0);
-                }
-                AnswerCurrentQuestionWithResourceRecord(m, cr, QC_rmv);
-            }
-        }
-        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e)
-{
-#if MDNS_MALLOC_DEBUGGING >= 1
-    unsigned int i;
-    for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
-#endif
-    e->next = m->rrcache_free;
-    m->rrcache_free = e;
-    m->rrcache_totalused--;
-}
-
-mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
-{
-    CacheEntity *e = (CacheEntity *)(*cp);
-    //LogMsg("ReleaseCacheGroup:  Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c);
-    if ((*cp)->rrcache_tail != &(*cp)->members)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
-    }
-    //if ((*cp)->name != (domainname*)((*cp)->namestorage))
-    //  LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
-    if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
-    (*cp)->name = mDNSNULL;
-    *cp = (*cp)->next;          // Cut record from list
-    ReleaseCacheEntity(m, e);
-}
-
-mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp)
-{
-    while (*rp)
-    {
-        CacheRecord *rr = *rp;
-        *rp = (*rp)->next;          // Cut record from list
-        if (rr->resrec.rdata && rr->resrec.rdata != (RData*)&rr->smallrdatastorage)
-        {
-            mDNSPlatformMemFree(rr->resrec.rdata);
-            rr->resrec.rdata = mDNSNULL;
-        }
-        // NSEC or SOA records that are not added to the CacheGroup do not share the name
-        // of the CacheGroup.
-        if (rr->resrec.name)
-        {
-            debugf("ReleaseAdditionalCacheRecords: freeing cached record %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
-            mDNSPlatformMemFree((void *)rr->resrec.name);
-            rr->resrec.name = mDNSNULL;
-        }
-        // Don't count the NSEC3 records used by anonymous browse/reg
-        if (!rr->resrec.InterfaceID)
-        {
-            m->rrcache_totalused_unicast -= rr->resrec.rdlength;
-        }
-        ReleaseCacheEntity(m, (CacheEntity *)rr);
-    }
-}
-
-mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
-{
-    CacheGroup *cg;
-
-    //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
-    if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
-    r->resrec.rdata = mDNSNULL;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_forget(&r->resrec.dnsservice);
-#endif
-
-    cg = CacheGroupForRecord(m, &r->resrec);
-
-    if (!cg)
-    {
-        // It is okay to have this printed for NSEC/NSEC3s
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "ReleaseCacheRecord: ERROR!! cg NULL for " PRI_DM_NAME " (" PUB_S ")", DM_NAME_PARAM(r->resrec.name),
-            DNSTypeName(r->resrec.rrtype));
-    }
-    // When NSEC records are not added to the cache, it is usually cached at the "nsec" list
-    // of the CacheRecord. But sometimes they may be freed without adding to the "nsec" list
-    // (which is handled below) and in that case it should be freed here.
-    if (r->resrec.name && cg && r->resrec.name != cg->name)
-    {
-        debugf("ReleaseCacheRecord: freeing %##s (%s)", r->resrec.name->c, DNSTypeName(r->resrec.rrtype));
-        mDNSPlatformMemFree((void *)r->resrec.name);
-    }
-    r->resrec.name = mDNSNULL;
-
-    if (!r->resrec.InterfaceID)
-    {
-        m->rrcache_totalused_unicast -= r->resrec.rdlength;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    MDNS_DISPOSE_DNSSEC_OBJ(r->resrec.dnssec);
-#endif
-
-    ReleaseAdditionalCacheRecords(m, &r->soa);
-
-    ReleaseCacheEntity(m, (CacheEntity *)r);
-}
-
-// Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering
-// CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all
-// callbacks for old records are delivered before callbacks for newer records.
-mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGroup *const cg)
-{
-    CacheRecord **rp = &cg->members;
-
-    if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; }
-    m->lock_rrcache = 1;
-
-    while (*rp)
-    {
-        CacheRecord *const rr = *rp;
-        mDNSBool recordReleased = mDNSfalse;
-        mDNSs32 event = RRExpireTime(rr);
-        if (m->timenow - event >= 0)    // If expired, delete it
-        {
-            if (rr->CRActiveQuestion)   // If this record has one or more active questions, tell them it's going away
-            {
-                DNSQuestion *q = rr->CRActiveQuestion;
-                verbosedebugf("CheckCacheExpiration: Removing%7d %7d %p %s",
-                              m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
-                // When a cache record is about to expire, we expect to do four queries at 80-82%, 85-87%, 90-92% and
-                // then 95-97% of the TTL. If the DNS server does not respond, then we will remove the cache entry
-                // before we pick a new DNS server. As the question interval is set to MaxQuestionInterval, we may
-                // not send out a query anytime soon. Hence, we need to reset the question interval. If this is
-                // a normal deferred ADD case, then AnswerCurrentQuestionWithResourceRecord will reset it to
-                // MaxQuestionInterval. If we have inactive questions referring to negative cache entries,
-                // don't ressurect them as they will deliver duplicate "No such Record" ADD events
-                if (((mDNSOpaque16IsZero(q->TargetQID) && (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)) ||
-                     (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived)) && ActiveQuestion(q))
-                {
-                    q->ThisQInterval = InitialQuestionInterval;
-                    q->LastQTime     = m->timenow - q->ThisQInterval;
-                    SetNextQueryTime(m, q);
-                }
-                CacheRecordRmv(m, rr);
-                m->rrcache_active--;
-            }
-
-            event += MAX_GHOST_TIME;                                                    // Adjust so we can check for a ghost expiration
-            if (rr->resrec.mortality == Mortality_Mortal ||                             // Normal expired mortal record that needs released
-                rr->resrec.rroriginalttl == 0            ||                             // Non-mortal record that is set to be purged
-                (rr->resrec.mortality == Mortality_Ghost && m->timenow - event >= 0))   // A ghost record that expired more than MAX_GHOST_TIME ago
-            {   //  Release as normal
-                *rp = rr->next;                                     // Cut it from the list before ReleaseCacheRecord
-                verbosedebugf("CheckCacheExpiration: Deleting (%s)%7d %7d %p %s",
-                              MortalityDisplayString(rr->resrec.mortality),
-                              m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
-                ReleaseCacheRecord(m, rr);
-                recordReleased = mDNStrue;
-            }
-            else                                                    // An immortal record needs to become a ghost when it expires
-            {   // Don't release this entry
-                if (rr->resrec.mortality == Mortality_Immortal)
-                {
-                    rr->resrec.mortality = Mortality_Ghost;         // Expired immortal records become ghosts
-                    verbosedebugf("CheckCacheExpiration: NOT Deleting (%s)%7d %7d %p %s",
-                                  MortalityDisplayString(rr->resrec.mortality),
-                                  m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
-                    if (rr->DelayDelivery)
-                    {
-                        rr->DelayDelivery = 0;
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "CheckCacheExpiration: Resetting DelayDelivery for new ghost");
-                    }
-                }
-            }
-        }
-        else                                                        // else, not expired; see if we need to query
-        {
-            // If waiting to delay delivery, do nothing until then
-            if (rr->DelayDelivery && rr->DelayDelivery - m->timenow > 0)
-                event = rr->DelayDelivery;
-            else
-            {
-                if (rr->DelayDelivery) CacheRecordDeferredAdd(m, rr);
-                if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
-                {
-                    if (m->timenow - rr->NextRequiredQuery < 0)     // If not yet time for next query
-                        event = NextCacheCheckEvent(rr);            // 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 SetNextCacheCheckTimeForRecord(),
-                        // which will correctly update m->NextCacheCheck for us.
-                        event = m->timenow + FutureTime;
-                    }
-                }
-            }
-        }
-
-        if (!recordReleased)  //  Schedule if we did not release the record
-        {
-            verbosedebugf("CheckCacheExpiration:%6d %5d %s",
-                          (event - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m, rr));
-            if (m->rrcache_nextcheck[slot] - event > 0)
-                m->rrcache_nextcheck[slot] = event;
-            rp = &rr->next;
-        }
-    }
-    if (cg->rrcache_tail != rp) verbosedebugf("CheckCacheExpiration: Updating CacheGroup tail from %p to %p", cg->rrcache_tail, rp);
-    cg->rrcache_tail = rp;
-    m->lock_rrcache = 0;
-}
-
-// "LORecord" includes both LocalOnly and P2P record. This function assumes m->CurrentQuestion is pointing to "q".
-//
-// If "CheckOnly" is set to "true", the question won't be answered but just check to see if there is an answer and
-// returns true if there is an answer.
-//
-// If "CheckOnly" is set to "false", the question will be answered if there is a LocalOnly/P2P record and
-// returns true to indicate the same.
-mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDNSBool checkOnly)
-{
-    AuthRecord *lr;
-    AuthGroup *ag;
-
-    if (m->CurrentRecord)
-        LogMsg("AnswerQuestionWithLORecord ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-
-    ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
-    if (ag)
-    {
-        m->CurrentRecord = ag->members;
-        while (m->CurrentRecord && m->CurrentRecord != ag->NewLocalOnlyRecords)
-        {
-            AuthRecord *rr = m->CurrentRecord;
-            m->CurrentRecord = rr->next;
-            //
-            // If the question is mDNSInterface_LocalOnly, all records local to the machine should be used
-            // to answer the query. This is handled in AnswerNewLocalOnlyQuestion.
-            //
-            // We handle mDNSInterface_Any and scoped questions here. See LocalOnlyRecordAnswersQuestion for more
-            // details on how we handle this case. For P2P we just handle "Interface_Any" questions. For LocalOnly
-            // we handle both mDNSInterface_Any and scoped questions.
-
-            if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && (q->InterfaceID == mDNSInterface_Any || q->InterfaceID == mDNSInterface_BLE)))
-                if (LocalOnlyRecordAnswersQuestion(rr, q))
-                {
-                    if (checkOnly)
-                    {
-                        LogInfo("AnswerQuestionWithLORecord: question %##s (%s) answered by %s", q->qname.c, DNSTypeName(q->qtype),
-                            ARDisplayString(m, rr));
-                        m->CurrentRecord = mDNSNULL;
-                        return mDNStrue;
-                    }
-                    AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add);
-                    if (m->CurrentQuestion != q)
-                        break;     // If callback deleted q, then we're finished here
-                }
-        }
-    }
-    m->CurrentRecord = mDNSNULL;
-
-    if (m->CurrentQuestion != q)
-    {
-        LogInfo("AnswerQuestionWithLORecord: Question deleted while while answering LocalOnly record answers");
-        return mDNStrue;
-    }
-
-    if (q->LOAddressAnswers)
-    {
-        LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) answered using local auth records LOAddressAnswers %d",
-                q, q->qname.c, DNSTypeName(q->qtype), q->LOAddressAnswers);
-        return mDNStrue;
-    }
-
-    // Before we go check the cache and ship this query on the wire, we have to be sure that there are
-    // no local records that could possibly answer this question. As we did not check the NewLocalRecords, we
-    // need to just peek at them to see whether it will answer this question. If it would answer, pretend
-    // that we answered. AnswerAllLocalQuestionsWithLocalAuthRecord will answer shortly. This happens normally
-    // when we add new /etc/hosts entries and restart the question. It is a new question and also a new record.
-    if (ag)
-    {
-        lr = ag->NewLocalOnlyRecords;
-        while (lr)
-        {
-            if (UniqueLocalOnlyRecord(lr) && LocalOnlyRecordAnswersQuestion(lr, q))
-            {
-                LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) will be answered using new local auth records "
-                        " LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), q->LOAddressAnswers);
-                return mDNStrue;
-            }
-            lr = lr->next;
-        }
-    }
-    return mDNSfalse;
-}
-
-// Today, we suppress questions (not send them on the wire) for several reasons e.g.,
-// AAAA query is suppressed because no IPv6 capability or PID is not allowed to make
-// DNS requests.
-mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q)
-{
-    // If the client did not set the kDNSServiceFlagsReturnIntermediates flag, then don't generate a negative response,
-    // just deactivate the DNSQuestion.
-    if (q->ReturnIntermed)
-    {
-        GenerateNegativeResponse(m, mDNSInterface_Any, QC_suppressed);
-    }
-    else
-    {
-        q->ThisQInterval = 0;
-    }
-}
-
-mDNSlocal void AnswerNewQuestion(mDNS *const m)
-{
-    mDNSBool ShouldQueryImmediately = mDNStrue;
-    DNSQuestion *const q = m->NewQuestions;     // Grab the question we're going to answer
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    if (!mDNSOpaque16IsZero(q->TargetQID)) DNS64HandleNewQuestion(m, q);
-#endif
-    CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-
-    verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-    if (cg) CheckCacheExpiration(m, HashSlotFromNameHash(q->qnamehash), cg);
-    if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; }
-    m->NewQuestions = q->next;
-    // Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first
-    // then CheckCacheExpiration may give this question add/remove callbacks, and it's not yet ready for that.
-    //
-    // Also, CheckCacheExpiration() calls CacheRecordDeferredAdd() and CacheRecordRmv(), which invoke
-    // client callbacks, which may delete their own or any other question. Our mechanism for detecting
-    // whether our current m->NewQuestions question got deleted by one of these callbacks is to store the
-    // value of m->NewQuestions in 'q' before calling CheckCacheExpiration(), and then verify afterwards
-    // that they're still the same. If m->NewQuestions has changed (because mDNS_StopQuery_internal
-    // advanced it), that means the question was deleted, so we no longer need to worry about answering
-    // it (and indeed 'q' is now a dangling pointer, so dereferencing it at all would be bad, and the
-    // values we computed for slot and cg are now stale and relate to a question that no longer exists).
-    //
-    // We can't use the usual m->CurrentQuestion mechanism for this because  CacheRecordDeferredAdd() and
-    // CacheRecordRmv() both use that themselves when walking the list of (non-new) questions generating callbacks.
-    // Fortunately mDNS_StopQuery_internal auto-advances both m->CurrentQuestion *AND* m->NewQuestions when
-    // deleting a question, so luckily we have an easy alternative way of detecting if our question got deleted.
-
-    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) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] AnswerNewQuestion ERROR m->CurrentQuestion already set: " PRI_DM_NAME " (" PUB_S ")",
-            m->CurrentQuestion->request_id, mDNSVal16(m->CurrentQuestion->TargetQID),
-            DM_NAME_PARAM(&m->CurrentQuestion->qname), DNSTypeName(m->CurrentQuestion->qtype));
-    }
-
-    m->CurrentQuestion = q;     // Indicate which question we're answering, so we'll know if it gets deleted
-    if (m->CurrentQuestion != q)
-    {
-        LogInfo("AnswerNewQuestion: Question deleted while generating NoAnswer_Fail response");
-        goto exit;
-    }
-
-    // See if we want to tell it about LocalOnly/P2P records. If we answered them using LocalOnly
-    // or P2P record, then we are done.
-    if (AnswerQuestionWithLORecord(m, q, mDNSfalse))
-        goto exit;
-
-    // If it is a question trying to validate some response, it already checked the cache for a response. If it still
-    // reissues a question it means it could not find the RRSIGs. So, we need to bypass the cache check and send
-    // the question out.
-    if (q->Suppressed)
-    {
-        AnswerSuppressedQuestion(m, q);
-    }
-    else
-    {
-        CacheRecord *cr;
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        mDNSu32 answersToValidateCount = 0;         // Count the number of "to be validated" answers for a primary DNSSEC requestor.
-        mDNSBool wildcardCNameAnswer = mDNSfalse;   // Set to true if the returned "to be validated" answers contains a wildcard matched CNAME.
-        mDNSBool negativeProvesWildcard = mDNSfalse;// Set to true if a negative record that proves wildcard answer exists has been returned.
-        mDNSu32 positiveRRSetSize = 0;              // The positive RRSet size (excluding the denial of existence record).
-        #endif
-        for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-        {
-            if (SameNameCacheRecordAnswersQuestion(cr, q))
-            {
-                // SecsSinceRcvd is whole number of elapsed seconds, rounded down
-                mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - cr->TimeRcvd)) / mDNSPlatformOneSecond;
-                mDNSBool IsExpired = (cr->resrec.rroriginalttl <= SecsSinceRcvd);
-                if (IsExpired && q->allowExpired != AllowExpired_AllowExpiredAnswers) 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 ((cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) || (q->ExpectUnique))
-                {
-                    ShouldQueryImmediately = mDNSfalse;
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    // However, for DNSSEC we need to take extra steps to check if a query is necessary.
-                    if (dns_question_is_primary_dnssec_requestor(q) && resource_record_is_to_be_dnssec_validated(&cr->resrec))
-                    {
-                        answersToValidateCount++;
-                        if (resource_record_is_positive(&cr->resrec))
-                        {
-                            if (resource_record_as_rrsig_covers_rr_type(&cr->resrec, kDNSType_CNAME) &&
-                                resource_record_as_rrsig_covers_wildcard_rr(&cr->resrec))
-                            {
-                                // If the RRSIG covers a CNAME, and this RRSIG covers a wildcard resource record,
-                                // then the record (the CNAME) is a wildcard match.
-                                wildcardCNameAnswer = mDNStrue;
-                            }
-                            if (positiveRRSetSize == 0)
-                            {
-                                // Initialized once, to get the positive RRSet size.
-                                positiveRRSetSize = (mDNSu32)dnssec_obj_resource_record_member_get_rrset_size(cr->resrec.dnssec);
-                            }
-                        }
-                        else // Negative record
-                        {
-                            negativeProvesWildcard = resource_record_as_denial_of_existence_proves_wildcard_answer(&cr->resrec);
-                        }
-                    }
-                #endif
-                }
-                q->CurrentAnswers++;
-                if (cr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
-                if (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-                cr->LastCachedAnswerTime = m->timenow;
-                dnssd_analytics_update_cache_request(mDNSOpaque16IsZero(q->TargetQID) ? CacheRequestType_multicast : CacheRequestType_unicast, CacheState_hit);
-#endif
-                AnswerCurrentQuestionWithResourceRecord(m, cr, QC_add);
-                if (m->CurrentQuestion != q) break;     // If callback deleted q, then we're finished here
-            }
-            else if (mDNSOpaque16IsZero(q->TargetQID) && RRTypeIsAddressType(cr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
-            {
-                ShouldQueryImmediately = mDNSfalse;
-            }
-        }
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        if (m->CurrentQuestion == q && dns_question_is_primary_dnssec_requestor(q) && !ShouldQueryImmediately)
-        {
-            // If we have decided to hold the query, check if we still need to send the query out because of an
-            // incomplete answer set.
-            // If we have a wildcard CName answer, then we must have a denial of existence record that proves the
-            // existence of this CName. Therefore, we can only be sure that we have a complete set if and only if:
-            // answersToValidateCount == positiveRRSetSize + 1, where 1 is the denial of existence record. (which means the
-            // corresponding nagative record has expired from cache).
-            // Or if we only returned a denial of existence record that proves a wildcard answer (which means the
-            // corresponding positive RRSet has expired from cache)
-            // In either of two cases above, send out query anyway to get the full RRSets.
-            const mDNSBool onlyPositive = (wildcardCNameAnswer && (answersToValidateCount != positiveRRSetSize + 1));
-            const mDNSBool onlyNegative = (negativeProvesWildcard && (answersToValidateCount == 1));
-            if (onlyPositive || onlyNegative)
-            {
-                ShouldQueryImmediately = mDNStrue;
-                LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_DEFAULT,
-                    "[Q%u] Continue sending out query for the primary DNSSEC question due to incomplete answer set - "
-                    "only positive: " PUB_BOOL ", only negative: " PUB_BOOL, mDNSVal16(q->TargetQID),
-                    BOOL_PARAM(onlyPositive), BOOL_PARAM(onlyNegative));
-            }
-        }
-    #endif
-    }
-    // We don't use LogInfo for this "Question deleted" message because it happens so routinely that
-    // it's not remotely remarkable, and therefore unlikely to be of much help tracking down bugs.
-    if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving cache answers"); goto exit; }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-    dnssd_analytics_update_cache_request(mDNSOpaque16IsZero(q->TargetQID) ? CacheRequestType_multicast : CacheRequestType_unicast, CacheState_miss);
-#endif
-    q->InitialCacheMiss  = mDNStrue;                                    // Initial cache check is done, so mark as a miss from now on
-    if (q->allowExpired == AllowExpired_AllowExpiredAnswers)
-    {
-        q->allowExpired = AllowExpired_MakeAnswersImmortal;             // After looking through the cache for an answer, demote to make immortal
-        if (q->firstExpiredQname.c[0])                                  // If an original query name was saved on an expired answer, start it over in case it is updated
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] AnswerNewQuestion: Restarting original question %p firstExpiredQname " PRI_DM_NAME
-                " for allowExpiredAnswers question",
-                q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->firstExpiredQname));
-            mDNS_StopQuery_internal(m, q);                              // Stop old query
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (!SameDomainName(&q->qname, &q->firstExpiredQname))
-            {
-                Querier_PrepareQuestionForUnwindRestart(q);
-            }
-#endif
-            AssignDomainName(&q->qname, &q->firstExpiredQname);         // Update qname
-            q->qnamehash = DomainNameHashValue(&q->qname);              // and namehash
-            mDNS_StartQuery_internal(m, q);                             // start new query
-            q->CNAMEReferrals = 0;                                      // Reset referral count
-            q->firstExpiredQname.c[0] = 0;                              // Erase the domain name
-        }
-    }
-
-    // Note: When a query gets suppressed or retried with search domains, we de-activate the question.
-    // Hence we don't execute the following block of code for those cases.
-    if (ShouldQueryImmediately && ActiveQuestion(q))
-    {
-        debugf("[R%d->Q%d] AnswerNewQuestion: ShouldQueryImmediately %##s (%s)", q->request_id, mDNSVal16(q->TargetQID), q->qname.c, DNSTypeName(q->qtype));
-        q->ThisQInterval  = InitialQuestionInterval;
-        q->LastQTime      = m->timenow - q->ThisQInterval;
-        if (mDNSOpaque16IsZero(q->TargetQID))       // For mDNS, spread packets to avoid a burst of simultaneous queries
-        {
-            // Compute random delay in the range 1-6 seconds, then divide by 50 to get 20-120ms
-            if (!m->RandomQueryDelay)
-                m->RandomQueryDelay = (mDNSPlatformOneSecond + mDNSRandom(mDNSPlatformOneSecond*5) - 1) / 50 + 1;
-            q->LastQTime += m->RandomQueryDelay;
-        }
-    }
-
-    // IN ALL CASES make sure that m->NextScheduledQuery is set appropriately.
-    // In cases where m->NewQuestions->DelayAnswering is set, we may have delayed generating our
-    // answers for this question until *after* its scheduled transmission time, in which case
-    // m->NextScheduledQuery may now be set to 'never', and in that case -- even though we're *not* doing
-    // ShouldQueryImmediately -- we still need to make sure we set m->NextScheduledQuery correctly.
-    SetNextQueryTime(m,q);
-
-exit:
-    m->CurrentQuestion = mDNSNULL;
-    m->lock_rrcache = 0;
-}
-
-// When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any
-// appropriate answers, stopping if it reaches a NewLocalOnlyRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord
-mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
-{
-    AuthGroup *ag;
-    DNSQuestion *q = m->NewLocalOnlyQuestions;      // Grab the question we're going to answer
-    mDNSBool retEv = mDNSfalse;
-    m->NewLocalOnlyQuestions = q->next;             // Advance NewLocalOnlyQuestions to the next (if any)
-
-    debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-    if (m->CurrentQuestion)
-        LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = q;     // Indicate which question we're answering, so we'll know if it gets deleted
-
-    if (m->CurrentRecord)
-        LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-
-    // 1. First walk the LocalOnly records answering the LocalOnly question
-    // 2. As LocalOnly questions should also be answered by any other Auth records local to the machine,
-    //    walk the ResourceRecords list delivering the answers
-    ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
-    if (ag)
-    {
-        m->CurrentRecord = ag->members;
-        while (m->CurrentRecord && m->CurrentRecord != ag->NewLocalOnlyRecords)
-        {
-            AuthRecord *rr = m->CurrentRecord;
-            m->CurrentRecord = rr->next;
-            if (LocalOnlyRecordAnswersQuestion(rr, q))
-            {
-                retEv = mDNStrue;
-                AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add);
-                if (m->CurrentQuestion != q) break;     // If callback deleted q, then we're finished here
-            }
-        }
-    }
-
-    if (m->CurrentQuestion == q)
-    {
-        m->CurrentRecord = m->ResourceRecords;
-
-        while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords)
-        {
-            AuthRecord *ar = m->CurrentRecord;
-            m->CurrentRecord = ar->next;
-            if (AuthRecordAnswersQuestion(ar, q))
-            {
-                retEv = mDNStrue;
-                AnswerLocalQuestionWithLocalAuthRecord(m, ar, QC_add);
-                if (m->CurrentQuestion != q) break;     // If callback deleted q, then we're finished here
-            }
-        }
-    }
-
-    // The local host is the authoritative source for LocalOnly questions
-    // so if no records exist and client requested intermediates, then generate a negative response
-    if (!retEv && (m->CurrentQuestion == q) && q->ReturnIntermed)
-        GenerateNegativeResponse(m, mDNSInterface_LocalOnly, QC_forceresponse);
-
-    m->CurrentQuestion = mDNSNULL;
-    m->CurrentRecord   = mDNSNULL;
-}
-
-mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const PreserveCG)
-{
-    CacheEntity *e = 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)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetFreeCacheRR: count mismatch: m->rrcache_totalused %u != m->rrcache_size %u",
-                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 our cache grows above 512kB (approx 3168 records at 164 bytes each),
-        // and we're actively using less than 1/32 of that cache, then we purge all the unused records
-        // and recycle them, instead of allocating more memory.
-        if (m->rrcache_size > 5000 && m->rrcache_size / 32 > m->rrcache_active)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Possible denial-of-service attack in progress: m->rrcache_size %u; m->rrcache_active %u",
-                m->rrcache_size, m->rrcache_active);
-        }
-        else
-        {
-            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-            m->MainCallback(m, mStatus_GrowCache);
-            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-        }
-    }
-
-    // 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)
-    {
-        mDNSu32 oldtotalused = m->rrcache_totalused;
-        mDNSu32 slot;
-        for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-        {
-            CacheGroup **cp = &m->rrcache_hash[slot];
-            while (*cp)
-            {
-                CacheRecord **rp = &(*cp)->members;
-                while (*rp)
-                {
-                    // Cases where we do not want to recycle cache entry:
-                    // 1. Records that answer still-active questions are not candidates for recycling.
-                    // 2. Records that are currently linked into the CacheFlushRecords list may not be recycled, or
-                    //    we'll crash.
-                    // 3. Records that are newly added to the cache but whose callback delivery gets delayed should not
-                    //    be recycled, because it will end up with an incomplete RRSet.
-                    mDNSBool doNotRecycle = ((*rp)->CRActiveQuestion || (*rp)->NextInCFList
-                        || ((*rp)->DelayDelivery != 0));
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    // 4. Records that are currently saved to a temporary array to calculate the response set size may
-                    //    not be recycled, or we'll crash.
-                    doNotRecycle = doNotRecycle || ((*rp)->ineligibleForRecycling);
-                #endif
-
-                    if (doNotRecycle)
-                    {
-                        rp=&(*rp)->next;
-                    }
-                    else
-                    {
-                        CacheRecord *rr = *rp;
-                        *rp = (*rp)->next;          // Cut record from list
-                        ReleaseCacheRecord(m, rr);
-                    }
-                }
-                if ((*cp)->rrcache_tail != rp)
-                    verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp);
-                (*cp)->rrcache_tail = rp;
-                if ((*cp)->members || (*cp)==PreserveCG) cp=&(*cp)->next;
-                else ReleaseCacheGroup(m, cp);
-            }
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "GetCacheEntity recycled %d records to reduce cache from %d to %d",
-            oldtotalused - m->rrcache_totalused, oldtotalused, m->rrcache_totalused);
-    }
-
-    if (m->rrcache_free)    // If there are records in the free list, take one
-    {
-        e = m->rrcache_free;
-        m->rrcache_free = e->next;
-        if (++m->rrcache_totalused >= m->rrcache_report)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "RR Cache now using %u objects", m->rrcache_totalused);
-            if      (m->rrcache_report <  100) m->rrcache_report += 10;
-            else if (m->rrcache_report < 1000) m->rrcache_report += 100;
-            else m->rrcache_report += 1000;
-        }
-        mDNSPlatformMemZero(e, sizeof(*e));
-    }
-
-    m->lock_rrcache = 0;
-
-    return(e);
-}
-
-mDNSlocal CacheRecord *GetCacheRecord(mDNS *const m, CacheGroup *cg, mDNSu16 RDLength)
-{
-    CacheRecord *r = (CacheRecord *)GetCacheEntity(m, cg);
-    if (r)
-    {
-        r->resrec.rdata = (RData*)&r->smallrdatastorage;    // 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*) mDNSPlatformMemAllocateClear(sizeofRDataHeader + RDLength);
-            if (r->resrec.rdata) r->resrec.rdata->MaxRDLength = r->resrec.rdlength = RDLength;
-            else { ReleaseCacheEntity(m, (CacheEntity*)r); r = mDNSNULL; }
-        }
-    }
-    return(r);
-}
-
-mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
-{
-    mDNSu16 namelen = DomainNameLength(rr->name);
-    CacheGroup *cg = (CacheGroup*)GetCacheEntity(m, mDNSNULL);
-    if (!cg) { LogMsg("GetCacheGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
-    cg->next         = m->rrcache_hash[slot];
-    cg->namehash     = rr->namehash;
-    cg->members      = mDNSNULL;
-    cg->rrcache_tail = &cg->members;
-    if (namelen > sizeof(cg->namestorage))
-        cg->name = (domainname *) mDNSPlatformMemAllocate(namelen);
-    else
-        cg->name = (domainname*)cg->namestorage;
-    if (!cg->name)
-    {
-        LogMsg("GetCacheGroup: Failed to allocate name storage for %##s", rr->name->c);
-        ReleaseCacheEntity(m, (CacheEntity*)cg);
-        return(mDNSNULL);
-    }
-    AssignDomainName(cg->name, rr->name);
-
-    if (CacheGroupForRecord(m, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c);
-    m->rrcache_hash[slot] = cg;
-    if (CacheGroupForRecord(m, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c);
-
-    return(cg);
-}
-
-mDNSexport void mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr)
-{
-    mDNS_CheckLock(m);
-
-    // 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;
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    rr->DNSPushSubscribed = mDNSfalse;
-#endif
-    SetNextCacheCheckTimeForRecord(m, rr);
-}
-
-mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m)
-{
-    mDNSs32 time;
-    mDNSPlatformLock(m);
-    if (m->mDNS_busy)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "Lock failure: mDNS_TimeNow called while holding mDNS lock. This is incorrect. Code protected by lock should just use m->timenow.");
-        if (!m->timenow)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "Lock failure: mDNS_TimeNow: m->mDNS_busy is %u but m->timenow not set", m->mDNS_busy);
-        }
-    }
-
-    if (m->timenow) time = m->timenow;
-    else time = mDNS_TimeNow_NoLock(m);
-    mDNSPlatformUnlock(m);
-    return(time);
-}
-
-// To avoid pointless CPU thrash, we use SetSPSProxyListChanged(X) to record the last interface that
-// had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute().
-// (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set)
-#define SetSPSProxyListChanged(X) do { \
-        if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m->SPSProxyListChanged); \
-        m->SPSProxyListChanged = (X); } while(0)
-
-// Called from mDNS_Execute() to expire stale proxy records
-mDNSlocal void CheckProxyRecords(mDNS *const m, AuthRecord *list)
-{
-    m->CurrentRecord = list;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rr = m->CurrentRecord;
-        if (rr->resrec.RecordType != kDNSRecordTypeDeregistering && rr->WakeUp.HMAC.l[0])
-        {
-            // If m->SPSSocket is NULL that means we're not acting as a sleep proxy any more,
-            // so we need to cease proxying for *all* records we may have, expired or not.
-            if (m->SPSSocket && m->timenow - rr->TimeExpire < 0)    // If proxy record not expired yet, update m->NextScheduledSPS
-            {
-                if (m->NextScheduledSPS - rr->TimeExpire > 0)
-                    m->NextScheduledSPS = rr->TimeExpire;
-            }
-            else                                                    // else proxy record expired, so remove it
-            {
-                LogSPS("CheckProxyRecords: Removing %d H-MAC %.6a I-MAC %.6a %d %s",
-                       m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, ARDisplayString(m, rr));
-                SetSPSProxyListChanged(rr->resrec.InterfaceID);
-                mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                // Don't touch rr after this -- memory may have been free'd
-            }
-        }
-        // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-        // new records could have been added to the end of the list as a result of that call.
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m)
-{
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rr = m->CurrentRecord;
-        if (rr->AnsweredLocalQ && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-        {
-            debugf("CheckRmvEventsForLocalRecords: Generating local RMV events for %s", ARDisplayString(m, rr));
-            rr->resrec.RecordType = kDNSRecordTypeShared;
-            AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv);
-            if (m->CurrentRecord == rr) // If rr still exists in list, restore its state now
-            {
-                rr->resrec.RecordType = kDNSRecordTypeDeregistering;
-                rr->AnsweredLocalQ = mDNSfalse;
-                // SendResponses normally calls CompleteDeregistration after sending goodbyes.
-                // For LocalOnly records, we don't do that and hence we need to do that here.
-                if (RRLocalOnly(rr)) CompleteDeregistration(m, rr);
-            }
-        }
-        if (m->CurrentRecord == rr)     // If m->CurrentRecord was not auto-advanced, do it ourselves now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-mDNSlocal void TimeoutQuestions_internal(mDNS *const m, DNSQuestion* questions, mDNSInterfaceID InterfaceID)
-{
-    if (m->CurrentQuestion)
-        LogMsg("TimeoutQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c,
-               DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = questions;
-    while (m->CurrentQuestion)
-    {
-        DNSQuestion *const q = m->CurrentQuestion;
-        if (q->StopTime)
-        {
-            if (!q->TimeoutQuestion)
-                LogMsg("TimeoutQuestions: ERROR!! TimeoutQuestion not set, but StopTime set for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-            if (m->timenow - q->StopTime >= 0)
-            {
-                LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime);
-                q->LOAddressAnswers = 0; // unset since timing out the question
-                GenerateNegativeResponse(m, InterfaceID, QC_forceresponse);
-                if (m->CurrentQuestion == q) q->StopTime = 0;
-            }
-            else
-            {
-                if (m->NextScheduledStopTime - q->StopTime > 0)
-                    m->NextScheduledStopTime = q->StopTime;
-            }
-        }
-        // If m->CurrentQuestion wasn't modified out from under us, advance it now
-        // We can't do this at the start of the loop because GenerateNegativeResponse
-        // depends on having m->CurrentQuestion point to the right question
-        if (m->CurrentQuestion == q)
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-mDNSlocal void TimeoutQuestions(mDNS *const m)
-{
-    m->NextScheduledStopTime = m->timenow + FutureTime; // push reschedule of TimeoutQuestions to way off into the future
-    TimeoutQuestions_internal(m, m->Questions, mDNSInterface_Any);
-    TimeoutQuestions_internal(m, m->LocalOnlyQuestions, mDNSInterface_LocalOnly);
-}
-
-mDNSlocal void mDNSCoreFreeProxyRR(mDNS *const m)
-{
-    AuthRecord *rrPtr = m->SPSRRSet, *rrNext = mDNSNULL;
-    LogSPS("%s : Freeing stored sleep proxy A/AAAA records", __func__);
-    while (rrPtr)
-    {
-        rrNext = rrPtr->next;
-        mDNSPlatformMemFree(rrPtr);
-        rrPtr  = rrNext;
-    }
-    m->SPSRRSet = mDNSNULL;
-}
-
-mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
-{
-    mDNS_Lock(m);   // Must grab lock before trying to read m->timenow
-
-    if (m->timenow - m->NextScheduledEvent >= 0)
-    {
-        int i;
-        AuthRecord *head, *tail;
-        mDNSu32 slot;
-        AuthGroup *ag;
-
-        verbosedebugf("mDNS_Execute");
-
-        if (m->CurrentQuestion)
-            LogMsg("mDNS_Execute: ERROR m->CurrentQuestion already set: %##s (%s)",
-                   m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-
-        if (m->CurrentRecord)
-            LogMsg("mDNS_Execute: ERROR m->CurrentRecord already set: %s", ARDisplayString(m, m->CurrentRecord));
-
-        // 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 numchecked = 0;
-            m->NextCacheCheck = m->timenow + FutureTime;
-            for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-            {
-                if (m->timenow - m->rrcache_nextcheck[slot] >= 0)
-                {
-                    CacheGroup **cp = &m->rrcache_hash[slot];
-                    m->rrcache_nextcheck[slot] = m->timenow + FutureTime;
-                    while (*cp)
-                    {
-                        debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL");
-                        numchecked++;
-                        CheckCacheExpiration(m, slot, *cp);
-                        if ((*cp)->members) cp=&(*cp)->next;
-                        else ReleaseCacheGroup(m, cp);
-                    }
-                }
-                // Even if we didn't need to actually check this slot yet, still need to
-                // factor its nextcheck time into our overall NextCacheCheck value
-                if (m->NextCacheCheck - m->rrcache_nextcheck[slot] > 0)
-                    m->NextCacheCheck = m->rrcache_nextcheck[slot];
-            }
-            debugf("m->NextCacheCheck %4d checked, next in %d", numchecked, m->NextCacheCheck - m->timenow);
-        }
-
-        if (m->timenow - m->NextScheduledSPS >= 0)
-        {
-            m->NextScheduledSPS = m->timenow + FutureTime;
-            CheckProxyRecords(m, m->DuplicateRecords);  // Clear m->DuplicateRecords first, then m->ResourceRecords
-            CheckProxyRecords(m, m->ResourceRecords);
-        }
-
-        SetSPSProxyListChanged(mDNSNULL);       // Perform any deferred BPF reconfiguration now
-
-        // Check to see if we need to send any keepalives. Do this after we called CheckProxyRecords above
-        // as records could have expired during that check
-        if (m->timenow - m->NextScheduledKA >= 0)
-        {
-            m->NextScheduledKA = m->timenow + FutureTime;
-            mDNS_SendKeepalives(m);
-        }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-        if (m->NextBonjourDisableTime && (m->timenow - m->NextBonjourDisableTime >= 0))
-        {
-            // Schedule immediate network change processing to leave the multicast group
-            // since the delay time has expired since the previous active registration or query.
-            m->NetworkChanged = m->timenow;
-            m->NextBonjourDisableTime = 0;
-            m->BonjourEnabled = 0;
-
-            LogInfo("mDNS_Execute: Scheduled network changed processing to leave multicast group.");
-        }
-#endif
-
-        // mDNS_SetUpDomainEnumeration() will check if the domain enumeration operation can be stopped.
-        for (DomainEnumerationOp *op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-        {
-            for (mDNSu32 type = 0; type < mDNS_DomainTypeMaxCount; type++)
-            {
-                mDNS_SetUpDomainEnumeration(m, op, type);
-            }
-        }
-
-        // Clear AnnounceOwner if necessary. (Do this *before* SendQueries() and SendResponses().)
-        if (m->AnnounceOwner && m->timenow - m->AnnounceOwner >= 0)
-        {
-            m->AnnounceOwner = 0;
-        }
-
-        if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
-        {
-            m->DelaySleep = 0;
-            if (m->SleepState == SleepState_Transferring)
-            {
-                LogSPS("Re-sleep delay passed; now checking for Sleep Proxy Servers");
-                BeginSleepProcessing(m);
-            }
-        }
-
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Check if there is any newly DNSSEC-validated record to be added to the cache.
-        if (m->NextUpdateDNSSECValidatedCache && m->timenow - m->NextUpdateDNSSECValidatedCache >= 0)
-        {
-            m->NextUpdateDNSSECValidatedCache = 0;
-            dnssec_update_cache_for_validated_records(m);
-        }
-    #endif
-
-        // 4. See if we can answer any of our new local questions from the cache
-        for (i=0; m->NewQuestions && i<1000; i++)
-        {
-            if (m->NewQuestions->DelayAnswering && m->timenow - m->NewQuestions->DelayAnswering < 0) break;
-            AnswerNewQuestion(m);
-        }
-        if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
-
-        // Make sure we deliver *all* local RMV events, and clear the corresponding rr->AnsweredLocalQ flags, *before*
-        // we begin generating *any* new ADD events in the m->NewLocalOnlyQuestions and m->NewLocalRecords loops below.
-        for (i=0; i<1000 && m->LocalRemoveEvents; i++)
-        {
-            m->LocalRemoveEvents = mDNSfalse;
-            m->CurrentRecord = m->ResourceRecords;
-            CheckRmvEventsForLocalRecords(m);
-            // Walk the LocalOnly records and deliver the RMV events
-            for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-                for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
-                {
-                    m->CurrentRecord = ag->members;
-                    if (m->CurrentRecord) CheckRmvEventsForLocalRecords(m);
-                }
-        }
-
-        if (i >= 1000) LogMsg("mDNS_Execute: m->LocalRemoveEvents exceeded loop limit");
-
-        for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m);
-        if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
-
-        head = tail = mDNSNULL;
-        for (i=0; i<1000 && m->NewLocalRecords && m->NewLocalRecords != head; i++)
-        {
-            AuthRecord *rr = m->NewLocalRecords;
-            m->NewLocalRecords = m->NewLocalRecords->next;
-            if (LocalRecordReady(rr))
-            {
-                debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr));
-                AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add);
-            }
-            else if (!rr->next)
-            {
-                // If we have just one record that is not ready, we don't have to unlink and
-                // reinsert. As the NewLocalRecords will be NULL for this case, the loop will
-                // terminate and set the NewLocalRecords to rr.
-                debugf("mDNS_Execute: Just one LocalAuthRecord %s, breaking out of the loop early", ARDisplayString(m, rr));
-                if (head != mDNSNULL || m->NewLocalRecords != mDNSNULL)
-                    LogMsg("mDNS_Execute: ERROR!!: head %p, NewLocalRecords %p", head, m->NewLocalRecords);
-
-                head = rr;
-            }
-            else
-            {
-                AuthRecord **p = &m->ResourceRecords;   // Find this record in our list of active records
-                debugf("mDNS_Execute: Skipping LocalAuthRecord %s", ARDisplayString(m, rr));
-                // if this is the first record we are skipping, move to the end of the list.
-                // if we have already skipped records before, append it at the end.
-                while (*p && *p != rr) p=&(*p)->next;
-                if (*p) *p = rr->next;                  // Cut this record from the list
-                else { LogMsg("mDNS_Execute: ERROR!! Cannot find record %s in ResourceRecords list", ARDisplayString(m, rr)); break; }
-                if (!head)
-                {
-                    while (*p) p=&(*p)->next;
-                    *p = rr;
-                    head = tail = rr;
-                }
-                else
-                {
-                    tail->next = rr;
-                    tail = rr;
-                }
-                rr->next = mDNSNULL;
-            }
-        }
-        m->NewLocalRecords = head;
-        debugf("mDNS_Execute: Setting NewLocalRecords to %s", (head ? ARDisplayString(m, head) : "NULL"));
-
-        if (i >= 1000) LogMsg("mDNS_Execute: m->NewLocalRecords exceeded loop limit");
-
-        // Check to see if we have any new LocalOnly/P2P records to examine for delivering
-        // to our local questions
-        if (m->NewLocalOnlyRecords)
-        {
-            m->NewLocalOnlyRecords = mDNSfalse;
-            for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-            {
-                for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
-                {
-                    for (i=0; i<100 && ag->NewLocalOnlyRecords; i++)
-                    {
-                        AuthRecord *rr = ag->NewLocalOnlyRecords;
-                        ag->NewLocalOnlyRecords = ag->NewLocalOnlyRecords->next;
-                        // LocalOnly records should always be ready as they never probe
-                        if (LocalRecordReady(rr))
-                        {
-                            debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr));
-                            AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add);
-                        }
-                        else LogMsg("mDNS_Execute: LocalOnlyRecord %s not ready", ARDisplayString(m, rr));
-                    }
-                    // We limit about 100 per AuthGroup that can be serviced at a time
-                    if (i >= 100) LogMsg("mDNS_Execute: ag->NewLocalOnlyRecords exceeded loop limit");
-                }
-            }
-        }
-
-        // 5. See what packets we need to send
-        if (m->mDNSPlatformStatus != mStatus_NoError || (m->SleepState == SleepState_Sleeping))
-            DiscardDeregistrations(m);
-        if (m->mDNSPlatformStatus == mStatus_NoError)
-        {
-            // 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.
-            if (!m->SuppressQueries || ((m->timenow - m->SuppressQueries) >= 0))
-            {
-                m->SuppressQueries = 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)
-                {
-                    DNSQuestion *q;
-                    LogMsg("mDNS_Execute: SendQueries didn't send all its queries (%d - %d = %d) will try again in one second",
-                           m->timenow, m->NextScheduledQuery, m->timenow - m->NextScheduledQuery);
-                    m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond;
-                    for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
-                        if (ActiveQuestion(q) && m->timenow - NextQSendTime(q) >= 0)
-                            LogMsg("mDNS_Execute: SendQueries didn't send %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-                }
-                if (m->timenow - m->NextScheduledProbe >= 0)
-                {
-                    LogMsg("mDNS_Execute: SendQueries didn't send all its probes (%d - %d = %d) will try again in one second",
-                           m->timenow, m->NextScheduledProbe, m->timenow - m->NextScheduledProbe);
-                    m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond;
-                }
-            }
-            if (!m->SuppressResponses || ((m->timenow - m->SuppressResponses) >= 0))
-            {
-                m->SuppressResponses = 0;
-
-                // 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;
-                }
-            }
-        }
-
-        // Clear RandomDelay values, ready to pick a new different value next time
-        m->RandomQueryDelay     = 0;
-        m->RandomReconfirmDelay = 0;
-
-        // See if any questions (or local-only questions) have timed out
-        if (m->NextScheduledStopTime && m->timenow - m->NextScheduledStopTime >= 0) TimeoutQuestions(m);
-#ifndef UNICAST_DISABLED
-        if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m);
-        if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m);
-        if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m);
-#endif
-    }
-
-    // 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);
-}
-
-#ifndef UNICAST_DISABLED
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-mDNSlocal void SuspendLLQs(mDNS *m)
-{
-    DNSQuestion *q;
-    for (q = m->Questions; q; q = q->next)
-        if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->state == LLQ_Established)
-        { q->ReqLease = 0; sendLLQRefresh(m, q); }
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-#endif // UNICAST_DISABLED
-
-mDNSlocal mDNSBool QuestionHasLocalAnswers(mDNS *const m, DNSQuestion *q)
-{
-    AuthRecord *rr;
-    AuthGroup *ag;
-
-    ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
-    if (ag)
-    {
-        for (rr = ag->members; rr; rr=rr->next)
-            // Filter the /etc/hosts records - LocalOnly, Unique, A/AAAA/CNAME
-            if (UniqueLocalOnlyRecord(rr) && LocalOnlyRecordAnswersQuestion(rr, q))
-            {
-                LogInfo("QuestionHasLocalAnswers: Question %p %##s (%s) has local answer %s", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr));
-                return mDNStrue;
-            }
-    }
-    return mDNSfalse;
-}
-
-// ActivateUnicastQuery() is called from three places:
-// 1. When a new question is created
-// 2. On wake from sleep
-// 3. When the DNS configuration changes
-// In case 1 we don't want to mess with our established ThisQInterval and LastQTime (ScheduleImmediately is false)
-// In cases 2 and 3 we do want to cause the question to be resent immediately (ScheduleImmediately is true)
-mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, mDNSBool ScheduleImmediately)
-{
-    if (!question->DuplicateOf)
-    {
-        debugf("ActivateUnicastQuery: %##s %s%s",
-               question->qname.c, DNSTypeName(question->qtype), ScheduleImmediately ? " ScheduleImmediately" : "");
-        question->CNAMEReferrals = 0;
-        if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
-        if (question->LongLived)
-        {
-            question->state = LLQ_Init;
-            question->id = zeroOpaque64;
-            question->servPort = zeroIPPort;
-            if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
-        }
-        // If the question has local answers, then we don't want answers from outside
-        if (ScheduleImmediately && !QuestionHasLocalAnswers(m, question))
-        {
-            question->ThisQInterval = InitialQuestionInterval;
-            question->LastQTime     = m->timenow - question->ThisQInterval;
-            SetNextQueryTime(m, question);
-        }
-    }
-}
-
-// Caller should hold the lock
-mDNSexport void mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
-                                              CallbackBeforeStartQuery BeforeStartCallback, void *context)
-{
-    DNSQuestion *q;
-    DNSQuestion *restart = mDNSNULL;
-
-    mDNS_CheckLock(m);
-
-    // 1. Flush the cache records
-    if (flushCacheRecords) flushCacheRecords(m);
-
-    // 2. Even though we may have purged the cache records above, before it can generate RMV event
-    // we are going to stop the question. Hence we need to deliver the RMV event before we
-    // stop the question.
-    //
-    // CurrentQuestion is used by RmvEventsForQuestion below. While delivering RMV events, the
-    // application callback can potentially stop the current question (detected by CurrentQuestion) or
-    // *any* other question which could be the next one that we may process here. RestartQuestion
-    // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal
-    // if the "next" question is stopped while the CurrentQuestion is stopped
-
-    if (m->RestartQuestion)
-        LogMsg("mDNSCoreRestartAddressQueries: ERROR!! m->RestartQuestion already set: %##s (%s)",
-               m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype));
-
-    m->RestartQuestion = m->Questions;
-    while (m->RestartQuestion)
-    {
-        q = m->RestartQuestion;
-        m->RestartQuestion = q->next;
-        // GetZoneData questions are referenced by other questions (original query that started the GetZoneData
-        // question)  through their "nta" pointer. Normally when the original query stops, it stops the
-        // GetZoneData question and also frees the memory (See CancelGetZoneData). If we stop the GetZoneData
-        // question followed by the original query that refers to this GetZoneData question, we will end up
-        // freeing the GetZoneData question and then start the "freed" question at the end.
-
-        if (IsGetZoneDataQuestion(q))
-        {
-            DNSQuestion *refq = q->next;
-            LogInfo("mDNSCoreRestartAddressQueries: Skipping GetZoneDataQuestion %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-            // debug stuff, we just try to find the referencing question and don't do much with it
-            while (refq)
-            {
-                if (q == &refq->nta->question)
-                {
-                    LogInfo("mDNSCoreRestartAddressQueries: Question %p %##s (%s) referring to GetZoneDataQuestion %p, not stopping", refq, refq->qname.c, DNSTypeName(refq->qtype), q);
-                }
-                refq = refq->next;
-            }
-            continue;
-        }
-
-        // This function is called when /etc/hosts changes and that could affect A, AAAA and CNAME queries
-        if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA && q->qtype != kDNSType_CNAME) continue;
-
-        // If the search domains did not change, then we restart all the queries. Otherwise, only
-        // for queries for which we "might" have appended search domains ("might" because we may
-        // find results before we apply search domains even though AppendSearchDomains is set to 1)
-        if (!SearchDomainsChanged || q->AppendSearchDomains)
-        {
-            // NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero
-            // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
-            // LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers). Let us say that
-            // /etc/hosts has an A Record for web.apple.com. Any queries for web.apple.com will be answered locally.
-            // But this can't prevent a CNAME/AAAA query to not to be sent on the wire. When it is sent on the wire,
-            // it could create cache entries. When we are restarting queries, we can't deliver the cache RMV events
-            // for the original query using these cache entries as ADDs were never delivered using these cache
-            // entries and hence this order is needed.
-
-            // If the query is suppressed, the RMV events won't be delivered
-            if (!CacheRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Cache Record RMV events"); continue; }
-
-            // Suppressed status does not affect questions that are answered using local records
-            if (!LocalRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Local Record RMV events"); continue; }
-
-            LogInfo("mDNSCoreRestartAddressQueries: Stop question %p %##s (%s), AppendSearchDomains %d", q,
-                    q->qname.c, DNSTypeName(q->qtype), q->AppendSearchDomains);
-            mDNS_StopQuery_internal(m, q);
-            if (q->ResetHandler) q->ResetHandler(q);
-            q->next = restart;
-            restart = q;
-        }
-    }
-
-    // 3. Callback before we start the query
-    if (BeforeStartCallback) BeforeStartCallback(m, context);
-
-    // 4. Restart all the stopped queries
-    while (restart)
-    {
-        q = restart;
-        restart = restart->next;
-        q->next = mDNSNULL;
-        LogInfo("mDNSCoreRestartAddressQueries: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-        mDNS_StartQuery_internal(m, q);
-    }
-}
-
-mDNSexport void mDNSCoreRestartQueries(mDNS *const m)
-{
-    DNSQuestion *q;
-
-#ifndef UNICAST_DISABLED
-    // Retrigger all our uDNS questions
-    if (m->CurrentQuestion)
-        LogMsg("mDNSCoreRestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-    m->CurrentQuestion = m->Questions;
-    while (m->CurrentQuestion)
-    {
-        q = m->CurrentQuestion;
-        m->CurrentQuestion = m->CurrentQuestion->next;
-        if (!mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            mdns_querier_forget(&q->querier);
-#endif
-            ActivateUnicastQuery(m, q, mDNStrue);
-        }
-    }
-#endif
-
-    // Retrigger all our mDNS questions
-    for (q = m->Questions; q; q=q->next)                // Scan our list of questions
-            mDNSCoreRestartQuestion(m, q);
-}
-
-// restart question if it's multicast and currently active
-mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q)
-{
-    if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
-    {
-        q->ThisQInterval    = InitialQuestionInterval;  // MUST be > zero for an active question
-        q->RequestUnicast   = kDefaultRequestUnicastCount;
-        q->LastQTime        = m->timenow - q->ThisQInterval;
-        q->RecentAnswerPkts = 0;
-        ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
-        m->NextScheduledQuery = m->timenow;
-    }
-}
-
-// restart the probe/announce cycle for multicast record
-mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount)
-{
-    if (!AuthRecord_uDNS(rr))
-    {
-        if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
-        rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-
-        if (mDNS_KeepaliveRecord(&rr->resrec))
-        {
-            rr->AnnounceCount = 0; // Do not announce keepalive records
-        }
-        else
-        {
-            // announceCount < 0 indicates default announce count should be used
-            if (announceCount < 0)
-                announceCount = InitialAnnounceCount;
-            if (rr->AnnounceCount < (mDNSu8)announceCount)
-                rr->AnnounceCount = (mDNSu8)announceCount;
-        }
-
-        rr->SendNSECNow    = mDNSNULL;
-        InitializeLastAPTime(m, rr);
-    }
-}
-
-// ***************************************************************************
-// MARK: - Power Management (Sleep/Wake)
-
-mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m)
-{
-#ifndef IDLESLEEPCONTROL_DISABLED
-    mDNSBool allowSleep = mDNStrue;
-    char reason[128];
-
-    reason[0] = 0;
-
-    if (m->SystemSleepOnlyIfWakeOnLAN)
-    {
-        // Don't sleep if we are a proxy for any services
-        if (m->ProxyRecords)
-        {
-            allowSleep = mDNSfalse;
-            mDNS_snprintf(reason, sizeof(reason), "sleep proxy for %d records", m->ProxyRecords);
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_UpdateAllowSleep: Sleep disabled because we are proxying %d records", m->ProxyRecords);
-        }
-
-        if (allowSleep && mDNSCoreHaveAdvertisedMulticastServices(m))
-        {
-            // Scan the list of active interfaces
-            NetworkInterfaceInfo *intf;
-            for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-            {
-                if (intf->McastTxRx && !intf->Loopback && !intf->MustNotPreventSleep && !mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
-                {
-                    // Disallow sleep if this interface doesn't support NetWake
-                    if (!intf->NetWake)
-                    {
-                        allowSleep = mDNSfalse;
-                        mDNS_snprintf(reason, sizeof(reason), "%s does not support NetWake", intf->ifname);
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_UpdateAllowSleep: Sleep disabled because " PUB_S " does not support NetWake",
-                            intf->ifname);
-                        break;
-                    }
-
-                    // If the interface can be an in-NIC Proxy, we should check if it can accomodate all the records
-                    // that will be offloaded. If not, we should prevent sleep.
-                    // This check will be possible once the lower layers provide an API to query the space available for offloads on the NIC.
-                    {
-                        // Disallow sleep if there is no sleep proxy server
-                        const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL);
-                        if ( cr == mDNSNULL)
-                        {
-                            allowSleep = mDNSfalse;
-                            mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname);
-                            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_UpdateAllowSleep: Sleep disabled because " PUB_S
-                                " has no sleep proxy server", intf->ifname);
-                            break;
-                        }
-                        else if (m->SPSType != 0)
-                        {
-                            mDNSu32 mymetric = LocalSPSMetric(m);
-                            mDNSu32 metric   = SPSMetric(cr->resrec.rdata->u.name.c);
-                            if (metric >= mymetric)
-                            {
-                                allowSleep = mDNSfalse;
-                                mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname);
-                                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_UpdateAllowSleep: Sleep disabled because " PUB_S
-                                    " has no sleep proxy server with a better metric", intf->ifname);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Call the platform code to enable/disable sleep
-    mDNSPlatformSetAllowSleep(allowSleep, reason);
-#else
-    (void) m;
-#endif /* !defined(IDLESLEEPCONTROL_DISABLED) */
-}
-
-mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSu32 scopeid)
-{
-    // If it is not a uDNS record, check to see if the updateid is zero. "updateid" is cleared when we have
-    // sent the resource record on all the interfaces. If the update id is not zero, check to see if it is time
-    // to send.
-    if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) ||
-        m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
-    {
-        return mDNSfalse;
-    }
-
-    // If we have a pending registration for "scopeid", it is ok to send the update on that interface.
-    // If the scopeid is too big to check for validity, we don't check against updateIntID. When
-    // we successfully update on all the interfaces (with whatever set in "rr->updateIntID"), we clear
-    // updateid and we should have returned from above.
-    //
-    // Note: scopeid is the same as intf->InterfaceID. It is passed in so that we don't have to call the
-    // platform function to extract the value from "intf" every time.
-
-    if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) &&
-        (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID))
-        return mDNStrue;
-
-    return mDNSfalse;
-}
-
-mDNSexport void UpdateRMAC(mDNS *const m, void *context)
-{
-    IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ;
-    m->CurrentRecord = m->ResourceRecords;
-
-    if (!addrmap)
-    {
-        LogMsg("UpdateRMAC: Address mapping is NULL");
-        return;
-    }
-
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rr = m->CurrentRecord;
-        // If this is a non-sleep proxy keepalive record and the remote IP address matches, update the RData
-        if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
-        {
-            mDNSAddr raddr;
-            getKeepaliveRaddr(m, rr, &raddr);
-            if (mDNSSameAddress(&raddr, &addrmap->ipaddr))
-            {
-                // Update the MAC address only if it is not a zero MAC address
-                mDNSEthAddr macAddr;
-                mDNSu8 *ptr = GetValueForMACAddr((mDNSu8 *)(addrmap->ethaddr), (mDNSu8 *) (addrmap->ethaddr + sizeof(addrmap->ethaddr)), &macAddr);
-                if (ptr != mDNSNULL && !mDNSEthAddressIsZero(macAddr))
-                {
-                    UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr));
-                }
-            }
-        }
-        m->CurrentRecord = rr->next;
-    }
-
-    if (addrmap)
-        mDNSPlatformMemFree(addrmap);
-
-}
-
-mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr)
-{
-    mDNSu16 newrdlength;
-    mDNSAddr laddr = zeroAddr;
-    mDNSAddr raddr = zeroAddr;
-    mDNSEthAddr eth = zeroEthAddr;
-    mDNSIPPort lport = zeroIPPort;
-    mDNSIPPort rport = zeroIPPort;
-    mDNSu32 timeout = 0;
-    mDNSu32 seq = 0;
-    mDNSu32 ack = 0;
-    mDNSu16 win = 0;
-    UTF8str255 txt;
-    int rdsize;
-    RData *newrd;
-    mDNSTCPInfo mti;
-    mStatus ret;
-
-    // Note: If we fail to update the  DNS NULL  record with additional information in this function, it will be registered
-    // with the SPS like any other record. SPS will not send keepalives if it does not have additional information.
-    mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
-    if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport))
-    {
-        LogMsg("UpdateKeepaliveRData: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, &raddr, rport.NotAnInteger);
-        return mStatus_UnknownErr;
-    }
-
-    if (updateMac)
-    {
-        if (laddr.type == mDNSAddrType_IPv4)
-            newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d h=%#a d=%#a l=%u r=%u m=%s", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), ethAddr);
-        else
-            newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d H=%#a D=%#a l=%u r=%u m=%s", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr,  mDNSVal16(lport), mDNSVal16(rport), ethAddr);
-
-    }
-    else
-    {
-        // If this keepalive packet would be sent on a different interface than the current one that we are processing
-        // now, then we don't update the DNS NULL record. But we do not prevent it from registering with the SPS. When SPS sees
-        // this DNS NULL record, it does not send any keepalives as it does not have all the information
-        mDNSPlatformMemZero(&mti, sizeof (mDNSTCPInfo));
-        ret = mDNSPlatformRetrieveTCPInfo(&laddr, &lport, &raddr, &rport, &mti);
-        if (ret != mStatus_NoError)
-        {
-            LogMsg("mDNSPlatformRetrieveTCPInfo: mDNSPlatformRetrieveTCPInfo failed %d", ret);
-            return ret;
-        }
-        if ((intf != mDNSNULL) && (mti.IntfId != intf->InterfaceID))
-        {
-            LogInfo("mDNSPlatformRetrieveTCPInfo: InterfaceID mismatch mti.IntfId = %p InterfaceID = %p",  mti.IntfId, intf->InterfaceID);
-            return mStatus_BadParamErr;
-        }
-
-        if (laddr.type == mDNSAddrType_IPv4)
-            newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d h=%#a d=%#a l=%u r=%u m=%.6a s=%u a=%u w=%u", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), &eth, mti.seq, mti.ack, mti.window);
-        else
-            newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d H=%#a D=%#a l=%u r=%u m=%.6a s=%u a=%u w=%u", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), &eth, mti.seq, mti.ack, mti.window);
-    }
-
-    // Did we insert a null byte at the end ?
-    if (newrdlength == (sizeof(txt.c) - 1))
-    {
-        LogMsg("UpdateKeepaliveRData: could not allocate memory %s", ARDisplayString(m, rr));
-        return mStatus_NoMemoryErr;
-    }
-
-    // Include the length for the null byte at the end
-    txt.c[0] = newrdlength + 1;
-    // Account for the first length byte and the null byte at the end
-    newrdlength += 2;
-
-    rdsize = newrdlength > sizeof(RDataBody) ? newrdlength : sizeof(RDataBody);
-    newrd = (RData *) mDNSPlatformMemAllocate(sizeof(RData) - sizeof(RDataBody) + rdsize);
-    if (!newrd) { LogMsg("UpdateKeepaliveRData: ptr NULL"); return mStatus_NoMemoryErr; }
-
-    newrd->MaxRDLength = (mDNSu16) rdsize;
-    mDNSPlatformMemCopy(&newrd->u, txt.c, newrdlength);
-
-    //  If we are updating the record for the first time, rdata points to rdatastorage as the rdata memory
-    //  was allocated as part of the AuthRecord itself. We allocate memory when we update the AuthRecord.
-    //  If the resource record has data that we allocated in a previous pass (to update MAC address),
-    //  free that memory here before copying in the new data.
-    if ( rr->resrec.rdata != &rr->rdatastorage)
-    {
-        LogSPS("UpdateKeepaliveRData: Freed allocated memory for keep alive packet: %s ", ARDisplayString(m, rr));
-        mDNSPlatformMemFree(rr->resrec.rdata);
-    }
-    SetNewRData(&rr->resrec, newrd, newrdlength);    // Update our rdata
-
-    LogSPS("UpdateKeepaliveRData: successfully updated the record %s", ARDisplayString(m, rr));
-    return mStatus_NoError;
-}
-
-mDNSlocal void SendSPSRegistrationForOwner(mDNS *const m, NetworkInterfaceInfo *const intf, const mDNSOpaque16 id, const OwnerOptData *const owner)
-{
-    const int optspace = DNSOpt_Header_Space + DNSOpt_LeaseData_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC);
-    const int sps = intf->NextSPSAttempt / 3;
-    AuthRecord *rr;
-    mDNSOpaque16 msgid;
-    mDNSu32 scopeid;
-
-    scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue);
-    if (!intf->SPSAddr[sps].type)
-    {
-        intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
-        if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
-            m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
-        LogSPS("SendSPSRegistration: %s SPS %d (%d) %##s not yet resolved", intf->ifname, intf->NextSPSAttempt, sps, intf->NetWakeResolve[sps].qname.c);
-        goto exit;
-    }
-
-    // Mark our mDNS records (not unicast records) for transfer to SPS
-    if (mDNSOpaque16IsZero(id))
-    {
-        // We may have to register this record over multiple interfaces and we don't want to
-        // overwrite the id. We send the registration over interface X with id "IDX" and before
-        // we get a response, we overwrite with id "IDY" for interface Y and we won't accept responses
-        // for "IDX". Hence, we want to use the same ID across all interfaces.
-        //
-        // In the case of sleep proxy server transfering its records when it goes to sleep, the owner
-        // option check below will set the same ID across the records from the same owner. Records
-        // with different owner option gets different ID.
-        msgid = mDNS_NewMessageID(m);
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-        {
-            if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
-            {
-                if (rr->resrec.InterfaceID == intf->InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
-                {
-                    if (mDNSPlatformMemSame(owner, &rr->WakeUp, sizeof(*owner)))
-                    {
-                        rr->SendRNow = mDNSInterfaceMark;   // mark it now
-                        // When we are registering on the first interface, rr->updateid is zero in which case
-                        // initialize with the new ID. For subsequent interfaces, we want to use the same ID.
-                        // At the end, all the updates sent across all the interfaces with the same ID.
-                        if (mDNSOpaque16IsZero(rr->updateid))
-                            rr->updateid = msgid;
-                        else
-                            msgid = rr->updateid;
-                    }
-                }
-            }
-        }
-    }
-    else
-        msgid = id;
-
-    while (1)
-    {
-        mDNSu8 *p = m->omsg.data;
-        // To comply with RFC 2782, PutResourceRecord suppresses name compression for SRV records in unicast updates.
-        // For now we follow that same logic for SPS registrations too.
-        // If we decide to compress SRV records in SPS registrations in the future, we can achieve that by creating our
-        // initial DNSMessage with h.flags set to zero, and then update it to UpdateReqFlags right before sending the packet.
-        InitializeDNSMessage(&m->omsg.h, msgid, UpdateReqFlags);
-
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-            if (rr->SendRNow || mDNSUpdateOkToSend(m, rr, intf, scopeid))
-            {
-                if (mDNSPlatformMemSame(owner, &rr->WakeUp, sizeof(*owner)))
-                {
-                    mDNSu8 *newptr;
-                    const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.mDNS_numUpdates ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData) - optspace;
-
-                    // If we can't update the keepalive record, don't send it
-                    if (mDNS_KeepaliveRecord(&rr->resrec) && (UpdateKeepaliveRData(m, rr, intf, mDNSfalse, mDNSNULL) != mStatus_NoError))
-                    {
-                        if (scopeid < (sizeof(rr->updateIntID) * mDNSNBBY))
-                        {
-                            bit_clr_opaque64(rr->updateIntID, scopeid);
-                        }
-                        rr->SendRNow = mDNSNULL;
-                        continue;
-                    }
-
-                    if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                        rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the 'unique' bit so PutResourceRecord will set it
-                    newptr = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
-                    rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;       // Make sure to clear 'unique' bit back to normal state
-                    if (!newptr)
-                        LogSPS("SendSPSRegistration put %s FAILED %d/%d %s", intf->ifname, p - m->omsg.data, limit - m->omsg.data, ARDisplayString(m, rr));
-                    else
-                    {
-                        LogSPS("SendSPSRegistration put %s 0x%x 0x%x (updateid %d)  %s", intf->ifname, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(m->omsg.h.id), ARDisplayString(m, rr));
-                        rr->SendRNow       = mDNSNULL;
-                        rr->ThisAPInterval = mDNSPlatformOneSecond;
-                        rr->LastAPTime     = m->timenow;
-                        // should be initialized above
-                        if (mDNSOpaque16IsZero(rr->updateid)) LogMsg("SendSPSRegistration: ERROR!! rr %s updateid is zero", ARDisplayString(m, rr));
-                        if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-                            m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
-                        p = newptr;
-                    }
-                }
-            }
-
-        if (!m->omsg.h.mDNS_numUpdates) break;
-        else
-        {
-            AuthRecord opt;
-            mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-            opt.resrec.rrclass    = NormalMaxDNSMessageData;
-            opt.resrec.rdlength   = sizeof(rdataOPT) * 2;   // Two options in this OPT record
-            opt.resrec.rdestimate = sizeof(rdataOPT) * 2;
-            opt.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
-            opt.resrec.rdata->u.opt[0].optlen        = DNSOpt_LeaseData_Space - 4;
-            opt.resrec.rdata->u.opt[0].u.updatelease = DEFAULT_UPDATE_LEASE;
-            if (!owner->HMAC.l[0])                                          // If no owner data,
-                SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[1]);        // use our own interface information
-            else                                                            // otherwise, use the owner data we were given
-            {
-                opt.resrec.rdata->u.opt[1].u.owner = *owner;
-                opt.resrec.rdata->u.opt[1].opt     = kDNSOpt_Owner;
-                opt.resrec.rdata->u.opt[1].optlen  = DNSOpt_Owner_Space(&owner->HMAC, &owner->IMAC) - 4;
-            }
-            LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, &opt));
-            p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
-            if (!p)
-                LogMsg("SendSPSRegistration: Failed to put OPT record (%d updates) %s", m->omsg.h.mDNS_numUpdates, ARDisplayString(m, &opt));
-            else
-            {
-                mStatus err;
-                // Once we've attempted to register, we need to include our OWNER option in our packets when we re-awaken
-                m->SentSleepProxyRegistration = mDNStrue;
-
-                LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps,
-                       mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps]));
-                // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID;  // For simulating packet loss
-                err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSfalse);
-                if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err);
-                if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv4 && intf->NetWakeResolve[sps].ThisQInterval == -1)
-                {
-                    LogSPS("SendSPSRegistration %d %##s failed to send to IPv4 address; will try IPv6 instead", sps, intf->NetWakeResolve[sps].qname.c);
-                    intf->NetWakeResolve[sps].qtype = kDNSType_AAAA;
-                    mDNS_StartQuery_internal(m, &intf->NetWakeResolve[sps]);
-                    return;
-                }
-            }
-        }
-    }
-
-    intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond * 10;     // If successful, update NextSPSAttemptTime
-
-exit:
-    if (mDNSOpaque16IsZero(id) && intf->NextSPSAttempt < 8) intf->NextSPSAttempt++;
-}
-
-mDNSlocal mDNSBool RecordIsFirstOccurrenceOfOwner(mDNS *const m, const AuthRecord *const rr)
-{
-    AuthRecord *ar;
-    for (ar = m->ResourceRecords; ar && ar != rr; ar=ar->next)
-        if (mDNSPlatformMemSame(&rr->WakeUp, &ar->WakeUp, sizeof(rr->WakeUp))) return mDNSfalse;
-    return mDNStrue;
-}
-
-mDNSlocal void mDNSCoreStoreProxyRR(mDNS *const m, const mDNSInterfaceID InterfaceID, AuthRecord *const rr)
-{
-    AuthRecord *newRR = (AuthRecord *) mDNSPlatformMemAllocateClear(sizeof(*newRR));
-    if (newRR == mDNSNULL)
-    {
-        LogSPS("%s : could not allocate memory for new resource record", __func__);
-        return;
-    }
-
-    mDNS_SetupResourceRecord(newRR, mDNSNULL, InterfaceID, rr->resrec.rrtype,
-                             rr->resrec.rroriginalttl, rr->resrec.RecordType,
-                             rr->ARType, mDNSNULL, mDNSNULL);
-
-    AssignDomainName(&newRR->namestorage, &rr->namestorage);
-    newRR->resrec.rdlength = DomainNameLength(rr->resrec.name);
-    newRR->resrec.namehash = DomainNameHashValue(newRR->resrec.name);
-    newRR->resrec.rrclass  = rr->resrec.rrclass;
-
-    if (rr->resrec.rrtype == kDNSType_A)
-    {
-        newRR->resrec.rdata->u.ipv4 =  rr->resrec.rdata->u.ipv4;
-    }
-    else if (rr->resrec.rrtype == kDNSType_AAAA)
-    {
-        newRR->resrec.rdata->u.ipv6 = rr->resrec.rdata->u.ipv6;
-    }
-    SetNewRData(&newRR->resrec, mDNSNULL, 0);
-
-    // Insert the new node at the head of the list.
-    newRR->next        = m->SPSRRSet;
-    m->SPSRRSet        = newRR;
-    LogSPS("%s : Storing proxy record : %s ", __func__, ARDisplayString(m, rr));
-}
-
-// Some records are interface specific and some are not. The ones that are supposed to be registered
-// on multiple interfaces need to be initialized with all the valid interfaces on which it will be sent.
-// updateIntID bit field tells us on which interfaces we need to register this record. When we get an
-// ack from the sleep proxy server, we clear the interface bit. This way, we know when a record completes
-// registration on all the interfaces
-mDNSlocal void SPSInitRecordsBeforeUpdate(mDNS *const m, mDNSOpaque64 updateIntID, mDNSBool *WakeOnlyService)
-{
-    AuthRecord *ar;
-    LogSPS("SPSInitRecordsBeforeUpdate: UpdateIntID 0x%x 0x%x", updateIntID.l[1], updateIntID.l[0]);
-
-    *WakeOnlyService = mDNSfalse;
-
-    // Before we store the A and AAAA records that we are going to register with the sleep proxy,
-    // make sure that the old sleep proxy records are removed.
-    mDNSCoreFreeProxyRR(m);
-
-    // For records that are registered only on a specific interface, mark only that bit as it will
-    // never be registered on any other interface. For others, it should be sent on all interfaces.
-    for (ar = m->ResourceRecords; ar; ar=ar->next)
-    {
-        ar->updateIntID = zeroOpaque64;
-        ar->updateid    = zeroID;
-        if (AuthRecord_uDNS(ar))
-        {
-            continue;
-        }
-        if (ar->AuthFlags & AuthFlagsWakeOnly)
-        {
-            if (ar->resrec.RecordType == kDNSRecordTypeShared && ar->RequireGoodbye)
-            {
-                ar->ImmedAnswer = mDNSInterfaceMark;
-                *WakeOnlyService = mDNStrue;
-                continue;
-            }
-        }
-        if (!ar->resrec.InterfaceID)
-        {
-            LogSPS("Setting scopeid (ALL) 0x%x 0x%x for %s", updateIntID.l[1], updateIntID.l[0], ARDisplayString(m, ar));
-            ar->updateIntID = updateIntID;
-        }
-        else
-        {
-            // Filter records that belong to interfaces that we won't register the records on. UpdateIntID captures
-            // exactly this.
-            mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, ar->resrec.InterfaceID, mDNStrue);
-            if ((scopeid < (sizeof(updateIntID) * mDNSNBBY)) && bit_get_opaque64(updateIntID, scopeid))
-            {
-                bit_set_opaque64(ar->updateIntID, scopeid);
-                LogSPS("SPSInitRecordsBeforeUpdate: Setting scopeid(%d) 0x%x 0x%x for %s", scopeid, ar->updateIntID.l[1],
-                    ar->updateIntID.l[0], ARDisplayString(m, ar));
-            }
-            else
-            {
-                LogSPS("SPSInitRecordsBeforeUpdate: scopeid %d beyond range or not valid for SPS registration", scopeid);
-            }
-        }
-        // Store the A and AAAA records that we registered with the sleep proxy.
-        // We will use this to prevent spurious name conflicts that may occur when we wake up
-        if (ar->resrec.rrtype == kDNSType_A || ar->resrec.rrtype == kDNSType_AAAA)
-        {
-            mDNSCoreStoreProxyRR(m, ar->resrec.InterfaceID, ar);
-        }
-    }
-}
-
-mDNSlocal void SendSPSRegistration(mDNS *const m, NetworkInterfaceInfo *const intf, const mDNSOpaque16 id)
-{
-    AuthRecord *ar;
-    OwnerOptData owner = zeroOwner;
-
-    SendSPSRegistrationForOwner(m, intf, id, &owner);
-
-    for (ar = m->ResourceRecords; ar; ar=ar->next)
-    {
-        if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)) && RecordIsFirstOccurrenceOfOwner(m, ar))
-        {
-            owner = ar->WakeUp;
-            SendSPSRegistrationForOwner(m, intf, id, &owner);
-        }
-    }
-}
-
-// RetrySPSRegistrations is called from SendResponses, with the lock held
-mDNSlocal void RetrySPSRegistrations(mDNS *const m)
-{
-    AuthRecord *rr;
-    NetworkInterfaceInfo *intf;
-
-    // First make sure none of our interfaces' NextSPSAttemptTimes are inadvertently set to m->timenow + mDNSPlatformOneSecond * 10
-    for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10)
-            intf->NextSPSAttemptTime++;
-
-    // Retry any record registrations that are due
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-        if (!AuthRecord_uDNS(rr) && !mDNSOpaque16IsZero(rr->updateid) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-        {
-            for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-            {
-                // If we still have registrations pending on this interface, send it now
-                mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue);
-                if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) &&
-                    (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID))
-                {
-                    LogSPS("RetrySPSRegistrations: 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m, rr));
-                    SendSPSRegistration(m, intf, rr->updateid);
-                }
-            }
-        }
-
-    // For interfaces where we did an SPS registration attempt, increment intf->NextSPSAttempt
-    for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10 && intf->NextSPSAttempt < 8)
-            intf->NextSPSAttempt++;
-}
-
-mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    NetworkInterfaceInfo *intf = (NetworkInterfaceInfo *)question->QuestionContext;
-    int sps = (int)(question - intf->NetWakeResolve);
-    (void)m;            // Unused
-    LogSPS("NetWakeResolve: SPS: %d Add: %d %s", sps, AddRecord, RRDisplayString(m, answer));
-
-    if (!AddRecord) return;                                             // Don't care about REMOVE events
-    if (answer->rrtype != question->qtype) return;                      // Don't care about CNAMEs
-
-    // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address
-
-    if (answer->rrtype == kDNSType_SRV)
-    {
-        // 1. Got the SRV record; now look up the target host's IP address
-        mDNS_StopQuery(m, question);
-        intf->SPSPort[sps] = answer->rdata->u.srv.port;
-        AssignDomainName(&question->qname, &answer->rdata->u.srv.target);
-        question->qtype = kDNSType_A;
-        mDNS_StartQuery(m, question);
-    }
-    else if (answer->rrtype == kDNSType_A && answer->rdlength == sizeof(mDNSv4Addr))
-    {
-        // 2. Got an IPv4 address for the target host; record address and initiate an SPS registration if appropriate
-        mDNS_StopQuery(m, question);
-        question->ThisQInterval = -1;
-        intf->SPSAddr[sps].type = mDNSAddrType_IPv4;
-        intf->SPSAddr[sps].ip.v4 = answer->rdata->u.ipv4;
-        mDNS_Lock(m);
-        if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);    // If we're ready for this result, use it now
-        mDNS_Unlock(m);
-    }
-    else if (answer->rrtype == kDNSType_A && answer->rdlength == 0)
-    {
-        // 3. Got negative response -- target host apparently has IPv6 disabled -- so try looking up the target host's IPv4 address(es) instead
-        mDNS_StopQuery(m, question);
-        LogSPS("NetWakeResolve: SPS %d %##s has no IPv4 address, will try IPv6 instead", sps, question->qname.c);
-        question->qtype = kDNSType_AAAA;
-        mDNS_StartQuery(m, question);
-    }
-    else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == sizeof(mDNSv6Addr) && mDNSv6AddressIsLinkLocal(&answer->rdata->u.ipv6))
-    {
-        // 4. Got the target host's IPv6 link-local address; record address and initiate an SPS registration if appropriate
-        mDNS_StopQuery(m, question);
-        question->ThisQInterval = -1;
-        intf->SPSAddr[sps].type = mDNSAddrType_IPv6;
-        intf->SPSAddr[sps].ip.v6 = answer->rdata->u.ipv6;
-        mDNS_Lock(m);
-        if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);    // If we're ready for this result, use it now
-        mDNS_Unlock(m);
-    }
-}
-
-mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m)
-{
-    AuthRecord *rr;
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-        if (mDNS_KeepaliveRecord(&rr->resrec) || (rr->resrec.rrtype == kDNSType_SRV && !AuthRecord_uDNS(rr) && !mDNSSameIPPort(rr->resrec.rdata->u.srv.port, DiscardPort)))
-            return mDNStrue;
-    return mDNSfalse;
-}
-
-#define WAKE_ONLY_SERVICE 1
-#define AC_ONLY_SERVICE   2
-
-
-
-
-mDNSlocal void SendSleepGoodbyes(mDNS *const m, mDNSBool AllInterfaces, mDNSBool unicast)
-{
-    AuthRecord *rr;
-    m->SleepState = SleepState_Sleeping;
-
-    // If AllInterfaces is not set, the caller has already marked it appropriately
-    // on which interfaces this should be sent.
-    if (AllInterfaces)
-    {
-        NetworkInterfaceInfo *intf;
-        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        {
-            intf->SendGoodbyes = 1;
-        }
-    }
-    if (unicast)
-    {
-#ifndef UNICAST_DISABLED
-        SleepRecordRegistrations(m);    // If we have no SPS, need to deregister our uDNS records
-#endif /* UNICAST_DISABLED */
-    }
-
-    // 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->RequireGoodbye)
-            rr->ImmedAnswer = mDNSInterfaceMark;
-    SendResponses(m);
-}
-
-/*
- * This function attempts to detect if multiple interfaces are on the same subnet.
- * It makes this determination based only on the IPv4 Addresses and subnet masks.
- * IPv6 link local addresses that are configured by default on all interfaces make
- * it hard to make this determination
- *
- * The 'real' fix for this would be to send out multicast packets over one interface
- * and conclude that multiple interfaces are on the same subnet only if these packets
- * are seen on other interfaces on the same system
- */
-mDNSlocal mDNSBool skipSameSubnetRegistration(mDNS *const m, mDNSInterfaceID *regID, mDNSu32 count, mDNSInterfaceID intfid)
-{
-    NetworkInterfaceInfo *intf;
-    NetworkInterfaceInfo *newIntf;
-    mDNSu32 i;
-
-    for (newIntf = FirstInterfaceForID(m, intfid); newIntf; newIntf = newIntf->next)
-    {
-        if ((newIntf->InterfaceID != intfid) ||
-            (newIntf->ip.type     != mDNSAddrType_IPv4))
-        {
-            continue;
-        }
-        for ( i = 0; i < count; i++)
-        {
-            for (intf = FirstInterfaceForID(m, regID[i]); intf; intf = intf->next)
-            {
-                if ((intf->InterfaceID != regID[i]) ||
-                    (intf->ip.type     != mDNSAddrType_IPv4))
-                {
-                    continue;
-                }
-                if ((intf->ip.ip.v4.NotAnInteger & intf->mask.ip.v4.NotAnInteger) == (newIntf->ip.ip.v4.NotAnInteger & newIntf->mask.ip.v4.NotAnInteger))
-                {
-                    LogSPS("%s : Already registered for the same subnet (IPv4) for interface %s", __func__, intf->ifname);
-                    return (mDNStrue);
-                }
-            }
-        }
-    }
-    return (mDNSfalse);
-}
-
-mDNSlocal void DoKeepaliveCallbacks(mDNS *m)
-{
-    // Loop through the keepalive records and callback with an error
-    m->CurrentRecord = m->ResourceRecords;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *const rr = m->CurrentRecord;
-        if ((mDNS_KeepaliveRecord(&rr->resrec)) && (rr->resrec.RecordType != kDNSRecordTypeDeregistering))
-        {
-            LogSPS("DoKeepaliveCallbacks: Invoking the callback for %s", ARDisplayString(m, rr));
-            if (rr->RecordCallback)
-                rr->RecordCallback(m, rr, mStatus_BadStateErr);
-        }
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-// BeginSleepProcessing is called, with the lock held, from either mDNS_Execute or mDNSCoreMachineSleep
-mDNSlocal void BeginSleepProcessing(mDNS *const m)
-{
-    mDNSBool SendGoodbyes = mDNStrue;
-    mDNSBool WakeOnlyService  = mDNSfalse;
-    mDNSBool invokeKACallback = mDNStrue;
-    const CacheRecord *sps[3] = { mDNSNULL };
-    mDNSOpaque64 updateIntID = zeroOpaque64;
-    mDNSInterfaceID registeredIntfIDS[128] = { 0 };
-    mDNSu32 registeredCount = 0;
-    int skippedRegistrations = 0;
-
-    m->NextScheduledSPRetry = m->timenow;
-
-    // Clear out the SCDynamic entry that stores the external SPS information
-    mDNSPlatformClearSPSData();
-
-    if      (!m->SystemWakeOnLANEnabled) LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false");
-    else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services");
-    else    // If we have at least one advertised service
-    {
-        NetworkInterfaceInfo *intf;
-        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        {
-            mDNSBool skipFullSleepProxyRegistration = mDNSfalse;
-            // Intialize it to false. These values make sense only when SleepState is set to Sleeping.
-            intf->SendGoodbyes = 0;
-
-            // If it is not multicast capable, we could not have possibly discovered sleep proxy
-            // servers.
-            if (!intf->McastTxRx || mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
-            {
-                LogSPS("BeginSleepProcessing: %-6s Ignoring for registrations", intf->ifname);
-                continue;
-            }
-
-            // If we are not capable of WOMP, then don't register with sleep proxy.
-            //
-            // Note: If we are not NetWake capable, we don't browse for the sleep proxy server.
-            // We might find sleep proxy servers in the cache and start a resolve on them.
-            // But then if the interface goes away, we won't stop these questions because
-            // mDNS_DeactivateNetWake_internal assumes that a browse has been started for it
-            // to stop both the browse and resolve questions.
-            if (!intf->NetWake)
-            {
-                LogSPS("BeginSleepProcessing: %-6s not capable of magic packet wakeup", intf->ifname);
-                intf->SendGoodbyes = 1;
-                skippedRegistrations++;
-                continue;
-            }
-
-            // Check if we have already registered with a sleep proxy for this subnet.
-            // If so, then the subsequent in-NIC sleep proxy registration is limited to any keepalive records that belong
-            // to the interface.
-            if (skipSameSubnetRegistration(m, registeredIntfIDS, registeredCount, intf->InterfaceID))
-            {
-                LogSPS("%s : Skipping full sleep proxy registration on %s", __func__, intf->ifname);
-                skipFullSleepProxyRegistration = mDNStrue;
-            }
-
-            if (!skipFullSleepProxyRegistration)
-            {
-                FindSPSInCache(m, &intf->NetWakeBrowse, sps);
-                if (!sps[0]) LogSPS("BeginSleepProcessing: %-6s %#a No Sleep Proxy Server found (Next Browse Q in %d, interval %d)",
-                                    intf->ifname, &intf->ip, NextQSendTime(&intf->NetWakeBrowse) - m->timenow, intf->NetWakeBrowse.ThisQInterval);
-                else
-                {
-                    int i;
-                    mDNSu32 scopeid;
-                    SendGoodbyes = mDNSfalse;
-                    intf->NextSPSAttempt = 0;
-                    intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
-
-                    scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue);
-                    // Now we know for sure that we have to wait for registration to complete on this interface.
-                    if (scopeid < (sizeof(updateIntID) * mDNSNBBY))
-                        bit_set_opaque64(updateIntID, scopeid);
-
-                    // Don't need to set m->NextScheduledSPRetry here because we already set "m->NextScheduledSPRetry = m->timenow" above
-                    for (i=0; i<3; i++)
-                    {
-#if ForceAlerts
-                        if (intf->SPSAddr[i].type)
-                            LogFatalError("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type);
-                        if (intf->NetWakeResolve[i].ThisQInterval >= 0)
-                            LogFatalError("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval);
-#endif
-                        intf->SPSAddr[i].type = mDNSAddrType_None;
-                        if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]);
-                        intf->NetWakeResolve[i].ThisQInterval = -1;
-                        if (sps[i])
-                        {
-                            LogSPS("BeginSleepProcessing: %-6s Found Sleep Proxy Server %d TTL %d %s", intf->ifname, i, sps[i]->resrec.rroriginalttl, CRDisplayString(m, sps[i]));
-                            mDNS_SetupQuestion(&intf->NetWakeResolve[i], intf->InterfaceID, &sps[i]->resrec.rdata->u.name, kDNSType_SRV, NetWakeResolve, intf);
-                            intf->NetWakeResolve[i].ReturnIntermed = mDNStrue;
-                            mDNS_StartQuery_internal(m, &intf->NetWakeResolve[i]);
-
-                            // If we are registering with a Sleep Proxy for a new subnet, add it to our list
-                            registeredIntfIDS[registeredCount] = intf->InterfaceID;
-                            registeredCount++;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // If we have at least one interface on which we are registering with an external sleep proxy,
-    // initialize all the records appropriately.
-    if (!mDNSOpaque64IsZero(&updateIntID))
-        SPSInitRecordsBeforeUpdate(m, updateIntID, &WakeOnlyService);
-
-    // Call the applicaitons that registered a keepalive record to inform them that we failed to offload
-    // the records to a sleep proxy.
-    if (invokeKACallback)
-    {
-        LogSPS("BeginSleepProcessing: Did not register with an in-NIC proxy - invoking the callbacks for KA records");
-        DoKeepaliveCallbacks(m);
-    }
-
-    // SendSleepGoodbyes last two arguments control whether we send goodbyes on all
-    // interfaces and also deregister unicast registrations.
-    //
-    // - If there are no sleep proxy servers, then send goodbyes on all interfaces
-    //   for both multicast and unicast.
-    //
-    // - If we skipped registrations on some interfaces, then we have already marked
-    //   them appropriately above. We don't need to send goodbyes for unicast as
-    //   we have registered with at least one sleep proxy.
-    //
-    // - If we are not planning to send any goodbyes, then check for WakeOnlyServices.
-    //
-    // Note: If we are planning to send goodbyes, we mark the record with mDNSInterfaceAny
-    // and call SendResponses which inturn calls ShouldSendGoodbyesBeforeSleep which looks
-    // at WakeOnlyServices first.
-    if (SendGoodbyes)
-    {
-        LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server");
-        SendSleepGoodbyes(m, mDNStrue, mDNStrue);
-    }
-    else if (skippedRegistrations)
-    {
-        LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server on all interfaces");
-        SendSleepGoodbyes(m, mDNSfalse, mDNSfalse);
-    }
-    else if (WakeOnlyService)
-    {
-        // If we saw WakeOnly service above, send the goodbyes now.
-        LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyService");
-        SendResponses(m);
-    }
-}
-
-// 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.
-mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
-{
-    AuthRecord *rr;
-
-    LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, PUB_S " (old state %d) at %d", sleep ? "Sleeping" : "Waking", m->SleepState, m->timenow);
-
-    if (sleep && !m->SleepState)        // Going to sleep
-    {
-        mDNS_Lock(m);
-        // If we're going to sleep, need to stop advertising that we're a Sleep Proxy Server
-        if (m->SPSSocket)
-        {
-            mDNSu8 oldstate = m->SPSState;
-            mDNS_DropLockBeforeCallback();      // mDNS_DeregisterService expects to be called without the lock held, so we emulate that here
-            m->SPSState = 2;
-#ifndef SPC_DISABLED
-            if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords);
-#else
-            (void)oldstate;
-#endif
-            mDNS_ReclaimLockAfterCallback();
-        }
-#ifdef _LEGACY_NAT_TRAVERSAL_
-        if (m->SSDPSocket)
-        {
-            mDNSPlatformUDPClose(m->SSDPSocket);
-            m->SSDPSocket = mDNSNULL;
-        }
-#endif
-        m->SleepState = SleepState_Transferring;
-        if (m->SystemWakeOnLANEnabled && m->DelaySleep)
-        {
-            // If we just woke up moments ago, allow ten seconds for networking to stabilize before going back to sleep
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNSCoreMachineSleep: Re-sleeping immediately after waking; will delay for %d ticks",
-                m->DelaySleep - m->timenow);
-            m->SleepLimit = NonZeroTime(m->DelaySleep + mDNSPlatformOneSecond * 10);
-        }
-        else
-        {
-            m->DelaySleep = 0;
-            m->SleepLimit = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 10);
-            m->mDNSStats.Sleeps++;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            Querier_HandleSleep();
-#endif
-            BeginSleepProcessing(m);
-        }
-
-#ifndef UNICAST_DISABLED
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-        SuspendLLQs(m);
-#endif
-#endif
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,  "mDNSCoreMachineSleep: m->SleepState %d (" PUB_S ") seq %d", m->SleepState,
-            m->SleepState == SleepState_Transferring ? "Transferring" :
-            m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?", m->SleepSeqNum);
-        mDNS_Unlock(m);
-    }
-    else if (!sleep)        // Waking up
-    {
-        mDNSu32 slot;
-        CacheGroup *cg;
-        CacheRecord *cr;
-        NetworkInterfaceInfo *intf;
-        mDNSs32 currtime, diff;
-
-        mDNS_Lock(m);
-        // Reset SleepLimit back to 0 now that we're awake again.
-        m->SleepLimit = 0;
-
-        // If we were previously sleeping, but now we're not, increment m->SleepSeqNum to indicate that we're entering a new period of wakefulness
-        if (m->SleepState != SleepState_Awake)
-        {
-            m->SleepState = SleepState_Awake;
-            m->SleepSeqNum++;
-            if (m->SentSleepProxyRegistration)		// Include OWNER option in packets for 60 seconds after waking
-            {
-                m->SentSleepProxyRegistration = mDNSfalse;
-                m->AnnounceOwner = NonZeroTime(m->timenow + 60 * mDNSPlatformOneSecond);
-                LogInfo("mDNSCoreMachineSleep: Waking, Setting AnnounceOwner");
-            }
-            // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake)
-            // then we enforce a minimum delay of five seconds before we begin sleep processing.
-            // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc.,
-            // before we make our determination of whether there's a Sleep Proxy out there we should register with.
-            m->DelaySleep = NonZeroTime(m->timenow + kDarkWakeDelaySleep);
-        }
-
-        if (m->SPSState == 3)
-        {
-            m->SPSState = 0;
-            mDNSCoreBeSleepProxyServer_internal(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags);
-        }
-        m->mDNSStats.Wakes++;
-        // ... and the same for NextSPSAttempt
-        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        Querier_HandleWake();
-#endif
-        // Restart unicast and multicast queries
-        mDNSCoreRestartQueries(m);
-
-        // and reactivtate service registrations
-        m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNSCoreMachineSleep waking: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
-
-        // 2. Re-validate our cache records
-        currtime = mDNSPlatformUTC();
-
-        diff = currtime - m->TimeSlept;
-        FORALL_CACHERECORDS(slot, cg, cr)
-        {
-            // Temporary fix: For unicast cache records, look at how much time we slept.
-            // Adjust the RecvTime by the amount of time we slept so that we age the
-            // cache record appropriately. If it is expired already, purge. If there
-            // is a network change that happens after the wakeup, we might purge the
-            // cache anyways and this helps only in the case where there are no network
-            // changes across sleep/wakeup transition.
-            //
-            // Note: If there is a network/DNS server change that already happened and
-            // these cache entries are already refreshed and we are getting a delayed
-            // wake up notification, we might adjust the TimeRcvd based on the time slept
-            // now which can cause the cache to purge pre-maturely. As this is not a very
-            // common case, this should happen rarely.
-            if (!cr->resrec.InterfaceID)
-            {
-                if (diff > 0)
-                {
-                    mDNSu32 uTTL = RRUnadjustedTTL(cr->resrec.rroriginalttl);
-                    const mDNSs32 remain = uTTL - (m->timenow - cr->TimeRcvd) / mDNSPlatformOneSecond;
-
-                    // -if we have slept longer than the remaining TTL, purge and start fresh.
-                    // -if we have been sleeping for a long time, we could reduce TimeRcvd below by
-                    //  a sufficiently big value which could cause the value to go into the future
-                    //  because of the signed comparison of time. For this to happen, we should have been
-                    //  sleeping really long (~24 days). For now, we want to be conservative and flush even
-                    //  if we have slept for more than two days.
-
-                    if (diff >= remain || diff > (2 * 24 * 3600))
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNSCoreMachineSleep: " PRI_S ": Purging cache entry SleptTime %d, Remaining TTL %d",
-                            CRDisplayString(m, cr), diff, remain);
-                        mDNS_PurgeCacheResourceRecord(m, cr);
-                        continue;
-                    }
-                    cr->TimeRcvd -= (diff * mDNSPlatformOneSecond);
-                    if (m->timenow - (cr->TimeRcvd + ((mDNSs32)uTTL * mDNSPlatformOneSecond)) >= 0)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNSCoreMachineSleep: " PRI_S ": Purging after adjusting the remaining TTL %d by %d seconds",
-                            CRDisplayString(m, cr), remain, diff);
-                        mDNS_PurgeCacheResourceRecord(m, cr);
-                    }
-                    else
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNSCoreMachineSleep: " PRI_S ": Adjusted the remain ttl %u by %d seconds",
-                            CRDisplayString(m, cr), remain, diff);
-                    }
-                }
-            }
-            else
-            {
-                mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake);
-            }
-        }
-
-        // 3. Retrigger probing and announcing for all our authoritative records
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-        {
-            if (AuthRecord_uDNS(rr))
-            {
-                ActivateUnicastRegistration(m, rr);
-            }
-            else
-            {
-                mDNSCoreRestartRegistration(m, rr, -1);
-            }
-        }
-
-        // 4. Refresh NAT mappings
-        // We don't want to have to assume that all hardware can necessarily keep accurate
-        // track of passage of time while asleep, so on wake we refresh our NAT mappings.
-        // We typically wake up with no interfaces active, so there's no need to rush to try to find our external address.
-        // But if we do get a network configuration change, mDNSMacOSXNetworkChanged will call uDNS_SetupDNSConfig, which
-        // will call mDNS_SetPrimaryInterfaceInfo, which will call RecreateNATMappings to refresh them, potentially sooner
-        // than five seconds from now.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,  "mDNSCoreMachineSleep: recreating NAT mappings in 5 seconds");
-        RecreateNATMappings(m, mDNSPlatformOneSecond * 5);
-        mDNS_Unlock(m);
-    }
-}
-
-mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now)
-{
-    DNSQuestion *q;
-    AuthRecord *rr;
-    NetworkInterfaceInfo *intf;
-
-    mDNS_Lock(m);
-
-    if (m->DelaySleep) goto notready;
-
-    // If we've not hit the sleep limit time, and it's not time for our next retry, we can skip these checks
-    if (m->SleepLimit - now > 0 && m->NextScheduledSPRetry - now > 0) goto notready;
-
-    m->NextScheduledSPRetry = now + 0x40000000UL;
-
-    // See if we might need to retransmit any lost Sleep Proxy Registrations
-    for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        if (intf->NextSPSAttempt >= 0)
-        {
-            if (now - intf->NextSPSAttemptTime >= 0)
-            {
-                LogSPS("mDNSCoreReadyForSleep: retrying for %s SPS %d try %d",
-                       intf->ifname, intf->NextSPSAttempt/3, intf->NextSPSAttempt);
-                SendSPSRegistration(m, intf, zeroID);
-                // Don't need to "goto notready" here, because if we do still have record registrations
-                // that have not been acknowledged yet, we'll catch that in the record list scan below.
-            }
-            else
-            if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
-                m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
-        }
-
-    // Scan list of interfaces, and see if we're still waiting for any sleep proxy resolves to complete
-    for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-    {
-        int sps = (intf->NextSPSAttempt == 0) ? 0 : (intf->NextSPSAttempt-1)/3;
-        if (intf->NetWakeResolve[sps].ThisQInterval >= 0)
-        {
-            LogSPS("mDNSCoreReadyForSleep: waiting for SPS Resolve %s %##s (%s)",
-                   intf->ifname, intf->NetWakeResolve[sps].qname.c, DNSTypeName(intf->NetWakeResolve[sps].qtype));
-            goto spsnotready;
-        }
-    }
-
-    // Scan list of registered records
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-        if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
-            if (!mDNSOpaque64IsZero(&rr->updateIntID))
-            { LogSPS("mDNSCoreReadyForSleep: waiting for SPS updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto spsnotready; }
-
-    // Scan list of private LLQs, and make sure they've all completed their handshake with the server
-    for (q = m->Questions; q; q = q->next)
-        if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp)
-        {
-            LogSPS("mDNSCoreReadyForSleep: waiting for LLQ %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-            goto notready;
-        }
-
-    // Scan list of registered records
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-        if (AuthRecord_uDNS(rr))
-        {
-            if (rr->state == regState_Refresh && rr->tcp)
-            { LogSPS("mDNSCoreReadyForSleep: waiting for Record updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
-        }
-
-    mDNS_Unlock(m);
-    return mDNStrue;
-
-spsnotready:
-
-    // If we failed to complete sleep proxy registration within ten seconds, we give up on that
-    // and allow up to ten seconds more to complete wide-area deregistration instead
-    if (now - m->SleepLimit >= 0)
-    {
-        LogMsg("Failed to register with SPS, now sending goodbyes");
-
-        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-            if (intf->NetWakeBrowse.ThisQInterval >= 0)
-            {
-                LogSPS("ReadyForSleep mDNS_DeactivateNetWake %s %##s (%s)",
-                       intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
-                mDNS_DeactivateNetWake_internal(m, intf);
-            }
-
-        for (rr = m->ResourceRecords; rr; rr = rr->next)
-            if (!AuthRecord_uDNS(rr))
-                if (!mDNSOpaque64IsZero(&rr->updateIntID))
-                {
-                    LogSPS("ReadyForSleep clearing updateIntID 0x%x 0x%x (updateid %d) for %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m, rr));
-                    rr->updateIntID = zeroOpaque64;
-                }
-
-        // We'd really like to allow up to ten seconds more here,
-        // but if we don't respond to the sleep notification within 30 seconds
-        // we'll be put back to sleep forcibly without the chance to schedule the next maintenance wake.
-        // Right now we wait 16 sec after wake for all the interfaces to come up, then we wait up to 10 seconds
-        // more for SPS resolves and record registrations to complete, which puts us at 26 seconds.
-        // If we allow just one more second to send our goodbyes, that puts us at 27 seconds.
-        m->SleepLimit = now + mDNSPlatformOneSecond * 1;
-
-        SendSleepGoodbyes(m, mDNStrue, mDNStrue);
-    }
-
-notready:
-    mDNS_Unlock(m);
-    return mDNSfalse;
-}
-
-mDNSexport mDNSs32 mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now, mDNSNextWakeReason *outReason)
-{
-    AuthRecord *ar;
-
-    // Even when we have no wake-on-LAN-capable interfaces, or we failed to find a sleep proxy, or we have other
-    // failure scenarios, we still want to wake up in at most 120 minutes, to see if the network environment has changed.
-    // E.g. we might wake up and find no wireless network because the base station got rebooted just at that moment,
-    // and if that happens we don't want to just give up and go back to sleep and never try again.
-    mDNSs32 e = now + (120 * 60 * mDNSPlatformOneSecond);       // Sleep for at most 120 minutes
-    mDNSNextWakeReason reason = mDNSNextWakeReason_UpkeepWake;
-
-    NATTraversalInfo *nat;
-    for (nat = m->NATTraversals; nat; nat=nat->next)
-    {
-        if (nat->Protocol && nat->ExpiryTime && nat->ExpiryTime - now > mDNSPlatformOneSecond*4)
-        {
-            mDNSs32 t = nat->ExpiryTime - (nat->ExpiryTime - now) / 10;     // Wake up when 90% of the way to the expiry time
-            if ((e - t) > 0)
-            {
-                e = t;
-                reason = mDNSNextWakeReason_NATPortMappingRenewal;
-            }
-            LogSPS("ComputeWakeTime: %p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d Wake %5d",
-                   nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP",
-                   mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result,
-                   nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
-                   nat->retryInterval / mDNSPlatformOneSecond,
-                   nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
-                   (t - now) / mDNSPlatformOneSecond);
-        }
-    }
-    // This loop checks both the time we need to renew wide-area registrations,
-    // and the time we need to renew Sleep Proxy registrations
-    for (ar = m->ResourceRecords; ar; ar = ar->next)
-    {
-        if (ar->expire && ar->expire - now > mDNSPlatformOneSecond*4)
-        {
-            mDNSs32 t = ar->expire - (ar->expire - now) / 10;       // Wake up when 90% of the way to the expiry time
-            if ((e - t) > 0)
-            {
-                e = t;
-                reason = mDNSNextWakeReason_RecordRegistrationRenewal;
-            }
-            LogSPS("ComputeWakeTime: %p Int %7d Next %7d Expire %7d Wake %7d %s",
-                   ar, ar->ThisAPInterval / mDNSPlatformOneSecond,
-                   (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
-                   ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
-                   (t - now) / mDNSPlatformOneSecond, ARDisplayString(m, ar));
-        }
-    }
-    if (outReason)
-    {
-        *outReason = reason;
-    }
-    return(e - now);
-}
-
-// ***************************************************************************
-// MARK: - Packet Reception Functions
-
-#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 = (!InterfaceID) ? mDNSMaximumUnicastTTLSeconds : mDNSMaximumMulticastTTLSeconds;
-    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)
-    {
-        maxttl = kStaticCacheTTL;
-        for (i=0; i<query->h.numQuestions; i++)                     // For each question...
-        {
-            DNSQuestion q;
-            ptr = getQuestion(query, ptr, end, InterfaceID, &q);    // get the question...
-            if (!ptr) 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!"); return(mDNSNULL); }
-                    break;      // break out of the ResponseRecords loop, and go on to the next question
-                }
-            }
-        }
-
-        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 = PutResourceRecordTTL(response, responseptr, &response->h.numAnswers, &rr->resrec,
-                                             maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
-            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 = PutResourceRecordTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec,
-                                             maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
-            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(const AuthRecord *const our, const CacheRecord *const pkt)
-{
-    mDNSu8 ourdata[256], *ourptr = ourdata, *ourend;
-    mDNSu8 pktdata[256], *pktptr = pktdata, *pktend;
-    if (!our) { LogMsg("CompareRData ERROR: our is NULL"); return(+1); }
-    if (!pkt) { LogMsg("CompareRData ERROR: pkt is NULL"); return(+1); }
-
-#if defined(__clang_analyzer__)
-    // Get rid of analyzer warnings about ourptr and pktptr pointing to garbage after retruning from putRData().
-    // There are no clear indications from the analyzer of the cause of the supposed problem.
-    mDNSPlatformMemZero(ourdata, 1);
-    mDNSPlatformMemZero(pktdata, 1);
-#endif
-    ourend = putRData(mDNSNULL, ourdata, ourdata + sizeof(ourdata), &our->resrec);
-    pktend = putRData(mDNSNULL, pktdata, pktdata + sizeof(pktdata), &pkt->resrec);
-    while (ourptr < ourend && pktptr < pktend && *ourptr == *pktptr) { ourptr++; pktptr++; }
-    if (ourptr >= ourend && pktptr >= pktend) return(0);            // If data identical, not a conflict
-
-    if (ourptr >= ourend) return(-1);                               // Our data ran out first; We lost
-    if (pktptr >= pktend) return(+1);                               // Packet data ran out first; We won
-    if (*pktptr > *ourptr) return(-1);                              // Our data is numerically lower; We lost
-    if (*pktptr < *ourptr) return(+1);                              // Packet data is numerically lower; We won
-
-    LogMsg("CompareRData ERROR: Invalid state");
-    return(-1);
-}
-
-mDNSlocal mDNSBool PacketRecordMatches(const AuthRecord *const rr, const CacheRecord *const pktrr, const AuthRecord *const master)
-{
-    if (IdenticalResourceRecord(&rr->resrec, &pktrr->resrec))
-    {
-        const AuthRecord *r2 = rr;
-        while (r2->DependentOn) r2 = r2->DependentOn;
-        if (r2 == master) return(mDNStrue);
-    }
-    return(mDNSfalse);
-}
-
-// 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 (PacketRecordMatches(r1, pktrr, master)) return(mDNStrue);
-    }
-    for (r1 = m->DuplicateRecords; r1; r1=r1->next)
-    {
-        if (PacketRecordMatches(r1, pktrr, 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 uintptr_t 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))
-        {
-            return(rr->RRSet ? rr->RRSet : (uintptr_t)rr);
-        }
-    }
-    return(0);
-}
-
-// 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)
-{
-    // 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);
-    else
-    {
-        // If the pktrr matches a member of ourset, not a conflict
-        const uintptr_t ourset = our->RRSet ? our->RRSet : (uintptr_t)our;
-        const uintptr_t pktset = FindRRSet(m, pktrr);
-        if (pktset == ourset) return(mDNSfalse);
-
-        // For records we're proxying, where we don't know the full
-        // relationship between the records, having any matching record
-        // in our AuthRecords list is sufficient evidence of non-conflict
-        if (our->WakeUp.HMAC.l[0] && pktset) return(mDNSfalse);
-    }
-
-    // Okay, this is a conflict
-    return(mDNStrue);
-}
-
-// Compare local TSR value with TSR value in packet.
-// Return +1 if our tsr_value is newer(we win).
-// Otherwise return -1(we lose).
-mDNSlocal int CompareTSRValue(const ResourceRecord *const ourTSR, const ResourceRecord *const pktTSR)
-{
-    int result = 1;
-    // tsr_value stored locally is absolute time.
-    mDNSs32 ourTimeOfReceipt = ourTSR->rdata->u.tsr_value;
-    // tsr_value in packet is relative time.
-    mDNSs32 pktTimeSinceReceived = pktTSR->rdata->u.tsr_value;
-    mDNSs32 pktTimeOfReceipt;
-
-    // out of range tsr_value in pkt
-    if (pktTimeSinceReceived < 0 || pktTimeSinceReceived > MaxTimeSinceReceived)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Out of range pktTimeSinceReceived %d in Pkt record", pktTimeSinceReceived);
-        pktTimeSinceReceived = MaxTimeSinceReceived;
-    }
-    pktTimeOfReceipt = mDNSPlatformContinuousTimeSeconds() - pktTimeSinceReceived;
-    // tsr in probe is newer, equal counted as we lose.
-    if (ourTimeOfReceipt <= pktTimeOfReceipt)
-    {
-        result = -1;
-    }
-    LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "CompareTSRValue: Pkt Record - name: " PRI_DM_NAME
-              ", interface id: %p, pktTimeOfReceipt: %d", DM_NAME_PARAM(pktTSR->name), pktTSR->InterfaceID, pktTimeOfReceipt);
-    LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "CompareTSRValue: Our Record - conflict: " PUB_S
-              ", interface id: %p, ourTimeOfReceipt: %d", result ? "lose" : "win", ourTSR->InterfaceID, ourTimeOfReceipt);
-    return result;
-}
-
-// If we don't have TSR record or probe doesn't have TSR record that has the same name with auth record, return 0;
-// If both have TSR, then compare tsr_value in our TSR AuthRecord and the TSR record in probe.
-// Return +1 if both have TSR and we win.
-// Return -1 if both have TSR and we lose.
-mDNSlocal int CheckTSR(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
-                       const DNSQuestion *const q, const AuthRecord *const ar)
-{
-    int i;
-    int result = 0;
-    const mDNSu8 *ptr = LocateAuthorities(query, end);
-    const AuthRecord *ourTSR = mDNSGetTSRRecord(m, ar);
-
-    if (ourTSR == mDNSNULL)
-    {
-        goto done;
-    }
-    for (i = 0; i < query->h.numAuthorities && ptr; i++)
-    {
-        ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        if (!ptr)
-        {
-            break;
-        }
-        // Packet has TSR.
-        if (m->rec.r.resrec.rrtype == kDNSType_TSR && ResourceRecordNameClassInterfaceMatch(&m->rec.r.resrec, &ar->resrec))
-        {
-            result = CompareTSRValue(&ourTSR->resrec, &m->rec.r.resrec);
-            mDNSCoreResetRecord(m);
-            goto done;
-        }
-        mDNSCoreResetRecord(m);
-    }
-
-done:
-    return result;
-}
-
-// 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;
-
-    for (i = 0; i < query->h.numAuthorities; i++)
-    {
-        ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        if (!ptr) break;
-        if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && CacheRecordAnswersQuestion(&m->rec.r, q))
-        {
-            FoundUpdate = mDNStrue;
-            if (PacketRRConflict(m, our, &m->rec.r))
-            {
-                int result = 0;
-
-                if (!result) result = (int)our->resrec.rrclass - (int)m->rec.r.resrec.rrclass;
-                if (!result) result = (int)our->resrec.rrtype  - (int)m->rec.r.resrec.rrtype;
-                if (!result) result = CompareRData(our, &m->rec.r);
-                if (result)
-                {
-                    const char *const msg = (result < 0) ? "lost:" : (result > 0) ? "won: " : "tie: ";
-                    LogMsg("ResolveSimultaneousProbe: %p Pkt Record:        %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
-                    LogMsg("ResolveSimultaneousProbe: %p Our Record %d %s %08lX %s", our->resrec.InterfaceID, our->ProbeCount, msg, our->resrec.rdatahash, ARDisplayString(m, our));
-                    // When conflict happen, look for TSR and compare.
-                    mDNSCoreResetRecord(m);
-                    int tsrResult = CheckTSR(m, query, end, q, our);
-                    // Overwrite result if both has TSR
-                    if (tsrResult)
-                    {
-                        result = tsrResult;
-                    }
-                }
-                // If we lost the tie-break for simultaneous probes, we don't immediately give up, because we might be seeing stale packets on the network.
-                // Instead we pause for one second, to give the other host (if real) a chance to establish its name, and then try probing again.
-                // If there really is another live host out there with the same name, it will answer our probes and we'll then rename.
-                if (result < 0)
-                {
-                    m->SuppressProbes   = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
-                    our->ProbeCount     = DefaultProbeCountForTypeUnique;
-                    our->AnnounceCount  = InitialAnnounceCount;
-                    InitializeLastAPTime(m, our);
-                    goto exit;
-                }
-            }
-#if 0
-            else
-            {
-                LogMsg("ResolveSimultaneousProbe: %p Pkt Record:        %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
-                LogMsg("ResolveSimultaneousProbe: %p Our Record %d ign:  %08lX %s", our->resrec.InterfaceID, our->ProbeCount, our->resrec.rdatahash, ARDisplayString(m, our));
-            }
-#endif
-        }
-        mDNSCoreResetRecord(m);
-    }
-    if (!FoundUpdate)
-        LogInfo("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
-exit:
-    mDNSCoreResetRecord(m);
-}
-
-// Return mDNStrue when the RR is currently tentative.
-mDNSlocal mDNSBool CheckAndResetRRTentative(mDNS *const m, AuthRecord *const rr)
-{
-    if (rr->Tentative)
-    {
-        if (m->timenow - rr->TentativeSetTime > MaxTentativeSeconds * mDNSPlatformOneSecond)
-        {
-            rr->Tentative = mDNSfalse;
-        }
-    }
-    return rr->Tentative;
-}
-
-// Return mDNStrue if the query is a probe and has an identical record in the authority section.
-// Otherwise return mDNSfalse.
-mDNSlocal mDNSBool ProbeHasIdenticalRR(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
-                                       const DNSQuestion *const q, const AuthRecord *const our)
-{
-    int i;
-    const mDNSu8 *ptr = LocateAuthorities(query, end);
-    mDNSBool result = mDNSfalse;
-
-    // This is not a probe
-    if (!ptr || query->h.numAuthorities == 0)
-    {
-        goto done;
-    }
-    for (i = 0; i < query->h.numAuthorities && ptr; i++)
-    {
-        ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        if (!ptr)
-        {
-            break;
-        }
-        if (m->rec.r.resrec.rrtype != kDNSType_TSR && IdenticalSameNameRecord(&m->rec.r.resrec, &our->resrec))
-        {
-            mDNSCoreResetRecord(m);
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Found identical rr in probe: " PRI_S, CRDisplayString(m, &m->rec.r));
-            result = mDNStrue;
-            goto done;
-        }
-        mDNSCoreResetRecord(m);
-    }
-done:
-    return result;
-}
-
-// Step1: Compare tsr_value in our TSR AuthRecord and the TSR record in probe, skip conflict check if there is no TSR record;
-// Step2: Check whether resource records in probe confict with our auth record;
-// Return mDNStrue if the tsr_value in probe wins, otherwise return mDNSfalse.
-mDNSlocal mDNSBool ProbeRRConflictAndTSRValueWin(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
-                                                 const DNSQuestion *const q, const AuthRecord *const our)
-{
-    int i;
-    const mDNSu8 *ptr = LocateAuthorities(query, end);
-    mDNSBool conflict = mDNSfalse;
-    mDNSBool probeTSRWin = mDNSfalse;
-
-    // This is not a probe
-    if (ptr == mDNSNULL || query->h.numAuthorities == 0)
-    {
-        goto done;
-    }
-    if (CheckTSR(m, query, end, q, our) < 0)
-    {
-        probeTSRWin = mDNStrue;
-    }
-    else
-    {
-        goto done;
-    }
-    for (i = 0; i < query->h.numAuthorities && ptr; i++)
-    {
-        ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        if (ptr == mDNSNULL)
-        {
-            break;
-        }
-        if (m->rec.r.resrec.rrtype != kDNSType_TSR && our->resrec.rrtype != kDNSType_TSR
-            && PacketRRMatchesSignature(&m->rec.r, our) && !IdenticalSameNameRecord(&m->rec.r.resrec, &our->resrec)
-            && (our->resrec.RecordType & kDNSRecordTypeUniqueMask))
-        {
-            mDNSCoreResetRecord(m);
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "pkt ar on interface  %p rrtype: " PRI_S ", name: " PRI_DM_NAME PRI_S,
-                      q->InterfaceID, DNSTypeName(m->rec.r.resrec.rrtype), DM_NAME_PARAM(m->rec.r.resrec.name), CRDisplayString(m, &m->rec.r));
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Conflict with our ar %p rrtype: " PRI_S ", name: " PRI_DM_NAME PRI_S,
-                      our->resrec.InterfaceID, DNSTypeName(our->resrec.rrtype), DM_NAME_PARAM(our->resrec.name), ARDisplayString(m, our));
-            conflict = mDNStrue;
-            break;
-        }
-        mDNSCoreResetRecord(m);
-    }
-done:
-    return (conflict && probeTSRWin);
-}
-
-mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr)
-{
-    CacheGroup *cg = CacheGroupForRecord(m, pktrr);
-    CacheRecord *rr;
-    mDNSBool match;
-    for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-    {
-        if (!pktrr->InterfaceID)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            match = (pktrr->dnsservice == rr->resrec.dnsservice) ? mDNStrue : mDNSfalse;
-#else
-            const mDNSu32 id1 = (pktrr->rDNSServer ? pktrr->rDNSServer->resGroupID : 0);
-            const mDNSu32 id2 = (rr->resrec.rDNSServer ? rr->resrec.rDNSServer->resGroupID : 0);
-            match = (id1 == id2);
-#endif
-        }
-        else match = (pktrr->InterfaceID == rr->resrec.InterfaceID);
-
-        if (match && IdenticalSameNameRecord(pktrr, &rr->resrec)) break;
-    }
-    return(rr);
-}
-mDNSlocal void DeregisterProxyRecord(mDNS *const m, AuthRecord *const rr)
-{
-    rr->WakeUp.HMAC    = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
-    rr->RequireGoodbye = mDNSfalse;   // and we don't want to send goodbye for it
-    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-    SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID);
-}
-
-mDNSlocal void ClearKeepaliveProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist, const mDNSInterfaceID InterfaceID)
-{
-    if (m->CurrentRecord)
-        LogMsg("ClearKeepaliveProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = thelist;
-
-    // Normally, the RDATA of the keepalive record will be different each time and hence we always
-    // clean up the keepalive record.
-    while (m->CurrentRecord)
-    {
-        AuthRecord *const rr = m->CurrentRecord;
-        if (InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC))
-        {
-            if (mDNS_KeepaliveRecord(&m->rec.r.resrec))
-            {
-                LogSPS("ClearKeepaliveProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s",
-                       m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
-                DeregisterProxyRecord(m, rr);
-            }
-        }
-        // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-        // new records could have been added to the end of the list as a result of that call.
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-// Called from mDNSCoreReceiveUpdate when we get a sleep proxy registration request,
-// to check our lists and discard any stale duplicates of this record we already have
-mDNSlocal void ClearIdenticalProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist)
-{
-    if (m->CurrentRecord)
-        LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = thelist;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *const rr = m->CurrentRecord;
-        if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC))
-            if (IdenticalResourceRecord(&rr->resrec, &m->rec.r.resrec))
-            {
-                LogSPS("ClearIdenticalProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s",
-                       m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
-                DeregisterProxyRecord(m, rr);
-            }
-        // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-        // new records could have been added to the end of the list as a result of that call.
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-// Called from ProcessQuery when we get an mDNS packet with an owner record in it
-mDNSlocal void ClearProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist)
-{
-    if (m->CurrentRecord)
-        LogMsg("ClearProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = thelist;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *const rr = m->CurrentRecord;
-        if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC))
-            if (owner->seq != rr->WakeUp.seq || m->timenow - rr->TimeRcvd > mDNSPlatformOneSecond * 60)
-            {
-                if (rr->AddressProxy.type == mDNSAddrType_IPv6)
-                {
-                    // We don't do this here because we know that the host is waking up at this point, so we don't send
-                    // Unsolicited Neighbor Advertisements -- even Neighbor Advertisements agreeing with what the host should be
-                    // saying itself -- because it can cause some IPv6 stacks to falsely conclude that there's an address conflict.
-                    #if defined(MDNS_USE_Unsolicited_Neighbor_Advertisements) && MDNS_USE_Unsolicited_Neighbor_Advertisements
-                    LogSPS("NDP Announcement -- Releasing traffic for H-MAC %.6a I-MAC %.6a %s",
-                           &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
-                    SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, &rr->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth);
-                    #endif
-                }
-                LogSPS("ClearProxyRecords: Removing %3d AC %2d %02X H-MAC %.6a I-MAC %.6a %d %d %s",
-                       m->ProxyRecords, rr->AnnounceCount, rr->resrec.RecordType,
-                       &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
-                if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) rr->resrec.RecordType = kDNSRecordTypeShared;
-                rr->WakeUp.HMAC = zeroEthAddr;  // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
-                rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it, since real host is now back and functional
-                mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID);
-            }
-        // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-        // new records could have been added to the end of the list as a result of that call.
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-// 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,
-                               mDNSBool QueryWasLocalUnicast, DNSMessage *const response)
-{
-    const mDNSBool FromLocalSubnet   = mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
-    AuthRecord   *ResponseRecords    = mDNSNULL;
-    AuthRecord  **nrp                = &ResponseRecords;
-
-#if POOF_ENABLED
-    mDNSBool    notD2D = !mDNSPlatformInterfaceIsD2D(InterfaceID);  // We don't run the POOF algorithm on D2D interfaces.
-    CacheRecord  *ExpectedAnswers    = mDNSNULL;            // Records in our cache we expect to see updated
-    CacheRecord **eap                = &ExpectedAnswers;
-#endif // POOF_ENABLED
-
-    DNSQuestion  *DupQuestions       = mDNSNULL;            // Our questions that are identical to questions in this packet
-    DNSQuestion **dqp                = &DupQuestions;
-    mDNSs32 delayresponse      = 0;
-    mDNSBool SendLegacyResponse = mDNSfalse;
-    const mDNSu8 *ptr;
-    mDNSu8       *responseptr        = mDNSNULL;
-    AuthRecord   *rr;
-    int i;
-
-    // ***
-    // *** 1. Look in Additional Section for an OPT record
-    // ***
-    ptr = LocateOptRR(query, end, DNSOpt_OwnerData_ID_Space);
-    if (ptr)
-    {
-        ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &m->rec);
-        if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT)
-        {
-            const rdataOPT *opt;
-            const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
-            // Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently
-            // delete all our own AuthRecords (which are identified by having zero MAC tags on them).
-            for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++)
-                if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0])
-                {
-                    ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords);
-                    ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords);
-                }
-        }
-        mDNSCoreResetRecord(m);
-    }
-
-    // ***
-    // *** 2. Parse Question Section and mark potential answers
-    // ***
-    ptr = query->data;
-    for (i=0; i<query->h.numQuestions; i++)                     // For each question...
-    {
-        mDNSBool QuestionNeedsMulticastResponse;
-        int NumAnswersForThisQuestion = 0;
-        AuthRecord *NSECAnswer = mDNSNULL;
-        DNSQuestion pktq, *q;
-        ptr = getQuestion(query, ptr, end, InterfaceID, &pktq); // get the question...
-        if (!ptr) 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);
-
-        if (pktq.qclass & kDNSQClass_UnicastResponse)
-            m->mDNSStats.UnicastBitInQueries++;
-        else
-            m->mDNSStats.NormalQueries++;
-
-        // 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 %s", ARDisplayString(m, m->CurrentRecord));
-        m->CurrentRecord = m->ResourceRecords;
-        while (m->CurrentRecord)
-        {
-            rr = m->CurrentRecord;
-            m->CurrentRecord = rr->next;
-            if (AnyTypeRecordAnswersQuestion(rr, &pktq) && (QueryWasMulticast || QueryWasLocalUnicast || rr->AllowRemoteQuery)
-                && !CheckAndResetRRTentative(m, rr))
-            {
-                m->mDNSStats.MatchingAnswersForQueries++;
-
-                const mDNSBool typeMatches = RRTypeAnswersQuestionType(&rr->resrec, pktq.qtype, kRRTypeAnswersQuestionTypeFlagsNone);
-                if (typeMatches)
-                {
-                    if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-                        ResolveSimultaneousProbe(m, query, end, &pktq, rr);
-                    else if (ProbeHasIdenticalRR(m, query, end, &pktq, rr))
-                    {
-                        // Don't include this rr in response if this is a probe, and it's authority section has an identical RR.
-                        continue;
-                    }
-                    else if (ProbeRRConflictAndTSRValueWin(m, query, end, &pktq, rr))
-                    {
-                        // Set this rr as tentative if it's conflicting with the records in probe's authority section and we lose in TSR comparison.
-                        // Don't include this rr in response in this case.
-                        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
-                                  "set tentative for " PRI_DM_NAME " type " PUB_S " on interface id: %p due to TSR lose",
-                                  DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype), rr->resrec.InterfaceID);
-                        rr->Tentative = mDNStrue;
-                        rr->TentativeSetTime = m->timenow;
-                    }
-                    else if (ResourceRecordIsValidAnswer(rr))
-                    {
-                        NumAnswersForThisQuestion++;
-
-                        // Note: We should check here if this is a probe-type query, and if so, generate an immediate
-                        // unicast answer back to the source, because timeliness in answering probes is important.
-
-                        // Notes:
-                        // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast)
-                        // NR_AnswerTo == NR_AnswerUnicast   means "answer via delayed unicast" (to modern querier; may promote to multicast instead)
-                        // NR_AnswerTo == NR_AnswerMulticast means "definitely answer via multicast" (can't downgrade to unicast later)
-                        // If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set,
-                        // but the multicast querier is not on a matching subnet (e.g. because of overlaid subnets on one link)
-                        // then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source)
-                        if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery))
-                        {
-                            // 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 may multicast it.
-                            // This is to guard against the case where someone blasts us with queries as fast as they can.
-                            if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)mDNSPlatformOneSecond ||
-                                (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
-                                rr->NR_AnswerTo = NR_AnswerMulticast;
-                        }
-                        else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : NR_AnswerUnicast;
-                    }
-                }
-                else if ((rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && ResourceRecordIsValidAnswer(rr))
-                {
-                    // If we don't have any answers for this question, but we do own another record with the same name,
-                    // then we'll want to mark it to generate an NSEC record on this interface
-                    if (!NSECAnswer) NSECAnswer = rr;
-                }
-            }
-        }
-
-        if (NumAnswersForThisQuestion == 0 && NSECAnswer)
-        {
-            NumAnswersForThisQuestion++;
-            NSECAnswer->SendNSECNow = InterfaceID;
-            m->NextScheduledResponse = m->timenow;
-        }
-
-        // 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
-
-        if (query->h.flags.b[0] & kDNSFlag0_TC)
-            m->mDNSStats.KnownAnswerMultiplePkts++;
-        // We only do the following accelerated cache expiration and duplicate question suppression processing
-        // for non-truncated 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.
-        // For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent
-        // known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets.
-        if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC))
-        {
-#if POOF_ENABLED
-            if (notD2D)
-            {
-                CacheGroup *cg = CacheGroupForName(m, pktq.qnamehash, &pktq.qname);
-                CacheRecord *cr;
-
-                // 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 (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-                {
-                    if (SameNameCacheRecordAnswersQuestion(cr, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
-                    {
-                        if (!cr->NextInKAList && eap != &cr->NextInKAList)
-                        {
-                            *eap = cr;
-                            eap = &cr->NextInKAList;
-                        }
-                    }
-                }
-            }
-#endif // POOF_ENABLED
-
-            // 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.
-            for (q = m->Questions; q; q=q->next)
-            {
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-                if (QuestionSendsMDNSQueriesViaUnicast(q))
-                {
-                    continue;
-                }
-#endif
-                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; }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // ***
-    // *** 3. 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
-
-    // ***
-    // *** 4. Add additional records
-    // ***
-    AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
-
-    // ***
-    // *** 5. 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...
-        CacheRecord *ourcacherr;
-        ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec);
-        if (!ptr) goto exit;
-        if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative)
-        {
-            // See if this Known-Answer suppresses any of our currently planned answers
-            for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-            {
-                if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&m->rec.r, rr))
-                {
-                    m->mDNSStats.KnownAnswerSuppressions++;
-                    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(&m->rec.r, rr))
-                {
-                    if (srcaddr->type == mDNSAddrType_IPv4)
-                    {
-                        if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zerov4Addr;
-                    }
-                    else if (srcaddr->type == mDNSAddrType_IPv6)
-                    {
-                        if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr;
-                    }
-                    if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester))
-                    {
-                        m->mDNSStats.KnownAnswerSuppressions++;
-                        rr->ImmedAnswer  = mDNSNULL;
-                        rr->ImmedUnicast = mDNSfalse;
-    #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-                        LogMsg("Suppressed after%4d: %s", m->timenow - rr->ImmedAnswerMarkTime, ARDisplayString(m, rr));
-    #endif
-                    }
-                }
-            }
-
-            ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec);
-
-#if POOF_ENABLED
-            if (notD2D)
-            {
-                // Having built our ExpectedAnswers list from the questions in this packet, we then remove
-                // any records that are suppressed by the Known Answer list in this packet.
-                eap = &ExpectedAnswers;
-                while (*eap)
-                {
-                    CacheRecord *cr = *eap;
-                    if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec))
-                    { *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; }
-                    else eap = &cr->NextInKAList;
-                }
-            }
-#endif // POOF_ENABLED
-
-            // 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 (CacheRecordAnswersQuestion(&m->rec.r, q))
-                    { *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; }
-                    else dqp = &q->NextInDQList;
-                }
-            }
-        }
-        mDNSCoreResetRecord(m);
-    }
-
-    // ***
-    // *** 6. 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; }
-
-    // ***
-    // *** 7. 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;     // Send modern multicast response
-            mDNSBool SendUnicastResponse   = mDNSfalse;     // Send modern unicast response (not legacy unicast response)
-
-            // If it's been one TTL/4 since we multicast this, then send a multicast response
-            // for conflict detection, etc.
-            if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)TicksTTL(rr)/4)
-            {
-                SendMulticastResponse = mDNStrue;
-                // If this record was marked for modern (delayed) unicast response, then mark it as promoted to
-                // multicast response instead (don't want to end up ALSO setting SendUnicastResponse in the check below).
-                // If this record was marked for legacy unicast response, then we mustn't change the NR_AnswerTo value.
-                if (rr->NR_AnswerTo == NR_AnswerUnicast)
-                {
-                    m->mDNSStats.UnicastDemotedToMulticast++;
-                    rr->NR_AnswerTo = NR_AnswerMulticast;
-                }
-            }
-
-            // If the client insists on a multicast response, then we'd better send one
-            if      (rr->NR_AnswerTo == NR_AnswerMulticast)
-            {
-                m->mDNSStats.MulticastResponses++;
-                SendMulticastResponse = mDNStrue;
-            }
-            else if (rr->NR_AnswerTo == NR_AnswerUnicast)
-            {
-                m->mDNSStats.UnicastResponses++;
-                SendUnicastResponse   = mDNStrue;
-            }
-            else if (rr->NR_AnswerTo)
-            {
-                SendLegacyResponse    = mDNStrue;
-            }
-
-            if (SendMulticastResponse || SendUnicastResponse)
-            {
-#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-                rr->ImmedAnswerMarkTime = m->timenow;
-#endif
-                m->NextScheduledResponse = m->timenow;
-                // 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;
-                else
-                {
-                    rr->ImmedAnswer = InterfaceID;          // Record interface to send it on
-                    if (SendUnicastResponse) rr->ImmedUnicast = mDNStrue;
-                    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 TC flag is set, it means we should expect that additional known answers may be coming in another packet,
-            // so we allow roughly half a second before deciding to reply (we've observed inter-packet delays of 100-200ms on 802.11)
-            // else, if record is a shared one, spread responses over 100ms to avoid implosion of simultaneous responses
-            // else, for a simple unique record reply, we can reply immediately; no need for delay
-            if      (query->h.flags.b[0] & kDNSFlag0_TC) delayresponse = mDNSPlatformOneSecond * 20;            // Divided by 50 = 400ms
-            else if (rr->resrec.RecordType == kDNSRecordTypeShared) delayresponse = mDNSPlatformOneSecond;      // Divided by 50 = 20ms
-        }
-        else if (rr->NR_AdditionalTo && rr->NR_AdditionalTo->NR_AnswerTo == NR_AnswerMulticast)
-        {
-            // 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
-        }
-    }
-
-    // ***
-    // *** 8. If we think other machines are likely to answer these questions, set our response suppression timer,
-    // ***    unless we're shutting down. While shutting down, we don't want to delay goodbyes for our auth records.
-    // ***
-    if (delayresponse && !m->ShutdownTime && (!m->SuppressResponses || ((m->SuppressResponses - m->timenow) < ((delayresponse + 49) / 50))))
-    {
-#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-        const mDNSBool alreadySuppressing = (m->SuppressResponses != 0);
-        if (alreadySuppressing)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "Current SuppressResponses delay %5d; require %5d", m->SuppressResponses - m->timenow, (delayresponse + 49) / 50);
-        }
-#endif
-        // 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 Bonjour 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->SuppressResponses = NonZeroTime(m->timenow + ((delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond * 5) + 49) / 50));
-#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-        if (alreadySuppressing)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "Set SuppressResponses to %d", m->SuppressResponses - m->timenow);
-        }
-#endif
-    }
-
-    // ***
-    // *** 9. If query is from a legacy client, or from a new client requesting a unicast reply, then generate a unicast response too
-    // ***
-    if (SendLegacyResponse)
-        responseptr = GenerateUnicastResponse(query, end, InterfaceID, LegacyQuery, response, ResponseRecords);
-
-exit:
-    mDNSCoreResetRecord(m);
-
-    // ***
-    // *** 10. 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;
-    }
-
-#if POOF_ENABLED
-    while (ExpectedAnswers && notD2D)
-    {
-        CacheRecord *cr = ExpectedAnswers;
-        ExpectedAnswers = cr->NextInKAList;
-        cr->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 (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond * 3/4)
-            {
-                cr->UnansweredQueries++;
-                cr->LastUnansweredTime = m->timenow;
-                if (cr->UnansweredQueries > 1)
-                        debugf("ProcessQuery: UnansweredQueries %lu %s", cr->UnansweredQueries, CRDisplayString(m, cr));
-                SetNextCacheCheckTimeForRecord(m, cr);
-            }
-
-        // 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 (cr->UnansweredQueries >= MaxUnansweredQueries)
-        {
-            // Only show debugging message if this record was not about to expire anyway
-            if (RRExpireTime(cr) - m->timenow > (mDNSs32) kDefaultReconfirmTimeForNoAnswer * 4 / 3 + mDNSPlatformOneSecond)
-                    LogInfo("ProcessQuery: UnansweredQueries %lu interface %lu TTL %lu mDNS_Reconfirm() for %s",
-                       cr->UnansweredQueries, InterfaceID, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr));
-
-            m->mDNSStats.PoofCacheDeletions++;
-            mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-        }
-    }
-#endif // POOF_ENABLED
-
-    while (DupQuestions)
-    {
-        DNSQuestion *q = DupQuestions;
-        DupQuestions = q->NextInDQList;
-        q->NextInDQList = mDNSNULL;
-        RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type);
-        debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s", q->qname.c, DNSTypeName(q->qtype), InterfaceID,
-               srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6");
-    }
-    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)
-{
-    mDNSu8    *responseend = mDNSNULL;
-    mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr &&
-                                    !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
-
-    if (!dstaddr || (!InterfaceID && mDNSAddrIsDNSMulticast(dstaddr)))
-    {
-        const char *const reason = !dstaddr ? "Received over TCP connection" : "Multicast, but no InterfaceID";
-        LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
-               "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (%s)",
-               srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), 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", end - msg->data, reason);
-        return;
-    }
-
-    verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
-                  "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
-                  srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), 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", end - msg->data);
-
-    responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID,
-                               !mDNSSameIPPort(srcport, MulticastDNSPort), mDNSAddrIsDNSMulticast(dstaddr), QueryWasLocalUnicast, &m->omsg);
-
-    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",
-               m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
-               m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
-               m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s",
-               srcaddr, mDNSVal16(srcport), InterfaceID, srcaddr->type);
-        mDNSSendDNSMessage(m, &m->omsg, responseend, InterfaceID, mDNSNULL, mDNSNULL, srcaddr, srcport, mDNSNULL, mDNSfalse);
-    }
-}
-
-#if 0
-mDNSlocal mDNSBool TrustedSource(const mDNS *const m, const mDNSAddr *const srcaddr)
-{
-    DNSServer *s;
-    (void)m; // Unused
-    (void)srcaddr; // Unused
-    for (s = m->DNSServers; s; s = s->next)
-        if (mDNSSameAddress(srcaddr, &s->addr)) return(mDNStrue);
-    return(mDNSfalse);
-}
-#endif
-
-struct UDPSocket_struct
-{
-    mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
-};
-
-mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port,
-    const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp)
-{
-    DNSQuestion *q;
-    for (q = m->Questions; q; q=q->next)
-    {
-        if (!tcp && !q->LocalSocket) continue;
-        if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port)       &&
-            q->qtype                  == question->qtype     &&
-            q->qclass                 == question->qclass    &&
-            q->qnamehash              == question->qnamehash &&
-            SameDomainName(&q->qname, &question->qname))
-        {
-            if (mDNSSameOpaque16(q->TargetQID, id)) return(q);
-            else
-            {
-                return(mDNSNULL);
-            }
-        }
-    }
-    return(mDNSNULL);
-}
-
-// This function is called when we receive a unicast response. This could be the case of a unicast response from the
-// DNS server or a response to the QU query. Hence, the cache record's InterfaceId can be both NULL or non-NULL (QU case)
-mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m,
-                                                         const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr, mDNSBool tcp)
-{
-    DNSQuestion *q;
-    (void)id;
-
-    for (q = m->Questions; q; q=q->next)
-    {
-        if (!q->DuplicateOf && ResourceRecordAnswersUnicastResponse(&rr->resrec, q))
-        {
-            if (!mDNSOpaque16IsZero(q->TargetQID))
-            {
-                debugf("ExpectingUnicastResponseForRecord msg->h.id %d q->TargetQID %d for %s", mDNSVal16(id), mDNSVal16(q->TargetQID), CRDisplayString(m, rr));
-
-                if (mDNSSameOpaque16(q->TargetQID, id))
-                {
-                    mDNSIPPort srcp;
-                    if (!tcp)
-                    {
-                        srcp = q->LocalSocket ? q->LocalSocket->port : zeroIPPort;
-                    }
-                    else
-                    {
-                        srcp = q->tcpSrcPort;
-                    }
-                    if (mDNSSameIPPort(srcp, port)) return(q);
-
-                    //  if (mDNSSameAddress(srcaddr, &q->Target))                   return(mDNStrue);
-                    //  if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
-                    //  if (TrustedSource(m, srcaddr))                              return(mDNStrue);
-                    LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) from %#a:%d %s",
-                            q->qname.c, DNSTypeName(q->qtype), srcaddr, mDNSVal16(port), CRDisplayString(m, rr));
-                    return(mDNSNULL);
-                }
-            }
-            else
-            {
-                if (SrcLocal && q->ExpectUnicastResp && (mDNSu32)(m->timenow - q->ExpectUnicastResp) < (mDNSu32)(mDNSPlatformOneSecond*2))
-                    return(q);
-            }
-        }
-    }
-    return(mDNSNULL);
-}
-
-// Certain data types need more space for in-memory storage than their in-packet rdlength would imply
-// Currently this applies only to rdata types containing more than one domainname,
-// or types where the domainname is not the last item in the structure.
-mDNSlocal mDNSu16 GetRDLengthMem(const ResourceRecord *const rr)
-{
-    switch (rr->rrtype)
-    {
-    case kDNSType_SOA: return sizeof(rdataSOA);
-    case kDNSType_RP:  return sizeof(rdataRP);
-    case kDNSType_PX:  return sizeof(rdataPX);
-    default:           return rr->rdlength;
-    }
-}
-
-mDNSlocal void AddCacheRecordToCacheGroup(CacheGroup *const cg, CacheRecord *const cr)
-{
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (resource_record_is_to_be_dnssec_validated(&cr->resrec))
-    {
-        // Insert the newly created cache record before the DNSSEC-aware CNAME records.
-        // This operation ensures that mDNSResponder will deliver all the records including RRSIG or denial of
-        // existence record before delivering CNAME and following it.
-        CacheRecord *node = mDNSNULL;
-        CacheRecord **ptr = &cg->members;
-        while ((node = *ptr) != mDNSNULL)
-        {
-            // Only search for CNAME record that is marked as DNSSEC aware.
-            if (node->resrec.rrtype == kDNSType_CNAME && resource_record_is_to_be_dnssec_validated(&node->resrec))
-            {
-                break;
-            }
-            ptr = &node->next;
-        }
-
-        // Insert the new record.
-        cr->next = *ptr;
-        *ptr = cr;
-
-        // Update the tail pointer.
-        if (ptr == cg->rrcache_tail)
-        {
-            cg->rrcache_tail = &(cr->next);
-        }
-    }
-    else
-#endif
-    {
-        *(cg->rrcache_tail) = cr;               // Append this record to tail of cache slot list
-        cg->rrcache_tail = &(cr->next);         // Advance tail pointer
-    }
-}
-
-mDNSexport CacheRecord *CreateNewCacheEntryEx(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, const mDNSs32 delay,
-    const mDNSBool add, const mDNSAddr *const sourceAddress, const CreateNewCacheEntryFlags flags)
-{
-    CacheRecord *rr = mDNSNULL;
-    mDNSu16 RDLength = GetRDLengthMem(&m->rec.r.resrec);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    const mDNSBool toBeDNSSECValidated = ((flags & kCreateNewCacheEntryFlagsDNSSECRRToValidate) != 0);
-    const mDNSBool dnssecValidated = ((flags & kCreateNewCacheEntryFlagsDNSSECRRValidatedSecure) != 0)
-                                        || ((flags & kCreateNewCacheEntryFlagsDNSSECRRValidatedInsecure) != 0);
-    dnssec_result_t validation_result = dnssec_indeterminate;
-    if (dnssecValidated)
-    {
-        if ((flags & kCreateNewCacheEntryFlagsDNSSECRRValidatedSecure) != 0)
-        {
-            validation_result = dnssec_secure;
-        } else if ((flags & kCreateNewCacheEntryFlagsDNSSECRRValidatedInsecure) != 0)
-        {
-            validation_result = dnssec_insecure;
-        }
-    }
-    if (toBeDNSSECValidated && dnssecValidated)
-    {
-        return mDNSNULL;
-    }
-#endif
-
-    if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r));
-
-    //if (RDLength > InlineCacheRDSize)
-    //  LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
-
-    if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec); // If we don't have a CacheGroup for this name, make one now
-    if (cg) rr = GetCacheRecord(m, cg, RDLength);   // Make a cache record, being careful not to recycle cg
-    if (!rr) NoCacheAnswer(m, &m->rec.r);
-    else
-    {
-        RData *saveptr              = rr->resrec.rdata;     // Save the rr->resrec.rdata pointer
-        *rr                         = m->rec.r;             // Block copy the CacheRecord object
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        mdns_retain_null_safe(rr->resrec.dnsservice);
-#endif
-        rr->resrec.rdata            = saveptr;              // Restore rr->resrec.rdata after the structure assignment
-        rr->resrec.name             = cg->name;             // And set rr->resrec.name to point into our CacheGroup header
-        rr->resrec.mortality        = Mortality_Mortal;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        dnssec_error_t err = DNSSEC_ERROR_NO_ERROR;
-        if (toBeDNSSECValidated)
-        {
-            rr->resrec.dnssec = dnssec_obj_resource_record_member_create_to_validate(rr->resrec.RecordType != kDNSRecordTypePacketNegative, rr, &err);
-        }
-        else if (dnssecValidated)
-        {
-            if (validation_result != dnssec_insecure && validation_result != dnssec_secure)
-            {
-                return mDNSNULL;
-            }
-            const mDNSBool insecure_validation_usable = ((flags & kCreateNewCacheEntryFlagsDNSSECInsecureValidationUsable) != 0);
-            rr->resrec.dnssec = dnssec_obj_resource_record_member_create_validated(rr, validation_result, insecure_validation_usable, &err);
-        }
-        if (err != DNSSEC_ERROR_NO_ERROR)
-        {
-            return mDNSNULL;
-        }
-#endif
-
-        rr->DelayDelivery = delay;
-
-        // If this is an oversized record with external storage allocated, copy rdata to external storage
-        if      (rr->resrec.rdata == (RData*)&rr->smallrdatastorage && RDLength > InlineCacheRDSize)
-            LogMsg("rr->resrec.rdata == &rr->rdatastorage but length > InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
-        else if (rr->resrec.rdata != (RData*)&rr->smallrdatastorage && RDLength <= InlineCacheRDSize)
-            LogMsg("rr->resrec.rdata != &rr->rdatastorage but length <= InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
-        if (RDLength > InlineCacheRDSize)
-            mDNSPlatformMemCopy(rr->resrec.rdata, m->rec.r.resrec.rdata, sizeofRDataHeader + RDLength);
-
-        rr->next = mDNSNULL;                    // Clear 'next' pointer
-        rr->soa  = mDNSNULL;
-
-        if (sourceAddress)
-            rr->sourceAddress = *sourceAddress;
-
-        if (!rr->resrec.InterfaceID)
-        {
-            m->rrcache_totalused_unicast += rr->resrec.rdlength;
-        }
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-        if (flags & kCreateNewCacheEntryFlagsDNSPushSubscribed)
-        {
-            rr->DNSPushSubscribed = mDNStrue;
-        }
-#else
-        (void)flags;
-#endif
-
-        if (add)
-        {
-            AddCacheRecordToCacheGroup(cg, rr);
-            CacheRecordAdd(m, rr);  // CacheRecordAdd calls SetNextCacheCheckTimeForRecord(m, rr); for us
-        }
-        else
-        {
-            // Can't use the "cg->name" if we are not adding to the cache as the
-            // CacheGroup may be released anytime if it is empty
-            domainname *name = (domainname *) mDNSPlatformMemAllocate(DomainNameLength(cg->name));
-            if (name)
-            {
-                AssignDomainName(name, cg->name);
-                rr->resrec.name   = name;
-            }
-            else
-            {
-                ReleaseCacheRecord(m, rr);
-                NoCacheAnswer(m, &m->rec.r);
-                rr = mDNSNULL;
-            }
-        }
-    }
-    return(rr);
-}
-
-mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, const mDNSs32 delay,
-                                            const mDNSBool add, const mDNSAddr *const sourceAddress)
-{
-    return CreateNewCacheEntryEx(m, slot, cg, delay, add, sourceAddress, kCreateNewCacheEntryFlagsNone);
-}
-
-mDNSlocal void RefreshCacheRecordCacheGroupOrder(CacheGroup *cg, CacheRecord *cr)
-{   //  Move the cache record to the tail of the cache group to maintain a fresh ordering
-    if (cg->rrcache_tail != &cr->next)          // If not already at the tail
-    {
-        CacheRecord **rp;
-        for (rp = &cg->members; *rp; rp = &(*rp)->next)
-        {
-            if (*rp == cr)                      // This item points to this record
-            {
-                *rp = cr->next;                 // Remove this record
-                break;
-            }
-        }
-        cr->next = mDNSNULL;                    // This record is now last
-        AddCacheRecordToCacheGroup(cg, cr);
-    }
-}
-
-mDNSexport void RefreshCacheRecord(mDNS *const m, CacheRecord *const rr, const mDNSu32 ttl)
-{
-    rr->TimeRcvd             = m->timenow;
-    rr->resrec.rroriginalttl = ttl;
-    rr->UnansweredQueries = 0;
-    if (rr->resrec.mortality != Mortality_Mortal) rr->resrec.mortality = Mortality_Immortal;
-    SetNextCacheCheckTimeForRecord(m, rr);
-}
-
-mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease)
-{
-    CacheRecord *rr;
-    CacheGroup *cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-    for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-        if (rr->CRActiveQuestion == q)
-        {
-            //LogInfo("GrantCacheExtensions: new lease %d / %s", lease, CRDisplayString(m, rr));
-            RefreshCacheRecord(m, rr, lease);
-        }
-}
-
-// When the response does not match the question directly, we still want to cache them sometimes. The current response is
-// in m->rec.
-mDNSlocal mDNSBool IsResponseAcceptable(mDNS *const m, const CacheRecord *crlist)
-{
-    const CacheRecord *const newcr = &m->rec.r;
-    const ResourceRecord *rr = &newcr->resrec;
-    const CacheRecord *cr;
-
-    for (cr = crlist; cr != (CacheRecord*)1; cr = cr->NextInCFList)
-    {
-        domainname *target = GetRRDomainNameTarget(&cr->resrec);
-        // When we issue a query for A record, the response might contain both a CNAME and A records. Only the CNAME would
-        // match the question and we already created a cache entry in the previous pass of this loop. Now when we process
-        // the A record, it does not match the question because the record name here is the CNAME. Hence we try to
-        // match with the previous records to make it an AcceptableResponse. We have to be careful about setting the
-        // DNSServer value that we got in the previous pass. This can happen for other record types like SRV also.
-
-        if (target && cr->resrec.rdatahash == rr->namehash && SameDomainName(target, rr->name))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "Found a matching entry in the CacheFlushRecords - "
-                "new rrtype: " PRI_S ", matched name: " PRI_DM_NAME ", description: " PRI_S, DNSTypeName(rr->rrtype),
-                DM_NAME_PARAM(rr->name), CRDisplayString(m, cr));
-            return (mDNStrue);
-        }
-    }
-    return mDNSfalse;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-#define MAX_CNAME_TRAVERSAL 11 // We follow at most 10 CNAMEs in a CNAME chain.
-
-mDNSlocal void
-ParseCNameChainFromMessage(
-    const DNSMessage *const      response,
-    const mDNSu8 *const          limit,
-    const mDNSInterfaceID        InterfaceID,
-    const domainname *const      qname,
-    domainname                   cnameChain[static const MAX_CNAME_TRAVERSAL],
-    mDNSu32  *const              outChainLen)
-{
-    if (response == mDNSNULL || limit == mDNSNULL || qname == mDNSNULL || cnameChain == mDNSNULL || outChainLen == mDNSNULL)
-    {
-        return;
-    }
-
-    AssignDomainName(&cnameChain[0], qname);
-    *outChainLen = 1;
-
-    const mDNSu16 answerCount = response->h.numAnswers;
-    if (answerCount == 0)
-    {
-        return;
-    }
-
-    const mDNSu8 *ptr = LocateAnswers(response, limit);
-    if (ptr == mDNSNULL)
-    {
-        return;
-    }
-
-    // Parse all CNAMEs in the answer section.
-#define MAX_CNAME_TO_PARSE ((MAX_CNAME_TRAVERSAL) * 2)
-    // Index 0 is the original owner name, Index 1 is the CNAME.
-    domainname cnames[MAX_CNAME_TO_PARSE][2];
-    mDNSu16 cnameCount = 0;
-    mDNS *const m = &mDNSStorage;
-
-    for (mDNSu32 i = 0; i < answerCount && ptr < limit && cnameCount < countof(cnames); mDNSCoreResetRecord(m), i++)
-    {
-        ptr = GetLargeResourceRecord(m, response, ptr, limit, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        const ResourceRecord *const rr = &(m->rec.r.resrec);
-        if (rr->RecordType == kDNSRecordTypePacketNegative)
-        {
-            continue;
-        }
-
-        if (rr->rrtype != kDNSType_CNAME)
-        {
-            continue;
-        }
-
-        // A CNAME cannot be placed at the root domain level.
-        if (IsRootDomain(rr->name))
-        {
-            continue;
-        }
-
-        // Found a CNAME.
-        if (SameDomainName(rr->name, &rr->rdata->u.name))
-        {
-            continue;
-        }
-
-        // Save the CNAME.
-        AssignDomainName(&(cnames[cnameCount][0]), rr->name);
-        AssignDomainName(&(cnames[cnameCount][1]), &rr->rdata->u.name);
-        cnameCount++;
-    }
-
-    // With the CNAME obtained above, construct a CNAME chain.
-    // The CNAME chain always starts with the original question name.
-    const domainname *nameToSearch = qname;
-
-    // *outChainLen != MAX_CNAME_TRAVERSAL: Do not follow more than 10 CNAMEs.
-    // *outChainLen <= cnameCount If all CNAMEs parsed above has been used to form a chain, the chain length would be
-    // cnameCount. When *outChainLen == cnameCount + 1, there is not point to continue the search.
-    while (*outChainLen != MAX_CNAME_TRAVERSAL && *outChainLen <= cnameCount)
-    {
-        const domainname *nextCName = mDNSNULL;
-
-        for (mDNSu32 i = 0; i < cnameCount; i++)
-        {
-            // IsRootDomain(&cnames[i][0]): Since root domain cannot have CNAME, here root domain is used to mark
-            // an already traversed CNAME. If a CNAME has been traversed before, skip it to avoid circular dependence.
-            if (IsRootDomain(&cnames[i][0]) || !SameDomainName(nameToSearch, &cnames[i][0]))
-            {
-                continue;
-            }
-
-            // We found the next name in the chain.
-            nextCName = &cnames[i][1];
-
-            // Mark the current CNAME as already traversed.
-            const domainname *const rootDomain = (const domainname *)"\x0";
-            AssignDomainName(&cnames[i][0], rootDomain);
-            break;
-        }
-
-        // If we did not find the next name in the chain, it means we have reached the end.
-        if (nextCName == mDNSNULL)
-        {
-            break;
-        }
-
-        // Place the name into the CNAME chain.
-        nameToSearch = nextCName;
-        AssignDomainName(&cnameChain[*outChainLen], nameToSearch);
-        *outChainLen += 1;
-    }
-}
-
-// A normal denial of existence response should have no more than 3 NSEC/NSEC3 records. Here we use 10 to allow more to
-// be able to processed and discarded.
-#define MAX_NUM_NSEC_NSEC3_TO_PROCESS   10
-// Here we assume that the total number of RRSIG records contained in a response should be no more than 30 (large enough).
-#define MAX_NUM_RRSIG_TO_PROCESS        30
-
-#define mDNSInvalidUnicastTTLSeconds (mDNSMaximumUnicastTTLSeconds + 1)
-
-// Parse SOA, NSEC/NSEC3, RRSIG records contained in the DNS message to DNSSEC objects.
-mDNSlocal mDNSu32
-ParseDenialOfExistenceObjsFromMessage(
-    const DNSMessage *const     response,
-    const mDNSu8 *const         limit,
-    const mDNSInterfaceID       InterfaceID,
-    dnssec_obj_rr_soa_t *const  outObjSOA,
-    dnssec_obj_rr_rrsig_t       objSOARRSIG[static const MAX_NUM_RRSIG_TO_PROCESS],
-    mDNSu8 *const               outSOARRSIGCount,
-    dnssec_obj_rr_nsec_t        outObjNSECs[static const MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-    mDNSu8 *const               outNSECCount,
-    dnssec_obj_rr_nsec3_t       outObjNSEC3s[static const MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-    mDNSu8 *const               outNSEC3Count,
-    dnssec_obj_rr_rrsig_t       outObjRRSIGs[static const MAX_NUM_RRSIG_TO_PROCESS],
-    mDNSu8 *const               outRRSIGCount)
-{
-    dnssec_error_t err;
-    mDNSu32 negativeTTL = mDNSInvalidUnicastTTLSeconds;
-
-    // To parse the authority section, the output pointers should be non-null, in order to get a valid denial of
-    // existence response set.
-    if (outObjSOA == mDNSNULL || objSOARRSIG == mDNSNULL || outSOARRSIGCount == mDNSNULL ||
-        outObjNSECs == mDNSNULL || outNSECCount == mDNSNULL || outObjNSEC3s == mDNSNULL || outNSEC3Count == mDNSNULL ||
-        outObjRRSIGs == mDNSNULL || outRRSIGCount == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    *outObjSOA = mDNSNULL;
-    *outSOARRSIGCount = 0;
-    *outNSECCount = 0;
-    *outNSEC3Count = 0;
-    *outRRSIGCount = 0;
-
-    // All SOA, NSEC/NSEC3, RRSIG records are in the authority section.
-    const mDNSu16 authorityCount = response->h.numAuthorities;
-    if (authorityCount == 0)
-    {
-        goto exit;
-    }
-
-    // Go to the authority section.
-    const mDNSu8 *ptr = LocateAuthorities(response, limit);
-    if (ptr == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    mDNS *const m = &mDNSStorage;
-    // For each DNS record contained in the authority section.
-    for (mDNSu32 i = 0; i < authorityCount && ptr < limit; mDNSCoreResetRecord(m), i++)
-    {
-        // Get the record from the DNS message.
-        ptr = GetLargeResourceRecord(m, response, ptr, limit, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-        const ResourceRecord *const rr = &(m->rec.r.resrec);
-        if (rr->RecordType == kDNSRecordTypePacketNegative)
-        {
-            continue;
-        }
-
-        if (negativeTTL == mDNSInvalidUnicastTTLSeconds)
-        {
-            // If the denial of existence record's TTL is equal to mDNSInvalidUnicastTTLSeconds, then we choose
-            // mDNSMaximumUnicastTTLSeconds (which is mDNSInvalidUnicastTTLSeconds minus one).
-            negativeTTL = (m->rec.r.resrec.rroriginalttl != mDNSInvalidUnicastTTLSeconds) ? m->rec.r.resrec.rroriginalttl : mDNSMaximumUnicastTTLSeconds;
-        }
-        else
-        {
-            negativeTTL = MIN(negativeTTL, m->rec.r.resrec.rroriginalttl);
-        }
-
-        if (rr->rrtype == kDNSType_SOA)
-        {
-            if (*outObjSOA != mDNSNULL)
-            {
-                // Should only have one SOA.
-                continue;
-            }
-
-            // Cautious!
-            // SOA has compression pointers, GetLargeResourceRecord() expands the compression pointer to the full size
-            // structure that is represented by mDNSResponder. To construct the uncompressed rdata from the resource
-            // record parsed by GetLargeResourceRecord(), use putRData().
-            // Other than SOA, NSEC/NSEC3/RRSIG can use the rdata parsed by GetLargeResourceRecord() directly because
-            // these records will not have any compression pointer.
-        #define MAX_SOA_RD_SIZE (MAX_DOMAIN_NAME + MAX_DOMAIN_NAME + 5 * sizeof(mDNSu32))
-            mDNSu8 soaRdata[MAX_SOA_RD_SIZE];
-            putRData(mDNSNULL, soaRdata, soaRdata + sizeof(soaRdata), rr);
-            *outObjSOA = dnssec_obj_rr_soa_create(rr->name->c, soaRdata, rr->rdlength, mDNStrue, &err);
-        }
-        else if (rr->rrtype == kDNSType_NSEC)
-        {
-            if (*outNSECCount == MAX_NUM_NSEC_NSEC3_TO_PROCESS)
-            {
-                continue;
-            }
-            outObjNSECs[*outNSECCount] = dnssec_obj_rr_nsec_create(rr->name->c, rr->rdata->u.data, rr->rdlength, mDNStrue, &err);
-            if (err == DNSSEC_ERROR_NO_ERROR)
-            {
-                *outNSECCount += 1;
-            }
-        }
-        else if (rr->rrtype == kDNSType_NSEC3)
-        {
-            if (*outNSEC3Count == MAX_NUM_NSEC_NSEC3_TO_PROCESS)
-            {
-                continue;
-            }
-            outObjNSEC3s[*outNSEC3Count] = dnssec_obj_rr_nsec3_create(rr->name->c, rr->rdata->u.data, rr->rdlength, mDNStrue, &err);
-            if (err == DNSSEC_ERROR_NO_ERROR)
-            {
-                *outNSEC3Count += 1;
-            }
-        }
-        else if (rr->rrtype == kDNSType_RRSIG)
-        {
-            dnssec_obj_rr_rrsig_t rrsig = dnssec_obj_rr_rrsig_create(rr->name->c, rr->rdata->u.data, rr->rdlength, mDNStrue, &err);
-            if (err != DNSSEC_ERROR_NO_ERROR)
-            {
-                goto rrsig_parsing_exit;
-            }
-
-            const mDNSu16 typeCovered = dnssec_obj_rr_rrsig_get_type_covered(rrsig);
-            if (typeCovered == kDNSType_SOA)
-            {
-                if (*outSOARRSIGCount == MAX_NUM_RRSIG_TO_PROCESS)
-                {
-                    goto rrsig_parsing_exit;
-                }
-                objSOARRSIG[*outSOARRSIGCount] = rrsig;
-                dnssec_obj_retain(objSOARRSIG[*outSOARRSIGCount]);
-                *outSOARRSIGCount += 1;
-            }
-            else if ((typeCovered == kDNSType_NSEC) || (typeCovered == kDNSType_NSEC3))
-            {
-                if (*outRRSIGCount == MAX_NUM_RRSIG_TO_PROCESS)
-                {
-                    goto rrsig_parsing_exit;
-                }
-                outObjRRSIGs[*outRRSIGCount] = rrsig;
-                dnssec_obj_retain(outObjRRSIGs[*outRRSIGCount]);
-                *outRRSIGCount += 1;
-            }
-
-        rrsig_parsing_exit:
-            MDNS_DISPOSE_DNSSEC_OBJ(rrsig);
-        }
-    }
-
-exit:
-    return negativeTTL;
-}
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
-    const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mdns_querier_t querier, const mdns_dns_service_t uDNSService,
-#endif
-    const uDNS_LLQType LLQType)
-{
-    int i;
-    const mDNSu8 *ptr   = response->data;
-    CacheRecord *SOARecord = mDNSNULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    dnssec_obj_denial_of_existence_t denial = NULL;
-
-    dnssec_obj_rr_soa_t objSOA = NULL;
-    dnssec_obj_rr_rrsig_t objSOARRSIG[MAX_NUM_RRSIG_TO_PROCESS];
-    mDNSu8 soaRRSIGCount = 0;
-
-    dnssec_obj_rr_nsec_t objNSECs[MAX_NUM_NSEC_NSEC3_TO_PROCESS];
-    mDNSu8 nsecCount = 0;
-
-    dnssec_obj_rr_nsec3_t objNSEC3s[MAX_NUM_NSEC_NSEC3_TO_PROCESS];
-    mDNSu8 nsec3Count = 0;
-
-    dnssec_obj_rr_rrsig_t objRRSIGs[MAX_NUM_RRSIG_TO_PROCESS];
-    mDNSu8 rrsigCount = 0;
-
-    mDNSBool hasParsed = mDNSfalse;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    // Determine whether the response is mDNS, as opposed to DNS.
-    // Thus far, the code has assumed that responses with IDs set to zero are mDNS responses. However, this condition
-    // isn't sufficient because queriers, which are used exclusively for DNS queries, may set the IDs of their queries
-    // to zero. And consequently, their responses may have their IDs set to zero. Specifically, zero-valued IDs are used
-    // for DNS over HTTPs, as specified by <https://tools.ietf.org/html/rfc8484#section-4.1>.
-    const mDNSBool ResponseIsMDNS = mDNSOpaque16IsZero(response->h.id) && !querier;
-#else
-    const mDNSBool ResponseIsMDNS = mDNSOpaque16IsZero(response->h.id);
-#endif
-
-    const mDNSBool toBeDNSSECValidated = (!ResponseIsMDNS) &&
-                            (
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                                (querier != mDNSNULL) ?
-                                (mdns_querier_get_dnssec_ok(querier) && mdns_querier_get_checking_disabled(querier)) :
-#endif
-                                mDNSfalse
-                            );
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-    for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
-    {
-        DNSQuestion q;
-        ptr = getQuestion(response, ptr, end, InterfaceID, &q);
-        if (ptr)
-        {
-            DNSQuestion *qptr;
-            CacheRecord *cr, *neg = mDNSNULL;
-            CacheGroup *cg;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (querier)
-            {
-                qptr = Querier_GetDNSQuestion(querier, mDNSNULL);
-            }
-            else
-#endif
-            {
-                qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr);
-                if (!qptr)
-                {
-                    continue;
-                }
-            }
-
-            // The CNAME chain always starts from the original question name.
-            const domainname *currentQNameInCNameChain = &q.qname;
-            mDNSu32 currentQNameHashInCNameChain = q.qnamehash;
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-            const uint32_t qid = (qptr != mDNSNULL) ? mDNSVal16(qptr->TargetQID) : 0;
-        #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            // When we use querier, it is possible we receive a response whose question has already gone, in which case
-            // qptr will be NULL and querier is an orphan. We still want to process the response to not waste the
-            // traffic. Therefore, do not rely on qptr to get DNSSEC response matched, instead, use querier.
-            // The response will be mDNS if querier is NULL.
-            const mDNSBool processDenialOfExistence = toBeDNSSECValidated;
-            const uint16_t qclass = (querier != mDNSNULL) ? mdns_querier_get_qclass(querier) : 0;
-            const uint16_t qtype = (querier != mDNSNULL) ? mdns_querier_get_qtype(querier) : 0;
-        #else
-            const mDNSBool processDenialOfExistence = toBeDNSSECValidated && !ResponseIsMDNS && (qptr != mDNSNULL) && dns_question_is_primary_dnssec_requestor(qptr);
-            const uint16_t qclass = (qptr != mDNSNULL) ? qptr->qclass : 0;
-            const uint16_t qtype = (qptr != mDNSNULL) ? qptr->qtype : 0;
-        #endif
-            domainname cnameChain[MAX_CNAME_TRAVERSAL];
-            mDNSu32 chainLen = 1;
-            mDNSu32 cnameIndex = 0;
-
-            // If we need to process denial of existence record for DNSSEC-enabled question, get the CNAME chain from
-            // the response answer section.
-            if (processDenialOfExistence)
-            {
-                ParseCNameChainFromMessage(response, end, InterfaceID, &q.qname, cnameChain, &chainLen);
-                currentQNameInCNameChain = &cnameChain[cnameIndex];
-                currentQNameHashInCNameChain = DomainNameHashValue(currentQNameInCNameChain);
-            }
-            // If the question has required DNSSEC RRs, iterate through all the CNAMEs in the chain.
-        #endif
-
-            // 1. If the question is a normal non-DNSSEC question, currentQNameInCNameChain will be set to the original
-            //    question name. It will be set to mDNSNULL after the first iteration.
-            // 2. If the question is a DNSSEC question, currentQNameInCNameChain will be set to the original question
-            //    name as well, and the question name is the start of a CNAME chain. It will be set to the next name
-            //    in the CNAME chain.
-            while (currentQNameInCNameChain != mDNSNULL)
-            {
-            cg = CacheGroupForName(m, currentQNameHashInCNameChain, currentQNameInCNameChain);
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            // The following code checks if the newly added or existing records in the cache that answer the question is
-            // a wildcard answer. If it is, then we must create a negative record to deny the existence of the original
-            // question name.
-            const mDNSBool checkWildcardAnswer = processDenialOfExistence && (response->h.numAnswers > 0);
-            mDNSBool wildcardAnswer = mDNSfalse;
-            domainname nameAfterWildcardExpansion;
-            mDNSu16 typeCoveredToCheck = kDNSRecordType_Invalid;
-            mDNSu32 denial_of_existence_ttl = mDNSInvalidUnicastTTLSeconds;
-
-            if (checkWildcardAnswer)
-            {
-                for (cr = cg ? cg->members : mDNSNULL; cr != mDNSNULL; cr = cr->next)
-                {
-                    mDNSBool isAnswer;
-                #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                    if (querier)
-                    {
-                        isAnswer = (cr->resrec.dnsservice == uDNSService) && Querier_SameNameCacheRecordIsAnswer(cr, querier);
-                    }
-                    else
-                #endif
-                    {
-                        isAnswer = SameNameCacheRecordAnswersQuestion(cr, qptr);
-                    }
-
-                    const ResourceRecord *const rr = &cr->resrec;
-                    // We only care about the non-negative record that answers our question positively.
-                    // (It is possible that we have a negative record that denies the existence of exact name match,
-                    // while having wildcard expanded positive record in the cache at the same time.)
-                    if (!isAnswer || rr->RecordType == kDNSRecordTypePacketNegative)
-                    {
-                        continue;
-                    }
-
-                    denial_of_existence_ttl = rr->rroriginalttl;
-                    if (rr->rrtype == kDNSType_RRSIG)
-                    {
-                        if (!resource_record_as_rrsig_covers_wildcard_rr(rr))
-                        {
-                            // This RRSIG does not cover wildcard, therefore, it is impossible that we have received wildcard
-                            // denial of existence.
-                            wildcardAnswer = mDNSfalse;
-                            break;
-                        }
-
-                        if (typeCoveredToCheck != 0)
-                        {
-                            if (resource_record_as_rrsig_covers_rr_type(rr, typeCoveredToCheck))
-                            {
-                                wildcardAnswer = mDNStrue;
-                                AssignDomainName(&nameAfterWildcardExpansion, rr->name);
-                            }
-                            else
-                            {
-                                // This RRSIG does not cover the expected wildcard RRSet type.
-                                wildcardAnswer = mDNSfalse;
-                                break;
-                            }
-                        }
-                        else
-                        {
-                            typeCoveredToCheck = resource_record_as_rrsig_get_covered_type(rr);
-                            wildcardAnswer = mDNStrue;
-                            AssignDomainName(&nameAfterWildcardExpansion, rr->name);
-                        }
-
-                    }
-                    else
-                    {
-                        if (typeCoveredToCheck != 0)
-                        {
-                            if (typeCoveredToCheck != rr->rrtype)
-                            {
-                                // The wildcard RRSIG does not cover the expected wildcard RRSet type.
-                                wildcardAnswer = mDNSfalse;
-                                break;
-                            }
-                        }
-                        else
-                        {
-                            typeCoveredToCheck = rr->rrtype;
-                        }
-                    }
-                }
-
-                if (!wildcardAnswer)
-                {
-                    typeCoveredToCheck = 0;
-                    denial_of_existence_ttl = 0;
-                }
-            }
-        #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-            for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-            {
-                mDNSBool isAnswer;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                if (querier)
-                {
-                    isAnswer = (cr->resrec.dnsservice == uDNSService) && Querier_SameNameCacheRecordIsAnswer(cr, querier);
-                }
-                else
-#endif
-                {
-                    isAnswer = SameNameCacheRecordAnswersQuestion(cr, qptr);
-                }
-                if (isAnswer)
-                {
-                    // 1. If we got a fresh answer to this query, then don't need to generate a negative entry
-                    if (RRExpireTime(cr) - m->timenow > 0)
-                    {
-                    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                        if (!wildcardAnswer)
-                    #endif
-                        {
-                            // If the matched question is a wildcard match (by looking into the labels field of RRSIG)
-                            // then we need a new or existing negative record to deny the original question name.
-                            break;
-                        }
-                    }
-                    // 2. If we already had a negative entry, keep track of it so we can resurrect it instead of creating a new one
-                    if (cr->resrec.RecordType == kDNSRecordTypePacketNegative) neg = cr;
-                    else if (cr->resrec.mortality == Mortality_Ghost)
-                    {
-                        // 3. If the existing entry is expired, mark it to be purged
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                            "mDNSCoreReceiveNoUnicastAnswers: Removing expired record" PRI_S, CRDisplayString(m, cr));
-                        mDNS_PurgeCacheResourceRecord(m, cr);
-                   }
-                }
-            }
-            // When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft
-            // Active Directory sites) we don't want to waste memory making negative cache entries for all the unicast answers.
-            // Otherwise we just fill up our cache with negative entries for just about every single multicast name we ever look up
-            // (since the Microsoft Active Directory server is going to assert that pretty much every single multicast name doesn't exist).
-            // This is not only a waste of memory, but there's also the problem of those negative entries confusing us later -- e.g. we
-            // suppress sending our mDNS query packet because we think we already have a valid (negative) answer to that query in our cache.
-            // The one exception is that we *DO* want to make a negative cache entry for "local. SOA", for the (common) case where we're
-            // *not* on a Microsoft Active Directory network, and there is no authoritative server for "local". Note that this is not
-            // in conflict with the mDNS spec, because that spec says, "Multicast DNS Zones have no SOA record," so it's okay to cache
-            // negative answers for "local. SOA" from a uDNS server, because the mDNS spec already says that such records do not exist :-)
-            //
-            // By suppressing negative responses, it might take longer to timeout a .local question as it might be expecting a
-            // response e.g., we deliver a positive "A" response and suppress negative "AAAA" response and the upper layer may
-            // be waiting longer to get the AAAA response before returning the "A" response to the application. To handle this
-            // case without creating the negative cache entries, we generate a negative response and let the layer above us
-            // do the appropriate thing. This negative response is also needed for appending new search domains.
-            mDNSBool doNotCreateUnicastNegativeRecordForLocalDomains = (!InterfaceID && (q.qtype != kDNSType_SOA) && IsLocalDomain(&q.qname));
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            doNotCreateUnicastNegativeRecordForLocalDomains = doNotCreateUnicastNegativeRecordForLocalDomains && !processDenialOfExistence;
-        #endif
-            if (doNotCreateUnicastNegativeRecordForLocalDomains)
-            {
-                if (!cr)
-                {
-                    if (qptr)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] mDNSCoreReceiveNoUnicastAnswers: Generate negative response for "
-                            PRI_DM_NAME " (" PUB_S ")",
-                            q.request_id, mDNSVal16(q.TargetQID), DM_NAME_PARAM(&q.qname), DNSTypeName(q.qtype));
-                        m->CurrentQuestion = qptr;
-                        // We are not creating a cache record in this case, we need to pass back
-                        // the error we got so that the proxy code can return the right one to
-                        // the application
-                        if (qptr->ProxyQuestion)
-                            qptr->responseFlags = response->h.flags;
-                        GenerateNegativeResponseEx(m, mDNSInterface_Any, QC_forceresponse, response->h.flags);
-                        m->CurrentQuestion = mDNSNULL;
-                    }
-                }
-                else
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] mDNSCoreReceiveNoUnicastAnswers: Skipping check and not creating a "
-                        "negative cache entry for " PRI_DM_NAME " (" PUB_S ")",
-                        q.request_id, mDNSVal16(q.TargetQID), DM_NAME_PARAM(&q.qname), DNSTypeName(q.qtype));
-                }
-            }
-            else
-            {
-                if (!cr)
-                {
-                    // We start off assuming a negative caching TTL of 60 seconds
-                    // but then look to see if we can find an SOA authority record to tell us a better value we should be using
-                    mDNSu32 negttl = 60;
-                    int repeat = 0;
-                    const domainname *currentQName = currentQNameInCNameChain;
-                    mDNSu32 currentQNameHash = currentQNameHashInCNameChain;
-
-                    // Special case for our special Microsoft Active Directory "local SOA" check.
-                    // Some cheap home gateways don't include an SOA record in the authority section when
-                    // they send negative responses, so we don't know how long to cache the negative result.
-                    // Because we don't want to keep hitting the root name servers with our query to find
-                    // if we're on a network using Microsoft Active Directory using "local" as a private
-                    // internal top-level domain, we make sure to cache the negative result for at least one day.
-                    mDNSBool useDefaultTTLForDotLocalDomain = (q.qtype == kDNSType_SOA) && SameDomainName(&q.qname, &localdomain);
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    useDefaultTTLForDotLocalDomain = (useDefaultTTLForDotLocalDomain && !processDenialOfExistence);
-                #endif
-                    if (useDefaultTTLForDotLocalDomain)
-                    {
-                        negttl = 60 * 60 * 24;
-                    }
-
-                    // If we're going to make (or update) a negative entry, then look for the appropriate TTL from the SOA record
-                    if (response->h.numAuthorities && (ptr = LocateAuthorities(response, end)) != mDNSNULL)
-                    {
-                        ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-                        if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA)
-                        {
-                            CacheGroup *cgSOA = CacheGroupForRecord(m, &m->rec.r.resrec);
-                            const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data;
-                            mDNSu32 ttl_s = soa->min;
-                            // We use the lesser of the SOA.MIN field and the SOA record's TTL, *except*
-                            // for the SOA record for ".", where the record is reported as non-cacheable
-                            // (TTL zero) for some reason, so in this case we just take the SOA record's TTL as-is
-                            if (ttl_s > m->rec.r.resrec.rroriginalttl && m->rec.r.resrec.name->c[0])
-                                ttl_s = m->rec.r.resrec.rroriginalttl;
-                            if (negttl < ttl_s) negttl = ttl_s;
-
-                            // Create the SOA record as we may have to return this to the questions
-                            // that we are acting as a proxy for currently or in the future.
-                            SOARecord = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cgSOA, 1, mDNSfalse, mDNSNULL);
-
-                            // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer,
-                            // with an Authority Section SOA record for d.com, then this is a hint that the authority
-                            // is d.com, and consequently SOA records b.c.d.com and c.d.com don't exist either.
-                            // To do this we set the repeat count so the while loop below will make a series of negative cache entries for us
-                            //
-                            // For ProxyQuestions, we don't do this as we need to create additional SOA records to cache them
-                            // along with the negative cache record. For simplicity, we don't create the additional records.
-                            mDNSBool deduceNegativeRecordFromSOA = (!qptr || !qptr->ProxyQuestion) && (q.qtype == kDNSType_SOA);
-                        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                            // For DNSSEC-aware response, we cannot deduce negative records from SOA, because we need
-                            // the NSEC/NSEC3 records to prove that. However, we can use NSEC/NSEC3 to deduce even more
-                            // negative records, but that cannot be finished here.
-                            deduceNegativeRecordFromSOA = (deduceNegativeRecordFromSOA && !processDenialOfExistence);
-                        #endif
-                            if (deduceNegativeRecordFromSOA)
-                            {
-                                int qcount = CountLabels(&q.qname);
-                                int scount = CountLabels(m->rec.r.resrec.name);
-                                if (qcount - 1 > scount)
-                                    if (SameDomainName(SkipLeadingLabels(&q.qname, qcount - scount), m->rec.r.resrec.name))
-                                        repeat = qcount - 1 - scount;
-                            }
-                        }
-                        mDNSCoreResetRecord(m);
-                    }
-
-                    // If we already had a negative entry in the cache, then we double our existing negative TTL. This is to avoid
-                    // the case where the record doesn't exist (e.g. particularly for things like our lb._dns-sd._udp.<domain> query),
-                    // and the server returns no SOA record (or an SOA record with a small MIN TTL) so we assume a TTL
-                    // of 60 seconds, and we end up polling the server every minute for a record that doesn't exist.
-                    // With this fix in place, when this happens, we double the effective TTL each time (up to one hour),
-                    // so that we back off our polling rate and don't keep hitting the server continually.
-                    if (neg)
-                    {
-                        if (negttl < neg->resrec.rroriginalttl * 2)
-                            negttl = neg->resrec.rroriginalttl * 2;
-                        if (negttl > 3600)
-                            negttl = 3600;
-                    }
-
-                    negttl = GetEffectiveTTL(LLQType, negttl);  // Add 25% grace period if necessary
-
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    CacheRecord *denialOfExistenceTarget = mDNSNULL;
-                    CacheRecord *const invalidTarget = (CacheRecord *)(-1);
-
-                    // Only parse the SOA, NSEC/NSEC3, RRSIG out if the question requires DNSSEC RRs and we have not
-                    // parsed it yet.
-                    if (processDenialOfExistence && !hasParsed)
-                    {
-                        const mDNSu32 possible_denial_ttl = ParseDenialOfExistenceObjsFromMessage(response, end, InterfaceID,
-                            &objSOA, objSOARRSIG, &soaRRSIGCount, objNSECs, &nsecCount, objNSEC3s, &nsec3Count,
-                            objRRSIGs, &rrsigCount);
-                        hasParsed = mDNStrue;
-
-                        // If the positive part of the DNSSEC response does not provide a valid TTL for us to use,
-                        // try to use the minimal TTL value of the denial of existence RRSet as our TTL.
-                        if (denial_of_existence_ttl == mDNSInvalidUnicastTTLSeconds)
-                        {
-                            denial_of_existence_ttl = possible_denial_ttl;
-                        }
-                    }
-
-                    // If the question requires DNSSEC RRs, and we found an existing negative record that denies the
-                    // question (which means the negative record is DNSSEC-aware), check to see if we need to make it
-                    // expired if its denial of existence record has changed since last time we have processed it.
-                    if (processDenialOfExistence && neg != mDNSNULL && resource_record_is_to_be_dnssec_validated(&neg->resrec))
-                    {
-                        // Compute the new denial of existence record.
-                        const mDNSBool containsNSECOrNSEC3Records = (nsecCount > 0) || (nsec3Count > 0);
-                        if (denial == mDNSNULL && containsNSECOrNSEC3Records)
-                        {
-                            dnssec_error_t err;
-                            denial = dnssec_obj_denial_of_existence_create(currentQName->c, qclass, qtype,
-                                wildcardAnswer ? nameAfterWildcardExpansion.c : mDNSNULL, typeCoveredToCheck,
-                                objSOA, objSOARRSIG, soaRRSIGCount, objNSECs, nsecCount,
-                                objNSEC3s, nsec3Count, objRRSIGs, rrsigCount, &err);
-
-                            if (denial == mDNSNULL)
-                            {
-                                LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_FAULT,
-                                    "[Q%u] Unable to create the denial of existence record set - "
-                                    "error: " PUB_S ", qname: " PRI_DM_NAME ", qtype: " PRI_S ", soaRRSIGCount: %u, "
-                                    "nsecCount: %u, nsec3Count: %u, rrsigCount: %u.", qid,
-                                    dnssec_error_get_error_description(err), DM_NAME_PARAM(currentQName),
-                                    DNSTypeName(qtype), soaRRSIGCount, nsecCount, nsec3Count, rrsigCount);
-                            } else {
-                                LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_DEFAULT, "[Q%u] Create the denial of existence record set "
-                                    "- qname: " PRI_DM_NAME ", qtype: " PRI_S ", denial type: " PUB_S,
-                                    qid, DM_NAME_PARAM(currentQName), DNSTypeName(qtype),
-                                    dnssec_obj_denial_of_existence_get_denial_type_description(denial));
-                            }
-                        }
-
-                        const dnssec_obj_denial_of_existence_t neg_denial = resource_record_get_denial_of_existence(&neg->resrec);
-                        // Check if the denial of existence record has changed.
-
-                        mDNSBool sameDenialOfExistence;
-                        if (neg_denial != mDNSNULL && denial != mDNSNULL) {
-                            sameDenialOfExistence = dnssec_obj_equal(neg_denial, denial);
-                        } else if (neg_denial == mDNSNULL && denial == mDNSNULL) {
-                            sameDenialOfExistence = true;
-                        } else {
-                            sameDenialOfExistence = false;
-                        }
-
-                        if (!sameDenialOfExistence)
-                        {
-                            LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_DEBUG, "Denial of existence record changes, purging the old negative record - "
-                                "name: " PRI_DM_NAME ", type: " PUB_S, DM_NAME_PARAM(currentQName), DNSTypeName(qtype));
-                            // If the denial of existence has changed, the old negative record should be removed and
-                            // the question callback needs to be notified about this change, therefore, we mark it
-                            // as expired and create a new negative record that contains the latest denial of
-                            // existence record.
-                            mDNS_PurgeCacheResourceRecord(m, neg);
-                            neg = mDNSNULL;
-                        }
-                        else
-                        {
-                            LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_DEBUG, "Denial of existence record does not change, rescuing the old negative record - "
-                                "name: " PRI_DM_NAME ", type: " PUB_S, DM_NAME_PARAM(currentQName), DNSTypeName(qtype));
-                        }
-                    }
-
-                    // If negative record is still valid after the checking above, assign it to denialOfExistenceTarget.
-                    // Continue the negative record refresh process.
-                    if (processDenialOfExistence && neg != mDNSNULL)
-                    {
-                        denialOfExistenceTarget = neg;
-                        denialOfExistenceTarget->ineligibleForRecycling = mDNStrue;
-                    }
-
-                    if (processDenialOfExistence && denial_of_existence_ttl != mDNSInvalidUnicastTTLSeconds)
-                    {
-                        negttl = denial_of_existence_ttl;
-                    }
-
-                #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-                    // If we already had a negative cache entry just update it, else make one or more new negative cache entries.
-                    if (neg)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                            "[R%u->Q%u] mDNSCoreReceiveNoUnicastAnswers: Renewing negative TTL from %d to %d " PRI_S,
-                            q.request_id, mDNSVal16(q.TargetQID), neg->resrec.rroriginalttl, negttl,
-                            CRDisplayString(m, neg));
-                        RefreshCacheRecord(m, neg, negttl);
-                        // When we created the cache for the first time and answered the question, the question's
-                        // interval was set to MaxQuestionInterval. If the cache is about to expire and we are resending
-                        // the queries, the interval should still be at MaxQuestionInterval. If the query is being
-                        // restarted (setting it to InitialQuestionInterval) for other reasons e.g., wakeup,
-                        // we should reset its question interval here to MaxQuestionInterval.
-                        if (qptr)
-                        {
-                            ResetQuestionState(m, qptr);
-                        }
-                        if (SOARecord)
-                        {
-                            if (neg->soa)
-                                ReleaseCacheRecord(m, neg->soa);
-                            neg->soa = SOARecord;
-                            SOARecord = mDNSNULL;
-                        }
-                    }
-                    else while (1)
-                        {
-                            CacheRecord *negcr;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                            const DNSServRef dnsserv = uDNSService;
-#else
-                            const DNSServRef dnsserv = qptr->qDNSServer;
-#endif
-                            debugf("mDNSCoreReceiveNoUnicastAnswers making negative cache entry TTL %d for %##s (%s)", negttl, name->c, DNSTypeName(q.qtype));
-                            // Create a negative record for the current name in the CNAME chain.
-                            MakeNegativeCacheRecord(m, &m->rec.r, currentQName, currentQNameHash, q.qtype, q.qclass, negttl, mDNSInterface_Any,
-                                dnsserv, response->h.flags);
-                            // We create SOA records above which might create new cache groups. Earlier
-                            // in the function we looked up the cache group for the name and it could have
-                            // been NULL. If we pass NULL cg to new cache entries that we create below,
-                            // it will create additional cache groups for the same name. To avoid that,
-                            // look up the cache group again to re-initialize cg again.
-                            cg = CacheGroupForName(m, currentQNameHash, currentQName);
-
-                            CreateNewCacheEntryFlags flags = kCreateNewCacheEntryFlagsNone;
-                            mDNSs32 delay = 1;
-                        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                            if (toBeDNSSECValidated)
-                            {
-                                flags |= kCreateNewCacheEntryFlagsDNSSECRRToValidate;
-                                delay = NonZeroTime(m->timenow);
-                            }
-                        #endif
-                            // Need to add with a delay so that we can tag the SOA record
-                            negcr = CreateNewCacheEntryEx(m, HashSlotFromNameHash(currentQNameHash), cg, delay, mDNStrue, mDNSNULL, flags);
-
-                        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                            // Remember the newly created negative cache record.
-                            if (processDenialOfExistence && denialOfExistenceTarget == mDNSNULL)
-                            {
-                                denialOfExistenceTarget = (negcr != mDNSNULL ? negcr : invalidTarget);
-                                // Make this negative record ineligible for cache recycling temporarily, since we have
-                                // a reference to it.
-                                if (denialOfExistenceTarget != invalidTarget)
-                                {
-                                    denialOfExistenceTarget->ineligibleForRecycling = mDNStrue;
-                                }
-                            }
-                        #endif
-
-                            if (negcr)
-                            {
-                                if (SOARecord)
-                                {
-                                    if (negcr->soa)
-                                        ReleaseCacheRecord(m, negcr->soa);
-                                    negcr->soa = SOARecord;
-                                    SOARecord = mDNSNULL;
-                                }
-
-                            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                                if (!processDenialOfExistence)
-                                {
-                            #endif
-                                    negcr->DelayDelivery = 0;
-                                    CacheRecordDeferredAdd(m, negcr);
-                            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                                }
-                                else
-                                {
-                                    // Always delay deliver DNSSEC response so that we can finish processing the entire response.
-                                    ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(currentQNameHash), negcr->DelayDelivery);
-                                }
-                            #endif
-                            }
-                            mDNSCoreResetRecord(m);
-                            if (!repeat) break;
-                            repeat--;
-                            currentQName = SkipLeadingLabels(currentQName, 1);
-                            currentQNameHash = DomainNameHashValue(currentQName);
-                        }
-
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    // Do not set denial of existence object:
-                    // 1. if the records come from mDNS response.
-                    // 2. If we do not know if the question requires DNSSEC RRs.
-                    // 3. If the question does not require DNSSEC RRs. (No one will use the denial object)
-                    // 4. If no negative is found or created.
-                    if (!processDenialOfExistence || denialOfExistenceTarget == invalidTarget ||
-                        !resource_record_is_dnssec_aware(&denialOfExistenceTarget->resrec))
-                    {
-                        goto process_denial_exit;
-                    }
-                    // Make the negative record eligible for cache recycling since we will finish the work with it.
-                    denialOfExistenceTarget->ineligibleForRecycling = mDNSfalse;
-
-                    // Check if we need to update the old denial of existence object.
-                    // If the denialOfExistenceTarget already has a denial of existence record, it is an existing
-                    // negative record whose denial of existence has not changed since last time. Therefore, we do not
-                    // need to assign new denial of existence object to it.
-                    if (resource_record_get_denial_of_existence(&denialOfExistenceTarget->resrec) != mDNSNULL)
-                    {
-                        goto process_denial_exit;
-                    }
-
-                    // Create the denial of existence object based on the parsed DNSSEC objects.
-                    const mDNSBool containsNSECOrNSEC3Records = (nsecCount > 0) || (nsec3Count > 0);
-                    if (denial == mDNSNULL && containsNSECOrNSEC3Records)
-                    {
-                        dnssec_error_t err;
-                        // Here, we are creating the denial of existence object because we cannot find an acceptable
-                        // positive record for the question, we can be sure that it is not a wildcard data response.
-                        // Therefore we can pass kDNSRecordType_Invalid to skip the wildcard data response checking.
-                        denial = dnssec_obj_denial_of_existence_create(currentQName->c, qclass, qtype,
-                            wildcardAnswer ? nameAfterWildcardExpansion.c : mDNSNULL, typeCoveredToCheck,
-                            objSOA, objSOARRSIG, soaRRSIGCount, objNSECs, nsecCount,
-                            objNSEC3s, nsec3Count, objRRSIGs, rrsigCount, &err);
-
-                        if (denial == mDNSNULL)
-                        {
-                            LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_FAULT,
-                                "[Q%u] Unable to create the denial of existence record set - "
-                                "error: " PUB_S ", qname: " PRI_DM_NAME ", qtype: " PRI_S ", soaRRSIGCount: %u, "
-                                "nsecCount: %u, nsec3Count: %u, rrsigCount: %u.", qid,
-                                dnssec_error_get_error_description(err), DM_NAME_PARAM(currentQName),
-                                DNSTypeName(qtype), soaRRSIGCount, nsecCount, nsec3Count, rrsigCount);
-                            goto process_denial_exit;
-                        }
-                        else
-                        {
-                            LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_DEFAULT, "[Q%u] Create the denial of existence record set "
-                                "- qname: " PRI_DM_NAME ", qtype: " PRI_S ", denial type: " PUB_S,
-                                qid, DM_NAME_PARAM(currentQName), DNSTypeName(qtype),
-                                dnssec_obj_denial_of_existence_get_denial_type_description(denial));
-                        }
-                    }
-
-                    resource_record_set_denial_of_existence(&denialOfExistenceTarget->resrec, denial);
-
-                process_denial_exit:
-                    (void)denialOfExistenceTarget; // To make process_denial_exit a non-empty label.
-                #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                }
-            }
-            // By default we do not traverse the CNAME chain.
-            currentQNameInCNameChain = mDNSNULL;
-            currentQNameHashInCNameChain = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            // However, if the question has required DNSSEC RRs, we need to traverse the CNAME chain to create the
-            // negative record for each name in the CNAME chain.
-            if (processDenialOfExistence)
-            {
-                cnameIndex++;
-                if (cnameIndex < chainLen)
-                {
-                    currentQNameInCNameChain = &cnameChain[cnameIndex];
-                    currentQNameHashInCNameChain = DomainNameHashValue(currentQNameInCNameChain);
-                }
-            }
-
-            if (!ResponseIsMDNS)
-            {
-                // Every CNAME in the chain has a separate denial of existence record.
-                MDNS_DISPOSE_DNSSEC_OBJ(denial);
-            }
-#endif
-            } // while (currentQNameInCNameChain != mDNSNULL)
-        } // if (ptr)
-    } // for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
-    if (SOARecord)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "mDNSCoreReceiveNoUnicastAnswers: SOARecord not used");
-        ReleaseCacheRecord(m, SOARecord);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (!ResponseIsMDNS)
-    {
-        MDNS_DISPOSE_DNSSEC_OBJ(objSOA);
-        for (mDNSu32 index = 0; index < soaRRSIGCount; index++)
-        {
-            MDNS_DISPOSE_DNSSEC_OBJ(objSOARRSIG[index]);
-        }
-
-        for (mDNSu32 index = 0; index < nsecCount; index++)
-        {
-            MDNS_DISPOSE_DNSSEC_OBJ(objNSECs[index]);
-        }
-        for (mDNSu32 index = 0; index < nsec3Count; index++)
-        {
-            MDNS_DISPOSE_DNSSEC_OBJ(objNSEC3s[index]);
-        }
-
-        for (mDNSu32 index = 0; index < rrsigCount; index++)
-        {
-            MDNS_DISPOSE_DNSSEC_OBJ(objRRSIGs[index]);
-        }
-    }
-#endif
-}
-
-mDNSlocal void mDNSCorePrintStoredProxyRecords(mDNS *const m)
-{
-    AuthRecord *rrPtr = mDNSNULL;
-    if (!m->SPSRRSet) return;
-    LogSPS("Stored Proxy records :");
-    for (rrPtr = m->SPSRRSet; rrPtr; rrPtr = rrPtr->next)
-    {
-        LogSPS("%s", ARDisplayString(m, rrPtr));
-    }
-}
-
-mDNSlocal mDNSBool mDNSCoreRegisteredProxyRecord(mDNS *const m, AuthRecord *rr)
-{
-    AuthRecord *rrPtr = mDNSNULL;
-
-    for (rrPtr = m->SPSRRSet; rrPtr; rrPtr = rrPtr->next)
-    {
-        if (IdenticalResourceRecord(&rrPtr->resrec, &rr->resrec))
-        {
-            LogSPS("mDNSCoreRegisteredProxyRecord: Ignoring packet registered with sleep proxy : %s ", ARDisplayString(m, rr));
-            return mDNStrue;
-        }
-    }
-    mDNSCorePrintStoredProxyRecords(m);
-    return mDNSfalse;
-}
-
-mDNSexport CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage *const response, uDNS_LLQType LLQType,
-    const mDNSu32 slot, CacheGroup *cg, CacheRecord ***cfp, mDNSInterfaceID InterfaceID)
-{
-    CacheRecord *cr;
-    CacheRecord **cflocal = *cfp;
-
-    for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-    {
-        mDNSBool match;
-        // Resource record received via unicast, the resGroupID should match ?
-        if (!InterfaceID)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            match = (cr->resrec.dnsservice == m->rec.r.resrec.dnsservice) ? mDNStrue : mDNSfalse;
-#else
-            const mDNSu32 id1 = (cr->resrec.rDNSServer ? cr->resrec.rDNSServer->resGroupID : 0);
-            const mDNSu32 id2 = (m->rec.r.resrec.rDNSServer ? m->rec.r.resrec.rDNSServer->resGroupID : 0);
-            match = (id1 == id2);
-#endif
-        }
-        else
-            match = (cr->resrec.InterfaceID == InterfaceID);
-        // If we found this exact resource record, refresh its TTL
-        if (match)
-        {
-            if (IdenticalSameNameRecord(&m->rec.r.resrec, &cr->resrec))
-            {
-                if (m->rec.r.resrec.rdlength > InlineCacheRDSize)
-                    verbosedebugf("mDNSCoreReceiveCacheCheck: Found record size %5d interface %p already in cache: %s",
-                                  m->rec.r.resrec.rdlength, InterfaceID, CRDisplayString(m, &m->rec.r));
-
-                if (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask)
-                {
-                    // If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list
-                    if (cr->NextInCFList == mDNSNULL && *cfp != &cr->NextInCFList && LLQType != uDNS_LLQ_Events)
-                    {
-                        *cflocal = cr;
-                        cflocal = &cr->NextInCFList;
-                        *cflocal = (CacheRecord*)1;
-                        *cfp = &cr->NextInCFList;
-                    }
-
-                    // If this packet record is marked unique, and our previous cached copy was not, then fix it
-                    if (!(cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))
-                    {
-                        DNSQuestion *q;
-                        for (q = m->Questions; q; q=q->next)
-                        {
-                            if (CacheRecordAnswersQuestion(cr, q))
-                                q->UniqueAnswers++;
-                        }
-                        cr->resrec.RecordType = m->rec.r.resrec.RecordType;
-                    }
-                }
-
-                if (!SameRDataBody(&m->rec.r.resrec, &cr->resrec.rdata->u, SameDomainNameCS))
-                {
-                    // If the rdata of the packet record differs in name capitalization from the record in our cache
-                    // then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get
-                    // a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one.
-                    // <rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing
-                    cr->resrec.rroriginalttl = 0;
-                    cr->TimeRcvd = m->timenow;
-                    cr->UnansweredQueries = MaxUnansweredQueries;
-                    SetNextCacheCheckTimeForRecord(m, cr);
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "mDNSCoreReceiveCacheCheck: Discarding due to domainname case change old: " PRI_S,
-                        CRDisplayString(m, cr));
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "mDNSCoreReceiveCacheCheck: Discarding due to domainname case change new: " PRI_S,
-                        CRDisplayString(m, &m->rec.r));
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,  "mDNSCoreReceiveCacheCheck: Discarding due to domainname case change in "
-                        "%d slot %3d in %d %d", NextCacheCheckEvent(cr) - m->timenow, slot,
-                        m->rrcache_nextcheck[slot] - m->timenow, m->NextCacheCheck - m->timenow);
-                    // DO NOT break out here -- we want to continue as if we never found it
-                }
-                else if (m->rec.r.resrec.rroriginalttl > 0)
-                {
-                    DNSQuestion *q;
-
-                    m->mDNSStats.CacheRefreshed++;
-
-                    if ((cr->resrec.mortality == Mortality_Ghost) && !cr->DelayDelivery)
-                    {
-                        cr->DelayDelivery = NonZeroTime(m->timenow);
-                        debugf("mDNSCoreReceiveCacheCheck: Reset DelayDelivery for mortalityExpired EXP:%d RR %s", m->timenow - RRExpireTime(cr), CRDisplayString(m, cr));
-                    }
-
-                    if (cr->resrec.rroriginalttl == 0) debugf("uDNS rescuing %s", CRDisplayString(m, cr));
-                    RefreshCacheRecord(m, cr, m->rec.r.resrec.rroriginalttl);
-                    // RefreshCacheRecordCacheGroupOrder will modify the cache group member list that is currently being iterated over in this for-loop.
-                    // It is safe to call because the else-if body will unconditionally break out of the for-loop now that it has found the entry to update.
-                    RefreshCacheRecordCacheGroupOrder(cg, cr);
-                    CacheRecordSetResponseFlags(cr, response->h.flags);
-
-                    // If we may have NSEC records returned with the answer (which we don't know yet as it
-                    // has not been processed), we need to cache them along with the first cache
-                    // record in the list that answers the question so that it can be used for validation
-                    // later. The "type" check below is to make sure that we cache on the cache record
-                    // that would answer the question. It is possible that we might cache additional things
-                    // e.g., MX question might cache A records also, and we want to cache the NSEC on
-                    // the record that answers the question.
-                    if (!InterfaceID)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                            "mDNSCoreReceiveCacheCheck: rescuing RR with new TTL %u: " PRI_S,
-                            cr->resrec.rroriginalttl, CRDisplayString(m, cr));
-                    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                        if (resource_record_is_to_be_dnssec_validated(&cr->resrec) && cr->CRActiveQuestion != mDNSNULL)
-                        {
-                            // We have update the "DNSSEC to be validated" record's TTL, schedule a cache update for
-                            // the "DNSSEC validated" record so their expiration time can also be updated.
-                            schedule_next_validated_cache_update(m);
-                        }
-                    #endif
-                    }
-                    // We have to reset the question interval to MaxQuestionInterval so that we don't keep
-                    // polling the network once we get a valid response back. For the first time when a new
-                    // cache entry is created, AnswerCurrentQuestionWithResourceRecord does that.
-                    // Subsequently, if we reissue questions from within the mDNSResponder e.g., DNS server
-                    // configuration changed, without flushing the cache, we reset the question interval here.
-                    // Currently, we do this for for both multicast and unicast questions as long as the record
-                    // type is unique. For unicast, resource record is always unique and for multicast it is
-                    // true for records like A etc. but not for PTR.
-                    if (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)
-                    {
-                        for (q = m->Questions; q; q=q->next)
-                        {
-                            if (!q->DuplicateOf && !q->LongLived &&
-                                ActiveQuestion(q) && CacheRecordAnswersQuestion(cr, q))
-                            {
-                                ResetQuestionState(m, q);
-                                debugf("mDNSCoreReceiveCacheCheck: Set MaxQuestionInterval for %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-                                break;      // Why break here? Aren't there other questions we might want to look at?-- SC July 2010
-                            }
-                        }
-                    }
-                    break;  // Check usage of RefreshCacheRecordCacheGroupOrder before removing (See note above)
-                }
-                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.
-                    // If record's current expiry time is more than a second from now, we set it to expire in one second.
-                    // If the record is already going to expire in less than one second anyway, we leave it alone --
-                    // we don't want to let the goodbye packet *extend* the record's lifetime in our cache.
-
-                    if (RRExpireTime(cr) - m->timenow > mDNSPlatformOneSecond)
-                    {
-                        const ResourceRecord *const resrec = &cr->resrec;
-
-                        // Since the Goodbye packet we care about is the PTR Goodbye packet, which tells us what
-                        // host is deregistering the record, only print the domain name in the RDATA if the RDATA type
-                        // is PTR.
-                        const domainname *ptrDomain = mDNSNULL;
-                        if (resrec->rrtype == kDNSType_PTR)
-                        {
-                            ptrDomain = &resrec->rdata->u.name;
-                        }
-
-                        char timestamp[MIN_TIMESTAMP_STRING_LENGTH];
-                        getLocalTimestampFromPlatformTime(m->timenow, cr->TimeRcvd, timestamp, sizeof(timestamp));
-
-                        const char *const ifName = InterfaceNameForID(m, InterfaceID);
-
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                            "Received Goodbye packet for cached record - "
-                            "name: " PRI_DM_NAME ", type: " PUB_S ", last time received: " PUB_S
-                            ", interface: " PUB_S ", source address: " PRI_IP_ADDR ", "
-                            "RDATA domain if PTR: " PRI_DM_NAME,
-                            DM_NAME_PARAM(resrec->name), DNSTypeName(resrec->rrtype), timestamp, ifName,
-                            &cr->sourceAddress, DM_NAME_PARAM(ptrDomain));
-
-                        cr->resrec.rroriginalttl = 1;
-                        cr->TimeRcvd = m->timenow;
-                        cr->UnansweredQueries = MaxUnansweredQueries;
-                        SetNextCacheCheckTimeForRecord(m, cr);
-                    }
-                    break;
-                }
-            }
-            else
-            {
-            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                // The DNSSEC status has to be the same to be comparable.
-                if (!resource_records_have_same_dnssec_rr_category(&m->rec.r.resrec, &cr->resrec))
-                {
-                    continue;
-                }
-            #endif
-
-                // If the cache record rrtype doesn't match and one is a CNAME, then flush this record.
-                if ((m->rec.r.resrec.rrtype == kDNSType_CNAME || cr->resrec.rrtype == kDNSType_CNAME))
-                {
-                    // Do not mark it to be flushable if it has already been marked as flushable.
-                    if (cr->resrec.rroriginalttl == 0)
-                    {
-                        continue;
-                    }
-                    // Do not mark it to be flushable if they have the same name and type, but different data.
-                    // The only case we want to handle here is the CNAME exclusion.
-                    // The same name and type, but different data case is handled by CacheFlushRecords part of
-                    // mDNSCoreReceiveResponse().
-                    if (m->rec.r.resrec.rrtype == cr->resrec.rrtype)
-                    {
-                        continue;
-                    }
-
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    // IN DNSSEC, a CNAME record can coexist with:
-                    // 1. RRSIGs that cover it.
-                    // 2. Negative records that indicate the CNAME is a wildcard answer.
-
-                    // Therefore, do not flush the RRSIG that covers the CNAME record that accompanies this CNAME.
-                    if (resource_record_as_rrsig_covers_rr_type(&m->rec.r.resrec, kDNSType_CNAME) ||
-                        resource_record_as_rrsig_covers_rr_type(&cr->resrec, kDNSType_CNAME))
-                    {
-                        continue;
-                    }
-                    // Do not flush the denial of existence record that accompanies the CNAME record.
-                    if (resource_record_as_denial_of_existence_proves_wildcard_answer(&m->rec.r.resrec) ||
-                        resource_record_as_denial_of_existence_proves_wildcard_answer(&cr->resrec))
-                    {
-                        continue;
-                    }
-                #endif
-
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "mDNSCoreReceiveCacheCheck: Discarding (" PUB_S ") " PRI_S " rrtype change from (" PUB_S PUB_S ") to (" PUB_S PUB_S ")",
-                        MortalityDisplayString(cr->resrec.mortality), CRDisplayString(m, cr),
-                        DNSTypeName(cr->resrec.rrtype), (cr->resrec.RecordType == kDNSRecordTypePacketNegative) ? ", Negative" : "",
-                        DNSTypeName(m->rec.r.resrec.rrtype), (m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative) ? ", Negative" : "");
-                    mDNS_PurgeCacheResourceRecord(m, cr);
-                    // DO NOT break out here -- we want to continue iterating the cache entries.
-                }
-            }
-        }
-    }
-    return cr;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-// A record set is a group of records received in the same response that have the same name and type.
-typedef struct
-{
-    const domainname *name;
-    mDNSu32 namehash;
-    mDNSu32 sizeOfRecordSet;    // The total number of records with the same name and type added to the cache.
-    mDNSu16 rrtype;             // The DNS type that this record set has in common. The rrtype of the RRSIG should be
-                                // treated as the type it covers.
-    mDNSBool noNewCachedRecordAdded; // If new cached record has been added.
-} RecordSet;
-
-mDNSlocal mDNSBool RecordInTheRRSet(const ResourceRecord * const rr, const RecordSet * const rrset)
-{
-    const mDNSBool typeMatchesDirectly = (rrset->rrtype == rr->rrtype);
-    const mDNSBool rrsigCoversType = resource_record_as_rrsig_covers_rr_type(rr, rrset->rrtype);
-    const mDNSBool inTheSameSet = typeMatchesDirectly || rrsigCoversType;
-
-    if (!inTheSameSet)
-    {
-        return mDNSfalse;
-    }
-    if (rrset->namehash != rr->namehash)
-    {
-        return mDNSfalse;
-    }
-    if (!SameDomainName(rrset->name, rr->name))
-    {
-        return mDNSfalse;
-    }
-
-    return mDNStrue;
-}
-
-#endif
-
-mDNSlocal mDNSBool SameNameCacheRecordsMatchInSourceTypeClass(const CacheRecord *const cr1, const CacheRecord *const cr2)
-{
-    const ResourceRecord *const rr1 = &cr1->resrec;
-    const ResourceRecord *const rr2 = &cr2->resrec;
-
-    if (rr1->InterfaceID != rr2->InterfaceID)
-    {
-        return mDNSfalse;
-    }
-
-    if (!rr1->InterfaceID)
-    {
-        // For Unicast (null InterfaceID) the resolver IDs should also match
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (rr1->dnsservice != rr2->dnsservice)
-        {
-            return mDNSfalse;
-        }
-#else
-        const mDNSu32 id1 = (rr1->rDNSServer ? rr1->rDNSServer->resGroupID : 0);
-        const mDNSu32 id2 = (rr2->rDNSServer ? rr2->rDNSServer->resGroupID : 0);
-        if (id1 != id2)
-        {
-            return mDNSfalse;
-        }
-#endif
-    }
-
-    if ((rr1->rrtype != rr2->rrtype) || (rr1->rrclass != rr2->rrclass))
-    {
-        return mDNSfalse;
-    }
-
-    return mDNStrue;
-}
-
-// 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.
-// InterfaceID non-NULL tells us the interface this multicast response was received on
-// InterfaceID NULL tells us this was a unicast response
-// dstaddr NULL tells us we received this over an outgoing TCP connection we made
-mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
-    const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_querier_t querier, mdns_dns_service_t uDNSService,
-#endif
-    const mDNSInterfaceID InterfaceID)
-{
-    int i;
-    const mDNSBool ResponseMCast    = dstaddr && mDNSAddrIsDNSMulticast(dstaddr);
-    const mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    DNSQuestion *llqMatch = mDNSNULL;
-    uDNS_LLQType LLQType      = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport, &llqMatch);
-#else
-    uDNS_LLQType LLQType = uDNS_LLQ_Not;
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-    // "(CacheRecord*)1" is a special (non-zero) end-of-list marker
-    // We use this non-zero marker so that records in our CacheFlushRecords list will always have NextInCFList
-    // set non-zero, and that tells GetCacheEntity() that they're not, at this moment, eligible for recycling.
-    CacheRecord *CacheFlushRecords = (CacheRecord*)1;
-    CacheRecord **cfp = &CacheFlushRecords;
-    NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID);
-    mDNSBool    recordAcceptedInResponse = mDNSfalse; // Set if a record is accepted from a unicast mDNS response that answers an existing question.
-
-    // 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 worrying about which section in the spoof packet contained the record.
-    int firstauthority  =                   response->h.numAnswers;
-    int firstadditional = firstauthority  + response->h.numAuthorities;
-    int totalrecords    = firstadditional + response->h.numAdditionals;
-    const mDNSu8 *ptr   = response->data;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer *uDNSServer = mDNSNULL;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    // Determine whether the response is mDNS, as opposed to DNS.
-    // Thus far, the code has assumed that responses with IDs set to zero are mDNS responses. However, this condition
-    // isn't sufficient because queriers, which are used exclusively for DNS queries, may set the IDs of their queries
-    // to zero. And consequently, their responses may have their IDs set to zero. Specifically, zero-valued IDs are used
-    // for DNS over HTTPs, as specified by <https://tools.ietf.org/html/rfc8484#section-4.1>.
-    const mDNSBool ResponseIsMDNS = mDNSOpaque16IsZero(response->h.id) && !querier;
-#else
-    const mDNSBool ResponseIsMDNS = mDNSOpaque16IsZero(response->h.id);
-#endif
-
-    debugf("Received Response from %#-15a addressed to %#-15a on %p with "
-           "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes LLQType %d",
-           srcaddr, dstaddr, 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", end - response->data, LLQType);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (mDNSSameIPPort(srcport, UnicastDNSPort))
-    {
-        bool isForCell  = (m->rec.r.resrec.rDNSServer && m->rec.r.resrec.rDNSServer->isCell);
-        dnssd_analytics_update_dns_reply_size(isForCell, dns_transport_Do53, (uint32_t)(end - (mDNSu8 *)response));
-    }
-#endif
-
-    // According to RFC 2181 <http://www.ietf.org/rfc/rfc2181.txt>
-    //    When a DNS client receives a reply with TC
-    //    set, it should ignore that response, and query again, using a
-    //    mechanism, such as a TCP connection, that will permit larger replies.
-    // It feels wrong to be throwing away data after the network went to all the trouble of delivering it to us, but
-    // delivering some records of the RRSet first and then the remainder a couple of milliseconds later was causing
-    // failures in our Microsoft Active Directory client, which expects to get the entire set of answers at once.
-    // <rdar://problem/6690034> Can't bind to Active Directory
-    // In addition, if the client immediately canceled its query after getting the initial partial response, then we'll
-    // abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache.
-    // Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already,
-    // and not even do the TCP query.
-    // Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the
-    // entire RRSet, with the following exception. If the response contains an answer section and one or more records in
-    // either the authority section or additional section, then that implies that truncation occurred beyond the answer
-    // section, and the answer section is therefore assumed to be complete.
-    //
-    // From section 6.2 of RFC 1035 <https://tools.ietf.org/html/rfc1035>:
-    //    When a response is so long that truncation is required, the truncation
-    //    should start at the end of the response and work forward in the
-    //    datagram.  Thus if there is any data for the authority section, the
-    //    answer section is guaranteed to be unique.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC) && !querier &&
-#else
-    if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC) &&
-#endif
-        ((response->h.numAnswers == 0) || ((response->h.numAuthorities == 0) && (response->h.numAdditionals == 0)))) return;
-
-    if (LLQType == uDNS_LLQ_Ignore) return;
-
-    // 1. We ignore questions (if any) in mDNS response packets
-    // 2. If this is an LLQ response, we handle it much the same
-    // Otherwise, this is a authoritative uDNS answer, so arrange for any stale records to be purged
-    if (ResponseMCast || LLQType == uDNS_LLQ_Events)
-        ptr = LocateAnswers(response, end);
-    // Otherwise, for one-shot queries, any answers in our cache that are not also contained
-    // in this response packet are immediately deemed to be invalid.
-    else
-    {
-        mDNSBool failure, returnEarly;
-        const int rcode = response->h.flags.b[1] & kDNSFlag1_RC_Mask;
-        failure = !(rcode == kDNSFlag1_RC_NoErr || rcode == kDNSFlag1_RC_NXDomain || rcode == kDNSFlag1_RC_NotAuth);
-        returnEarly = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        // When the QUERIER functionality is enabled, DNS transport is handled exclusively by querier objects. If this
-        // response was provided by a querier, but the RCODE is considered a failure, then set failure to false so that
-        // we don't return early. The logic of returning early was so that uDNS_CheckCurrentQuestion() could handle
-        // resending the query and generate a negative cache record if all servers were tried. If the querier provides a
-        // response, then it's the best response that it could provide. If the RCODE is considered a failure,
-        // mDNSCoreReceiveResponse() needs to create negative cache entries for the unanwered question, so totalrecords
-        // is set to 0 to ignore any records that the response may contain.
-        if (querier && failure)
-        {
-            totalrecords = 0;
-            failure = mDNSfalse;
-        }
-#endif
-        // We could possibly combine this with the similar loop at the end of this function --
-        // instead of tagging cache records here and then rescuing them if we find them in the answer section,
-        // we could instead use the "m->PktNum" mechanism to tag each cache record with the packet number in
-        // which it was received (or refreshed), and then at the end if we find any cache records which
-        // answer questions in this packet's question section, but which aren't tagged with this packet's
-        // packet number, then we deduce they are old and delete them
-        for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
-        {
-            DNSQuestion q;
-            DNSQuestion *qptr;
-            mDNSBool expectingResponse;
-            ptr = getQuestion(response, ptr, end, InterfaceID, &q);
-            if (!ptr)
-            {
-                continue;
-            }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (querier)
-            {
-                expectingResponse = mDNStrue;
-                qptr = mDNSNULL;
-            }
-            else
-#endif
-            {
-                qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr);
-                expectingResponse = qptr ? mDNStrue : mDNSfalse;
-            }
-            if (!expectingResponse)
-            {
-                continue;
-            }
-            if (!failure)
-            {
-                CacheRecord *cr;
-                CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname);
-                for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-                {
-                    mDNSBool isAnswer;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                    if (querier)
-                    {
-                        isAnswer = (cr->resrec.dnsservice == uDNSService) && Querier_SameNameCacheRecordIsAnswer(cr, querier);
-                    }
-                    else
-#endif
-                    {
-                        isAnswer = SameNameCacheRecordAnswersQuestion(cr, qptr);
-                    }
-                    if (isAnswer)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                            "Making record answered by the current response as expired if it is not refreshed in the response - "
-                            "Q interface ID: %p, qname: " PRI_DM_NAME ", qtype: " PRI_S
-                            ", RR interface ID: %p, RR description: " PRI_S ".", q.InterfaceID, DM_NAME_PARAM(&q.qname),
-                            DNSTypeName(q.qtype), cr->resrec.InterfaceID, CRDisplayString(m, cr));
-
-                        // Don't want to disturb rroriginalttl here, because code below might need it for the exponential backoff doubling algorithm
-                        cr->TimeRcvd          = m->timenow - TicksTTL(cr) - 1;
-                        cr->UnansweredQueries = MaxUnansweredQueries;
-                    }
-                }
-            }
-            else
-            {
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] mDNSCoreReceiveResponse: Server %p responded with code %d to query "
-                    PRI_DM_NAME " (" PUB_S ")", qptr->request_id, mDNSVal16(qptr->TargetQID), qptr->qDNSServer, rcode,
-                    DM_NAME_PARAM(&q.qname), DNSTypeName(q.qtype));
-                PenalizeDNSServer(m, qptr, response->h.flags);
-#endif
-                returnEarly = mDNStrue;
-            }
-        }
-        if (returnEarly)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[Q%d] Ignoring %2d Answer" PUB_S " %2d Authorit" PUB_S " %2d Additional" PUB_S,
-                mDNSVal16(response->h.id),
-                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");
-            // not goto exit because we won't have any CacheFlushRecords and we do not want to
-            // generate negative cache entries (we want to query the next server)
-            return;
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Use this CacheRecord array to track all the answer records we have added into cache. Currently, we allow at
-        // most 100 records to be contained in the answer section of the response.
-#define MAX_RESPONSE_RECORDS 100
-        CacheRecord *cachedRecords[MAX_RESPONSE_RECORDS];
-        mDNSu32 numOfCachedRecords = 0; // The total number of records added to the cache.
-        RecordSet recordSets[MAX_RESPONSE_RECORDS];
-        mDNSu32 numOfRecordSets = 0;
-
-        // Because DNSSEC signs record with the same type, when we are counting the number of records with within the
-        // same response, we should separate them by names and types.
-        // For example, if we received a CNAME response like this:
-        // =============================================================================================================
-        // www.apple.com.                                       300     IN CNAME www.apple.com.edgekey.net.
-        // www.apple.com.edgekey.net.                           17716   IN CNAME www.apple.com.edgekey.net.globalredir.akadns.net.
-        // www.apple.com.edgekey.net.globalredir.akadns.net.    3307    IN CNAME e6858.dscx.akamaiedge.net.
-        // RRSIG 1 for www.apple.com. CNAME
-        // RRSIG 2 for www.apple.com. CNAME
-        // RRSIG for www.apple.com.edgekey.net. CNAME
-        // RRSIG for www.apple.com.edgekey.net.globalredir.akadns.net. CNAME
-        // e6858.dscx.akamaiedge.net.                           6       IN A     104.123.204.248
-        // RRSIG for e6858.dscx.akamaiedge.net. A
-        // =============================================================================================================
-
-        // Instead of treating the response as a single response set with 9 records inside.
-        // It should be treated as 4 different responses:
-        // =============================================================================================================
-        // www.apple.com.                                       300     IN CNAME www.apple.com.edgekey.net.
-        // RRSIG 1 for www.apple.com. CNAME
-        // RRSIG 2 for www.apple.com. CNAME
-        // =============================================================================================================
-
-        // =============================================================================================================
-        // www.apple.com.edgekey.net.                           17716   IN CNAME www.apple.com.edgekey.net.globalredir.akadns.net.
-        // RRSIG for www.apple.com.edgekey.net. CNAME
-        // =============================================================================================================
-
-        // =============================================================================================================
-        // www.apple.com.edgekey.net.globalredir.akadns.net.    3307    IN CNAME e6858.dscx.akamaiedge.net.
-        // RRSIG for www.apple.com.edgekey.net.globalredir.akadns.net. CNAME
-        // =============================================================================================================
-
-        // =============================================================================================================
-        // e6858.dscx.akamaiedge.net.                           6       IN A     104.123.204.248
-        // RRSIG for e6858.dscx.akamaiedge.net. A
-        // =============================================================================================================
-
-        // A similar example can be found when mDNSResponder receives a MX response that contains the A/AAAA records of
-        // the MX name. The A/AAAA record set needs to be separated with the MX record set. Therefore, we need to count
-        // the record set size that has the same name and same type, including the RRSIG that covers the same type.
-
-        const mDNSBool toBeDNSSECValidated = (!ResponseIsMDNS) &&
-                            (
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                                (querier != mDNSNULL) ?
-                                (mdns_querier_get_dnssec_ok(querier) && mdns_querier_get_checking_disabled(querier)) :
-#endif
-                                mDNSfalse
-                            );
-
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-    for (i = 0; i < totalrecords && ptr && ptr < end; i++)
-    {
-        // All responses sent via LL multicast are acceptable for caching
-        // All responses received over our outbound TCP connections are acceptable for caching
-        // We accept all records in a unicast response to a multicast query once we find one that
-        // answers an active question.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        mDNSBool AcceptableResponse = ResponseMCast || (!querier && !dstaddr) || LLQType || recordAcceptedInResponse;
-#else
-        mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType || recordAcceptedInResponse;
-#endif
-        // (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer
-        // to any specific question -- any code reading records from the cache needs to make that determination for itself.)
-
-        const mDNSu8 RecordType =
-            (i < firstauthority ) ? (mDNSu8)kDNSRecordTypePacketAns  :
-            (i < firstadditional) ? (mDNSu8)kDNSRecordTypePacketAuth : (mDNSu8)kDNSRecordTypePacketAdd;
-        ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, &m->rec);
-        if (!ptr) goto exit;        // Break out of the loop and clean up our CacheFlushRecords list before exiting
-
-        if (m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
-        {
-            mDNSCoreResetRecord(m);
-            continue;
-        }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Mark the parsed record as DNSSEC-aware(can be used for DNSSEC validation) if it applies.
-        if (toBeDNSSECValidated)
-        {
-            m->rec.r.resrec.dnssec = dnssec_obj_resource_record_member_create_to_validate(mDNStrue, &m->rec.r, NULL);
-        }
-#endif
-
-        // Don't want to cache OPT or TSIG pseudo-RRs
-        if (m->rec.r.resrec.rrtype == kDNSType_TSIG)
-        {
-            mDNSCoreResetRecord(m);
-            continue;
-        }
-        if (m->rec.r.resrec.rrtype == kDNSType_OPT)
-        {
-            const rdataOPT *opt;
-            const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
-            // Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently
-            // delete all our own AuthRecords (which are identified by having zero MAC tags on them).
-            for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++)
-                if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0])
-                {
-                    ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords);
-                    ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords);
-                }
-            mDNSCoreResetRecord(m);
-            continue;
-        }
-        // if a CNAME record points to itself, then don't add it to the cache
-        if ((m->rec.r.resrec.rrtype == kDNSType_CNAME) && SameDomainName(m->rec.r.resrec.name, &m->rec.r.resrec.rdata->u.name))
-        {
-            LogInfo("mDNSCoreReceiveResponse: CNAME loop domain name %##s", m->rec.r.resrec.name->c);
-            mDNSCoreResetRecord(m);
-            continue;
-        }
-
-        // When we receive uDNS LLQ responses, we assume a long cache lifetime --
-        // In the case of active LLQs, we'll get remove events when the records actually do go away
-        // In the case of polling LLQs, we assume the record remains valid until the next poll
-        if (!ResponseIsMDNS)
-        {
-            m->rec.r.resrec.rroriginalttl = GetEffectiveTTL(LLQType, m->rec.r.resrec.rroriginalttl);
-        }
-
-        // If response was not sent via LL multicast,
-        // then see if it answers a recent query of ours, which would also make it acceptable for caching.
-        if (!ResponseMCast)
-        {
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-            if (LLQType)
-            {
-                // For Long Lived queries that are both sent over UDP and Private TCP, LLQType is set.
-                // Even though it is AcceptableResponse, we need a matching DNSServer pointer for the
-                // queries to get ADD/RMV events. To lookup the question, we can't use
-                // ExpectingUnicastResponseForRecord as the port numbers don't match. uDNS_recvLLQRespose
-                // has already matched the question using the 64 bit Id in the packet and we use that here.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                if (querier)
-                {
-                    mdns_replace(&m->rec.r.resrec.dnsservice, uDNSService);
-                }
-#else
-                if (llqMatch != mDNSNULL) m->rec.r.resrec.rDNSServer = uDNSServer = llqMatch->qDNSServer;
-#endif
-            }
-            else
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-                if (!AcceptableResponse || !dstaddr)
-            {
-                // For responses that come over TCP (Responses that can't fit within UDP) or TLS (Private queries
-                // that are not long lived e.g., AAAA lookup in a Private domain), it is indicated by !dstaddr.
-                // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that
-                // we create.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                if (querier)
-                {
-                    ResourceRecord *const rr = &m->rec.r.resrec;
-                    if (Querier_ResourceRecordIsAnswer(rr, querier))
-                    {
-                        const mdns_resolver_type_t resolver_type = mdns_querier_get_resolver_type(querier);
-                        if ((resolver_type == mdns_resolver_type_normal) &&
-                            (mdns_querier_get_over_tcp_reason(querier) != mdns_query_over_tcp_reason_null))
-                        {
-                            rr->protocol = mdns_resolver_type_tcp;
-                        }
-                        else
-                        {
-                            rr->protocol = resolver_type;
-                        }
-                        mdns_replace(&rr->dnsservice, uDNSService);
-                        AcceptableResponse = mDNStrue;
-                    }
-                }
-                else
-#endif
-                {
-                    const DNSQuestion *q;
-                    // Initialize the DNS server on the resource record which will now filter what questions we answer with
-                    // this record.
-                    //
-                    // We could potentially lookup the DNS server based on the source address, but that may not work always
-                    // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came
-                    // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based
-                    // on the "id" and "source port", then this response answers the question and assume the response
-                    // came from the same DNS server that we sent the query to.
-                    q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr);
-                    if (q != mDNSNULL)
-                    {
-                        AcceptableResponse = mDNStrue;
-                        if (!InterfaceID)
-                        {
-                            debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                            m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer;
-#endif
-                        }
-                        else
-                        {
-                            // Accept all remaining records in this unicast response to an mDNS query.
-                            recordAcceptedInResponse = mDNStrue;
-                            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] mDNSCoreReceiveResponse: Accepting response for query: "
-                                PRI_DM_NAME " (" PUB_S ")", q->request_id, mDNSVal16(q->TargetQID),
-                                DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-                        }
-                    }
-                    else
-                    {
-                        // If we can't find a matching question, we need to see whether we have seen records earlier that matched
-                        // the question. The code below does that. So, make this record unacceptable for now
-                        if (!InterfaceID)
-                        {
-                            debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c);
-                            AcceptableResponse = mDNSfalse;
-                        }
-                    }
-                }
-            }
-        }
-        else if (llintf && llintf->IgnoreIPv4LL && m->rec.r.resrec.rrtype == kDNSType_A)
-        {
-            // There are some routers (rare, thankfully) that generate bogus ARP responses for
-            // any IPv4 address they don’t recognize, including RFC 3927 IPv4 link-local addresses.
-            // To work with these broken routers, client devices need to blacklist these broken
-            // routers and ignore their bogus ARP responses. Some devices implement a technique
-            // such as the one described in US Patent 7436783, which lets clients detect and
-            // ignore these broken routers: <https://www.google.com/patents/US7436783>
-
-            // OS X and iOS do not implement this defensive mechanism, instead taking a simpler
-            // approach of just detecting these broken routers and completely disabling IPv4
-            // link-local communication on interfaces where a broken router is detected.
-            // OS X and iOS set the IFEF_ARPLL interface flag on interfaces
-            // that are deemed “safe” for IPv4 link-local communication;
-            // the flag is cleared on interfaces where a broken router is detected.
-
-            // OS X and iOS will not even try to communicate with an IPv4
-            // link-local destination on an interface without the IFEF_ARPLL flag set.
-            // This can cause some badly written applications to freeze for a long time if they
-            // attempt to connect to an IPv4 link-local destination address and then wait for
-            // that connection attempt to time out before trying other candidate addresses.
-
-            // To mask this client bug, we suppress acceptance of IPv4 link-local address
-            // records on interfaces where we know the OS will be unwilling even to attempt
-            // communication with those IPv4 link-local destination addresses.
-            // <rdar://problem/9400639> kSuppress IPv4LL answers on interfaces without IFEF_ARPLL
-
-            const CacheRecord *const rr = &m->rec.r;
-            const RDataBody2 *const rdb = (const RDataBody2 *)rr->smallrdatastorage.data;
-            if (mDNSv4AddressIsLinkLocal(&rdb->ipv4))
-            {
-                LogInfo("mDNSResponder: Dropping LinkLocal packet %s", CRDisplayString(m, &m->rec.r));
-                mDNSCoreResetRecord(m);
-                continue;
-            }
-        }
-
-        // 1. Check that this packet resource record does not conflict with any of ours
-        if (ResponseIsMDNS && m->rec.r.resrec.rrtype != kDNSType_NSEC && m->rec.r.resrec.rrtype != kDNSType_TSR)
-        {
-            if (m->CurrentRecord)
-                LogMsg("mDNSCoreReceiveResponse ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-            m->CurrentRecord = m->ResourceRecords;
-            while (m->CurrentRecord)
-            {
-                AuthRecord *rr = m->CurrentRecord;
-                m->CurrentRecord = rr->next;
-                // We accept all multicast responses, and unicast responses resulting from queries we issued
-                // For other unicast responses, this code accepts them only for responses with an
-                // (apparently) local source address that pertain to a record of our own that's in probing state
-                if (!AcceptableResponse && !(ResponseSrcLocal && rr->resrec.RecordType == kDNSRecordTypeUnique)) continue;
-
-                if (PacketRRMatchesSignature(&m->rec.r, rr))        // If interface, name, type (if shared record) and class match...
-                {
-                    // check to see if previously marked as tentative
-                    if(CheckAndResetRRTentative(m, rr))
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,"mDNSCoreReceiveResponse: tentative is true, ProbeCount %d; "
-                            "will deregister %s due to multiscast conflict via interface %d", rr->ProbeCount, ARDisplayString(m, rr),
-                            IIDPrintable(InterfaceID));
-                        m->mDNSStats.NameConflicts++;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-                        // See if this record was also registered with any D2D plugins.
-                        D2D_stop_advertising_record(rr);
-#endif
-                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
-                    }
-                    // ... check to see if type and rdata are identical
-                    else if (IdenticalSameNameRecord(&m->rec.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 (m->rec.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; rr->ImmedUnicast = mDNSfalse; }
-                        }
-                        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, the packet RR has different type or different rdata -- check to see if this is a conflict
-                    else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r))
-                    {
-                        LogInfo("mDNSCoreReceiveResponse: Pkt Record: %08lX %s (interface %d)",
-                            m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r), IIDPrintable(InterfaceID));
-                        LogInfo("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr->resrec.rdatahash, ARDisplayString(m, rr));
-
-                        // 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
-                        if (rr->DependentOn)
-                        {
-                            while (rr->DependentOn) rr = rr->DependentOn;
-                            LogInfo("mDNSCoreReceiveResponse: Dep Record: %08lX %s", rr->resrec.rdatahash, ARDisplayString(m, rr));
-                        }
-
-                        // If we've just whacked this record's ProbeCount, don't need to do it again
-                        if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
-                            LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr));
-                        else if (rr->ProbeCount == DefaultProbeCountForTypeUnique)
-                            LogInfo("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr));
-                        else
-                        {
-                            LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r));
-                            // If we'd previously verified this record, put it back to probing state and try again
-                            if (rr->resrec.RecordType == kDNSRecordTypeVerified)
-                            {
-                                LogMsg("mDNSCoreReceiveResponse: Resetting to Probing: %s", ARDisplayString(m, rr));
-                                rr->resrec.RecordType     = kDNSRecordTypeUnique;
-                                // We set ProbeCount to one more than the usual value so we know we've already touched this record.
-                                // This is because our single probe for "example-name.local" could yield a response with (say) two A records and
-                                // three AAAA records in it, and we don't want to call RecordProbeFailure() five times and count that as five conflicts.
-                                // This special value is recognised and reset to DefaultProbeCountForTypeUnique in SendQueries().
-                                rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
-                                rr->AnnounceCount  = InitialAnnounceCount;
-                                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)
-                            {
-	                            // At this point in the code, we're probing for uniqueness.
-	                            // We've sent at least one probe (rr->ProbeCount < DefaultProbeCountForTypeUnique)
-	                            // but we haven't completed probing yet (rr->resrec.RecordType == kDNSRecordTypeUnique).
-                                // Before we call deregister, check if this is a packet we registered with the sleep proxy.
-                                if (!mDNSCoreRegisteredProxyRecord(m, rr))
-                                {
-                                    if ((rr->ProbingConflictCount == 0) || (m->MPktNum != rr->LastConflictPktNum))
-                                    {
-                                        const NetworkInterfaceInfo *const intf = FirstInterfaceForID(m, InterfaceID);
-                                        rr->ProbingConflictCount++;
-                                        rr->LastConflictPktNum = m->MPktNum;
-                                        if (ResponseMCast && (!intf || intf->SupportsUnicastMDNSResponse) &&
-                                            (rr->ProbingConflictCount <= kMaxAllowedMCastProbingConflicts))
-                                        {
-                                            LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; restarting probing after %d-tick pause due to possibly "
-                                                "spurious multicast conflict (%d/%d) via interface %d for %s",
-                                                rr->ProbeCount, kProbingConflictPauseDuration, rr->ProbingConflictCount,
-                                                kMaxAllowedMCastProbingConflicts, IIDPrintable(InterfaceID), ARDisplayString(m, rr));
-                                            rr->ProbeCount = DefaultProbeCountForTypeUnique;
-                                            rr->LastAPTime = m->timenow + kProbingConflictPauseDuration - rr->ThisAPInterval;
-                                            SetNextAnnounceProbeTime(m, rr);
-                                        }
-                                        else
-                                        {
-                                            LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s due to %scast conflict via interface %d",
-                                                rr->ProbeCount, ARDisplayString(m, rr), ResponseMCast ? "multi" : "uni", IIDPrintable(InterfaceID));
-                                            m->mDNSStats.NameConflicts++;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-                                            // See if this record was also registered with any D2D plugins.
-                                            D2D_stop_advertising_record(rr);
-#endif
-                                            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, or there are two machines on the
-                            // network using the same IP address.) This is simply a misconfiguration, and there's nothing we can do
-                            // to fix it -- e.g. it's not our job to be trying to change the machine's IP address. We just discard our
-                            // record to avoid continued conflicts (as we do for a conflict on our Unique records) and get on with life.
-                            else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
-                            {
-                                LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr));
-                                m->mDNSStats.KnownUniqueNameConflicts++;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-                                D2D_stop_advertising_record(rr);
-#endif
-                                mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
-                            }
-                            else
-                                LogMsg("mDNSCoreReceiveResponse: Unexpected record type %X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
-                        }
-                    }
-                    // Else, matching signature, different type or 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 any record(s) of the same type that we should re-assert to rescue them
-                    // (see note about "multi-homing and bridged networks" at the end of this function).
-                    else if ((m->rec.r.resrec.rrtype == rr->resrec.rrtype) &&
-                        (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) &&
-                        ((mDNSu32)(m->timenow - rr->LastMCTime) > (mDNSu32)mDNSPlatformOneSecond/2) &&
-                        ResourceRecordIsValidAnswer(rr))
-                    {
-                        rr->ImmedAnswer = mDNSInterfaceMark;
-                        m->NextScheduledResponse = m->timenow;
-                    }
-                }
-            }
-        }
-
-        if (!AcceptableResponse)
-        {
-            AcceptableResponse = IsResponseAcceptable(m, CacheFlushRecords);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (AcceptableResponse) mdns_replace(&m->rec.r.resrec.dnsservice, uDNSService);
-#else
-            if (AcceptableResponse) m->rec.r.resrec.rDNSServer = uDNSServer;
-#endif
-        }
-
-        // 2. See if we want to add this packet resource record to our cache
-        // We only try to cache answers if we have a cache to put them in
-        // Also, we ignore any apparent attempts at cache poisoning unicast to us that do not answer any outstanding active query
-        if (m->rrcache_size && AcceptableResponse)
-        {
-            const mDNSu32 slot = HashSlotFromNameHash(m->rec.r.resrec.namehash);
-            CacheGroup *cg = CacheGroupForRecord(m, &m->rec.r.resrec);
-            CacheRecord *rr = mDNSNULL;
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            // Set to true if no new cache record has been created for the response, either due to existing cached
-            // record refresh or the reason that the new response is a subset of the previous one.
-            mDNSBool newRecordAdded = mDNSfalse;
-        #endif
-
-            // 2a. Check if this packet resource record is already in our cache.
-            rr = mDNSCoreReceiveCacheCheck(m, response, LLQType, slot, cg, &cfp, InterfaceID);
-
-            // 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 && m->rec.r.resrec.rroriginalttl > 0)
-            {
-                const mDNSBool AddToCFList = (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (LLQType != uDNS_LLQ_Events);
-                mDNSs32 delay;
-
-                if (AddToCFList)
-                    delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
-                else
-                    delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash);
-
-                CreateNewCacheEntryFlags flags = kCreateNewCacheEntryFlagsNone;
-            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                if (toBeDNSSECValidated)
-                {
-                    flags |= kCreateNewCacheEntryFlagsDNSSECRRToValidate;
-                }
-            #endif
-
-                // If unique, assume we may have to delay delivery of this 'add' event.
-                // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd()
-                // to immediately to generate answer callbacks, or we call ScheduleNextCacheCheckTime()
-                // to schedule an mDNS_Execute task at the appropriate time.
-                rr = CreateNewCacheEntryEx(m, slot, cg, delay, mDNStrue, srcaddr, flags);
-                if (rr)
-                {
-                    CacheRecordSetResponseFlags(rr, response->h.flags);
-                    if (AddToCFList)
-                    {
-                        *cfp = rr;
-                        cfp = &rr->NextInCFList;
-                        *cfp = (CacheRecord*)1;
-                    }
-                    else if (rr->DelayDelivery)
-                    {
-                        ScheduleNextCacheCheckTime(m, slot, rr->DelayDelivery);
-                    }
-
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    newRecordAdded = mDNStrue;
-                #endif
-                }
-            }
-
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            if (!ResponseIsMDNS) // Only count the answer number for unicast response.
-            {
-                // Do not increment the counter if rr is not in the cache (either newly added or existing).
-                if (rr == mDNSNULL)
-                {
-                    goto record_set_tracking_exit;
-                }
-                // Do not increment the counter if rr is a negative record.
-                if (rr->resrec.rroriginalttl == 0)
-                {
-                    goto record_set_tracking_exit;
-                }
-
-                // Do not read/write out of bound for the arrays.
-                if (numOfCachedRecords == countof(cachedRecords) ||
-                    numOfRecordSets == countof(recordSets))
-                {
-                    goto record_set_tracking_exit;
-                }
-
-                // Save the record pointer in a temporary array.
-                // Mark the record as "ineligible for cache recycling" because we will save the pointer to a temporary
-                // array in mDNSCoreReceiveResponse(). If the saved pointer is recycled while we are still looping
-                // through the records in the response, we will crash if we try to deference the recycled records later.
-                rr->ineligibleForRecycling = mDNStrue;
-                cachedRecords[numOfCachedRecords] = rr;
-                numOfCachedRecords++;
-
-                RecordSet *recordSet = mDNSNULL;
-                for (mDNSu32 k = 0; k < numOfRecordSets; k++)
-                {
-                    if (!RecordInTheRRSet(&rr->resrec, &recordSets[k]))
-                    {
-                        continue;
-                    }
-
-                    recordSet = &recordSets[k];
-                    break;
-                }
-
-                if (recordSet == mDNSNULL)
-                {
-                    recordSet = &recordSets[numOfRecordSets];
-                    numOfRecordSets++;
-
-                    recordSet->name = rr->resrec.name;
-                    recordSet->namehash = rr->resrec.namehash;
-                    if (rr->resrec.rrtype != kDNSType_RRSIG)
-                    {
-                        recordSet->rrtype = rr->resrec.rrtype;
-                    }
-                    else
-                    {
-                        recordSet->rrtype = resource_record_as_rrsig_get_covered_type(&rr->resrec);
-                    }
-
-                    recordSet->sizeOfRecordSet = 0;
-                    recordSet->noNewCachedRecordAdded = mDNSfalse;
-                }
-
-                recordSet->sizeOfRecordSet++;
-                recordSet->noNewCachedRecordAdded = newRecordAdded;
-
-            record_set_tracking_exit:
-                (void)0; // No-op for the label above.
-            }
-        #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        }
-        mDNSCoreResetRecord(m);
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // After finishing processing all the records in the response, update the corresponding fields for the records
-    // in the cache.
-    if (!ResponseIsMDNS) // Only count the answer number for the unicast response.
-    {
-        if (numOfCachedRecords == countof(cachedRecords) ||
-            numOfRecordSets == countof(recordSets))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Too many records contained in a single response - "
-                "cached records: %u, record set: %u", numOfCachedRecords, numOfRecordSets);
-        }
-
-        for (mDNSu32 k = 0; k < numOfCachedRecords; k++)
-        {
-            CacheRecord *const record = cachedRecords[k];
-
-            // Ensure that the max number of records in a response can be represented by numOfCachedRecords.
-            check_compile_time_code(countof(cachedRecords) < UINT8_MAX);
-
-            const RecordSet *recordSet = mDNSNULL;
-            for (mDNSu32 kk = 0; kk < numOfRecordSets; kk++)
-            {
-                if (!RecordInTheRRSet(&record->resrec, &recordSets[kk]))
-                {
-                    continue;
-                }
-
-                recordSet = &recordSets[kk];
-                break;
-            }
-
-            if (recordSet == mDNSNULL)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "Answer set counter not found for the cached record - name: " PRI_DM_NAME ", rrtype: " PRI_S ".",
-                    DM_NAME_PARAM(record->resrec.name), DNSTypeName(record->resrec.rrtype));
-                continue;
-            }
-
-            if (record->resrec.dnssec != NULL)
-            {
-                dnssec_obj_resource_record_member_set_rrset_size(record->resrec.dnssec, recordSet->sizeOfRecordSet);
-                dnssec_obj_resource_record_member_set_no_new_rr_added(record->resrec.dnssec, recordSet->noNewCachedRecordAdded);
-            }
-        }
-    }
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-exit:
-    mDNSCoreResetRecord(m);
-
-    // 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*)1)
-    {
-        CacheRecord *r1 = CacheFlushRecords, *r2;
-        const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash);
-        const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec);
-        mDNSBool purgedRecords = mDNSfalse;
-        CacheFlushRecords = CacheFlushRecords->NextInCFList;
-        r1->NextInCFList = mDNSNULL;
-
-        // Look for records in the cache with the same signature as this new one with the cache flush
-        // bit set, and either (a) if they're fresh, just make sure the whole RRSet has the same TTL
-        // (as required by DNS semantics) or (b) if they're old, mark them for deletion in one second.
-        // We make these TTL adjustments *only* for records that still have *more* than one second
-        // remaining to live. Otherwise, a record that we tagged for deletion half a second ago
-        // (and now has half a second remaining) could inadvertently get its life extended, by either
-        // (a) if we got an explicit goodbye packet half a second ago, the record would be considered
-        // "fresh" and would be incorrectly resurrected back to the same TTL as the rest of the RRSet,
-        // or (b) otherwise, the record would not be fully resurrected, but would be reset to expire
-        // in one second, thereby inadvertently delaying its actual expiration, instead of hastening it.
-        // If this were to happen repeatedly, the record's expiration could be deferred indefinitely.
-        // To avoid this, we need to ensure that the cache flushing operation will only act to
-        // *decrease* a record's remaining lifetime, never *increase* it.
-        for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
-        {
-
-            mDNSBool proceed = SameNameCacheRecordsMatchInSourceTypeClass(r1, r2);
-
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            proceed = proceed && resource_records_is_comparable_for_dnssec(&r1->resrec, &r2->resrec);
-        #endif
-
-            if (proceed)
-            {
-                if (r1->resrec.mortality == Mortality_Mortal && r2->resrec.mortality != Mortality_Mortal)
-                {
-                    verbosedebugf("mDNSCoreReceiveResponse: R1(%p) is being immortalized by R2(%p)", r1, r2);
-                    r1->resrec.mortality = Mortality_Immortal;   //  Immortalize the replacement record
-                }
-
-                // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics)
-                // else, if record is old, mark it to be flushed
-                if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond && RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
-                {
-                    // If we find mismatched TTLs in an RRSet, correct them.
-                    // We only do this for records with a TTL of 2 or higher. It's possible to have a
-                    // goodbye announcement with the cache flush bit set (or a case-change on record rdata,
-                    // which we treat as a goodbye followed by an addition) and in that case it would be
-                    // inappropriate to synchronize all the other records to a TTL of 0 (or 1).
-
-                    // We suppress the message for the specific case of correcting from 240 to 60 for type TXT,
-                    // because certain early Bonjour devices are known to have this specific mismatch, and
-                    // there's no point filling syslog with messages about something we already know about.
-                    // We also don't log this for uDNS responses, since a caching name server is obliged
-                    // to give us an aged TTL to correct for how long it has held the record,
-                    // so our received TTLs are expected to vary in that case
-
-                    // We also suppress log message in the case of SRV records that are received
-                    // with a TTL of 4500 that are already cached with a TTL of 120 seconds, since
-                    // this behavior was observed for a number of discoveryd based AppleTV's in iOS 8
-                    // GM builds.
-                    if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1)
-                    {
-                        if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) &&
-                            !(r2->resrec.rroriginalttl == 120 && r1->resrec.rroriginalttl == 4500 && r2->resrec.rrtype == kDNSType_SRV) &&
-                            ResponseIsMDNS)
-                            LogInfo("Correcting TTL from %4d to %4d for %s",
-                                    r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2));
-                        r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
-                    }
-                    r2->TimeRcvd = m->timenow;
-                    SetNextCacheCheckTimeForRecord(m, r2);
-                }
-                else if (r2->resrec.InterfaceID) // else, if record is old, mark it to be flushed
-                {
-                    verbosedebugf("Cache flush new %p age %d expire in %d %s", r1, m->timenow - r1->TimeRcvd, RRExpireTime(r1) - m->timenow, CRDisplayString(m, r1));
-                    verbosedebugf("Cache flush old %p age %d expire in %d %s", r2, m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2));
-                #if MDNSRESPONDER_SUPPORTS(APPLE, AWDL_FAST_CACHE_FLUSH)
-                    if (mDNSPlatformInterfaceIsAWDL(r2->resrec.InterfaceID))
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                            "Fast flushing AWDL cache record -- age: %d ticks, expire: %d ticks, record: " PRI_S,
-                            m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2));
-                        mDNS_PurgeCacheResourceRecord(m, r2);
-                    }
-                    else
-                #endif
-                    {
-                        // 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.
-
-                        // If a record is deleted twice, first with an explicit DE record, then a second time by virtue of the cache
-                        // flush bit on the new record replacing it, then we allow the record to be deleted immediately, without the usual
-                        // one-second grace period. This improves responsiveness for mDNS_Update(), as used for things like iChat status updates.
-                        // <rdar://problem/5636422> Updating TXT records is too slow
-                        // We check for "rroriginalttl == 1" because we want to include records tagged by the "packet TTL is zero" check above,
-                        // which sets rroriginalttl to 1, but not records tagged by the rdata case-change check, which sets rroriginalttl to 0.
-                        if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl == 1 && r2->UnansweredQueries == MaxUnansweredQueries)
-                        {
-                            LogInfo("Cache flush for DE record %s", CRDisplayString(m, r2));
-                            r2->resrec.rroriginalttl = 0;
-                        }
-                        else if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
-                        {
-                            // We only set a record to expire in one second if it currently has *more* than a second to live
-                            // If it's already due to expire in a second or less, we just leave it alone
-                            r2->resrec.rroriginalttl = 1;
-                            r2->UnansweredQueries = MaxUnansweredQueries;
-                            r2->TimeRcvd = m->timenow - 1;
-                            // We use (m->timenow - 1) instead of m->timenow, because we use that to identify records
-                            // that we marked for deletion via an explicit DE record
-                        }
-                        SetNextCacheCheckTimeForRecord(m, r2);
-                    }
-                }
-                else
-                {
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    // Update the sizeOfRRSet counter of the records that will be flushed to reflect the
-                    // response changes, which will be noticed by the callback function.
-
-                    // Only update positive record state, negative record will be handled in
-                    // mDNSCoreReceiveNoUnicastAnswers().
-                    if (!ResponseIsMDNS && resource_record_is_positive(&r2->resrec))
-                    {
-                        const RecordSet *recordSet = mDNSNULL;
-                        for (mDNSu32 kk = 0; kk < numOfRecordSets; kk++)
-                        {
-                            if (!RecordInTheRRSet(&r2->resrec, &recordSets[kk]))
-                            {
-                                continue;
-                            }
-                            recordSet = &recordSets[kk];
-                            break;
-                        }
-
-                        if (recordSet == mDNSNULL)
-                        {
-                            // If we cannot find the records with the same name and type, then it means the records set
-                            // has been marked as expired by the authoritative DNS server. Therefore, there will be
-                            // 0 answer added (sizeOfRRSet == 0), and we do not need to wait for an add
-                            // event(noNewRRAdded == mDNStrue).
-                            if (r2->resrec.dnssec != NULL)
-                            {
-                                dnssec_obj_resource_record_member_set_rrset_size(r2->resrec.dnssec, 0);
-                                dnssec_obj_resource_record_member_set_no_new_rr_added(r2->resrec.dnssec, mDNStrue);
-                            }
-                        }
-                        else
-                        {
-                            if (r2->resrec.dnssec != NULL)
-                            {
-                                dnssec_obj_resource_record_member_set_rrset_size(r2->resrec.dnssec, recordSet->sizeOfRecordSet);
-                                dnssec_obj_resource_record_member_set_no_new_rr_added(r2->resrec.dnssec, recordSet->noNewCachedRecordAdded);
-                            }
-                        }
-                    }
-                #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-                    // Old uDNS records are scheduled to be purged instead of given at most one second to live.
-                    mDNS_PurgeCacheResourceRecord(m, r2);
-                    purgedRecords = mDNStrue;
-                }
-            }
-        }
-
-        if (r1->DelayDelivery)  // If we were planning to delay delivery of this record, see if we still need to
-        {
-            if (r1->resrec.InterfaceID)
-            {
-                r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash);
-            }
-            else
-            {
-                // If uDNS records from an older RRset were scheduled to be purged, then delay delivery slightly to allow
-                // them to be deleted before any ADD events for this record.
-                mDNSBool delayDelivery = purgedRecords;
-            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                // We always delay the delivery of DNSSEC-aware response to make sure that we generate the corresponding
-                // negative record for the wildcard answer in mDNSCoreReceiveNoUnicastAnswers().
-                delayDelivery = delayDelivery || toBeDNSSECValidated;
-            #endif
-                r1->DelayDelivery = delayDelivery ? NonZeroTime(m->timenow) : 0;
-            }
-            // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time
-            if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
-            else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery);
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (!ResponseIsMDNS)
-    {
-        for (mDNSu32 k = 0; k < numOfCachedRecords; k++)
-        {
-            // Now we have finished the response size counting, the record is now eligible for cache recycling.
-            cachedRecords[k]->ineligibleForRecycling = mDNSfalse;
-        }
-    }
-#endif
-
-    // See if we need to generate negative cache entries for unanswered unicast questions
-    mDNSCoreReceiveNoUnicastAnswers(m, response, end, dstaddr, dstport, InterfaceID,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        querier, uDNSService,
-#endif
-        LLQType);
-}
-
-// ScheduleWakeup causes all proxy records with WakeUp.HMAC matching mDNSEthAddr 'e' to be deregistered, causing
-// multiple wakeup magic packets to be sent if appropriate, and all records to be ultimately freed after a few seconds.
-// ScheduleWakeup is called on mDNS record conflicts, ARP conflicts, NDP conflicts, or reception of trigger traffic
-// that warrants waking the sleeping host.
-// ScheduleWakeup must be called with the lock held (ScheduleWakeupForList uses mDNS_Deregister_internal)
-
-mDNSlocal void ScheduleWakeupForList(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e, AuthRecord *const thelist)
-{
-    // We need to use the m->CurrentRecord mechanism here when dealing with DuplicateRecords list as
-    // mDNS_Deregister_internal deregisters duplicate records immediately as they are not used
-    // to send wakeups or goodbyes. See the comment in that function for more details. To keep it
-    // simple, we use the same mechanism for both lists.
-    if (!e->l[0])
-    {
-        LogMsg("ScheduleWakeupForList ERROR: Target HMAC is zero");
-        return;
-    }
-    m->CurrentRecord = thelist;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *const rr = m->CurrentRecord;
-        if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && mDNSSameEthAddress(&rr->WakeUp.HMAC, e))
-        {
-            LogInfo("ScheduleWakeupForList: Scheduling wakeup packets for %s", ARDisplayString(m, rr));
-            mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-        }
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-mDNSlocal void ScheduleWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e)
-{
-    if (!e->l[0])
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "ScheduleWakeup ERROR: Target HMAC is zero");
-        return;
-    }
-    ScheduleWakeupForList(m, InterfaceID, e, m->DuplicateRecords);
-    ScheduleWakeupForList(m, InterfaceID, e, m->ResourceRecords);
-}
-
-mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus result)
-{
-    if (result && result != mStatus_MemFree)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, "SPS Callback %d " PRI_S, result, ARDisplayString(m, ar));
-    }
-
-    if (result == mStatus_NameConflict)
-    {
-        mDNS_Lock(m);
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, PUB_S " Conflicting mDNS -- waking " PRI_MAC_ADDR " " PRI_S,
-            InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar));
-        if (ar->WakeUp.HMAC.l[0])
-        {
-            SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password, mDNSfalse);  // Send one wakeup magic packet
-            ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC);                               // Schedule all other records with the same owner to be woken
-        }
-        mDNS_Unlock(m);
-    }
-
-    if (result == mStatus_NameConflict || result == mStatus_MemFree)
-    {
-        m->ProxyRecords--;
-        mDNSPlatformMemFree(ar);
-        mDNS_UpdateAllowSleep(m);
-    }
-}
-
-mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth)
-{
-    int     i;
-    mDNSs8  hval   = 0;
-    int     colons = 0;
-    mDNSu8  val    = 0;
-
-    for (i = 0; ptr < limit && *ptr != ' ' && i < 17; i++, ptr++)
-    {
-        hval = HexVal(*ptr);
-        if (hval != -1)
-        {
-            val <<= 4;
-            val |= hval;
-        }
-        else if (*ptr == ':')
-        {
-            if (colons >=5)
-            {
-                LogMsg("GetValueForMACAddr: Address malformed colons %d val %d", colons, val);
-                return mDNSNULL;
-            }
-            eth->b[colons] = val;
-            colons++;
-            val = 0;
-        }
-    }
-    if (colons != 5)
-    {
-        LogMsg("GetValueForMACAddr: Address malformed colons %d", colons);
-        return mDNSNULL;
-    }
-    eth->b[colons] = val;
-    return ptr;
-}
-
-mDNSlocal mDNSu8 *GetValueForIPv6Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv6Addr *v6)
-{
-    int hval;
-    int value;
-    int numBytes;
-    int digitsProcessed;
-    int zeroFillStart;
-    int numColons;
-    mDNSu8 v6addr[16];
-
-    // RFC 3513: Section 2.2 specifies IPv6 presentation format. The following parsing
-    // handles both (1) and (2) and does not handle embedded IPv4 addresses.
-    //
-    // First forms a address in "v6addr", then expands to fill the zeroes in and returns
-    // the result in "v6"
-
-    numColons = numBytes = value = digitsProcessed = zeroFillStart = 0;
-    while (ptr < limit && *ptr != ' ')
-    {
-        hval = HexVal(*ptr);
-        if (hval != -1)
-        {
-            value <<= 4;
-            value |= hval;
-            digitsProcessed = 1;
-        }
-        else if (*ptr == ':')
-        {
-            if (!digitsProcessed)
-            {
-                // If we have already seen a "::", we should not see one more. Handle the special
-                // case of "::"
-                if (numColons)
-                {
-                    // if we never filled any bytes and the next character is space (we have reached the end)
-                    // we are done
-                    if (!numBytes && (ptr + 1) < limit && *(ptr + 1) == ' ')
-                    {
-                        mDNSPlatformMemZero(v6->b, 16);
-                        return ptr + 1;
-                    }
-                    LogMsg("GetValueForIPv6Addr: zeroFillStart non-zero %d", zeroFillStart);
-                    return mDNSNULL;
-                }
-
-                // We processed "::". We need to fill zeroes later. For now, mark the
-                // point where we will start filling zeroes from.
-                zeroFillStart = numBytes;
-                numColons++;
-            }
-            else if ((ptr + 1) < limit && *(ptr + 1) == ' ')
-            {
-                // We have a trailing ":" i.e., no more characters after ":"
-                LogMsg("GetValueForIPv6Addr: Trailing colon");
-                return mDNSNULL;
-            }
-            else
-            {
-                // For a fully expanded IPv6 address, we fill the 14th and 15th byte outside of this while
-                // loop below as there is no ":" at the end. Hence, the last two bytes that can possibly
-                // filled here is 12 and 13.
-                if (numBytes > 13) { LogMsg("GetValueForIPv6Addr:1: numBytes is %d", numBytes); return mDNSNULL; }
-
-                v6addr[numBytes++] = (mDNSu8) ((value >> 8) & 0xFF);
-                v6addr[numBytes++] = (mDNSu8) (value & 0xFF);
-                digitsProcessed = value = 0;
-
-                // Make sure that we did not fill the 13th and 14th byte above
-                if (numBytes > 14) { LogMsg("GetValueForIPv6Addr:2: numBytes is %d", numBytes); return mDNSNULL; }
-            }
-        }
-        ptr++;
-    }
-
-    // We should be processing the last set of bytes following the last ":" here
-    if (!digitsProcessed)
-    {
-        LogMsg("GetValueForIPv6Addr: no trailing bytes after colon, numBytes is %d", numBytes);
-        return mDNSNULL;
-    }
-
-    if (numBytes > 14) { LogMsg("GetValueForIPv6Addr:3: numBytes is %d", numBytes); return mDNSNULL; }
-    v6addr[numBytes++] = (mDNSu8) ((value >> 8) & 0xFF);
-    v6addr[numBytes++] = (mDNSu8) (value & 0xFF);
-
-    if (zeroFillStart)
-    {
-        int i, j, n;
-        for (i = 0; i < zeroFillStart; i++)
-            v6->b[i] = v6addr[i];
-        for (j = i, n = 0; n < 16 - numBytes; j++, n++)
-            v6->b[j] = 0;
-        for (; j < 16; i++, j++)
-            v6->b[j] = v6addr[i];
-    }
-    else if (numBytes == 16)
-        mDNSPlatformMemCopy(v6->b, v6addr, 16);
-    else
-    {
-        LogMsg("GetValueForIPv6addr: Not enough bytes for IPv6 address, numBytes is %d", numBytes);
-        return mDNSNULL;
-    }
-    return ptr;
-}
-
-mDNSlocal mDNSu8 *GetValueForIPv4Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv4Addr *v4)
-{
-    mDNSu32 val;
-    int dots = 0;
-    val = 0;
-
-    for ( ; ptr < limit && *ptr != ' '; ptr++)
-    {
-        if (*ptr >= '0' &&  *ptr <= '9')
-            val = val * 10 + *ptr - '0';
-        else if (*ptr == '.')
-        {
-            if (val > 255 || dots >= 3)
-            {
-                LogMsg("GetValueForIPv4Addr: something wrong ptr(%p) %c, limit %p, dots %d", ptr, *ptr, limit, dots);
-                return mDNSNULL;
-            }
-            v4->b[dots++] = val;
-            val = 0;
-        }
-        else
-        {
-            // We have a zero at the end and if we reached that, then we are done.
-            if (*ptr == 0 && ptr == limit - 1 && dots == 3)
-            {
-                v4->b[dots] = val;
-                return ptr + 1;
-            }
-            else { LogMsg("GetValueForIPv4Addr: something wrong ptr(%p) %c, limit %p, dots %d", ptr, *ptr, limit, dots); return mDNSNULL; }
-        }
-    }
-    if (dots != 3) { LogMsg("GetValueForIPv4Addr: Address malformed dots %d", dots); return mDNSNULL; }
-    v4->b[dots] = val;
-    return ptr;
-}
-
-mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *value)
-{
-    mDNSu32 val;
-
-    val = 0;
-    for ( ; ptr < limit && *ptr != ' '; ptr++)
-    {
-        if (*ptr < '0' || *ptr > '9')
-        {
-            // We have a zero at the end and if we reached that, then we are done.
-            if (*ptr == 0 && ptr == limit - 1)
-            {
-                *value = val;
-                return ptr + 1;
-            }
-            else { LogMsg("GetValueForKeepalive: *ptr %d, ptr %p, limit %p, ptr +1 %d", *ptr, ptr, limit, *(ptr + 1)); return mDNSNULL; }
-        }
-        val = val * 10 + *ptr - '0';
-    }
-    *value = val;
-    return ptr;
-}
-
-mDNSexport mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr)
-{
-    mDNSAddr    laddr, raddr;
-    mDNSEthAddr eth;
-    mDNSIPPort  lport, rport;
-    mDNSu32     timeout, seq, ack;
-    mDNSu16     win;
-
-    if (!mDNS_KeepaliveRecord(&rr->resrec))
-    {
-        return mDNSfalse;
-    }
-
-    timeout = seq = ack = 0;
-    win = 0;
-    laddr = raddr = zeroAddr;
-    lport = rport = zeroIPPort;
-    eth = zeroEthAddr;
-
-    mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
-
-    if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) ||
-        mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) ||
-        mDNSEthAddressIsZero(eth))
-    {
-        return mDNSfalse;
-    }
-
-    return mDNStrue;
-}
-
-
-mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, mDNSu32 *seq,
-                                         mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win)
-{
-    if (ar->resrec.rrtype != kDNSType_NULL)
-        return;
-
-    if (mDNS_KeepaliveRecord(&ar->resrec))
-    {
-        int len = ar->resrec.rdlength;
-        mDNSu8 *ptr = &ar->resrec.rdata->u.txt.c[1];
-        mDNSu8 *limit = ptr + len - 1; // Exclude the first byte that is the length
-        mDNSu32 value = 0;
-
-        while (ptr < limit)
-        {
-            mDNSu8 param = *ptr;
-            ptr += 2;   // Skip the letter and the "="
-            if (param == 'h')
-            {
-                laddr->type = mDNSAddrType_IPv4;
-                ptr = GetValueForIPv4Addr(ptr, limit, &laddr->ip.v4);
-            }
-            else if (param == 'd')
-            {
-                raddr->type = mDNSAddrType_IPv4;
-                ptr = GetValueForIPv4Addr(ptr, limit, &raddr->ip.v4);
-            }
-            else if (param == 'H')
-            {
-                laddr->type = mDNSAddrType_IPv6;
-                ptr = GetValueForIPv6Addr(ptr, limit, &laddr->ip.v6);
-            }
-            else if (param == 'D')
-            {
-                raddr->type = mDNSAddrType_IPv6;
-                ptr = GetValueForIPv6Addr(ptr, limit, &raddr->ip.v6);
-            }
-            else if (param == 'm')
-            {
-                ptr = GetValueForMACAddr(ptr, limit, eth);
-            }
-            else
-            {
-                ptr = GetValueForKeepalive(ptr, limit, &value);
-            }
-            if (!ptr)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_ExtractKeepaliveInfo: Cannot parse\n");
-                return;
-            }
-
-            // Extract everything in network order so that it is easy for sending a keepalive and also
-            // for matching incoming TCP packets
-            switch (param)
-            {
-            case 't':
-                *timeout = value;
-                //if (*timeout < 120) *timeout = 120;
-                break;
-            case 'h':
-            case 'H':
-            case 'd':
-            case 'D':
-            case 'm':
-            case 'i':
-            case 'c':
-                break;
-            case 'l':
-                lport->NotAnInteger = swap16((mDNSu16)value);
-                break;
-            case 'r':
-                rport->NotAnInteger = swap16((mDNSu16)value);
-                break;
-            case 's':
-                *seq = swap32(value);
-                break;
-            case 'a':
-                *ack = swap32(value);
-                break;
-            case 'w':
-                *win = swap16((mDNSu16)value);
-                break;
-            default:
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_ExtractKeepaliveInfo: unknown value %c\n", param);
-                ptr = limit;
-                break;
-            }
-            ptr++; // skip the space
-        }
-    }
-}
-
-// Matches the proxied auth records to the incoming TCP packet and returns the match and its sequence and ack in "rseq" and "rack" so that
-// the clients need not retrieve this information from the auth record again.
-mDNSlocal AuthRecord* mDNS_MatchKeepaliveInfo(mDNS *const m, const mDNSAddr* pladdr, const mDNSAddr* praddr, const mDNSIPPort plport,
-                                              const mDNSIPPort prport, mDNSu32 *rseq, mDNSu32 *rack)
-{
-    AuthRecord *ar;
-    mDNSAddr laddr, raddr;
-    mDNSEthAddr eth;
-    mDNSIPPort lport, rport;
-    mDNSu32 timeout, seq, ack;
-    mDNSu16 win;
-
-    for (ar = m->ResourceRecords; ar; ar=ar->next)
-    {
-        timeout = seq = ack = 0;
-        win = 0;
-        laddr = raddr = zeroAddr;
-        lport = rport = zeroIPPort;
-
-        if (!ar->WakeUp.HMAC.l[0]) continue;
-
-        mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
-
-        // Did we parse correctly ?
-        if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win)
-        {
-            debugf("mDNS_MatchKeepaliveInfo: not a valid record %s for keepalive", ARDisplayString(m, ar));
-            continue;
-        }
-
-        debugf("mDNS_MatchKeepaliveInfo: laddr %#a pladdr %#a, raddr %#a praddr %#a, lport %d plport %d, rport %d prport %d",
-               &laddr, pladdr, &raddr, praddr, mDNSVal16(lport), mDNSVal16(plport), mDNSVal16(rport), mDNSVal16(prport));
-
-        // Does it match the incoming TCP packet ?
-        if (mDNSSameAddress(&laddr, pladdr) && mDNSSameAddress(&raddr, praddr) && mDNSSameIPPort(lport, plport) && mDNSSameIPPort(rport, prport))
-        {
-            // returning in network order
-            *rseq = seq;
-            *rack = ack;
-            return ar;
-        }
-    }
-    return mDNSNULL;
-}
-
-mDNSlocal void mDNS_SendKeepalives(mDNS *const m)
-{
-    AuthRecord *ar;
-
-    for (ar = m->ResourceRecords; ar; ar=ar->next)
-    {
-        mDNSu32 timeout, seq, ack;
-        mDNSu16 win;
-        mDNSAddr laddr, raddr;
-        mDNSEthAddr eth;
-        mDNSIPPort lport, rport;
-
-        timeout = seq = ack = 0;
-        win = 0;
-
-        laddr = raddr = zeroAddr;
-        lport = rport = zeroIPPort;
-
-        if (!ar->WakeUp.HMAC.l[0]) continue;
-
-        mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
-
-        if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win)
-        {
-            debugf("mDNS_SendKeepalives: not a valid record %s for keepalive", ARDisplayString(m, ar));
-            continue;
-        }
-        LogMsg("mDNS_SendKeepalives: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport));
-
-        // When we receive a proxy update, we set KATimeExpire to zero so that we always send a keepalive
-        // immediately (to detect any potential problems). After that we always set it to a non-zero value.
-        if (!ar->KATimeExpire || (m->timenow - ar->KATimeExpire >= 0))
-        {
-            mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win);
-            ar->KATimeExpire = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
-        }
-        if (m->NextScheduledKA - ar->KATimeExpire > 0)
-            m->NextScheduledKA = ar->KATimeExpire;
-    }
-}
-
-mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar)
-{
-    mDNSu32     timeout, seq, ack, seqInc;
-    mDNSu16     win;
-    mDNSAddr    laddr, raddr;
-    mDNSEthAddr eth;
-    mDNSIPPort  lport, rport;
-    mDNSu8      *ptr;
-
-    if (ar == mDNSNULL)
-    {
-        LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL");
-        return;
-    }
-
-    timeout = seq = ack = 0;
-    win = 0;
-
-    laddr = raddr = zeroAddr;
-    lport = rport = zeroIPPort;
-
-    mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
-
-    if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win)
-    {
-        LogInfo("mDNS_SendKeepaliveACK: not a valid record %s for keepalive", ARDisplayString(m, ar));
-        return;
-    }
-
-    // To send a keepalive ACK, we need to add one to the sequence number from the keepalive
-    // record, which is the TCP connection's "next" sequence number minus one. Otherwise, the
-    // keepalive ACK also ends up being a keepalive probe. Also, seq is in network byte order, so
-    // it's converted to host byte order before incrementing it by one.
-    ptr = (mDNSu8 *)&seq;
-    seqInc = (mDNSu32)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]) + 1;
-    ptr[0] = (mDNSu8)((seqInc >> 24) & 0xFF);
-    ptr[1] = (mDNSu8)((seqInc >> 16) & 0xFF);
-    ptr[2] = (mDNSu8)((seqInc >>  8) & 0xFF);
-    ptr[3] = (mDNSu8)((seqInc      ) & 0xFF);
-    LogMsg("mDNS_SendKeepaliveACK: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport));
-    mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win);
-}
-
-mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m,
-                                     const DNSMessage *const msg, const mDNSu8 *end,
-                                     const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
-                                     const mDNSInterfaceID InterfaceID)
-{
-    int i;
-    AuthRecord opt;
-    mDNSu8 *p = m->omsg.data;
-    OwnerOptData owner = zeroOwner;     // Need to zero this, so we'll know if this Update packet was missing its Owner option
-    mDNSu32 updatelease = 0;
-    const mDNSu8 *ptr;
-
-    LogSPS("Received Update from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
-           "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
-           srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), 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", end - msg->data);
-
-    if (!InterfaceID || !m->SPSSocket || !mDNSSameIPPort(dstport, m->SPSSocket->port)) return;
-
-    if (mDNS_PacketLoggingEnabled)
-        DumpPacket(mStatus_NoError, mDNSfalse, "UDP", srcaddr, srcport, dstaddr, dstport, msg, end, InterfaceID);
-
-    ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space + DNSOpt_OwnerData_ID_Space);
-    if (ptr)
-    {
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-        if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT)
-        {
-            const rdataOPT *o;
-            const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
-            for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
-            {
-                if      (o->opt == kDNSOpt_Lease) updatelease = o->u.updatelease;
-                else if (o->opt == kDNSOpt_Owner && o->u.owner.vers == 0) owner       = o->u.owner;
-            }
-        }
-        mDNSCoreResetRecord(m);
-    }
-
-    InitializeDNSMessage(&m->omsg.h, msg->h.id, UpdateRespFlags);
-
-    if (!updatelease || !owner.HMAC.l[0])
-    {
-        static int msgs = 0;
-        if (msgs < 100)
-        {
-            msgs++;
-            LogMsg("Refusing sleep proxy registration from %#a:%d:%s%s", srcaddr, mDNSVal16(srcport),
-                   !updatelease ? " No lease" : "", !owner.HMAC.l[0] ? " No owner" : "");
-        }
-        m->omsg.h.flags.b[1] |= kDNSFlag1_RC_FormErr;
-    }
-    else if (m->ProxyRecords + msg->h.mDNS_numUpdates > MAX_PROXY_RECORDS)
-    {
-        static int msgs = 0;
-        if (msgs < 100)
-        {
-            msgs++;
-            LogMsg("Refusing sleep proxy registration from %#a:%d: Too many records %d + %d = %d > %d", srcaddr, mDNSVal16(srcport),
-                   m->ProxyRecords, msg->h.mDNS_numUpdates, m->ProxyRecords + msg->h.mDNS_numUpdates, MAX_PROXY_RECORDS);
-        }
-        m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused;
-    }
-    else
-    {
-        LogSPS("Received Update for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
-
-        if (updatelease > 24 * 60 * 60)
-            updatelease = 24 * 60 * 60;
-
-        if (updatelease > 0x40000000UL / mDNSPlatformOneSecond)
-            updatelease = 0x40000000UL / mDNSPlatformOneSecond;
-
-        ptr = LocateAuthorities(msg, end);
-
-        // Clear any stale TCP keepalive records that may exist
-        ClearKeepaliveProxyRecords(m, &owner, m->DuplicateRecords, InterfaceID);
-        ClearKeepaliveProxyRecords(m, &owner, m->ResourceRecords, InterfaceID);
-
-        for (i = 0; i < msg->h.mDNS_numUpdates && ptr && ptr < end; i++)
-        {
-            ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-            if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative)
-            {
-                mDNSu16 RDLengthMem = GetRDLengthMem(&m->rec.r.resrec);
-                AuthRecord *ar = (AuthRecord *) mDNSPlatformMemAllocateClear(sizeof(AuthRecord) - sizeof(RDataBody) + RDLengthMem);
-                if (!ar)
-                {
-                    m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused;
-                    break;
-                }
-                else
-                {
-                    mDNSu8 RecordType = m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask ? kDNSRecordTypeUnique : kDNSRecordTypeShared;
-                    m->rec.r.resrec.rrclass &= ~kDNSClass_UniqueRRSet;
-                    // All stale keepalive records have been flushed prior to this loop.
-                    if (!mDNS_KeepaliveRecord(&m->rec.r.resrec))
-                    {
-                        ClearIdenticalProxyRecords(m, &owner, m->DuplicateRecords); // Make sure we don't have any old stale duplicates of this record
-                        ClearIdenticalProxyRecords(m, &owner, m->ResourceRecords);
-                    }
-                    mDNS_SetupResourceRecord(ar, mDNSNULL, InterfaceID, m->rec.r.resrec.rrtype, m->rec.r.resrec.rroriginalttl, RecordType, AuthRecordAny, SPSRecordCallback, ar);
-                    AssignDomainName(&ar->namestorage, m->rec.r.resrec.name);
-                    ar->resrec.rdlength = GetRDLength(&m->rec.r.resrec, mDNSfalse);
-                    ar->resrec.rdata->MaxRDLength = RDLengthMem;
-                    mDNSPlatformMemCopy(ar->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, RDLengthMem);
-                    ar->ForceMCast = mDNStrue;
-                    ar->WakeUp     = owner;
-                    if (m->rec.r.resrec.rrtype == kDNSType_PTR)
-                    {
-                        mDNSs32 t = ReverseMapDomainType(m->rec.r.resrec.name);
-                        if      (t == mDNSAddrType_IPv4) GetIPv4FromName(&ar->AddressProxy, m->rec.r.resrec.name);
-                        else if (t == mDNSAddrType_IPv6) GetIPv6FromName(&ar->AddressProxy, m->rec.r.resrec.name);
-                        debugf("mDNSCoreReceiveUpdate: PTR %d %d %#a %s", t, ar->AddressProxy.type, &ar->AddressProxy, ARDisplayString(m, ar));
-                        if (ar->AddressProxy.type) SetSPSProxyListChanged(InterfaceID);
-                    }
-                    ar->TimeRcvd   = m->timenow;
-                    ar->TimeExpire = m->timenow + updatelease * mDNSPlatformOneSecond;
-                    if (m->NextScheduledSPS - ar->TimeExpire > 0)
-                        m->NextScheduledSPS = ar->TimeExpire;
-                    ar->KATimeExpire = 0;
-                    mDNS_Register_internal(m, ar);
-
-                    m->ProxyRecords++;
-                    mDNS_UpdateAllowSleep(m);
-                    LogSPS("SPS Registered %4d %X %s", m->ProxyRecords, RecordType, ARDisplayString(m,ar));
-                }
-            }
-            mDNSCoreResetRecord(m);
-        }
-
-        if (m->omsg.h.flags.b[1] & kDNSFlag1_RC_Mask)
-        {
-            LogMsg("Refusing sleep proxy registration from %#a:%d: Out of memory", srcaddr, mDNSVal16(srcport));
-            ClearProxyRecords(m, &owner, m->DuplicateRecords);
-            ClearProxyRecords(m, &owner, m->ResourceRecords);
-        }
-        else
-        {
-            mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-            opt.resrec.rrclass    = NormalMaxDNSMessageData;
-            opt.resrec.rdlength   = sizeof(rdataOPT);   // One option in this OPT record
-            opt.resrec.rdestimate = sizeof(rdataOPT);
-            opt.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
-            opt.resrec.rdata->u.opt[0].u.updatelease = updatelease;
-            p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
-        }
-    }
-
-    if (p) mDNSSendDNSMessage(m, &m->omsg, p, InterfaceID, mDNSNULL, m->SPSSocket, srcaddr, srcport, mDNSNULL, mDNSfalse);
-    mDNS_SendKeepalives(m);
-}
-
-mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInterfaceID InterfaceID, DNSMessage *msg)
-{
-    mDNSu8 *ptr    = msg->data;
-    mDNSu8 *end    = mDNSNULL;
-    mDNSu32 length = 0;
-    AuthRecord opt;
-    NetworkInterfaceInfo *intf;
-
-    mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-    opt.resrec.rrclass    = NormalMaxDNSMessageData;
-    opt.resrec.rdlength   = sizeof(rdataOPT);
-    opt.resrec.rdestimate = sizeof(rdataOPT);
-
-    intf = FirstInterfaceForID(m, InterfaceID);
-    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
-
-    LogSPS("Generated OPT record : %s", ARDisplayString(m, &opt));
-    end = PutResourceRecord(msg, ptr, &msg->h.numAdditionals, &opt.resrec);
-    if (end != mDNSNULL)
-    {
-        // Put all the integer values in IETF byte-order (MSB first, LSB second)
-        SwapDNSHeaderBytes(msg);
-        length = (mDNSu32)(end - msg->data);
-    }
-    else
-        LogSPS("mDNSGenerateOwnerOptForInterface: Failed to generate owner OPT record");
-
-    return length;
-}
-
-// Note that this routine is called both for Sleep Proxy Registrations, and for Standard Dynamic
-// DNS registrations, but (currently) only has to handle the Sleep Proxy Registration reply case,
-// and should ignore Standard Dynamic DNS registration replies, because those are handled elsewhere.
-// Really, both should be unified and handled in one place.
-mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID)
-{
-    if (InterfaceID)
-    {
-        mDNSu32 pktlease = 0, spsupdates = 0;
-        const mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease);
-        const mDNSu32 updatelease = gotlease ? pktlease : 60 * 60; // If SPS fails to indicate lease time, assume one hour
-        if (gotlease) LogSPS("DNS Update response contains lease option granting %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID);
-
-        if (m->CurrentRecord)
-            LogMsg("mDNSCoreReceiveUpdateR ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-        m->CurrentRecord = m->ResourceRecords;
-        while (m->CurrentRecord)
-        {
-            AuthRecord *const rr = m->CurrentRecord;
-            if (rr->resrec.InterfaceID == InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
-                if (mDNSSameOpaque16(rr->updateid, msg->h.id))
-                {
-                    // We successfully completed this record's registration on this "InterfaceID". Clear that bit.
-                    // Clear the updateid when we are done sending on all interfaces.
-                    mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
-                    if (scopeid < (sizeof(rr->updateIntID) * mDNSNBBY))
-                        bit_clr_opaque64(rr->updateIntID, scopeid);
-                    if (mDNSOpaque64IsZero(&rr->updateIntID))
-                        rr->updateid = zeroID;
-                    rr->expire   = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond);
-                    spsupdates++;
-                    LogSPS("Sleep Proxy %s record %2d %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", spsupdates, updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr));
-                    if (rr->WakeUp.HMAC.l[0])
-                    {
-                        rr->WakeUp.HMAC = zeroEthAddr;  // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
-                        rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it
-                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                    }
-                }
-            // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-            // new records could have been added to the end of the list as a result of that call.
-            if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-                m->CurrentRecord = rr->next;
-        }
-        if (spsupdates) // Only do this dynamic store stuff if this was, in fact, a Sleep Proxy Update response
-        {
-            char *ifname;
-            mDNSAddr spsaddr;
-            DNSMessage optMsg;
-            int length;
-            // Update the dynamic store with the IP Address and MAC address of the sleep proxy
-            ifname = InterfaceNameForID(m, InterfaceID);
-            mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr));
-            mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname);
-
-            // Store the Owner OPT record for this interface.
-            // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up
-            InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags);
-            length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg);
-            if (length != 0)
-            {
-                length += sizeof(DNSMessageHeader);
-                mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length);
-            }
-        }
-    }
-    // If we were waiting to go to sleep, then this SPS registration or wide-area record deletion
-    // may have been the thing we were waiting for, so schedule another check to see if we can sleep now.
-    if (m->SleepLimit) m->NextScheduledSPRetry = m->timenow;
-}
-
-mDNSlocal void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, const domainname *const name,
-    const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, const mDNSu32 ttl,
-    const mDNSInterfaceID InterfaceID, const DNSServRef dnsserv, const mDNSOpaque16 responseFlags)
-{
-    if (cr == &m->rec.r && m->rec.r.resrec.RecordType)
-        LogFatalError("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
-
-    // Create empty resource record
-    cr->resrec.RecordType    = kDNSRecordTypePacketNegative;
-    cr->resrec.InterfaceID   = InterfaceID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_replace(&cr->resrec.dnsservice, dnsserv);
-#else
-    cr->resrec.rDNSServer    = dnsserv;
-#endif
-    cr->resrec.name          = name;    // Will be updated to point to cg->name when we call CreateNewCacheEntry
-    cr->resrec.rrtype        = rrtype;
-    cr->resrec.rrclass       = rrclass;
-    cr->resrec.rroriginalttl = ttl;
-    cr->resrec.rdlength      = 0;
-    cr->resrec.rdestimate    = 0;
-    cr->resrec.namehash      = namehash;
-    cr->resrec.rdatahash     = 0;
-    cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
-    cr->resrec.rdata->MaxRDLength = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    cr->resrec.dnssec = mDNSNULL;
-#endif
-
-    cr->NextInKAList         = mDNSNULL;
-    cr->TimeRcvd             = m->timenow;
-    cr->DelayDelivery        = 0;
-    cr->NextRequiredQuery    = m->timenow;
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-    cr->LastCachedAnswerTime = 0;
-#endif
-    cr->CRActiveQuestion     = mDNSNULL;
-    cr->UnansweredQueries    = 0;
-    cr->LastUnansweredTime   = 0;
-    cr->NextInCFList         = mDNSNULL;
-    cr->soa                  = mDNSNULL;
-    CacheRecordSetResponseFlags(cr, responseFlags);
-}
-
-mDNSexport void MakeNegativeCacheRecordForQuestion(mDNS *const m, CacheRecord *const cr, const DNSQuestion *const q,
-    const mDNSu32 ttl, const mDNSInterfaceID InterfaceID, const mDNSOpaque16 responseFlags)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const DNSServRef dnsserv = q->dnsservice;
-#else
-    const DNSServRef dnsserv = q->qDNSServer;
-#endif
-    MakeNegativeCacheRecord(m, cr, &q->qname, q->qnamehash, q->qtype, q->qclass, ttl, InterfaceID, dnsserv, responseFlags);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport void mDNSCoreReceiveForQuerier(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-    mdns_querier_t querier, mdns_dns_service_t dnsservice)
-{
-    SwapDNSHeaderBytes(msg);
-    mDNS_Lock(m);
-    mDNSCoreReceiveResponse(m, msg, end, mDNSNULL, zeroIPPort, mDNSNULL, zeroIPPort, querier, dnsservice, mDNSNULL);
-    mDNS_Unlock(m);
-}
-#endif
-
-mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-                                const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport,
-                                const mDNSInterfaceID InterfaceID)
-{
-    mDNSInterfaceID ifid = InterfaceID;
-    const mDNSu8 *const pkt = (mDNSu8 *)msg;
-    const mDNSu8 StdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery;
-    const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
-    const mDNSu8 UpdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update;
-    const mDNSu8 UpdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
-    mDNSu8 QR_OP;
-    mDNSu8 *ptr = mDNSNULL;
-    mDNSBool TLS = (dstaddr == (mDNSAddr *)1);  // For debug logs: dstaddr = 0 means TCP; dstaddr = 1 means TLS
-    if (TLS) dstaddr = mDNSNULL;
-
-#ifndef UNICAST_DISABLED
-    if (mDNSSameAddress(srcaddr, &m->Router))
-    {
-#ifdef _LEGACY_NAT_TRAVERSAL_
-        if (mDNSSameIPPort(srcport, SSDPPort) || (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)))
-        {
-            mDNS_Lock(m);
-            LNT_ConfigureRouterInfo(m, InterfaceID, (mDNSu8 *)msg, (mDNSu16)(end - pkt));
-            mDNS_Unlock(m);
-            return;
-        }
-#endif
-        if (mDNSSameIPPort(srcport, NATPMPPort))
-        {
-            mDNS_Lock(m);
-            uDNS_ReceiveNATPacket(m, InterfaceID, (mDNSu8 *)msg, (mDNSu16)(end - pkt));
-            mDNS_Unlock(m);
-            return;
-        }
-    }
-#ifdef _LEGACY_NAT_TRAVERSAL_
-    else if (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)) { debugf("Ignoring SSDP response from %#a:%d", srcaddr, mDNSVal16(srcport)); return; }
-#endif
-
-#endif
-    if ((unsigned)(end - pkt) < sizeof(DNSMessageHeader))
-    {
-        LogMsg("DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt));
-        return;
-    }
-    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)
-    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);
-    m->PktNum++;
-    if (mDNSOpaque16IsZero(msg->h.id))
-    {
-        m->MPktNum++;
-    }
-
-#ifndef UNICAST_DISABLED
-    if (!dstaddr || (!mDNSAddressIsAllDNSLinkGroup(dstaddr) && (QR_OP == StdR || QR_OP == UpdR)))
-        if (!mDNSOpaque16IsZero(msg->h.id)) // uDNS_ReceiveMsg only needs to get real uDNS responses, not "QU" mDNS responses
-        {
-            ifid = mDNSInterface_Any;
-            if (mDNS_PacketLoggingEnabled)
-                DumpPacket(mStatus_NoError, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end, InterfaceID);
-            uDNS_ReceiveMsg(m, msg, end, srcaddr, srcport);
-            // Note: mDNSCore also needs to get access to received unicast responses
-        }
-#endif
-    if      (QR_OP == StdQ) mDNSCoreReceiveQuery   (m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, srcport, dstaddr, dstport, mDNSNULL, mDNSNULL, ifid);
-#else
-    else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
-#endif
-    else if (QR_OP == UpdQ) mDNSCoreReceiveUpdate  (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID);
-    else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end, srcaddr,                            InterfaceID);
-    else
-    {
-        if (mDNS_LoggingEnabled)
-        {
-            static int msgCount = 0;
-            if (msgCount < 1000) {
-                int i = 0;
-                msgCount++;
-                LogInfo("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
-                        msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt), InterfaceID);
-                while (i < (int)(end - pkt))
-                {
-                    char buffer[128];
-                    char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i);
-                    do if (i < (int)(end - pkt)) p += mDNS_snprintf(p, sizeof(buffer), " %02X", pkt[i]);while (++i & 15);
-                    LogInfo("%s", buffer);
-                }
-            }
-        }
-    }
-    // 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);
-}
-
-// ***************************************************************************
-// MARK: - Searcher Functions
-
-// Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the
-// circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV"
-// and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails
-// doing a standard DNS query for the _dns-query-tls._tcp SRV record for company.com. If we make the latter (public) query
-// a duplicate of the former (private) query, then it will block forever waiting for an answer that will never come.
-//
-// We keep SuppressUnusable questions separate so that we can return a quick response to them and not get blocked behind
-// the queries that are not marked SuppressUnusable. But if the query is not suppressed, they are treated the same as
-// non-SuppressUnusable questions. This should be fine as the goal of SuppressUnusable is to return quickly only if it
-// is suppressed. If it is not suppressed, we do try all the DNS servers for valid answers like any other question.
-// The main reason for this design is that cache entries point to a *single* question and that question is responsible
-// for keeping the cache fresh as long as it is active. Having multiple active question for a single cache entry
-// breaks this design principle.
-//
-
-// If IsLLQ(Q) is true, it means the question is both:
-// (a) long-lived and
-// (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling)
-// for multicast questions, we don't want to treat LongLived as anything special
-#define IsLLQ(Q)                 ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID))
-#define AWDLIsIncluded(Q)        (((Q)->flags & kDNSServiceFlagsIncludeAWDL) != 0)
-#define SameQuestionKind(Q1, Q2) (mDNSOpaque16IsZero((Q1)->TargetQID) == mDNSOpaque16IsZero((Q2)->TargetQID))
-
-mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
-{
-    DNSQuestion *q;
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-    const mDNSBool questionSendsUnicastMDNSQueries = QuestionSendsMDNSQueriesViaUnicast(question);
-#endif
-    // 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)
-    {
-        if (!SameQuestionKind(q, question))                             continue;
-        if (q->qnamehash          != question->qnamehash)               continue;
-        if (q->InterfaceID        != question->InterfaceID)             continue;
-        if (q->qtype              != question->qtype)                   continue;
-        if (q->qclass             != question->qclass)                  continue;
-        if (IsLLQ(q)              != IsLLQ(question))                   continue;
-        if (q->AuthInfo && !question->AuthInfo)                         continue;
-        if (!q->Suppressed        != !question->Suppressed)             continue;
-        if (q->BrowseThreshold    != question->BrowseThreshold)         continue;
-        if (AWDLIsIncluded(q)     != AWDLIsIncluded(question))          continue;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (q->dnsservice         != question->dnsservice)              continue;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // DNSSEC-disabled question cannot be duped to DNSSEC-enabled question, vice versa.
-        if (!q->enableDNSSEC      != !question->enableDNSSEC)                   continue;
-        // If enables DNSSEC, the question being duped to must be a primary DNSSEC requestor.
-        if (q->enableDNSSEC && !dns_question_is_primary_dnssec_requestor(q))    continue;
-#endif
-        if (!SameDomainName(&q->qname, &question->qname))               continue;
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-        if (questionSendsUnicastMDNSQueries)
-        {
-            // If question sends mDNS queries via unicast, then q must also send mDNS queries via
-            // unicast and to the same mDNS resolver address.
-            const mDNSAddr *const addr1 = &question->UnicastMDNSResolver;
-            const mDNSAddr *const addr2 = &q->UnicastMDNSResolver;
-            if (!QuestionSendsMDNSQueriesViaUnicast(q)) continue;
-            if (!mDNSSameAddress(addr1, addr2))         continue;
-        }
-        else
-        {
-            // Otherwise, q must also not send mDNS queries via unicast.
-            if (QuestionSendsMDNSQueriesViaUnicast(q))  continue;
-        }
-#endif
-        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, DNSQuestion *const question)
-{
-    DNSQuestion *q;
-    DNSQuestion *first = mDNSNULL;
-
-    // This is referring to some other question as duplicate. No other question can refer to this
-    // question as a duplicate.
-    if (question->DuplicateOf)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%d->DupQ%d->Q%d] UpdateQuestionDuplicates: question %p " PRI_DM_NAME " (" PUB_S
-            ") duplicate of %p " PRI_DM_NAME " (" PUB_S ")",
-            question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(question->DuplicateOf->TargetQID),
-            question, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype), question->DuplicateOf,
-            DM_NAME_PARAM(&question->DuplicateOf->qname), DNSTypeName(question->DuplicateOf->qtype));
-        return;
-    }
-
-    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->DuplicateOf = first;
-            if (!first)
-            {
-                first = q;
-                // If q used to be a duplicate, but now is not,
-                // then inherit the state from the question that's going away
-                q->LastQTime         = question->LastQTime;
-                q->ThisQInterval     = question->ThisQInterval;
-                q->ExpectUnicastResp = question->ExpectUnicastResp;
-                q->LastAnswerPktNum  = question->LastAnswerPktNum;
-                q->RecentAnswerPkts  = question->RecentAnswerPkts;
-                q->RequestUnicast    = question->RequestUnicast;
-                q->LastQTxTime       = question->LastQTxTime;
-                q->CNAMEReferrals    = question->CNAMEReferrals;
-                q->nta               = question->nta;
-                q->servAddr          = question->servAddr;
-                q->servPort          = question->servPort;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                mdns_replace(&q->dnsservice, question->dnsservice);
-                mdns_forget(&question->dnsservice);
-                mdns_querier_forget(&q->querier);
-                mdns_replace(&q->querier, question->querier);
-                mdns_forget(&question->querier);
-#else
-                q->qDNSServer        = question->qDNSServer;
-                q->validDNSServers   = question->validDNSServers;
-                q->unansweredQueries = question->unansweredQueries;
-                q->noServerResponse  = question->noServerResponse;
-                q->triedAllServersOnce = question->triedAllServersOnce;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                // If this question is a primary DNSSEC question that does the validation work, transfer the work to
-                // its duplicate question, by making the duplicate question the primary one.
-                if (dns_question_is_primary_dnssec_requestor(question))
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_INFO, "[Q%u->Q%u] Non-primary DNSSEC question becomes primary due to primary question cancelation.",
-                        mDNSVal16(q->TargetQID), mDNSVal16(question->TargetQID));
-
-                    dns_question_update_primary_dnssec_requestor(q, question);
-                }
-#endif
-
-                q->TargetQID         = question->TargetQID;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                q->LocalSocket       = question->LocalSocket;
-                // No need to close old q->LocalSocket first -- duplicate questions can't have their own sockets
-#endif
-
-                q->state             = question->state;
-                //  q->tcp               = question->tcp;
-                q->ReqLease          = question->ReqLease;
-                q->expire            = question->expire;
-                q->ntries            = question->ntries;
-                q->id                = question->id;
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-                DNSPushUpdateQuestionDuplicate(question, q);
-#endif
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                question->LocalSocket = mDNSNULL;
-#endif
-                question->nta        = mDNSNULL;    // If we've got a GetZoneData in progress, transfer it to the newly active question
-                //  question->tcp        = mDNSNULL;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                if (q->LocalSocket)
-                    debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-#endif
-                if (q->nta)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "UpdateQuestionDuplicates transferred nta pointer for " PRI_DM_NAME " (" PUB_S ")",
-                        DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-                    q->nta->ZoneDataContext = q;
-                }
-
-                // Need to work out how to safely transfer this state too -- appropriate context pointers need to be updated or the code will crash
-                if (question->tcp) LogInfo("UpdateQuestionDuplicates did not transfer tcp pointer");
-
-                if (question->state == LLQ_Established)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "UpdateQuestionDuplicates transferred LLQ state for " PRI_DM_NAME " (" PUB_S ")",
-                        DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-                    question->state = LLQ_Invalid;    // Must zero question->state, or mDNS_StopQuery_internal will clean up and cancel our LLQ from the server
-                }
-
-                SetNextQueryTime(m,q);
-            }
-        }
-}
-
-mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout)
-{
-    McastResolver **p = &m->McastResolvers;
-    McastResolver *tmp = mDNSNULL;
-
-    if (!d) d = (const domainname *)"";
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "mDNS_AddMcastResolver: Adding " PUB_DM_NAME ", InterfaceID %p, timeout %u",
-        DM_NAME_PARAM(d), interface, timeout);
-
-    mDNS_CheckLock(m);
-
-    while (*p)  // Check if we already have this {interface, domain} tuple registered
-    {
-        if ((*p)->interface == interface && SameDomainName(&(*p)->domain, d))
-        {
-            if (!((*p)->flags & McastResolver_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface);
-            (*p)->flags &= ~McastResolver_FlagDelete;
-            tmp = *p;
-            *p = tmp->next;
-            tmp->next = mDNSNULL;
-        }
-        else
-            p=&(*p)->next;
-    }
-
-    if (tmp) *p = tmp; // move to end of list, to ensure ordering from platform layer
-    else
-    {
-        // allocate, add to list
-        *p = (McastResolver *) mDNSPlatformMemAllocateClear(sizeof(**p));
-        if (!*p) LogMsg("mDNS_AddMcastResolver: ERROR!! - malloc");
-        else
-        {
-            (*p)->interface = interface;
-            (*p)->flags     = McastResolver_FlagNew;
-            (*p)->timeout   = timeout;
-            AssignDomainName(&(*p)->domain, d);
-            (*p)->next = mDNSNULL;
-        }
-    }
-    return(*p);
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSinline mDNSs32 PenaltyTimeForServer(mDNS *m, DNSServer *server)
-{
-    mDNSs32 ptime = 0;
-    if (server->penaltyTime != 0)
-    {
-        ptime = server->penaltyTime - m->timenow;
-        if (ptime < 0)
-        {
-            // This should always be a positive value between 0 and DNSSERVER_PENALTY_TIME
-            // If it does not get reset in ResetDNSServerPenalties for some reason, we do it
-            // here
-            LogMsg("PenaltyTimeForServer: PenaltyTime negative %d, (server penaltyTime %d, timenow %d) resetting the penalty",
-                   ptime, server->penaltyTime, m->timenow);
-            server->penaltyTime = 0;
-            ptime = 0;
-        }
-    }
-    return ptime;
-}
-#endif
-
-//Checks to see whether the newname is a better match for the name, given the best one we have
-//seen so far (given in bestcount).
-//Returns -1 if the newname is not a better match
-//Returns 0 if the newname is the same as the old match
-//Returns 1 if the newname is a better match
-mDNSlocal int BetterMatchForName(const domainname *name, int namecount, const domainname *newname, int newcount,
-                                 int bestcount)
-{
-    // If the name contains fewer labels than the new server's domain or the new name
-    // contains fewer labels than the current best, then it can't possibly be a better match
-    if (namecount < newcount || newcount < bestcount) return -1;
-
-    // If there is no match, return -1 and the caller will skip this newname for
-    // selection
-    //
-    // If we find a match and the number of labels is the same as bestcount, then
-    // we return 0 so that the caller can do additional logic to pick one of
-    // the best based on some other factors e.g., penaltyTime
-    //
-    // If we find a match and the number of labels is more than bestcount, then we
-    // return 1 so that the caller can pick this over the old one.
-    //
-    // Note: newcount can either be equal or greater than bestcount beause of the
-    // check above.
-
-    if (SameDomainName(SkipLeadingLabels(name, namecount - newcount), newname))
-        return bestcount == newcount ? 0 : 1;
-    else
-        return -1;
-}
-
-// Normally, we have McastResolvers for .local, in-addr.arpa and ip6.arpa. But there
-// can be queries that can forced to multicast (ForceMCast) even though they don't end in these
-// names. In that case, we give a default timeout of 5 seconds
-mDNSlocal mDNSu32 GetTimeoutForMcastQuestion(mDNS *m, DNSQuestion *question)
-{
-    McastResolver *curmatch = mDNSNULL;
-    int bestmatchlen = -1, namecount = CountLabels(&question->qname);
-    McastResolver *curr;
-    int bettermatch, currcount;
-    for (curr = m->McastResolvers; curr; curr = curr->next)
-    {
-        currcount = CountLabels(&curr->domain);
-        bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
-        // Take the first best match. If there are multiple equally good matches (bettermatch = 0), we take
-        // the timeout value from the first one
-        if (bettermatch == 1)
-        {
-            curmatch = curr;
-            bestmatchlen = currcount;
-        }
-    }
-    LogInfo("GetTimeoutForMcastQuestion: question %##s curmatch %p, Timeout %d", question->qname.c, curmatch,
-            curmatch ? curmatch->timeout : DEFAULT_MCAST_TIMEOUT);
-    return ( curmatch ? curmatch->timeout : DEFAULT_MCAST_TIMEOUT);
-}
-
-// Returns true if it is a Domain Enumeration Query
-mDNSexport mDNSBool DomainEnumQuery(const domainname *qname)
-{
-    const mDNSu8 *mDNS_DEQLabels[] = { (const mDNSu8 *)"\001b", (const mDNSu8 *)"\002db", (const mDNSu8 *)"\002lb",
-                                       (const mDNSu8 *)"\001r", (const mDNSu8 *)"\002dr", (const mDNSu8 *)mDNSNULL, };
-    const domainname *d = qname;
-    const mDNSu8 *label;
-    int i = 0;
-
-    // We need at least 3 labels (DEQ prefix) + one more label to make a meaningful DE query
-    if (CountLabels(qname) < 4) { debugf("DomainEnumQuery: question %##s, not enough labels", qname->c); return mDNSfalse; }
-
-    label = (const mDNSu8 *)d;
-    while (mDNS_DEQLabels[i] != (const mDNSu8 *)mDNSNULL)
-    {
-        if (SameDomainLabel(mDNS_DEQLabels[i], label)) {debugf("DomainEnumQuery: DEQ %##s, label1 match", qname->c); break;}
-        i++;
-    }
-    if (mDNS_DEQLabels[i] == (const mDNSu8 *)mDNSNULL)
-    {
-        debugf("DomainEnumQuery: Not a DEQ %##s, label1 mismatch", qname->c);
-        return mDNSfalse;
-    }
-    debugf("DomainEnumQuery: DEQ %##s, label1 match", qname->c);
-
-    // CountLabels already verified the number of labels
-    d = (const domainname *)(d->c + 1 + d->c[0]);   // Second Label
-    label = (const mDNSu8 *)d;
-    if (!SameDomainLabel(label, (const mDNSu8 *)"\007_dns-sd"))
-    {
-        debugf("DomainEnumQuery: Not a DEQ %##s, label2 mismatch", qname->c);
-        return(mDNSfalse);
-    }
-    debugf("DomainEnumQuery: DEQ %##s, label2 match", qname->c);
-
-    d = (const domainname *)(d->c + 1 + d->c[0]);   // Third Label
-    label = (const mDNSu8 *)d;
-    if (!SameDomainLabel(label, (const mDNSu8 *)"\004_udp"))
-    {
-        debugf("DomainEnumQuery: Not a DEQ %##s, label3 mismatch", qname->c);
-        return(mDNSfalse);
-    }
-    debugf("DomainEnumQuery: DEQ %##s, label3 match", qname->c);
-
-    debugf("DomainEnumQuery: Question %##s is a Domain Enumeration query", qname->c);
-
-    return mDNStrue;
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-// Note: InterfaceID is the InterfaceID of the question
-mDNSlocal mDNSBool DNSServerMatch(DNSServer *d, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID)
-{
-    // 1) Unscoped questions (NULL InterfaceID) should consider *only* unscoped DNSServers ( DNSServer
-    // with scopeType set to kScopeNone)
-    //
-    // 2) Scoped questions (non-NULL InterfaceID) should consider *only* scoped DNSServers (DNSServer
-    // with scopeType set to kScopeInterfaceID) and their InterfaceIDs should match.
-    //
-    // 3) Scoped questions (non-zero ServiceID) should consider *only* scoped DNSServers (DNSServer
-    // with scopeType set to kScopeServiceID) and their ServiceIDs should match.
-    //
-    // The first condition in the "if" statement checks to see if both the question and the DNSServer are
-    // unscoped. The question is unscoped only if InterfaceID is zero and ServiceID is -1.
-    //
-    // If the first condition fails, following are the possible cases (the notes below are using
-    // InterfaceID for discussion and the same holds good for ServiceID):
-    //
-    // - DNSServer is not scoped, InterfaceID is not NULL - we should skip the current DNSServer entry
-    //   as scoped questions should not pick non-scoped DNSServer entry (Refer to (2) above).
-    //
-    // - DNSServer is scoped, InterfaceID is NULL - we should skip the current DNSServer entry as
-    //   unscoped question should not match scoped DNSServer (Refer to (1) above). The InterfaceID check
-    //   would fail in this case.
-    //
-    // - DNSServer is scoped and InterfaceID is not NULL - the InterfaceID of the question and the DNSServer
-    //   should match (Refer to (2) above).
-
-    if (((d->scopeType == kScopeNone) && (!InterfaceID && ServiceID == -1))  ||
-        ((d->scopeType == kScopeInterfaceID) && d->interface == InterfaceID) ||
-        ((d->scopeType == kScopeServiceID) && d->serviceID == ServiceID))
-    {
-        return mDNStrue;
-    }
-    return mDNSfalse;
-}
-
-// Sets all the Valid DNS servers for a question
-mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
-{
-    int bestmatchlen = -1, namecount = CountLabels(&question->qname);
-    DNSServer *curr;
-    int bettermatch, currcount;
-    int index = 0;
-    mDNSu32 timeout = 0;
-    mDNSBool DEQuery;
-
-    question->validDNSServers = zeroOpaque128;
-    DEQuery = DomainEnumQuery(&question->qname);
-    for (curr = m->DNSServers; curr; curr = curr->next)
-    {
-        debugf("SetValidDNSServers: Parsing DNS server Address %#a (Domain %##s), Scope: %d", &curr->addr, curr->domain.c, curr->scopeType);
-        // skip servers that will soon be deleted
-        if (curr->flags & DNSServerFlag_Delete)
-        {
-            debugf("SetValidDNSServers: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scopeType);
-            continue;
-        }
-
-        // This happens normally when you unplug the interface where we reset the interfaceID to mDNSInterface_Any for all
-        // the DNS servers whose scope match the interfaceID. Few seconds later, we also receive the updated DNS configuration.
-        // But any questions that has mDNSInterface_Any scope that are started/restarted before we receive the update
-        // (e.g., CheckSuppressUnusableQuestions is called when interfaces are deregistered with the core) should not
-        // match the scoped entries by mistake.
-        //
-        // Note: DNS configuration change will help pick the new dns servers but currently it does not affect the timeout
-
-        // Skip DNSServers that are InterfaceID Scoped but have no valid interfaceid set OR DNSServers that are ServiceID Scoped but have no valid serviceid set
-        if (((curr->scopeType == kScopeInterfaceID) && (curr->interface == mDNSInterface_Any)) ||
-            ((curr->scopeType == kScopeServiceID) && (curr->serviceID <= 0)))
-        {
-            LogInfo("SetValidDNSServers: ScopeType[%d] Skipping DNS server %#a (Domain %##s) Interface:[%p] Serviceid:[%d]",
-                (int)curr->scopeType, &curr->addr, curr->domain.c, curr->interface, curr->serviceID);
-            continue;
-        }
-
-        currcount = CountLabels(&curr->domain);
-        if ((!DEQuery || !curr->isCell) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID))
-        {
-            bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
-
-            // If we found a better match (bettermatch == 1) then clear all the bits
-            // corresponding to the old DNSServers that we have may set before and start fresh.
-            // If we find an equal match, then include that DNSServer also by setting the corresponding
-            // bit
-            if ((bettermatch == 1) || (bettermatch == 0))
-            {
-                bestmatchlen = currcount;
-                if (bettermatch)
-                {
-                    debugf("SetValidDNSServers: Resetting all the bits");
-                    question->validDNSServers = zeroOpaque128;
-                    timeout = 0;
-                }
-                debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d,"
-                       " Timeout %d, interface %p", question->qname.c, &curr->addr, curr->domain.c, curr->scopeType, index, curr->timeout,
-                       curr->interface);
-                timeout += curr->timeout;
-                if (DEQuery)
-                    debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->isCell);
-                bit_set_opaque128(question->validDNSServers, index);
-            }
-        }
-        index++;
-    }
-    question->noServerResponse = 0;
-
-    debugf("SetValidDNSServers: ValidDNSServer bits 0x%08x%08x%08x%08x for question %p %##s (%s)",
-           question->validDNSServers.l[3], question->validDNSServers.l[2], question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype));
-    // If there are no matching resolvers, then use the default timeout value.
-    return (timeout ? timeout : DEFAULT_UDNS_TIMEOUT);
-}
-
-// Get the Best server that matches a name. If you find penalized servers, look for the one
-// that will come out of the penalty box soon
-mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque128 validBits,
-    int *selected, mDNSBool nameMatch)
-{
-    DNSServer *curmatch = mDNSNULL;
-    int bestmatchlen = -1, namecount = name ? CountLabels(name) : 0;
-    DNSServer *curr;
-    mDNSs32 bestPenaltyTime, currPenaltyTime;
-    int bettermatch, currcount;
-    int index = 0;
-    int currindex = -1;
-
-    debugf("GetBestServer: ValidDNSServer bits  0x%x%x", validBits.l[1], validBits.l[0]);
-    bestPenaltyTime = DNSSERVER_PENALTY_TIME + 1;
-    for (curr = m->DNSServers; curr; curr = curr->next)
-    {
-        // skip servers that will soon be deleted
-        if (curr->flags & DNSServerFlag_Delete)
-        {
-            debugf("GetBestServer: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scopeType);
-            continue;
-        }
-
-        // Check if this is a valid DNSServer
-        if (!bit_get_opaque64(validBits, index))
-        {
-            debugf("GetBestServer: continuing for index %d", index);
-            index++;
-            continue;
-        }
-
-        currcount = CountLabels(&curr->domain);
-        currPenaltyTime = PenaltyTimeForServer(m, curr);
-
-        debugf("GetBestServer: Address %#a (Domain %##s), PenaltyTime(abs) %d, PenaltyTime(rel) %d",
-               &curr->addr, curr->domain.c, curr->penaltyTime, currPenaltyTime);
-
-        // If there are multiple best servers for a given question, we will pick the first one
-        // if none of them are penalized. If some of them are penalized in that list, we pick
-        // the least penalized one. BetterMatchForName walks through all best matches and
-        // "currPenaltyTime < bestPenaltyTime" check lets us either pick the first best server
-        // in the list when there are no penalized servers and least one among them
-        // when there are some penalized servers.
-
-        if (DNSServerMatch(curr, InterfaceID, ServiceID))
-        {
-
-            // If we know that all the names are already equally good matches, then skip calling BetterMatchForName.
-            // This happens when we initially walk all the DNS servers and set the validity bit on the question.
-            // Actually we just need PenaltyTime match, but for the sake of readability we just skip the expensive
-            // part and still do some redundant steps e.g., InterfaceID match
-
-            if (nameMatch)
-                bettermatch = BetterMatchForName(name, namecount, &curr->domain, currcount, bestmatchlen);
-            else
-                bettermatch = 0;
-
-            // If we found a better match (bettermatch == 1) then we don't need to
-            // compare penalty times. But if we found an equal match, then we compare
-            // the penalty times to pick a better match
-
-            if ((bettermatch == 1) || ((bettermatch == 0) && currPenaltyTime < bestPenaltyTime))
-            {
-                currindex = index;
-                curmatch = curr;
-                bestmatchlen = currcount;
-                bestPenaltyTime = currPenaltyTime;
-            }
-        }
-        index++;
-    }
-    if (selected) *selected = currindex;
-    return curmatch;
-}
-
-// Look up a DNS Server, matching by name and InterfaceID
-mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID)
-{
-    DNSServer *curmatch = mDNSNULL;
-    char *ifname = mDNSNULL;    // for logging purposes only
-    mDNSOpaque128 allValid;
-
-    if (InterfaceID == mDNSInterface_LocalOnly)
-        InterfaceID = mDNSNULL;
-
-    if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID);
-
-    // By passing in all ones, we make sure that every DNS server is considered
-    allValid.l[0] = allValid.l[1] = allValid.l[2] = allValid.l[3] = 0xFFFFFFFF;
-
-    curmatch = GetBestServer(m, name, InterfaceID, ServiceID, allValid, mDNSNULL, mDNStrue);
-
-    if (curmatch != mDNSNULL)
-        LogInfo("GetServerForName: DNS server %#a:%d (Penalty Time Left %d) (Scope %s:%p) for %##s", &curmatch->addr,
-                mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0), ifname ? ifname : "None",
-                InterfaceID, name);
-    else
-        LogInfo("GetServerForName: no DNS server (Scope %s:%p) for %##s", ifname ? ifname : "None", InterfaceID, name);
-
-    return(curmatch);
-}
-
-// Look up a DNS Server for a question within its valid DNSServer bits
-mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question)
-{
-    DNSServer *curmatch = mDNSNULL;
-    char *ifname = mDNSNULL;    // for logging purposes only
-    mDNSInterfaceID InterfaceID = question->InterfaceID;
-    const domainname *name = &question->qname;
-    int currindex;
-
-    if (InterfaceID == mDNSInterface_LocalOnly)
-        InterfaceID = mDNSNULL;
-
-    if (InterfaceID)
-        ifname = InterfaceNameForID(m, InterfaceID);
-
-    if (!mDNSOpaque128IsZero(&question->validDNSServers))
-    {
-        curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse);
-        if (currindex != -1)
-            bit_clr_opaque128(question->validDNSServers, currindex);
-    }
-
-    if (curmatch != mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] GetServerForQuestion: %p DNS server (%p) " PRI_IP_ADDR
-            ":%d (Penalty Time Left %d) (Scope " PUB_S ":%p:%d) for " PRI_DM_NAME " (" PUB_S ")",
-            question->request_id, mDNSVal16(question->TargetQID), question, curmatch, &curmatch->addr,
-            mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0),
-            ifname ? ifname : "None", InterfaceID, question->ServiceID, DM_NAME_PARAM(name),
-            DNSTypeName(question->qtype));
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] GetServerForQuestion: %p no DNS server (Scope " PUB_S ":%p:%d) for "
-            PRI_DM_NAME " (" PUB_S ")", question->request_id, mDNSVal16(question->TargetQID), question,
-            ifname ? ifname : "None", InterfaceID, question->ServiceID, DM_NAME_PARAM(name),
-            DNSTypeName(question->qtype));
-    }
-
-    return(curmatch);
-}
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-// Called in normal client context (lock not held)
-mDNSlocal void LLQNATCallback(mDNS *m, NATTraversalInfo *n)
-{
-    DNSQuestion *q;
-    mDNS_Lock(m);
-    LogInfo("LLQNATCallback external address:port %.4a:%u, NAT result %d", &n->ExternalAddress, mDNSVal16(n->ExternalPort), n->Result);
-    n->clientContext = mDNSNULL; // we received at least one callback since starting this NAT-T
-    for (q = m->Questions; q; q=q->next)
-        if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived)
-            startLLQHandshake(m, q);    // If ExternalPort is zero, will do StartLLQPolling instead
-    mDNS_Unlock(m);
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-// This function takes the DNSServer as a separate argument because sometimes the
-// caller has not yet assigned the DNSServer, but wants to evaluate the Suppressed
-// status before switching to it.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport mDNSBool ShouldSuppressUnicastQuery(const DNSQuestion *const q, const mdns_dns_service_t dnsservice)
-#else
-mDNSlocal mDNSBool ShouldSuppressUnicastQuery(const DNSQuestion *const q, const DNSServer *const server)
-#endif
-{
-    mDNSBool suppress = mDNSfalse;
-    const char *reason = mDNSNULL;
-
-    if (q->BlockedByPolicy)
-    {
-        suppress = mDNStrue;
-        reason   = " (blocked by policy)";
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    else if (!dnsservice)
-    {
-        if (!q->IsUnicastDotLocal)
-        {
-            suppress = mDNStrue;
-            reason   = " (no DNS service)";
-        }
-    }
-#else
-    else if (!server)
-    {
-        if (!q->IsUnicastDotLocal)
-        {
-            suppress = mDNStrue;
-            reason   = " (no DNS server)";
-        }
-    }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    else if ((q->flags & kDNSServiceFlagsDenyCellular) && mdns_dns_service_interface_is_cellular(dnsservice))
-#else
-    else if ((q->flags & kDNSServiceFlagsDenyCellular) && server->isCell)
-#endif
-    {
-        suppress = mDNStrue;
-        reason   = " (interface is cellular)";
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    else if ((q->flags & kDNSServiceFlagsDenyExpensive) && mdns_dns_service_interface_is_expensive(dnsservice))
-#else
-    else if ((q->flags & kDNSServiceFlagsDenyExpensive) && server->isExpensive)
-#endif
-    {
-        suppress = mDNStrue;
-        reason   = " (interface is expensive)";
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    else if ((q->flags & kDNSServiceFlagsDenyConstrained) && mdns_dns_service_interface_is_constrained(dnsservice))
-#else
-    else if ((q->flags & kDNSServiceFlagsDenyConstrained) && server->isConstrained)
-#endif
-    {
-        suppress = mDNStrue;
-        reason   = " (interface is constrained)";
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    else if (q->SuppressUnusable && !DNS64IsQueryingARecord(q->dns64.state))
-#else
-    else if (q->SuppressUnusable)
-#endif
-    {
-        if (q->qtype == kDNSType_A)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (!mdns_dns_service_a_queries_advised(dnsservice))
-#else
-            if (!server->usableA)
-#endif
-            {
-                suppress = mDNStrue;
-                reason   = " (A records are unusable)";
-            }
-            // If the server's configuration allows A record queries, suppress this query if
-            //     1. the interface associated with the server is CLAT46; and
-            //     2. the query has the kDNSServiceFlagsPathEvaluationDone flag, indicating that it's from libnetwork.
-            // See <rdar://problem/42672030> for more info.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            else if ((q->flags & kDNSServiceFlagsPathEvaluationDone) && mdns_dns_service_interface_is_clat46(dnsservice))
-#else
-            else if ((q->flags & kDNSServiceFlagsPathEvaluationDone) && server->isCLAT46)
-#endif
-            {
-                suppress = mDNStrue;
-                reason   = " (CLAT46 A records are unusable)";
-            }
-        }
-        else if (q->qtype == kDNSType_AAAA)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (!mdns_dns_service_aaaa_queries_advised(dnsservice))
-#else
-            if (!server->usableAAAA)
-#endif
-            {
-                suppress = mDNStrue;
-                reason   = " (AAAA records are unusable)";
-            }
-        }
-    }
-    if (suppress)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[Q%u] ShouldSuppressUnicastQuery: Query suppressed for " PRI_DM_NAME " " PUB_S PUB_S,
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), reason ? reason : "");
-    }
-    return suppress;
-}
-
-mDNSlocal mDNSBool ShouldSuppressQuery(DNSQuestion *q)
-{
-    // Multicast queries are never suppressed.
-    if (mDNSOpaque16IsZero(q->TargetQID))
-    {
-        return mDNSfalse;
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    return (ShouldSuppressUnicastQuery(q, q->dnsservice));
-#else
-    return (ShouldSuppressUnicastQuery(q, q->qDNSServer));
-#endif
-}
-
-mDNSlocal void CacheRecordRmvEventsForCurrentQuestion(mDNS *const m, DNSQuestion *q)
-{
-    CacheRecord *cr;
-    CacheGroup *cg;
-
-    cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-    for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-    {
-        // Don't deliver RMV events for negative records if the question has not required DNSSEC RRs.
-        if (cr->resrec.RecordType == kDNSRecordTypePacketNegative
-        #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-            && !dns_question_is_primary_dnssec_requestor(q)
-        #endif
-            )
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] CacheRecordRmvEventsForCurrentQuestion: Suppressing RMV events for question - "
-                "rr name: " PRI_DM_NAME ", rr type: " PUB_DNS_TYPE ", current active question: Q%u, current answers: %u", mDNSVal16(q->TargetQID),
-                DM_NAME_PARAM(cr->resrec.name), DNS_TYPE_PARAM(cr->resrec.rrtype),
-                cr->CRActiveQuestion ? mDNSVal16(cr->CRActiveQuestion->TargetQID) : 0, q->CurrentAnswers);
-
-            continue;
-        }
-
-        if (SameNameCacheRecordAnswersQuestion(cr, q))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] CacheRecordRmvEventsForCurrentQuestion: Calling AnswerCurrentQuestionWithResourceRecord (RMV) for question - "
-                "rr name: " PRI_DM_NAME ", rr type: " PUB_DNS_TYPE ", local answers: %u", mDNSVal16(q->TargetQID),
-                DM_NAME_PARAM(cr->resrec.name), DNS_TYPE_PARAM(cr->resrec.rrtype), q->LOAddressAnswers);
-
-            q->CurrentAnswers--;
-            if (cr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
-            if (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
-            AnswerCurrentQuestionWithResourceRecord(m, cr, QC_rmv);
-            if (m->CurrentQuestion != q) break;     // If callback deleted q, then we're finished here
-        }
-    }
-}
-
-mDNSlocal mDNSBool IsQuestionInList(const DNSQuestion *const list, const DNSQuestion *const question)
-{
-    for (const DNSQuestion *q = list; q; q = q->next)
-    {
-        if (q == question)
-        {
-            return mDNStrue;
-        }
-    }
-    return mDNSfalse;
-}
-
-mDNSlocal mDNSBool IsQuestionNew(const mDNS *const m, const DNSQuestion *const question)
-{
-    return IsQuestionInList(m->NewQuestions, question);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
-#else
-mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
-#endif
-{
-    AuthRecord *rr;
-    AuthGroup *ag;
-
-    if (m->CurrentQuestion)
-        LogMsg("LocalRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-
-    if (IsQuestionNew(m, q))
-    {
-        LogInfo("LocalRecordRmvEventsForQuestion: New Question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNStrue;
-    }
-    m->CurrentQuestion = q;
-    ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
-    if (ag)
-    {
-        for (rr = ag->members; rr; rr=rr->next)
-            // Filter the /etc/hosts records - LocalOnly, Unique, A/AAAA/CNAME
-            if (UniqueLocalOnlyRecord(rr) && LocalOnlyRecordAnswersQuestion(rr, q))
-            {
-                LogInfo("LocalRecordRmvEventsForQuestion: Delivering possible Rmv events with record %s",
-                        ARDisplayString(m, rr));
-                if (q->CurrentAnswers <= 0 || q->LOAddressAnswers <= 0)
-                {
-                    LogMsg("LocalRecordRmvEventsForQuestion: ERROR!! CurrentAnswers or LOAddressAnswers is zero %p %##s"
-                           " (%s) CurrentAnswers %d, LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype),
-                           q->CurrentAnswers, q->LOAddressAnswers);
-                    continue;
-                }
-                AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_rmv);      // MUST NOT dereference q again
-                if (m->CurrentQuestion != q) { m->CurrentQuestion = mDNSNULL; return mDNSfalse; }
-            }
-    }
-    m->CurrentQuestion = mDNSNULL;
-    return mDNStrue;
-}
-
-// Returns false if the question got deleted while delivering the RMV events
-// The caller should handle the case
-mDNSexport mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
-{
-    if (m->CurrentQuestion)
-        LogMsg("CacheRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)",
-               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
-
-    // If it is a new question, we have not delivered any ADD events yet. So, don't deliver RMV events.
-    // If this question was answered using local auth records, then you can't deliver RMVs using cache
-    if (!IsQuestionNew(m, q) && !q->LOAddressAnswers)
-    {
-        m->CurrentQuestion = q;
-        CacheRecordRmvEventsForCurrentQuestion(m, q);
-        if (m->CurrentQuestion != q) { m->CurrentQuestion = mDNSNULL; return mDNSfalse; }
-        m->CurrentQuestion = mDNSNULL;
-    }
-    else { LogInfo("CacheRecordRmvEventsForQuestion: Question %p %##s (%s) is a new question", q, q->qname.c, DNSTypeName(q->qtype)); }
-    return mDNStrue;
-}
-
-mDNSlocal void SuppressStatusChanged(mDNS *const m, DNSQuestion *q, DNSQuestion **restart)
-{
-    // NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero
-    // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
-    // LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers)
-    if (q->Suppressed)
-    {
-        q->Suppressed = mDNSfalse;
-        if (!CacheRecordRmvEventsForQuestion(m, q))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] SuppressStatusChanged: Question deleted while delivering RMV events from cache",
-                q->request_id, mDNSVal16(q->TargetQID));
-            return;
-        }
-        q->Suppressed = mDNStrue;
-    }
-
-    // SuppressUnusable does not affect questions that are answered from the local records (/etc/hosts)
-    // and Suppressed status does not mean anything for these questions. As we are going to stop the
-    // question below, we need to deliver the RMV events so that the ADDs that will be delivered during
-    // the restart will not be a duplicate ADD
-    if (!LocalRecordRmvEventsForQuestion(m, q))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[R%u->Q%u] SuppressStatusChanged: Question deleted while delivering RMV events from Local AuthRecords",
-            q->request_id, mDNSVal16(q->TargetQID));
-        return;
-    }
-
-    // There are two cases here.
-    //
-    // 1. Previously it was suppressed and now it is not suppressed, restart the question so
-    // that it will start as a new question. Note that we can't just call ActivateUnicastQuery
-    // because when we get the response, if we had entries in the cache already, it will not answer
-    // this question if the cache entry did not change. Hence, we need to restart
-    // the query so that it can be answered from the cache.
-    //
-    // 2. Previously it was not suppressed and now it is suppressed. We need to restart the questions
-    // so that we redo the duplicate checks in mDNS_StartQuery_internal. A SuppressUnusable question
-    // is a duplicate of non-SuppressUnusable question if it is not suppressed (Suppressed is false).
-    // A SuppressUnusable question is not a duplicate of non-SuppressUnusable question if it is suppressed
-    // (Suppressed is true). The reason for this is that when a question is suppressed, we want an
-    // immediate response and not want to be blocked behind a question that is querying DNS servers. When
-    // the question is not suppressed, we don't want two active questions sending packets on the wire.
-    // This affects both efficiency and also the current design where there is only one active question
-    // pointed to from a cache entry.
-    //
-    // We restart queries in a two step process by first calling stop and build a temporary list which we
-    // will restart at the end. The main reason for the two step process is to handle duplicate questions.
-    // If there are duplicate questions, calling stop inherits the values from another question on the list (which
-    // will soon become the real question) including q->ThisQInterval which might be zero if it was
-    // suppressed before. At the end when we have restarted all questions, none of them is active as each
-    // inherits from one another and we need to reactivate one of the questions here which is a little hacky.
-    //
-    // It is much cleaner and less error prone to build a list of questions and restart at the end.
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] SuppressStatusChanged: Stop question %p " PRI_DM_NAME " (" PUB_S ")",
-        q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-    mDNS_StopQuery_internal(m, q);
-    q->next = *restart;
-    *restart = q;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-mDNSexport void mDNSCoreReceiveD2DResponse(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
-    const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
-    const mDNSInterfaceID InterfaceID)
-{
-        mDNSCoreReceiveResponse(m, response, end, srcaddr, srcport, dstaddr, dstport, mDNSNULL, mDNSNULL, InterfaceID);
-}
-#endif
-
-// The caller should hold the lock
-mDNSexport void CheckSuppressUnusableQuestions(mDNS *const m)
-{
-    DNSQuestion *q;
-    DNSQuestion *restart = mDNSNULL;
-
-    // We look through all questions including new questions. During network change events,
-    // we potentially restart questions here in this function that ends up as new questions,
-    // which may be suppressed at this instance. Before it is handled we get another network
-    // event that changes the status e.g., address becomes available. If we did not process
-    // new questions, we would never change its Suppressed status.
-    //
-    // CurrentQuestion is used by RmvEventsForQuestion below. While delivering RMV events, the
-    // application callback can potentially stop the current question (detected by CurrentQuestion) or
-    // *any* other question which could be the next one that we may process here. RestartQuestion
-    // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal
-    // if the "next" question is stopped while the CurrentQuestion is stopped
-    if (m->RestartQuestion)
-        LogMsg("CheckSuppressUnusableQuestions: ERROR!! m->RestartQuestion already set: %##s (%s)",
-               m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype));
-    m->RestartQuestion = m->Questions;
-    while (m->RestartQuestion)
-    {
-        q = m->RestartQuestion;
-        m->RestartQuestion = q->next;
-        if (q->SuppressUnusable)
-        {
-            const mDNSBool old = q->Suppressed;
-            q->Suppressed = ShouldSuppressQuery(q);
-            if (q->Suppressed != old)
-            {
-                // Previously it was not suppressed, Generate RMV events for the ADDs that we might have delivered before
-                // followed by a negative cache response. Temporarily turn off suppression so that
-                // AnswerCurrentQuestionWithResourceRecord can answer the question
-                SuppressStatusChanged(m, q, &restart);
-            }
-        }
-    }
-    while (restart)
-    {
-        q = restart;
-        restart = restart->next;
-        q->next = mDNSNULL;
-        LogInfo("CheckSuppressUnusableQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-        mDNS_StartQuery_internal(m, q);
-    }
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal void RestartUnicastQuestions(mDNS *const m)
-{
-    DNSQuestion *q;
-    DNSQuestion *restartList = mDNSNULL;
-
-    if (m->RestartQuestion)
-        LogMsg("RestartUnicastQuestions: ERROR!! m->RestartQuestion already set: %##s (%s)",
-               m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype));
-    m->RestartQuestion = m->Questions;
-    while (m->RestartQuestion)
-    {
-        q = m->RestartQuestion;
-        m->RestartQuestion = q->next;
-        if (q->Restart)
-        {
-            if (mDNSOpaque16IsZero(q->TargetQID))
-                LogMsg("RestartUnicastQuestions: ERROR!! Restart set for multicast question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-            q->Restart = mDNSfalse;
-            SuppressStatusChanged(m, q, &restartList);
-        }
-    }
-    while ((q = restartList) != mDNSNULL)
-    {
-        restartList = q->next;
-        q->next = mDNSNULL;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] RestartUnicastQuestions: Start question %p " PRI_DM_NAME " (" PUB_S ")",
-             q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-        mDNS_StartQuery_internal(m, q);
-    }
-}
-#endif
-
-// ValidateParameters() is called by mDNS_StartQuery_internal() to check the client parameters of
-// DNS Question that are already set by the client before calling mDNS_StartQuery()
-mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
-{
-    if (!ValidateDomainName(&question->qname))
-    {
-        LogMsg("ValidateParameters: Attempt to start query with invalid qname %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
-        return(mStatus_Invalid);
-    }
-
-    // If this question is referencing a specific interface, verify it exists
-    if (question->InterfaceID && !LocalOnlyOrP2PInterface(question->InterfaceID))
-    {
-        NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
-        if (!intf)
-            LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list",
-                    IIDPrintable(question->InterfaceID), question->qname.c, DNSTypeName(question->qtype));
-    }
-
-    return(mStatus_NoError);
-}
-
-// InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question.
-// These are a subset of the internal uDNS fields. Must be done before ShouldSuppressQuery() & mDNS_PurgeBeforeResolve()
-mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
-{
-    // First reset all DNS Configuration
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_forget(&question->dnsservice);
-    question->NeedUpdatedQuerier  = mDNSfalse;
-#else
-    question->qDNSServer          = mDNSNULL;
-    question->validDNSServers     = zeroOpaque128;
-    question->triedAllServersOnce = mDNSfalse;
-    question->noServerResponse    = mDNSfalse;
-#endif
-    question->StopTime            = (question->TimeoutQuestion) ? question->StopTime : 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics));
-#endif
-
-    // Need not initialize the DNS Configuration for Local Only OR P2P Questions when timeout not specified
-    if (LocalOnlyOrP2PInterface(question->InterfaceID) && !question->TimeoutQuestion)
-        return;
-    // Proceed to initialize DNS Configuration (some are set in SetValidDNSServers())
-    if (!mDNSOpaque16IsZero(question->TargetQID))
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        mDNSu32 timeout = 30;
-#else
-        mDNSu32 timeout = SetValidDNSServers(m, question);
-#endif
-        // We set the timeout value the first time mDNS_StartQuery_internal is called for a question.
-        // So if a question is restarted when a network change occurs, the StopTime is not reset.
-        // Note that we set the timeout for all questions. If this turns out to be a duplicate,
-        // it gets a full timeout value even if the original question times out earlier.
-        if (question->TimeoutQuestion && !question->StopTime)
-        {
-            question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[Q%u] InitDNSConfig: Setting StopTime on the uDNS question %p " PRI_DM_NAME " (" PUB_S ")",
-                mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
-                DNSTypeName(question->qtype));
-        }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        Querier_SetDNSServiceForQuestion(question);
-#else
-        question->qDNSServer = GetServerForQuestion(m, question);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%u->Q%u] InitDNSConfig: question %p " PRI_DM_NAME " " PUB_S " Timeout %d, DNS Server "
-            PRI_IP_ADDR ":%d",
-            question->request_id, mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
-            DNSTypeName(question->qtype), timeout, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
-            mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
-#endif
-    }
-    else if (question->TimeoutQuestion && !question->StopTime)
-    {
-        // If the question is to be timed out and its a multicast, local-only or P2P case,
-        // then set it's stop time.
-        mDNSu32 timeout = LocalOnlyOrP2PInterface(question->InterfaceID) ?
-                            DEFAULT_LO_OR_P2P_TIMEOUT : GetTimeoutForMcastQuestion(m, question);
-        question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] InitDNSConfig: Setting StopTime on the uDNS question %p " PRI_DM_NAME " (" PUB_S ")",
-            question->request_id, mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
-            DNSTypeName(question->qtype));
-    }
-    // Set StopTime here since it is a part of DNS Configuration
-    if (question->StopTime)
-        SetNextQueryStopTime(m, question);
-    // Don't call SetNextQueryTime() if a LocalOnly OR P2P Question since those questions
-    // will never be transmitted on the wire.
-    if (!(LocalOnlyOrP2PInterface(question->InterfaceID)))
-        SetNextQueryTime(m,question);
-}
-
-// InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal
-// state fields of the DNS Question. These are independent of the Client layer.
-mDNSlocal void InitCommonState(mDNS *const m, DNSQuestion *const question)
-{
-    int i;
-
-    // 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 (InitialQuestionInterval).
-    // If AnswerNewQuestion() finds that we have *no* relevant answers currently in our cache, then it will accelerate
-    // that to go out immediately.
-    question->next              = mDNSNULL;
-    // ThisQInterval should be initialized before any memory allocations occur. If malloc
-    // debugging is turned on within mDNSResponder (see mDNSDebug.h for details) it validates
-    // the question list to check if ThisQInterval is negative which means the question has been
-    // stopped and can't be on the list. The question is already on the list and ThisQInterval
-    // can be negative if the caller just stopped it and starting it again. Hence, it always has to
-    // be initialized. CheckForSoonToExpireRecords below prints the cache records when logging is
-    // turned ON which can allocate memory e.g., base64 encoding.
-    question->ThisQInterval     = InitialQuestionInterval;                  // MUST be > zero for an active question
-    question->qnamehash         = DomainNameHashValue(&question->qname);
-    mDNSs32 delay = 0;
-    if (mDNSOpaque16IsZero(question->TargetQID))
-    {
-        delay = CheckForSoonToExpireRecordsEx(m, &question->qname, question->qnamehash, question->qtype, question->qclass);
-    }
-    question->DelayAnswering    = delay;
-    question->LastQTime         = m->timenow;
-    question->ExpectUnicastResp = 0;
-    question->LastAnswerPktNum  = m->PktNum;
-    question->RecentAnswerPkts  = 0;
-    question->CurrentAnswers    = 0;
-
-   question->BrowseThreshold   = 0;
-    question->CachedAnswerNeedsUpdate = mDNSfalse;
-
-    question->LargeAnswers      = 0;
-    question->UniqueAnswers     = 0;
-    question->LOAddressAnswers  = 0;
-    question->FlappingInterface1 = mDNSNULL;
-    question->FlappingInterface2 = mDNSNULL;
-
-    // mDNSPlatformGetDNSRoutePolicy() and InitDNSConfig() may set a DNSQuestion's BlockedByPolicy value,
-    // so they should be called before calling ShouldSuppressQuery(), which checks BlockedByPolicy.
-    question->BlockedByPolicy = mDNSfalse;
-
-    // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetDNSRoutePolicy()
-    // since we would already have the question->ServiceID in that case.
-    if (!(question->flags & kDNSServiceFlagsServiceIndex))
-    {
-        question->ServiceID = -1;
-    }
-    else
-        LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c,
-                DNSTypeName(question->qtype), question->pid, question->euid, question->ServiceID);
-
-    InitDNSConfig(m, question);
-    question->AuthInfo          = GetAuthInfoForQuestion(m, question);
-    question->Suppressed        = ShouldSuppressQuery(question);
-    question->NextInDQList      = mDNSNULL;
-    question->SendQNow          = mDNSNULL;
-    question->SendOnAll         = mDNSfalse;
-    question->RequestUnicast    = kDefaultRequestUnicastCount;
-
-
-    question->LastQTxTime       = m->timenow;
-    question->CNAMEReferrals    = 0;
-
-    question->WakeOnResolveCount = 0;
-    if (question->WakeOnResolve)
-    {
-        question->WakeOnResolveCount = InitialWakeOnResolveCount;
-    }
-
-    for (i=0; i<DupSuppressInfoSize; i++)
-        question->DupSuppress[i].InterfaceID = mDNSNULL;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    question->Restart = mDNSfalse;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    question->dnssec = mDNSNULL;
-#endif
-
-    debugf("InitCommonState: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)",
-            question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow,
-            NextQSendTime(question) - m->timenow,
-            question->DelayAnswering ? question->DelayAnswering - m->timenow : 0,
-            question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf);
-
-    if (question->DelayAnswering)
-        LogInfo("InitCommonState: Delaying answering for %d ticks while cache stabilizes for %##s (%s)",
-                 question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype));
-}
-
-// Excludes the DNS Config fields which are already handled by InitDNSConfig()
-mDNSlocal void InitWABState(DNSQuestion *const question)
-{
-    // We'll create our question->LocalSocket on demand, if needed.
-    // We won't need one for duplicate questions, or from questions answered immediately out of the cache.
-    // We also don't need one for LLQs because (when we're using NAT) we want them all to share a single
-    // NAT mapping for receiving inbound add/remove events.
-    question->LocalSocket       = mDNSNULL;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_querier_forget(&question->querier);
-#else
-    question->unansweredQueries = 0;
-#endif
-    question->nta               = mDNSNULL;
-    question->servAddr          = zeroAddr;
-    question->servPort          = zeroIPPort;
-    question->tcp               = mDNSNULL;
-}
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-mDNSlocal void InitLLQNATState(mDNS *const m)
-{
-    // If we don't have our NAT mapping active, start it now
-    if (!m->LLQNAT.clientCallback)
-    {
-        m->LLQNAT.Protocol       = NATOp_MapUDP;
-        m->LLQNAT.IntPort        = m->UnicastPort4;
-        m->LLQNAT.RequestedPort  = m->UnicastPort4;
-        m->LLQNAT.clientCallback = LLQNATCallback;
-        m->LLQNAT.clientContext  = (void*)1; // Means LLQ NAT Traversal just started
-        mDNS_StartNATOperation_internal(m, &m->LLQNAT);
-    }
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-mDNSlocal void InitLLQState(DNSQuestion *const question)
-{
-    question->state             = LLQ_Init;
-    question->ReqLease          = 0;
-    question->expire            = 0;
-    question->ntries            = 0;
-    question->id                = zeroOpaque64;
-}
-
-// InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize
-// DNSSEC & DNS Proxy fields of the DNS Question.
-mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question)
-{
-    (void) m;
-    question->responseFlags = zeroID;
-}
-
-// Once the question is completely initialized including the duplicate logic, this function
-// is called to finalize the unicast question which requires flushing the cache if needed,
-// activating the query etc.
-mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question)
-{
-    // Ensure DNS related info of duplicate question is same as the orig question
-    if (question->DuplicateOf)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        const DNSQuestion *const duplicateOf = question->DuplicateOf;
-        mdns_replace(&question->dnsservice, duplicateOf->dnsservice);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->DupQ%u->Q%u] Duplicate question " PRI_DM_NAME " (" PUB_S ")",
-           question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(duplicateOf->TargetQID),
-           DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-#else
-        question->validDNSServers = question->DuplicateOf->validDNSServers;
-        // If current(dup) question has DNS Server assigned but the original question has no DNS Server assigned to it,
-        // then we log a line as it could indicate an issue
-        if (question->DuplicateOf->qDNSServer == mDNSNULL)
-        {
-            if (question->qDNSServer)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] FinalizeUnicastQuestion: Current(dup) question %p has DNSServer(" PRI_IP_ADDR
-                    ":%d) but original question(%p) has no DNS Server! " PRI_DM_NAME " (" PUB_S ")",
-                    question->request_id, mDNSVal16(question->TargetQID), question,
-                    question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
-                    mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort), question->DuplicateOf,
-                    DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-            }
-        }
-        question->qDNSServer = question->DuplicateOf->qDNSServer;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->DupQ%d->Q%d] FinalizeUnicastQuestion: Duplicate question %p (%p) " PRI_DM_NAME " (" PUB_S
-            "), DNS Server " PRI_IP_ADDR ":%d",
-            question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(question->DuplicateOf->TargetQID),
-            question, question->DuplicateOf, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype),
-            question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
-            mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
-#endif
-    }
-
-    ActivateUnicastQuery(m, question, mDNSfalse);
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    if (question->LongLived)
-    {
-        // Unlike other initializations, InitLLQNATState should be done after
-        // we determine that it is a unicast question.  LongLived is set for
-        // both multicast and unicast browse questions but we should initialize
-        // the LLQ NAT state only for LLQ. Otherwise we will unnecessarily
-        // start the NAT traversal that is not needed.
-        InitLLQNATState(m);
-    }
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-}
-
-mDNSlocal void InsertNewQuestionInList(DNSQuestion *const question)
-{
-    DNSQuestion **qptr;
-    DNSQuestion *q;
-    const mDNSBool localOnlyOrP2P = LocalOnlyOrP2PInterface(question->InterfaceID);
-    mDNS *const m = &mDNSStorage;
-    DNSQuestion **const newQSublistPtr = localOnlyOrP2P ? &m->NewLocalOnlyQuestions : &m->NewQuestions;
-    const DNSQuestion *const newQSublist = *newQSublistPtr;
-    mDNSBool inNewQSublist = mDNSfalse;
-    mDNSBool passedPrimary = mDNSfalse;
-    for (qptr = localOnlyOrP2P ? &m->LocalOnlyQuestions : &m->Questions; (q = *qptr) != mDNSNULL; qptr = &q->next)
-    {
-        // If there's no new question sublist, then keep going until the end of the question list so that the new
-        // question can be appended. Otherwise, the new question needs to be carefully inserted in the sublist such that
-        // it doesn't precede any questions that are supposed to be answered earlier or at the same clock time as
-        // itself, and such that it doesn't follow any questions that are supposed to be answered later than itself.
-        if (newQSublist)
-        {
-            // We've entered the new question sublist when we encounter the head of the sublist.
-            if (!inNewQSublist && (q == newQSublist))
-            {
-                inNewQSublist = mDNStrue;
-            }
-            // If we're in the new question sublist, check if it's appropriate to insert the new question before the
-            // current question:
-            //
-            // 1. The current question must also have a delayed answering time.
-            // 2. For questions that are duplicates, make sure that the new question is inserted after its primary
-            //    question because the rest of the code expects a duplicate question to always come after its primary
-            //    question in a question list.
-            if (inNewQSublist && (q->DelayAnswering != 0) && (!question->DuplicateOf || passedPrimary))
-            {
-                // Determine when the new question's answering should begin.
-                const mDNSs32 answeringTime = (question->DelayAnswering != 0) ? question->DelayAnswering : m->timenow;
-                // If the current question's answering time is later, then the new question should be inserted before.
-                if ((q->DelayAnswering - answeringTime) > 0)
-                {
-                    break;
-                }
-            }
-            if (!passedPrimary && question->DuplicateOf && (q == question->DuplicateOf))
-            {
-                passedPrimary = mDNStrue;
-            }
-        }
-    }
-    // Insert the new question in the list.
-    question->next = q;
-    *qptr = question;
-    // If there was no new question sublist, or the new question was inserted right before the head of the sublist, then
-    // the new question becomes the head of the new question sublist.
-    if (!newQSublist || (newQSublist == q))
-    {
-        *newQSublistPtr = question;
-    }
-}
-
-mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
-{
-    mStatus vStatus;
-
-    // First check for cache space (can't do queries if there is no cache space allocated)
-    if (m->rrcache_size == 0)
-        return(mStatus_NoCache);
-
-    vStatus = ValidateParameters(m, question);
-    if (vStatus)
-        return(vStatus);
-
-#ifdef USE_LIBIDN
-    // If the TLD includes high-ascii bytes, assume it will need to be converted to Punycode.
-    // (In the future the root name servers may answer UTF-8 queries directly, but for now they do not.)
-    // This applies to the top label (TLD) only
-    // -- for the second level and down we try UTF-8 first, and then fall back to Punycode only if UTF-8 fails.
-    if (IsHighASCIILabel(LastLabel(&question->qname)))
-    {
-        domainname newname;
-        if (PerformNextPunycodeConversion(question, &newname))
-            AssignDomainName(&question->qname, &newname);
-    }
-#endif // USE_LIBIDN
-
-#ifndef UNICAST_DISABLED
-    question->TargetQID = Question_uDNS(question) ? mDNS_NewMessageID(m) : zeroID;
-#else
-    question->TargetQID = zeroID;
-#endif
-    debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
-
-    const mDNSBool localOnlyOrP2P = LocalOnlyOrP2PInterface(question->InterfaceID);
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-    if (resolved_cache_is_enabled()                             &&
-        !mDNSOpaque16IsZero(question->TargetQID)                &&
-        question->qclass == kDNSClass_IN                        &&
-        !localOnlyOrP2P                                         &&
-        (question->qtype == kDNSType_AAAA   ||
-         question->qtype == kDNSType_A      ||
-         question->qtype == kDNSType_CNAME))
-    {
-        resolved_cache_append_name(question, &question->qname);
-    }
-#endif
-    const DNSQuestion *const qlist = localOnlyOrP2P ? m->LocalOnlyQuestions : m->Questions;
-    if (IsQuestionInList(qlist, question))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartQuery_internal: Error! Tried to add a question " PRI_DM_NAME " (" PUB_S ") %p "
-            "that's already in the active list",
-            DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype), question);
-        return(mStatus_AlreadyRegistered);
-    }
-
-    // Intialize the question. The only ordering constraint we have today is that
-    // InitDNSSECProxyState should be called after the DNS server is selected (in
-    // InitCommonState -> InitDNSConfig) as DNS server selection affects DNSSEC
-    // validation.
-
-    InitCommonState(m, question);
-    InitWABState(question);
-    InitLLQState(question);
-    InitDNSSECProxyState(m, question);
-
-    // FindDuplicateQuestion should be called last after all the intialization
-    // as the duplicate logic could be potentially based on any field in the
-    // question.
-    question->DuplicateOf  = FindDuplicateQuestion(m, question);
-    if (question->DuplicateOf)
-        question->AuthInfo = question->DuplicateOf->AuthInfo;
-
-    InsertNewQuestionInList(question);
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (question->enableDNSSEC)
-    {
-        const dnssec_error_t dnssec_err = dnssec_handle_question_start(m, question);
-        if (dnssec_err != DNSSEC_ERROR_NO_ERROR)
-        {
-            return mStatus_UnknownErr;
-        }
-    }
-#endif
-    if (!localOnlyOrP2P)
-    {
-        // If the question's id is non-zero, then it's Wide Area
-        // MUST NOT do this Wide Area setup until near the end of
-        // mDNS_StartQuery_internal -- this code may itself issue queries (e.g. SOA,
-        // NS, etc.) and if we haven't finished setting up our own question and setting
-        // m->NewQuestions if necessary then we could end up recursively re-entering
-        // this routine with the question list data structures in an inconsistent state.
-        if (!mDNSOpaque16IsZero(question->TargetQID))
-        {
-            FinalizeUnicastQuestion(m, question);
-        }
-        else
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-            m->NumAllInterfaceQuestions++;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartQuery_internal: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u "
-                PRI_DM_NAME " (" PUB_S ")", m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions,
-                DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-            if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
-            {
-                m->NextBonjourDisableTime = 0;
-                if (m->BonjourEnabled == 0)
-                {
-                    // Enable Bonjour immediately by scheduling network changed processing where
-                    // we will join the multicast group on each active interface.
-                    m->BonjourEnabled = 1;
-                    m->NetworkChanged = m->timenow;
-                }
-            }
-#endif
-            if (question->WakeOnResolve)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartQuery_internal: Purging for " PRI_DM_NAME, DM_NAME_PARAM(&question->qname));
-                mDNS_PurgeBeforeResolve(m, question);
-            }
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    // Only start the resolver discovery if the question meets condition to do so.
-    // This ensures that we do not recursively start resolver discovery when we start a query to discover the DNS resolver.
-    const domainname *domain_to_discover_resolver = mDNSNULL;
-    if (dns_question_requires_resolver_discovery(question, &domain_to_discover_resolver))
-    {
-        // Inside mDNS_StartQuery_internal(), we already grabbed the lock, so no need to lock it again.
-        resolver_discovery_add(domain_to_discover_resolver, mDNSfalse);
-    }
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    if (is_apple_internal_build() && question->logPrivacyLevel == dnssd_log_privacy_level_private)
-    {
-        gNumOfPrivateLogRedactionEnabledQueries++;
-        if (!gPrivateLogRedactionEnabled)
-        {
-            gPrivateLogRedactionEnabled = mDNStrue;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] Question enables private log redaction, all the private level logs and the state dump will now be redacted.",
-                mDNSVal16(question->TargetQID));
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] Question enables private log redaction, redaction already in effect. - "
-                "number of enabled questions: %d.", mDNSVal16(question->TargetQID),
-                gNumOfPrivateLogRedactionEnabledQueries);
-        }
-    }
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-
-    return(mStatus_NoError);
-}
-
-// CancelGetZoneData is an internal routine (i.e. must be called with the lock already held)
-mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta)
-{
-    debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
-    // This function may be called anytime to free the zone information.The question may or may not have stopped.
-    // If it was already stopped, mDNS_StopQuery_internal would have set q->ThisQInterval to -1 and should not
-    // call it again
-    if (nta->question.ThisQInterval != -1)
-    {
-        mDNS_StopQuery_internal(m, &nta->question);
-        if (nta->question.ThisQInterval != -1)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "CancelGetZoneData: Question "PRI_DM_NAME" (" PUB_S ") ThisQInterval %d not -1",
-                DM_NAME_PARAM(&nta->question.qname), DNSTypeName(nta->question.qtype), nta->question.ThisQInterval);
-        }
-    }
-    mDNSPlatformMemFree(nta);
-}
-
-mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Must reset the question's parameters to the original values if it is a DNSSEC question.
-    dnssec_handle_question_stop(question);
-#endif
-    CacheGroup *cg = CacheGroupForName(m, question->qnamehash, &question->qname);
-    CacheRecord *cr;
-    DNSQuestion **qp = &m->Questions;
-    const mDNSu32 request_id = question->request_id;
-    const mDNSu16 question_id = mDNSVal16(question->TargetQID);
-
-    //LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
-
-    if (LocalOnlyOrP2PInterface(question->InterfaceID))
-        qp = &m->LocalOnlyQuestions;
-    while (*qp && *qp != question) qp=&(*qp)->next;
-    if (*qp) *qp = (*qp)->next;
-    else
-    {
-#if !ForceAlerts
-        if (question->ThisQInterval >= 0)   // Only log error message if the query was supposed to be active
-#endif
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "[R%u->Q%u] mDNS_StopQuery_internal: Question " PRI_DM_NAME " (" PUB_S ") not found in active list.",
-                request_id, question_id, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-        }
-        return(mStatus_BadReferenceErr);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    if (!LocalOnlyOrP2PInterface(question->InterfaceID) && mDNSOpaque16IsZero(question->TargetQID))
-    {
-        if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
-            m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
-        m->NumAllInterfaceQuestions--;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "mDNS_StopQuery_internal: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u " PRI_DM_NAME " (" PUB_S ")",
-            m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, DM_NAME_PARAM(&question->qname),
-            DNSTypeName(question->qtype));
-    }
-#endif
-
-    // 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 there is any
-    // other question that is also referencing them, else their CRActiveQuestion needs to get set to NULL.
-    for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-    {
-        if (cr->CRActiveQuestion == question)
-        {
-            DNSQuestion *q;
-            DNSQuestion *replacement = mDNSNULL;
-            // If we find an active question that is answered by this cached record, use it as the cache record's
-            // CRActiveQuestion replacement. If there are no such questions, but there's at least one unsuppressed inactive
-            // question that is answered by this cache record, then use an inactive one to not forgo generating RMV events
-            // via CacheRecordRmv() when the cache record expires.
-            for (q = m->Questions; q && (q != m->NewQuestions); q = q->next)
-            {
-                if (!q->DuplicateOf && !q->Suppressed && CacheRecordAnswersQuestion(cr, q))
-                {
-                    if (q->ThisQInterval > 0)
-                    {
-                        replacement = q;
-                        break;
-                    }
-                    else if (!replacement)
-                    {
-                        replacement = q;
-                    }
-                }
-            }
-            if (replacement)
-                debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question "
-                       "CurrentAnswers %d, Suppressed %d", replacement, CRDisplayString(m,cr), question->CurrentAnswers, replacement->CurrentAnswers, replacement->Suppressed);
-            cr->CRActiveQuestion = replacement;    // Question used to be active; new value may or may not be null
-            if (!replacement) 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;
-
-    if (m->RestartQuestion == question)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StopQuery_internal: Just deleted the current restart question: " PRI_DM_NAME " (" PUB_S ")",
-            DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-        m->RestartQuestion = question->next;
-    }
-
-    // Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions
-    question->next = mDNSNULL;
-
-    // LogMsg("mDNS_StopQuery_internal: Question %##s (%s) removed", question->qname.c, DNSTypeName(question->qtype));
-
-    // And finally, cancel any associated GetZoneData operation that's still running.
-    // Must not do this until last, because there's a good chance the GetZoneData question is the next in the list,
-    // so if we delete it earlier in this routine, we could find that our "question->next" pointer above is already
-    // invalid before we even use it. By making sure that we update m->CurrentQuestion and m->NewQuestions if necessary
-    // *first*, then they're all ready to be updated a second time if necessary when we cancel our GetZoneData query.
-    if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
-    if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; }
-
-    if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived)
-    {
-        // Scan our list to see if any more wide-area LLQs remain. If not, stop our NAT Traversal.
-        DNSQuestion *q;
-        for (q = m->Questions; q; q=q->next)
-            if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived) break;
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-        if (!q)
-        {
-            if (!m->LLQNAT.clientCallback)       // Should never happen, but just in case...
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StopQuery ERROR LLQNAT.clientCallback NULL");
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Stopping LLQNAT");
-                mDNS_StopNATOperation_internal(m, &m->LLQNAT);
-                m->LLQNAT.clientCallback = mDNSNULL; // Means LLQ NAT Traversal not running
-            }
-        }
-
-        // If necessary, tell server it can delete this LLQ state
-        if (question->state == LLQ_Established)
-        {
-            question->ReqLease = 0;
-            sendLLQRefresh(m, question);
-            // If we need need to make a TCP connection to cancel the LLQ, that's going to take a little while.
-            // We clear the tcp->question backpointer so that when the TCP connection completes, it doesn't
-            // crash trying to access our cancelled question, but we don't cancel the TCP operation itself --
-            // we let that run out its natural course and complete asynchronously.
-            if (question->tcp)
-            {
-                question->tcp->question = mDNSNULL;
-                question->tcp           = mDNSNULL;
-            }
-        }
-        else
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-            if (question->dnsPushServer != mDNSNULL)
-        {
-            // UnsubscribeQuestionFromDNSPushServer() must happen before Querier_HandleStoppedDNSQuestion(), because it
-            // checks the dnsservice to determine if the cached response answers the current long-lived query.
-            UnsubscribeQuestionFromDNSPushServer(m, question, mDNSfalse);
-        }
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    }
-    // wait until we send the refresh above which needs the nta
-    if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    Querier_HandleStoppedDNSQuestion(question);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    uDNSMetricsClear(&question->metrics);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    DNS64ResetState(question);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    const domainname *domain_to_discover_resolver = mDNSNULL;
-    // Only stop the resolver discover if the question has required the discovery when it is started.
-    if (dns_question_requires_resolver_discovery(question, &domain_to_discover_resolver))
-    {
-        // Inside mDNS_StopQuery_internal(), we already grabbed the lock, so no need to lock it again.
-        resolver_discovery_remove(domain_to_discover_resolver, mDNSfalse);
-    }
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    if (is_apple_internal_build() && question->logPrivacyLevel == dnssd_log_privacy_level_private)
-    {
-         gNumOfPrivateLogRedactionEnabledQueries--;
-
-        if (gNumOfPrivateLogRedactionEnabledQueries == 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] Last question that enables private log redaction is stopped.", mDNSVal16(question->TargetQID));
-            gPrivateLogRedactionEnabled = mDNSfalse;
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[Q%u] number of log redaction enabled questions: %u.",
-                mDNSVal16(question->TargetQID), gNumOfPrivateLogRedactionEnabledQueries);
-        }
-    }
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Must drop the lock before releasing DNSSEC context because its finalizer may stop other questions, which would
-    // grab the lock again.
-    // For example:
-    // Stopping www.ietf.org. AAAA will stop ietf.org. DNSKEY
-    // Stopping ietf.org. DNSKEY will stop ietf.org. DS
-    // ...until the root trust anchor is reached.
-    mDNS_DropLockBeforeCallback();
-    MDNS_DISPOSE_DNSSEC_OBJ(question->dnssec);
-    mDNS_ReclaimLockAfterCallback();
-#endif
-
-    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);
-}
-
-mDNSlocal mStatus mDNS_CheckQuestionBeforeStoppingQuery(const mDNS *const m, const DNSQuestion *const question)
-{
-    mStatus err = mStatus_NoError;
-
-    DNSQuestion *const *qp = LocalOnlyOrP2PInterface(question->InterfaceID) ? &m->LocalOnlyQuestions : &m->Questions;
-
-    // Check if the current question is in mDNSResponder's question list.
-    for (; *qp != mDNSNULL && *qp != question; qp = &(*qp)->next)
-        ;
-    if (*qp == mDNSNULL)
-    {
-    #if !ForceAlerts
-        if (question->ThisQInterval >= 0)
-    #endif
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Question not found in the active list - "
-                "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", DM_NAME_PARAM(&question->qname),
-                DNSTypeName(question->qtype));
-        }
-        err = mStatus_BadReferenceErr;
-    }
-
-    return err;
-}
-
-// Note that mDNS_StopQueryWithRemoves() does not currently implement the full generality of the other APIs
-// Specifically, question callbacks invoked as a result of this call cannot themselves make API calls.
-// We invoke the callback without using mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback
-// specifically to catch and report if the client callback does try to make API calls
-mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question)
-{
-    DNSQuestion *qq;
-    mDNS_Lock(m);
-
-    // Check if question is new -- don't want to give remove events for a question we haven't even answered yet
-    for (qq = m->NewQuestions; qq; qq=qq->next) if (qq == question) break;
-
-    // Ensure that the question is still in the mDNSResponder's question list, or there is no point to deliver RMV
-    // event.
-    const mStatus err = mDNS_CheckQuestionBeforeStoppingQuery(m, question);
-    if (err != mStatus_NoError)
-    {
-        goto exit;
-    }
-
-    if (qq == mDNSNULL) // The question being stopped is not a new question.
-    {
-        const CacheRecord *cr;
-        CacheGroup *const cg = CacheGroupForName(m, question->qnamehash, &question->qname);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[Q%u] Generating RMV events because the question will be stopped - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(question->TargetQID),
-            DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
-        for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
-        {
-            if (cr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameCacheRecordAnswersQuestion(cr, question))
-            {
-                // Don't use mDNS_DropLockBeforeCallback() here, since we don't allow API calls
-                if (question->QuestionCallback)
-                    question->QuestionCallback(m, question, &cr->resrec, mDNSfalse);
-            }
-        }
-    }
-
-    mDNS_StopQuery_internal(m, question);
-
-exit:
-    mDNS_Unlock(m);
-    return err;
-}
-
-mDNSexport mStatus mDNS_Reconfirm(mDNS *const m, CacheRecord *const cr)
-{
-    mStatus status;
-    mDNS_Lock(m);
-    status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-    if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, cr->resrec.InterfaceID, 0);
-    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);
-    debugf("mDNS_ReconfirmByValue: %p %s", cr, RRDisplayString(m, rr));
-    if (cr) status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-    if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, cr->resrec.InterfaceID, 0);
-    mDNS_Unlock(m);
-    return(status);
-}
-
-mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const question,
-                                            const domainname *const srv, const domainname *const domain,
-                                            const mDNSInterfaceID InterfaceID, mDNSu32 flags,
-                                            mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
-                                            mDNSQuestionCallback *Callback, void *Context)
-{
-    question->InterfaceID      = InterfaceID;
-    question->flags            = flags;
-    question->qtype            = kDNSType_PTR;
-    question->qclass           = kDNSClass_IN;
-    question->LongLived        = mDNStrue;
-    question->ExpectUnique     = mDNSfalse;
-    question->ForceMCast       = ForceMCast;
-    question->ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
-    question->SuppressUnusable = mDNSfalse;
-    question->AppendSearchDomains = mDNSfalse;
-    question->TimeoutQuestion  = 0;
-    question->WakeOnResolve    = 0;
-    question->UseBackgroundTraffic = useBackgroundTrafficClass;
-    question->ProxyQuestion    = 0;
-    question->QuestionCallback = Callback;
-    question->QuestionContext  = Context;
-
-    if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain))
-        return(mStatus_BadParamErr);
-
-    return(mDNS_StartQuery_internal(m, question));
-}
-
-mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
-                                    const domainname *const srv, const domainname *const domain,
-                                    const mDNSInterfaceID InterfaceID, mDNSu32 flags,
-                                    mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
-                                    mDNSQuestionCallback *Callback, void *Context)
-{
-    mStatus status;
-    mDNS_Lock(m);
-    status = mDNS_StartBrowse_internal(m, question, srv, domain, InterfaceID, flags, ForceMCast, useBackgroundTrafficClass, Callback, Context);
-    mDNS_Unlock(m);
-    return(status);
-}
-
-mDNSlocal mStatus mDNS_GetDomains_Internal(mDNS *const m, DNSQuestion *const question, const mDNS_DomainType DomainType,
-    const domainname * domain, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *const Callback,
-    void *const Context)
-{
-    question->InterfaceID      = InterfaceID;
-    question->flags            = 0;
-    question->qtype            = kDNSType_PTR;
-    question->qclass           = kDNSClass_IN;
-    question->LongLived        = mDNSfalse;
-    question->ExpectUnique     = mDNSfalse;
-    question->ForceMCast       = mDNSfalse;
-    question->ReturnIntermed   = mDNSfalse;
-    question->SuppressUnusable = mDNSfalse;
-    question->AppendSearchDomains = mDNSfalse;
-    question->TimeoutQuestion  = 0;
-    question->WakeOnResolve    = 0;
-    question->UseBackgroundTraffic = mDNSfalse;
-    question->ProxyQuestion    = 0;
-    question->pid              = mDNSPlatformGetPID();
-    question->euid             = 0;
-    question->QuestionCallback = Callback;
-    question->QuestionContext  = Context;
-    if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
-    if (!MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
-    if (!domain) domain = &localdomain;
-    if (!AppendDomainName(&question->qname, domain)) return(mStatus_BadParamErr);
-    return(mDNS_StartQuery_internal(m, question));
-}
-
-mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, const mDNS_DomainType DomainType,
-    const domainname *const domain, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *const Callback,
-    void *const Context)
-{
-    mDNS_Lock(m);
-    const mStatus err = mDNS_GetDomains_Internal(m, question, DomainType, domain, InterfaceID, Callback, Context);
-    mDNS_Unlock(m);
-
-    return err;
-}
-
-static const char *const mDNS_DomainType_Description[] =
-{
-    "browse domain",                // Use index mDNS_DomainTypeBrowse to get.
-    "default browse domain",        // Use index mDNS_DomainTypeBrowseDefault to get.
-    "automatic browse domain",      // Use index mDNS_DomainTypeBrowseAutomatic to get.
-    "registration domain",          // Use index mDNS_DomainTypeRegistration to get.
-    "default registration domain",  // Use index mDNS_DomainTypeRegistrationDefault to get.
-};
-#ifdef check_compile_time
-    // The index count must match the array size above.
-    check_compile_time(countof(mDNS_DomainType_Description) == mDNS_DomainTypeMaxCount);
-#endif
-
-mDNSlocal void mDNS_DeregisterDomainsDiscoveredForDomainEnumeration(mDNS *m, DomainEnumerationOp *op, mDNSu32 type);
-
-mDNSlocal mStatus mDNS_SetUpDomainEnumeration(mDNS *const m, DomainEnumerationOp *const op,
-    const mDNS_DomainType type)
-{
-    mStatus err;
-
-    // Currently, we only support doing domain enumeration looking for automatic browse domain.
-    if (type != mDNS_DomainTypeBrowseAutomatic)
-    {
-        err = mStatus_UnsupportedErr;
-        goto exit;
-    }
-
-    DomainEnumerationWithType *const enumeration = op->enumerations[type];
-    if (enumeration == mDNSNULL)
-    {
-        // No operations have been done for this domain enumeration type.
-        err = mStatus_NoError;
-        goto exit;
-    }
-
-    switch (enumeration->state)
-    {
-        case DomainEnumerationState_Stopped:
-            if (enumeration->activeClientCount == 1)
-            {
-                // If there is a client who needs to do domain enumeration, start it.
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Starting the " PUB_S " enumeration "
-                    "- domain: " PRI_DM_NAME ".", mDNS_DomainType_Description[type], DM_NAME_PARAM(&op->name));
-
-                // Avoid the build failure for the target mDNSNetMonitor and non-Apple builds.
-            #if (!defined(NET_MONITOR) || !NET_MONITOR) && defined(__APPLE__) && !defined(POSIX_BUILD)
-                err = mDNS_GetDomains_Internal(m, &enumeration->question, type, &op->name, mDNSInterface_Any,
-                    FoundNonLocalOnlyAutomaticBrowseDomain, mDNSNULL);
-            #else
-                err = mStatus_UnsupportedErr;
-            #endif
-                if (err != mStatus_NoError)
-                {
-                    goto exit;
-                }
-
-                enumeration->state = DomainEnumerationState_Started;
-            }
-            // If there are more than one clients need to do enumeration, the process has begun, no need to start again.
-            break;
-
-        case DomainEnumerationState_Started:
-            if (enumeration->activeClientCount == 0)
-            {
-                // If the number of client that need domain enumeration becomes 0, get ready to stop it.
-                // However, we give it a grace period so that the enumeration will not be stopped immediately, to
-                // avoid the case where a single client starts and stops request too frequently.
-                const mDNSs32 gracePeriodInSeconds = 60;
-
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG, "Planning to stop the " PUB_S " enumeration "
-                    "- domain: " PRI_DM_NAME ", grace period: %ds.", mDNS_DomainType_Description[type],
-                    DM_NAME_PARAM(&op->name), gracePeriodInSeconds);
-
-                enumeration->state = DomainEnumerationState_StopInProgress;
-
-                // Ensure that we will check the stop time when the grace period has passed.
-                const mDNSs32 gracePeriodPlatformTime = gracePeriodInSeconds * mDNSPlatformOneSecond;
-                enumeration->nextStopTime = NonZeroTime(m->timenow + gracePeriodPlatformTime);
-            }
-            break;
-
-        case DomainEnumerationState_StopInProgress:
-            if (enumeration->activeClientCount == 0 && m->timenow - enumeration->nextStopTime >= 0)
-            {
-                // If there is no active client that needs the domain enumeration and we have passed the scheduled
-                // stop time, stop the enumeration immediately.
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG, "Stopping the " PUB_S " enumeration "
-                    "- domain: " PRI_DM_NAME ".", mDNS_DomainType_Description[type], DM_NAME_PARAM(&op->name));
-
-                err = mDNS_StopGetDomains_Internal(m, &enumeration->question);
-                if (err != mStatus_NoError)
-                {
-                    goto exit;
-                }
-
-                mDNS_DeregisterDomainsDiscoveredForDomainEnumeration(m, op, type);
-
-                enumeration->state = DomainEnumerationState_Stopped;
-            }
-            else if (enumeration->activeClientCount == 1)
-            {
-                // If there is new client that needs the domain enumeration, terminate the stopping process and go back
-                // to the active mode.
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Resuming the " PUB_S " enumeration "
-                    "- active client count: %u, domain: " PRI_DM_NAME ".", mDNS_DomainType_Description[type],
-                        enumeration->activeClientCount, DM_NAME_PARAM(&op->name));
-
-                // Reschedule the next event since our stopping process is terminated.
-                enumeration->state = DomainEnumerationState_Started;
-            }
-            break;
-    }
-
-    err = mStatus_NoError;
-exit:
-    return err;
-}
-
-mDNSexport mStatus mDNS_StartDomainEnumeration(mDNS *const m, const domainname *const domain, const mDNS_DomainType type)
-{
-    mStatus err;
-    mDNS_Lock(m);
-
-    DomainEnumerationOp *op = mDNSNULL;
-
-    for (op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        if (SameDomainName(&op->name, domain))
-        {
-            break;
-        }
-    }
-
-    if (op == mDNSNULL)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    if (op->enumerations[type] == mDNSNULL)
-    {
-        op->enumerations[type] = mDNSPlatformMemAllocateClear(sizeof(*op->enumerations[type]));
-        if (op->enumerations[type] == mDNSNULL)
-        {
-            err = mStatus_NoMemoryErr;
-            goto exit;
-        }
-    }
-
-    op->enumerations[type]->activeClientCount++;
-
-    err = mDNS_SetUpDomainEnumeration(m, op, type);
-
-exit:
-    mDNS_Unlock(m);
-    return err;
-}
-
-mDNSexport mStatus mDNS_StopDomainEnumeration(mDNS *const m, const domainname *const domain, const mDNS_DomainType type)
-{
-    mStatus err;
-    mDNS_Lock(m);
-
-    DomainEnumerationOp *op = mDNSNULL;
-
-    for (op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        if (SameDomainName(&op->name, domain))
-        {
-            break;
-        }
-    }
-
-    if (op == mDNSNULL || op->enumerations[type] == mDNSNULL)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    if ( op->enumerations[type]->activeClientCount == 0)
-    {
-        err = mStatus_Invalid;
-        goto exit;
-    }
-
-    op->enumerations[type]->activeClientCount--;
-
-    err = mDNS_SetUpDomainEnumeration(m, op, type);
-
-exit:
-    mDNS_Unlock(m);
-    return err;
-}
-
-mDNSexport mStatus mDNS_AddDomainDiscoveredForDomainEnumeration(mDNS *const m, const domainname *const domain,
-    const mDNS_DomainType type, const domainname *const domainDiscovered)
-{
-    mStatus err;
-    mDNS_Lock(m);
-
-    DomainEnumerationOp *op = mDNSNULL;
-
-    for (op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        if (SameDomainName(&op->name, domain))
-        {
-            break;
-        }
-    }
-
-    if (op == mDNSNULL || op->enumerations[type] == mDNSNULL)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    // Remember the domain name we discovered so that when the domain enumeration is stopped when we can remove them
-    // from the auth record set.
-
-    EnumeratedDomainList *const domainDiscoveredItem = mDNSPlatformMemAllocateClear(sizeof(*domainDiscoveredItem));
-    if (domainDiscoveredItem == mDNSNULL)
-    {
-        err = mStatus_NoMemoryErr;
-        goto exit;
-    }
-
-    AssignDomainName(&domainDiscoveredItem->name, domainDiscovered);
-
-    domainDiscoveredItem->next = op->enumerations[type]->domainList;
-    op->enumerations[type]->domainList = domainDiscoveredItem;
-    err = mStatus_NoError;
-
-exit:
-    mDNS_Unlock(m);
-    return err;
-}
-
-mDNSexport mStatus mDNS_RemoveDomainDiscoveredForDomainEnumeration(mDNS *const m, const domainname *const domain,
-    const mDNS_DomainType type, const domainname *const domainDiscovered)
-{
-    mStatus err;
-    mDNS_Lock(m);
-
-    DomainEnumerationOp *op = mDNSNULL;
-
-    for (op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        if (SameDomainName(&op->name, domain))
-        {
-            break;
-        }
-    }
-
-    if (op == mDNSNULL || op->enumerations[type] == mDNSNULL)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    EnumeratedDomainList *node;
-    EnumeratedDomainList **ptr = &op->enumerations[type]->domainList;
-    while ((node = *ptr) != mDNSNULL)
-    {
-        if (SameDomainName(&node->name, domainDiscovered))
-        {
-            break;
-        }
-        ptr = &node->next;
-    }
-    if (node != mDNSNULL)
-    {
-        *ptr = node->next;
-        mDNSPlatformMemFree(node);
-    }
-
-    err = mStatus_NoError;
-
-exit:
-    mDNS_Unlock(m);
-    return err;
-}
-
-mDNSlocal void mDNS_DeregisterDomainsDiscoveredForDomainEnumeration(mDNS *const m, DomainEnumerationOp *const op,
-                                                                    const mDNSu32 type)
-{
-    // Given all the domain we have discovered through domain enumeration, deregister them from our cache.
-
-    if (op->enumerations[type] == mDNSNULL)
-    {
-        return;
-    }
-
-    for (EnumeratedDomainList *node = op->enumerations[type]->domainList, *next = mDNSNULL; node != mDNSNULL; node = next)
-    {
-        next = node->next;
-
-        // Avoid the build failure for the target mDNSNetMonitor and non-Apple builds.
-    #if (!defined(NET_MONITOR) || !NET_MONITOR) && defined(__APPLE__) && !defined(POSIX_BUILD)
-        DeregisterLocalOnlyDomainEnumPTR_Internal(m, &node->name, type, mDNStrue);
-    #else
-        (void)m;
-    #endif
-        mDNSPlatformMemFree(node);
-    }
-    op->enumerations[type]->domainList = mDNSNULL;
-}
-
-// ***************************************************************************
-// MARK: - Responder Functions
-
-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);
-}
-
-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(&rr->resrec, &newrdata->u, m->MsgBuffer));
-        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, rr->newrdlength);  // ...and let the client free this memory, if necessary
-    }
-
-    rr->NewRData             = newrdata;
-    rr->newrdlength          = newrdlength;
-    rr->UpdateCallback       = Callback;
-
-#ifndef UNICAST_DISABLED
-    if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P && AuthRecord_uDNS(rr))
-    {
-        mStatus status = uDNS_UpdateRecord(m, rr);
-        // The caller frees the memory on error, don't retain stale pointers
-        if (status != mStatus_NoError) { rr->NewRData = mDNSNULL; rr->newrdlength = 0; }
-        mDNS_Unlock(m);
-        return(status);
-    }
-#endif
-
-    if (RRLocalOnly(rr) || (rr->resrec.rrtype == kDNSType_TSR) || (rr->resrec.rroriginalttl == newttl &&
-                            rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength)))
-        CompleteRDataUpdate(m, rr);
-    else
-    {
-        rr->AnnounceCount = InitialAnnounceCount;
-        InitializeLastAPTime(m, rr);
-        while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
-        if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
-        if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval);
-        if (rr->AnnounceCount > rr->UpdateCredits + 1) rr->AnnounceCount = (mDNSu8)(rr->UpdateCredits + 1);
-        if (rr->UpdateCredits <= 5)
-        {
-            mDNSu32 delay = 6 - rr->UpdateCredits;      // Delay 1 second, then 2, then 3, etc. up to 6 seconds maximum
-            if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + (mDNSs32)delay * mDNSPlatformOneSecond);
-            rr->ThisAPInterval *= 4;
-            rr->LastAPTime = rr->UpdateBlocked - rr->ThisAPInterval;
-            LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s",
-                   rr->resrec.name->c, delay, delay > 1 ? "s" : "");
-        }
-        rr->resrec.rroriginalttl = newttl;
-    }
-
-    mDNS_Unlock(m);
-    return(mStatus_NoError);
-}
-
-// 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);
-}
-
-// Circular reference: AdvertiseInterface references mDNS_HostNameCallback, which calls mDNS_SetFQDN, which call AdvertiseInterface
-mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-mDNSlocal void mDNS_RandomizedHostNameCallback(mDNS *m, AuthRecord *rr, mStatus result);
-#endif
-
-mDNSlocal AuthRecord *GetInterfaceAddressRecord(NetworkInterfaceInfo *intf, mDNSBool forRandHostname)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        return(forRandHostname ? &intf->RR_AddrRand : &intf->RR_A);
-#else
-        (void)forRandHostname; // Unused.
-        return(&intf->RR_A);
-#endif
-}
-
-mDNSlocal AuthRecord *GetFirstAddressRecordEx(const mDNS *const m, const mDNSBool forRandHostname)
-{
-    NetworkInterfaceInfo *intf;
-    for (intf = m->HostInterfaces; intf; intf = intf->next)
-    {
-        if (!intf->Advertise) continue;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        if (mDNSPlatformInterfaceIsAWDL(intf->InterfaceID)) continue;
-#endif
-        return(GetInterfaceAddressRecord(intf, forRandHostname));
-    }
-    return(mDNSNULL);
-}
-#if !MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-#define GetFirstAddressRecord(M)    GetFirstAddressRecordEx(M, mDNSfalse)
-#endif
-
-// The parameter "set" here refers to the set of AuthRecords used to advertise this interface.
-// (It's a set of records, not a set of interfaces.)
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool useRandomizedHostname)
-#else
-mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
-#endif
-{
-    const domainname *hostname;
-    mDNSRecordCallback *hostnameCallback;
-    AuthRecord *addrAR;
-    AuthRecord *ptrAR;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    const mDNSBool interfaceIsAWDL = mDNSPlatformInterfaceIsAWDL(set->InterfaceID);
-#endif
-    mDNSu8 addrRecordType;
-    char buffer[MAX_REVERSE_MAPPING_NAME];
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (interfaceIsAWDL || useRandomizedHostname)
-    {
-        hostname         = &m->RandomizedHostname;
-        hostnameCallback = mDNS_RandomizedHostNameCallback;
-    }
-    else
-#endif
-    {
-        hostname         = &m->MulticastHostname;
-        hostnameCallback = mDNS_HostNameCallback;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (!interfaceIsAWDL && useRandomizedHostname)
-    {
-        addrAR = &set->RR_AddrRand;
-        ptrAR  = mDNSNULL;
-    }
-    else
-#endif
-    {
-        addrAR = &set->RR_A;
-        ptrAR  = &set->RR_PTR;
-    }
-    if (addrAR->resrec.RecordType != kDNSRecordTypeUnregistered) return;
-
-    addrRecordType = set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (hostname == &m->RandomizedHostname) addrRecordType = kDNSRecordTypeKnownUnique;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "AdvertiseInterface: Advertising " PUB_S " hostname on interface " PUB_S,
-        (hostname == &m->RandomizedHostname) ? "randomized" : "normal", set->ifname);
-#else
-    LogInfo("AdvertiseInterface: Advertising for ifname %s", set->ifname);
-#endif
-
-    // Send dynamic update for non-linklocal IPv4 Addresses
-    mDNS_SetupResourceRecord(addrAR, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, addrRecordType, AuthRecordAny, hostnameCallback, set);
-    if (ptrAR) mDNS_SetupResourceRecord(ptrAR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-
-#if ANSWER_REMOTE_HOSTNAME_QUERIES
-    addrAR->AllowRemoteQuery = mDNStrue;
-    if (ptrAR) ptrAR->AllowRemoteQuery = mDNStrue;
-#endif
-    // 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(&addrAR->namestorage, hostname);
-    if (set->ip.type == mDNSAddrType_IPv4)
-    {
-        addrAR->resrec.rrtype        = kDNSType_A;
-        addrAR->resrec.rdata->u.ipv4 = set->ip.ip.v4;
-        // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-        mDNS_snprintf(buffer, sizeof(buffer), "%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;
-        addrAR->resrec.rrtype        = kDNSType_AAAA;
-        addrAR->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], sizeof(buffer)-64, "ip6.arpa.");
-    }
-
-    if (ptrAR)
-    {
-        MakeDomainNameFromDNSNameString(&ptrAR->namestorage, buffer);
-        ptrAR->AutoTarget = Target_AutoHost;    // Tell mDNS that the target of this PTR is to be kept in sync with our host name
-        ptrAR->ForceMCast = mDNStrue;           // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    addrAR->RRSet = (uintptr_t)(interfaceIsAWDL ? addrAR : GetFirstAddressRecordEx(m, useRandomizedHostname));
-#else
-    addrAR->RRSet = (uintptr_t)GetFirstAddressRecord(m);
-#endif
-    if (!addrAR->RRSet) addrAR->RRSet = (uintptr_t)addrAR;
-    mDNS_Register_internal(m, addrAR);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "Initialized RRSet for " PRI_S, ARDisplayString(m, addrAR));
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "RRSet:                %" PRIxPTR "", addrAR->RRSet);
-    if (ptrAR) mDNS_Register_internal(m, ptrAR);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    // must be after the mDNS_Register_internal() calls so that records have complete rdata fields, etc
-    D2D_start_advertising_interface(set);
-#endif
-}
-
-mDNSlocal void AdvertiseInterfaceIfNeeded(mDNS *const m, NetworkInterfaceInfo *set)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (mDNSPlatformInterfaceIsAWDL(set->InterfaceID))
-    {
-        if ((m->AutoTargetAWDLIncludedCount > 0) || (m->AutoTargetAWDLOnlyCount > 0))
-        {
-            AdvertiseInterface(m, set, mDNSfalse);
-        }
-    }
-    else
-    {
-        if (m->AutoTargetServices          > 0) AdvertiseInterface(m, set, mDNSfalse);
-        if (m->AutoTargetAWDLIncludedCount > 0) AdvertiseInterface(m, set, mDNStrue);
-    }
-#else
-    if (m->AutoTargetServices > 0) AdvertiseInterface(m, set);
-#endif
-}
-
-mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set, DeadvertiseFlags flags)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    const mDNSBool interfaceIsAWDL = mDNSPlatformInterfaceIsAWDL(set->InterfaceID);
-#endif
-
-    // Unregister these records.
-    // When doing the mDNS_Exit processing, we first call 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 MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if ((!interfaceIsAWDL && (flags & kDeadvertiseFlag_NormalHostname)) ||
-        ( interfaceIsAWDL && (flags & kDeadvertiseFlag_RandHostname)))
-#else
-    if (flags & kDeadvertiseFlag_NormalHostname)
-#endif
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "DeadvertiseInterface: Deadvertising " PUB_S " hostname on interface " PUB_S,
-            (flags & kDeadvertiseFlag_RandHostname) ? "randomized" : "normal", set->ifname);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        D2D_stop_advertising_interface(set);
-#endif
-        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 MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (!interfaceIsAWDL && (flags & kDeadvertiseFlag_RandHostname))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "DeadvertiseInterface: Deadvertising randomized hostname on interface " PUB_S, set->ifname);
-        AuthRecord *const ar = &set->RR_AddrRand;
-        if (ar->resrec.RecordType) mDNS_Deregister_internal(m, ar, mDNS_Dereg_normal);
-    }
-#endif
-}
-
-// Change target host name for record.
-mDNSlocal void UpdateTargetHostName(mDNS *const m, AuthRecord *const rr)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    // If this record was also registered with any D2D plugins, stop advertising
-    // the version with the old host name.
-    D2D_stop_advertising_record(rr);
-#endif
-
-    SetTargetToHostName(m, rr);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    // Advertise the record with the updated host name with the D2D plugins if appropriate.
-    D2D_start_advertising_record(rr);
-#endif
-}
-
-mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m, DeadvertiseFlags flags)
-{
-    NetworkInterfaceInfo *intf;
-    for (intf = m->HostInterfaces; intf; intf = intf->next)
-    {
-        if (intf->Advertise) DeadvertiseInterface(m, intf, flags);
-    }
-}
-
-mDNSexport void mDNS_SetFQDN(mDNS *const m)
-{
-    domainname newmname;
-    AuthRecord *rr;
-    newmname.c[0] = 0;
-
-    if (!AppendDomainLabel(&newmname, &m->hostlabel))  { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
-    if (!AppendLiteralLabelString(&newmname, "local")) { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
-
-    mDNS_Lock(m);
-
-    if (SameDomainNameCS(&m->MulticastHostname, &newmname)) debugf("mDNS_SetFQDN - hostname unchanged");
-    else
-    {
-        AssignDomainName(&m->MulticastHostname, &newmname);
-        DeadvertiseAllInterfaceRecords(m, kDeadvertiseFlag_NormalHostname);
-        AdvertiseNecessaryInterfaceRecords(m);
-    }
-
-    // 3. Make sure that any AutoTarget SRV records (and the like) get updated
-    for (rr = m->ResourceRecords;  rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr);
-    for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr);
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void mDNS_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("mDNS_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, mStatus_NoError);
-    }
-    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
-        // This needs to be case-INSENSITIVE compare, because we need to know that the name has been changed so as to
-        // remedy the conflict, and a name that differs only in capitalization will just suffer the exact same conflict again.
-        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_SetFQDN(m);
-        LogMsg("Local Hostname %#s.local already in use; will try %#s.local instead", oldlabel.c, m->hostlabel.c);
-    }
-    else if (result == mStatus_MemFree)
-    {
-        // .local hostnames do not require goodbyes - we ignore the MemFree (which is sent directly by
-        // mDNS_Deregister_internal), and allow the caller to deallocate immediately following mDNS_DeadvertiseInterface
-        debugf("mDNS_HostNameCallback: MemFree (ignored)");
-    }
-    else
-        LogMsg("mDNS_HostNameCallback: Unknown error %d for registration of record %s", result,  rr->resrec.name->c);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-mDNSlocal void mDNS_RandomizedHostNameCallback(mDNS *const m, AuthRecord *const addrRecord, const mStatus result)
-{
-    (void)addrRecord;   // Unused parameter
-
-    if (result == mStatus_NameConflict)
-    {
-        AuthRecord *rr;
-        domainlabel newUUIDLabel;
-
-        GetRandomUUIDLabel(&newUUIDLabel);
-        if (SameDomainLabel(newUUIDLabel.c, m->RandomizedHostname.c))
-        {
-            IncrementLabelSuffix(&newUUIDLabel, mDNSfalse);
-        }
-
-        mDNS_Lock(m);
-
-        m->RandomizedHostname.c[0] = 0;
-        AppendDomainLabel(&m->RandomizedHostname, &newUUIDLabel);
-        AppendLiteralLabelString(&m->RandomizedHostname, "local");
-
-        DeadvertiseAllInterfaceRecords(m, kDeadvertiseFlag_RandHostname);
-        AdvertiseNecessaryInterfaceRecords(m);
-        for (rr = m->ResourceRecords; rr; rr = rr->next)
-        {
-            if (rr->AutoTarget && AuthRecordIncludesOrIsAWDL(rr)) UpdateTargetHostName(m, rr);
-        }
-        for (rr = m->DuplicateRecords; rr; rr = rr->next)
-        {
-            if (rr->AutoTarget && AuthRecordIncludesOrIsAWDL(rr)) UpdateTargetHostName(m, rr);
-        }
-
-        mDNS_Unlock(m);
-    }
-}
-#endif
-
-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->McastTxRx) active->IPv4Available = mDNStrue;
-            if (intf->ip.type == mDNSAddrType_IPv6 && intf->McastTxRx) active->IPv6Available = mDNStrue;
-        }
-}
-
-mDNSlocal void RestartRecordGetZoneData(mDNS * const m)
-{
-    AuthRecord *rr;
-    LogInfo("RestartRecordGetZoneData: ResourceRecords");
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-        if (AuthRecord_uDNS(rr) && rr->state != regState_NoTarget)
-        {
-            debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", rr->resrec.name->c);
-            // Zero out the updateid so that if we have a pending response from the server, it won't
-            // be accepted as a valid response. If we accept the response, we might free the new "nta"
-            if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); }
-            rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
-        }
-}
-
-mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set)
-{
-    int i;
-    // We initialize ThisQInterval to -1 indicating that the question has not been started
-    // yet. If the question (browse) is started later during interface registration, it will
-    // be stopped during interface deregistration. We can't sanity check to see if the
-    // question has been stopped or not before initializing it to -1 because we need to
-    // initialize it to -1 the very first time.
-
-    set->NetWakeBrowse.ThisQInterval = -1;
-    for (i=0; i<3; i++)
-    {
-        set->NetWakeResolve[i].ThisQInterval = -1;
-        set->SPSAddr[i].type = mDNSAddrType_None;
-    }
-    set->NextSPSAttempt     = -1;
-    set->NextSPSAttemptTime = m->timenow;
-}
-
-mDNSexport void mDNS_ActivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
-{
-    NetworkInterfaceInfo *p = m->HostInterfaces;
-    while (p && p != set) p=p->next;
-    if (!p)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_ActivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set);
-        return;
-    }
-
-    if (set->InterfaceActive)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, "ActivateNetWake for " PUB_S " (" PRI_IP_ADDR ")", set->ifname, &set->ip);
-        mDNS_StartBrowse_internal(m, &set->NetWakeBrowse, &SleepProxyServiceType, &localdomain, set->InterfaceID, 0, mDNSfalse, mDNSfalse, m->SPSBrowseCallback, set);
-    }
-}
-
-mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
-{
-    NetworkInterfaceInfo *p = m->HostInterfaces;
-    while (p && p != set) p=p->next;
-    if (!p)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_DeactivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set);
-        return;
-    }
-
-    // Note: We start the browse only if the interface is NetWake capable and we use this to
-    // stop the resolves also. Hence, the resolves should not be started without the browse
-    // being started i.e, resolves should not happen unless NetWake capable which is
-    // guaranteed by BeginSleepProcessing.
-    if (set->NetWakeBrowse.ThisQInterval >= 0)
-    {
-        int i;
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, "DeactivateNetWake for " PUB_S " (" PRI_IP_ADDR ")", set->ifname, &set->ip);
-
-        // Stop our browse and resolve operations
-        mDNS_StopQuery_internal(m, &set->NetWakeBrowse);
-        for (i=0; i<3; i++) if (set->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery_internal(m, &set->NetWakeResolve[i]);
-
-        // Make special call to the browse callback to let it know it can to remove all records for this interface
-        if (m->SPSBrowseCallback)
-        {
-            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-            m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, mDNSfalse);
-            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-        }
-
-        // Reset our variables back to initial state, so we're ready for when NetWake is turned back on
-        // (includes resetting NetWakeBrowse.ThisQInterval back to -1)
-        InitializeNetWakeState(m, set);
-    }
-}
-
-mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed)
-{
-    AuthRecord *rr;
-    mDNSBool FirstOfType = mDNStrue;
-    NetworkInterfaceInfo **p = &m->HostInterfaces;
-
-    if (!set->InterfaceID)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Tried to register a NetworkInterfaceInfo with zero InterfaceID - ifaddr: " PRI_IP_ADDR,
-            &set->ip);
-        return(mStatus_Invalid);
-    }
-
-    if (!mDNSAddressIsValidNonZero(&set->mask))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Tried to register a NetworkInterfaceInfo with invalid mask - ifaddr: "  PRI_IP_ADDR
-            ", ifmask: " PUB_IP_ADDR, &set->ip, &set->mask);
-        return(mStatus_Invalid);
-    }
-
-    mDNS_Lock(m);
-
-    // Assume this interface will be active now, unless we find a duplicate already in the list
-    set->InterfaceActive = mDNStrue;
-    set->IPv4Available   = (mDNSu8)(set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx);
-    set->IPv6Available   = (mDNSu8)(set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx);
-
-    InitializeNetWakeState(m, set);
-
-    // Scan list to see if this InterfaceID is already represented
-    while (*p)
-    {
-        if (*p == set)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Tried to register a NetworkInterfaceInfo that's already in the list - "
-                "ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR, set->ifname, &set->ip);
-            mDNS_Unlock(m);
-            return(mStatus_AlreadyRegistered);
-        }
-
-        if ((*p)->InterfaceID == set->InterfaceID)
-        {
-            // This InterfaceID already represented by a different interface in the list, so mark this instance inactive for now
-            set->InterfaceActive = mDNSfalse;
-            if (set->ip.type == (*p)->ip.type) FirstOfType = mDNSfalse;
-            if (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx) (*p)->IPv4Available = mDNStrue;
-            if (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx) (*p)->IPv6Available = mDNStrue;
-        }
-
-        p=&(*p)->next;
-    }
-
-    set->next = mDNSNULL;
-    *p = set;
-
-    if (set->Advertise) AdvertiseInterfaceIfNeeded(m, set);
-
-    if (set->InterfaceActive)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Interface not represented in list; marking active and retriggering queries - "
-            "ifid: %d, ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR, IIDPrintable(set->InterfaceID), set->ifname, &set->ip);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Interface already represented in list - ifid: %d, ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR,
-            IIDPrintable(set->InterfaceID), set->ifname, &set->ip);
-    }
-
-    if (set->NetWake) mDNS_ActivateNetWake_internal(m, set);
-
-    // In early 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 (set->McastTxRx && (FirstOfType || set->InterfaceActive))
-    {
-        DNSQuestion *q;
-        // Normally, after an interface comes up, we pause half a second before beginning probing.
-        // This is to guard against cases where there's rapid interface changes, where we could be confused by
-        // seeing packets we ourselves sent just moments ago (perhaps when this interface had a different address)
-        // which are then echoed back after a short delay by some Ethernet switches and some 802.11 base stations.
-        // We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent,
-        // and think it's a conflicting answer to our probe.
-        // In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet.
-        mDNSs32 probedelay;
-        mDNSu8 numannounce;
-        switch (activationSpeed)
-        {
-            case FastActivation:
-                probedelay = (mDNSs32)0;
-                numannounce = InitialAnnounceCount;
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
-                    "Using fast activation for DirectLink interface - ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR,
-                    set->ifname, &set->ip);
-                break;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-            case SlowActivation:
-                probedelay = mDNSPlatformOneSecond * 5;
-                numannounce = (mDNSu8)1;
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Frequent transitions for interface, doing slow activation - "
-                    "ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR, set->ifname, &set->ip);
-                m->mDNSStats.InterfaceUpFlap++;
-                break;
-#endif
-
-            case NormalActivation:
-                probedelay = mDNSPlatformOneSecond / 2;
-                numannounce = InitialAnnounceCount;
-                break;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Interface probe will be delayed - ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR ", probe delay: %d",
-            set->ifname, &set->ip, probedelay);
-
-        // No probe or sending suppression on DirectLink type interfaces.
-        if (activationSpeed == FastActivation)
-        {
-            m->SuppressQueries   = 0;
-            m->SuppressResponses = 0;
-            m->SuppressProbes    = 0;
-        }
-        else
-        {
-	        // 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 all
-	        // to go and hit the network with identical queries at exactly the same moment.
-	        // We set a random delay of up to InitialQuestionInterval (1/3 second).
-	        // We must *never* set m->SuppressQueries to more than that (or set it repeatedly in a way
-	        // that causes mDNSResponder to remain in a prolonged state of SuppressQueries, because
-	        // suppressing packet sending for more than about 1/3 second can cause protocol correctness
-	        // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts).
-	        // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically
-            if (!m->SuppressQueries)
-            {
-                m->SuppressQueries = NonZeroTime(m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval));
-            }
-            if (m->SuppressProbes == 0 ||
-                m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0)
-                m->SuppressProbes = NonZeroTime(m->timenow + probedelay);
-        }
-
-        // Include OWNER option in packets for 60 seconds after connecting to the network. Setting
-        // it here also handles the wake up case as the network link comes UP after waking causing
-        // us to reconnect to the network. If we do this as part of the wake up code, it is possible
-        // that the network link comes UP after 60 seconds and we never set the OWNER option
-        m->AnnounceOwner = NonZeroTime(m->timenow + 60 * mDNSPlatformOneSecond);
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG, "Setting AnnounceOwner");
-
-        m->mDNSStats.InterfaceUp++;
-        for (q = m->Questions; q; q=q->next)                                // Scan our list of questions
-        {
-            if (mDNSOpaque16IsZero(q->TargetQID))
-            {
-                if (!q->InterfaceID || q->InterfaceID == set->InterfaceID)      // If non-specific Q, or Q on this specific interface,
-                {                                                               // then reactivate this question
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-                    // If flapping, delay between first and second queries is nine seconds instead of one second
-                    mDNSBool dodelay = (activationSpeed == SlowActivation) && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
-                    mDNSs32 initial  = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
-                    mDNSs32 qdelay   = dodelay ? kDefaultQueryDelayTimeForFlappingInterface : 0;
-                    if (dodelay)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "No cache records expired for the question " PRI_DM_NAME " (" PUB_S ");"
-                            " delaying it by %d seconds", DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), qdelay);
-                    }
-#else
-                    mDNSs32 initial  = InitialQuestionInterval;
-                    mDNSs32 qdelay   = 0;
-#endif
-
-                    if (!q->ThisQInterval || q->ThisQInterval > initial)
-                    {
-                        q->ThisQInterval  = initial;
-                        q->RequestUnicast = kDefaultRequestUnicastCount;
-                    }
-                    q->LastQTime = m->timenow - q->ThisQInterval + qdelay;
-                    q->RecentAnswerPkts = 0;
-                    SetNextQueryTime(m,q);
-                }
-            }
-        }
-
-        // 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)
-            {
-                mDNSCoreRestartRegistration(m, rr, numannounce);
-            }
-        }
-    }
-
-    RestartRecordGetZoneData(m);
-
-    mDNS_UpdateAllowSleep(m);
-
-    mDNS_Unlock(m);
-    return(mStatus_NoError);
-}
-
-mDNSlocal void AdjustAddressRecordSetsEx(mDNS *const m, NetworkInterfaceInfo *removedIntf, mDNSBool forRandHostname)
-{
-    NetworkInterfaceInfo *intf;
-    const AuthRecord *oldAR;
-    AuthRecord *newAR;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    if (mDNSPlatformInterfaceIsAWDL(removedIntf->InterfaceID)) return;
-#endif
-    oldAR = GetInterfaceAddressRecord(removedIntf, forRandHostname);
-    newAR = GetFirstAddressRecordEx(m, forRandHostname);
-    for (intf = m->HostInterfaces; intf; intf = intf->next)
-    {
-        AuthRecord *ar;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-        if (mDNSPlatformInterfaceIsAWDL(intf->InterfaceID)) continue;
-#endif
-        ar = GetInterfaceAddressRecord(intf, forRandHostname);
-        if (ar->RRSet == (uintptr_t)oldAR)
-        {
-            ar->RRSet = (uintptr_t)(newAR ? newAR : ar);
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "Changed RRSet for " PRI_S, ARDisplayString(m, ar));
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "New RRSet:        %" PRIxPTR "", ar->RRSet);
-        }
-    }
-}
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-#define AdjustAddressRecordSetsForRandHostname(M, REMOVED_INTF) AdjustAddressRecordSetsEx(M, REMOVED_INTF, mDNStrue)
-#endif
-#define AdjustAddressRecordSets(M, REMOVED_INTF)                AdjustAddressRecordSetsEx(M, REMOVED_INTF, mDNSfalse)
-
-// 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, InterfaceActivationSpeed activationSpeed)
-{
-#if !MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-    (void)activationSpeed;   // Unused parameter
-#endif
-    NetworkInterfaceInfo **p = &m->HostInterfaces;
-    mDNSBool revalidate = mDNSfalse;
-    NetworkInterfaceInfo *intf;
-
-    mDNS_Lock(m);
-
-    // Find this record in our list
-    while (*p && *p != set) p=&(*p)->next;
-    if (!*p)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEBUG, "NetworkInterfaceInfo not found in list");
-        mDNS_Unlock(m);
-        return;
-    }
-
-    mDNS_DeactivateNetWake_internal(m, set);
-
-    // 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
-        for (intf = m->HostInterfaces; intf; intf = intf->next)
-            if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID)
-                UpdateInterfaceProtocols(m, intf);
-    }
-    else
-    {
-        intf = FirstInterfaceForID(m, set->InterfaceID);
-        if (intf)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
-                "Another representative of InterfaceID exists - ifid: %d, ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR,
-                IIDPrintable(set->InterfaceID), set->ifname, &set->ip);
-            if (intf->InterfaceActive)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "intf->InterfaceActive already set for interface - ifname: "
-                    PUB_S ", ifaddr: " PRI_IP_ADDR, set->ifname, &set->ip);
-            }
-            intf->InterfaceActive = mDNStrue;
-            UpdateInterfaceProtocols(m, intf);
-
-            if (intf->NetWake) mDNS_ActivateNetWake_internal(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
-        {
-            mDNSu32 slot;
-            CacheGroup *cg;
-            CacheRecord *rr;
-            DNSQuestion *q;
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-            mDNSu32     cacheHitMulticastCount = 0;
-            mDNSu32     cacheMissMulticastCount = 0;
-            mDNSu32     cacheHitUnicastCount = 0;
-            mDNSu32     cacheMissUnicastCount = 0;
-#endif
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Last representative of InterfaceID deregistered; marking questions etc. dormant - "
-                "ifid: %d, ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR,
-                IIDPrintable(set->InterfaceID), set->ifname, &set->ip);
-
-            m->mDNSStats.InterfaceDown++;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-            if (set->McastTxRx && (activationSpeed == SlowActivation))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "Frequent transitions for interface - ifname: " PUB_S ", ifaddr: " PRI_IP_ADDR,
-                    set->ifname, &set->ip);
-                m->mDNSStats.InterfaceDownFlap++;
-            }
-#endif
-
-            // 1. Deactivate any questions specific to this interface, and tag appropriate questions
-            // so that mDNS_RegisterInterface() knows how swiftly it needs to reactivate them
-            for (q = m->Questions; q; q=q->next)
-            {
-                if (mDNSOpaque16IsZero(q->TargetQID))                   // Only deactivate multicast quesstions. (Unicast questions are stopped when/if the associated DNS server group goes away.)
-                {
-                    if (q->InterfaceID == set->InterfaceID) q->ThisQInterval = 0;
-                    if (!q->InterfaceID || q->InterfaceID == set->InterfaceID)
-                    {
-                        q->FlappingInterface2 = q->FlappingInterface1;
-                        q->FlappingInterface1 = set->InterfaceID;       // Keep history of the last two interfaces to go away
-                    }
-                }
-            }
-
-            // 2. Flush any cache records received on this interface
-            revalidate = mDNSfalse;     // Don't revalidate if we're flushing the records
-            FORALL_CACHERECORDS(slot, cg, rr)
-            {
-                if (rr->resrec.InterfaceID == set->InterfaceID)
-                {
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-                    // If this interface is deemed flapping,
-                    // postpone deleting the cache records in case the interface comes back again
-                    if (set->McastTxRx && (activationSpeed == SlowActivation))
-                    {
-                        // For a flapping interface we want these records to go away after
-                        // kDefaultReconfirmTimeForFlappingInterface seconds if they are not reconfirmed.
-                        mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
-                        // We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them --
-                        // if the interface does come back, any relevant questions will be reactivated anyway
-                        rr->UnansweredQueries = MaxUnansweredQueries;
-                    }
-                    else
-#endif
-                    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-                        if (rr->LastCachedAnswerTime)
-                        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                            if (rr->resrec.dnsservice)  cacheHitUnicastCount++;
-#else
-                            if (rr->resrec.rDNSServer)  cacheHitUnicastCount++;
-#endif
-                            else                        cacheHitMulticastCount++;
-                        }
-                        else
-                        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                            if (rr->resrec.dnsservice)  cacheMissUnicastCount++;
-#else
-                            if (rr->resrec.rDNSServer)  cacheMissUnicastCount++;
-#endif
-                            else                        cacheMissMulticastCount++;
-                        }
-#endif
-                        mDNS_PurgeCacheResourceRecord(m, rr);
-                    }
-                }
-            }
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-            dnssd_analytics_update_cache_usage_counts(cacheHitMulticastCount, cacheMissMulticastCount, cacheHitUnicastCount, cacheMissUnicastCount);
-#endif
-        }
-    }
-
-    // If we still have address records referring to this one, update them.
-    // This is safe, because this NetworkInterfaceInfo has already been unlinked from the list,
-    // so the call to AdjustAddressRecordSets*() won’t accidentally find it.
-    AdjustAddressRecordSets(m, set);
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    AdjustAddressRecordSetsForRandHostname(m, set);
-#endif
-
-    // If we were advertising on this interface, deregister those address and reverse-lookup records now
-    if (set->Advertise) DeadvertiseInterface(m, set, kDeadvertiseFlag_All);
-
-    // 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->ShutdownTime)
-    {
-        mDNSu32 slot;
-        CacheGroup *cg;
-        CacheRecord *rr;
-        FORALL_CACHERECORDS(slot, cg, rr)
-        if (rr->resrec.InterfaceID == set->InterfaceID)
-            mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
-    }
-
-    mDNS_UpdateAllowSleep(m);
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext;
-    mDNSBool unregistered = mDNSfalse;
-
-    #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 (%d)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
-    }
-    #endif
-
-    // Only pass on the NoError acknowledgement for the SRV record (when it finishes probing)
-    if (result == mStatus_NoError && rr != &sr->RR_SRV) return;
-
-    // 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
-        mDNS_DeregisterService(m, sr);          // Unlink the records from our list
-        return;
-    }
-
-    if (result == mStatus_MemFree)
-    {
-        // If the SRV/TXT/PTR records, or the _services._dns-sd._udp record, or any of the subtype PTR records,
-        // are still in the process of deregistering, don't pass on the NameConflict/MemFree message until
-        // every record is finished cleaning up.
-        mDNSu32 i;
-        ExtraResourceRecord *e = sr->Extras;
-
-        if (sr->RR_SRV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-        if (sr->RR_TXT.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-        if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-        if (sr->RR_ADV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-        for (i=0; i<sr->NumSubTypes; i++) if (sr->SubTypes[i].resrec.RecordType != kDNSRecordTypeUnregistered) return;
-
-        while (e)
-        {
-            if (e->r.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-            e = e->next;
-        }
-
-        // 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;
-
-        // Complete any pending record updates to avoid memory leaks.
-        if (sr->RR_SRV.NewRData) CompleteRDataUpdate(m, &sr->RR_SRV);
-        if (sr->RR_TXT.NewRData) CompleteRDataUpdate(m, &sr->RR_TXT);
-        if (sr->RR_PTR.NewRData) CompleteRDataUpdate(m, &sr->RR_PTR);
-        if (sr->RR_ADV.NewRData) CompleteRDataUpdate(m, &sr->RR_ADV);
-        unregistered = mDNStrue;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "ServiceCallback: All records " PUB_S "registered for " PRI_DM_NAME,
-        unregistered ? "un" : "", DM_NAME_PARAM(sr->RR_PTR.resrec.name));
-    // 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);
-}
-
-mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext;
-    if (sr->ServiceCallback)
-        sr->ServiceCallback(m, sr, result);
-}
-
-
-// Derive AuthRecType from the kDNSServiceFlags* values.
-mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags)
-{
-    AuthRecType artype;
-
-    if (InterfaceID == mDNSInterface_LocalOnly)
-        artype = AuthRecordLocalOnly;
-    else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
-        artype = AuthRecordP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
-            && (flags & kDNSServiceFlagsIncludeAWDL))
-        artype = AuthRecordAnyIncludeAWDLandP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
-        artype = AuthRecordAnyIncludeP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL))
-        artype = AuthRecordAnyIncludeAWDL;
-    else
-        artype = AuthRecordAny;
-
-    return artype;
-}
-
-// 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. "_ipp._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->MulticastHostname) is automatically used
-// If the optional target host parameter is set, then the storage it points to must remain valid for the lifetime of the service registration
-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, RData *const txtrdata, const mDNSu8 txtinfo[], mDNSu16 txtlen,
-                                        AuthRecord *SubTypes, mDNSu32 NumSubTypes,
-                                        mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags)
-{
-    mStatus err;
-    mDNSu32 i;
-    AuthRecType artype;
-    mDNSu8 recordType = (flags & kDNSServiceFlagsKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique;
-
-    sr->ServiceCallback = Callback;
-    sr->ServiceContext  = Context;
-    sr->Conflict        = mDNSfalse;
-
-    sr->Extras          = mDNSNULL;
-    sr->NumSubTypes     = NumSubTypes;
-    sr->SubTypes        = SubTypes;
-    sr->flags           = flags;
-
-    artype = setAuthRecType(InterfaceID, flags);
-
-    // Initialize the AuthRecord objects to sane values
-    // Need to initialize everything correctly *before* making the decision whether to do a RegisterNoSuchService and bail out
-    mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, artype, ServiceCallback, sr);
-    mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared,   artype, ServiceCallback, sr);
-
-    if (flags & kDNSServiceFlagsWakeOnlyService)
-    {
-        sr->RR_PTR.AuthFlags = AuthFlagsWakeOnly;
-    }
-
-    mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, recordType, artype, ServiceCallback, sr);
-    mDNS_SetupResourceRecord(&sr->RR_TXT, txtrdata, InterfaceID, kDNSType_TXT, kStandardTTL, recordType, artype, ServiceCallback, sr);
-
-    // If port number is zero, that means the client is really trying to do a RegisterNoSuchService
-    if (mDNSIPPortIsZero(port))
-        return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, InterfaceID, NSSCallback, sr, flags));
-
-    // If the caller is registering an oversized TXT record,
-    // it is the caller's responsibility to allocate 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.namestorage, (const domainlabel*)"\x09_services", (const domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL)
-        return(mStatus_BadParamErr);
-    if (ConstructServiceName(&sr->RR_PTR.namestorage, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-    if (ConstructServiceName(&sr->RR_SRV.namestorage, name,     type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-    AssignDomainName(&sr->RR_TXT.namestorage, 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
-    // Note: uDNS registration code assumes that Additional1 points to the SRV record
-    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++)
-    {
-        domainname st;
-        AssignDomainName(&st, sr->SubTypes[i].resrec.name);
-        st.c[1+st.c[0]] = 0;            // Only want the first label, not the whole FQDN (particularly for mDNS_RenameAndReregisterService())
-        AppendDomainName(&st, type);
-        mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr);
-        if (ConstructServiceName(&sr->SubTypes[i].namestorage, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr);
-        AssignDomainName(&sr->SubTypes[i].resrec.rdata->u.name, &sr->RR_SRV.namestorage);
-        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 AutoTarget tells DNS that the target of this SRV is to be automatically kept in sync with our host name
-    if (host && host->c[0]) AssignDomainName(&sr->RR_SRV.resrec.rdata->u.srv.target, host);
-    else { sr->RR_SRV.AutoTarget = Target_AutoHost; sr->RR_SRV.resrec.rdata->u.srv.target.c[0] = '\0'; }
-
-    // 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
-    // Note: uDNS registration code assumes that DependentOn points to the SRV record
-    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(sr->RR_TXT.resrec.rdata->u.txt.c, txtinfo, txtlen);
-    }
-    sr->RR_TXT.DependentOn = &sr->RR_SRV;
-
-    mDNS_Lock(m);
-    // It is important that we register SRV first. uDNS assumes that SRV is registered first so
-    // that if the SRV cannot find a target, rest of the records that belong to this service
-    // will not be activated.
-    err = mDNS_Register_internal(m, &sr->RR_SRV);
-    // If we can't register the SRV record due to errors, bail out. It has not been inserted in
-    // any list and hence no need to deregister. We could probably do similar checks for other
-    // records below and bail out. For now, this seems to be sufficient to address rdar://9304275
-    if (err)
-    {
-        mDNS_Unlock(m);
-        return err;
-    }
-    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_StartExit, 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,  mDNSu32 flags)
-{
-    ExtraResourceRecord **e;
-    mStatus status;
-    AuthRecType artype;
-    mDNSInterfaceID InterfaceID = sr->RR_PTR.resrec.InterfaceID;
-    ResourceRecord *rr;
-
-    artype = setAuthRecType(InterfaceID, flags);
-
-    extra->next = mDNSNULL;
-    mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID,
-                             extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, artype, ServiceCallback, sr);
-    AssignDomainName(&extra->r.namestorage, sr->RR_SRV.resrec.name);
-
-    mDNS_Lock(m);
-    rr = mDNSNULL;
-    if (extra->r.resrec.rrtype == kDNSType_TXT)
-    {
-        if (sr->RR_TXT.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_TXT.resrec;
-    }
-    else if (extra->r.resrec.rrtype == kDNSType_SRV)
-    {
-        if (sr->RR_SRV.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_SRV.resrec;
-    }
-
-    if (!rr)
-    {
-        ExtraResourceRecord *srExtra;
-
-        for (srExtra = sr->Extras; srExtra; srExtra = srExtra->next)
-        {
-            if ((srExtra->r.resrec.rrtype == extra->r.resrec.rrtype) && (srExtra->r.resrec.RecordType & kDNSRecordTypeUniqueMask))
-            {
-                rr = &srExtra->r.resrec;
-                break;
-            }
-        }
-    }
-
-    if (rr && (extra->r.resrec.rroriginalttl != rr->rroriginalttl))
-    {
-        LogMsg("mDNS_AddRecordToService: Correcting TTL from %4d to %4d for %s",
-            extra->r.resrec.rroriginalttl, rr->rroriginalttl, RRDisplayString(m, &extra->r.resrec));
-        extra->r.resrec.rroriginalttl = rr->rroriginalttl;
-    }
-
-    e = &sr->Extras;
-    while (*e) e = &(*e)->next;
-
-    extra->r.DependentOn = &sr->RR_SRV;
-
-    debugf("mDNS_AddRecordToService adding record to %##s %s %d",
-           extra->r.resrec.name->c, DNSTypeName(extra->r.resrec.rrtype), extra->r.resrec.rdlength);
-
-    status = mDNS_Register_internal(m, &extra->r);
-    if (status == mStatus_NoError) *e = extra;
-
-    mDNS_Unlock(m);
-    return(status);
-}
-
-mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra,
-                                                mDNSRecordCallback MemFreeCallback, void *Context)
-{
-    ExtraResourceRecord **e;
-    mStatus status;
-
-    mDNS_Lock(m);
-    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);
-        status = mStatus_BadReferenceErr;
-    }
-    else
-    {
-        debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name->c);
-        extra->r.RecordCallback = MemFreeCallback;
-        extra->r.RecordContext  = Context;
-        *e = (*e)->next;
-        status = mDNS_Deregister_internal(m, &extra->r, mDNS_Dereg_normal);
-    }
-    mDNS_Unlock(m);
-    return(status);
-}
-
-mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname)
-{
-    // Note: Don't need to use mDNS_Lock(m) here, because this code is just using public routines
-    // mDNS_RegisterService() and mDNS_AddRecordToService(), which do the right locking internally.
-    domainlabel name1, name2;
-    domainname type, domain;
-    const domainname *host = sr->RR_SRV.AutoTarget ? mDNSNULL : &sr->RR_SRV.resrec.rdata->u.srv.target;
-    ExtraResourceRecord *extras = sr->Extras;
-    mStatus err;
-
-    DeconstructServiceName(sr->RR_SRV.resrec.name, &name1, &type, &domain);
-    if (!newname)
-    {
-        name2 = name1;
-        IncrementLabelSuffix(&name2, mDNStrue);
-        newname = &name2;
-    }
-
-    if (SameDomainName(&domain, &localdomain))
-        debugf("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c);
-    else debugf("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c);
-
-    // If there's a pending TXT record update at this point, which can happen if a DNSServiceUpdateRecord() call was made
-    // after the TXT record's deregistration, execute it now, otherwise it will be lost during the service re-registration.
-    if (sr->RR_TXT.NewRData) CompleteRDataUpdate(m, &sr->RR_TXT);
-    err = mDNS_RegisterService(m, sr, newname, &type, &domain,
-                               host, sr->RR_SRV.resrec.rdata->u.srv.port,
-                               (sr->RR_TXT.resrec.rdata != &sr->RR_TXT.rdatastorage) ? sr->RR_TXT.resrec.rdata : mDNSNULL,
-                               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, sr->flags);
-
-    // 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, 0);
-    }
-
-    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_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt)
-{
-    // If port number is zero, that means this was actually registered using mDNS_RegisterNoSuchService()
-    if (mDNSIPPortIsZero(sr->RR_SRV.resrec.rdata->u.srv.port)) return(mDNS_DeregisterNoSuchService(m, &sr->RR_SRV));
-
-    if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name->c);
-        return(mStatus_BadReferenceErr);
-    }
-    else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering)
-    {
-        LogInfo("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c);
-        // Avoid race condition:
-        // If a service gets a conflict, then we set the Conflict flag to tell us to generate
-        // an mStatus_NameConflict message when we get the mStatus_MemFree for our PTR record.
-        // If the client happens to deregister the service in the middle of that process, then
-        // we clear the flag back to the normal state, so that we deliver a plain mStatus_MemFree
-        // instead of incorrectly promoting it to mStatus_NameConflict.
-        // This race condition is exposed particularly when the conformance test generates
-        // a whole batch of simultaneous conflicts across a range of services all advertised
-        // using the same system default name, and if we don't take this precaution then
-        // we end up incrementing m->nicelabel multiple times instead of just once.
-        // <rdar://problem/4060169> Bug when auto-renaming Computer Name after name collision
-        sr->Conflict = mDNSfalse;
-        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, drt);
-
-        // 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], drt);
-
-        status = mDNS_Deregister_internal(m, &sr->RR_PTR, drt);
-        mDNS_Unlock(m);
-        return(status);
-    }
-}
-
-// 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, mDNSu32 flags)
-{
-    AuthRecType artype;
-
-    artype = setAuthRecType(InterfaceID, flags);
-
-    mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnique, artype, Callback, Context);
-    if (ConstructServiceName(&rr->namestorage, 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->AutoTarget = Target_AutoHost;
-    return(mDNS_Register(m, rr));
-}
-
-mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr,
-                                         mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname)
-{
-    AuthRecType artype;
-
-    if (InterfaceID == mDNSInterface_LocalOnly)
-        artype = AuthRecordLocalOnly;
-    else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
-        artype = AuthRecordP2P;
-    else
-        artype = AuthRecordAny;
-    mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, mDNSNULL, mDNSNULL);
-    if (!MakeDomainNameFromDNSNameString(&rr->namestorage, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
-    if (!MakeDomainNameFromDNSNameString(&rr->resrec.rdata->u.name, domname)) return(mStatus_BadParamErr);
-    return(mDNS_Register(m, rr));
-}
-
-mDNSlocal mDNSBool mDNS_IdUsedInResourceRecordsList(mDNS * const m, mDNSOpaque16 id)
-{
-    AuthRecord *r;
-    for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->updateid)) return mDNStrue;
-    return mDNSfalse;
-}
-
-mDNSlocal mDNSBool mDNS_IdUsedInQuestionsList(mDNS * const m, mDNSOpaque16 id)
-{
-    DNSQuestion *q;
-    for (q = m->Questions; q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) return mDNStrue;
-    return mDNSfalse;
-}
-
-mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m)
-{
-    mDNSOpaque16 id = zeroID;
-    int i;
-
-    for (i=0; i<10; i++)
-    {
-        id = mDNSOpaque16fromIntVal(1 + (mDNSu16)mDNSRandom(0xFFFE));
-        if (!mDNS_IdUsedInResourceRecordsList(m, id) && !mDNS_IdUsedInQuestionsList(m, id)) break;
-    }
-
-    debugf("mDNS_NewMessageID: %5d", mDNSVal16(id));
-
-    return id;
-}
-
-// ***************************************************************************
-// MARK: - Sleep Proxy Server
-
-mDNSlocal void RestartARPProbing(mDNS *const m, AuthRecord *const rr)
-{
-    // If we see an ARP from a machine we think is sleeping, then either
-    // (i) the machine has woken, or
-    // (ii) it's just a stray old packet from before the machine slept
-    // To handle the second case, we reset ProbeCount, so we'll suppress our own answers for a while, to avoid
-    // generating ARP conflicts with a waking machine, and set rr->LastAPTime so we'll start probing again in 10 seconds.
-    // If the machine has just woken then we'll discard our records when we see the first new mDNS probe from that machine.
-    // If it was a stray old packet, then after 10 seconds we'll probe again and then start answering ARPs again. In this case we *do*
-    // need to send new ARP Announcements, because the owner's ARP broadcasts will have updated neighboring ARP caches, so we need to
-    // re-assert our (temporary) ownership of that IP address in order to receive subsequent packets addressed to that IPv4 address.
-
-    rr->resrec.RecordType = kDNSRecordTypeUnique;
-    rr->ProbeCount        = DefaultProbeCountForTypeUnique;
-    rr->ProbeRestartCount++;
-
-    // If we haven't started announcing yet (and we're not already in ten-second-delay mode) the machine is probably
-    // still going to sleep, so we just reset rr->ProbeCount so we'll continue probing until it stops responding.
-    // If we *have* started announcing, the machine is probably in the process of waking back up, so in that case
-    // we're more cautious and we wait ten seconds before probing it again. We do this because while waking from
-    // sleep, some network interfaces tend to lose or delay inbound packets, and without this delay, if the waking machine
-    // didn't answer our three probes within three seconds then we'd announce and cause it an unnecessary address conflict.
-    if (rr->AnnounceCount == InitialAnnounceCount && m->timenow - rr->LastAPTime >= 0)
-        InitializeLastAPTime(m, rr);
-    else
-    {
-        rr->AnnounceCount  = InitialAnnounceCount;
-        rr->ThisAPInterval = mDNSPlatformOneSecond;
-        rr->LastAPTime     = m->timenow + mDNSPlatformOneSecond * 9;    // Send first packet at rr->LastAPTime + rr->ThisAPInterval, i.e. 10 seconds from now
-        SetNextAnnounceProbeTime(m, rr);
-    }
-}
-
-mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, const mDNSInterfaceID InterfaceID)
-{
-    static const mDNSOpaque16 ARP_op_request = { { 0, 1 } };
-    AuthRecord *rr;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
-    if (!intf) return;
-
-    mDNS_Lock(m);
-
-    // Pass 1:
-    // Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary.
-    // We also process ARPs from our own kernel (and 'answer' them by injecting a local ARP table entry)
-    // We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them.
-    // The times we might need to react to an ARP Announcement are:
-    // (i) as an indication that the host in question has not gone to sleep yet (so we should delay beginning to proxy for it) or
-    // (ii) if it's a conflicting Announcement from another host
-    // -- and we check for these in Pass 2 below.
-    if (mDNSSameOpaque16(arp->op, ARP_op_request) && !mDNSSameIPv4Address(arp->spa, arp->tpa))
-    {
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-            if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->tpa))
-            {
-                static const char msg1[] = "ARP Req from owner -- re-probing";
-                static const char msg2[] = "Ignoring  ARP Request from      ";
-                static const char msg3[] = "Creating Local ARP Cache entry  ";
-                static const char msg4[] = "Answering ARP Request from      ";
-                const char *const msg = mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC) ? msg1 :
-                                        (rr->AnnounceCount == InitialAnnounceCount)     ? msg2 :
-                                        mDNSSameEthAddress(&arp->sha, &intf->MAC)       ? msg3 : msg4;
-                LogMsg("Arp %-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s",
-                       intf->ifname, msg, arp->sha.b, arp->spa.b, arp->tpa.b,
-                       &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                if (msg == msg1)
-                {
-                    if ( rr->ProbeRestartCount < MAX_PROBE_RESTARTS)
-                        RestartARPProbing(m, rr);
-                    else
-                        LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr));
-                }
-                else if (msg == msg3)
-                {
-                    mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
-                }
-                else if (msg == msg4)
-                {
-                    const mDNSv4Addr tpa = arp->tpa;
-                    const mDNSv4Addr spa = arp->spa;
-                    SendARP(m, 2, rr, &tpa, &arp->sha, &spa, &arp->sha);
-                }
-            }
-    }
-
-    // Pass 2:
-    // For all types of ARP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding.
-    // (Strictly speaking we're only checking Announcement/Request/Reply packets, since ARP Probes have zero Sender IP address,
-    // so by definition (and by design) they can never conflict with any real (i.e. non-zero) IP address).
-    // We ignore ARPs we sent ourselves (Sender MAC address is our MAC address) because our own proxy ARPs do not constitute a conflict that we need to handle.
-    // If we see an apparently conflicting ARP, we check the sender hardware address:
-    //   If the sender hardware address is the original owner this is benign, so we just suppress our own proxy answering for a while longer.
-    //   If the sender hardware address is *not* the original owner, then this is a conflict, and we need to wake the sleeping machine to handle it.
-    if (mDNSSameEthAddress(&arp->sha, &intf->MAC))
-        debugf("ARP from self for %.4a", arp->tpa.b);
-    else
-    {
-        if (!mDNSSameIPv4Address(arp->spa, zerov4Addr))
-            for (rr = m->ResourceRecords; rr; rr=rr->next)
-                if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                    rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->spa) && (rr->ProbeRestartCount < MAX_PROBE_RESTARTS))
-                {
-                    if (mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC))
-                    {
-                        LogMsg("%-7s ARP from %.6a %.4a for %.4a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname,
-                                arp->sha.b, arp->spa.b, arp->tpa.b, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                    }
-                    else
-                    {
-                        RestartARPProbing(m, rr);
-                        if (mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC))
-                        {
-                            LogMsg("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s", intf->ifname,
-                                    mDNSSameIPv4Address(arp->spa, arp->tpa) ? "Announcement " : mDNSSameOpaque16(arp->op, ARP_op_request) ? "Request      " : "Response     ",
-                                    arp->sha.b, arp->spa.b, arp->tpa.b, ARDisplayString(m, rr));
-                        }
-                        else
-                        {
-                            LogMsg("%-7s Conflicting ARP from %.6a %.4a for %.4a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname,
-                                    arp->sha.b, arp->spa.b, arp->tpa.b, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                            ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
-                        }
-                    }
-                }
-    }
-
-    mDNS_Unlock(m);
-}
-
-/*
-   // Option 1 is Source Link Layer Address Option
-   // Option 2 is Target Link Layer Address Option
-   mDNSlocal const mDNSEthAddr *GetLinkLayerAddressOption(const IPv6NDP *const ndp, const mDNSu8 *const end, mDNSu8 op)
-    {
-    const mDNSu8 *options = (mDNSu8 *)(ndp+1);
-    while (options < end)
-        {
-        debugf("NDP Option %02X len %2d %d", options[0], options[1], end - options);
-        if (options[0] == op && options[1] == 1) return (const mDNSEthAddr*)(options+2);
-        options += options[1] * 8;
-        }
-    return mDNSNULL;
-    }
- */
-
-mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha, const mDNSv6Addr *spa,
-                                    const IPv6NDP *const ndp, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
-{
-    AuthRecord *rr;
-    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
-    if (!intf) return;
-
-    mDNS_Lock(m);
-
-    // Pass 1: Process Neighbor Solicitations, and generate a Neighbor Advertisement if necessary.
-    if (ndp->type == NDP_Sol)
-    {
-        //const mDNSEthAddr *const sha = GetLinkLayerAddressOption(ndp, end, NDP_SrcLL);
-        (void)end;
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-            if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, ndp->target))
-            {
-                static const char msg1[] = "NDP Req from owner -- re-probing";
-                static const char msg2[] = "Ignoring  NDP Request from      ";
-                static const char msg3[] = "Creating Local NDP Cache entry  ";
-                static const char msg4[] = "Answering NDP Request from      ";
-                static const char msg5[] = "Answering NDP Probe   from      ";
-                const char *const msg = mDNSSameEthAddress(sha, &rr->WakeUp.IMAC)   ? msg1 :
-                                        (rr->AnnounceCount == InitialAnnounceCount) ? msg2 :
-                                        mDNSSameEthAddress(sha, &intf->MAC)         ? msg3 :
-                                        mDNSIPv6AddressIsZero(*spa)                 ? msg4 : msg5;
-                LogSPS("%-7s %s %.6a %.16a for %.16a -- H-MAC %.6a I-MAC %.6a %s",
-                       intf->ifname, msg, sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                if (msg == msg1)
-                {
-                    if (rr->ProbeRestartCount < MAX_PROBE_RESTARTS)
-                        RestartARPProbing(m, rr);
-                    else
-                        LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr));
-                }
-                else if (msg == msg3)
-                    mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
-                else if (msg == msg4)
-                    SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha);
-                else if (msg == msg5)
-                    SendNDP(m, NDP_Adv, 0, rr, &ndp->target, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
-            }
-    }
-
-    // Pass 2: For all types of NDP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding.
-    if (mDNSSameEthAddress(sha, &intf->MAC))
-        debugf("NDP from self for %.16a", &ndp->target);
-    else
-    {
-        // For Neighbor Advertisements we check the Target address field, not the actual IPv6 source address.
-        // When a machine has both link-local and routable IPv6 addresses, it may send NDP packets making assertions
-        // about its routable IPv6 address, using its link-local address as the source address for all NDP packets.
-        // Hence it is the NDP target address we care about, not the actual packet source address.
-        if (ndp->type == NDP_Adv) spa = &ndp->target;
-        if (!mDNSSameIPv6Address(*spa, zerov6Addr))
-            for (rr = m->ResourceRecords; rr; rr=rr->next)
-                if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                    rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, *spa) && (rr->ProbeRestartCount < MAX_PROBE_RESTARTS))
-                {
-                    if (mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC))
-                    {
-                        LogSPS("%-7s NDP from %.6a %.16a for %.16a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname,
-                                    sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                    }
-                    else
-                    {
-                        RestartARPProbing(m, rr);
-                        if (mDNSSameEthAddress(sha, &rr->WakeUp.IMAC))
-                        {
-                            LogSPS("%-7s NDP %s from owner %.6a %.16a for %.16a -- re-starting probing for %s", intf->ifname,
-                                    ndp->type == NDP_Sol ? "Solicitation " : "Advertisement", sha, spa, &ndp->target, ARDisplayString(m, rr));
-                        }
-                        else
-                        {
-                            LogMsg("%-7s Conflicting NDP from %.6a %.16a for %.16a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname,
-                                    sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
-                            ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
-                        }
-                    }
-                }
-    }
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void mDNSCoreReceiveRawTransportPacket(mDNS *const m, const mDNSEthAddr *const sha, const mDNSAddr *const src, const mDNSAddr *const dst, const mDNSu8 protocol,
-                                                 const mDNSu8 *const p, const TransportLayerPacket *const t, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID, const mDNSu16 len)
-{
-    const mDNSIPPort port = (protocol == 0x06) ? t->tcp.dst : (protocol == 0x11) ? t->udp.dst : zeroIPPort;
-    mDNSBool wake = mDNSfalse;
-    mDNSBool kaWake = mDNSfalse;
-
-    switch (protocol)
-    {
-        #define XX wake ? "Received" : "Ignoring", end-p
-    case 0x01:  LogSPS("Ignoring %d-byte ICMP from %#a to %#a", end-p, src, dst);
-        break;
-
-    case 0x06:  {
-        AuthRecord *kr;
-        mDNSu32 seq, ack;
-                    #define TH_FIN  0x01
-                    #define TH_SYN  0x02
-                    #define TH_RST  0x04
-                    #define TH_ACK  0x10
-
-        kr = mDNS_MatchKeepaliveInfo(m, dst, src, port, t->tcp.src, &seq, &ack);
-        if (kr)
-        {
-            LogSPS("mDNSCoreReceiveRawTransportPacket: Found a Keepalive record from %#a:%d  to %#a:%d", src, mDNSVal16(t->tcp.src), dst, mDNSVal16(port));
-            // Plan to wake if
-            // (a) RST or FIN is set (the keepalive that we sent could have caused a reset)
-            // (b) packet that contains new data and acks a sequence number higher than the one
-            //     we have been sending in the keepalive
-
-            wake = ((t->tcp.flags & TH_RST) || (t->tcp.flags & TH_FIN)) ;
-            if (!wake)
-            {
-                mDNSu8 *ptr;
-                mDNSu32 pseq, pack;
-                mDNSBool data = mDNSfalse;
-                mDNSu8 tcphlen;
-
-                // Convert to host order
-                ptr = (mDNSu8 *)&seq;
-                seq = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
-
-                ptr = (mDNSu8 *)&ack;
-                ack = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
-
-                pseq = t->tcp.seq;
-                ptr = (mDNSu8 *)&pseq;
-                pseq = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
-
-                pack = t->tcp.ack;
-                ptr = (mDNSu8 *)&pack;
-                pack = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
-
-                // If the other side is acking one more than our sequence number (keepalive is one
-                // less than the last valid sequence sent) and it's sequence is more than what we
-                // acked before
-                //if (end - p - 34  - ((t->tcp.offset >> 4) * 4) > 0) data = mDNStrue;
-                tcphlen = ((t->tcp.offset >> 4) * 4);
-                if (end - ((const mDNSu8 *)t + tcphlen) > 0) data = mDNStrue;
-                wake = ((int)(pack - seq) > 0) && ((int)(pseq - ack) >= 0) && data;
-
-                // If we got a regular keepalive on a connection that was registed with the KeepAlive API, respond with an ACK
-                if ((t->tcp.flags & TH_ACK) && (data == mDNSfalse) &&
-                    ((int)(ack - pseq) == 1))
-                {
-                    // Send an ACK;
-                    mDNS_SendKeepaliveACK(m, kr);
-                }
-                LogSPS("mDNSCoreReceiveRawTransportPacket: End %p, hlen %d, Datalen %d, pack %u, seq %u, pseq %u, ack %u, wake %d",
-                       end, tcphlen, end - ((const mDNSu8 *)t + tcphlen), pack, seq, pseq, ack, wake);
-            }
-            else { LogSPS("mDNSCoreReceiveRawTransportPacket: waking because of RST or FIN th_flags %d", t->tcp.flags); }
-            kaWake = wake;
-        }
-        else
-        {
-            // Plan to wake if
-            // (a) RST is not set, AND
-            // (b) packet is SYN, SYN+FIN, or plain data packet (no SYN or FIN). We won't wake for FIN alone.
-            wake = (!(t->tcp.flags & TH_RST) && (t->tcp.flags & (TH_FIN|TH_SYN)) != TH_FIN);
-
-            // For now, to reduce spurious wakeups, we wake only for TCP SYN,
-            // except for ssh connections, where we'll wake for plain data packets too
-            if  (!mDNSSameIPPort(port, SSHPort) && !(t->tcp.flags & 2)) wake = mDNSfalse;
-
-            LogSPS("%s %d-byte TCP from %#a:%d to %#a:%d%s%s%s", XX,
-                   src, mDNSVal16(t->tcp.src), dst, mDNSVal16(port),
-                   (t->tcp.flags & 2) ? " SYN" : "",
-                   (t->tcp.flags & 1) ? " FIN" : "",
-                   (t->tcp.flags & 4) ? " RST" : "");
-        }
-        break;
-    }
-
-    case 0x11:  {
-                    #define ARD_AsNumber 3283
-        static const mDNSIPPort ARD = { { ARD_AsNumber >> 8, ARD_AsNumber & 0xFF } };
-        const mDNSu16 udplen = (mDNSu16)((mDNSu16)t->bytes[4] << 8 | t->bytes[5]);                  // Length *including* 8-byte UDP header
-        if (udplen >= sizeof(UDPHeader))
-        {
-            const mDNSu16 datalen = udplen - sizeof(UDPHeader);
-            wake = mDNStrue;
-
-            // For Back to My Mac UDP port 4500 (IPSEC) packets, we do some special handling
-            if (mDNSSameIPPort(port, IPSECPort))
-            {
-                // Specifically ignore NAT keepalive packets
-                if (datalen == 1 && end >= &t->bytes[9] && t->bytes[8] == 0xFF) wake = mDNSfalse;
-                else
-                {
-                    // Skip over the Non-ESP Marker if present
-                    const mDNSBool NonESP = (end >= &t->bytes[12] && t->bytes[8] == 0 && t->bytes[9] == 0 && t->bytes[10] == 0 && t->bytes[11] == 0);
-                    const IKEHeader *const ike    = (const IKEHeader *)(t + (NonESP ? 12 : 8));
-                    const mDNSu16 ikelen = datalen - (NonESP ? 4 : 0);
-                    if (ikelen >= sizeof(IKEHeader) && end >= ((const mDNSu8 *)ike) + sizeof(IKEHeader))
-                        if ((ike->Version & 0x10) == 0x10)
-                        {
-                            // ExchangeType ==  5 means 'Informational' <http://www.ietf.org/rfc/rfc2408.txt>
-                            // ExchangeType == 34 means 'IKE_SA_INIT'   <http://www.iana.org/assignments/ikev2-parameters>
-                            if (ike->ExchangeType == 5 || ike->ExchangeType == 34) wake = mDNSfalse;
-                            LogSPS("%s %d-byte IKE ExchangeType %d", XX, ike->ExchangeType);
-                        }
-                }
-            }
-
-            // For now, because we haven't yet worked out a clean elegant way to do this, we just special-case the
-            // Apple Remote Desktop port number -- we ignore all packets to UDP 3283 (the "Net Assistant" port),
-            // except for Apple Remote Desktop's explicit manual wakeup packet, which looks like this:
-            // UDP header (8 bytes)
-            // Payload: 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 110 bytes total
-            if (mDNSSameIPPort(port, ARD)) wake = (datalen >= 110 && end >= &t->bytes[10] && t->bytes[8] == 0x13 && t->bytes[9] == 0x88);
-
-            LogSPS("%s %d-byte UDP from %#a:%d to %#a:%d", XX, src, mDNSVal16(t->udp.src), dst, mDNSVal16(port));
-        }
-    }
-    break;
-
-    case 0x3A:  if (&t->bytes[len] <= end)
-        {
-            mDNSu16 checksum = IPv6CheckSum(&src->ip.v6, &dst->ip.v6, protocol, t->bytes, len);
-            if (!checksum) mDNSCoreReceiveRawND(m, sha, &src->ip.v6, &t->ndp, &t->bytes[len], InterfaceID);
-            else LogInfo("IPv6CheckSum bad %04X %02X%02X from %#a to %#a", checksum, t->bytes[2], t->bytes[3], src, dst);
-        }
-        break;
-
-    default:    LogSPS("Ignoring %d-byte IP packet unknown protocol %d from %#a to %#a", end-p, protocol, src, dst);
-        break;
-    }
-
-    if (wake)
-    {
-        AuthRecord *rr, *r2;
-
-        mDNS_Lock(m);
-        for (rr = m->ResourceRecords; rr; rr=rr->next)
-            if (rr->resrec.InterfaceID == InterfaceID &&
-                rr->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                rr->AddressProxy.type && mDNSSameAddress(&rr->AddressProxy, dst))
-            {
-                const mDNSu8 *const tp = (protocol == 6) ? (const mDNSu8 *)"\x4_tcp" : (const mDNSu8 *)"\x4_udp";
-                for (r2 = m->ResourceRecords; r2; r2=r2->next)
-                    if (r2->resrec.InterfaceID == InterfaceID && mDNSSameEthAddress(&r2->WakeUp.HMAC, &rr->WakeUp.HMAC) &&
-                        r2->resrec.RecordType != kDNSRecordTypeDeregistering &&
-                        r2->resrec.rrtype == kDNSType_SRV && mDNSSameIPPort(r2->resrec.rdata->u.srv.port, port) &&
-                        SameDomainLabel(ThirdLabel(r2->resrec.name)->c, tp))
-                        break;
-                if (!r2 && mDNSSameIPPort(port, IPSECPort)) r2 = rr;    // So that we wake for BTMM IPSEC packets, even without a matching SRV record
-                if (!r2 && kaWake) r2 = rr;                             // So that we wake for keepalive packets, even without a matching SRV record
-                if (r2)
-                {
-                    LogMsg("Waking host at %s %#a H-MAC %.6a I-MAC %.6a for %s",
-                           InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, r2));
-                    ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC);
-                }
-                else
-                    LogSPS("Sleeping host at %s %#a %.6a has no service on %#s %d",
-                           InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port));
-            }
-        mDNS_Unlock(m);
-    }
-}
-
-mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
-{
-    static const mDNSOpaque16 Ethertype_ARP  = { { 0x08, 0x06 } };  // Ethertype 0x0806 = ARP
-    static const mDNSOpaque16 Ethertype_IPv4 = { { 0x08, 0x00 } };  // Ethertype 0x0800 = IPv4
-    static const mDNSOpaque16 Ethertype_IPv6 = { { 0x86, 0xDD } };  // Ethertype 0x86DD = IPv6
-    static const mDNSOpaque16 ARP_hrd_eth    = { { 0x00, 0x01 } };  // Hardware address space (Ethernet = 1)
-    static const mDNSOpaque16 ARP_pro_ip     = { { 0x08, 0x00 } };  // Protocol address space (IP = 0x0800)
-
-    // Note: BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header.
-    // In other words, we can safely assume that pkt below (ARP, IPv4 or IPv6) is properly word aligned,
-    // but if pkt is 4-byte aligned, that necessarily means that eth CANNOT also be 4-byte aligned
-    // since it points to a an address 14 bytes before pkt.
-    const EthernetHeader     *const eth = (const EthernetHeader *)p;
-    const NetworkLayerPacket *const pkt = (const NetworkLayerPacket *)(eth+1);
-    mDNSAddr src, dst;
-    #define RequiredCapLen(P) ((P)==0x01 ? 4 : (P)==0x06 ? 20 : (P)==0x11 ? 8 : (P)==0x3A ? 24 : 0)
-
-    // Is ARP? Length must be at least 14 + 28 = 42 bytes
-    if (end >= p+42 && mDNSSameOpaque16(eth->ethertype, Ethertype_ARP) && mDNSSameOpaque16(pkt->arp.hrd, ARP_hrd_eth) && mDNSSameOpaque16(pkt->arp.pro, ARP_pro_ip))
-        mDNSCoreReceiveRawARP(m, &pkt->arp, InterfaceID);
-    // Is IPv4 with zero fragmentation offset? Length must be at least 14 + 20 = 34 bytes
-    else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv4) && (pkt->v4.flagsfrags.b[0] & 0x1F) == 0 && pkt->v4.flagsfrags.b[1] == 0)
-    {
-        const mDNSu8 *const trans = p + 14 + (pkt->v4.vlen & 0xF) * 4;
-        const mDNSu8 * transEnd = p + 14 + mDNSVal16(pkt->v4.totlen);
-        if (transEnd > end) transEnd = end;
-        debugf("Got IPv4 %02X from %.4a to %.4a", pkt->v4.protocol, &pkt->v4.src.b, &pkt->v4.dst.b);
-        src.type = mDNSAddrType_IPv4; src.ip.v4 = pkt->v4.src;
-        dst.type = mDNSAddrType_IPv4; dst.ip.v4 = pkt->v4.dst;
-        if (transEnd >= trans + RequiredCapLen(pkt->v4.protocol))
-            mDNSCoreReceiveRawTransportPacket(m, &eth->src, &src, &dst, pkt->v4.protocol, p, (const TransportLayerPacket*)trans, transEnd, InterfaceID, 0);
-    }
-    // Is IPv6? Length must be at least 14 + 28 = 42 bytes
-    else if (end >= p+54 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv6))
-    {
-        const mDNSu8 *const trans = p + 54;
-        debugf("Got IPv6  %02X from %.16a to %.16a", pkt->v6.pro, &pkt->v6.src.b, &pkt->v6.dst.b);
-        src.type = mDNSAddrType_IPv6; src.ip.v6 = pkt->v6.src;
-        dst.type = mDNSAddrType_IPv6; dst.ip.v6 = pkt->v6.dst;
-        if (end >= trans + RequiredCapLen(pkt->v6.pro))
-            mDNSCoreReceiveRawTransportPacket(m, &eth->src, &src, &dst, pkt->v6.pro, p, (const TransportLayerPacket*)trans, end, InterfaceID,
-                                              (mDNSu16)pkt->bytes[4] << 8 | pkt->bytes[5]);
-    }
-}
-
-mDNSlocal void ConstructSleepProxyServerName(mDNS *const m, domainlabel *name)
-{
-    name->c[0] = (mDNSu8)mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d.%d %#s",
-                                       m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags, &m->nicelabel);
-}
-
-#ifndef SPC_DISABLED
-mDNSlocal void SleepProxyServerCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
-{
-    if (result == mStatus_NameConflict)
-        mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
-    else if (result == mStatus_MemFree)
-    {
-        if (m->SleepState)
-            m->SPSState = 3;
-        else
-        {
-            m->SPSState = (mDNSu8)(m->SPSSocket != mDNSNULL);
-            if (m->SPSState)
-            {
-                domainlabel name;
-                ConstructSleepProxyServerName(m, &name);
-                mDNS_RegisterService(m, srs,
-                                     &name, &SleepProxyServiceType, &localdomain,
-                                     mDNSNULL, m->SPSSocket->port, // Host, port
-                                     mDNSNULL,
-                                     (mDNSu8 *)"", 1,           // TXT data, length
-                                     mDNSNULL, 0,               // Subtypes (none)
-                                     mDNSInterface_Any,         // Interface ID
-                                     SleepProxyServerCallback, mDNSNULL, 0); // Callback, context, flags
-            }
-            LogSPS("Sleep Proxy Server %#s %s", srs->RR_SRV.resrec.name->c, m->SPSState ? "started" : "stopped");
-        }
-    }
-}
-#endif
-
-// Called with lock held
-mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features)
-{
-    // This routine uses mDNS_DeregisterService and calls SleepProxyServerCallback, so we execute in user callback context
-    mDNS_DropLockBeforeCallback();
-
-    // If turning off SPS, close our socket
-    // (Do this first, BEFORE calling mDNS_DeregisterService below)
-    if (!sps && m->SPSSocket) { mDNSPlatformUDPClose(m->SPSSocket); m->SPSSocket = mDNSNULL; }
-
-    // If turning off, or changing type, deregister old name
-#ifndef SPC_DISABLED
-    if (m->SPSState == 1 && sps != m->SPSType)
-    { m->SPSState = 2; mDNS_DeregisterService_drt(m, &m->SPSRecords, sps ? mDNS_Dereg_rapid : mDNS_Dereg_normal); }
-#endif // SPC_DISABLED
-
-    // Record our new SPS parameters
-    m->SPSType          = sps;
-    m->SPSPortability   = port;
-    m->SPSMarginalPower = marginalpower;
-    m->SPSTotalPower    = totpower;
-    m->SPSFeatureFlags  = features;
-    // If turning on, open socket and advertise service
-    if (sps)
-    {
-        if (!m->SPSSocket)
-        {
-            m->SPSSocket = mDNSPlatformUDPSocket(zeroIPPort);
-            if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; }
-        }
-#ifndef SPC_DISABLED
-        if (m->SPSState == 0) SleepProxyServerCallback(m, &m->SPSRecords, mStatus_MemFree);
-#endif // SPC_DISABLED
-    }
-    else if (m->SPSState)
-    {
-        LogSPS("mDNSCoreBeSleepProxyServer turning off from state %d; will wake clients", m->SPSState);
-        m->NextScheduledSPS = m->timenow;
-    }
-fail:
-    mDNS_ReclaimLockAfterCallback();
-}
-
-// ***************************************************************************
-// MARK: - Startup and Shutdown
-
-mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
-{
-    if (storage && numrecords)
-    {
-        mDNSu32 i;
-        debugf("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity));
-        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 void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
-{
-    mDNS_Lock(m);
-    mDNS_GrowCache_internal(m, storage, numrecords);
-    mDNS_Unlock(m);
-}
-
-mDNSlocal mStatus mDNS_InitStorage(mDNS *const m, mDNS_PlatformSupport *const p,
-                                   CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
-                                   mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
-{
-    mDNSu32 slot;
-    mDNSs32 timenow;
-    mStatus result;
-
-    if (!rrcachestorage) rrcachesize = 0;
-
-    m->p                             = p;
-    m->NetworkChanged                = 0;
-    m->CanReceiveUnicastOn5353       = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise
-    m->AdvertiseLocalAddresses       = AdvertiseLocalAddresses;
-    m->DivertMulticastAdvertisements = mDNSfalse;
-    m->mDNSPlatformStatus            = mStatus_Waiting;
-    m->UnicastPort4                  = zeroIPPort;
-    m->UnicastPort6                  = zeroIPPort;
-    m->PrimaryMAC                    = zeroEthAddr;
-    m->MainCallback                  = Callback;
-    m->MainContext                   = Context;
-    m->rec.r.resrec.RecordType       = 0;
-
-    // For debugging: To catch and report locking failures
-    m->mDNS_busy               = 0;
-    m->mDNS_reentrancy         = 0;
-    m->ShutdownTime            = 0;
-    m->lock_rrcache            = 0;
-    m->lock_Questions          = 0;
-    m->lock_Records            = 0;
-
-    // Task Scheduling variables
-    result = mDNSPlatformTimeInit();
-    if (result != mStatus_NoError) return(result);
-    m->timenow_adjust = (mDNSs32)mDNSRandom(0xFFFFFFFF);
-    timenow = mDNS_TimeNow_NoLock(m);
-
-    m->timenow                 = 0;     // MUST only be set within mDNS_Lock/mDNS_Unlock section
-    m->timenow_last            = timenow;
-    m->NextScheduledEvent      = timenow;
-    m->SuppressQueries         = timenow;
-    m->SuppressResponses       = timenow;
-    m->NextCacheCheck          = timenow + FutureTime;
-    m->NextScheduledQuery      = timenow + FutureTime;
-    m->NextScheduledProbe      = timenow + FutureTime;
-    m->NextScheduledResponse   = timenow + FutureTime;
-    m->NextScheduledNATOp      = timenow + FutureTime;
-    m->NextScheduledSPS        = timenow + FutureTime;
-    m->NextScheduledKA         = timenow + FutureTime;
-    m->NextScheduledStopTime   = timenow + FutureTime;
-    m->NextBLEServiceTime      = 0;    // zero indicates inactive
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    m->NextBonjourDisableTime  = 0; // Timer active when non zero.
-    m->BonjourEnabled          = 0; // Set when Bonjour on Demand is enabled and Bonjour is currently enabled.
-#endif
-
-    m->RandomQueryDelay        = 0;
-    m->RandomReconfirmDelay    = 0;
-    m->PktNum                  = 0;
-    m->MPktNum                 = 0;
-    m->LocalRemoveEvents       = mDNSfalse;
-    m->SleepState              = SleepState_Awake;
-    m->SleepSeqNum             = 0;
-    m->SystemWakeOnLANEnabled  = mDNSfalse;
-    m->SentSleepProxyRegistration = mDNSfalse;
-    m->AnnounceOwner           = NonZeroTime(timenow + 60 * mDNSPlatformOneSecond);
-    m->DelaySleep              = 0;
-    m->SleepLimit              = 0;
-
-
-    // These fields only required for mDNS Searcher...
-    m->Questions               = mDNSNULL;
-    m->NewQuestions            = mDNSNULL;
-    m->CurrentQuestion         = mDNSNULL;
-    m->LocalOnlyQuestions      = mDNSNULL;
-    m->NewLocalOnlyQuestions   = mDNSNULL;
-    m->RestartQuestion         = 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_nextcheck[slot] = timenow + FutureTime;;
-    }
-
-    mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize);
-    m->rrauth.rrauth_free            = mDNSNULL;
-
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        m->rrauth.rrauth_hash[slot] = mDNSNULL;
-
-    // Fields below only required for mDNS Responder...
-    m->hostlabel.c[0]          = 0;
-    m->nicelabel.c[0]          = 0;
-    m->MulticastHostname.c[0]  = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    m->RandomizedHostname.c[0] = 0;
-#endif
-    m->HIHardware.c[0]         = 0;
-    m->HISoftware.c[0]         = 0;
-    m->ResourceRecords         = mDNSNULL;
-    m->DuplicateRecords        = mDNSNULL;
-    m->NewLocalRecords         = mDNSNULL;
-    m->NewLocalOnlyRecords     = mDNSfalse;
-    m->CurrentRecord           = mDNSNULL;
-    m->HostInterfaces          = mDNSNULL;
-    m->ProbeFailTime           = 0;
-    m->NumFailedProbes         = 0;
-    m->SuppressProbes          = 0;
-
-#ifndef UNICAST_DISABLED
-    m->NextuDNSEvent            = timenow + FutureTime;
-    m->NextSRVUpdate            = timenow + FutureTime;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    m->DNSServers               = mDNSNULL;
-#endif
-
-    m->Router                   = zeroAddr;
-    m->AdvertisedV4             = zeroAddr;
-    m->AdvertisedV6             = zeroAddr;
-
-    m->AuthInfoList             = mDNSNULL;
-
-    m->ReverseMap.ThisQInterval = -1;
-    m->StaticHostname.c[0]      = 0;
-    m->FQDN.c[0]                = 0;
-    m->Hostnames                = mDNSNULL;
-
-    m->WABBrowseQueriesCount    = 0;
-    m->WABLBrowseQueriesCount   = 0;
-    m->WABRegQueriesCount       = 0;
-    m->AutoTargetServices       = 0;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    m->NumAllInterfaceRecords   = 0;
-    m->NumAllInterfaceQuestions = 0;
-#endif
-    // NAT traversal fields
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    m->LLQNAT.clientCallback    = mDNSNULL;
-    m->LLQNAT.clientContext     = mDNSNULL;
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    m->NATTraversals            = mDNSNULL;
-    m->CurrentNATTraversal      = mDNSNULL;
-    m->retryIntervalGetAddr     = 0;    // delta between time sent and retry
-    m->retryGetAddr             = timenow + FutureTime; // absolute time when we retry
-    m->ExtAddress               = zerov4Addr;
-    m->PCPNonce[0]              = mDNSRandom(-1);
-    m->PCPNonce[1]              = mDNSRandom(-1);
-    m->PCPNonce[2]              = mDNSRandom(-1);
-
-    m->NATMcastRecvskt          = mDNSNULL;
-    m->LastNATupseconds         = 0;
-    m->LastNATReplyLocalTime    = timenow;
-    m->LastNATMapResultCode     = NATErr_None;
-
-    m->UPnPInterfaceID          = 0;
-    m->SSDPSocket               = mDNSNULL;
-    m->SSDPWANPPPConnection     = mDNSfalse;
-    m->UPnPRouterPort           = zeroIPPort;
-    m->UPnPSOAPPort             = zeroIPPort;
-    m->UPnPRouterURL            = mDNSNULL;
-    m->UPnPWANPPPConnection     = mDNSfalse;
-    m->UPnPSOAPURL              = mDNSNULL;
-    m->UPnPRouterAddressString  = mDNSNULL;
-    m->UPnPSOAPAddressString    = mDNSNULL;
-    m->SPSType                  = 0;
-    m->SPSPortability           = 0;
-    m->SPSMarginalPower         = 0;
-    m->SPSTotalPower            = 0;
-    m->SPSFeatureFlags          = 0;
-    m->SPSState                 = 0;
-    m->SPSProxyListChanged      = mDNSNULL;
-    m->SPSSocket                = mDNSNULL;
-    m->SPSBrowseCallback        = mDNSNULL;
-    m->ProxyRecords             = 0;
-
-    m->DNSPushServers           = mDNSNULL;
-    m->DNSPushZones             = mDNSNULL;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-    if (WCFConnectionNew)
-    {
-        m->WCF = WCFConnectionNew();
-        if (!m->WCF) { LogMsg("WCFConnectionNew failed"); return -1; }
-    }
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    // Currently we only support the root trust anchor.
-    dnssec_error_t dnssec_err;
-    m->DNSSECTrustAnchorManager = dnssec_obj_trust_anchor_manager_with_root_anchor_create(&dnssec_err);
-    if (dnssec_err != DNSSEC_ERROR_NO_ERROR)
-    {
-        return mStatus_UnknownErr;
-    }
-#endif
-
-    // Set .local domain as one of the domain that can do domain enumeration.
-    DomainEnumerationOp *const dotLocalDomainToDoEnumeration = mDNSPlatformMemAllocateClear(sizeof(*dotLocalDomainToDoEnumeration));
-    if (dotLocalDomainToDoEnumeration != mDNSNULL)
-    {
-        AssignDomainName(&dotLocalDomainToDoEnumeration->name, &localdomain);
-        m->domainsToDoEnumeration = dotLocalDomainToDoEnumeration;
-    }
-
-    return(result);
-}
-
-mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
-                             CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
-                             mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
-{
-    mStatus result = mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context);
-    if (result != mStatus_NoError)
-        return(result);
-
-#if MDNS_MALLOC_DEBUGGING
-    static mDNSListValidator lv;
-    mDNSPlatformAddListValidator(&lv, mDNS_ValidateLists, "mDNS_ValidateLists", m);
-#endif
-    result = mDNSPlatformInit(m);
-
-#ifndef UNICAST_DISABLED
-    // It's better to do this *after* the platform layer has set up the
-    // interface list and security credentials
-    uDNS_SetupDNSConfig(m);                     // Get initial DNS configuration
-#endif
-
-    return(result);
-}
-
-mDNSexport void mDNS_ConfigChanged(mDNS *const m)
-{
-    if (m->SPSState == 1)
-    {
-        domainlabel name, newname;
-#ifndef SPC_DISABLED
-        domainname type, domain;
-        DeconstructServiceName(m->SPSRecords.RR_SRV.resrec.name, &name, &type, &domain);
-#endif // SPC_DISABLED
-        ConstructSleepProxyServerName(m, &newname);
-        if (!SameDomainLabelCS(name.c, newname.c))
-        {
-            LogSPS("Renaming SPS from “%#s” to “%#s”", name.c, newname.c);
-            // When SleepProxyServerCallback gets the mStatus_MemFree message,
-            // it will reregister the service under the new name
-            m->SPSState = 2;
-#ifndef SPC_DISABLED
-            mDNS_DeregisterService_drt(m, &m->SPSRecords, mDNS_Dereg_rapid);
-#endif // SPC_DISABLED
-        }
-    }
-
-    if (m->MainCallback)
-        m->MainCallback(m, mStatus_ConfigChanged);
-}
-
-mDNSlocal void DynDNSHostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;    // unused
-    debugf("NameStatusCallback: result %d for registration of name %##s", result, rr->resrec.name->c);
-    mDNSPlatformDynDNSHostNameStatusChanged(rr->resrec.name, result);
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr)
-{
-    mDNSBool purge = cr->resrec.RecordType == kDNSRecordTypePacketNegative ||
-                     cr->resrec.rrtype     == kDNSType_A ||
-                     cr->resrec.rrtype     == kDNSType_AAAA ||
-                     cr->resrec.rrtype     == kDNSType_SRV ||
-                     cr->resrec.rrtype     == kDNSType_CNAME;
-
-    debugf("PurgeOrReconfirmCacheRecord: %s cache record due to server %#a:%d (%##s): %s",
-           purge    ? "purging"   : "reconfirming",
-           cr->resrec.rDNSServer ? &cr->resrec.rDNSServer->addr : mDNSNULL,
-           cr->resrec.rDNSServer ? mDNSVal16(cr->resrec.rDNSServer->port) : -1,
-           cr->resrec.rDNSServer ? cr->resrec.rDNSServer->domain.c : mDNSNULL, CRDisplayString(m, cr));
-
-    if (purge)
-    {
-        LogInfo("PurgeorReconfirmCacheRecord: Purging Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType);
-        mDNS_PurgeCacheResourceRecord(m, cr);
-    }
-    else
-    {
-        LogInfo("PurgeorReconfirmCacheRecord: Reconfirming Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType);
-        mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-    }
-}
-#endif
-
-mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q)
-{
-    CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-    CacheRecord *rp;
-    for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
-    {
-        if (SameNameCacheRecordAnswersQuestion(rp, q))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_PurgeBeforeResolve: Flushing " PRI_S, CRDisplayString(m, rp));
-            mDNS_PurgeCacheResourceRecord(m, rp);
-        }
-    }
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *new)
-{
-    DNSQuestion *qptr;
-
-    (void) m;
-
-    if (q->DuplicateOf)
-        LogMsg("DNSServerChangeForQuestion: ERROR: Called for duplicate question %##s", q->qname.c);
-
-    // Make sure all the duplicate questions point to the same DNSServer so that delivery
-    // of events for all of them are consistent. Duplicates for a question are always inserted
-    // after in the list.
-    q->qDNSServer = new;
-    for (qptr = q->next ; qptr; qptr = qptr->next)
-    {
-        if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = new; }
-    }
-}
-#endif
-
-mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete)
-{
-    McastResolver *mr;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer *ptr;
-#endif
-
-    if (delete)
-    {
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        for (ptr = m->DNSServers; ptr; ptr = ptr->next)
-        {
-            ptr->penaltyTime = 0;
-            ptr->flags |= DNSServerFlag_Delete;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-            if (ptr->flags & DNSServerFlag_Unreachable)
-                NumUnreachableDNSServers--;
-#endif
-        }
-#endif
-        // We handle the mcast resolvers here itself as mDNSPlatformSetDNSConfig looks at
-        // mcast resolvers. Today we get both mcast and ucast configuration using the same
-        // API
-        for (mr = m->McastResolvers; mr; mr = mr->next)
-            mr->flags |= McastResolver_FlagDelete;
-    }
-    else
-    {
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        for (ptr = m->DNSServers; ptr; ptr = ptr->next)
-        {
-            ptr->penaltyTime = 0;
-            ptr->flags &= ~DNSServerFlag_Delete;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-            if (ptr->flags & DNSServerFlag_Unreachable)
-                NumUnreachableDNSServers++;
-#endif
-        }
-#endif
-        for (mr = m->McastResolvers; mr; mr = mr->next)
-            mr->flags &= ~McastResolver_FlagDelete;
-    }
-}
-
-mDNSlocal void SetDynDNSHostNameIfChanged(mDNS *const m, domainname *const fqdn)
-{
-    // Did our FQDN change?
-    if (!SameDomainName(fqdn, &m->FQDN))
-    {
-        if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN);
-
-        AssignDomainName(&m->FQDN, fqdn);
-
-        if (m->FQDN.c[0])
-        {
-            mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
-            mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL);
-        }
-    }
-}
-
-// Even though this is called “Setup” it is not called just once at startup.
-// It’s actually called multiple times, every time there’s a configuration change.
-mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
-{
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSu32 slot;
-    CacheGroup *cg;
-    CacheRecord *cr;
-#endif
-    mDNSAddr v4, v6, r;
-    domainname fqdn;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer   *ptr, **p = &m->DNSServers;
-    const DNSServer *oldServers = m->DNSServers;
-    DNSQuestion *q;
-#endif
-    McastResolver *mr, **mres = &m->McastResolvers;
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSPushServer **psp;
-#endif
-
-    debugf("uDNS_SetupDNSConfig: entry");
-
-    // Let the platform layer get the current DNS information and setup the WAB queries if needed.
-    uDNS_SetupWABQueries(m);
-
-    mDNS_Lock(m);
-
-    // We need to first mark all the entries to be deleted. If the configuration changed, then
-    // the entries would be undeleted appropriately. Otherwise, we need to clear them.
-    //
-    // Note: The last argument to mDNSPlatformSetDNSConfig is "mDNStrue" which means ack the
-    // configuration. We already processed search domains in uDNS_SetupWABQueries above and
-    // hence we are ready to ack the configuration as this is the last call to mDNSPlatformSetConfig
-    // for the dns configuration change notification.
-    SetConfigState(m, mDNStrue);
-    if (!mDNSPlatformSetDNSConfig(mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue))
-    {
-        SetDynDNSHostNameIfChanged(m, &fqdn);
-        SetConfigState(m, mDNSfalse);
-        mDNS_Unlock(m);
-        LogInfo("uDNS_SetupDNSConfig: No configuration change");
-        return mStatus_NoError;
-    }
-
-    // For now, we just delete the mcast resolvers. We don't deal with cache or
-    // questions here. Neither question nor cache point to mcast resolvers. Questions
-    // do inherit the timeout values from mcast resolvers. But we don't bother
-    // affecting them as they never change.
-    while (*mres)
-    {
-        if (((*mres)->flags & McastResolver_FlagDelete) != 0)
-        {
-            mr = *mres;
-            *mres = (*mres)->next;
-            debugf("uDNS_SetupDNSConfig: Deleting mcast resolver %##s", mr, mr->domain.c);
-            mDNSPlatformMemFree(mr);
-        }
-        else
-        {
-            (*mres)->flags &= ~McastResolver_FlagNew;
-            mres = &(*mres)->next;
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    Querier_ProcessDNSServiceChanges();
-#else
-    // Update our qDNSServer pointers before we go and free the DNSServer object memory
-    //
-    // All non-scoped resolvers share the same resGroupID. At no point in time a cache entry using DNSServer
-    // from scoped resolver will be used to answer non-scoped questions and vice versa, as scoped and non-scoped
-    // resolvers don't share the same resGroupID. A few examples to describe the interaction with how we pick
-    // DNSServers and flush the cache.
-    //
-    // - A non-scoped question picks DNSServer X, creates a cache entry with X. If a new resolver gets added later that
-    //   is a better match, we pick the new DNSServer for the question and activate the unicast query. We may or may not
-    //   flush the cache (See PurgeOrReconfirmCacheRecord). In either case, we don't change the cache record's DNSServer
-    //   pointer immediately (qDNSServer and rDNSServer may be different but still share the same resGroupID). If we don't
-    //   flush the cache immediately, the record's rDNSServer pointer will be updated (in mDNSCoreReceiveResponse)
-    //   later when we get the response. If we purge the cache, we still deliver a RMV when it is purged even though
-    //   we don't update the cache record's DNSServer pointer to match the question's DNSSever, as they both point to
-    //   the same resGroupID.
-    //
-    //   Note: If the new DNSServer comes back with a different response than what we have in the cache, we will deliver a RMV
-    //   of the old followed by ADD of the new records.
-    //
-    // - A non-scoped question picks DNSServer X,  creates a cache entry with X. If the resolver gets removed later, we will
-    //   pick a new DNSServer for the question which may or may not be NULL and set the cache record's pointer to the same
-    //   as in question's qDNSServer if the cache record is not flushed. If there is no active question, it will be set to NULL.
-    //
-    // - Two questions scoped and non-scoped for the same name will pick two different DNSServer and will end up creating separate
-    //   cache records and as the resGroupID is different, you can't use the cache record from the scoped DNSServer to answer the
-    //   non-scoped question and vice versa.
-    //
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    DNS64RestartQuestions(m);
-#endif
-
-    // First, restart questions whose suppression status will change. The suppression status of each question in a given
-    // question set, i.e., a non-duplicate question and all of its duplicates, if any, may or may not change. For example,
-    // a suppressed (or non-suppressed) question that is currently a duplicate of a suppressed (or non-suppressed) question
-    // may become a non-suppressed (or suppressed) question, while the question that it's a duplicate of may remain
-    // suppressed (or non-suppressed).
-    for (q = m->Questions; q; q = q->next)
-    {
-        DNSServer *s;
-        const DNSServer *t;
-        mDNSBool oldSuppressed;
-
-        if (mDNSOpaque16IsZero(q->TargetQID)) continue;
-
-        SetValidDNSServers(m, q);
-        q->triedAllServersOnce = mDNSfalse;
-        s = GetServerForQuestion(m, q);
-        t = q->qDNSServer;
-        if (s != t)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[R%u->Q%u] uDNS_SetupDNSConfig: Updating DNS server from " PRI_IP_ADDR ":%d (" PRI_DM_NAME ") to "
-                PRI_IP_ADDR ":%d (" PRI_DM_NAME ") for question " PRI_DM_NAME " (" PUB_S ") (scope:%p)",
-                q->request_id, mDNSVal16(q->TargetQID),
-                t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), DM_NAME_PARAM(t ? &t->domain : mDNSNULL),
-                s ? &s->addr : mDNSNULL, mDNSVal16(s ? s->port : zeroIPPort), DM_NAME_PARAM(s ? &s->domain : mDNSNULL),
-                DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->InterfaceID);
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-            // If this question had a DNS Push server associated with it, substitute the new server for the
-            // old one.   If there is no new server, then we'll clean up the push server later.
-            if (!q->DuplicateOf && (q->dnsPushServer != mDNSNULL))
-            {
-                if (q->dnsPushServer->qDNSServer == t)
-                {
-                    q->dnsPushServer->qDNSServer = s; // which might be null
-                }
-                // If it is null, cancel the DNS push server.
-                if (q->dnsPushServer->qDNSServer == mDNSNULL)
-                {
-                    DNSPushReconcileConnection(m, q);
-                }
-            }
-#endif
-        }
-        oldSuppressed = q->Suppressed;
-        q->Suppressed = ShouldSuppressUnicastQuery(q, s);
-        if (!q->Suppressed != !oldSuppressed) q->Restart = mDNStrue;
-    }
-    RestartUnicastQuestions(m);
-
-    // Now, change the server for each question set, if necessary. Note that questions whose suppression status changed
-    // have already had their server changed by being restarted.
-    for (q = m->Questions; q; q = q->next)
-    {
-        DNSServer *s;
-        const DNSServer *t;
-
-        if (mDNSOpaque16IsZero(q->TargetQID) || q->DuplicateOf) continue;
-
-        SetValidDNSServers(m, q);
-        q->triedAllServersOnce = mDNSfalse;
-        s = GetServerForQuestion(m, q);
-        t = q->qDNSServer;
-        DNSServerChangeForQuestion(m, q, s);
-        if (s == t) continue;
-
-        q->Suppressed = ShouldSuppressUnicastQuery(q, s);
-        q->unansweredQueries = 0;
-        q->TargetQID = mDNS_NewMessageID(m);
-        if (!q->Suppressed) ActivateUnicastQuery(m, q, mDNStrue);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    // The above code may have found some DNS Push servers that are no longer valid.   Now that we
-    // are done running through the code, we need to drop our connections to those servers.
-    // When we get here, any such servers should have zero questions associated with them.
-    for (psp = &m->DNSPushServers; *psp != mDNSNULL; )
-    {
-        DNSPushServer *server = *psp;
-
-        // It's possible that a push server whose DNS server has been deleted could be still connected but
-        // not referenced by any questions.  In this case, we just delete the push server rather than trying
-        // to figure out with which DNS server (if any) to associate it.
-        if (server->qDNSServer == mDNSNULL || (server->qDNSServer->flags & DNSServerFlag_Delete))
-        {
-            // Since we are changing the m->DNSPushServers that DNSPushServerCancel() will iterate later, we will do the
-            // server removal for it. And tell it to not touch the m->DNSPushServers by passing alreadyRemovedFromSystem
-            // == true.
-            // Unlink from the m->DNSPushServers list.
-            *psp = server->next;
-            server->next = mDNSNULL;
-            // Release all the DNS push zones that use this server from the m->DNSPushZones list.
-            DNSPushZoneRemove(m, server);
-            // Cancel the server.
-            DNSPushServerCancel(server, mDNStrue);
-            // Release the reference to the server that m->DNSPushServers list holds.
-            DNS_PUSH_RELEASE(server, DNSPushServerFinalize);
-        }
-        else
-        {
-            psp = &(server->next);
-        }
-    }
-#endif
-
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->resrec.InterfaceID) continue;
-
-        // We already walked the questions and restarted/reactivated them if the dns server
-        // change affected the question. That should take care of updating the cache. But
-        // what if there is no active question at this point when the DNS server change
-        // happened ? There could be old cache entries lying around and if we don't flush
-        // them, a new question after the DNS server change could pick up these stale
-        // entries and get a wrong answer.
-        //
-        // For cache entries that have active questions we might have skipped rescheduling
-        // the questions if they were suppressed (see above). To keep it simple, we walk
-        // all the cache entries to make sure that there are no stale entries. We use the
-        // active question's InterfaceID/ServiceID for looking up the right DNS server.
-        //
-        // Note: If GetServerForName returns NULL, it could either mean that there are no
-        // DNS servers or no matching DNS servers for this question. In either case,
-        // the cache should get purged below when we process deleted DNS servers.
-
-        if (cr->CRActiveQuestion)
-        {
-            // Purge or Reconfirm if this cache entry would use the new DNS server
-            ptr = GetServerForName(m, cr->resrec.name, cr->CRActiveQuestion->InterfaceID, cr->CRActiveQuestion->ServiceID);
-            if (ptr && (ptr != cr->resrec.rDNSServer))
-            {
-                LogInfo("uDNS_SetupDNSConfig: Purging/Reconfirming Resourcerecord %s, New DNS server %#a, Old DNS server %#a",
-                        CRDisplayString(m, cr), &ptr->addr,
-                        cr->resrec.rDNSServer ? &cr->resrec.rDNSServer->addr : mDNSNULL);
-                PurgeOrReconfirmCacheRecord(m, cr);
-
-                // If a cache record's DNSServer pointer is NULL, but its active question got a DNSServer in this DNS configuration
-                // update, then use its DNSServer. This way, the active question and its duplicates don't miss out on RMV events.
-                if (!cr->resrec.rDNSServer && cr->CRActiveQuestion->qDNSServer)
-                {
-                    LogInfo("uDNS_SetupDNSConfig: Using active question's DNS server %#a for cache record %s", &cr->CRActiveQuestion->qDNSServer->addr, CRDisplayString(m, cr));
-                    cr->resrec.rDNSServer = cr->CRActiveQuestion->qDNSServer;
-                }
-            }
-
-            if (cr->resrec.rDNSServer && cr->resrec.rDNSServer->flags & DNSServerFlag_Delete)
-            {
-                DNSQuestion *qptr = cr->CRActiveQuestion;
-                if (qptr->qDNSServer == cr->resrec.rDNSServer)
-                {
-                    LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s  Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a"
-                           " to be freed", CRDisplayString(m, cr),
-                           qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID,
-                           &cr->resrec.rDNSServer->addr);
-                    qptr->validDNSServers = zeroOpaque128;
-                    qptr->qDNSServer = mDNSNULL;
-                    cr->resrec.rDNSServer = mDNSNULL;
-                }
-                else
-                {
-                    LogInfo("uDNS_SetupDNSConfig: Cache Record %s,  Active question %##s (%s) (scope:%p), pointing to DNSServer %#a (to be deleted),"
-                            " resetting to  question's DNSServer Address %#a", CRDisplayString(m, cr),
-                            qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID,
-                            &cr->resrec.rDNSServer->addr,
-                            qptr->qDNSServer ? &qptr->qDNSServer->addr : mDNSNULL);
-                    cr->resrec.rDNSServer = qptr->qDNSServer;
-                }
-                PurgeOrReconfirmCacheRecord(m, cr);
-            }
-        }
-        else if (!cr->resrec.rDNSServer || cr->resrec.rDNSServer->flags & DNSServerFlag_Delete)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "uDNS_SetupDNSConfig: Purging Resourcerecord " PRI_S ", DNS server " PUB_S " " PRI_IP_ADDR " " PUB_S,
-                CRDisplayString(m, cr), !cr->resrec.rDNSServer ? "(to be deleted)" : "",
-                cr->resrec.rDNSServer ? &cr->resrec.rDNSServer->addr : mDNSNULL,
-                cr->resrec.rDNSServer ? DNSScopeToString(cr->resrec.rDNSServer->scopeType) : "" );
-            cr->resrec.rDNSServer = mDNSNULL;
-            mDNS_PurgeCacheResourceRecord(m, cr);
-        }
-    }
-
-    //  Delete all the DNS servers that are flagged for deletion
-    while (*p)
-    {
-        if (((*p)->flags & DNSServerFlag_Delete) != 0)
-        {
-            ptr = *p;
-            *p = (*p)->next;
-            LogInfo("uDNS_SetupDNSConfig: Deleting server %p %#a:%d (%##s)", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c);
-            mDNSPlatformMemFree(ptr);
-        }
-        else
-        {
-            p = &(*p)->next;
-        }
-    }
-    LogInfo("uDNS_SetupDNSConfig: CountOfUnicastDNSServers %d", CountOfUnicastDNSServers(m));
-
-    // If we now have no DNS servers at all and we used to have some, then immediately purge all unicast cache records (including for LLQs).
-    // This is important for giving prompt remove events when the user disconnects the Ethernet cable or turns off wireless.
-    // Otherwise, stale data lingers for 5-10 seconds, which is not the user-experience people expect from Bonjour.
-    // Similarly, if we now have some DNS servers and we used to have none, we want to purge any fake negative results we may have generated.
-    if ((m->DNSServers != mDNSNULL) != (oldServers != mDNSNULL))
-    {
-        int count = 0;
-        FORALL_CACHERECORDS(slot, cg, cr)
-        {
-            if (!cr->resrec.InterfaceID)
-            {
-                mDNS_PurgeCacheResourceRecord(m, cr);
-                count++;
-            }
-        }
-        LogInfo("uDNS_SetupDNSConfig: %s available; purged %d unicast DNS records from cache",
-                m->DNSServers ? "DNS server became" : "No DNS servers", count);
-
-        // Force anything that needs to get zone data to get that information again
-        RestartRecordGetZoneData(m);
-    }
-#endif // !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-    SetDynDNSHostNameIfChanged(m, &fqdn);
-
-    mDNS_Unlock(m);
-
-    // handle router and primary interface changes
-    v4 = v6 = r = zeroAddr;
-    v4.type = r.type = mDNSAddrType_IPv4;
-
-    if (mDNSPlatformGetPrimaryInterface(&v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4))
-    {
-        mDNS_SetPrimaryInterfaceInfo(m,
-                                     !mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL,
-                                     !mDNSIPv6AddressIsZero(v6.ip.v6) ? &v6 : mDNSNULL,
-                                     !mDNSIPv4AddressIsZero(r.ip.v4) ? &r  : mDNSNULL);
-    }
-    else
-    {
-        mDNS_SetPrimaryInterfaceInfo(m, mDNSNULL, mDNSNULL, mDNSNULL);
-        if (m->FQDN.c[0]) mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); // Set status to 1 to indicate temporary failure
-    }
-
-    debugf("uDNS_SetupDNSConfig: number of unicast DNS servers %d", CountOfUnicastDNSServers(m));
-    return mStatus_NoError;
-}
-
-mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result)
-{
-    m->mDNSPlatformStatus = result;
-    if (m->MainCallback)
-    {
-        mDNS_Lock(m);
-        mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-        m->MainCallback(m, mStatus_NoError);
-        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-        mDNS_Unlock(m);
-    }
-}
-
-mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start)
-{
-    m->CurrentRecord = start;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rr = m->CurrentRecord;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DeregLoop: " PUB_S " deregistration for %p %02X " PRI_S,
-            (rr->resrec.RecordType != kDNSRecordTypeDeregistering) ? "Initiating  " : "Accelerating",
-            rr, rr->resrec.RecordType, ARDisplayString(m, rr));
-        if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
-            mDNS_Deregister_internal(m, rr, mDNS_Dereg_rapid);
-        else if (rr->AnnounceCount > 1)
-        {
-            rr->AnnounceCount = 1;
-            rr->LastAPTime = m->timenow - rr->ThisAPInterval;
-            SetNextAnnounceProbeTime(m, rr);
-        }
-        // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
-        // new records could have been added to the end of the list as a result of that call.
-        if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
-            m->CurrentRecord = rr->next;
-    }
-}
-
-mDNSexport void mDNS_StartExit(mDNS *const m)
-{
-    AuthRecord *rr;
-
-    mDNS_Lock(m);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit");
-    m->ShutdownTime = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
-
-    mDNSCoreBeSleepProxyServer_internal(m, 0, 0, 0, 0, 0);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-    if (WCFConnectionDealloc)
-    {
-        if (m->WCF)
-        {
-            WCFConnectionDealloc(m->WCF);
-            m->WCF = mDNSNULL;
-        }
-    }
-#endif
-
-#ifndef UNICAST_DISABLED
-    {
-        SearchListElem *s;
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-        SuspendLLQs(m);
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-        // Don't need to do SleepRecordRegistrations() here
-        // because we deregister all records and services later in this routine
-        while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
-
-        // For each member of our SearchList, deregister any records it may have created, and cut them from the list.
-        // Otherwise they'll be forcibly deregistered for us (without being cut them from the appropriate list)
-        // and we may crash because the list still contains dangling pointers.
-        for (s = SearchList; s; s = s->next)
-            while (s->AuthRecs)
-            {
-                ARListElem *dereg = s->AuthRecs;
-                s->AuthRecs = s->AuthRecs->next;
-                mDNS_Deregister_internal(m, &dereg->ar, mDNS_Dereg_normal); // Memory will be freed in the FreeARElemCallback
-            }
-    }
-#endif
-
-    // When mDNSResponder exits, also deregister all the domains that are discovered through domain enumeration.
-    for (DomainEnumerationOp *op = m->domainsToDoEnumeration; op != mDNSNULL; op = op->next)
-    {
-        for (mDNSu32 type = 0; type < mDNS_DomainTypeMaxCount; type++)
-        {
-            mDNS_DeregisterDomainsDiscoveredForDomainEnumeration(m, op, type);
-        }
-    }
-
-    DeadvertiseAllInterfaceRecords(m, kDeadvertiseFlag_All);
-
-    // Shut down all our active NAT Traversals
-    while (m->NATTraversals)
-    {
-        NATTraversalInfo *t = m->NATTraversals;
-        mDNS_StopNATOperation_internal(m, t);       // This will cut 't' from the list, thereby advancing m->NATTraversals in the process
-
-        // After stopping the NAT Traversal, we zero out the fields.
-        // This has particularly important implications for our AutoTunnel records --
-        // when we deregister our AutoTunnel records below, we don't want their mStatus_MemFree
-        // handlers to just turn around and attempt to re-register those same records.
-        // Clearing t->ExternalPort/t->RequestedPort will cause the mStatus_MemFree callback handlers
-        // to not do this.
-        t->ExternalAddress = zerov4Addr;
-        t->NewAddress      = zerov4Addr;
-        t->ExternalPort    = zeroIPPort;
-        t->RequestedPort   = zeroIPPort;
-        t->Lifetime        = 0;
-        t->Result          = mStatus_NoError;
-    }
-
-    // Make sure there are nothing but deregistering records remaining in the list
-    if (m->CurrentRecord)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: ERROR m->CurrentRecord already set " PRI_S, ARDisplayString(m, m->CurrentRecord));
-    }
-
-    // We're in the process of shutting down, so queries, etc. are no longer available.
-    // Consequently, determining certain information, e.g. the uDNS update server's IP
-    // address, will not be possible.  The records on the main list are more likely to
-    // already contain such information, so we deregister the duplicate records first.
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: Deregistering duplicate resource records");
-    DeregLoop(m, m->DuplicateRecords);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: Deregistering resource records");
-
-    DeregLoop(m, m->ResourceRecords);
-
-    // If we scheduled a response to send goodbye packets, we set NextScheduledResponse to now. Normally when deregistering records,
-    // we allow up to 100ms delay (to help improve record grouping) but when shutting down we don't want any such delay.
-    if (m->NextScheduledResponse - m->timenow < mDNSPlatformOneSecond)
-    {
-        m->NextScheduledResponse = m->timenow;
-        m->SuppressResponses = 0;
-    }
-
-    if (m->ResourceRecords)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: Sending final record deregistrations");
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: No deregistering records remain");
-    }
-
-    for (rr = m->DuplicateRecords; rr; rr = rr->next)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: Should not still have Duplicate Records remaining: %02X " PRI_S,
-            rr->resrec.RecordType, ARDisplayString(m, rr));
-    }
-
-    // If any deregistering records remain, send their deregistration announcements before we exit
-    if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
-
-    mDNS_Unlock(m);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartExit: done");
-}
-
-mDNSexport void mDNS_FinalExit(mDNS *const m)
-{
-    mDNSu32 rrcache_active = 0;
-    mDNSu32 rrcache_totalused = m->rrcache_totalused;
-    mDNSu32 slot;
-    AuthRecord *rr;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_FinalExit: mDNSPlatformClose");
-    mDNSPlatformClose(m);
-
-    for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-    {
-        while (m->rrcache_hash[slot])
-        {
-            CacheGroup *cg = m->rrcache_hash[slot];
-            while (cg->members)
-            {
-                CacheRecord *cr = cg->members;
-                cg->members = cg->members->next;
-                if (cr->CRActiveQuestion) rrcache_active++;
-                ReleaseCacheRecord(m, cr);
-            }
-            cg->rrcache_tail = &cg->members;
-            ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
-        }
-    }
-    debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
-    if (rrcache_active != m->rrcache_active)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "*** ERROR *** rrcache_totalused %u; rrcache_active %u != m->rrcache_active %u",
-            rrcache_totalused, rrcache_active, m->rrcache_active);
-    }
-
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_FinalExit failed to send goodbye for: %p %02X " PRI_S, rr, rr->resrec.RecordType,
-            ARDisplayString(m, rr));
-    }
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    tls_cert_dispose();
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    MDNS_DISPOSE_DNSSEC_OBJ(m->DNSSECTrustAnchorManager);
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_FinalExit: done");
-}
-
-#ifdef UNIT_TEST
-#include "../unittests/mdns_ut.c"
-#endif
diff --git a/mDNSCore/mDNSDebug.h b/mDNSCore/mDNSDebug.h
deleted file mode 100644
index be3539b..0000000
--- a/mDNSCore/mDNSDebug.h
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __mDNSDebug_h
-#define __mDNSDebug_h
-
-#include "mDNSFeatures.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-#include <os/log.h>
-#endif
-
-// 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
-// (If you edit the file here to turn on MDNS_DEBUGMSGS while you're debugging some code, be careful
-// not to accidentally check-in that change by mistake when you check in your other changes.)
-
-#ifndef MDNS_DEBUGMSGS
-#define MDNS_DEBUGMSGS 0
-#endif
-
-// 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 MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-typedef os_log_t mDNSLogCategory_t;
-
-typedef os_log_type_t mDNSLogLevel_t;
-#define MDNS_LOG_FAULT      OS_LOG_TYPE_FAULT
-#define MDNS_LOG_ERROR      OS_LOG_TYPE_ERROR
-#define MDNS_LOG_WARNING    OS_LOG_TYPE_DEFAULT
-#define MDNS_LOG_DEFAULT    OS_LOG_TYPE_DEFAULT
-#define MDNS_LOG_INFO       OS_LOG_TYPE_INFO
-#define MDNS_LOG_DEBUG      OS_LOG_TYPE_DEBUG
-#else
-typedef const char * mDNSLogCategory_t;
-typedef enum
-{
-    MDNS_LOG_FAULT   = 1,
-    MDNS_LOG_ERROR   = 2,
-    MDNS_LOG_WARNING = 3,
-    MDNS_LOG_DEFAULT = 4,
-    MDNS_LOG_INFO    = 5,
-    MDNS_LOG_DEBUG   = 6
-} mDNSLogLevel_t;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-
-    #define MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(NAME)                       \
-        extern os_log_t mDNSLogCategory_ ## NAME;                           \
-        extern os_log_t mDNSLogCategory_ ## NAME ## _redacted
-
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(Default);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(mDNS);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(uDNS);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(SPS);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(NAT);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(D2D);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(XPC);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(Analytics);
-    MDNS_OS_LOG_CATEGORY_DECLARE_EXTERN(DNSSEC);
-
-    #define MDNS_LOG_CATEGORY_DEFINITION(NAME)  mDNSLogCategory_ ## NAME
-#else
-    #define MDNS_LOG_CATEGORY_DEFINITION(NAME)  # NAME
-#endif
-
-#define MDNS_LOG_CATEGORY_DEFAULT   MDNS_LOG_CATEGORY_DEFINITION(Default)
-#define MDNS_LOG_CATEGORY_MDNS      MDNS_LOG_CATEGORY_DEFINITION(mDNS)
-#define MDNS_LOG_CATEGORY_UDNS      MDNS_LOG_CATEGORY_DEFINITION(uDNS)
-#define MDNS_LOG_CATEGORY_SPS       MDNS_LOG_CATEGORY_DEFINITION(SPS)
-#define MDNS_LOG_CATEGORY_NAT       MDNS_LOG_CATEGORY_DEFINITION(NAT)
-#define MDNS_LOG_CATEGORY_D2D       MDNS_LOG_CATEGORY_DEFINITION(D2D)
-#define MDNS_LOG_CATEGORY_XPC       MDNS_LOG_CATEGORY_DEFINITION(XPC)
-#define MDNS_LOG_CATEGORY_ANALYTICS MDNS_LOG_CATEGORY_DEFINITION(Analytics)
-#define MDNS_LOG_CATEGORY_DNSSEC    MDNS_LOG_CATEGORY_DEFINITION(DNSSEC)
-
-// Use MDNS_LOG_CATEGORY_DISABLED to disable a log temporarily.
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define MDNS_LOG_CATEGORY_DISABLED OS_LOG_DISABLED
-#else
-    #define MDNS_LOG_CATEGORY_DISABLED "Log Disabled"
-#endif
-
-// Set this symbol to 1 to answer remote queries for our Address, and reverse mapping PTR
-#define ANSWER_REMOTE_HOSTNAME_QUERIES 0
-
-// Set this symbol to 1 to do extra debug checks on malloc() and free()
-// Set this symbol to 2 to write a log message for every malloc() and free()
-#ifndef MDNS_MALLOC_DEBUGGING
-#define MDNS_MALLOC_DEBUGGING 0
-#endif
-
-#if (MDNS_MALLOC_DEBUGGING > 0) && defined(WIN32)
-#error "Malloc debugging does not yet work on Windows"
-#endif
-
-#define ForceAlerts 0
-//#define LogTimeStamps 1
-
-// Developer-settings section ends here
-
-#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
-
-// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
-
-#if (defined(__GNUC__))
-    #if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
-        #define MDNS_C99_VA_ARGS        1
-        #define MDNS_GNU_VA_ARGS        0
-    #else
-        #define MDNS_C99_VA_ARGS        0
-        #define MDNS_GNU_VA_ARGS        1
-    #endif
-    #define MDNS_HAS_VA_ARG_MACROS      1
-#elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
-    #define MDNS_C99_VA_ARGS            1
-    #define MDNS_GNU_VA_ARGS            0
-    #define MDNS_HAS_VA_ARG_MACROS      1
-#elif (defined(__MWERKS__))
-    #define MDNS_C99_VA_ARGS            1
-    #define MDNS_GNU_VA_ARGS            0
-    #define MDNS_HAS_VA_ARG_MACROS      1
-#else
-    #define MDNS_C99_VA_ARGS            0
-    #define MDNS_GNU_VA_ARGS            0
-    #define MDNS_HAS_VA_ARG_MACROS      0
-#endif
-
-#if (MDNS_HAS_VA_ARG_MACROS)
-    #if (MDNS_C99_VA_ARGS)
-        #define MDNS_LOG_DEFINITION(LEVEL, ...) \
-            do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, LEVEL, __VA_ARGS__); } while (0)
-
-        #define debug_noop(...)   do {} while(0)
-        #define LogMsg(...)       LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, __VA_ARGS__)
-        #define LogOperation(...) MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
-        #define LogSPS(...)       MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
-        #define LogInfo(...)      MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  __VA_ARGS__)
-        #define LogDebug(...)     MDNS_LOG_DEFINITION(MDNS_LOG_DEBUG, __VA_ARGS__)
-    #elif (MDNS_GNU_VA_ARGS)
-        #define MDNS_LOG_DEFINITION(LEVEL, ARGS...) \
-            do { if (mDNS_LoggingEnabled) LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, LEVEL, ARGS); } while (0)
-
-        #define debug_noop(ARGS...)   do {} while (0)
-        #define LogMsg(ARGS... )      LogMsgWithLevel(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, ARGS)
-        #define LogOperation(ARGS...) MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
-        #define LogSPS(ARGS...)       MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
-        #define LogInfo(ARGS...)      MDNS_LOG_DEFINITION(MDNS_LOG_DEFAULT,  ARGS)
-        #define LogDebug(ARGS...)     MDNS_LOG_DEFINITION(MDNS_LOG_DEBUG, ARGS)
-    #else
-        #error "Unknown variadic macros"
-    #endif
-#else
-// If your platform does not support variadic macros, you need to define the following variadic functions.
-// See mDNSShared/mDNSDebug.c for sample implementation
-    #define debug_noop 1 ? (void)0 : (void)
-    #define LogMsg LogMsg_
-    #define LogOperation (mDNS_LoggingEnabled == 0) ? ((void)0) : LogOperation_
-    #define LogSPS       (mDNS_LoggingEnabled == 0) ? ((void)0) : LogSPS_
-    #define LogInfo      (mDNS_LoggingEnabled == 0) ? ((void)0) : LogInfo_
-    #define LogDebug     (mDNS_LoggingEnabled == 0) ? ((void)0) : LogDebug_
-extern void LogMsg_(const char *format, ...)       IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void LogOperation_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void LogSPS_(const char *format, ...)       IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void LogInfo_(const char *format, ...)      IS_A_PRINTF_STYLE_FUNCTION(1,2);
-extern void LogDebug_(const char *format, ...)     IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#endif
-
-
-#if MDNS_DEBUGMSGS
-#define debugf debugf_
-extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else
-#define debugf debug_noop
-#endif
-
-#if MDNS_DEBUGMSGS > 1
-#define verbosedebugf verbosedebugf_
-extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else
-#define verbosedebugf debug_noop
-#endif
-
-extern int mDNS_LoggingEnabled;
-extern int mDNS_PacketLoggingEnabled;
-extern int mDNS_McastLoggingEnabled;
-extern int mDNS_McastTracingEnabled;
-extern int mDNS_DebugMode;          // If non-zero, LogMsg() writes to stderr instead of syslog
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-extern int gNumOfPrivateLogRedactionEnabledQueries;
-extern int gPrivateLogRedactionEnabled; // If true, LogRedact() will redact all private level logs. The content of state
-                                        // dump that is related to user's privacy will also be redacted.
-#endif
-
-extern const char ProgramName[];
-
-extern void LogMsgWithLevel(mDNSLogCategory_t category, mDNSLogLevel_t level, const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
-// LogMsgNoIdent needs to be fixed so that it logs without the ident prefix like it used to
-// (or completely overhauled to use the new "log to a separate file" facility)
-#define LogMsgNoIdent LogMsg
-
-#define LogFatalError LogMsg
-
-#if MDNS_MALLOC_DEBUGGING >= 1
-extern void *mallocL(const char *msg, mDNSu32 size);
-extern void *callocL(const char *msg, mDNSu32 size);
-extern void freeL(const char *msg, void *x);
-#define LogMemCorruption LogMsg
-#else
-#define mallocL(MSG, SIZE) mdns_malloc(SIZE)
-#define callocL(MSG, SIZE) mdns_calloc(1, SIZE)
-#define freeL(MSG, PTR) mdns_free(PTR)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-
-/** @brief Write a log message to system's log storage(memory or disk).
- *
- *  On Apple platform, os_log() will be called to log a message.
- *
- *  @param CATEGORY         A custom log object previously created by the os_log_create function, and such an object is
- *                          used to specify "subsystem" and "category". For mDNSResponder, the subsystem should always
- *                          be set to "com.apple.mDNSResponder"; and the category is used for categorization and
- *                          filtering of related log messages within the subsystem’s settings. We have 4 categories that
- *                          are pre-defined: MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_CATEGORY_UDNS,
- *                          MDNS_LOG_CATEGORY_SPS. If these categories are not enough, use os_log_create to create more.
- *
- *  @param LEVEL            The log level that determines the importance of the message. The levels are, in order of
- *                          decreasing importance:
- *                              MDNS_LOG_FAULT      Fault-level messages are intended for capturing system-level errors
- *                                                  that are critical to the system. They are always saved in the data store.
- *                              MDNS_LOG_ERROR      Error-level messages are intended for reporting process-level errors
- *                                                  that are unexpected and incorrect during the normal operation. They
- *                                                  are always saved in the data store.
- *                              MDNS_LOG_WARNING    Warning-level messages are intended for capturing unexpected and
- *                                                  possible incorrect behavior that might be used later to root cause
- *                                                  an error or fault. They are are initially stored in memory buffers
- *                                                  and then moved to a data store.
- *                              MDNS_LOG_DEFAULT    Default-level messages are intended for reporting things that might
- *                                                  result a failure. They are are initially stored in memory buffers
- *                                                  and then moved to a data store.
- *                              MDNS_LOG_INFO       Info-level messages are intended for capturing information that may
- *                                                  be helpful, but isn’t essential, for troubleshooting errors. They
- *                                                  are initially stored in memory buffers, but will only be moved into
- *                                                  data store when faults and, optionally, errors occur.
- *                              MDNS_LOG_DEBUG      Debug-level messages are intended for information that may be useful
- *                                                  during development or while troubleshooting a specific problem, Debug
- *                                                  logging should not be used in shipping software. They are only
- *                                                  captured in memory when debug logging is enabled through a
- *                                                  configuration change.
- *
- *  @param FORMAT           A constant string or format string that produces a human-readable log message. The format
- *                          string follows the IEEE printf specification, besides the following customized format specifiers:
- *                              %{mdnsresponder:domain_name}.*P     the pointer to a DNS lable sequence
- *                              %{mdnsresponder:ip_addr}.20P        the pointer to a mDNSAddr variable
- *                              %{network:in_addr}.4P               the pointer to a mDNSv4Addr variable
- *                              %{network:in6_addr}.16P             the pointer to a mDNSv6Addr variable
- *                              %{mdnsresponder:mac_addr}.6P        the pointer to a 6-byte-length MAC address
- *
- *  @param ...              The parameter list that will be formated by the format string. Note that if the customized
- *                          format specifiers are used and the data length is not specified in the format string, the
- *                          size should be listed before the pointer to the data, for example:
- *                              "%{mdnsresponder:domain_name}.*P", (name ? (int)DomainNameLength((const domainname *)name) : 0), <the pointer to a DNS label sequence>
- *
- */
-    #define JOIN(X, Y) JOIN_AGAIN(X, Y)
-    #define JOIN_AGAIN(X, Y) X ## Y
-
-    #define LogRedact(CATEGORY, LEVEL, FORMAT, ...)                                         \
-        do                                                                                  \
-        {                                                                                   \
-            if (!gPrivateLogRedactionEnabled)                                               \
-            {                                                                               \
-                os_log_with_type(CATEGORY, LEVEL, FORMAT, ## __VA_ARGS__);                  \
-            }                                                                               \
-            else                                                                            \
-            {                                                                               \
-                os_log_with_type(JOIN(CATEGORY, _redacted), LEVEL, FORMAT, ## __VA_ARGS__); \
-            }                                                                               \
-        } while(0)
-#else
-    #if (MDNS_HAS_VA_ARG_MACROS)
-        #if (MDNS_C99_VA_ARGS)
-            #define LogRedact(CATEGORY, LEVEL, ...) \
-                do { if (mDNS_LoggingEnabled) LogMsgWithLevel(CATEGORY, LEVEL, __VA_ARGS__); } while (0)
-        #elif (MDNS_GNU_VA_ARGS)
-            #define LogRedact(CATEGORY, LEVEL, ARGS...) \
-                do { if (mDNS_LoggingEnabled) LogMsgWithLevel(CATEGORY, LEVEL, ARGS); } while (0)
-        #else
-            #error "Unknown variadic macros"
-        #endif
-    #else
-        #define LogRedact      (mDNS_LoggingEnabled == 0) ? ((void)0) : LogRedact_
-        extern void LogRedact_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-    #endif
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-
-// The followings are the customized log specifier defined in os_log. For compatibility, we have to define it when it is
-// not on the Apple platform, for example, the Posix platform. The keyword "public" or "private" is used to control whether
-// the content would be redacted when the redaction is turned on: "public" means the content will always be printed;
-// "private" means the content will be printed as <mask.hash: '<The hashed string from binary data>'> if the redaction is turned on,
-// only when the redaction is turned off, the content will be printed as what it should be. Note that the hash performed
-// to the data is a salted hashing transformation, and the salt is generated randomly on a per-process basis, meaning
-// that hashes cannot be correlated across processes or devices.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_S "%{public}s"
-    #define PRI_S "%{sensitive, mask.hash}s"
-#else
-    #define PUB_S "%s"
-    #define PRI_S PUB_S
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_BOOL                    "%{BOOL}d"
-    #define BOOL_PARAM(boolean_value)   (boolean_value)
-#else
-    #define PUB_BOOL                    PUB_S
-    #define BOOL_PARAM(boolean_value)   ((boolean_value) ? "YES" : "NO")
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_DNS_TYPE                "%{mdns:rrtype}d"
-    #define DNS_TYPE_PARAM(type_value)  (type_value)
-#else
-    #define PUB_DNS_TYPE                PUB_S
-    #define DNS_TYPE_PARAM(type_value)  (DNSTypeName(type_value))
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_ADD_RMV                     "%{mdns:addrmv}d"
-    #define ADD_RMV_PARAM(add_rmv_value)    (add_rmv_value)
-#else
-    #define PUB_ADD_RMV                     PUB_S
-    #define ADD_RMV_PARAM(add_rmv_value)    ((add_rmv_value) ? "add" : "rmv")
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_PN                      "%{mdns:pos/neg}d"
-    #define PN_PARAM(pn_boolean_value)  (pn_boolean_value)
-#else
-    #define PUB_PN                      PUB_S
-    #define PN_PARAM(pn_boolean_value)  ((pn_boolean_value) ? "positive" : "negative")
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_MORTALITY                       "%{mdns:mortality}d"
-    #define MORTALITY_PARAM(mortality_value)    (mortality_value)
-#else
-    #define PUB_MORTALITY                       PUB_S
-    #define MORTALITY_PARAM(mortality_value)    (MortalityDisplayString(mortality_value))
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_DM_NAME "%{public, mdnsresponder:domain_name}.*P"
-    #define PRI_DM_NAME "%{sensitive, mask.hash, mdnsresponder:domain_name}.*P"
-    // When DM_NAME_PARAM is used, the file where the function is defined must include DNSEmbeddedAPI.h
-    #define DM_NAME_PARAM(name) ((name) ? ((int)DomainNameLength((name))) : 0), (name)
-#else
-    #define PUB_DM_NAME "%##s"
-    #define PRI_DM_NAME PUB_DM_NAME
-    #define DM_NAME_PARAM(name) (name)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_DM_LABEL "%{public, mdnsresponder:domain_label}.*P"
-    #define PRI_DM_LABEL "%{sensitive, mask.hash, mdnsresponder:domain_label}.*P"
-    #define DM_LABEL_PARAM(label) 1 + ((label)->c[0]), ((label)->c)
-#else
-    #define PUB_DM_LABEL "%#s"
-    #define PRI_DM_LABEL PUB_DM_LABEL
-    #define DM_LABEL_PARAM(label) (label)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_IP_ADDR "%{public, mdnsresponder:ip_addr}.20P"
-    #define PRI_IP_ADDR "%{sensitive, mask.hash, mdnsresponder:ip_addr}.20P"
-
-    #define PUB_IPv4_ADDR "%{public, network:in_addr}.4P"
-    #define PRI_IPv4_ADDR "%{sensitive, mask.hash, network:in_addr}.4P"
-
-    #define PUB_IPv6_ADDR "%{public, network:in6_addr}.16P"
-    #define PRI_IPv6_ADDR "%{sensitive, mask.hash, network:in6_addr}.16P"
-#else
-    #define PUB_IP_ADDR "%#a"
-    #define PRI_IP_ADDR PUB_IP_ADDR
-
-    #define PUB_IPv4_ADDR "%.4a"
-    #define PRI_IPv4_ADDR PUB_IPv4_ADDR
-
-    #define PUB_IPv6_ADDR "%.16a"
-    #define PRI_IPv6_ADDR PUB_IPv6_ADDR
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_MAC_ADDR "%{public, mdnsresponder:mac_addr}.6P"
-    #define PRI_MAC_ADDR "%{sensitive, mask.hash, mdnsresponder:mac_addr}.6P"
-#else
-    #define PUB_MAC_ADDR "%.6a"
-    #define PRI_MAC_ADDR PUB_MAC_ADDR
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_HEX "%{public, mdnsresponder:hex_sequence}.*P"
-    #define PRI_HEX "%{sensitive, mask.hash, mdnsresponder:hex_sequence}.*P"
-    #define HEX_PARAM(hex, hex_length) (int)(hex_length), (hex)
-#else
-    #define PUB_HEX "%p"
-    #define PRI_HEX PUB_HEX
-    #define HEX_PARAM(hex, hex_length) (hex)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_DNSKEY "%{public, mdns:rd.dnskey}.*P"
-    #define PRI_DNSKEY "%{sensitive, mask.hash, mdns:rd.dnskey}.*P"
-    #define DNSKEY_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_DNSKEY "%p"
-    #define PRI_DNSKEY PUB_DNSKEY
-    #define DNSKEY_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_DS "%{public, mdns:rd.ds}.*P"
-    #define PRI_DS "%{sensitive, mask.hash, mdns:rd.ds}.*P"
-    #define DS_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_DS "%p"
-    #define PRI_DS PUB_DS
-    #define DS_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_NSEC "%{public, mdns:rd.nsec}.*P"
-    #define PRI_NSEC "%{sensitive, mask.hash, mdns:rd.nsec}.*P"
-    #define NSEC_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_NSEC "%p"
-    #define PRI_NSEC PUB_NSEC
-    #define NSEC_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_NSEC3 "%{public, mdns:rd.nsec3}.*P"
-    #define PRI_NSEC3 "%{sensitive, mask.hash, mdns:rd.nsec3}.*P"
-    #define NSEC3_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_NSEC3 "%p"
-    #define PRI_NSEC3 PUB_NSEC3
-    #define NSEC3_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_RRSIG "%{public, mdns:rd.rrsig}.*P"
-    #define PRI_RRSIG "%{sensitive, mask.hash, mdns:rd.rrsig}.*P"
-    #define RRSIG_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_RRSIG "%p"
-    #define PRI_RRSIG PUB_RRSIG
-    #define RRSIG_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    #define PUB_SVCB "%{public, mdns:rd.svcb}.*P"
-    #define PRI_SVCB "%{sensitive, mask.hash, mdns:rd.svcb}.*P"
-    #define SVCB_PARAM(rdata, rdata_length) (rdata_length), (rdata)
-#else
-    #define PUB_SVCB "%p"
-    #define PRI_SVCB PUB_SVCB
-    #define SVCB_PARAM(rdata, rdata_length) (rdata)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-        #define PUB_DNSSEC_RESULT                           "%{public, mdns:dnssec_result}d"
-        #define DNSSEC_RESULT_PARAM(dnssec_result_value)    (dnssec_result_value)
-    #else
-        #define PUB_DNSSEC_RESULT                           "%s"
-        #define DNSSEC_RESULT_PARAM(dnssec_result_value)    (dnssec_result_to_description(dnssec_result_value))
-    #endif
-#else
-        #define PUB_DNSSEC_RESULT                           "%s"
-        #define DNSSEC_RESULT_PARAM(dnssec_result_value)    ("<DNSSEC Unsupported>")
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-        #define PUB_DNSSEC_INVAL_STATE                  "%{public, mdns:dnssec_inval_state}d"
-        #define DNSSEC_INVAL_STATE_PARAM(state_value)   (state_value)
-    #else
-        #define PUB_DNSSEC_INVAL_STATE                  "%s"
-        #define DNSSEC_INVAL_STATE_PARAM(state_value)   (dnssec_insecure_validation_state_to_description(state_value))
-    #endif
-#else
-        #define PUB_DNSSEC_INVAL_STATE                  "%s"
-        #define DNSSEC_INVAL_STATE_PARAM(state_value)   ("<DNSSEC Unsupported>")
-#endif
-
-extern void LogToFD(int fd, const char *format, ...);
-
-#endif // __mDNSDebug_h
diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h
deleted file mode 100644
index ab82617..0000000
--- a/mDNSCore/mDNSEmbeddedAPI.h
+++ /dev/null
@@ -1,3699 +0,0 @@
-/*
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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 __mDNSEmbeddedAPI_h
-#define __mDNSEmbeddedAPI_h
-
-#ifdef __MINGW32__
-// MinGW defines "#define interface struct" for ObjC compatibility.
-#undef interface
-#endif
-
-#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 <inttypes.h>   // for uintptr_t and PRIXPTR
-
-
-#include "mDNSFeatures.h"
-#include "mDNSDebug.h"
-
-// ***************************************************************************
-// Feature removal compile options & limited resource targets
-
-// The following compile options are responsible for removing certain features from mDNSCore to reduce the
-// memory footprint for use in embedded systems with limited resources.
-
-// UNICAST_DISABLED - disables unicast DNS functionality, including Wide Area Bonjour
-// SPC_DISABLED - disables Bonjour Sleep Proxy client
-// IDLESLEEPCONTROL_DISABLED - disables sleep control for Bonjour Sleep Proxy clients
-
-// In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-#include <WebFilterDNS/WebFilterDNS.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec_obj_dns_question_member.h"
-#include "dnssec_obj_resource_record_member.h"
-#include "dnssec_obj_denial_of_existence.h"
-#include "dnssec_obj_trust_anchor_manager.h"
-#endif
-
-// Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes.
-
-#ifdef LIMITED_RESOURCES_TARGET
-// Don't support jumbo frames
-// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
-#define AbsoluteMaxDNSMessageData   1440
-// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
-#define MaximumRDSize               264
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include <mdns/private.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-#include "dnssd_private.h" // For dnssd_log_privacy_level_t.
-#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
-
-#ifndef fallthrough
- #if __clang__
-  #if __has_c_attribute(fallthrough)
-   #define fallthrough() [[fallthrough]]
-  #else
-   #define fallthrough()
-  #endif
- #elif __GNUC__
-  #define fallthrough() __attribute__((fallthrough))
- #else
-  #define fallthrough()
- #endif // __GNUC__
-#endif // fallthrough
-
-// ***************************************************************************
-#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_SVCB = 64,     // 64 Service Binding
-    kDNSType_HTTPS,         // 65 HTTPS Service Binding
-
-    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"
-    kDNSType_TSR = 65323    // Time since received, private for now, will update when allocated by IANA
-} 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 unsigned char mDNSBool;
-typedef   signed char mDNSs8;
-typedef unsigned char mDNSu8;
-typedef   signed short mDNSs16;
-typedef unsigned short mDNSu16;
-
-// Source: http://www.unix.org/version2/whatsnew/lp64_wp.html
-// http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_structure/Support_for_ILP64_Programming.htm
-// It can be safely assumed that int is 32bits on the platform
-#if defined(_ILP64) || defined(__ILP64__)
-typedef   signed int32 mDNSs32;
-typedef unsigned int32 mDNSu32;
-#else
-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 const struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
-
-// Use when printing interface IDs; the interface ID is actually a pointer, but we're only using
-// the pointer as a unique identifier, and in special cases it's actually a small number.   So there's
-// little point in printing all 64 bits--the upper 32 bits in particular will not add information.
-#define IIDPrintable(x) ((uint32_t)(uintptr_t)(x))
-
-// 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))))
-
-// Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits
-#define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-#define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-#define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-
-typedef enum
-{
-    mDNSAddrType_None    = 0,
-    mDNSAddrType_IPv4    = 4,
-    mDNSAddrType_IPv6    = 6,
-    mDNSAddrType_Unknown = ~0   // Special marker value used in known answer list recording
-} mDNSAddr_Type;
-
-typedef enum
-{
-    mDNSTransport_None = 0,
-    mDNSTransport_UDP  = 1,
-    mDNSTransport_TCP  = 2
-} mDNSTransport_Type;
-
-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 PCP, NAT-PMP or UPnP
-    mStatus_NATPortMappingDisabled    = -65565,     // NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator
-    mStatus_NoRouter                  = -65566,
-    mStatus_PollingMode               = -65567,
-    mStatus_Timeout                   = -65568,
-    mStatus_DefunctConnection         = -65569,
-    mStatus_PolicyDenied              = -65570,
-    // -65571 to -65785 currently unused; available for allocation
-
-    // udp connection status
-    mStatus_HostUnreachErr    = -65786,
-
-    // 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;
-
-#define MaxIp 5 // Needs to be consistent with MaxInputIf in dns_services.h
-
-typedef enum { q_stop = 0, q_start } q_state;
-typedef enum { reg_stop = 0, reg_start } reg_state;
-
-// 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
-
-// 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)
-#define mDNS_KeepaliveRecord(rr) ((rr)->rrtype == kDNSType_NULL && SameDomainLabel(SecondLabel((rr)->name)->c, (mDNSu8 *)"\x0A_keepalive"))
-
-// Number of times keepalives are sent if no ACK is received before waking up the system
-// this is analogous to net.inet.tcp.keepcnt
-#define kKeepaliveRetryCount    10
-// The frequency at which keepalives are retried if no ACK is received
-#define kKeepaliveRetryInterval 30
-
-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;
-typedef struct ResourceRecord_struct ResourceRecord;
-
-// 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 TCPListener_struct TCPListener;
-typedef struct TCPSocket_struct TCPSocket;
-typedef struct UDPSocket_struct UDPSocket;
-typedef struct TLSContext_struct TLSContext;
-typedef struct TLSServerContext_struct TLSServerContext;
-
-// ***************************************************************************
-#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
-#ifndef AbsoluteMaxDNSMessageData
-#define AbsoluteMaxDNSMessageData 8940
-#endif
-#define NormalMaxDNSMessageData 1440
-typedef struct
-{
-    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;
-    mDNSOpaque16 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 struct
-{
-    mDNSInterfaceID IntfId;
-    mDNSu32 seq;
-    mDNSu32 ack;
-    mDNSu16 window;
-} mDNSTCPInfo;
-
-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 struct
-{
-    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
-
-typedef struct
-{
-    mDNSAddr    ipaddr;
-    char        ethaddr[18];
-} IPAddressMACMapping;
-
-#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
-
-typedef 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
-} kDNSRecordTypes;
-
-typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
-typedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
-typedef       struct { 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;
-
-typedef enum
-{
-    platform_OSX = 1,   // OSX Platform
-    platform_iOS,       // iOS Platform
-    platform_Atv,       // Atv Platform
-    platform_NonApple   // Non-Apple (Windows, POSIX) Platform
-} Platform_t;
-
-// 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
-#define kDNSOpt_Trace 65001  // 65001-65534 Reserved for Local/Experimental Use
-
-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;
-
-typedef struct
-{
-    mDNSu8    platf;      // Running platform (see enum Platform_t)
-    mDNSu32   mDNSv;      // mDNSResponder Version (DNS_SD_H defined in dns_sd.h)
-} TracerOptData;
-
-// Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
-typedef struct
-{
-    mDNSu16 opt;
-    mDNSu16 optlen;
-    union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; TracerOptData tracer; } 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  bytes (opt 2, len 2, owner 8-20)
-// Trace rdata     9  bytes (opt 2, len 2, platf 1, mDNSv 4)
-
-
-#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 DNSOpt_TraceData_Space             (4 + 1 + 4)
-
-#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_Trace ? DNSOpt_TraceData_Space :        \
-        (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
-
-// NSEC record is defined in RFC 4034.
-// 16 bit RRTYPE space is split into 256 windows and each window has 256 bits (32 bytes).
-// If we create a structure for NSEC, it's size would be:
-//
-//   256 bytes domainname 'nextname'
-// + 256 * 34 = 8704 bytes of bitmap data
-// = 8960 bytes total
-//
-// This would be a waste, as types about 256 are not very common. But it would be odd, if we receive
-// a type above 256 (.US zone had TYPE65534 when this code was written) and not able to handle it.
-// Hence, we handle any size by not fixing a strucure in place. The following is just a placeholder
-// and never used anywhere.
-//
-#define NSEC_MCAST_WINDOW_SIZE 32
-typedef struct
-{
-    domainname *next; //placeholders are uncommented because C89 in Windows requires that a struct has at least a member.
-    char 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
-#ifndef MaximumRDSize
-#define MaximumRDSize 8192
-#endif
-
-// 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
-
-// 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;
-    mDNSs32 tsr_value;      // For TSR record
-    rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
-} 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;
-    mDNSs32 tsr_value;      // For TSR record
-    rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
-} 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 struct // packedstruct unnecessary
-{
-    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;
-
-// PCP Support for IPv4 mappings
-
-#define PCP_VERS 0x02
-#define PCP_WAITSECS_AFTER_EPOCH_INVALID 5
-
-typedef enum
-{
-    PCPOp_Announce = 0,
-    PCPOp_Map      = 1
-} PCPOp_t;
-
-typedef enum
-{
-    PCPProto_All = 0,
-    PCPProto_TCP = 6,
-    PCPProto_UDP = 17
-} PCPProto_t;
-
-typedef enum
-{
-    PCPResult_Success         = 0,
-    PCPResult_UnsuppVersion   = 1,
-    PCPResult_NotAuthorized   = 2,
-    PCPResult_MalformedReq    = 3,
-    PCPResult_UnsuppOpcode    = 4,
-    PCPResult_UnsuppOption    = 5,
-    PCPResult_MalformedOption = 6,
-    PCPResult_NetworkFailure  = 7,
-    PCPResult_NoResources     = 8,
-    PCPResult_UnsuppProtocol  = 9,
-    PCPResult_UserExQuota     = 10,
-    PCPResult_CantProvideExt  = 11,
-    PCPResult_AddrMismatch    = 12,
-    PCPResult_ExcesRemotePeer = 13
-} PCPResult_t;
-
-typedef struct
-{
-    mDNSu8       version;
-    mDNSu8       opCode;
-    mDNSOpaque16 reserved;
-    mDNSu32      lifetime;
-    mDNSv6Addr   clientAddr;
-    mDNSu32      nonce[3];
-    mDNSu8       protocol;
-    mDNSu8       reservedMapOp[3];
-    mDNSIPPort   intPort;
-    mDNSIPPort   extPort;
-    mDNSv6Addr   extAddress;
-} PCPMapRequest;
-
-typedef struct
-{
-    mDNSu8     version;
-    mDNSu8     opCode;
-    mDNSu8     reserved;
-    mDNSu8     result;
-    mDNSu32    lifetime;
-    mDNSu32    epoch;
-    mDNSu32    clientAddrParts[3];
-    mDNSu32    nonce[3];
-    mDNSu8     protocol;
-    mDNSu8     reservedMapOp[3];
-    mDNSIPPort intPort;
-    mDNSIPPort extPort;
-    mDNSv6Addr extAddress;
-} PCPMapReply;
-
-// LNT Support
-
-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
-
-typedef enum
-{
-    NATTProtocolNone    = 0,
-    NATTProtocolNATPMP  = 1,
-    NATTProtocolUPNPIGD = 2,
-    NATTProtocolPCP     = 3,
-} NATTProtocol;
-
-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
-    NATTProtocol lastSuccessfulProtocol;            // To send correct deletion request & update non-PCP external address operations
-    mDNSBool sentNATPMP;                            // Whether we just sent a NAT-PMP packet, so we won't send another if
-                                                    //    we receive another NAT-PMP "Unsupported Version" packet
-
-#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 PCP, 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
-    mDNSv4Addr NewAddress;                          // May be updated with actual value assigned by gateway
-    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;
-};
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - DNSServer & McastResolver structures and constants
-#endif
-
-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;
-
-enum {
-    Mortality_Mortal      = 0,          // This cache record can expire and get purged
-    Mortality_Immortal    = 1,          // Allow this record to remain in the cache indefinitely
-    Mortality_Ghost       = 2           // An immortal record that has expired and can linger in the cache
-};
-typedef mDNSu8 MortalityState;
-
-// ScopeType values for DNSServer matching
-typedef enum
-{
-    kScopeNone         = 0,        // DNS server used by unscoped questions
-    kScopeInterfaceID  = 1,        // Scoped DNS server used only by scoped questions
-    kScopeServiceID    = 2         // Service specific DNS server used only by questions
-                                   // have a matching serviceID
-} ScopeType;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-typedef mDNSu32 DNSServerFlags;
-#define DNSServerFlag_Delete        (1U << 0)
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-#define DNSServerFlag_Unreachable   (1U << 1)
-#endif
-
-typedef struct DNSServer
-{
-    struct DNSServer *next;
-    mDNSInterfaceID interface;  // DNS requests should be sent on this interface
-    mDNSs32 serviceID;          // ServiceID from DNS configuration.
-    mDNSAddr addr;              // DNS server's IP address.
-    DNSServerFlags flags;       // Set when we're planning to delete this from the list.
-    mDNSs32 penaltyTime;        // amount of time this server is penalized
-    ScopeType scopeType;        // See the ScopeType enum above
-    mDNSu32 timeout;            // timeout value for questions
-    mDNSu32 resGroupID;         // ID of the resolver group that contains this DNSServer
-    mDNSIPPort port;            // DNS server's port number.
-    mDNSBool usableA;           // True if A query results are usable over the interface, i.e., interface has IPv4.
-    mDNSBool usableAAAA;        // True if AAAA query results are usable over the interface, i.e., interface has IPv6.
-    mDNSBool isCell;            // True if the interface to this server is cellular.
-    mDNSBool isExpensive;       // True if the interface to this server is expensive.
-    mDNSBool isConstrained;     // True if the interface to this server is constrained.
-    mDNSBool isCLAT46;          // True if the interface to this server supports CLAT46.
-    domainname domain;          // name->server matching for "split dns"
-} DNSServer;
-#endif
-
-struct ResourceRecord_struct
-{
-    mDNSu8 RecordType;                  // See kDNSRecordTypes enum.
-    mDNSu8 rcode;                       // If the record was received via DNS, specifies the RCODE of the response message.
-    MortalityState mortality;           // Mortality of this resource record (See MortalityState enum)
-    mDNSu16 rrtype;                     // See DNS_TypeValues enum.
-    mDNSu16 rrclass;                    // See DNS_ClassValues enum.
-    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)
-    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
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_dns_service_t dnsservice;
-    mdns_resolver_type_t protocol;
-#else
-    DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry; null for multicast
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    dnssec_obj_resource_record_member_t dnssec;     // DNSSEC-related information for the current RR.
-#endif
-};
-
-
-// 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;
-
-#define AUTH_GROUP_NAME_SIZE    128
-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;
-    mDNSu8 namestorage[AUTH_GROUP_NAME_SIZE];
-};
-
-#ifndef AUTH_HASH_SLOTS
-#define AUTH_HASH_SLOTS 499
-#endif
-#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.
-typedef enum
-{
-    AuthRecordAny,              // registered for *Any, NOT including P2P interfaces
-    AuthRecordAnyIncludeP2P,    // registered for *Any, including P2P interfaces
-    AuthRecordAnyIncludeAWDL,   // registered for *Any, including AWDL interface
-    AuthRecordAnyIncludeAWDLandP2P, // registered for *Any, including AWDL and P2P interfaces
-    AuthRecordLocalOnly,
-    AuthRecordP2P,              // discovered over D2D/P2P framework
-} AuthRecType;
-
-#define AuthRecordIncludesAWDL(AR) \
-    (((AR)->ARType == AuthRecordAnyIncludeAWDL) || ((AR)->ARType == AuthRecordAnyIncludeAWDLandP2P))
-
-typedef enum
-{
-    AuthFlagsWakeOnly = 0x1     // WakeOnly service
-} AuthRecordFlags;
-
-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 (now 44/64)
-
-    // 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
-    uintptr_t      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
-    mDNSu8 AuthFlags;
-
-    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 ?
-    mDNSs32 KATimeExpire;               // In platform time units: time to send keepalive packet for the proxy record
-
-    // Field Group 3: Transient state for Authoritative Records
-    mDNSs32 ProbingConflictCount;       // Number of conflicting records observed during probing.
-    mDNSs32 LastConflictPktNum;         // Number of the last received packet that caused a probing conflict.
-    mDNSu8 Acknowledged;                // Set if we've given the success callback to the client
-    mDNSu8 ProbeRestartCount;           // Number of times we have restarted probing
-    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 defined(MDNS_LOG_ANSWER_SUPPRESSION_TIMES) && 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
-    mDNSBool Tentative;                 // Set if there is more recent TSR value is in probe, records with Tentative set to true will be deregistered when announcement received and conflict happen
-    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
-    mDNSs32 TentativeSetTime;           // In platform time units
-
-    // 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
-    mDNSOpaque64 updateIntID;   // Interface IDs (one bit per interface index)to which updates have been sent
-    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)->IsUnicastDotLocal || (Q)->ProxyQuestion || \
-                            ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
-
-// AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and
-// AuthRecordP2P records are created by D2DServiceFound events.  Both record types are kept on the same list.
-#define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
-
-// All other auth records, not including those defined as RRLocalOnly().
-#define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
-
-// 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;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-// This enum is used by state dump to determine whether the cache record should be redacted when printing the state.
-typedef enum
-{
-    // The state change flow:
-    // CRLogPrivacyLevel_Default -> CRLogPrivacyLevel_Private -> CRLogPrivacyLevel_Public
-    //            |                                                         ^
-    //            ----------------------------------------------------------|
-    CRLogPrivacyLevel_Default = 0,  // No state has been set, unredacted
-    CRLogPrivacyLevel_Private,      // Private state, redacted
-    CRLogPrivacyLevel_Public,       // Public state, unredacted
-} CRLogPrivacyLevel_t;
-
-#define PRIVATE_DOMAIN_NAME         ((const domainname *)"\x7" "private" "\x6" "domain" "\x4" "name" "\x7" "invalid")
-#define PRIVATE_RECORD_DESCRIPTION  "<private record description>"
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-
-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 (now 44/64)
-
-    // 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
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-    mDNSs32 LastCachedAnswerTime;       // Last time this record was used as an answer from the cache (before a query)
-                                        // In platform time units
-#else
-    // Extra four bytes here (on 64bit)
-#endif
-    DNSQuestion    *CRActiveQuestion;   // Points to an active question referencing this answer. Can never point to a NewQuestion.
-    mDNSs32 LastUnansweredTime;         // In platform time units; last time we incremented UnansweredQueries
-    mDNSu8  UnansweredQueries;          // Number of times we've issued a query for this record without getting an answer
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    mDNSBool DNSPushSubscribed;         // Indicate whether the cached record has an active DNS push subscription. If
-                                        // true, the record never expires.
-#endif
-
-    mDNSOpaque16 responseFlags;         // Second 16 bit in the DNS response
-    CacheRecord    *NextInCFList;       // Set if this is in the list of records we just received with the cache flush bit set
-    CacheRecord    *soa;                // SOA record to return for proxy questions
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    mDNSBool ineligibleForRecycling;    // If this cached record can be recycled when there is not enough cache space.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    mDNSu8 PrivacyLevel;                // The privacy level of the cache record, should be CRLogPrivacyLevel_t type, to
-                                        // save memory use mDNSu8 here.
-#endif
-
-    mDNSAddr sourceAddress;             // node from which we received this record
-    // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit)
-    RData_small smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
-};
-
-// Should match the CacheGroup_struct members, except namestorage[].  Only used to calculate
-// the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord)
-struct CacheGroup_base
-{
-    CacheGroup     *next;
-    mDNSu32         namehash;
-    CacheRecord    *members;
-    CacheRecord   **rrcache_tail;
-    domainname     *name;
-};
-
-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
-    mDNSu8 namestorage[sizeof(CacheRecord) - sizeof(struct CacheGroup_base)];  // match sizeof(CacheRecord)
-};
-
-// 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. e.g. TSR record
-    mDNSu32 NumSubTypes;
-    AuthRecord          *SubTypes;
-    mDNSu32             flags;      // saved for subsequent calls to mDNS_RegisterService() if records
-                                    // need to be re-registered.
-    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
-{
-    mDNSInterfaceID InterfaceID;
-    mDNSs32 Time;
-    mDNSs32 Type;                           // v4 or v6?
-} DupSuppressInfo;
-
-typedef enum
-{
-    LLQ_Invalid = 0,
-    // This is the initial state.
-    LLQ_Init = 1,
-
-    // All of these states indicate that we are doing DNS Push, and haven't given up yet.
-	LLQ_DNSPush_ServerDiscovery = 100,
-	LLQ_DNSPush_Connecting      = 101,
-	LLQ_DNSPush_Established     = 102,
-
-    // All of these states indicate that we are doing LLQ and haven't given up yet.
-    LLQ_InitialRequest   = 200,
-    LLQ_SecondaryRequest = 201,
-    LLQ_Established      = 202,
-
-    // If we get here, it means DNS Push isn't available, so we're polling.
-    LLQ_Poll                    = 300
-} LLQ_State;
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-#define DNS_PUSH_IN_PROGRESS(STATE) ((STATE) == LLQ_DNSPush_ServerDiscovery || (STATE) == LLQ_DNSPush_Connecting \
-                                        || (STATE) == LLQ_DNSPush_Established)
-#endif
-
-// 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
-};
-
-typedef enum {
-    DNSPushServerDisconnected,
-	DNSPushServerConnectFailed,
-	DNSPushServerConnectionInProgress,
-	DNSPushServerConnected,
-	DNSPushServerSessionEstablished,
-	DNSPushServerNoDNSPush
-} DNSPushServer_ConnectState;
-
-enum {
-    AllowExpired_None = 0,                  // Don't allow expired answers or mark answers immortal (behave normally)
-    AllowExpired_MakeAnswersImmortal = 1,   // Any answers to this question get marked as immortal
-    AllowExpired_AllowExpiredAnswers = 2    // Allow already expired answers from the cache
-};
-typedef mDNSu8 AllowExpiredState;
-
-#define HMAC_LEN    64
-#define HMAC_IPAD   0x36
-#define HMAC_OPAD   0x5c
-#define MD5_LEN     16
-
-// Internal data structure to maintain authentication information
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-
-typedef enum {
-    kDNSDigest_HMACAlg_None = 0,
-    kDNSDigest_HMACAlg_MD5,
-    kDNSDigest_HMACAlg_SHA1,
-    kDNSDigest_HMACAlg_SHA224,
-    kDNSDigest_HMACAlg_SHA256,
-    kDNSDigest_HMACAlg_SHA384,
-    kDNSDigest_HMACAlg_SHA512,
-} DNSDigest_HMACAlgorithm;
-
-#define kDNSDigest_HMACMD5_OutputLengthInBytes      16
-#define kDNSDigest_HMACSHA1_OutputLengthInBytes     20
-#define kDNSDigest_HMACSHA224_OutputLengthInBytes   28
-#define kDNSDigest_HMACSHA256_OutputLengthInBytes   32
-#define kDNSDigest_HMACSHA384_OutputLengthInBytes   48
-#define kDNSDigest_HMACSHA512_OutputLengthInBytes   64
-
-#define kDNSDigest_HMACMD5_KeyLengthInBytes      kDNSDigest_HMACMD5_OutputLengthInBytes
-#define kDNSDigest_HMACSHA1_KeyLengthInBytes     kDNSDigest_HMACSHA1_OutputLengthInBytes
-#define kDNSDigest_HMACSHA224_KeyLengthInBytes   kDNSDigest_HMACSHA224_OutputLengthInBytes
-#define kDNSDigest_HMACSHA256_KeyLengthInBytes   kDNSDigest_HMACSHA256_OutputLengthInBytes
-#define kDNSDigest_HMACSHA384_KeyLengthInBytes   kDNSDigest_HMACSHA384_OutputLengthInBytes
-#define kDNSDigest_HMACSHA512_KeyLengthInBytes   kDNSDigest_HMACSHA512_OutputLengthInBytes
-
-#define DNSDigest_Base64EncodedSize(SIZE)       ((((SIZE) + 2) / 3) * 4)
-#define DNSDigest_Base64EncodedMaxSize(SIZE)    (DNSDigest_Base64EncodedSize(SIZE))
-
-#define kDNSDigest_HMACKeyLengthInBytesMAX                  kDNSDigest_HMACSHA512_KeyLengthInBytes
-#define kDNSDigest_HMACBase64EncodedKeyLengthInBytesMAX     (DNSDigest_Base64EncodedMaxSize(kDNSDigest_HMACKeyLengthInBytesMAX))
-#define kDNSDigest_HMACOutputLengthInBytesMAX               kDNSDigest_HMACSHA512_OutputLengthInBytes
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-
-typedef struct DomainAuthInfo
-{
-    struct DomainAuthInfo *next;
-    mDNSs32 deltime;                        // If we're planning to delete this DomainAuthInfo, the time we want it deleted
-    domainname domain;
-    domainname keyname;
-    domainname hostname;
-    mDNSIPPort port;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
-    DNSDigest_HMACAlgorithm algorithm;                  // The algorithm of the key.
-    mDNSu32 key_len;                                    // The actual length of the key data in bytes.
-    mDNSu8 key[kDNSDigest_HMACKeyLengthInBytesMAX];     // The "large enough" key data buffer.
-#else
-    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
-#endif
-} DomainAuthInfo;
-
-// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-// Note: Any value other than QC_rmv i.e., any non-zero value will result in kDNSServiceFlagsAdd to the application
-// layer. These values are used within mDNSResponder and not sent across to the application. QC_addnocache is for
-// delivering a response without adding to the cache. QC_forceresponse is superset of QC_addnocache where in
-// addition to not entering in the cache, it also forces the negative response through.
-typedef enum { QC_rmv = 0, QC_add, QC_addnocache, QC_forceresponse, QC_suppressed } QC_result;
-typedef void mDNSQuestionCallback (mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
-typedef void (*mDNSQuestionResetHandler)(DNSQuestion *question);
-typedef void AsyncDispatchFunc(mDNS *const m, void *context);
-extern void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func);
-
-#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)
-#define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
-extern mDNSs32 RRExpireTime(const CacheRecord *cr);
-#define MaxUnansweredQueries 4
-#define MaxTentativeSeconds  5
-
-// RFC 4122 defines it to be 16 bytes
-#define UUID_SIZE       16
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-typedef struct
-{
-    mDNSu32             querySendCount;         // Number of queries that have been sent to DNS servers so far.
-    mDNSs32             firstQueryTime;         // The time when the first query was sent to a DNS server.
-    mDNSBool            answered;               // Has this question been answered?
-}   uDNSMetrics;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-#include "DNS64State.h"
-#endif
-
-typedef struct mDNS_DNSPushServer DNSPushServer;
-typedef struct mDNS_DNSPushZone   DNSPushZone;
-
-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 BrowseThreshold;                // If we have received at least this number of answers,
-                                            // set the next question interval to MaxQuestionInterval
-    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
-    mDNSBool CachedAnswerNeedsUpdate;       // See SendQueries().  Set if we're sending this question
-                                            // because a cached answer needs to be refreshed.
-    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 Suppressed;                    // This query should be suppressed, i.e., not sent on the wire.
-    mDNSu8 LOAddressAnswers;                // Number of answers from the local only auth records that are
-                                            // answering A, AAAA, CNAME, or PTR (/etc/hosts)
-    mDNSu8 WakeOnResolveCount;              // Number of wakes that should be sent on resolve
-    mDNSBool InitialCacheMiss;              // True after the question cannot be answered from the cache
-    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 (Unicast)
-    UDPSocket            *LocalSocket;
-
-    // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields)
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_dns_service_t    dnsservice;       // The current DNS service.
-    mdns_dns_service_id_t lastDNSServiceID; // The ID of the previous DNS service before a CNAME restart.
-    mdns_querier_t        querier;          // The current querier.
-#else
-    DNSServer            *qDNSServer;       // Caching server for this query (in the absence of an SRV saying otherwise)
-    mDNSOpaque128 validDNSServers;          // Valid DNSServers for this question
-    mDNSu16 noServerResponse;               // At least one server did not respond.
-    mDNSBool triedAllServersOnce;           // True if all DNS servers have been tried once.
-    mDNSu8 unansweredQueries;               // The number of unanswered queries to this server
-#endif
-    AllowExpiredState allowExpired;         // Allow expired answers state (see enum AllowExpired_None, etc. above)
-
-    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
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSBool Restart;                       // This question should be restarted soon.
-#endif
-
-    // 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
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    // DNS Push fields. These fields are only meaningful when LongLived flag is set.
-    DNSPushZone   *dnsPushZone;             // The DNS push zone where the current question is if the
-                                            // kDNSServiceFlagsLongLivedQuery flag is set.
-    DNSPushServer *dnsPushServer;           // The DNS push server that is responsible for answering the current
-                                            // question if the kDNSServiceFlagsLongLivedQuery flag is set.
-#endif
-
-    mDNSOpaque64 id;
-
-    // DNS Proxy fields
-    mDNSOpaque16 responseFlags;             // Temporary place holder for the error we get back from the DNS server
-                                            // till we populate in the cache
-    mDNSBool     BlockedByPolicy;           // True if the question is blocked by policy rule evaluation.
-    mDNSs32      ServiceID;                 // Service identifier to match against the DNS server
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSu8       ResolverUUID[UUID_SIZE];   // Resolver UUID to match against the DNS server
-    mdns_dns_service_id_t CustomID;
-#endif
-
-    // 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
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-    mDNSAddr UnicastMDNSResolver;           // If a non-zero IP address, mDNS queries will be sent to this address via
-                                            // unicast instead of to an mDNS multicast address.
-#endif
-    mDNSu32  flags;                         // flags from original DNSService*() API request.
-    mDNSOpaque16 TargetQID;                 // DNS or mDNS message ID.
-    domainname qname;
-    domainname firstExpiredQname;           // first expired qname in request chain
-    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 TimeoutQuestion;               // Timeout this question if there is no reply in configured time
-    mDNSBool IsUnicastDotLocal;             // True if this is a dot-local query that should be answered via unicast DNS.
-    mDNSBool WakeOnResolve;                 // Send wakeup on resolve
-    mDNSBool UseBackgroundTraffic;          // Set by client to use background traffic class for request
-    mDNSBool AppendSearchDomains;           // Search domains can be appended for this query
-    mDNSBool ForcePathEval;                 // Perform a path evaluation even if kDNSServiceFlagsPathEvaluationDone is set.
-    mDNSBool IsFailover;                    // True if the client requested to skip resolvers that allow failover.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSBool RequireEncryption;             // Set by client to require encrypted queries
-    mDNSBool NeedUpdatedQuerier;            // True if new querier is needed for DNSQuestion's updated qname/qtype/qclass.
-    mDNSBool UsedAsFailFastProbe;           // True if used as a probe for fail-fast service with connection problems.
-    mDNSBool ProhibitEncryptedDNS;          // True if use of encrypted DNS protocols is prohibited.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    mDNSBool inAppBrowserRequest;           // Is request associated with an in-app-browser
-    audit_token_t  peerAuditToken;          // audit token of the peer requesting the question
-    audit_token_t  delegateAuditToken;      // audit token of the delegated client the question is for
-#endif
-    mDNSu8 ProxyQuestion;                   // Proxy Question
-    mDNSs32 pid;                            // Process ID of the client that is requesting the question
-    mDNSu8  uuid[UUID_SIZE];                // Unique ID of the client that is requesting the question (valid only if pid is zero)
-    mDNSu32 euid;                           // Effective User Id of the client that is requesting the question
-    mDNSu32 request_id;                     // The ID of request that generates the current question
-    mDNSQuestionCallback *QuestionCallback;
-    mDNSQuestionResetHandler ResetHandler;
-    void                 *QuestionContext;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    uDNSMetrics metrics;                    // Data used for collecting unicast DNS query metrics.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-    DNS64 dns64;                            // DNS64 state for performing IPv6 address synthesis on networks with NAT64.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    mDNSBool enableDNSSEC;                      // The boolean value controlling whether to enable DNSSEC for this question.
-    dnssec_obj_dns_question_member_t dnssec;    // DNSSEC-related information for the current question.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    dnssd_log_privacy_level_t logPrivacyLevel; // The log privacy level that the client wishes to have when the question
-                                               // is started.
-#endif
-};
-
-typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } 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 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
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    AuthRecord RR_AddrRand;             // For non-AWDL interfaces, this is the A or AAAA record of the randomized hostname.
-#endif
-
-    // 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
-    mDNSu8 IgnoreIPv4LL;                // Set if IPv4 Link-Local addresses have to be ignored.
-    mDNSu8 SendGoodbyes;                // Send goodbyes on this interface while sleeping
-    mDNSBool DirectLink;                // a direct link, indicating we can skip the probe for
-                                        // address records
-    mDNSBool SupportsUnicastMDNSResponse;  // Indicates that the interface supports unicast responses
-                                        // to Bonjour queries.  Generally true for an interface.
-    mDNSBool MustNotPreventSleep;       // Set if this interface must not ever prevent sleep.
-};
-
-#define SLE_DELETE                      0x00000001
-#define SLE_WAB_BROWSE_QUERY_STARTED    0x00000002
-#define SLE_WAB_LBROWSE_QUERY_STARTED   0x00000004
-#define SLE_WAB_REG_QUERY_STARTED       0x00000008
-
-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;
-
-typedef enum
-{
-    mDNS_DomainTypeBrowse              = 0,
-    mDNS_DomainTypeBrowseDefault       = 1,
-    mDNS_DomainTypeBrowseAutomatic     = 2,
-    mDNS_DomainTypeRegistration        = 3,
-    mDNS_DomainTypeRegistrationDefault = 4,
-
-    mDNS_DomainTypeMax      = 4,
-    mDNS_DomainTypeMaxCount = 5
-} mDNS_DomainType;
-
-typedef struct EnumeratedDomainList
-{
-    domainname name;
-    struct EnumeratedDomainList *next;
-} EnumeratedDomainList;
-
-typedef enum {
-    DomainEnumerationState_Stopped,         // Domain enumeration is inactive.
-    DomainEnumerationState_Started,         // Domain enumeration is active.
-    DomainEnumerationState_StopInProgress,  // Domain enumeration is active but will become inactive later.
-} DomainEnumerationState;
-
-typedef struct DomainEnumerationWithType DomainEnumerationWithType;
-struct DomainEnumerationWithType
-{
-    EnumeratedDomainList    *domainList;        // Domain discovered through the domain enumeration.
-    DNSQuestion             question;           // The DNS question that is used to do the domain enumeration.
-    DomainEnumerationState  state;              // The state of the domain enumeration operation.
-    mDNSu32                 activeClientCount;  // The number of active clients that need the domain enumeration.
-    mDNSs32                 nextStopTime;       // If the operation state is DomainEnumerationState_StopInProgress, it indicates when the operation will be stopped.
-};
-
-typedef struct DomainEnumerationOp DomainEnumerationOp;
-struct DomainEnumerationOp
-{
-    domainname                  name;                                   // The name of the domain that does domain enumeration.
-    DomainEnumerationWithType   *enumerations[mDNS_DomainTypeMaxCount]; // The specific domain enumeration for different types.
-    DomainEnumerationOp         *next;                                  // The next domain in the list to do enumeration.
-};
-
-// 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);
-
-#ifndef CACHE_HASH_SLOTS
-#define CACHE_HASH_SLOTS 499
-#endif
-
-enum
-{
-    SleepState_Awake = 0,
-    SleepState_Transferring = 1,
-    SleepState_Sleeping = 2
-};
-
-typedef struct
-{
-    mDNSu32 NameConflicts;                  // Normal Name conflicts
-    mDNSu32 KnownUniqueNameConflicts;       // Name Conflicts for KnownUnique Records
-    mDNSu32 DupQuerySuppressions;           // Duplicate query suppressions
-    mDNSu32 KnownAnswerSuppressions;        // Known Answer suppressions
-    mDNSu32 KnownAnswerMultiplePkts;        // Known Answer in queries spannign multiple packets
-    mDNSu32 PoofCacheDeletions;             // Number of times the cache was deleted due to POOF
-    mDNSu32 UnicastBitInQueries;            // Queries with QU bit set
-    mDNSu32 NormalQueries;                  // Queries with QU bit not set
-    mDNSu32 MatchingAnswersForQueries;      // Queries for which we had a response
-    mDNSu32 UnicastResponses;               // Unicast responses to queries
-    mDNSu32 MulticastResponses;             // Multicast responses to queries
-    mDNSu32 UnicastDemotedToMulticast;      // Number of times unicast demoted to multicast
-    mDNSu32 Sleeps;                         // Total sleeps
-    mDNSu32 Wakes;                          // Total wakes
-    mDNSu32 InterfaceUp;                    // Total Interface UP events
-    mDNSu32 InterfaceUpFlap;                // Total Interface UP events with flaps
-    mDNSu32 InterfaceDown;                  // Total Interface Down events
-    mDNSu32 InterfaceDownFlap;              // Total Interface Down events with flaps
-    mDNSu32 CacheRefreshQueries;            // Number of queries that we sent for refreshing cache
-    mDNSu32 CacheRefreshed;                 // Number of times the cache was refreshed due to a response
-    mDNSu32 WakeOnResolves;                 // Number of times we did a wake on resolve
-} mDNSStatistics;
-
-extern void LogMDNSStatisticsToFD(int fd, mDNS *const m);
-
-// Time constant (~= 260 hours ~= 10 days and 21 hours) used to set
-// various time values to a point well into the future.
-#define FutureTime   0x38000000
-
-// Seven days in seconds, used to limit the time since received in TSR record.
-#define MaxTimeSinceReceived   (7*86400)
-
-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
-    mDNSs32 NetworkChanged;
-    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;
-
-    // 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 SuppressQueries;            // Don't send local-link mDNS queries during this time
-    mDNSs32 SuppressResponses;          // Don't send local-link mDNS responses 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 NextScheduledKA;            // Next time to send Keepalive packets (SPS)
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    mDNSs32 NextBonjourDisableTime;     // Next time to leave multicast group if Bonjour on Demand is enabled
-    mDNSu8 BonjourEnabled;              // Non zero if Bonjour is currently enabled by the Bonjour on Demand logic
-#endif
-    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
-    mDNSs32 MPktNum;                    // Unique sequence number assigned to each received Multicast 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 TimeSlept;                  // Time we went to sleep.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    mDNSs32 NextUpdateDNSSECValidatedCache; // Next time to update the cache with DNSSEC-validated records.
-#endif
-
-    mDNSs32 UnicastPacketsSent;         // Number of unicast packets sent.
-    mDNSs32 MulticastPacketsSent;       // Number of multicast packets sent.
-    mDNSs32 RemoteSubnet;               // Multicast packets received from outside our subnet.
-
-    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
-
-    mDNSs32 NextBLEServiceTime;         // Next time to call the BLE discovery management layer.  Non zero when active.
-
-    // 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_totalused_unicast;  // Number of cache entries currently occupied by unicast
-    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."
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    domainname RandomizedHostname;      // Randomized hostname to use for services involving AWDL interfaces. This is to
-                                        // avoid using a hostname derived from the device's name, which may contain the
-                                        // owner's real name, (e.g., "Steve's iPhone" -> "Steves-iPhone.local"), which is a
-                                        // privacy concern.
-    mDNSu32 AutoTargetAWDLIncludedCount;// Number of registered AWDL-included auto-target records.
-    mDNSu32 AutoTargetAWDLOnlyCount;    // Number of registered AWDL-only auto-target records.
-#endif
-    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;
-    Platform_t mDNS_plat;               // Why is this here in the “only required for mDNS Responder” section? -- SC
-
-    // Unicast-specific data
-    mDNSs32 NextuDNSEvent;                  // uDNS next event
-    mDNSs32 NextSRVUpdate;                  // Time to perform delayed update
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer        *DNSServers;           // list of DNS servers
-#endif
-    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_Internal;    // The internal DNS question started to manage all automatic browse domain events from different sources.
-
-    DomainEnumerationOp *domainsToDoEnumeration; // The list of domain(s) that possibly need(s) to do the domain enumeration.
-
-    domainname StaticHostname;              // Current answer to reverse-map query
-    domainname FQDN;
-    HostnameInfo     *Hostnames;            // List of registered hostnames + hostname metadata
-
-    mDNSu32 WABBrowseQueriesCount;          // Number of WAB Browse domain enumeration queries (b, db) callers
-    mDNSu32 WABLBrowseQueriesCount;         // Number of legacy WAB Browse domain enumeration queries (lb) callers
-    mDNSu32 WABRegQueriesCount;             // Number of WAB Registration domain enumeration queries (r, dr) callers
-    mDNSu8 SearchDomainsHash[MD5_LEN];
-
-    // NAT-Traversal fields
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    NATTraversalInfo LLQNAT;                    // Single shared NAT Traversal to receive inbound LLQ notifications
-#endif
-    NATTraversalInfo *NATTraversals;
-    NATTraversalInfo *CurrentNATTraversal;
-    mDNSs32 retryIntervalGetAddr;               // delta between time sent and retry for NAT-PMP & UPnP/IGD external address request
-    mDNSs32 retryGetAddr;                       // absolute time when we retry for NAT-PMP & UPnP/IGD external address request
-    mDNSv4Addr ExtAddress;                      // the external address discovered via NAT-PMP or UPnP/IGD
-    mDNSu32 PCPNonce[3];                        // the nonce if using PCP
-
-    UDPSocket        *NATMcastRecvskt;          // For receiving PCP & NAT-PMP announcement 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
-    char             *UPnPRouterURL;            // router's URL string
-    mDNSBool UPnPWANPPPConnection;              // whether we're using WANIPConnection or WANPPPConnection
-    char             *UPnPSOAPURL;              // router's SOAP control URL string
-    char             *UPnPRouterAddressString;  // holds both the router's address and port
-    char             *UPnPSOAPAddressString;    // holds both address and port for SOAP messages
-
-    // DNS Push fields
-    DNSPushServer *DNSPushServers;
-    DNSPushZone   *DNSPushZones;
-
-    // Sleep Proxy client fields
-    AuthRecord *SPSRRSet;                       // To help the client keep track of the records registered with the sleep proxy
-
-    // 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 SPSFeatureFlags;                     // Features supported. Currently 1 = TCP KeepAlive supported.
-    mDNSu8 SPSState;                            // 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
-    mDNSInterfaceID SPSProxyListChanged;
-    UDPSocket        *SPSSocket;
-#ifndef SPC_DISABLED
-    ServiceRecordSet SPSRecords;
-#endif
-    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 MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-    WCFConnection    *WCF;
-#endif
-    int             notifyToken;
-    int             uds_listener_skt;           // Listening socket for incoming UDS clients. This should not be here -- it's private to uds_daemon.c and nothing to do with mDNSCore -- SC
-    mDNSu32         AutoTargetServices;         // # of services that have AutoTarget set
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    // Counters used in Bonjour on Demand logic.
-    mDNSu32         NumAllInterfaceRecords;     // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.)
-    mDNSu32         NumAllInterfaceQuestions;   // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately.
-#endif
-
-    mDNSStatistics   mDNSStats;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    dnssec_obj_trust_anchor_manager_t   DNSSECTrustAnchorManager;   // The trust anchor manager manages all the useful anchors for DNSSEC.
-#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
-
-#ifndef MaxMsg
-    #define MaxMsg 512
-#endif
-    char MsgBuffer[MaxMsg];                 // Temp storage used while building error log messages (keep at end of struct)
-};
-
-#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 mDNSInterfaceMark;             // Special value
-extern const mDNSInterfaceID mDNSInterface_P2P;             // Special value
-extern const mDNSInterfaceID uDNSInterfaceMark;             // Special value
-extern const mDNSInterfaceID mDNSInterface_BLE;             // Special value
-
-#define LocalOnlyOrP2PInterface(INTERFACE)  (((INTERFACE) == mDNSInterface_LocalOnly) || ((INTERFACE) == mDNSInterface_P2P) || ((INTERFACE) == mDNSInterface_BLE))
-
-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 mDNSOpaque16 SubscribeFlags;
-extern const mDNSOpaque16 UnSubscribeFlags;
-extern const mDNSOpaque16 uDNSSecQueryFlags;
-
-extern const mDNSOpaque64 zeroOpaque64;
-extern const mDNSOpaque128 zeroOpaque128;
-
-extern mDNSBool StrictUnicastOrdering;
-
-#define localdomain           (*(const domainname *)"\x5" "local")
-#define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
-#define LocalDeviceInfoName   (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp" "\x5" "local")
-#define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    #define THREAD_DOMAIN_NAME ((const domainname *) "\xA" "openthread" "\x6" "thread" "\x4" "home" "\x4" "arpa")
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-// ***************************************************************************
-#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)
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern int          CountOfUnicastDNSServers(mDNS *const m);
-#endif
-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
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSinline int CountOfUnicastDNSServers(mDNS *const m)
-{
-    int count = 0;
-    DNSServer *ptr = m->DNSServers;
-    while(ptr) { if(!(ptr->flags & DNSServerFlag_Delete)) count++; ptr = ptr->next; }
-    return (count);
-}
-#endif
-
-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);
-}
-
-mDNSinline mDNSu32 mDNSVal32(mDNSOpaque32 x)
-{
-    return((mDNSu32)((((mDNSu32)x.b[0]) << 24) | (((mDNSu32)x.b[1]) << 16) | (((mDNSu32)x.b[2]) << 8) | (mDNSu32)x.b[3]));
-}
-
-#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, 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_StartExit (mDNS *const m);
-extern void    mDNS_FinalExit (mDNS *const m);
-#define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
-#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_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval);
-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_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);
-
-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, RData *txtrdata, 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 flags);
-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_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, mDNSu32 flags);
-#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, mDNSu32 flags,
-                                mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
-                                mDNSQuestionCallback *Callback, void *Context);
-#define        mDNS_StopBrowse mDNS_StopQuery
-
-
-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
-#define        mDNS_StopGetDomains_Internal mDNS_StopQuery_internal
-extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
-#define        mDNS_StopAdvertiseDomains mDNS_Deregister
-
-// Function that is used to do domain enumeration.
-extern mStatus mDNS_StartDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type);
-extern mStatus mDNS_StopDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type);
-extern mStatus mDNS_AddDomainDiscoveredForDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type,
-                                                            const domainname *domainDiscovered);
-extern mStatus mDNS_RemoveDomainDiscoveredForDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type,
-                                                               const domainname *domainDiscovered);
-extern void FoundNonLocalOnlyAutomaticBrowseDomain(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result add_record);
-extern void DeregisterLocalOnlyDomainEnumPTR_Internal(mDNS *m, const domainname *d, int type, mDNSBool lockHeld);
-
-extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
-extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
-#endif
-extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern mDNSBool ShouldSuppressUnicastQuery(const DNSQuestion *q, mdns_dns_service_t dnsservice);
-extern mDNSBool LocalRecordRmvEventsForQuestion(mDNS *m, DNSQuestion *q);
-#endif
-
-// ***************************************************************************
-#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)
-#define AssignConstStringDomainName(DST, SRC) do { \
-    mDNSu16 len__ = DomainNameLengthLimit((domainname *)(SRC), (mDNSu8 *)(SRC) + sizeof (SRC)); \
-    if (len__ <= MAX_DOMAIN_NAME) \
-        mDNSPlatformMemCopy((DST)->c, (SRC), 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 SameDomainNameBytes(const mDNSu8 *d1, const mDNSu8 *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
-extern mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *r1, const AuthRecord *r2);
-
-#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 mDNSBool IsRootDomain(const domainname *d);
-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)
-extern mDNSu16 DomainNameBytesLength(const mDNSu8 *name, const mDNSu8 *limit);
-
-extern mDNSu8 DomainLabelLength(const domainlabel *const label);
-
-// 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);
-
-#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \
-                                    ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \
-                                    ((X)[4] | 0x20) == 'p')
-
-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) IS_A_PRINTF_STYLE_FUNCTION(3,0);
-extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
-extern void mDNS_snprintf_add(char **dst, const char *lim, 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 const char *mStatusDescription(mStatus error);
-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)
-#define MortalityDisplayString(M) (M == Mortality_Mortal ? "mortal" : (M == Mortality_Immortal ? "immortal" : "ghost"))
-extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
-extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
-extern mDNSBool mDNSv4AddrIsRFC1918(const mDNSv4Addr * const addr);  // returns true for RFC1918 private addresses
-#define mDNSAddrIsRFC1918(X) ((X)->type == mDNSAddrType_IPv4 && mDNSv4AddrIsRFC1918(&(X)->ip.v4))
-extern const char *DNSScopeToString(mDNSu32 scope);
-
-// For PCP
-extern void mDNSAddrMapIPv4toIPv6(mDNSv4Addr* in, mDNSv6Addr* out);
-extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
-
-#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 mDNSSameIPv6NetworkPart(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1])
-#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 mDNSOpaque128IsZero(A)   (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 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)
-
-#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))    )
-
-#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)
-
-
-// ***************************************************************************
-#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);
-
-extern void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks);
-
-// 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);
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr,
-                                    const mDNSIPPort port, ScopeType scopeType, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSBool isConstrained, mDNSBool isCLAT46,
-                                    mDNSu32 resGroupID, mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO);
-extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags);
-#endif
-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);
-
-static inline void SwapDNSHeaderBytes(DNSMessage *const msg)
-{
-    const mDNSu8 *const questions   = ((const mDNSu8 *)&(msg)->h.numQuestions);
-    const mDNSu8 *const answers     = ((const mDNSu8 *)&(msg)->h.numAnswers);
-    const mDNSu8 *const authorities = ((const mDNSu8 *)&(msg)->h.numAuthorities);
-    const mDNSu8 *const additionals = ((const mDNSu8 *)&(msg)->h.numAdditionals);
-
-    msg->h.numQuestions   = (mDNSu16) ((mDNSu16)questions[0]    << 8 | questions[1]);
-    msg->h.numAnswers     = (mDNSu16) ((mDNSu16)answers[0]      << 8 | answers[1]);
-    msg->h.numAuthorities = (mDNSu16) ((mDNSu16)authorities[0]  << 8 | authorities[1]);
-    msg->h.numAdditionals = (mDNSu16) ((mDNSu16)additionals[0]  << 8 | additionals[1]);
-}
-
-// 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(const DNSMessage *msg, const mDNSu8 *end, const LargeCacheRecord *tsig,
-    const DomainAuthInfo *info, mDNSu16 *rcode, mDNSu16 *tcode);
-
-#if defined(DEBUG) && DEBUG
-extern void DNSDigest_VerifyMessage_Verify(DNSMessage *msg, const mDNSu8 *end, const DomainAuthInfo *authInfo);
-#endif
-
-// ***************************************************************************
-#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
-
-#ifdef MDNS_MALLOC_DEBUGGING
-typedef void mDNSListValidationFunction(void *);
-typedef struct listValidator mDNSListValidator;
-struct listValidator {
-    struct listValidator *next;
-    const char *validationFunctionName;
-    mDNSListValidationFunction *validator;
-    void *context;
-};
-#endif // MDNS_MALLOC_DEBUGGING
-
-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, mDNSBool useBackgroundTrafficClass);
-
-extern void     mDNSPlatformLock        (const mDNS *const m);
-extern void     mDNSPlatformUnlock      (const mDNS *const m);
-
-extern void     mDNSPlatformStrLCopy    (      void *dst, const void *src, mDNSu32 len);
-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 int      mDNSPlatformMemCmp      (const void *dst, const void *src, mDNSu32 len);
-extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu32 len);
-extern void mDNSPlatformQsort       (void *base, int nel, int width, int (*compar)(const void *, const void *));
-#if MDNS_MALLOC_DEBUGGING
-#define         mDNSPlatformMemAllocate(X)      mallocL(# X, X)
-#define         mDNSPlatformMemAllocateClear(X)	callocL(# X, X)
-#define         mDNSPlatformMemFree(X)          freeL(# X, X)
-extern void     mDNSPlatformValidateLists (void);
-extern void     mDNSPlatformAddListValidator(mDNSListValidator *validator,
-                                             mDNSListValidationFunction *vf, const char *vfName, void *context);
-#else
-extern void *   mDNSPlatformMemAllocate(mDNSu32 len);
-extern void *   mDNSPlatformMemAllocateClear(mDNSu32 len);
-extern void     mDNSPlatformMemFree(void *mem);
-#endif // MDNS_MALLOC_DEBUGGING
-
-// 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);
-extern mDNSs32  mDNSPlatformContinuousTimeSeconds (void);
-
-// strlen("1900-01-01 00:00:00.000000-0000" + "\0") == 32;
-// bufferLen must be greater than MIN_TIMESTAMP_STRING_LENGTH to avoid the string truncation.
-#define MIN_TIMESTAMP_STRING_LENGTH 32
-extern void getLocalTimestampFromPlatformTime(mDNSs32 platformTimeNow, mDNSs32 platformTime,
-                                              char *outBuffer, mDNSu32 bufferLen);
-extern void getLocalTimestampNow(char *outBuffer, mDNSu32 bufferLen);
-
-#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);
-
-// 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),
-	kTCPSocketFlags_TLSValidationNotRequired = (1 << 1)
-} TCPSocketFlags;
-
-typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
-typedef void (*TCPAcceptedCallback)(TCPSocket *sock, mDNSAddr *addr, mDNSIPPort *port,
-									const char *remoteName, void *context);
-extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSAddr_Type addrtype, mDNSIPPort *port, domainname *hostname, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
-extern TCPListener *mDNSPlatformTCPListen(mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
-										  TCPSocketFlags socketFlags, mDNSBool reuseAddr, int queueLength,
-										  TCPAcceptedCallback callback, void *context); // Listen on a port
-extern mStatus mDNSPlatformTCPSocketSetCallback(TCPSocket *sock, TCPConnectionCallback callback, void *context);
-extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
-extern int        mDNSPlatformTCPGetFD(TCPSocket *sock);
-extern mDNSBool   mDNSPlatformTCPWritable(TCPSocket *sock);
-extern mStatus    mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport,
-                                         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(const mDNSIPPort requestedport);
-extern mDNSu16    mDNSPlatformGetUDPPort(UDPSocket *sock);
-extern void       mDNSPlatformUDPClose(UDPSocket *sock);
-extern mDNSBool   mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock);
-extern void       mDNSPlatformReceiveBPF_fd(int fd);
-extern void       mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
-extern void       mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win);
-extern mStatus    mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr,  mDNSIPPort *rport, mDNSTCPInfo *mti);
-extern mStatus    mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr);
-extern mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
-extern mStatus    mDNSPlatformClearSPSData(void);
-extern mStatus    mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length);
-
-// 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 mDNSBool   mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
-                                           DNameListElem **BrowseDomains, mDNSBool ackConfig);
-extern mStatus    mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
-extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
-
-extern void       mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason);
-extern void       mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason);
-extern void       mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
-
-extern mDNSBool   mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID);
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME) || MDNSRESPONDER_SUPPORTS(APPLE, AWDL_FAST_CACHE_FLUSH)
-extern mDNSBool   mDNSPlatformInterfaceIsAWDL(mDNSInterfaceID interfaceID);
-#endif
-extern mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool   mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID);
-extern mDNSBool   mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf);
-
-extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize);
-
-// Platform event API
-
-#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 *const n);
-extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *const 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);
-
-// Attributes that controls the Bonjour operation initiation and response speed for an interface.
-typedef enum
-{
-    FastActivation,     // For p2p* and DirectLink type interfaces
-    NormalActivation,   // For standard interface timing
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-    SlowActivation      // For flapping interfaces
-#endif
-} InterfaceActivationSpeed;
-
-extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
-extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
-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 *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern void     mDNSCoreReceiveForQuerier(mDNS *m, DNSMessage *msg, const mDNSu8 *end, mdns_querier_t querier, mdns_dns_service_t service);
-#endif
-extern CacheRecord *mDNSCheckCacheFlushRecords(mDNS *m, CacheRecord *CacheFlushRecords, mDNSBool id_is_zero, int numAnswers,
-											   DNSQuestion *unicastQuestion, CacheRecord *NSECCachePtr, CacheRecord *NSECRecords,
-											   mDNSu8 rcode);
-extern void     mDNSCoreRestartQueries(mDNS *const m);
-extern void     mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q);
-extern void     mDNSCoreRestartRegistration(mDNS *const m, AuthRecord  *rr, int announceCount);
-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);
-
-typedef enum
-{
-    mDNSNextWakeReason_Null                        = 0,
-    mDNSNextWakeReason_NATPortMappingRenewal       = 1,
-    mDNSNextWakeReason_RecordRegistrationRenewal   = 2,
-    mDNSNextWakeReason_UpkeepWake                  = 3,
-    mDNSNextWakeReason_DHCPLeaseRenewal            = 4,
-    mDNSNextWakeReason_SleepProxyRegistrationRetry = 5
-} mDNSNextWakeReason;
-
-extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now, mDNSNextWakeReason *outReason);
-
-extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
-
-extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
-
-typedef mDNSu32 CreateNewCacheEntryFlags;
-#define kCreateNewCacheEntryFlagsNone 0
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-#define kCreateNewCacheEntryFlagsDNSPushSubscribed (1U << 0)
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-// Set this flag if the record being created comes from a DNSSEC-aware response.
-#define kCreateNewCacheEntryFlagsDNSSECRRToValidate                 (1U << 1)
-#define kCreateNewCacheEntryFlagsDNSSECRRValidatedSecure            (1U << 2)
-#define kCreateNewCacheEntryFlagsDNSSECRRValidatedInsecure          (1U << 3)
-#define kCreateNewCacheEntryFlagsDNSSECInsecureValidationUsable     (1U << 4)
-#endif
-extern CacheRecord *CreateNewCacheEntryEx(mDNS *m, mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool add,
-                                          const mDNSAddr *sourceAddress, CreateNewCacheEntryFlags flags);
-extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress);
-extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name);
-extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r);
-extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
-extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr);
-extern void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl);
-extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
-extern void MakeNegativeCacheRecordForQuestion(mDNS *m, CacheRecord *cr, const DNSQuestion *q, mDNSu32 ttl,
-    mDNSInterfaceID InterfaceID, mDNSOpaque16 responseFlags);
-extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
-extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
-extern void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr);
-extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
-extern void CacheRecordSetResponseFlags(CacheRecord *const cr, const mDNSOpaque16 responseFlags);
-extern void mDNSCoreResetRecord(mDNS *const m);
-extern AuthRecord *mDNSGetTSRRecord(mDNS *m, const AuthRecord *rr);
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
-#endif
-extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-extern void mDNSCoreReceiveD2DResponse(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
-    const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
-    const mDNSInterfaceID InterfaceID);
-#endif
-extern void CheckSuppressUnusableQuestions(mDNS *const m);
-extern void RetrySearchDomainQuestions(mDNS *const m);
-extern mDNSBool DomainEnumQuery(const domainname *qname);
-extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr);
-extern void  UpdateKeepaliveRMACAsync(mDNS *const m, void *context);
-extern void UpdateRMAC(mDNS *const m, void *context);
-
-// 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 namehash, const domainname *const name);
-extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr);
-extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
-extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
-
-
-typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-    const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
-extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
-extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m);
-extern void mDNSPlatformDisposeProxyContext(void *context);
-extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit);
-
-extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q);
-extern mDNSs32 mDNSPlatformGetPID(void);
-extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr);
-extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-extern void GetRandomUUIDLabel(domainlabel *label);
-extern void GetRandomUUIDLocalHostname(domainname *hostname);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-extern void uDNSMetricsClear(uDNSMetrics *metrics);
-#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.FF Name
-//
-// Metrics:
-//
-// AA = Intent
-// BB = Portability
-// CC = Marginal Power
-// DD = Total Power
-// FF = Features Supported (Currently TCP Keepalive only)
-//
-//
-// ** 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;
-
-typedef enum
-{
-    mDNS_NoWake        = 0, // System does not support Wake on LAN
-    mDNS_WakeOnAC      = 1, // System supports Wake on LAN when connected to AC power only
-    mDNS_WakeOnBattery = 2  // System supports Wake on LAN on battery
-} mDNSWakeForNetworkAccess;
-
-extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features);
-#define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP,F)                       \
-    do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP),(F)); 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'))
-#define LocalSPSMetric(X) ( (X)->SPSType * 10000 + (X)->SPSPortability * 100 + (X)->SPSMarginalPower)
-#define SPSFeatures(X) ((X)[0] >= 13 && (X)[12] =='.' ? ((X)[13]-'0') : 0 )
-
-#define MD5_DIGEST_LENGTH   16          /* digest length in bytes */
-#define MD5_BLOCK_BYTES     64          /* block size in bytes */
-#define MD5_BLOCK_LONG       (MD5_BLOCK_BYTES / sizeof(mDNSu32))
-
-typedef struct MD5state_st
-{
-    mDNSu32 A,B,C,D;
-    mDNSu32 Nl,Nh;
-    mDNSu32 data[MD5_BLOCK_LONG];
-    mDNSu32 num;
-} MD5_CTX;
-
-extern int MD5_Init(MD5_CTX *c);
-extern int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
-extern int MD5_Final(unsigned char *md, MD5_CTX *c);
-
-// ***************************************************************************
-#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];
-	char assertN[(sizeof(rdataOPT)		   ==   24                         ) ? 1 : -1];
-	char assertP[(sizeof(PCPMapRequest)    ==   60                         ) ? 1 : -1];
-	char assertQ[(sizeof(PCPMapReply)      ==   60                         ) ? 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)       <=    72) ? 1 : -1];
-    char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1184) ? 1 : -1];
-    char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   232) ? 1 : -1];
-    char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   232) ? 1 : -1];
-    char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=  1160) ? 1 : -1];
-    char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  2048) ? 1 : -1];
-    char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   200) ? 1 : -1];
-    char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   328) ? 1 : -1];
-#endif
-    char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  8416) ? 1 : -1];
-    char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  4792) ? 1 : -1];
-    char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=   944) ? 1 : -1];
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    // structure size is assumed by LogRedact routine.
-    char sizecheck_mDNSAddr            [(sizeof(mDNSAddr)             ==    20) ? 1 : -1];
-    char sizecheck_mDNSv4Addr          [(sizeof(mDNSv4Addr)           ==     4) ? 1 : -1];
-    char sizecheck_mDNSv6Addr          [(sizeof(mDNSv6Addr)           ==    16) ? 1 : -1];
-#endif
-};
-
-// Routine to initialize device-info TXT record contents
-mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr);
-
-// ***************************************************************************
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/mDNSCore/mdns_strict.h b/mDNSCore/mdns_strict.h
deleted file mode 100644
index 433d17b..0000000
--- a/mDNSCore/mdns_strict.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __MDNS_STRICT_H__
-#define __MDNS_STRICT_H__
-
-#ifndef MDNS_NO_STRICT
-	#if !defined(__APPLE__)
-		#define MDNS_NO_STRICT				1
-	#else // !defined(__APPLE__)
-		#define MDNS_NO_STRICT				0
-	#endif // !defined(__APPLE__)
-#endif // MDNS_NO_STRICT
-
-	#define APPLE_OSX_mDNSResponder			0
-
-#ifndef DEBUG
-	#define DEBUG 							0
-#endif
-
-#ifndef _MDNS_STRICT_DISPOSE_TEMPLATE
-	#if MDNS_NO_STRICT
-		#define _MDNS_STRICT_DISPOSE_TEMPLATE(ptr, function) \
-			do {                                        \
-				if ((ptr) != NULL) {                    \
-					function(ptr);                      \
-					(ptr) = NULL;                       \
-				}                                       \
-			} while(0)
-	#else // MDNS_NO_STRICT
-		#define _MDNS_STRICT_DISPOSE_TEMPLATE _STRICT_DISPOSE_TEMPLATE
-	#endif // MDNS_NO_STRICT
-#endif // _MDNS_STRICT_DISPOSE_TEMPLATE
-
-#if !MDNS_NO_STRICT
-#include <CoreFoundation/CoreFoundation.h>
-#include <os/log.h>
-
-#include "../mDNSMacOSX/secure_coding/strict.h"
-
-#pragma mark -- Alloc --
-
-#define mdns_malloc strict_malloc
-#define MDNS_MALLOC_TYPE STRICT_MALLOC_TYPE
-#define mdns_calloc strict_calloc
-#define MDNS_CALLOC_TYPE STRICT_CALLOC_TYPE
-#define mdns_reallocf strict_reallocf
-#define MDNS_REALLOCF_TYPE STRICT_REALLOCF_TYPE
-#define mdns_memalign strict_memalign
-#define MDNS_ALLOC_ALIGN_TYPE STRICT_ALLOC_ALIGN_TYPE
-#define mdns_strdup strict_strdup
-#define mdns_strlcpy strict_strlcpy
-
-#pragma mark -- Dispose --
-
-#define MDNS_DISPOSE_XPC STRICT_DISPOSE_XPC
-#define MDNS_DISPOSE_XPC_PROPERTY(obj, prop) MDNS_DISPOSE_XPC(obj->prop)
-
-#define MDNS_DISPOSE_ALLOCATED STRICT_DISPOSE_ALLOCATED
-#define MDNS_DISPOSE_ALLOCATED_PROPERTY(obj, prop) MDNS_DISPOSE_ALLOCATED(obj->prop)
-#define mdns_free(ptr) MDNS_DISPOSE_ALLOCATED(ptr)
-
-#define MDNS_DISPOSE_DISPATCH STRICT_DISPOSE_DISPATCH
-#define MDNS_DISPOSE_DISPATCH_PROPERTY(obj, prop) MDNS_DISPOSE_DISPATCH(obj->prop)
-
-#define MDNS_RESET_BLOCK STRICT_RESET_BLOCK
-#define MDNS_RESET_BLOCK_PROPERTY(obj, prop, new_block) MDNS_RESET_BLOCK(obj->prop, new_block)
-
-#define MDNS_DISPOSE_BLOCK STRICT_DISPOSE_BLOCK
-#define MDNS_DISPOSE_BLOCK_PROPERTY(obj, prop) MDNS_DISPOSE_BLOCK(obj->prop)
-
-#define MDNS_DISPOSE_CF_OBJECT STRICT_DISPOSE_CF_OBJECT
-#define MDNS_DISPOSE_CF_PROPERTY(obj, prop) MDNS_DISPOSE_CF_OBJECT(obj->prop)
-
-#define MDNS_DISPOSE_ADDRINFO STRICT_DISPOSE_ADDRINFO
-
-#define MDNS_DISPOSE_NW(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, nw_release)
-
-#define MDNS_DISPOSE_SEC(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, sec_release)
-
-#define MDNS_DISPOSE_DNS_SERVICE_REF(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, DNSServiceRefDeallocate)
-
-#ifdef BlockForget
-// Redfine BlockForget to bypass poisoned Block_release
-#undef BlockForget
-#if( COMPILER_ARC )
-	#define	BlockForget( X )			do { *(X) = nil; } while( 0 )
-#else
-	#define	BlockForget( X )			ForgetCustom( X, _Block_release )
-#endif
-#endif
-
-#else  // !MDNS_NO_STRICT
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#define mdns_malloc 			malloc
-#define mdns_calloc 			calloc
-#define mdns_strdup 			strdup
-#define mdns_free(obj) \
-	_MDNS_STRICT_DISPOSE_TEMPLATE(obj, free)
-
-static
-inline __attribute__((always_inline))
-void _mdns_strict_strlcpy(char * const restrict dst, const char * const restrict src, const size_t dst_len)
-{
-	if (dst_len == 0) {
-		return;
-	}
-
-	char *d = dst;
-	const char *s = src;
-	for (size_t n = dst_len - 1; n > 0; n--) {
-		if ((*d++ = *s++) == '\0') {
-			return;
-		}
-	}
-	*d = '\0';
-}
-#define mdns_strlcpy			_mdns_strict_strlcpy
-
-
-#define MDNS_DISPOSE_DNS_SERVICE_REF(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, DNSServiceRefDeallocate)
-
-
-
-#endif // !MDNS_NO_STRICT
-
-#endif // __MDNS_STRICT_H__
diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c
deleted file mode 100644
index 5611517..0000000
--- a/mDNSCore/uDNS.c
+++ /dev/null
@@ -1,7382 +0,0 @@
-/*
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
-
- * To Do:
- * Elimate all mDNSPlatformMemAllocate/mDNSPlatformMemFree from this code -- the core code
- * is supposed to be malloc-free so that it runs in constant memory determined at compile-time.
- * Any dynamic run-time requirements should be handled by the platform layer below or client layer above
- */
-
-#include "uDNS.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-#include "SymptomReporter.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#include "mdns_strict.h"
-
-#if (defined(_MSC_VER))
-// 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
-
-// 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.
-mDNSexport SearchListElem *SearchList = mDNSNULL;
-
-// The value can be set to true by the Platform code e.g., MacOSX uses the plist mechanism
-mDNSBool StrictUnicastOrdering = mDNSfalse;
-
-extern mDNS mDNSStorage;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-// We keep track of the number of unicast DNS servers and log a message when we exceed 64.
-// Currently the unicast queries maintain a 128 bit map to track the valid DNS servers for that
-// question. Bit position is the index into the DNS server list. This is done so to try all
-// the servers exactly once before giving up. If we could allocate memory in the core, then
-// arbitrary limitation of 128 DNSServers can be removed.
-#define MAX_UNICAST_DNS_SERVERS 128
-#endif
-
-#define SetNextuDNSEvent(m, rr) { \
-        if ((m)->NextuDNSEvent - ((rr)->LastAPTime + (rr)->ThisAPInterval) >= 0)                                                                              \
-            (m)->NextuDNSEvent = ((rr)->LastAPTime + (rr)->ThisAPInterval);                                                                         \
-}
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    #define DNS_PUSH_SERVER_INVALID_SERIAL 0
-#endif
-
-#ifndef UNICAST_DISABLED
-
-// ***************************************************************************
-// MARK: - General Utility Functions
-
-// set retry timestamp for record with exponential backoff
-mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mDNSu32 random)
-{
-    rr->LastAPTime = m->timenow;
-
-    if (rr->expire && rr->refreshCount < MAX_UPDATE_REFRESH_COUNT)
-    {
-        mDNSs32 remaining = rr->expire - m->timenow;
-        rr->refreshCount++;
-        if (remaining > MIN_UPDATE_REFRESH_TIME)
-        {
-            // Refresh at 70% + random (currently it is 0 to 10%)
-            rr->ThisAPInterval =  7 * (remaining/10) + (random ? random : mDNSRandom(remaining/10));
-            // Don't update more often than 5 minutes
-            if (rr->ThisAPInterval < MIN_UPDATE_REFRESH_TIME)
-                rr->ThisAPInterval = MIN_UPDATE_REFRESH_TIME;
-            LogInfo("SetRecordRetry refresh in %d of %d for %s",
-                    rr->ThisAPInterval/mDNSPlatformOneSecond, (rr->expire - m->timenow)/mDNSPlatformOneSecond, ARDisplayString(m, rr));
-        }
-        else
-        {
-            rr->ThisAPInterval = MIN_UPDATE_REFRESH_TIME;
-            LogInfo("SetRecordRetry clamping to min refresh in %d of %d for %s",
-                    rr->ThisAPInterval/mDNSPlatformOneSecond, (rr->expire - m->timenow)/mDNSPlatformOneSecond, ARDisplayString(m, rr));
-        }
-        return;
-    }
-
-    rr->expire = 0;
-
-    rr->ThisAPInterval = rr->ThisAPInterval * QuestionIntervalStep; // Same Retry logic as Unicast Queries
-    if (rr->ThisAPInterval < INIT_RECORD_REG_INTERVAL)
-        rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-    if (rr->ThisAPInterval > MAX_RECORD_REG_INTERVAL)
-        rr->ThisAPInterval = MAX_RECORD_REG_INTERVAL;
-
-    LogInfo("SetRecordRetry retry in %d ms for %s", rr->ThisAPInterval, ARDisplayString(m, rr));
-}
-
-// ***************************************************************************
-// MARK: - Name Server List Management
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *domain, const mDNSInterfaceID interface,
-    const mDNSs32 serviceID, const mDNSAddr *addr, const mDNSIPPort port, ScopeType scopeType, mDNSu32 timeout,
-    mDNSBool isCell, mDNSBool isExpensive, mDNSBool isConstrained, mDNSBool isCLAT46, mDNSu32 resGroupID,
-    mDNSBool usableA, mDNSBool usableAAAA, mDNSBool reqDO)
-{
-    DNSServer **p;
-    DNSServer *server;
-    int       dnsCount = CountOfUnicastDNSServers(m);
-    if (dnsCount >= MAX_UNICAST_DNS_SERVERS)
-    {
-        LogMsg("mDNS_AddDNSServer: DNS server count of %d reached, not adding this server", dnsCount);
-        return mDNSNULL;
-    }
-
-    if (!domain) domain = (const domainname *)"";
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "mDNS_AddDNSServer(%d): Adding " PRI_IP_ADDR " for " PRI_DM_NAME " interface " PUB_S " (%p), serviceID %u, "
-        "scopeType %d, resGroupID %u" PUB_S PUB_S PUB_S PUB_S PUB_S PUB_S PUB_S,
-        dnsCount + 1, addr, DM_NAME_PARAM(domain), InterfaceNameForID(&mDNSStorage, interface), interface, serviceID,
-        (int)scopeType, resGroupID,
-        usableA       ? ", usableA"     : "",
-        usableAAAA    ? ", usableAAAA"  : "",
-        isCell        ? ", cell"        : "",
-        isExpensive   ? ", expensive"   : "",
-        isConstrained ? ", constrained" : "",
-        isCLAT46      ? ", CLAT46"      : "",
-        reqDO         ? ", reqDO"       : "");
-
-    mDNS_CheckLock(m);
-
-    // Scan our existing list to see if we already have a matching record for this DNS resolver
-    for (p = &m->DNSServers; (server = *p) != mDNSNULL; p = &server->next)
-    {
-        if (server->interface       != interface)       continue;
-        if (server->serviceID       != serviceID)       continue;
-        if (!mDNSSameAddress(&server->addr, addr))      continue;
-        if (!mDNSSameIPPort(server->port, port))        continue;
-        if (!SameDomainName(&server->domain, domain))   continue;
-        if (server->scopeType       != scopeType)       continue;
-        if (server->timeout         != timeout)         continue;
-        if (!server->usableA        != !usableA)        continue;
-        if (!server->usableAAAA     != !usableAAAA)     continue;
-        if (!server->isCell         != !isCell)         continue;
-        if (!(server->flags & DNSServerFlag_Delete))
-        {
-            debugf("Note: DNS Server %#a:%d for domain %##s (%p) registered more than once",
-                addr, mDNSVal16(port), domain->c, interface);
-        }
-        // If we found a matching record, cut it from the list
-        // (and if we’re *not* resurrecting a record that was marked for deletion, it’s a duplicate,
-        // and the debugf message signifies that we’re collapsing duplicate entries into one)
-        *p = server->next;
-        server->next = mDNSNULL;
-        break;
-    }
-
-    // If we broke out because we found an existing matching record, advance our pointer to the end of the list
-    while (*p)
-    {
-        p = &(*p)->next;
-    }
-
-    if (server)
-    {
-        if (server->flags & DNSServerFlag_Delete)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-            server->flags &= ~DNSServerFlag_Unreachable;
-#endif
-            server->flags &= ~DNSServerFlag_Delete;
-        }
-        server->isExpensive   = isExpensive;
-        server->isConstrained = isConstrained;
-        server->isCLAT46      = isCLAT46;
-        *p = server;    // Append resurrected record at end of list
-    }
-    else
-    {
-        server = (DNSServer *) mDNSPlatformMemAllocateClear(sizeof(*server));
-        if (!server)
-        {
-            LogMsg("Error: mDNS_AddDNSServer - malloc");
-        }
-        else
-        {
-            server->interface     = interface;
-            server->serviceID     = serviceID;
-            server->addr          = *addr;
-            server->port          = port;
-            server->scopeType     = scopeType;
-            server->timeout       = timeout;
-            server->usableA       = usableA;
-            server->usableAAAA    = usableAAAA;
-            server->isCell        = isCell;
-            server->isExpensive   = isExpensive;
-            server->isConstrained = isConstrained;
-            server->isCLAT46      = isCLAT46;
-            AssignDomainName(&server->domain, domain);
-            *p = server; // Append new record at end of list
-        }
-    }
-    if (server)
-    {
-        server->penaltyTime = 0;
-        // We always update the ID (not just when we allocate a new instance) because we want
-        // all the resGroupIDs for a particular domain to match.
-        server->resGroupID  = resGroupID;
-    }
-    return(server);
-}
-
-// PenalizeDNSServer is called when the number of queries to the unicast
-// DNS server exceeds MAX_UCAST_UNANSWERED_QUERIES or when we receive an
-// error e.g., SERV_FAIL from DNS server.
-mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags)
-{
-    DNSServer *new;
-    DNSServer *orig = q->qDNSServer;
-    mDNSu8 rcode = '\0';
-
-    mDNS_CheckLock(m);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-              "PenalizeDNSServer: Penalizing DNS server " PRI_IP_ADDR " question for question %p " PRI_DM_NAME " (" PUB_S ") SuppressUnusable %d",
-              (q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->SuppressUnusable);
-
-    // If we get error from any DNS server, remember the error. If all of the servers,
-    // return the error, then return the first error.
-    if (mDNSOpaque16IsZero(q->responseFlags))
-        q->responseFlags = responseFlags;
-
-    rcode = (mDNSu8)(responseFlags.b[1] & kDNSFlag1_RC_Mask);
-
-    // After we reset the qDNSServer to NULL, we could get more SERV_FAILS that might end up
-    // penalizing again.
-    if (!q->qDNSServer)
-        goto end;
-
-    // If strict ordering of unicast servers needs to be preserved, we just lookup
-    // the next best match server below
-    //
-    // If strict ordering is not required which is the default behavior, we penalize the server
-    // for DNSSERVER_PENALTY_TIME. We may also use additional logic e.g., don't penalize for PTR
-    // in the future.
-
-    if (!StrictUnicastOrdering)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "PenalizeDNSServer: Strict Unicast Ordering is FALSE");
-        // We penalize the server so that new queries don't pick this server for DNSSERVER_PENALTY_TIME
-        // XXX Include other logic here to see if this server should really be penalized
-        //
-        if (q->qtype == kDNSType_PTR)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "PenalizeDNSServer: Not Penalizing PTR question");
-        }
-        else if ((rcode == kDNSFlag1_RC_FormErr) || (rcode == kDNSFlag1_RC_ServFail) || (rcode == kDNSFlag1_RC_NotImpl))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "PenalizeDNSServer: Not Penalizing DNS Server since it at least responded with rcode %d", rcode);
-        }
-        else
-        {
-            const char *reason = "";
-            if (rcode == kDNSFlag1_RC_Refused)
-            {
-                reason = " because server refused to answer";
-            }
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "PenalizeDNSServer: Penalizing question type %d" PUB_S,
-                      q->qtype, reason);
-            q->qDNSServer->penaltyTime = NonZeroTime(m->timenow + DNSSERVER_PENALTY_TIME);
-        }
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "PenalizeDNSServer: Strict Unicast Ordering is TRUE");
-    }
-
-end:
-    new = GetServerForQuestion(m, q);
-
-    if (new == orig)
-    {
-        if (new)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "PenalizeDNSServer: ERROR!! GetServerForQuestion returned the same server " PRI_IP_ADDR ":%d",
-                      &new->addr, mDNSVal16(new->port));
-            q->ThisQInterval = 0;   // Inactivate this question so that we dont bombard the network
-        }
-        else
-        {
-            // When we have no more DNS servers, we might end up calling PenalizeDNSServer multiple
-            // times when we receive SERVFAIL from delayed packets in the network e.g., DNS server
-            // is slow in responding and we have sent three queries. When we repeatedly call, it is
-            // okay to receive the same NULL DNS server. Next time we try to send the query, we will
-            // realize and re-initialize the DNS servers.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "PenalizeDNSServer: GetServerForQuestion returned the same server NULL");
-        }
-    }
-    else
-    {
-        // The new DNSServer is set in DNSServerChangeForQuestion
-        DNSServerChangeForQuestion(m, q, new);
-
-        if (new)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "PenalizeDNSServer: Server for " PRI_DM_NAME " (" PUB_S ") changed to " PRI_IP_ADDR ":%d (" PRI_DM_NAME ")",
-                      DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), DM_NAME_PARAM(&q->qDNSServer->domain));
-            // We want to try the next server immediately. As the question may already have backed off, reset
-            // the interval. We do this only the first time when we try all the DNS servers. Once we reached the end of
-            // list and retrying all the servers again e.g., at least one server failed to respond in the previous try, we
-            // use the normal backoff which is done in uDNS_CheckCurrentQuestion when we send the packet out.
-            if (!q->triedAllServersOnce)
-            {
-                q->ThisQInterval = InitialQuestionInterval;
-                q->LastQTime  = m->timenow - q->ThisQInterval;
-                SetNextQueryTime(m, q);
-            }
-        }
-        else
-        {
-            // We don't have any more DNS servers for this question. If some server in the list did not return
-            // any response, we need to keep retrying till we get a response. uDNS_CheckCurrentQuestion handles
-            // this case.
-            //
-            // If all servers responded with a negative response, We need to do two things. First, generate a
-            // negative response so that applications get a reply. We also need to reinitialize the DNS servers
-            // so that when the cache expires, we can restart the query.  We defer this up until we generate
-            // a negative cache response in uDNS_CheckCurrentQuestion.
-            //
-            // Be careful not to touch the ThisQInterval here. For a normal question, when we answer the question
-            // in AnswerCurrentQuestionWithResourceRecord will set ThisQInterval to MaxQuestionInterval and hence
-            // the next query will not happen until cache expiry. If it is a long lived question,
-            // AnswerCurrentQuestionWithResourceRecord will not set it to MaxQuestionInterval. In that case,
-            // we want the normal backoff to work.
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "PenalizeDNSServer: Server for %p, " PRI_DM_NAME " (" PUB_S ") changed to NULL, Interval %d",
-                      q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->ThisQInterval);
-        }
-        q->unansweredQueries = 0;
-
-    }
-}
-#endif // !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-// ***************************************************************************
-// MARK: - authorization management
-
-mDNSlocal DomainAuthInfo *GetAuthInfoForName_direct(mDNS *m, const domainname *const name)
-{
-    const domainname *n = name;
-    while (n->c[0])
-    {
-        DomainAuthInfo *ptr;
-        for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
-            if (SameDomainName(&ptr->domain, n))
-            {
-                debugf("GetAuthInfoForName %##s Matched %##s Key name %##s", name->c, ptr->domain.c, ptr->keyname.c);
-                return(ptr);
-            }
-        n = (const domainname *)(n->c + 1 + n->c[0]);
-    }
-    //LogInfo("GetAuthInfoForName none found for %##s", name->c);
-    return mDNSNULL;
-}
-
-// MUST be called with lock held
-mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name)
-{
-    DomainAuthInfo **p = &m->AuthInfoList;
-
-    mDNS_CheckLock(m);
-
-    // First purge any dead keys from the list
-    while (*p)
-    {
-        if ((*p)->deltime && m->timenow - (*p)->deltime >= 0)
-        {
-            DNSQuestion *q;
-            DomainAuthInfo *info = *p;
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "GetAuthInfoForName_internal deleting expired key " PRI_DM_NAME " " PRI_DM_NAME,
-                DM_NAME_PARAM(&info->domain), DM_NAME_PARAM(&info->keyname));
-            *p = info->next;    // Cut DomainAuthInfo from list *before* scanning our question list updating AuthInfo pointers
-            for (q = m->Questions; q; q=q->next)
-                if (q->AuthInfo == info)
-                {
-                    q->AuthInfo = GetAuthInfoForName_direct(m, &q->qname);
-                    debugf("GetAuthInfoForName_internal updated q->AuthInfo from %##s to %##s for %##s (%s)",
-                           info->domain.c, q->AuthInfo ? q->AuthInfo->domain.c : mDNSNULL, q->qname.c, DNSTypeName(q->qtype));
-                }
-
-            // Probably not essential, but just to be safe, zero out the secret key data
-            // so we don't leave it hanging around in memory
-            // (where it could potentially get exposed via some other bug)
-            mDNSPlatformMemZero(info, sizeof(*info));
-            mDNSPlatformMemFree(info);
-        }
-        else
-            p = &(*p)->next;
-    }
-
-    return(GetAuthInfoForName_direct(m, name));
-}
-
-mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name)
-{
-    DomainAuthInfo *d;
-    mDNS_Lock(m);
-    d = GetAuthInfoForName_internal(m, name);
-    mDNS_Unlock(m);
-    return(d);
-}
-
-// MUST be called with the lock held
-mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
-                                           const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port)
-{
-    DNSQuestion *q;
-    DomainAuthInfo **p = &m->AuthInfoList;
-    if (!info || !b64keydata)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "No DomainAuthInfo or Base64 encoded secret - "
-            "info: %p, b64keydata: %p", info, b64keydata);
-        return mStatus_BadParamErr;
-    }
-
-    if (DNSDigest_ConstructHMACKeyfromBase64(info, b64keydata) < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "Could not convert shared secret from base64 - "
-            "domain: " PRI_DM_NAME ", key name: " PRI_DM_NAME ".", DM_NAME_PARAM(domain), DM_NAME_PARAM(keyname));
-        return mStatus_BadParamErr;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "Setting shared secret for domain - "
-        "domain: " PRI_DM_NAME ", key name: " PRI_DM_NAME ".", DM_NAME_PARAM(domain), DM_NAME_PARAM(keyname));
-
-    AssignDomainName(&info->domain,  domain);
-    AssignDomainName(&info->keyname, keyname);
-    if (hostname)
-        AssignDomainName(&info->hostname, hostname);
-    else
-        info->hostname.c[0] = 0;
-    if (port)
-        info->port = *port;
-    else
-        info->port = zeroIPPort;
-
-    // Don't clear deltime until after we've ascertained that b64keydata is valid
-    info->deltime = 0;
-
-    while (*p && (*p) != info) p=&(*p)->next;
-    if (*p)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO, "DomainAuthInfo already in the list - "
-            "domain: " PRI_DM_NAME, DM_NAME_PARAM(&(*p)->domain));
-        return mStatus_AlreadyRegistered;
-    }
-
-    info->next = mDNSNULL;
-    *p = info;
-
-    // Check to see if adding this new DomainAuthInfo has changed the credentials for any of our questions
-    for (q = m->Questions; q; q=q->next)
-    {
-        DomainAuthInfo *newinfo = GetAuthInfoForQuestion(m, q);
-        if (q->AuthInfo != newinfo)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "Updating question's AuthInfo - "
-                "qname: " PRI_DM_NAME ", qtype: " PUB_DNS_TYPE ", old AuthInfo domain: " PRI_DM_NAME
-                ", new AuthInfo domain: " PRI_DM_NAME, DM_NAME_PARAM(&q->qname), DNS_TYPE_PARAM(q->qtype),
-                DM_NAME_PARAM(q->AuthInfo ? &q->AuthInfo->domain : mDNSNULL),
-                DM_NAME_PARAM(newinfo ? &newinfo->domain : mDNSNULL));
-            q->AuthInfo = newinfo;
-        }
-    }
-
-    return(mStatus_NoError);
-}
-
-// ***************************************************************************
-// MARK: - NAT Traversal
-
-// Keep track of when to request/refresh the external address using NAT-PMP or UPnP/IGD,
-// and do so when necessary
-mDNSlocal mStatus uDNS_RequestAddress(mDNS *m)
-{
-    mStatus err = mStatus_NoError;
-
-    if (!m->NATTraversals)
-    {
-        m->retryGetAddr = NonZeroTime(m->timenow + FutureTime);
-        LogInfo("uDNS_RequestAddress: Setting retryGetAddr to future");
-    }
-    else if (m->timenow - m->retryGetAddr >= 0)
-    {
-        if (mDNSv4AddrIsRFC1918(&m->Router.ip.v4))
-        {
-            static NATAddrRequest req = {NATMAP_VERS, NATOp_AddrRequest};
-            static mDNSu8* start = (mDNSu8*)&req;
-            mDNSu8* end = start + sizeof(NATAddrRequest);
-            err = mDNSPlatformSendUDP(m, start, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse);
-            debugf("uDNS_RequestAddress: Sent NAT-PMP external address request %d", err);
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-            if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort))
-            {
-                LNT_SendDiscoveryMsg(m);
-                debugf("uDNS_RequestAddress: LNT_SendDiscoveryMsg");
-            }
-            else
-            {
-                mStatus lnterr = LNT_GetExternalAddress(m);
-                if (lnterr)
-                    LogMsg("uDNS_RequestAddress: LNT_GetExternalAddress returned error %d", lnterr);
-
-                err = err ? err : lnterr; // NAT-PMP error takes precedence
-            }
-#endif // _LEGACY_NAT_TRAVERSAL_
-        }
-
-        // Always update the interval and retry time, so that even if we fail to send the
-        // packet, we won't spin in an infinite loop repeatedly failing to send the packet
-        if (m->retryIntervalGetAddr < NATMAP_INIT_RETRY)
-        {
-            m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
-        }
-        else if (m->retryIntervalGetAddr < NATMAP_MAX_RETRY_INTERVAL / 2)
-        {
-            m->retryIntervalGetAddr *= 2;
-        }
-        else
-        {
-            m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL;
-        }
-
-        m->retryGetAddr = NonZeroTime(m->timenow + m->retryIntervalGetAddr);
-    }
-    else
-    {
-        debugf("uDNS_RequestAddress: Not time to send address request");
-    }
-
-    // Always update NextScheduledNATOp, even if we didn't change retryGetAddr, so we'll
-    // be called when we need to send the request(s)
-    if (m->NextScheduledNATOp - m->retryGetAddr > 0)
-        m->NextScheduledNATOp = m->retryGetAddr;
-
-    return err;
-}
-
-mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool usePCP, mDNSBool unmapping)
-{
-    mStatus err = mStatus_NoError;
-
-    if (!info)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "uDNS_SendNATMsg called unexpectedly with NULL info");
-        return mStatus_BadParamErr;
-    }
-
-    // send msg if the router's address is private (which means it's non-zero)
-    if (mDNSv4AddrIsRFC1918(&m->Router.ip.v4))
-    {
-        if (!usePCP)
-        {
-            if (!info->sentNATPMP)
-            {
-                if (info->Protocol)
-                {
-                    static NATPortMapRequest NATPortReq;
-                    static const mDNSu8* end = (mDNSu8 *)&NATPortReq + sizeof(NATPortMapRequest);
-                    mDNSu8 *p = (mDNSu8 *)&NATPortReq.NATReq_lease;
-
-                    NATPortReq.vers    = NATMAP_VERS;
-                    NATPortReq.opcode  = info->Protocol;
-                    NATPortReq.unused  = zeroID;
-                    NATPortReq.intport = info->IntPort;
-                    NATPortReq.extport = info->RequestedPort;
-                    p[0] = (mDNSu8)((info->NATLease >> 24) &  0xFF);
-                    p[1] = (mDNSu8)((info->NATLease >> 16) &  0xFF);
-                    p[2] = (mDNSu8)((info->NATLease >>  8) &  0xFF);
-                    p[3] = (mDNSu8)( info->NATLease        &  0xFF);
-
-                    err = mDNSPlatformSendUDP(m, (mDNSu8 *)&NATPortReq, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse);
-                    debugf("uDNS_SendNATMsg: Sent NAT-PMP mapping request %d", err);
-                }
-
-                // In case the address request already went out for another NAT-T,
-                // set the NewAddress to the currently known global external address, so
-                // Address-only operations will get the callback immediately
-                info->NewAddress = m->ExtAddress;
-
-                // Remember that we just sent a NAT-PMP packet, so we won't resend one later.
-                // We do this because the NAT-PMP "Unsupported Version" response has no
-                // information about the (PCP) request that triggered it, so we must send
-                // NAT-PMP requests for all operations. Without this, we'll send n PCP
-                // requests for n operations, receive n NAT-PMP "Unsupported Version"
-                // responses, and send n NAT-PMP requests for each of those responses,
-                // resulting in (n + n^2) packets sent. We only want to send 2n packets:
-                // n PCP requests followed by n NAT-PMP requests.
-                info->sentNATPMP = mDNStrue;
-            }
-        }
-        else
-        {
-            PCPMapRequest req;
-            mDNSu8* start = (mDNSu8*)&req;
-            mDNSu8* end = start + sizeof(req);
-            mDNSu8* p = (mDNSu8*)&req.lifetime;
-
-            req.version = PCP_VERS;
-            req.opCode = PCPOp_Map;
-            req.reserved = zeroID;
-
-            p[0] = (mDNSu8)((info->NATLease >> 24) &  0xFF);
-            p[1] = (mDNSu8)((info->NATLease >> 16) &  0xFF);
-            p[2] = (mDNSu8)((info->NATLease >>  8) &  0xFF);
-            p[3] = (mDNSu8)( info->NATLease        &  0xFF);
-
-            mDNSAddrMapIPv4toIPv6(&m->AdvertisedV4.ip.v4, &req.clientAddr);
-
-            req.nonce[0] = m->PCPNonce[0];
-            req.nonce[1] = m->PCPNonce[1];
-            req.nonce[2] = m->PCPNonce[2];
-
-            req.protocol = (info->Protocol == NATOp_MapUDP ? PCPProto_UDP : PCPProto_TCP);
-
-            req.reservedMapOp[0] = 0;
-            req.reservedMapOp[1] = 0;
-            req.reservedMapOp[2] = 0;
-
-            req.intPort = info->Protocol ? info->IntPort : DiscardPort;
-            req.extPort = info->RequestedPort;
-
-            // Since we only support IPv4, even if using the all-zeros address, map it, so
-            // the PCP gateway will give us an IPv4 address & not an IPv6 address.
-            mDNSAddrMapIPv4toIPv6(&info->NewAddress, &req.extAddress);
-
-            err = mDNSPlatformSendUDP(m, start, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse);
-            debugf("uDNS_SendNATMsg: Sent PCP Mapping request %d", err);
-
-            // Unset the sentNATPMP flag, so that we'll send a NAT-PMP packet if we
-            // receive a NAT-PMP "Unsupported Version" packet. This will result in every
-            // renewal, retransmission, etc. being tried first as PCP, then if a NAT-PMP
-            // "Unsupported Version" response is received, fall-back & send the request
-            // using NAT-PMP.
-            info->sentNATPMP = mDNSfalse;
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-            // If an unmapping is being performed, then don't send an LNT discovery message or an LNT port map request.
-            if (!unmapping)
-            {
-                if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort))
-                {
-                    LNT_SendDiscoveryMsg(m);
-                    debugf("uDNS_SendNATMsg: LNT_SendDiscoveryMsg");
-                }
-                else
-                {
-                    mStatus lnterr = LNT_MapPort(m, info);
-                    if (lnterr)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "uDNS_SendNATMsg: LNT_MapPort returned error %d", lnterr);
-                    }
-
-                    err = err ? err : lnterr; // PCP error takes precedence
-                }
-            }
-#else
-            (void)unmapping; // Unused
-#endif // _LEGACY_NAT_TRAVERSAL_
-        }
-    }
-
-    return(err);
-}
-
-mDNSexport void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks)
-{
-    mDNSu32 when = NonZeroTime(m->timenow + waitTicks);
-    NATTraversalInfo *n;
-    for (n = m->NATTraversals; n; n=n->next)
-    {
-        n->ExpiryTime    = 0;       // Mark this mapping as expired
-        n->retryInterval = NATMAP_INIT_RETRY;
-        n->retryPortMap  = when;
-        n->lastSuccessfulProtocol = NATTProtocolNone;
-        if (!n->Protocol) n->NewResult = mStatus_NoError;
-#ifdef _LEGACY_NAT_TRAVERSAL_
-        if (n->tcpInfo.sock) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock = mDNSNULL; }
-#endif // _LEGACY_NAT_TRAVERSAL_
-    }
-
-    m->PCPNonce[0] = mDNSRandom(-1);
-    m->PCPNonce[1] = mDNSRandom(-1);
-    m->PCPNonce[2] = mDNSRandom(-1);
-    m->retryIntervalGetAddr = 0;
-    m->retryGetAddr = when;
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-    LNT_ClearState(m);
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-    m->NextScheduledNATOp = m->timenow;     // Need to send packets immediately
-}
-
-mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr)
-{
-    static mDNSu16 last_err = 0;
-    NATTraversalInfo *n;
-
-    if (err)
-    {
-        if (err != last_err) LogMsg("Error getting external address %d", err);
-        ExtAddr = zerov4Addr;
-    }
-    else
-    {
-        LogInfo("Received external IP address %.4a from NAT", &ExtAddr);
-        if (mDNSv4AddrIsRFC1918(&ExtAddr))
-            LogMsg("Double NAT (external NAT gateway address %.4a is also a private RFC 1918 address)", &ExtAddr);
-        if (mDNSIPv4AddressIsZero(ExtAddr))
-            err = NATErr_NetFail; // fake error to handle routers that pathologically report success with the zero address
-    }
-
-    // Globally remember the most recently discovered address, so it can be used in each
-    // new NATTraversal structure
-    m->ExtAddress = ExtAddr;
-
-    if (!err) // Success, back-off to maximum interval
-        m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL;
-    else if (!last_err) // Failure after success, retry quickly (then back-off exponentially)
-        m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
-    // else back-off normally in case of pathological failures
-
-    m->retryGetAddr = m->timenow + m->retryIntervalGetAddr;
-    if (m->NextScheduledNATOp - m->retryGetAddr > 0)
-        m->NextScheduledNATOp = m->retryGetAddr;
-
-    last_err = err;
-
-    for (n = m->NATTraversals; n; n=n->next)
-    {
-        // We should change n->NewAddress only when n is one of:
-        // 1) a mapping operation that most recently succeeded using NAT-PMP or UPnP/IGD,
-        //    because such an operation needs the update now. If the lastSuccessfulProtocol
-        //    is currently none, then natTraversalHandlePortMapReplyWithAddress() will be
-        //    called should NAT-PMP or UPnP/IGD succeed in the future.
-        // 2) an address-only operation that did not succeed via PCP, because when such an
-        //    operation succeeds via PCP, it's for the TCP discard port just to learn the
-        //    address. And that address may be different than the external address
-        //    discovered via NAT-PMP or UPnP/IGD. If the lastSuccessfulProtocol
-        //    is currently none, we must update the NewAddress as PCP may not succeed.
-        if (!mDNSSameIPv4Address(n->NewAddress, ExtAddr) &&
-             (n->Protocol ?
-               (n->lastSuccessfulProtocol == NATTProtocolNATPMP || n->lastSuccessfulProtocol == NATTProtocolUPNPIGD) :
-               (n->lastSuccessfulProtocol != NATTProtocolPCP)))
-        {
-            // Needs an update immediately
-            n->NewAddress    = ExtAddr;
-            n->ExpiryTime    = 0;
-            n->retryInterval = NATMAP_INIT_RETRY;
-            n->retryPortMap  = m->timenow;
-#ifdef _LEGACY_NAT_TRAVERSAL_
-            if (n->tcpInfo.sock) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock = mDNSNULL; }
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-            m->NextScheduledNATOp = m->timenow;     // Need to send packets immediately
-        }
-    }
-}
-
-// Both places that call NATSetNextRenewalTime() update m->NextScheduledNATOp correctly afterwards
-mDNSlocal void NATSetNextRenewalTime(mDNS *const m, NATTraversalInfo *n)
-{
-    n->retryInterval = (n->ExpiryTime - m->timenow)/2;
-    if (n->retryInterval < NATMAP_MIN_RETRY_INTERVAL)   // Min retry interval is 2 seconds
-        n->retryInterval = NATMAP_MIN_RETRY_INTERVAL;
-    n->retryPortMap = m->timenow + n->retryInterval;
-}
-
-mDNSlocal void natTraversalHandlePortMapReplyWithAddress(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSv4Addr extaddr, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol)
-{
-    const char *prot = n->Protocol == 0 ? "Add" : n->Protocol == NATOp_MapUDP ? "UDP" : n->Protocol == NATOp_MapTCP ? "TCP" : "???";
-    (void)prot;
-    n->NewResult = err;
-    if (err || lease == 0 || mDNSIPPortIsZero(extport))
-    {
-        LogInfo("natTraversalHandlePortMapReplyWithAddress: %p Response %s Port %5d External %.4a:%d lease %d error %d",
-                n, prot, mDNSVal16(n->IntPort), &extaddr, mDNSVal16(extport), lease, err);
-        n->retryInterval = NATMAP_MAX_RETRY_INTERVAL;
-        n->retryPortMap = m->timenow + NATMAP_MAX_RETRY_INTERVAL;
-        // No need to set m->NextScheduledNATOp here, since we're only ever extending the m->retryPortMap time
-        if      (err == NATErr_Refused) n->NewResult = mStatus_NATPortMappingDisabled;
-        else if (err > NATErr_None && err <= NATErr_Opcode) n->NewResult = mStatus_NATPortMappingUnsupported;
-    }
-    else
-    {
-        if (lease > 999999999UL / mDNSPlatformOneSecond)
-            lease = 999999999UL / mDNSPlatformOneSecond;
-        n->ExpiryTime = NonZeroTime(m->timenow + lease * mDNSPlatformOneSecond);
-
-        if (!mDNSSameIPv4Address(n->NewAddress, extaddr) || !mDNSSameIPPort(n->RequestedPort, extport))
-            LogInfo("natTraversalHandlePortMapReplyWithAddress: %p %s Response %s Port %5d External %.4a:%d changed to %.4a:%d lease %d",
-                    n,
-                    (n->lastSuccessfulProtocol == NATTProtocolNone    ? "None    " :
-                     n->lastSuccessfulProtocol == NATTProtocolNATPMP  ? "NAT-PMP " :
-                     n->lastSuccessfulProtocol == NATTProtocolUPNPIGD ? "UPnP/IGD" :
-                     n->lastSuccessfulProtocol == NATTProtocolPCP     ? "PCP     " :
-                     /* else */                                         "Unknown " ),
-                    prot, mDNSVal16(n->IntPort), &n->NewAddress, mDNSVal16(n->RequestedPort),
-                    &extaddr, mDNSVal16(extport), lease);
-
-        n->InterfaceID   = InterfaceID;
-        n->NewAddress    = extaddr;
-        if (n->Protocol) n->RequestedPort = extport; // Don't report the (PCP) external port to address-only operations
-        n->lastSuccessfulProtocol = protocol;
-
-        NATSetNextRenewalTime(m, n);            // Got our port mapping; now set timer to renew it at halfway point
-        m->NextScheduledNATOp = m->timenow;     // May need to invoke client callback immediately
-    }
-}
-
-// To be called for NAT-PMP or UPnP/IGD mappings, to use currently discovered (global) address
-mDNSexport void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol)
-{
-    natTraversalHandlePortMapReplyWithAddress(m, n, InterfaceID, err, m->ExtAddress, extport, lease, protocol);
-}
-
-// Must be called with the mDNS_Lock held
-mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalInfo *traversal)
-{
-    NATTraversalInfo **n;
-
-    LogInfo("mDNS_StartNATOperation_internal %p Protocol %d IntPort %d RequestedPort %d NATLease %d", traversal,
-            traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease);
-
-    // Note: It important that new traversal requests are appended at the *end* of the list, not prepended at the start
-    for (n = &m->NATTraversals; *n; n=&(*n)->next)
-    {
-        if (traversal == *n)
-        {
-            LogFatalError("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d",
-                   traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease);
-            return(mStatus_AlreadyRegistered);
-        }
-        if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) &&
-            !mDNSSameIPPort(traversal->IntPort, SSHPort))
-            LogMsg("Warning: Created port mapping request %p Prot %d Int %d TTL %d "
-                   "duplicates existing port mapping request %p Prot %d Int %d TTL %d",
-                   traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease,
-                   *n,        (*n)->Protocol, mDNSVal16((*n)->IntPort), (*n)->NATLease);
-    }
-
-    // Initialize necessary fields
-    traversal->next            = mDNSNULL;
-    traversal->ExpiryTime      = 0;
-    traversal->retryInterval   = NATMAP_INIT_RETRY;
-    traversal->retryPortMap    = m->timenow;
-    traversal->NewResult       = mStatus_NoError;
-    traversal->lastSuccessfulProtocol = NATTProtocolNone;
-    traversal->sentNATPMP      = mDNSfalse;
-    traversal->ExternalAddress = onesIPv4Addr;
-    traversal->NewAddress      = zerov4Addr;
-    traversal->ExternalPort    = zeroIPPort;
-    traversal->Lifetime        = 0;
-    traversal->Result          = mStatus_NoError;
-
-    // set default lease if necessary
-    if (!traversal->NATLease) traversal->NATLease = NATMAP_DEFAULT_LEASE;
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-    mDNSPlatformMemZero(&traversal->tcpInfo, sizeof(traversal->tcpInfo));
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-    if (!m->NATTraversals)      // If this is our first NAT request, kick off an address request too
-    {
-        m->retryGetAddr         = m->timenow;
-        m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
-    }
-
-    // If this is an address-only operation, initialize to the current global address,
-    // or (in non-PCP environments) we won't know the address until the next external
-    // address request/response.
-    if (!traversal->Protocol)
-    {
-        traversal->NewAddress = m->ExtAddress;
-    }
-
-    m->NextScheduledNATOp = m->timenow; // This will always trigger sending the packet ASAP, and generate client callback if necessary
-
-    *n = traversal;     // Append new NATTraversalInfo to the end of our list
-
-    return(mStatus_NoError);
-}
-
-// Must be called with the mDNS_Lock held
-mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
-{
-    mDNSBool unmap = mDNStrue;
-    NATTraversalInfo *p;
-    NATTraversalInfo **ptr = &m->NATTraversals;
-
-    while (*ptr && *ptr != traversal) ptr=&(*ptr)->next;
-    if (*ptr) *ptr = (*ptr)->next;      // If we found it, cut this NATTraversalInfo struct from our list
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNS_StopNATOperation_internal: NATTraversalInfo %p not found in list", traversal);
-        return(mStatus_BadReferenceErr);
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNS_StopNATOperation_internal %p %d %d %d %d", traversal,
-        traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease);
-
-    if (m->CurrentNATTraversal == traversal)
-        m->CurrentNATTraversal = m->CurrentNATTraversal->next;
-
-    // If there is a match for the operation being stopped, don't send a deletion request (unmap)
-    for (p = m->NATTraversals; p; p=p->next)
-    {
-        if (traversal->Protocol ?
-            ((traversal->Protocol == p->Protocol && mDNSSameIPPort(traversal->IntPort, p->IntPort)) ||
-             (!p->Protocol && traversal->Protocol == NATOp_MapTCP && mDNSSameIPPort(traversal->IntPort, DiscardPort))) :
-            (!p->Protocol || (p->Protocol == NATOp_MapTCP && mDNSSameIPPort(p->IntPort, DiscardPort))))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "Warning: Removed port mapping request %p Prot %d Int %d TTL %d "
-                "duplicates existing port mapping request %p Prot %d Int %d TTL %d",
-                traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease,
-                p, p->Protocol, mDNSVal16(p->IntPort), p->NATLease);
-            unmap = mDNSfalse;
-        }
-    }
-
-    // Even if we DIDN'T make a successful UPnP mapping yet, we might still have a partially-open TCP connection we need to clean up
-    // Before zeroing traversal->RequestedPort below, perform the LNT unmapping, which requires the mapping's external port,
-    // held by the traversal->RequestedPort variable.
-    #ifdef _LEGACY_NAT_TRAVERSAL_
-    {
-        mStatus err = LNT_UnmapPort(m, traversal);
-        if (err)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "Legacy NAT Traversal - unmap request failed with error %d", err);
-        }
-    }
-    #endif // _LEGACY_NAT_TRAVERSAL_
-
-    if (traversal->ExpiryTime && unmap)
-    {
-        traversal->NATLease = 0;
-        traversal->retryInterval = 0;
-
-        // In case we most recently sent NAT-PMP, we need to set sentNATPMP to false so
-        // that we'll send a NAT-PMP request to destroy the mapping. We do this because
-        // the NATTraversal struct has already been cut from the list, and the client
-        // layer will destroy the memory upon returning from this function, so we can't
-        // try PCP first and then fall-back to NAT-PMP. That is, if we most recently
-        // created/renewed the mapping using NAT-PMP, we need to destroy it using NAT-PMP
-        // now, because we won't get a chance later.
-        traversal->sentNATPMP = mDNSfalse;
-
-        // Both NAT-PMP & PCP RFCs state that the suggested port in deletion requests
-        // should be zero. And for PCP, the suggested external address should also be
-        // zero, specifically, the all-zeros IPv4-mapped address, since we would only
-        // would have requested an IPv4 address.
-        traversal->RequestedPort = zeroIPPort;
-        traversal->NewAddress = zerov4Addr;
-
-        uDNS_SendNATMsg(m, traversal, traversal->lastSuccessfulProtocol != NATTProtocolNATPMP, mDNStrue);
-    }
-
-    return(mStatus_NoError);
-}
-
-mDNSexport mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal)
-{
-    mStatus status;
-    mDNS_Lock(m);
-    status = mDNS_StartNATOperation_internal(m, traversal);
-    mDNS_Unlock(m);
-    return(status);
-}
-
-mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal)
-{
-    mStatus status;
-    mDNS_Lock(m);
-    status = mDNS_StopNATOperation_internal(m, traversal);
-    mDNS_Unlock(m);
-    return(status);
-}
-
-// ***************************************************************************
-// MARK: - Long-Lived Queries
-
-mDNSlocal const char *LLQStateToString(LLQ_State state);
-
-// Lock must be held -- otherwise m->timenow is undefined
-mDNSlocal void StartLLQPolling(mDNS *const m, DNSQuestion *q)
-{
-    const mDNSu32 request_id = q->request_id;
-    const mDNSu16 question_id = mDNSVal16(q->TargetQID);
-
-    if (q->ThisQInterval != -1)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] Starting long-lived query polling - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_S ", LLQ_State: " PUB_S ".", request_id, question_id,
-            DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), LLQStateToString(q->state));
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[R%u->Q%u] Not starting long-lived query polling since the question has been stopped - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_S ", LLQ_State: " PUB_S ".", request_id, question_id,
-            DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), LLQStateToString(q->state));
-        return;
-    }
-
-    // If we start the LLQ poll for the question, then the query for getting the zone data can be canceled since zone
-    // data is not required for LLQ poll to work.
-    if (q->nta != mDNSNULL)
-    {
-        const DNSQuestion *const zone_question = &(q->nta->question);
-        const mDNSu16 zone_question_id = mDNSVal16(zone_question->TargetQID);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u->subQ%u] Stop getting the zone data - "
-            "zone qname: " PRI_DM_NAME ", zone qtype: " PUB_S ".", request_id, question_id, zone_question_id,
-            DM_NAME_PARAM(&zone_question->qname), DNSTypeName(zone_question->qtype));
-        CancelGetZoneData(m, q->nta);
-        q->nta = mDNSNULL;
-    }
-
-    q->state = LLQ_Poll;
-    q->ThisQInterval = INIT_UCAST_POLL_INTERVAL;
-    // We want to send our poll query ASAP, but the "+ 1" is because if we set the time to now,
-    // we risk causing spurious "SendQueries didn't send all its queries" log messages
-    q->LastQTime     = m->timenow - q->ThisQInterval + 1;
-    SetNextQueryTime(m, q);
-}
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *const question, const LLQOptData *const data)
-{
-    AuthRecord rr;
-    ResourceRecord *opt = &rr.resrec;
-    rdataOPT *optRD;
-
-    //!!!KRS when we implement multiple llqs per message, we'll need to memmove anything past the question section
-    ptr = putQuestion(msg, ptr, msg->data + AbsoluteMaxDNSMessageData, &question->qname, question->qtype, question->qclass);
-    if (!ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "ERROR: putLLQ - putQuestion");
-        return mDNSNULL;
-    }
-
-    // locate OptRR if it exists, set pointer to end
-    // !!!KRS implement me
-
-    // format opt rr (fields not specified are zero-valued)
-    mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-    opt->rrclass    = NormalMaxDNSMessageData;
-    opt->rdlength   = sizeof(rdataOPT); // One option in this OPT record
-    opt->rdestimate = sizeof(rdataOPT);
-
-    optRD = &rr.resrec.rdata->u.opt[0];
-    optRD->opt = kDNSOpt_LLQ;
-    optRD->u.llq = *data;
-    ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, opt, 0);
-    if (!ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "ERROR: putLLQ - PutResourceRecordTTLJumbo");
-        return mDNSNULL;
-    }
-
-    return ptr;
-}
-
-// Normally we'd just request event packets be sent directly to m->LLQNAT.ExternalPort, except...
-// with LLQs over TLS/TCP we're doing a weird thing where instead of requesting packets be sent to ExternalAddress:ExternalPort
-// we're requesting that packets be sent to ExternalPort, but at the source address of our outgoing TCP connection.
-// Normally, after going through the NAT gateway, the source address of our outgoing TCP connection is the same as ExternalAddress,
-// so this is fine, except when the TCP connection ends up going over a VPN tunnel instead.
-// To work around this, if we find that the source address for our TCP connection is not a private address, we tell the Dot Mac
-// LLQ server to send events to us directly at port 5353 on that address, instead of at our mapped external NAT port.
-
-mDNSlocal mDNSu16 GetLLQEventPort(const mDNS *const m, const mDNSAddr *const dst)
-{
-    mDNSAddr src;
-    mDNSPlatformSourceAddrForDest(&src, dst);
-    //LogMsg("GetLLQEventPort: src %#a for dst %#a (%d)", &src, dst, mDNSv4AddrIsRFC1918(&src.ip.v4) ? mDNSVal16(m->LLQNAT.ExternalPort) : 0);
-    return(mDNSv4AddrIsRFC1918(&src.ip.v4) ? mDNSVal16(m->LLQNAT.ExternalPort) : mDNSVal16(MulticastDNSPort));
-}
-
-// Normally called with llq set.
-// May be called with llq NULL, when retransmitting a lost Challenge Response
-mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const LLQOptData *llq)
-{
-    mDNSu8 *responsePtr = m->omsg.data;
-    LLQOptData llqBuf;
-
-    if (q->tcp) { LogMsg("sendChallengeResponse: ERROR!!: question %##s (%s) tcp non-NULL", q->qname.c, DNSTypeName(q->qtype)); return; }
-
-    if (q->ntries++ == kLLQ_MAX_TRIES)
-    {
-        LogMsg("sendChallengeResponse: %d failed attempts for LLQ %##s", kLLQ_MAX_TRIES, q->qname.c);
-        StartLLQPolling(m,q);
-        return;
-    }
-
-    if (!llq)       // Retransmission: need to make a new LLQOptData
-    {
-        llqBuf.vers     = kLLQ_Vers;
-        llqBuf.llqOp    = kLLQOp_Setup;
-        llqBuf.err      = LLQErr_NoError;   // Don't need to tell server UDP notification port when sending over UDP
-        llqBuf.id       = q->id;
-        llqBuf.llqlease = q->ReqLease;
-        llq = &llqBuf;
-    }
-
-    q->LastQTime     = m->timenow;
-    q->ThisQInterval = q->tcp ? 0 : (kLLQ_INIT_RESEND * q->ntries * mDNSPlatformOneSecond);     // If using TCP, don't need to retransmit
-    SetNextQueryTime(m, q);
-
-    // To simulate loss of challenge response packet, uncomment line below
-    //if (q->ntries == 1) return;
-
-    InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-    responsePtr = putLLQ(&m->omsg, responsePtr, q, llq);
-    if (responsePtr)
-    {
-        mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, mDNSNULL, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSfalse);
-        if (err) { LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); }
-    }
-    else StartLLQPolling(m,q);
-}
-
-mDNSlocal void SetLLQTimer(mDNS *const m, DNSQuestion *const q, const LLQOptData *const llq)
-{
-    mDNSs32 lease = (mDNSs32)llq->llqlease * mDNSPlatformOneSecond;
-    q->ReqLease      = llq->llqlease;
-    q->LastQTime     = m->timenow;
-    q->expire        = m->timenow + lease;
-    q->ThisQInterval = lease/2 + mDNSRandom(lease/10);
-    debugf("SetLLQTimer setting %##s (%s) to %d %d", q->qname.c, DNSTypeName(q->qtype), lease/mDNSPlatformOneSecond, q->ThisQInterval/mDNSPlatformOneSecond);
-    SetNextQueryTime(m, q);
-}
-
-mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const q, const LLQOptData *const llq)
-{
-    if (rcode && rcode != kDNSFlag1_RC_NXDomain)
-    { LogMsg("ERROR: recvSetupResponse %##s (%s) - rcode && rcode != kDNSFlag1_RC_NXDomain", q->qname.c, DNSTypeName(q->qtype)); return; }
-
-    if (llq->llqOp != kLLQOp_Setup)
-    { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad op %d", q->qname.c, DNSTypeName(q->qtype), llq->llqOp); return; }
-
-    if (llq->vers != kLLQ_Vers)
-    { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad vers %d", q->qname.c, DNSTypeName(q->qtype), llq->vers); return; }
-
-    if (q->state == LLQ_InitialRequest)
-    {
-        //LogInfo("Got LLQ_InitialRequest");
-
-        if (llq->err) { LogMsg("recvSetupResponse - received llq->err %d from server", llq->err); StartLLQPolling(m,q); return; }
-
-        if (q->ReqLease != llq->llqlease)
-            debugf("recvSetupResponse: requested lease %lu, granted lease %lu", q->ReqLease, llq->llqlease);
-
-        // cache expiration in case we go to sleep before finishing setup
-        q->ReqLease = llq->llqlease;
-        q->expire = m->timenow + ((mDNSs32)llq->llqlease * mDNSPlatformOneSecond);
-
-        // update state
-        q->state  = LLQ_SecondaryRequest;
-        q->id     = llq->id;
-        q->ntries = 0; // first attempt to send response
-        sendChallengeResponse(m, q, llq);
-    }
-    else if (q->state == LLQ_SecondaryRequest)
-    {
-        if (llq->err) { LogMsg("ERROR: recvSetupResponse %##s (%s) code %d from server", q->qname.c, DNSTypeName(q->qtype), llq->err); StartLLQPolling(m,q); return; }
-        if (!mDNSSameOpaque64(&q->id, &llq->id))
-        { LogMsg("recvSetupResponse - ID changed.  discarding"); return; }     // this can happen rarely (on packet loss + reordering)
-        q->state         = LLQ_Established;
-        q->ntries        = 0;
-        SetLLQTimer(m, q, llq);
-    }
-}
-
-mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-                                             const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion)
-{
-    DNSQuestion pktQ, *q;
-    if (msg->h.numQuestions && getQuestion(msg, msg->data, end, 0, &pktQ))
-    {
-        const rdataOPT *opt = GetLLQOptData(m, msg, end);
-
-        for (q = m->Questions; q; q = q->next)
-        {
-            if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->qtype == pktQ.qtype && q->qnamehash == pktQ.qnamehash && SameDomainName(&q->qname, &pktQ.qname))
-            {
-                debugf("uDNS_recvLLQResponse found %##s (%s) %d %#a %#a %X %X %X %X %d",
-                       q->qname.c, DNSTypeName(q->qtype), q->state, srcaddr, &q->servAddr,
-                       opt ? opt->u.llq.id.l[0] : 0, opt ? opt->u.llq.id.l[1] : 0, q->id.l[0], q->id.l[1], opt ? opt->u.llq.llqOp : 0);
-                if (q->state == LLQ_Poll) debugf("uDNS_LLQ_Events: q->state == LLQ_Poll msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID));
-                if (q->state == LLQ_Poll && mDNSSameOpaque16(msg->h.id, q->TargetQID))
-                {
-                    mDNSCoreResetRecord(m);
-
-                    // Don't reset the state to IntialRequest as we may write that to the dynamic store
-                    // and PrefPane might wrongly think that we are "Starting" instead of "Polling". If
-                    // we are in polling state because of PCP/NAT-PMP disabled or DoubleNAT, next LLQNATCallback
-                    // would kick us back to LLQInitialRequest. So, resetting the state here may not be useful.
-                    //
-                    // If we have a good NAT (neither PCP/NAT-PMP disabled nor Double-NAT), then we should not be
-                    // possibly in polling state. To be safe, we want to retry from the start in that case
-                    // as there may not be another LLQNATCallback
-                    //
-                    // NOTE: We can be in polling state if we cannot resolve the SOA record i.e, servAddr is set to
-                    // all ones. In that case, we would set it in LLQ_InitialRequest as it overrides the PCP/NAT-PMP or
-                    // Double-NAT state.
-                    if (!mDNSAddressIsOnes(&q->servAddr) && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort) &&
-                        !m->LLQNAT.Result)
-                    {
-                        debugf("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-                        q->state         = LLQ_InitialRequest;
-                    }
-                    q->servPort      = zeroIPPort;      // Clear servPort so that startLLQHandshake will retry the GetZoneData processing
-                    q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);    // Retry LLQ setup in approx 15 minutes
-                    q->LastQTime     = m->timenow;
-                    SetNextQueryTime(m, q);
-                    *matchQuestion = q;
-                    return uDNS_LLQ_Entire;     // uDNS_LLQ_Entire means flush stale records; assume a large effective TTL
-                }
-                // Note: In LLQ Event packets, the msg->h.id does not match our q->TargetQID, because in that case the msg->h.id nonce is selected by the server
-                else if (opt && q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Event && mDNSSameOpaque64(&opt->u.llq.id, &q->id))
-                {
-                    mDNSu8 *ackEnd;
-                    //debugf("Sending LLQ ack for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-                    InitializeDNSMessage(&m->omsg.h, msg->h.id, ResponseFlags);
-                    ackEnd = putLLQ(&m->omsg, m->omsg.data, q, &opt->u.llq);
-                    if (ackEnd) mDNSSendDNSMessage(m, &m->omsg, ackEnd, mDNSInterface_Any, mDNSNULL, q->LocalSocket, srcaddr, srcport, mDNSNULL, mDNSfalse);
-                    mDNSCoreResetRecord(m);
-                    debugf("uDNS_LLQ_Events: q->state == LLQ_Established msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID));
-                    *matchQuestion = q;
-                    return uDNS_LLQ_Events;
-                }
-                if (opt && mDNSSameOpaque16(msg->h.id, q->TargetQID))
-                {
-                    if (q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Refresh && mDNSSameOpaque64(&opt->u.llq.id, &q->id) && msg->h.numAdditionals && !msg->h.numAnswers)
-                    {
-                        if (opt->u.llq.err != LLQErr_NoError) LogMsg("recvRefreshReply: received error %d from server", opt->u.llq.err);
-                        else
-                        {
-                            //LogInfo("Received refresh confirmation ntries %d for %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype));
-                            // If we're waiting to go to sleep, then this LLQ deletion may have been the thing
-                            // we were waiting for, so schedule another check to see if we can sleep now.
-                            if (opt->u.llq.llqlease == 0 && m->SleepLimit) m->NextScheduledSPRetry = m->timenow;
-                            GrantCacheExtensions(m, q, opt->u.llq.llqlease);
-                            SetLLQTimer(m, q, &opt->u.llq);
-                            q->ntries = 0;
-                        }
-                        mDNSCoreResetRecord(m);
-                        *matchQuestion = q;
-                        return uDNS_LLQ_Ignore;
-                    }
-                    if (q->state < LLQ_Established && mDNSSameAddress(srcaddr, &q->servAddr))
-                    {
-                        LLQ_State oldstate = q->state;
-                        recvSetupResponse(m, msg->h.flags.b[1] & kDNSFlag1_RC_Mask, q, &opt->u.llq);
-                        mDNSCoreResetRecord(m);
-                        // We have a protocol anomaly here in the LLQ definition.
-                        // Both the challenge packet from the server and the ack+answers packet have opt->u.llq.llqOp == kLLQOp_Setup.
-                        // However, we need to treat them differently:
-                        // The challenge packet has no answers in it, and tells us nothing about whether our cache entries
-                        // are still valid, so this packet should not cause us to do anything that messes with our cache.
-                        // The ack+answers packet gives us the whole truth, so we should handle it by updating our cache
-                        // to match the answers in the packet, and only the answers in the packet.
-                        *matchQuestion = q;
-                        return (oldstate == LLQ_SecondaryRequest ? uDNS_LLQ_Entire : uDNS_LLQ_Ignore);
-                    }
-                }
-            }
-        }
-        mDNSCoreResetRecord(m);
-    }
-    *matchQuestion = mDNSNULL;
-    return uDNS_LLQ_Not;
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-// Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.)
-struct TCPSocket_struct { mDNSIPPort port; TCPSocketFlags flags; /* ... */ };
-
-// tcpCallback is called to handle events (e.g. connection opening and data reception) on TCP connections for
-// Private DNS operations -- private queries, private LLQs, private record updates and private service updates
-mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err)
-{
-    tcpInfo_t *tcpInfo = (tcpInfo_t *)context;
-    mDNSBool closed  = mDNSfalse;
-    mDNS      *m       = tcpInfo->m;
-    DNSQuestion *const q = tcpInfo->question;
-    tcpInfo_t **backpointer =
-        q                 ? &q->tcp :
-        tcpInfo->rr       ? &tcpInfo->rr->tcp : mDNSNULL;
-    if (backpointer && *backpointer != tcpInfo)
-        LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p rr %p",
-               mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, q, tcpInfo->rr);
-
-    if (err) goto exit;
-
-    if (ConnectionEstablished)
-    {
-        mDNSu8    *end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
-        DomainAuthInfo *AuthInfo;
-
-        // Defensive coding for <rdar://problem/5546824> Crash in mDNSResponder at GetAuthInfoForName_internal + 366
-        // Don't know yet what's causing this, but at least we can be cautious and try to avoid crashing if we find our pointers in an unexpected state
-        if (tcpInfo->rr && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage)
-            LogMsg("tcpCallback: ERROR: tcpInfo->rr->resrec.name %p != &tcpInfo->rr->namestorage %p",
-                   tcpInfo->rr->resrec.name, &tcpInfo->rr->namestorage);
-        if (tcpInfo->rr  && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage) return;
-
-        AuthInfo =  tcpInfo->rr  ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name)         : mDNSNULL;
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-     // connection is established - send the message
-        if (q && q->LongLived && q->state == LLQ_Established)
-        {
-            // Lease renewal over TCP, resulting from opening a TCP connection in sendLLQRefresh
-            end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
-        }
-        else if (q && q->LongLived && q->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort) && !mDNSIPPortIsZero(q->servPort))
-        {
-            // Notes:
-            // If we have a NAT port mapping, ExternalPort is the external port
-            // If we have a routable address so we don't need a port mapping, ExternalPort is the same as our own internal port
-            // If we need a NAT port mapping but can't get one, then ExternalPort is zero
-            LLQOptData llqData;         // set llq rdata
-            llqData.vers  = kLLQ_Vers;
-            llqData.llqOp = kLLQOp_Setup;
-            llqData.err   = GetLLQEventPort(m, &tcpInfo->Addr); // We're using TCP; tell server what UDP port to send notifications to
-            LogInfo("tcpCallback: eventPort %d", llqData.err);
-            llqData.id    = zeroOpaque64;
-            llqData.llqlease = kLLQ_DefLease;
-            InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags);
-            end = putLLQ(&tcpInfo->request, tcpInfo->request.data, q, &llqData);
-            if (!end) { LogMsg("ERROR: tcpCallback - putLLQ"); err = mStatus_UnknownErr; goto exit; }
-            AuthInfo = q->AuthInfo;     // Need to add TSIG to this message
-            q->ntries = 0; // Reset ntries so that tcp/tls connection failures don't affect sendChallengeResponse failures
-        }
-        else
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-            if (q)
-        {
-            mDNSOpaque16 HeaderFlags = uQueryFlags;
-
-            // LLQ Polling mode or non-LLQ uDNS over TCP
-            InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, HeaderFlags);
-            end = putQuestion(&tcpInfo->request, tcpInfo->request.data, tcpInfo->request.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
-
-            AuthInfo = q->AuthInfo;     // Need to add TSIG to this message
-        }
-
-        err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, sock, mDNSNULL, &tcpInfo->Addr, tcpInfo->Port, AuthInfo, mDNSfalse);
-        if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %d", err); err = mStatus_UnknownErr; goto exit; }
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-        if (mDNSSameIPPort(tcpInfo->Port, UnicastDNSPort))
-        {
-            bool isForCell;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            isForCell = (q && q->dnsservice && mdns_dns_service_interface_is_cellular(q->dnsservice));
-#else
-            isForCell = (q && q->qDNSServer && q->qDNSServer->isCell);
-#endif
-            dnssd_analytics_update_dns_query_size(isForCell, dns_transport_Do53, (uint32_t)(end - (mDNSu8 *)&tcpInfo->request));
-        }
-#endif
-
-        // Record time we sent this question
-        if (q)
-        {
-            mDNS_Lock(m);
-            q->LastQTime = m->timenow;
-            if (q->ThisQInterval < (256 * mDNSPlatformOneSecond))   // Now we have a TCP connection open, make sure we wait at least 256 seconds before retrying
-                q->ThisQInterval = (256 * mDNSPlatformOneSecond);
-            SetNextQueryTime(m, q);
-            mDNS_Unlock(m);
-        }
-    }
-    else
-    {
-        long n;
-        const mDNSBool Read_replylen = (tcpInfo->nread < 2);  // Do we need to read the replylen field first?
-        if (Read_replylen)         // First read the two-byte length preceeding the DNS message
-        {
-            mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replylen;
-            n = mDNSPlatformReadTCP(sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed);
-            if (n < 0)
-            {
-                LogMsg("ERROR: tcpCallback - attempt to read message length failed (%d)", n);
-                err = mStatus_ConnFailed;
-                goto exit;
-            }
-            else if (closed)
-            {
-                // It's perfectly fine for this socket to close after the first reply. The server might
-                // be sending gratuitous replies using UDP and doesn't have a need to leave the TCP socket open.
-                // We'll only log this event if we've never received a reply before.
-                // BIND 9 appears to close an idle connection after 30 seconds.
-                if (tcpInfo->numReplies == 0)
-                {
-                    LogMsg("ERROR: socket closed prematurely tcpInfo->nread = %d", tcpInfo->nread);
-                    err = mStatus_ConnFailed;
-                    goto exit;
-                }
-                else
-                {
-                    // Note that we may not be doing the best thing if an error occurs after we've sent a second request
-                    // over this tcp connection.  That is, we only track whether we've received at least one response
-                    // which may have been to a previous request sent over this tcp connection.
-                    if (backpointer) *backpointer = mDNSNULL; // Clear client backpointer FIRST so we don't risk double-disposing our tcpInfo_t
-                    DisposeTCPConn(tcpInfo);
-                    return;
-                }
-            }
-
-            tcpInfo->nread += n;
-            if (tcpInfo->nread < 2) goto exit;
-
-            tcpInfo->replylen = (mDNSu16)((mDNSu16)lenptr[0] << 8 | lenptr[1]);
-            if (tcpInfo->replylen < sizeof(DNSMessageHeader))
-            { LogMsg("ERROR: tcpCallback - length too short (%d bytes)", tcpInfo->replylen); err = mStatus_UnknownErr; goto exit; }
-
-            tcpInfo->reply = (DNSMessage *) mDNSPlatformMemAllocate(tcpInfo->replylen);
-            if (!tcpInfo->reply) { LogMsg("ERROR: tcpCallback - malloc failed"); err = mStatus_NoMemoryErr; goto exit; }
-        }
-
-        n = mDNSPlatformReadTCP(sock, ((char *)tcpInfo->reply) + (tcpInfo->nread - 2), tcpInfo->replylen - (tcpInfo->nread - 2), &closed);
-
-        if (n < 0)
-        {
-            // If this is our only read for this invokation, and it fails, then that's bad.
-            // But if we did successfully read some or all of the replylen field this time through,
-            // and this is now our second read from the socket, then it's expected that sometimes
-            // there may be no more data present, and that's perfectly okay.
-            // Assuming failure of the second read is a problem is what caused this bug:
-            // <rdar://problem/15043194> mDNSResponder fails to read DNS over TCP packet correctly
-            if (!Read_replylen) { LogMsg("ERROR: tcpCallback - read returned %d", n); err = mStatus_ConnFailed; }
-            goto exit;
-        }
-        else if (closed)
-        {
-            if (tcpInfo->numReplies == 0)
-            {
-                LogMsg("ERROR: socket closed prematurely tcpInfo->nread = %d", tcpInfo->nread);
-                err = mStatus_ConnFailed;
-                goto exit;
-            }
-            else
-            {
-                // Note that we may not be doing the best thing if an error occurs after we've sent a second request
-                // over this tcp connection.  That is, we only track whether we've received at least one response
-                // which may have been to a previous request sent over this tcp connection.
-                if (backpointer) *backpointer = mDNSNULL; // Clear client backpointer FIRST so we don't risk double-disposing our tcpInfo_t
-                DisposeTCPConn(tcpInfo);
-                return;
-            }
-        }
-
-        tcpInfo->nread += n;
-
-        if ((tcpInfo->nread - 2) == tcpInfo->replylen)
-        {
-            mDNSBool tls;
-            DNSMessage *reply = tcpInfo->reply;
-            mDNSu8     *end   = (mDNSu8 *)tcpInfo->reply + tcpInfo->replylen;
-            mDNSAddr Addr  = tcpInfo->Addr;
-            mDNSIPPort Port  = tcpInfo->Port;
-            mDNSIPPort srcPort = zeroIPPort;
-            tcpInfo->numReplies++;
-            tcpInfo->reply    = mDNSNULL;   // Detach reply buffer from tcpInfo_t, to make sure client callback can't cause it to be disposed
-            tcpInfo->nread    = 0;
-            tcpInfo->replylen = 0;
-
-            // If we're going to dispose this connection, do it FIRST, before calling client callback
-            // Note: Sleep code depends on us clearing *backpointer here -- it uses the clearing of rr->tcp
-            // as the signal that the DNS deregistration operation with the server has completed, and the machine may now sleep
-            // If we clear the tcp pointer in the question, mDNSCoreReceiveResponse cannot find a matching question. Hence
-            // we store the minimal information i.e., the source port of the connection in the question itself.
-            // Dereference sock before it is disposed in DisposeTCPConn below.
-
-            if (sock->flags & kTCPSocketFlags_UseTLS) tls = mDNStrue;
-            else tls = mDNSfalse;
-
-            if (q && q->tcp) {srcPort = q->tcp->SrcPort; q->tcpSrcPort = srcPort;}
-
-            if (backpointer)
-                if (!q || !q->LongLived || m->SleepState)
-                { *backpointer = mDNSNULL; DisposeTCPConn(tcpInfo); }
-
-            mDNSCoreReceive(m, reply, end, &Addr, Port, tls ? (mDNSAddr *)1 : mDNSNULL, srcPort, 0);
-            // USE CAUTION HERE: Invoking mDNSCoreReceive may have caused the environment to change, including canceling this operation itself
-
-            mDNSPlatformMemFree(reply);
-            return;
-        }
-    }
-
-exit:
-
-    if (err)
-    {
-        // Clear client backpointer FIRST -- that way if one of the callbacks cancels its operation
-        // we won't end up double-disposing our tcpInfo_t
-        if (backpointer) *backpointer = mDNSNULL;
-
-        mDNS_Lock(m);       // Need to grab the lock to get m->timenow
-
-        if (q)
-        {
-            if (q->ThisQInterval == 0)
-            {
-                // We get here when we fail to establish a new TCP/TLS connection that would have been used for a new LLQ request or an LLQ renewal.
-                // Note that ThisQInterval is also zero when sendChallengeResponse resends the LLQ request on an extant TCP/TLS connection.
-                q->LastQTime = m->timenow;
-                if (q->LongLived)
-                {
-                    // We didn't get the chance to send our request packet before the TCP/TLS connection failed.
-                    // We want to retry quickly, but want to back off exponentially in case the server is having issues.
-                    // Since ThisQInterval was 0, we can't just multiply by QuestionIntervalStep, we must track the number
-                    // of TCP/TLS connection failures using ntries.
-                    mDNSu32 count = q->ntries + 1; // want to wait at least 1 second before retrying
-
-                    q->ThisQInterval = InitialQuestionInterval;
-
-                    for (; count; count--)
-                        q->ThisQInterval *= QuestionIntervalStep;
-
-                    if (q->ThisQInterval > LLQ_POLL_INTERVAL)
-                        q->ThisQInterval = LLQ_POLL_INTERVAL;
-                    else
-                        q->ntries++;
-
-                    LogMsg("tcpCallback: stream connection for LLQ %##s (%s) failed %d times, retrying in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ntries, q->ThisQInterval);
-                }
-                else
-                {
-                    q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
-                    LogMsg("tcpCallback: stream connection for %##s (%s) failed, retrying in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
-                }
-                SetNextQueryTime(m, q);
-            }
-            else if (NextQSendTime(q) - m->timenow > (q->LongLived ? LLQ_POLL_INTERVAL : MAX_UCAST_POLL_INTERVAL))
-            {
-                // If we get an error and our next scheduled query for this question is more than the max interval from now,
-                // reset the next query to ensure we wait no longer the maximum interval from now before trying again.
-                q->LastQTime     = m->timenow;
-                q->ThisQInterval = q->LongLived ? LLQ_POLL_INTERVAL : MAX_UCAST_POLL_INTERVAL;
-                SetNextQueryTime(m, q);
-                LogMsg("tcpCallback: stream connection for %##s (%s) failed, retrying in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
-            }
-
-            // We're about to dispose of the TCP connection, so we must reset the state to retry over TCP/TLS
-            // because sendChallengeResponse will send the query via UDP if we don't have a tcp pointer.
-            // Resetting to LLQ_InitialRequest will cause uDNS_CheckCurrentQuestion to call startLLQHandshake, which
-            // will attempt to establish a new tcp connection.
-            if (q->LongLived && q->state == LLQ_SecondaryRequest)
-                q->state = LLQ_InitialRequest;
-
-            // ConnFailed may happen if the server sends a TCP reset or TLS fails, in which case we want to retry establishing the LLQ
-            // quickly rather than switching to polling mode.  This case is handled by the above code to set q->ThisQInterval just above.
-            // If the error isn't ConnFailed, then the LLQ is in bad shape, so we switch to polling mode.
-            if (err != mStatus_ConnFailed)
-            {
-                if (q->LongLived && q->state != LLQ_Poll) StartLLQPolling(m, q);
-            }
-        }
-
-        mDNS_Unlock(m);
-
-        DisposeTCPConn(tcpInfo);
-    }
-}
-
-mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-                                 TCPSocketFlags flags, const mDNSAddr *const Addr, const mDNSIPPort Port, domainname *hostname,
-                                 DNSQuestion *const question, AuthRecord *const rr)
-{
-    mStatus err;
-    mDNSIPPort srcport = zeroIPPort;
-    tcpInfo_t *info;
-    mDNSBool useBackgroundTrafficClass;
-
-    useBackgroundTrafficClass = question ? question->UseBackgroundTraffic : mDNSfalse;
-
-    if ((flags & kTCPSocketFlags_UseTLS) && (!hostname || !hostname->c[0]))
-    { LogMsg("MakeTCPConn: TLS connection being setup with NULL hostname"); return mDNSNULL; }
-
-    info = (tcpInfo_t *) mDNSPlatformMemAllocateClear(sizeof(*info));
-    if (!info) { LogMsg("ERROR: MakeTCP - memallocate failed"); return(mDNSNULL); }
-
-    if (msg)
-    {
-        const mDNSu8 *const start = (const mDNSu8 *)msg;
-        if ((end < start) || ((end - start) > (int)sizeof(info->request)))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "MakeTCPConn: invalid DNS message pointers -- msg: %p, end: %p", msg, end);
-            mDNSPlatformMemFree(info);
-            return mDNSNULL;
-        }
-        info->requestLen = (int)(end - start);
-        mDNSPlatformMemCopy(&info->request, msg, info->requestLen);
-    }
-
-    info->m          = m;
-    info->sock       = mDNSPlatformTCPSocket(flags, Addr->type, &srcport, hostname, useBackgroundTrafficClass);
-    info->question   = question;
-    info->rr         = rr;
-    info->Addr       = *Addr;
-    info->Port       = Port;
-    info->reply      = mDNSNULL;
-    info->replylen   = 0;
-    info->nread      = 0;
-    info->numReplies = 0;
-    info->SrcPort = srcport;
-
-    if (!info->sock) { LogMsg("MakeTCPConn: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
-    mDNSPlatformSetSocktOpt(info->sock, mDNSTransport_TCP, Addr->type, question);
-    err = mDNSPlatformTCPConnect(info->sock, Addr, Port, (question ? question->InterfaceID : mDNSNULL), tcpCallback, info);
-
-    // Probably suboptimal here.
-    // Instead of returning mDNSNULL here on failure, we should probably invoke the callback with an error code.
-    // That way clients can put all the error handling and retry/recovery code in one place,
-    // instead of having to handle immediate errors in one place and async errors in another.
-    // Also: "err == mStatus_ConnEstablished" probably never happens.
-
-    // Don't need to log "connection failed" in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
-    if      (err == mStatus_ConnEstablished) { tcpCallback(info->sock, info, mDNStrue, mStatus_NoError); }
-    else if (err != mStatus_ConnPending    ) { LogInfo("MakeTCPConn: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
-    return(info);
-}
-
-mDNSexport void DisposeTCPConn(struct tcpInfo_t *tcp)
-{
-    mDNSPlatformTCPCloseConnection(tcp->sock);
-    if (tcp->reply) mDNSPlatformMemFree(tcp->reply);
-    mDNSPlatformMemFree(tcp);
-}
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-// Lock must be held
-mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
-{
-    // States prior to LLQ_InitialRequest should not react to NAT Mapping changes.
-    // startLLQHandshake is never called with q->state < LLQ_InitialRequest except
-    // from LLQNATCallback.   When we are actually trying to do LLQ, then q->state will
-    // be equal to or greater than LLQ_InitialRequest when LLQNATCallback calls
-    // startLLQHandshake.
-    if (q->state < LLQ_InitialRequest)
-    {
-        return;
-    }
-
-    if (m->LLQNAT.clientContext != mDNSNULL) // LLQNAT just started, give it some time
-    {
-        LogInfo("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);    // Retry in approx 15 minutes
-        q->LastQTime = m->timenow;
-        SetNextQueryTime(m, q);
-        return;
-    }
-
-    // Either we don't have {PCP, NAT-PMP, UPnP/IGD} support (ExternalPort is zero) or behind a Double NAT that may or
-    // may not have {PCP, NAT-PMP, UPnP/IGD} support (NATResult is non-zero)
-    if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort) || m->LLQNAT.Result)
-    {
-        LogInfo("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s) External Port %d, NAT Result %d",
-                q->qname.c, DNSTypeName(q->qtype), mDNSVal16(m->LLQNAT.ExternalPort), m->LLQNAT.Result);
-        StartLLQPolling(m, q);
-        return;
-    }
-
-    if (mDNSIPPortIsZero(q->servPort))
-    {
-        debugf("startLLQHandshake: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);    // Retry in approx 15 minutes
-        q->LastQTime     = m->timenow;
-        SetNextQueryTime(m, q);
-        q->servAddr = zeroAddr;
-        // We know q->servPort is zero because of check above
-        if (q->nta) CancelGetZoneData(m, q->nta);
-        q->nta = StartGetZoneData(m, &q->qname, ZoneServiceLLQ, LLQGotZoneData, q);
-        return;
-    }
-
-    debugf("startLLQHandshake: m->AdvertisedV4 %#a%s Server %#a:%d%s %##s (%s)",
-           &m->AdvertisedV4,                     mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC 1918)" : "",
-           &q->servAddr, mDNSVal16(q->servPort), mDNSAddrIsRFC1918(&q->servAddr)             ? " (RFC 1918)" : "",
-           q->qname.c, DNSTypeName(q->qtype));
-
-    if (q->ntries++ >= kLLQ_MAX_TRIES)
-    {
-        LogMsg("startLLQHandshake: %d failed attempts for LLQ %##s Polling.", kLLQ_MAX_TRIES, q->qname.c);
-        StartLLQPolling(m, q);
-    }
-    else
-    {
-        mDNSu8 *end;
-        LLQOptData llqData;
-
-        // set llq rdata
-        llqData.vers  = kLLQ_Vers;
-        llqData.llqOp = kLLQOp_Setup;
-        llqData.err   = LLQErr_NoError; // Don't need to tell server UDP notification port when sending over UDP
-        llqData.id    = zeroOpaque64;
-        llqData.llqlease = kLLQ_DefLease;
-
-        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-        end = putLLQ(&m->omsg, m->omsg.data, q, &llqData);
-        if (!end) { LogMsg("ERROR: startLLQHandshake - putLLQ"); StartLLQPolling(m,q); return; }
-
-        mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, mDNSNULL, q->LocalSocket, &q->servAddr, q->servPort , mDNSNULL, mDNSfalse);
-
-        // update question state
-        q->state         = LLQ_InitialRequest;
-        q->ReqLease      = kLLQ_DefLease;
-        q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond);
-        q->LastQTime     = m->timenow;
-        SetNextQueryTime(m, q);
-    }
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-// forward declaration so GetServiceTarget can do reverse lookup if needed
-mDNSlocal void GetStaticHostname(mDNS *m);
-
-mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr)
-{
-    debugf("GetServiceTarget %##s", rr->resrec.name->c);
-
-    if (!rr->AutoTarget)        // If not automatically tracking this host's current name, just return the existing target
-        return(&rr->resrec.rdata->u.srv.target);
-    else
-    {
-        {
-            const int srvcount = CountLabels(rr->resrec.name);
-            HostnameInfo *besthi = mDNSNULL, *hi;
-            int best = 0;
-            for (hi = m->Hostnames; hi; hi = hi->next)
-                if (hi->arv4.state == regState_Registered || hi->arv4.state == regState_Refresh ||
-                    hi->arv6.state == regState_Registered || hi->arv6.state == regState_Refresh)
-                {
-                    int x, hostcount = CountLabels(&hi->fqdn);
-                    for (x = hostcount < srvcount ? hostcount : srvcount; x > 0 && x > best; x--)
-                        if (SameDomainName(SkipLeadingLabels(rr->resrec.name, srvcount - x), SkipLeadingLabels(&hi->fqdn, hostcount - x)))
-                        { best = x; besthi = hi; }
-                }
-
-            if (besthi) return(&besthi->fqdn);
-        }
-        if (m->StaticHostname.c[0]) return(&m->StaticHostname);
-        else GetStaticHostname(m); // asynchronously do reverse lookup for primary IPv4 address
-        LogInfo("GetServiceTarget: Returning NULL for %s", ARDisplayString(m, rr));
-        return(mDNSNULL);
-    }
-}
-
-mDNSlocal const domainname *PUBLIC_UPDATE_SERVICE_TYPE         = (const domainname*)"\x0B_dns-update"     "\x04_udp";
-mDNSlocal const domainname *PUBLIC_LLQ_SERVICE_TYPE            = (const domainname*)"\x08_dns-llq"        "\x04_udp";
-
-mDNSlocal const domainname *PRIVATE_UPDATE_SERVICE_TYPE        = (const domainname*)"\x0F_dns-update-tls" "\x04_tcp";
-mDNSlocal const domainname *PRIVATE_QUERY_SERVICE_TYPE         = (const domainname*)"\x0E_dns-query-tls"  "\x04_tcp";
-mDNSlocal const domainname *PRIVATE_LLQ_SERVICE_TYPE           = (const domainname*)"\x0C_dns-llq-tls"    "\x04_tcp";
-mDNSlocal const domainname *DNS_PUSH_NOTIFICATION_SERVICE_TYPE = (const domainname*)"\x0D_dns-push-tls"   "\x04_tcp";
-
-#define ZoneDataSRV(X) ( \
-        (X)->ZoneService == ZoneServiceUpdate  ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \
-        (X)->ZoneService == ZoneServiceQuery   ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE  : (const domainname*)""     ) : \
-        (X)->ZoneService == ZoneServiceLLQ     ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE    : PUBLIC_LLQ_SERVICE_TYPE   ) : \
-        (X)->ZoneService == ZoneServiceDNSPush ? DNS_PUSH_NOTIFICATION_SERVICE_TYPE : (const domainname*)"")
-
-// Forward reference: GetZoneData_StartQuery references GetZoneData_QuestionCallback, and
-// GetZoneData_QuestionCallback calls GetZoneData_StartQuery
-mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qtype);
-
-// GetZoneData_QuestionCallback is called from normal client callback context (core API calls allowed)
-mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    ZoneData *zd = (ZoneData*)question->QuestionContext;
-
-    debugf("GetZoneData_QuestionCallback: %s %s", AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer));
-
-    if (!AddRecord) return;                                             // Don't care about REMOVE events
-    if (AddRecord == QC_addnocache && answer->rdlength == 0) return;    // Don't care about transient failure indications
-    if (answer->rrtype != question->qtype) return;                      // Don't care about CNAMEs
-
-    if (answer->rrtype == kDNSType_SOA)
-    {
-        debugf("GetZoneData GOT SOA %s", RRDisplayString(m, answer));
-        mDNS_StopQuery(m, question);
-        if (question->ThisQInterval != -1)
-            LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
-        if (answer->rdlength)
-        {
-            AssignDomainName(&zd->ZoneName, answer->name);
-            zd->ZoneClass = answer->rrclass;
-            GetZoneData_StartQuery(m, zd, kDNSType_SRV);
-        }
-        else if (zd->CurrentSOA->c[0])
-        {
-            zd->CurrentSOA = (domainname *)(zd->CurrentSOA->c + zd->CurrentSOA->c[0]+1);
-            AssignDomainName(&zd->question.qname, zd->CurrentSOA);
-            GetZoneData_StartQuery(m, zd, kDNSType_SOA);
-        }
-        else
-        {
-            LogInfo("GetZoneData recursed to root label of %##s without finding SOA", zd->ChildName.c);
-            zd->ZoneDataCallback(m, mStatus_NoSuchNameErr, zd);
-        }
-    }
-    else if (answer->rrtype == kDNSType_SRV)
-    {
-        debugf("GetZoneData GOT SRV %s", RRDisplayString(m, answer));
-        mDNS_StopQuery(m, question);
-        if (question->ThisQInterval != -1)
-            LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
-// Right now we don't want to fail back to non-encrypted operations
-// If the AuthInfo has the AutoTunnel field set, then we want private or nothing
-// <rdar://problem/5687667> BTMM: Don't fallback to unencrypted operations when SRV lookup fails
-#if 0
-        if (!answer->rdlength && zd->ZonePrivate && zd->ZoneService != ZoneServiceQuery)
-        {
-            zd->ZonePrivate = mDNSfalse;    // Causes ZoneDataSRV() to yield a different SRV name when building the query
-            GetZoneData_StartQuery(m, zd, kDNSType_SRV);        // Try again, non-private this time
-        }
-        else
-#endif
-        {
-            if (answer->rdlength)
-            {
-                AssignDomainName(&zd->Host, &answer->rdata->u.srv.target);
-                zd->Port = answer->rdata->u.srv.port;
-                // The MakeTCPConn path, which is used by everything but DNS Push, won't work at all for
-                // IPv6.  This should be fixed for all cases we care about, but for now we make an exception
-                // for Push notifications: we do not look up the a record here, but rather rely on the DSO
-                // infrastructure to do a GetAddrInfo call on the name and try each IP address in sequence
-                // until one connects.  We can't do this for the other use cases because this is in the DSO
-                // code, not in MakeTCPConn.  Ultimately the fix for this is to use Network Framework to do
-                // the connection establishment for all of these use cases.
-                //
-                // One implication of this is that if two different zones have DNS push server SRV records
-                // pointing to the same server using a different domain name, we will not see these as being
-                // the same server, and will not share the connection.   This isn't something we can easily
-                // fix, and so the advice if someone runs into this and considers it a problem should be to
-                // use the same name.
-                //
-                // Another issue with this code is that at present, we do not wait for more than one SRV
-                // record--we cancel the query as soon as the first one comes in.   This isn't ideal: it
-                // would be better to wait until we've gotten all our answers and then pick the one with
-                // the highest priority.   Of course, this is unlikely to cause an operational problem in
-                // practice, and as with the previous point, the fix is easy: figure out which server you
-                // want people to use and don't list any other servers.   Fully switching to Network
-                // Framework for this would (I think!) address this problem, or at least make it someone
-                // else's problem.
-                if (zd->ZoneService != ZoneServiceDNSPush)
-                {
-                    AssignDomainName(&zd->question.qname, &zd->Host);
-                    GetZoneData_StartQuery(m, zd, kDNSType_A);
-                }
-                else
-                {
-                    zd->ZoneDataCallback(m, mStatus_NoError, zd);
-                }
-            }
-            else
-            {
-                zd->ZonePrivate = mDNSfalse;
-                zd->Host.c[0] = 0;
-                zd->Port = zeroIPPort;
-                zd->Addr = zeroAddr;
-                // The response does not contain any record in the answer section, indicating that the SRV record with
-                // the corresponding name does not exist.
-                zd->ZoneDataCallback(m, mStatus_NoSuchRecord, zd);
-            }
-        }
-    }
-    else if (answer->rrtype == kDNSType_A)
-    {
-        debugf("GetZoneData GOT A %s", RRDisplayString(m, answer));
-        mDNS_StopQuery(m, question);
-        if (question->ThisQInterval != -1)
-            LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval);
-        zd->Addr.type  = mDNSAddrType_IPv4;
-        zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : zerov4Addr;
-        // In order to simulate firewalls blocking our outgoing TCP connections, returning immediate ICMP errors or TCP resets,
-        // the code below will make us try to connect to loopback, resulting in an immediate "port unreachable" failure.
-        // This helps us test to make sure we handle this case gracefully
-        // <rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1
-#if 0
-        zd->Addr.ip.v4.b[0] = 127;
-        zd->Addr.ip.v4.b[1] = 0;
-        zd->Addr.ip.v4.b[2] = 0;
-        zd->Addr.ip.v4.b[3] = 1;
-#endif
-        // The caller needs to free the memory when done with zone data
-        zd->ZoneDataCallback(m, mStatus_NoError, zd);
-    }
-}
-
-// GetZoneData_StartQuery is called from normal client context (lock not held, or client callback)
-mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qtype)
-{
-    if (qtype == kDNSType_SRV)
-    {
-        AssignDomainName(&zd->question.qname, ZoneDataSRV(zd));
-        AppendDomainName(&zd->question.qname, &zd->ZoneName);
-        debugf("lookupDNSPort %##s", zd->question.qname.c);
-    }
-
-    // CancelGetZoneData can get called at any time. We should stop the question if it has not been
-    // stopped already. A value of -1 for ThisQInterval indicates that the question is not active
-    // yet.
-    zd->question.ThisQInterval       = -1;
-    zd->question.InterfaceID         = mDNSInterface_Any;
-    zd->question.flags               = 0;
-    //zd->question.qname.c[0]        = 0;           // Already set
-    zd->question.qtype               = qtype;
-    zd->question.qclass              = kDNSClass_IN;
-    zd->question.LongLived           = mDNSfalse;
-    zd->question.ExpectUnique        = mDNStrue;
-    zd->question.ForceMCast          = mDNSfalse;
-    zd->question.ReturnIntermed      = mDNStrue;
-    zd->question.SuppressUnusable    = mDNSfalse;
-    zd->question.AppendSearchDomains = 0;
-    zd->question.TimeoutQuestion     = 0;
-    zd->question.WakeOnResolve       = 0;
-    zd->question.UseBackgroundTraffic = mDNSfalse;
-    zd->question.ProxyQuestion      = 0;
-    zd->question.pid                 = mDNSPlatformGetPID();
-    zd->question.euid                = 0;
-    zd->question.QuestionCallback    = GetZoneData_QuestionCallback;
-    zd->question.QuestionContext     = zd;
-
-    //LogMsg("GetZoneData_StartQuery %##s (%s) %p", zd->question.qname.c, DNSTypeName(zd->question.qtype), zd->question.Private);
-    return(mDNS_StartQuery(m, &zd->question));
-}
-
-// StartGetZoneData is an internal routine (i.e. must be called with the lock already held)
-mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *ZoneDataContext)
-{
-    ZoneData *zd = (ZoneData*) mDNSPlatformMemAllocateClear(sizeof(*zd));
-    if (!zd) { LogMsg("ERROR: StartGetZoneData - mDNSPlatformMemAllocateClear failed"); return mDNSNULL; }
-    AssignDomainName(&zd->ChildName, name);
-    zd->ZoneService      = target;
-    zd->CurrentSOA       = &zd->ChildName;
-    zd->ZoneName.c[0]    = 0;
-    zd->ZoneClass        = 0;
-    zd->Host.c[0]        = 0;
-    zd->Port             = zeroIPPort;
-    zd->Addr             = zeroAddr;
-    zd->ZonePrivate      = mDNSfalse;
-    zd->ZoneDataCallback = callback;
-    zd->ZoneDataContext  = ZoneDataContext;
-
-    zd->question.QuestionContext = zd;
-
-    mDNS_DropLockBeforeCallback();      // GetZoneData_StartQuery expects to be called from a normal callback, so we emulate that here
-    AssignDomainName(&zd->question.qname, zd->CurrentSOA);
-    GetZoneData_StartQuery(m, zd, kDNSType_SOA);
-    mDNS_ReclaimLockAfterCallback();
-
-    return zd;
-}
-
-// Returns if the question is a GetZoneData question. These questions are special in
-// that they are created internally while resolving a private query or LLQs.
-mDNSexport mDNSBool IsGetZoneDataQuestion(DNSQuestion *q)
-{
-    if (q->QuestionCallback == GetZoneData_QuestionCallback) return(mDNStrue);
-    else return(mDNSfalse);
-}
-
-// GetZoneData queries are a special case -- even if we have a key for them, we don't do them privately,
-// because that would result in an infinite loop (i.e. to do a private query we first need to get
-// the _dns-query-tls SRV record for the zone, and we can't do *that* privately because to do so
-// we'd need to already know the _dns-query-tls SRV record.
-// Also, as a general rule, we never do SOA queries privately
-mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q)  // Must be called with lock held
-{
-    if (q->QuestionCallback == GetZoneData_QuestionCallback) return(mDNSNULL);
-    if (q->qtype            == kDNSType_SOA                ) return(mDNSNULL);
-    return(GetAuthInfoForName_internal(m, &q->qname));
-}
-
-// ***************************************************************************
-// MARK: - host name and interface management
-
-mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr);
-mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr);
-mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time);
-
-// When this function is called, service record is already deregistered. We just
-// have to deregister the PTR and TXT records.
-mDNSlocal void UpdateAllServiceRecords(mDNS *const m, AuthRecord *rr, mDNSBool reg)
-{
-    AuthRecord *r, *srvRR;
-
-    if (rr->resrec.rrtype != kDNSType_SRV) { LogMsg("UpdateAllServiceRecords:ERROR!! ResourceRecord not a service record %s", ARDisplayString(m, rr)); return; }
-
-    if (reg && rr->state == regState_NoTarget) { LogMsg("UpdateAllServiceRecords:ERROR!! SRV record %s in noTarget state during registration", ARDisplayString(m, rr)); return; }
-
-    LogInfo("UpdateAllServiceRecords: ResourceRecord %s", ARDisplayString(m, rr));
-
-    for (r = m->ResourceRecords; r; r=r->next)
-    {
-        if (!AuthRecord_uDNS(r)) continue;
-        srvRR = mDNSNULL;
-        if (r->resrec.rrtype == kDNSType_PTR)
-            srvRR = r->Additional1;
-        else if (r->resrec.rrtype == kDNSType_TXT)
-            srvRR = r->DependentOn;
-        if (srvRR && srvRR->resrec.rrtype != kDNSType_SRV)
-            LogMsg("UpdateAllServiceRecords: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
-        if (srvRR == rr)
-        {
-            if (!reg)
-            {
-                LogInfo("UpdateAllServiceRecords: deregistering %s", ARDisplayString(m, r));
-                r->SRVChanged = mDNStrue;
-                r->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-                r->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-                r->state = regState_DeregPending;
-            }
-            else
-            {
-                // Clearing SRVchanged is a safety measure. If our pevious dereg never
-                // came back and we had a target change, we are starting fresh
-                r->SRVChanged = mDNSfalse;
-                // if it is already registered or in the process of registering, then don't
-                // bother re-registering. This happens today for non-BTMM domains where the
-                // TXT and PTR get registered before SRV records because of the delay in
-                // getting the port mapping. There is no point in re-registering the TXT
-                // and PTR records.
-                if ((r->state == regState_Registered) ||
-                    (r->state == regState_Pending && r->nta && !mDNSIPv4AddressIsZero(r->nta->Addr.ip.v4)))
-                    LogInfo("UpdateAllServiceRecords: not registering %s, state %d", ARDisplayString(m, r), r->state);
-                else
-                {
-                    LogInfo("UpdateAllServiceRecords: registering %s, state %d", ARDisplayString(m, r), r->state);
-                    ActivateUnicastRegistration(m, r);
-                }
-            }
-        }
-    }
-}
-
-// Called in normal client context (lock not held)
-// Currently only supports SRV records for nat mapping
-mDNSlocal void CompleteRecordNatMap(mDNS *m, NATTraversalInfo *n)
-{
-    const domainname *target;
-    domainname *srvt;
-    AuthRecord *rr = (AuthRecord *)n->clientContext;
-    debugf("SRVNatMap complete %.4a IntPort %u ExternalPort %u NATLease %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease);
-
-    if (!rr) { LogMsg("CompleteRecordNatMap called with unknown AuthRecord object"); return; }
-    if (!n->NATLease) { LogMsg("CompleteRecordNatMap No NATLease for %s", ARDisplayString(m, rr)); return; }
-
-    if (rr->resrec.rrtype != kDNSType_SRV) {LogMsg("CompleteRecordNatMap: Not a service record %s", ARDisplayString(m, rr)); return; }
-
-    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) { LogInfo("CompleteRecordNatMap called for %s, Service deregistering", ARDisplayString(m, rr)); return; }
-
-    if (rr->state == regState_DeregPending) { LogInfo("CompleteRecordNatMap called for %s, record in DeregPending", ARDisplayString(m, rr)); return; }
-
-    // As we free the zone info after registering/deregistering with the server (See hndlRecordUpdateReply),
-    // we need to restart the get zone data and nat mapping request to get the latest mapping result as we can't handle it
-    // at this moment. Restart from the beginning.
-    if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
-    {
-        LogInfo("CompleteRecordNatMap called for %s but no zone information!", ARDisplayString(m, rr));
-        // We need to clear out the NATinfo state so that it will result in re-acquiring the mapping
-        // and hence this callback called again.
-        if (rr->NATinfo.clientContext)
-        {
-            mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-            rr->NATinfo.clientContext = mDNSNULL;
-        }
-        rr->state = regState_Pending;
-        rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-        rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-        return;
-    }
-
-    mDNS_Lock(m);
-    // Reevaluate the target always as Target could have changed while
-    // we were getting the port mapping (See UpdateOneSRVRecord)
-    target = GetServiceTarget(m, rr);
-    srvt = GetRRDomainNameTarget(&rr->resrec);
-    if (!target || target->c[0] == 0 || mDNSIPPortIsZero(n->ExternalPort))
-    {
-        if (target && target->c[0])
-            LogInfo("CompleteRecordNatMap - Target %##s for ResourceRecord %##s, ExternalPort %d", target->c, rr->resrec.name->c, mDNSVal16(n->ExternalPort));
-        else
-            LogInfo("CompleteRecordNatMap - no target for %##s, ExternalPort %d", rr->resrec.name->c, mDNSVal16(n->ExternalPort));
-        if (srvt) srvt->c[0] = 0;
-        rr->state = regState_NoTarget;
-        rr->resrec.rdlength = rr->resrec.rdestimate = 0;
-        mDNS_Unlock(m);
-        UpdateAllServiceRecords(m, rr, mDNSfalse);
-        return;
-    }
-    LogInfo("CompleteRecordNatMap - Target %##s for ResourceRecord %##s, ExternalPort %d", target->c, rr->resrec.name->c, mDNSVal16(n->ExternalPort));
-    // This function might get called multiple times during a network transition event. Previosuly, we could
-    // have put the SRV record in NoTarget state above and deregistered all the other records. When this
-    // function gets called again with a non-zero ExternalPort, we need to set the target and register the
-    // other records again.
-    if (srvt && !SameDomainName(srvt, target))
-    {
-        AssignDomainName(srvt, target);
-        SetNewRData(&rr->resrec, mDNSNULL, 0);      // Update rdlength, rdestimate, rdatahash
-    }
-
-    // SRVChanged is set when when the target of the SRV record changes (See UpdateOneSRVRecord).
-    // As a result of the target change, we might register just that SRV Record if it was
-    // previously registered and we have a new target OR deregister SRV (and the associated
-    // PTR/TXT records) if we don't have a target anymore. When we get a response from the server,
-    // SRVChanged state tells that we registered/deregistered because of a target change
-    // and hence handle accordingly e.g., if we deregistered, put the records in NoTarget state OR
-    // if we registered then put it in Registered state.
-    //
-    // Here, we are registering all the records again from the beginning. Treat this as first time
-    // registration rather than a temporary target change.
-    rr->SRVChanged = mDNSfalse;
-
-    // We want IsRecordMergeable to check whether it is a record whose update can be
-    // sent with others. We set the time before we call IsRecordMergeable, so that
-    // it does not fail this record based on time. We are interested in other checks
-    // at this time
-    rr->state = regState_Pending;
-    rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-    rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-    if (IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME))
-        // Delay the record registration by MERGE_DELAY_TIME so that we can merge them
-        // into one update
-        rr->LastAPTime += MERGE_DELAY_TIME;
-    mDNS_Unlock(m);
-    // We call this always even though it may not be necessary always e.g., normal registration
-    // process where TXT and PTR gets registered followed by the SRV record after it gets
-    // the port mapping. In that case, UpdateAllServiceRecords handles the optimization. The
-    // update of TXT and PTR record is required if we entered noTargetState before as explained
-    // above.
-    UpdateAllServiceRecords(m, rr, mDNStrue);
-}
-
-mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
-{
-    const mDNSu8 *p;
-    mDNSu8 protocol;
-
-    if (rr->resrec.rrtype != kDNSType_SRV)
-    {
-        LogInfo("StartRecordNatMap: Resource Record %##s type %d, not supported", rr->resrec.name->c, rr->resrec.rrtype);
-        return;
-    }
-    p = rr->resrec.name->c;
-    //Assume <Service Instance>.<App Protocol>.<Transport protocol>.<Name>
-    // Skip the first two labels to get to the transport protocol
-    if (p[0]) p += 1 + p[0];
-    if (p[0]) p += 1 + p[0];
-    if      (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocol = NATOp_MapTCP;
-    else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocol = NATOp_MapUDP;
-    else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; }
-
-    //LogMsg("StartRecordNatMap: clientContext %p IntPort %d srv.port %d %s",
-    //  rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr));
-    if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-    rr->NATinfo.Protocol       = protocol;
-
-    // Shouldn't be trying to set IntPort here --
-    // BuildUpdateMessage overwrites srs->RR_SRV.resrec.rdata->u.srv.port with external (mapped) port number
-    rr->NATinfo.IntPort        = rr->resrec.rdata->u.srv.port;
-    rr->NATinfo.RequestedPort  = rr->resrec.rdata->u.srv.port;
-    rr->NATinfo.NATLease       = 0;     // Request default lease
-    rr->NATinfo.clientCallback = CompleteRecordNatMap;
-    rr->NATinfo.clientContext  = rr;
-    mDNS_StartNATOperation_internal(m, &rr->NATinfo);
-}
-
-// Unlink an Auth Record from the m->ResourceRecords list.
-// When a resource record enters regState_NoTarget initially, mDNS_Register_internal
-// does not initialize completely e.g., it cannot check for duplicates etc. The resource
-// record is temporarily left in the ResourceRecords list so that we can initialize later
-// when the target is resolvable. Similarly, when host name changes, we enter regState_NoTarget
-// and we do the same.
-
-// This UnlinkResourceRecord routine is very worrying. It bypasses all the normal cleanup performed
-// by mDNS_Deregister_internal and just unceremoniously cuts the record from the active list.
-// This is why re-regsitering this record was producing syslog messages like this:
-// "Error! Tried to add a NAT traversal that's already in the active list"
-// Right now UnlinkResourceRecord is fortunately only called by RegisterAllServiceRecords,
-// which then immediately calls mDNS_Register_internal to re-register the record, which probably
-// masked more serious problems. Any other use of UnlinkResourceRecord is likely to lead to crashes.
-// For now we'll workaround that specific problem by explicitly calling mDNS_StopNATOperation_internal,
-// but long-term we should either stop cancelling the record registration and then re-registering it,
-// or if we really do need to do this for some reason it should be done via the usual
-// mDNS_Deregister_internal path instead of just cutting the record from the list.
-
-mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
-{
-    AuthRecord **list = &m->ResourceRecords;
-    while (*list && *list != rr) list = &(*list)->next;
-    if (*list)
-    {
-        *list = rr->next;
-        rr->next = mDNSNULL;
-
-        // Temporary workaround to cancel any active NAT mapping operation
-        if (rr->NATinfo.clientContext)
-        {
-            mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-            rr->NATinfo.clientContext = mDNSNULL;
-            if (rr->resrec.rrtype == kDNSType_SRV) rr->resrec.rdata->u.srv.port = rr->NATinfo.IntPort;
-        }
-
-        return(mStatus_NoError);
-    }
-    LogMsg("UnlinkResourceRecord:ERROR!! - no such active record %##s", rr->resrec.name->c);
-    return(mStatus_NoSuchRecord);
-}
-
-// We need to go through mDNS_Register again as we did not complete the
-// full initialization last time e.g., duplicate checks.
-// After we register, we will be in regState_GetZoneData.
-mDNSlocal void RegisterAllServiceRecords(mDNS *const m, AuthRecord *rr)
-{
-    LogInfo("RegisterAllServiceRecords: Service Record %##s", rr->resrec.name->c);
-    // First Register the service record, we do this differently from other records because
-    // when it entered NoTarget state, it did not go through complete initialization
-    rr->SRVChanged = mDNSfalse;
-    UnlinkResourceRecord(m, rr);
-    mDNS_Register_internal(m, rr);
-    // Register the other records
-    UpdateAllServiceRecords(m, rr, mDNStrue);
-}
-
-// Called with lock held
-mDNSlocal void UpdateOneSRVRecord(mDNS *m, AuthRecord *rr)
-{
-    // Target change if:
-    // We have a target and were previously waiting for one, or
-    // We had a target and no longer do, or
-    // The target has changed
-
-    domainname *curtarget = &rr->resrec.rdata->u.srv.target;
-    const domainname *const nt = GetServiceTarget(m, rr);
-    const domainname *const newtarget = nt ? nt : (domainname*)"";
-    mDNSBool TargetChanged = (newtarget->c[0] && rr->state == regState_NoTarget) || !SameDomainName(curtarget, newtarget);
-    mDNSBool HaveZoneData  = rr->nta && !mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4);
-
-    // Nat state change if:
-    // We were behind a NAT, and now we are behind a new NAT, or
-    // We're not behind a NAT but our port was previously mapped to a different external port
-    // We were not behind a NAT and now we are
-
-    mDNSIPPort port        = rr->resrec.rdata->u.srv.port;
-    mDNSBool NowNeedNATMAP = (rr->AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(port) && mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && rr->nta && !mDNSAddrIsRFC1918(&rr->nta->Addr));
-    mDNSBool WereBehindNAT = (rr->NATinfo.clientContext != mDNSNULL);
-    mDNSBool PortWasMapped = (rr->NATinfo.clientContext && !mDNSSameIPPort(rr->NATinfo.RequestedPort, port));       // I think this is always false -- SC Sept 07
-    mDNSBool NATChanged    = (!WereBehindNAT && NowNeedNATMAP) || (!NowNeedNATMAP && PortWasMapped);
-
-    (void)HaveZoneData; //unused
-
-    LogInfo("UpdateOneSRVRecord: Resource Record %s TargetChanged %d, NewTarget %##s", ARDisplayString(m, rr), TargetChanged, nt->c);
-
-    debugf("UpdateOneSRVRecord: %##s newtarget %##s TargetChanged %d HaveZoneData %d port %d NowNeedNATMAP %d WereBehindNAT %d PortWasMapped %d NATChanged %d",
-           rr->resrec.name->c, newtarget,
-           TargetChanged, HaveZoneData, mDNSVal16(port), NowNeedNATMAP, WereBehindNAT, PortWasMapped, NATChanged);
-
-    mDNS_CheckLock(m);
-
-    if (!TargetChanged && !NATChanged) return;
-
-    // If we are deregistering the record, then ignore any NAT/Target change.
-    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-    {
-        LogInfo("UpdateOneSRVRecord: Deregistering record, Ignoring TargetChanged %d, NATChanged %d for %##s, state %d", TargetChanged, NATChanged,
-                rr->resrec.name->c, rr->state);
-        return;
-    }
-
-    if (newtarget)
-        LogInfo("UpdateOneSRVRecord: TargetChanged %d, NATChanged %d for %##s, state %d, newtarget %##s", TargetChanged, NATChanged, rr->resrec.name->c, rr->state, newtarget->c);
-    else
-        LogInfo("UpdateOneSRVRecord: TargetChanged %d, NATChanged %d for %##s, state %d, null newtarget", TargetChanged, NATChanged, rr->resrec.name->c, rr->state);
-    switch(rr->state)
-    {
-    case regState_NATMap:
-        // In these states, the SRV has either not yet been registered (it will get up-to-date information when it is)
-        // or is in the process of, or has already been, deregistered. This assumes that whenever we transition out
-        // of this state, we need to look at the target again.
-        return;
-
-    case regState_UpdatePending:
-        // We are getting a Target change/NAT change while the SRV record is being updated ?
-        // let us not do anything for now.
-        return;
-
-    case regState_NATError:
-        if (!NATChanged) return;
-        fallthrough();
-    // if nat changed, register if we have a target (below)
-
-    case regState_NoTarget:
-        if (!newtarget->c[0])
-        {
-            LogInfo("UpdateOneSRVRecord: No target yet for Resource Record %s", ARDisplayString(m, rr));
-            return;
-        }
-        RegisterAllServiceRecords(m, rr);
-        return;
-    case regState_DeregPending:
-    // We are in DeregPending either because the service was deregistered from above or we handled
-    // a NAT/Target change before and sent the deregistration below. There are a few race conditions
-    // possible
-    //
-    // 1. We are handling a second NAT/Target change while the first dereg is in progress. It is possible
-    //    that first dereg never made it through because there was no network connectivity e.g., disconnecting
-    //    from network triggers this function due to a target change and later connecting to the network
-    //    retriggers this function but the deregistration never made it through yet. Just fall through.
-    //    If there is a target register otherwise deregister.
-    //
-    // 2. While we sent the dereg during a previous NAT/Target change, uDNS_DeregisterRecord gets
-    //    called as part of service deregistration. When the response comes back, we call
-    //    CompleteDeregistration rather than handle NAT/Target change because the record is in
-    //    kDNSRecordTypeDeregistering state.
-    //
-    // 3. If the upper layer deregisters the service, we check for kDNSRecordTypeDeregistering both
-    //    here in this function to avoid handling NAT/Target change and in hndlRecordUpdateReply to call
-    //    CompleteDeregistration instead of handling NAT/Target change. Hence, we are not concerned
-    //    about that case here.
-    //
-    // We just handle case (1) by falling through
-    case regState_Pending:
-    case regState_Refresh:
-    case regState_Registered:
-        // target or nat changed.  deregister service.  upon completion, we'll look for a new target
-        rr->SRVChanged = mDNStrue;
-        rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-        rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-        if (newtarget->c[0])
-        {
-            LogInfo("UpdateOneSRVRecord: SRV record changed for service %##s, registering with new target %##s",
-                    rr->resrec.name->c, newtarget->c);
-            rr->state = regState_Pending;
-        }
-        else
-        {
-            LogInfo("UpdateOneSRVRecord: SRV record changed for service %##s de-registering", rr->resrec.name->c);
-            rr->state = regState_DeregPending;
-            UpdateAllServiceRecords(m, rr, mDNSfalse);
-        }
-        return;
-    case regState_Unregistered:
-    case regState_Zero:
-        break;
-    }
-    LogMsg("UpdateOneSRVRecord: Unknown state %d for %##s", rr->state, rr->resrec.name->c);
-}
-
-mDNSexport void UpdateAllSRVRecords(mDNS *m)
-{
-    m->NextSRVUpdate = 0;
-    LogInfo("UpdateAllSRVRecords %d", m->SleepState);
-
-    if (m->CurrentRecord)
-        LogMsg("UpdateAllSRVRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-    m->CurrentRecord = m->ResourceRecords;
-    while (m->CurrentRecord)
-    {
-        AuthRecord *rptr = m->CurrentRecord;
-        m->CurrentRecord = m->CurrentRecord->next;
-        if (AuthRecord_uDNS(rptr) && rptr->resrec.rrtype == kDNSType_SRV)
-            UpdateOneSRVRecord(m, rptr);
-    }
-}
-
-// Forward reference: AdvertiseHostname references HostnameCallback, and HostnameCallback calls AdvertiseHostname
-mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-// Called in normal client context (lock not held)
-mDNSlocal void hostnameGetPublicAddressCallback(mDNS *m, NATTraversalInfo *n)
-{
-    HostnameInfo *h = (HostnameInfo *)n->clientContext;
-
-    if (!h) { LogMsg("RegisterHostnameRecord: registration cancelled"); return; }
-
-    if (!n->Result)
-    {
-        if (mDNSIPv4AddressIsZero(n->ExternalAddress) || mDNSv4AddrIsRFC1918(&n->ExternalAddress)) return;
-
-        if (h->arv4.resrec.RecordType)
-        {
-            if (mDNSSameIPv4Address(h->arv4.resrec.rdata->u.ipv4, n->ExternalAddress)) return;  // If address unchanged, do nothing
-            LogInfo("Updating hostname %p %##s IPv4 from %.4a to %.4a (NAT gateway's external address)",n,
-                    h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress);
-            mDNS_Deregister(m, &h->arv4);   // mStatus_MemFree callback will re-register with new address
-        }
-        else
-        {
-            LogInfo("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress);
-            h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
-            h->arv4.resrec.rdata->u.ipv4 = n->ExternalAddress;
-            mDNS_Register(m, &h->arv4);
-        }
-    }
-}
-
-// register record or begin NAT traversal
-mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
-{
-    if (!mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4) && h->arv4.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        mDNS_SetupResourceRecord(&h->arv4, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnregistered, AuthRecordAny, HostnameCallback, h);
-        AssignDomainName(&h->arv4.namestorage, &h->fqdn);
-        h->arv4.resrec.rdata->u.ipv4 = m->AdvertisedV4.ip.v4;
-        h->arv4.state = regState_Unregistered;
-        if (mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4))
-        {
-            // If we already have a NAT query active, stop it and restart it to make sure we get another callback
-            if (h->natinfo.clientContext) mDNS_StopNATOperation_internal(m, &h->natinfo);
-            h->natinfo.Protocol         = 0;
-            h->natinfo.IntPort          = zeroIPPort;
-            h->natinfo.RequestedPort    = zeroIPPort;
-            h->natinfo.NATLease         = 0;
-            h->natinfo.clientCallback   = hostnameGetPublicAddressCallback;
-            h->natinfo.clientContext    = h;
-            mDNS_StartNATOperation_internal(m, &h->natinfo);
-        }
-        else
-        {
-            LogInfo("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4);
-            h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
-            mDNS_Register_internal(m, &h->arv4);
-        }
-    }
-
-    if (!mDNSIPv6AddressIsZero(m->AdvertisedV6.ip.v6) && h->arv6.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        mDNS_SetupResourceRecord(&h->arv6, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, HostnameCallback, h);
-        AssignDomainName(&h->arv6.namestorage, &h->fqdn);
-        h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6;
-        h->arv6.state = regState_Unregistered;
-        LogInfo("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6);
-        mDNS_Register_internal(m, &h->arv6);
-    }
-}
-
-mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    HostnameInfo *hi = rr->RecordContext;
-
-    if (result == mStatus_MemFree)
-    {
-        if (hi)
-        {
-            // If we're still in the Hostnames list, update to new address
-            HostnameInfo *i;
-            LogInfo("HostnameCallback: Got mStatus_MemFree for %p %p %s", hi, rr, ARDisplayString(m, rr));
-            for (i = m->Hostnames; i; i = i->next)
-                if (rr == &i->arv4 || rr == &i->arv6)
-                { mDNS_Lock(m); AdvertiseHostname(m, i); mDNS_Unlock(m); return; }
-
-            // Else, we're not still in the Hostnames list, so free the memory
-            if (hi->arv4.resrec.RecordType == kDNSRecordTypeUnregistered &&
-                hi->arv6.resrec.RecordType == kDNSRecordTypeUnregistered)
-            {
-                if (hi->natinfo.clientContext) mDNS_StopNATOperation_internal(m, &hi->natinfo);
-                hi->natinfo.clientContext = mDNSNULL;
-                mDNSPlatformMemFree(hi);    // free hi when both v4 and v6 AuthRecs deallocated
-            }
-        }
-        return;
-    }
-
-    if (result)
-    {
-        // don't unlink or free - we can retry when we get a new address/router
-        if (rr->resrec.rrtype == kDNSType_A)
-            LogMsg("HostnameCallback: Error %d for registration of %##s IP %.4a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
-        else
-            LogMsg("HostnameCallback: Error %d for registration of %##s IP %.16a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
-        if (!hi) { mDNSPlatformMemFree(rr); return; }
-        if (rr->state != regState_Unregistered) LogMsg("Error: HostnameCallback invoked with error code for record not in regState_Unregistered!");
-
-        if (hi->arv4.state == regState_Unregistered &&
-            hi->arv6.state == regState_Unregistered)
-        {
-            // only deliver status if both v4 and v6 fail
-            rr->RecordContext = (void *)hi->StatusContext;
-            if (hi->StatusCallback)
-                hi->StatusCallback(m, rr, result); // client may NOT make API calls here
-            rr->RecordContext = hi;
-        }
-        return;
-    }
-
-    // register any pending services that require a target
-    mDNS_Lock(m);
-    m->NextSRVUpdate = NonZeroTime(m->timenow);
-    mDNS_Unlock(m);
-
-    // Deliver success to client
-    if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; }
-    if (rr->resrec.rrtype == kDNSType_A)
-        LogInfo("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
-    else
-        LogInfo("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
-
-    rr->RecordContext = (void *)hi->StatusContext;
-    if (hi->StatusCallback)
-        hi->StatusCallback(m, rr, result); // client may NOT make API calls here
-    rr->RecordContext = hi;
-}
-
-mDNSlocal void FoundStaticHostname(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    const domainname *pktname = &answer->rdata->u.name;
-    domainname *storedname = &m->StaticHostname;
-    HostnameInfo *h = m->Hostnames;
-
-    (void)question;
-
-    if (answer->rdlength != 0)
-        LogInfo("FoundStaticHostname: question %##s -> answer %##s (%s)", question->qname.c, answer->rdata->u.name.c, AddRecord ? "ADD" : "RMV");
-    else
-        LogInfo("FoundStaticHostname: question %##s -> answer NULL (%s)", question->qname.c, AddRecord ? "ADD" : "RMV");
-
-    if (AddRecord && answer->rdlength != 0 && !SameDomainName(pktname, storedname))
-    {
-        AssignDomainName(storedname, pktname);
-        while (h)
-        {
-            if (h->arv4.state == regState_Pending || h->arv4.state == regState_NATMap || h->arv6.state == regState_Pending)
-            {
-                // if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds
-                m->NextSRVUpdate = NonZeroTime(m->timenow + 5 * mDNSPlatformOneSecond);
-                debugf("FoundStaticHostname: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
-                return;
-            }
-            h = h->next;
-        }
-        mDNS_Lock(m);
-        m->NextSRVUpdate = NonZeroTime(m->timenow);
-        mDNS_Unlock(m);
-    }
-    else if (!AddRecord && SameDomainName(pktname, storedname))
-    {
-        mDNS_Lock(m);
-        storedname->c[0] = 0;
-        m->NextSRVUpdate = NonZeroTime(m->timenow);
-        mDNS_Unlock(m);
-    }
-}
-
-// Called with lock held
-mDNSlocal void GetStaticHostname(mDNS *m)
-{
-    char buf[MAX_REVERSE_MAPPING_NAME_V4];
-    DNSQuestion *q = &m->ReverseMap;
-    mDNSu8 *ip = m->AdvertisedV4.ip.v4.b;
-    mStatus err;
-
-    if (m->ReverseMap.ThisQInterval != -1) return; // already running
-    if (mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4)) return;
-
-    mDNSPlatformMemZero(q, sizeof(*q));
-    // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-    mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", ip[3], ip[2], ip[1], ip[0]);
-    if (!MakeDomainNameFromDNSNameString(&q->qname, buf)) { LogMsg("Error: GetStaticHostname - bad name %s", buf); return; }
-
-    q->InterfaceID      = mDNSInterface_Any;
-    q->flags            = 0;
-    q->qtype            = kDNSType_PTR;
-    q->qclass           = kDNSClass_IN;
-    q->LongLived        = mDNSfalse;
-    q->ExpectUnique     = mDNSfalse;
-    q->ForceMCast       = mDNSfalse;
-    q->ReturnIntermed   = mDNStrue;
-    q->SuppressUnusable = mDNSfalse;
-    q->AppendSearchDomains = 0;
-    q->TimeoutQuestion  = 0;
-    q->WakeOnResolve    = 0;
-    q->UseBackgroundTraffic = mDNSfalse;
-    q->ProxyQuestion      = 0;
-    q->pid              = mDNSPlatformGetPID();
-    q->euid             = 0;
-    q->QuestionCallback = FoundStaticHostname;
-    q->QuestionContext  = mDNSNULL;
-
-    LogInfo("GetStaticHostname: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-    err = mDNS_StartQuery_internal(m, q);
-    if (err) LogMsg("Error: GetStaticHostname - StartQuery returned error %d", err);
-}
-
-mDNSexport void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
-{
-    HostnameInfo **ptr = &m->Hostnames;
-
-    LogInfo("mDNS_AddDynDNSHostName %##s", fqdn);
-
-    while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next;
-    if (*ptr) { LogMsg("DynDNSHostName %##s already in list", fqdn->c); return; }
-
-    // allocate and format new address record
-    *ptr = (HostnameInfo *) mDNSPlatformMemAllocateClear(sizeof(**ptr));
-    if (!*ptr) { LogMsg("ERROR: mDNS_AddDynDNSHostName - malloc"); return; }
-
-    AssignDomainName(&(*ptr)->fqdn, fqdn);
-    (*ptr)->arv4.state     = regState_Unregistered;
-    (*ptr)->arv6.state     = regState_Unregistered;
-    (*ptr)->StatusCallback = StatusCallback;
-    (*ptr)->StatusContext  = StatusContext;
-
-    AdvertiseHostname(m, *ptr);
-}
-
-mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn)
-{
-    HostnameInfo **ptr = &m->Hostnames;
-
-    LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "mDNS_RemoveDynDNSHostName " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-
-    while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next;
-    if (!*ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "mDNS_RemoveDynDNSHostName: no such domainname " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-    }
-    else
-    {
-        HostnameInfo *hi = *ptr;
-        // We do it this way because, if we have no active v6 record, the "mDNS_Deregister_internal(m, &hi->arv4);"
-        // below could free the memory, and we have to make sure we don't touch hi fields after that.
-        mDNSBool f4 = hi->arv4.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv4.state != regState_Unregistered;
-        mDNSBool f6 = hi->arv6.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv6.state != regState_Unregistered;
-        *ptr = (*ptr)->next; // unlink
-        if (f4 || f6)
-        {
-            if (f4)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "mDNS_RemoveDynDNSHostName removing v4 " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-                mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal);
-            }
-            if (f6)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "mDNS_RemoveDynDNSHostName removing v6 " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-                mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal);
-            }
-            // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback
-        }
-        else
-        {
-            if (hi->natinfo.clientContext)
-            {
-                mDNS_StopNATOperation_internal(m, &hi->natinfo);
-                hi->natinfo.clientContext = mDNSNULL;
-            }
-            mDNSPlatformMemFree(hi);
-        }
-    }
-    mDNS_CheckLock(m);
-    m->NextSRVUpdate = NonZeroTime(m->timenow);
-}
-
-// Currently called without holding the lock
-// Maybe we should change that?
-mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router)
-{
-    mDNSBool v4Changed, v6Changed, RouterChanged;
-
-    mDNS_Lock(m);
-
-    if (v4addr && v4addr->type != mDNSAddrType_IPv4) { LogMsg("mDNS_SetPrimaryInterfaceInfo v4 address - incorrect type.  Discarding. %#a", v4addr); goto exit; }
-    if (v6addr && v6addr->type != mDNSAddrType_IPv6) { LogMsg("mDNS_SetPrimaryInterfaceInfo v6 address - incorrect type.  Discarding. %#a", v6addr); goto exit; }
-    if (router && router->type != mDNSAddrType_IPv4) { LogMsg("mDNS_SetPrimaryInterfaceInfo passed non-v4 router.  Discarding. %#a",        router); goto exit; }
-
-    v4Changed     = !mDNSSameIPv4Address(m->AdvertisedV4.ip.v4, v4addr ? v4addr->ip.v4 : zerov4Addr);
-    v6Changed     = !mDNSSameIPv6Address(m->AdvertisedV6.ip.v6, v6addr ? v6addr->ip.v6 : zerov6Addr);
-    RouterChanged = !mDNSSameIPv4Address(m->Router.ip.v4,       router ? router->ip.v4 : zerov4Addr);
-
-    if (v4addr && (v4Changed || RouterChanged))
-        debugf("mDNS_SetPrimaryInterfaceInfo: address changed from %#a to %#a", &m->AdvertisedV4, v4addr);
-
-    if (v4addr) m->AdvertisedV4 = *v4addr;else m->AdvertisedV4.ip.v4 = zerov4Addr;
-    if (v6addr) m->AdvertisedV6 = *v6addr;else m->AdvertisedV6.ip.v6 = zerov6Addr;
-    if (router) m->Router       = *router;else m->Router.ip.v4 = zerov4Addr;
-    // setting router to zero indicates that nat mappings must be reestablished when router is reset
-
-    if (v4Changed || RouterChanged || v6Changed)
-    {
-        HostnameInfo *i;
-        LogInfo("mDNS_SetPrimaryInterfaceInfo: %s%s%s%#a %#a %#a",
-                v4Changed     ? "v4Changed "     : "",
-                RouterChanged ? "RouterChanged " : "",
-                v6Changed     ? "v6Changed "     : "", v4addr, v6addr, router);
-
-        for (i = m->Hostnames; i; i = i->next)
-        {
-            LogInfo("mDNS_SetPrimaryInterfaceInfo updating host name registrations for %##s", i->fqdn.c);
-
-            if (i->arv4.resrec.RecordType > kDNSRecordTypeDeregistering &&
-                !mDNSSameIPv4Address(i->arv4.resrec.rdata->u.ipv4, m->AdvertisedV4.ip.v4))
-            {
-                LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv4));
-                mDNS_Deregister_internal(m, &i->arv4, mDNS_Dereg_normal);
-            }
-
-            if (i->arv6.resrec.RecordType > kDNSRecordTypeDeregistering &&
-                !mDNSSameIPv6Address(i->arv6.resrec.rdata->u.ipv6, m->AdvertisedV6.ip.v6))
-            {
-                LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv6));
-                mDNS_Deregister_internal(m, &i->arv6, mDNS_Dereg_normal);
-            }
-
-            // AdvertiseHostname will only register new address records.
-            // For records still in the process of deregistering it will ignore them, and let the mStatus_MemFree callback handle them.
-            AdvertiseHostname(m, i);
-        }
-
-        if (v4Changed || RouterChanged)
-        {
-            // If we have a non-zero IPv4 address, we should try immediately to see if we have a NAT gateway
-            // If we have no IPv4 address, we don't want to be in quite such a hurry to report failures to our clients
-            // <rdar://problem/6935929> Sleeping server sometimes briefly disappears over Back to My Mac after it wakes up
-            mDNSu32 waitSeconds = v4addr ? 0 : 5;
-            NATTraversalInfo *n;
-            m->ExtAddress           = zerov4Addr;
-            m->LastNATMapResultCode = NATErr_None;
-
-            RecreateNATMappings(m, mDNSPlatformOneSecond * waitSeconds);
-
-            for (n = m->NATTraversals; n; n=n->next)
-                n->NewAddress = zerov4Addr;
-
-            LogInfo("mDNS_SetPrimaryInterfaceInfo:%s%s: recreating NAT mappings in %d seconds",
-                    v4Changed     ? " v4Changed"     : "",
-                    RouterChanged ? " RouterChanged" : "",
-                    waitSeconds);
-        }
-
-        if (m->ReverseMap.ThisQInterval != -1) mDNS_StopQuery_internal(m, &m->ReverseMap);
-        m->StaticHostname.c[0] = 0;
-
-        m->NextSRVUpdate = NonZeroTime(m->timenow);
-    }
-
-exit:
-    mDNS_Unlock(m);
-}
-
-// ***************************************************************************
-// MARK: - Incoming Message Processing
-
-mDNSlocal mStatus ParseTSIGError(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const domainname *const displayname)
-{
-    const mDNSu8 *ptr;
-    mStatus err = mStatus_NoError;
-    int i;
-
-    ptr = LocateAdditionals(msg, end);
-    if (!ptr) goto finish;
-
-    for (i = 0; i < msg->h.numAdditionals; i++)
-    {
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
-        if (!ptr) goto finish;
-        if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_TSIG)
-        {
-            mDNSu32 macsize;
-            mDNSu8 *rd = m->rec.r.resrec.rdata->u.data;
-            mDNSu8 *rdend = rd + m->rec.r.resrec.rdlength;
-            int alglen = DomainNameLengthLimit(&m->rec.r.resrec.rdata->u.name, rdend);
-            if (alglen > MAX_DOMAIN_NAME) goto finish;
-            rd += alglen;                                       // algorithm name
-            if (rd + 6 > rdend) goto finish;
-            rd += 6;                                            // 48-bit timestamp
-            if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
-            rd += sizeof(mDNSOpaque16);                         // fudge
-            if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
-            macsize = mDNSVal16(*(mDNSOpaque16 *)rd);
-            rd += sizeof(mDNSOpaque16);                         // MAC size
-            if (rd + macsize > rdend) goto finish;
-            rd += macsize;
-            if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
-            rd += sizeof(mDNSOpaque16);                         // orig id
-            if (rd + sizeof(mDNSOpaque16) > rdend) goto finish;
-            err = mDNSVal16(*(mDNSOpaque16 *)rd);               // error code
-
-            if      (err == TSIG_ErrBadSig)  { LogMsg("%##s: bad signature", displayname->c);              err = mStatus_BadSig;     }
-            else if (err == TSIG_ErrBadKey)  { LogMsg("%##s: bad key", displayname->c);                    err = mStatus_BadKey;     }
-            else if (err == TSIG_ErrBadTime) { LogMsg("%##s: bad time", displayname->c);                   err = mStatus_BadTime;    }
-            else if (err)                    { LogMsg("%##s: unknown tsig error %d", displayname->c, err); err = mStatus_UnknownErr; }
-            goto finish;
-        }
-        mDNSCoreResetRecord(m);
-    }
-
-finish:
-    mDNSCoreResetRecord(m);
-    return err;
-}
-
-mDNSlocal mStatus checkUpdateResult(mDNS *const m, const domainname *const displayname, const mDNSu8 rcode, const DNSMessage *const msg, const mDNSu8 *const end)
-{
-    (void)msg;  // currently unused, needed for TSIG errors
-    if (!rcode) return mStatus_NoError;
-    else if (rcode == kDNSFlag1_RC_YXDomain)
-    {
-        debugf("name in use: %##s", displayname->c);
-        return mStatus_NameConflict;
-    }
-    else if (rcode == kDNSFlag1_RC_Refused)
-    {
-        LogMsg("Update %##s refused", displayname->c);
-        return mStatus_Refused;
-    }
-    else if (rcode == kDNSFlag1_RC_NXRRSet)
-    {
-        LogMsg("Reregister refused (NXRRSET): %##s", displayname->c);
-        return mStatus_NoSuchRecord;
-    }
-    else if (rcode == kDNSFlag1_RC_NotAuth)
-    {
-        // TSIG errors should come with FormErr as per RFC 2845, but BIND 9 sends them with NotAuth so we look here too
-        mStatus tsigerr = ParseTSIGError(m, msg, end, displayname);
-        if (!tsigerr)
-        {
-            LogMsg("Permission denied (NOAUTH): %##s", displayname->c);
-            return mStatus_UnknownErr;
-        }
-        else return tsigerr;
-    }
-    else if (rcode == kDNSFlag1_RC_FormErr)
-    {
-        mStatus tsigerr = ParseTSIGError(m, msg, end, displayname);
-        if (!tsigerr)
-        {
-            LogMsg("Format Error: %##s", displayname->c);
-            return mStatus_UnknownErr;
-        }
-        else return tsigerr;
-    }
-    else
-    {
-        LogMsg("Update %##s failed with rcode %d", displayname->c, rcode);
-        return mStatus_UnknownErr;
-    }
-}
-
-mDNSlocal mDNSu32 RRAdditionalSize(DomainAuthInfo *AuthInfo)
-{
-    mDNSu32 leaseSize, tsigSize;
-    mDNSu32 rr_base_size = 10; // type (2) class (2) TTL (4) rdlength (2)
-
-    // OPT RR : Emptyname(.) + base size + rdataOPT
-    leaseSize = 1 + rr_base_size + sizeof(rdataOPT);
-
-    //TSIG: Resource Record Name + base size + RDATA
-    // RDATA:
-    //  Algorithm name: hmac-md5.sig-alg.reg.int (8+7+3+3 + 5 bytes for length = 26 bytes)
-    //  Time: 6 bytes
-    //  Fudge: 2 bytes
-    //  Mac Size: 2 bytes
-    //  Mac: 16 bytes
-    //  ID: 2 bytes
-    //  Error: 2 bytes
-    //  Len: 2 bytes
-    //  Total: 58 bytes
-    tsigSize = 0;
-    if (AuthInfo) tsigSize = DomainNameLength(&AuthInfo->keyname) + rr_base_size + 58;
-
-    return (leaseSize + tsigSize);
-}
-
-//Note: Make sure that RREstimatedSize is updated accordingly if anything that is done here
-//would modify rdlength/rdestimate
-mDNSlocal mDNSu8* BuildUpdateMessage(mDNS *const m, mDNSu8 *ptr, AuthRecord *rr, mDNSu8 *limit)
-{
-    //If this record is deregistering, then just send the deletion record
-    if (rr->state == regState_DeregPending)
-    {
-        rr->expire = 0;     // Indicate that we have no active registration any more
-        ptr = putDeletionRecordWithLimit(&m->omsg, ptr, &rr->resrec, limit);
-        if (!ptr) goto exit;
-        return ptr;
-    }
-
-    // This is a common function to both sending an update in a group or individual
-    // records separately. Hence, we change the state here.
-    if (rr->state == regState_Registered) rr->state = regState_Refresh;
-    if (rr->state != regState_Refresh && rr->state != regState_UpdatePending)
-        rr->state = regState_Pending;
-
-    // For Advisory records like e.g., _services._dns-sd, which is shared, don't send goodbyes as multiple
-    // host might be registering records and deregistering from one does not make sense
-    if (rr->resrec.RecordType != kDNSRecordTypeAdvisory) rr->RequireGoodbye = mDNStrue;
-
-    if ((rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHostAndNATMAP) &&
-        !mDNSIPPortIsZero(rr->NATinfo.ExternalPort))
-    {
-        rr->resrec.rdata->u.srv.port = rr->NATinfo.ExternalPort;
-    }
-
-    if (rr->state == regState_UpdatePending)
-    {
-        // delete old RData
-        SetNewRData(&rr->resrec, rr->OrigRData, rr->OrigRDLen);
-        if (!(ptr = putDeletionRecordWithLimit(&m->omsg, ptr, &rr->resrec, limit))) goto exit; // delete old rdata
-
-        // add new RData
-        SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
-        if (!(ptr = PutResourceRecordTTLWithLimit(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit))) goto exit;
-    }
-    else
-    {
-        if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique || rr->resrec.RecordType == kDNSRecordTypeVerified)
-        {
-            // KnownUnique : Delete any previous value
-            // For Unicast registrations, we don't verify that it is unique, but set to verified and hence we want to
-            // delete any previous value
-            ptr = putDeleteRRSetWithLimit(&m->omsg, ptr, rr->resrec.name, rr->resrec.rrtype, limit);
-            if (!ptr) goto exit;
-        }
-        else if (rr->resrec.RecordType != kDNSRecordTypeShared)
-        {
-            // For now don't do this, until we have the logic for intelligent grouping of individual records into logical service record sets
-            //ptr = putPrereqNameNotInUse(rr->resrec.name, &m->omsg, ptr, end);
-            if (!ptr) goto exit;
-        }
-
-        ptr = PutResourceRecordTTLWithLimit(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
-        if (!ptr) goto exit;
-    }
-
-    return ptr;
-exit:
-    LogMsg("BuildUpdateMessage: Error formatting message for %s", ARDisplayString(m, rr));
-    return mDNSNULL;
-}
-
-// Called with lock held
-mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr)
-{
-    mDNSu8 *ptr = m->omsg.data;
-    mStatus err = mStatus_UnknownErr;
-    mDNSu8 *limit;
-    DomainAuthInfo *AuthInfo;
-
-    // For the ability to register large TXT records, we limit the single record registrations
-    // to AbsoluteMaxDNSMessageData
-    limit = ptr + AbsoluteMaxDNSMessageData;
-
-    AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
-    limit -= RRAdditionalSize(AuthInfo);
-
-    mDNS_CheckLock(m);
-
-    if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
-    {
-        // We never call this function when there is no zone information . Log a message if it ever happens.
-        LogMsg("SendRecordRegistration: No Zone information, should not happen %s", ARDisplayString(m, rr));
-        return;
-    }
-
-    rr->updateid = mDNS_NewMessageID(m);
-    InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags);
-
-    // set zone
-    ptr = putZone(&m->omsg, ptr, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
-    if (!ptr) goto exit;
-
-    if (!(ptr = BuildUpdateMessage(m, ptr, rr, limit))) goto exit;
-
-    if (rr->uselease)
-    {
-        ptr = putUpdateLeaseWithLimit(&m->omsg, ptr, DEFAULT_UPDATE_LEASE, limit);
-        if (!ptr) goto exit;
-    }
-    if (rr->Private)
-    {
-        LogInfo("SendRecordRegistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
-        if (rr->tcp) LogInfo("SendRecordRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
-        if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
-        if (!rr->nta) { LogMsg("SendRecordRegistration:Private:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
-        rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->nta->Addr, rr->nta->Port, &rr->nta->Host, mDNSNULL, rr);
-    }
-    else
-    {
-        LogInfo("SendRecordRegistration UDP %s", ARDisplayString(m, rr));
-        if (!rr->nta) { LogMsg("SendRecordRegistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
-        err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, mDNSNULL, &rr->nta->Addr, rr->nta->Port, GetAuthInfoForName_internal(m, rr->resrec.name), mDNSfalse);
-        if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %d", err);
-    }
-
-    SetRecordRetry(m, rr, 0);
-    return;
-exit:
-    LogMsg("SendRecordRegistration: Error formatting message for %s, disabling further updates", ARDisplayString(m, rr));
-    // Disable this record from future updates
-    rr->state = regState_NoTarget;
-}
-
-// Is the given record "rr" eligible for merging ?
-mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time)
-{
-    DomainAuthInfo *info;
-    // A record is eligible for merge, if the following properties are met.
-    //
-    // 1. uDNS Resource Record
-    // 2. It is time to send them now
-    // 3. It is in proper state
-    // 4. Update zone has been resolved
-    // 5. if DomainAuthInfo exists for the zone, it should not be soon deleted
-    // 6. Zone information is present
-    // 7. Update server is not zero
-    // 8. It has a non-null zone
-    // 9. It uses a lease option
-    // 10. DontMerge is not set
-    //
-    // Following code is implemented as separate "if" statements instead of one "if" statement
-    // is for better debugging purposes e.g., we know exactly what failed if debugging turned on.
-
-    if (!AuthRecord_uDNS(rr)) return mDNSfalse;
-
-    if (rr->LastAPTime + rr->ThisAPInterval - time > 0)
-    { debugf("IsRecordMergeable: Time %d not reached for %s", rr->LastAPTime + rr->ThisAPInterval - m->timenow, ARDisplayString(m, rr)); return mDNSfalse; }
-
-    if (!rr->zone) return mDNSfalse;
-
-    info = GetAuthInfoForName_internal(m, rr->zone);
-
-    if (info && info->deltime && m->timenow - info->deltime >= 0) {debugf("IsRecordMergeable: Domain %##s will be deleted soon", info->domain.c); return mDNSfalse;}
-
-    if (rr->state != regState_DeregPending && rr->state != regState_Pending && rr->state != regState_Registered && rr->state != regState_Refresh && rr->state != regState_UpdatePending)
-    { debugf("IsRecordMergeable: state %d not right  %s", rr->state, ARDisplayString(m, rr)); return mDNSfalse; }
-
-    if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4)) return mDNSfalse;
-
-    if (!rr->uselease) return mDNSfalse;
-
-    if (rr->mState == mergeState_DontMerge) {debugf("IsRecordMergeable Dontmerge true %s", ARDisplayString(m, rr)); return mDNSfalse;}
-    debugf("IsRecordMergeable: Returning true for %s", ARDisplayString(m, rr));
-    return mDNStrue;
-}
-
-// Is the resource record "rr" eligible to merge to with "currentRR" ?
-mDNSlocal mDNSBool AreRecordsMergeable(mDNS *const m, AuthRecord *currentRR, AuthRecord *rr, mDNSs32 time)
-{
-    // A record is eligible to merge with another record as long it is eligible for merge in itself
-    // and it has the same zone information as the other record
-    if (!IsRecordMergeable(m, rr, time)) return mDNSfalse;
-
-    if (!SameDomainName(currentRR->zone, rr->zone))
-    { debugf("AreRecordMergeable zone mismatch current rr Zone %##s, rr zone  %##s", currentRR->zone->c, rr->zone->c); return mDNSfalse; }
-
-    if (!mDNSSameIPv4Address(currentRR->nta->Addr.ip.v4, rr->nta->Addr.ip.v4)) return mDNSfalse;
-
-    if (!mDNSSameIPPort(currentRR->nta->Port, rr->nta->Port)) return mDNSfalse;
-
-    debugf("AreRecordsMergeable: Returning true for %s", ARDisplayString(m, rr));
-    return mDNStrue;
-}
-
-// If we can't build the message successfully because of problems in pre-computing
-// the space, we disable merging for all the current records
-mDNSlocal void RRMergeFailure(mDNS *const m)
-{
-    AuthRecord *rr;
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-    {
-        rr->mState = mergeState_DontMerge;
-        rr->SendRNow = mDNSNULL;
-        // Restarting the registration is much simpler than saving and restoring
-        // the exact time
-        ActivateUnicastRegistration(m, rr);
-    }
-}
-
-mDNSlocal void SendGroupRRMessage(mDNS *const m, AuthRecord *anchorRR, mDNSu8 *ptr, DomainAuthInfo *info)
-{
-    mDNSu8 *limit;
-    if (!anchorRR) {debugf("SendGroupRRMessage: Could not merge records"); return;}
-
-    limit = m->omsg.data + NormalMaxDNSMessageData;
-
-    // This has to go in the additional section and hence need to be done last
-    ptr = putUpdateLeaseWithLimit(&m->omsg, ptr, DEFAULT_UPDATE_LEASE, limit);
-    if (!ptr)
-    {
-        LogMsg("SendGroupRRMessage: ERROR: Could not put lease option, failing the group registration");
-        // if we can't put the lease, we need to undo the merge
-        RRMergeFailure(m);
-        return;
-    }
-    if (anchorRR->Private)
-    {
-        if (anchorRR->tcp) debugf("SendGroupRRMessage: Disposing existing TCP connection for %s", ARDisplayString(m, anchorRR));
-        if (anchorRR->tcp) { DisposeTCPConn(anchorRR->tcp); anchorRR->tcp = mDNSNULL; }
-        if (!anchorRR->nta) { LogMsg("SendGroupRRMessage:ERROR!! nta is NULL for %s", ARDisplayString(m, anchorRR)); return; }
-        anchorRR->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &anchorRR->nta->Addr, anchorRR->nta->Port, &anchorRR->nta->Host, mDNSNULL, anchorRR);
-        if (!anchorRR->tcp) LogInfo("SendGroupRRMessage: Cannot establish TCP connection for %s", ARDisplayString(m, anchorRR));
-        else LogInfo("SendGroupRRMessage: Sent a group update ID: %d start %p, end %p, limit %p", mDNSVal16(m->omsg.h.id), m->omsg.data, ptr, limit);
-    }
-    else
-    {
-        mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, mDNSNULL, &anchorRR->nta->Addr, anchorRR->nta->Port, info, mDNSfalse);
-        if (err) LogInfo("SendGroupRRMessage: Cannot send UDP message for %s", ARDisplayString(m, anchorRR));
-        else LogInfo("SendGroupRRMessage: Sent a group UDP update ID: %d start %p, end %p, limit %p", mDNSVal16(m->omsg.h.id), m->omsg.data, ptr, limit);
-    }
-    return;
-}
-
-// As we always include the zone information and the resource records contain zone name
-// at the end, it will get compressed. Hence, we subtract zoneSize and add two bytes for
-// the compression pointer
-mDNSlocal mDNSu32 RREstimatedSize(AuthRecord *rr, int zoneSize)
-{
-    int rdlength;
-
-    // Note: Estimation of the record size has to mirror the logic in BuildUpdateMessage, otherwise estimation
-    // would be wrong. Currently BuildUpdateMessage calls SetNewRData in UpdatePending case. Hence, we need
-    // to account for that here. Otherwise, we might under estimate the size.
-    if (rr->state == regState_UpdatePending)
-        // old RData that will be deleted
-        // new RData that will be added
-        rdlength = rr->OrigRDLen + rr->InFlightRDLen;
-    else
-        rdlength = rr->resrec.rdestimate;
-
-    if (rr->state == regState_DeregPending)
-    {
-        debugf("RREstimatedSize: ResourceRecord %##s (%s), DomainNameLength %d, zoneSize %d, rdestimate %d",
-               rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), DomainNameLength(rr->resrec.name), zoneSize, rdlength);
-        return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + rdlength;
-    }
-
-    // For SRV, TXT, AAAA etc. that are Unique/Verified, we also send a Deletion Record
-    if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique || rr->resrec.RecordType == kDNSRecordTypeVerified)
-    {
-        // Deletion Record: Resource Record Name + Base size (10) + 0
-        // Record: Resource Record Name (Compressed = 2) + Base size (10) + rdestimate
-
-        debugf("RREstimatedSize: ResourceRecord %##s (%s), DomainNameLength %d, zoneSize %d, rdestimate %d",
-               rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), DomainNameLength(rr->resrec.name), zoneSize, rdlength);
-        return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + 2 + 10 + rdlength;
-    }
-    else
-    {
-        return DomainNameLength(rr->resrec.name) - zoneSize + 2 + 10 + rdlength;
-    }
-}
-
-mDNSlocal AuthRecord *MarkRRForSending(mDNS *const m)
-{
-    AuthRecord *rr;
-    AuthRecord *firstRR = mDNSNULL;
-
-    // Look for records that needs to be sent in the next two seconds (MERGE_DELAY_TIME is set to 1 second).
-    // The logic is as follows.
-    //
-    // 1. Record 1 finishes getting zone data and its registration gets delayed by 1 second
-    // 2. Record 2 comes 0.1 second later, finishes getting its zone data and its registration is also delayed by
-    //    1 second which is now scheduled at 1.1 second
-    //
-    // By looking for 1 second into the future (m->timenow + MERGE_DELAY_TIME below does that) we have merged both
-    // of the above records. Note that we can't look for records too much into the future as this will affect the
-    // retry logic. The first retry is scheduled at 3 seconds. Hence, we should always look smaller than that.
-    // Anything more than one second will affect the first retry to happen sooner.
-    //
-    // Note: As a side effect of looking one second into the future to facilitate merging, the retries happen
-    // one second sooner.
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-    {
-        if (!firstRR)
-        {
-            if (!IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME)) continue;
-            firstRR = rr;
-        }
-        else if (!AreRecordsMergeable(m, firstRR, rr, m->timenow + MERGE_DELAY_TIME)) continue;
-
-        if (rr->SendRNow) LogMsg("MarkRRForSending: Resourcerecord %s already marked for sending", ARDisplayString(m, rr));
-        rr->SendRNow = uDNSInterfaceMark;
-    }
-
-    // We parsed through all records and found something to send. The services/records might
-    // get registered at different times but we want the refreshes to be all merged and sent
-    // as one update. Hence, we accelerate some of the records so that they will sync up in
-    // the future. Look at the records excluding the ones that we have already sent in the
-    // previous pass. If it half way through its scheduled refresh/retransmit, merge them
-    // into this packet.
-    //
-    // Note that we only look at Registered/Refresh state to keep it simple. As we don't know
-    // whether the current update will fit into one or more packets, merging a resource record
-    // (which is in a different state) that has been scheduled for retransmit would trigger
-    // sending more packets.
-    if (firstRR)
-    {
-        int acc = 0;
-        for (rr = m->ResourceRecords; rr; rr = rr->next)
-        {
-            if ((rr->state != regState_Registered && rr->state != regState_Refresh) ||
-                (rr->SendRNow == uDNSInterfaceMark) ||
-                (!AreRecordsMergeable(m, firstRR, rr, m->timenow + rr->ThisAPInterval/2)))
-                continue;
-            rr->SendRNow = uDNSInterfaceMark;
-            acc++;
-        }
-        if (acc) LogInfo("MarkRRForSending: Accelereated %d records", acc);
-    }
-    return firstRR;
-}
-
-mDNSlocal mDNSBool SendGroupUpdates(mDNS *const m)
-{
-    mDNSOpaque16 msgid = zeroID;
-    mDNSs32 spaceleft = 0;
-    mDNSs32 zoneSize, rrSize;
-    mDNSu8 *oldnext; // for debugging
-    mDNSu8 *next = m->omsg.data;
-    AuthRecord *rr;
-    AuthRecord *anchorRR = mDNSNULL;
-    int nrecords = 0;
-    AuthRecord *startRR = m->ResourceRecords;
-    mDNSu8 *limit = mDNSNULL;
-    DomainAuthInfo *AuthInfo = mDNSNULL;
-    mDNSBool sentallRecords = mDNStrue;
-
-
-    // We try to fit as many ResourceRecords as possible in AbsoluteNormal/MaxDNSMessageData. Before we start
-    // putting in resource records, we need to reserve space for a few things. Every group/packet should
-    // have the following.
-    //
-    // 1) Needs space for the Zone information (which needs to be at the beginning)
-    // 2) Additional section MUST have space for lease option, HINFO and TSIG option (which needs to
-    //    to be at the end)
-    //
-    // In future we need to reserve space for the pre-requisites which also goes at the beginning.
-    // To accomodate pre-requisites in the future, first we walk the whole list marking records
-    // that can be sent in this packet and computing the space needed for these records.
-    // For TXT and SRV records, we delete the previous record if any by sending the same
-    // resource record with ANY RDATA and zero rdlen. Hence, we need to have space for both of them.
-
-    while (startRR)
-    {
-        AuthInfo = mDNSNULL;
-        anchorRR = mDNSNULL;
-        nrecords = 0;
-        zoneSize = 0;
-        for (rr = startRR; rr; rr = rr->next)
-        {
-            if (rr->SendRNow != uDNSInterfaceMark) continue;
-
-            rr->SendRNow = mDNSNULL;
-
-            if (!anchorRR)
-            {
-                AuthInfo = GetAuthInfoForName_internal(m, rr->zone);
-
-                // Though we allow single record registrations for UDP to be AbsoluteMaxDNSMessageData (See
-                // SendRecordRegistration) to handle large TXT records, to avoid fragmentation we limit UDP
-                // message to NormalMaxDNSMessageData
-                spaceleft = NormalMaxDNSMessageData;
-
-                next = m->omsg.data;
-                spaceleft -= RRAdditionalSize(AuthInfo);
-                if (spaceleft <= 0)
-                {
-                    LogMsg("SendGroupUpdates: ERROR!!: spaceleft is zero at the beginning");
-                    RRMergeFailure(m);
-                    return mDNSfalse;
-                }
-                limit = next + spaceleft;
-
-                // Build the initial part of message before putting in the other records
-                msgid = mDNS_NewMessageID(m);
-                InitializeDNSMessage(&m->omsg.h, msgid, UpdateReqFlags);
-
-                // We need zone information at the beginning of the packet. Length: ZNAME, ZTYPE(2), ZCLASS(2)
-                // zone has to be non-NULL for a record to be mergeable, hence it is safe to set/ examine zone
-                //without checking for NULL.
-                zoneSize = DomainNameLength(rr->zone) + 4;
-                spaceleft -= zoneSize;
-                if (spaceleft <= 0)
-                {
-                    LogMsg("SendGroupUpdates: ERROR no space for zone information, disabling merge");
-                    RRMergeFailure(m);
-                    return mDNSfalse;
-                }
-                next = putZone(&m->omsg, next, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
-                if (!next)
-                {
-                    LogMsg("SendGroupUpdates: ERROR! Cannot put zone, disabling merge");
-                    RRMergeFailure(m);
-                    return mDNSfalse;
-                }
-                anchorRR = rr;
-            }
-
-            rrSize = RREstimatedSize(rr, zoneSize - 4);
-
-            if ((spaceleft - rrSize) < 0)
-            {
-                // If we can't fit even a single message, skip it, it will be sent separately
-                // in CheckRecordUpdates
-                if (!nrecords)
-                {
-                    LogInfo("SendGroupUpdates: Skipping message %s, spaceleft %d, rrSize %d", ARDisplayString(m, rr), spaceleft, rrSize);
-                    // Mark this as not sent so that the caller knows about it
-                    rr->SendRNow = uDNSInterfaceMark;
-                    // We need to remove the merge delay so that we can send it immediately
-                    rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-                    rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-                    rr = rr->next;
-                    anchorRR = mDNSNULL;
-                    sentallRecords = mDNSfalse;
-                }
-                else
-                {
-                    LogInfo("SendGroupUpdates:1: Parsed %d records and sending using %s, spaceleft %d, rrSize %d", nrecords, ARDisplayString(m, anchorRR), spaceleft, rrSize);
-                    SendGroupRRMessage(m, anchorRR, next, AuthInfo);
-                }
-                break;      // breaks out of for loop
-            }
-            spaceleft -= rrSize;
-            oldnext = next;
-            LogInfo("SendGroupUpdates: Building a message with resource record %s, next %p, state %d, ttl %d", ARDisplayString(m, rr), next, rr->state, rr->resrec.rroriginalttl);
-            if (!(next = BuildUpdateMessage(m, next, rr, limit)))
-            {
-                // We calculated the space and if we can't fit in, we had some bug in the calculation,
-                // disable merge completely.
-                LogMsg("SendGroupUpdates: ptr NULL while building message with %s", ARDisplayString(m, rr));
-                RRMergeFailure(m);
-                return mDNSfalse;
-            }
-            // If our estimate was higher, adjust to the actual size
-            if ((next - oldnext) > rrSize)
-                LogMsg("SendGroupUpdates: ERROR!! Record size estimation is wrong for %s, Estimate %d, Actual %d, state %d", ARDisplayString(m, rr), rrSize, next - oldnext, rr->state);
-            else { spaceleft += rrSize; spaceleft -= (next - oldnext); }
-
-            nrecords++;
-            // We could have sent an update earlier with this "rr" as anchorRR for which we never got a response.
-            // To preserve ordering, we blow away the previous connection before sending this.
-            if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL;}
-            rr->updateid = msgid;
-
-            // By setting the retry time interval here, we will not be looking at these records
-            // again when we return to CheckGroupRecordUpdates.
-            SetRecordRetry(m, rr, 0);
-        }
-        // Either we have parsed all the records or stopped at "rr" above due to lack of space
-        startRR = rr;
-    }
-
-    if (anchorRR)
-    {
-        LogInfo("SendGroupUpdates: Parsed %d records and sending using %s", nrecords, ARDisplayString(m, anchorRR));
-        SendGroupRRMessage(m, anchorRR, next, AuthInfo);
-    }
-    return sentallRecords;
-}
-
-// Merge the record registrations and send them as a group only if they
-// have same DomainAuthInfo and hence the same key to put the TSIG
-mDNSlocal void CheckGroupRecordUpdates(mDNS *const m)
-{
-    AuthRecord *rr, *nextRR;
-    // Keep sending as long as there is at least one record to be sent
-    while (MarkRRForSending(m))
-    {
-        if (!SendGroupUpdates(m))
-        {
-            // if everything that was marked was not sent, send them out individually
-            for (rr = m->ResourceRecords; rr; rr = nextRR)
-            {
-                // SendRecordRegistrtion might delete the rr from list, hence
-                // dereference nextRR before calling the function
-                nextRR = rr->next;
-                if (rr->SendRNow == uDNSInterfaceMark)
-                {
-                    // Any records marked for sending should be eligible to be sent out
-                    // immediately. Just being cautious
-                    if (rr->LastAPTime + rr->ThisAPInterval - m->timenow > 0)
-                    { LogMsg("CheckGroupRecordUpdates: ERROR!! Resourcerecord %s not ready", ARDisplayString(m, rr)); continue; }
-                    rr->SendRNow = mDNSNULL;
-                    SendRecordRegistration(m, rr);
-                }
-            }
-        }
-    }
-
-    debugf("CheckGroupRecordUpdates: No work, returning");
-    return;
-}
-
-mDNSlocal void hndlSRVChanged(mDNS *const m, AuthRecord *rr)
-{
-    // Reevaluate the target always as NAT/Target could have changed while
-    // we were registering/deeregistering
-    domainname *dt;
-    const domainname *target = GetServiceTarget(m, rr);
-    if (!target || target->c[0] == 0)
-    {
-        // we don't have a target, if we just derregistered, then we don't have to do anything
-        if (rr->state == regState_DeregPending)
-        {
-            LogInfo("hndlSRVChanged: SRVChanged, No Target, SRV Deregistered for %##s, state %d", rr->resrec.name->c,
-                    rr->state);
-            rr->SRVChanged = mDNSfalse;
-            dt = GetRRDomainNameTarget(&rr->resrec);
-            if (dt) dt->c[0] = 0;
-            rr->state = regState_NoTarget;  // Wait for the next target change
-            rr->resrec.rdlength = rr->resrec.rdestimate = 0;
-            return;
-        }
-
-        // we don't have a target, if we just registered, we need to deregister
-        if (rr->state == regState_Pending)
-        {
-            LogInfo("hndlSRVChanged: SRVChanged, No Target, Deregistering again %##s, state %d", rr->resrec.name->c, rr->state);
-            rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-            rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-            rr->state = regState_DeregPending;
-            return;
-        }
-        LogInfo("hndlSRVChanged: Not in DeregPending or RegPending state %##s, state %d", rr->resrec.name->c, rr->state);
-    }
-    else
-    {
-        // If we were in registered state and SRV changed to NULL, we deregister and come back here
-        // if we have a target, we need to register again.
-        //
-        // if we just registered check to see if it is same. If it is different just re-register the
-        // SRV and its assoicated records
-        //
-        // UpdateOneSRVRecord takes care of re-registering all service records
-        if ((rr->state == regState_DeregPending) ||
-            (rr->state == regState_Pending && !SameDomainName(target, &rr->resrec.rdata->u.srv.target)))
-        {
-            dt = GetRRDomainNameTarget(&rr->resrec);
-            if (dt) dt->c[0] = 0;
-            rr->state = regState_NoTarget;  // NoTarget will allow us to pick up new target OR nat traversal state
-            rr->resrec.rdlength = rr->resrec.rdestimate = 0;
-            LogInfo("hndlSRVChanged: SRVChanged, Valid Target %##s, Registering all records for %##s, state %d",
-                    target->c, rr->resrec.name->c, rr->state);
-            rr->SRVChanged = mDNSfalse;
-            UpdateOneSRVRecord(m, rr);
-            return;
-        }
-        // Target did not change while this record was registering. Hence, we go to
-        // Registered state - the state we started from.
-        if (rr->state == regState_Pending) rr->state = regState_Registered;
-    }
-
-    rr->SRVChanged = mDNSfalse;
-}
-
-// Called with lock held
-mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err, mDNSu32 random)
-{
-    mDNSBool InvokeCallback = mDNStrue;
-    mDNSIPPort UpdatePort = zeroIPPort;
-
-    mDNS_CheckLock(m);
-
-    LogInfo("hndlRecordUpdateReply: err %d ID %d state %d %s(%p)", err, mDNSVal16(rr->updateid), rr->state, ARDisplayString(m, rr), rr);
-
-    rr->updateError = err;
-
-    SetRecordRetry(m, rr, random);
-
-    rr->updateid = zeroID;  // Make sure that this is not considered as part of a group anymore
-    // Later when need to send an update, we will get the zone data again. Thus we avoid
-    // using stale information.
-    //
-    // Note: By clearing out the zone info here, it also helps better merging of records
-    // in some cases. For example, when we get out regState_NoTarget state e.g., move out
-    // of Double NAT, we want all the records to be in one update. Some BTMM records like
-    // _autotunnel6 and host records are registered/deregistered when NAT state changes.
-    // As they are re-registered the zone information is cleared out. To merge with other
-    // records that might be possibly going out, clearing out the information here helps
-    // as all of them try to get the zone data.
-    if (rr->nta)
-    {
-        // We always expect the question to be stopped when we get a valid response from the server.
-        // If the zone info tries to change during this time, updateid would be different and hence
-        // this response should not have been accepted.
-        if (rr->nta->question.ThisQInterval != -1)
-            LogMsg("hndlRecordUpdateReply: ResourceRecord %s, zone info question %##s (%s) interval %d not -1",
-                   ARDisplayString(m, rr), rr->nta->question.qname.c, DNSTypeName(rr->nta->question.qtype), rr->nta->question.ThisQInterval);
-        UpdatePort = rr->nta->Port;
-        CancelGetZoneData(m, rr->nta);
-        rr->nta = mDNSNULL;
-    }
-
-    // If we are deregistering the record, then complete the deregistration. Ignore any NAT/SRV change
-    // that could have happened during that time.
-    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->state == regState_DeregPending)
-    {
-        debugf("hndlRecordUpdateReply: Received reply for deregister record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype);
-        if (err) LogMsg("ERROR: Deregistration of record %##s type %d failed with error %d",
-                        rr->resrec.name->c, rr->resrec.rrtype, err);
-        rr->state = regState_Unregistered;
-        CompleteDeregistration(m, rr);
-        return;
-    }
-
-    // We are returning early without updating the state. When we come back from sleep we will re-register after
-    // re-initializing all the state as though it is a first registration. If the record can't be registered e.g.,
-    // no target, it will be deregistered. Hence, the updating to the right state should not matter when going
-    // to sleep.
-    if (m->SleepState)
-    {
-        // Need to set it to NoTarget state so that RecordReadyForSleep knows that
-        // we are done
-        if (rr->resrec.rrtype == kDNSType_SRV && rr->state == regState_DeregPending)
-            rr->state = regState_NoTarget;
-        return;
-    }
-
-    if (rr->state == regState_UpdatePending)
-    {
-        if (err) LogMsg("Update record failed for %##s (err %d)", rr->resrec.name->c, err);
-        rr->state = regState_Registered;
-        // deallocate old RData
-        if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData, rr->OrigRDLen);
-        SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
-        rr->OrigRData = mDNSNULL;
-        rr->InFlightRData = mDNSNULL;
-    }
-
-    if (rr->SRVChanged)
-    {
-        if (rr->resrec.rrtype == kDNSType_SRV)
-            hndlSRVChanged(m, rr);
-        else
-        {
-            LogInfo("hndlRecordUpdateReply: Deregistered %##s (%s), state %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->state);
-            rr->SRVChanged = mDNSfalse;
-            if (rr->state != regState_DeregPending) LogMsg("hndlRecordUpdateReply: ResourceRecord %s not in DeregPending state %d", ARDisplayString(m, rr), rr->state);
-            rr->state = regState_NoTarget;  // Wait for the next target change
-        }
-        return;
-    }
-
-    if (rr->state == regState_Pending || rr->state == regState_Refresh)
-    {
-        if (!err)
-        {
-            if (rr->state == regState_Refresh) InvokeCallback = mDNSfalse;
-            rr->state = regState_Registered;
-        }
-        else
-        {
-            // Retry without lease only for non-Private domains
-            LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %d", rr->resrec.name->c, rr->resrec.rrtype, err);
-            if (!rr->Private && rr->uselease && err == mStatus_UnknownErr && mDNSSameIPPort(UpdatePort, UnicastDNSPort))
-            {
-                LogMsg("hndlRecordUpdateReply: Will retry update of record %##s without lease option", rr->resrec.name->c);
-                rr->uselease = mDNSfalse;
-                rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-                rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-                SetNextuDNSEvent(m, rr);
-                return;
-            }
-            // Communicate the error to the application in the callback below
-        }
-    }
-
-    if (rr->QueuedRData && rr->state == regState_Registered)
-    {
-        rr->state = regState_UpdatePending;
-        rr->InFlightRData = rr->QueuedRData;
-        rr->InFlightRDLen = rr->QueuedRDLen;
-        rr->OrigRData = rr->resrec.rdata;
-        rr->OrigRDLen = rr->resrec.rdlength;
-        rr->QueuedRData = mDNSNULL;
-        rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-        rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-        SetNextuDNSEvent(m, rr);
-        return;
-    }
-
-    // Don't invoke the callback on error as this may not be useful to the client.
-    // The client may potentially delete the resource record on error which we normally
-    // delete during deregistration
-    if (!err && InvokeCallback && rr->RecordCallback)
-    {
-        LogInfo("hndlRecordUpdateReply: Calling record callback on %##s", rr->resrec.name->c);
-        mDNS_DropLockBeforeCallback();
-        rr->RecordCallback(m, rr, err);
-        mDNS_ReclaimLockAfterCallback();
-    }
-    // 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.
-}
-
-mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len)
-{
-    NATTraversalInfo *ptr;
-    NATAddrReply     *AddrReply    = (NATAddrReply    *)pkt;
-    NATPortMapReply  *PortMapReply = (NATPortMapReply *)pkt;
-    mDNSu32 nat_elapsed, our_elapsed;
-
-    // Minimum NAT-PMP packet is vers (1) opcode (1) + err (2) = 4 bytes
-    if (len < 4) { LogMsg("NAT-PMP message too short (%d bytes)", len); return; }
-
-    // Read multi-byte error value (field is identical in a NATPortMapReply)
-    AddrReply->err = (mDNSu16) ((mDNSu16)pkt[2] << 8 | pkt[3]);
-
-    if (AddrReply->err == NATErr_Vers)
-    {
-        NATTraversalInfo *n;
-        LogInfo("NAT-PMP version unsupported message received");
-        for (n = m->NATTraversals; n; n=n->next)
-        {
-            // Send a NAT-PMP request for this operation as needed
-            // and update the state variables
-            uDNS_SendNATMsg(m, n, mDNSfalse, mDNSfalse);
-        }
-
-        m->NextScheduledNATOp = m->timenow;
-
-        return;
-    }
-
-    // The minimum reasonable NAT-PMP packet length is vers (1) + opcode (1) + err (2) + upseconds (4) = 8 bytes
-    // If it's not at least this long, bail before we byte-swap the upseconds field & overrun our buffer.
-    // The retry timer will ensure we converge to correctness.
-    if (len < 8)
-    {
-        LogMsg("NAT-PMP message too short (%d bytes) 0x%X 0x%X", len, AddrReply->opcode, AddrReply->err);
-        return;
-    }
-
-    // Read multi-byte upseconds value (field is identical in a NATPortMapReply)
-    AddrReply->upseconds = (mDNSs32) ((mDNSs32)pkt[4] << 24 | (mDNSs32)pkt[5] << 16 | (mDNSs32)pkt[6] << 8 | pkt[7]);
-
-    nat_elapsed = AddrReply->upseconds - m->LastNATupseconds;
-    our_elapsed = (m->timenow - m->LastNATReplyLocalTime) / mDNSPlatformOneSecond;
-    debugf("uDNS_ReceiveNATPMPPacket %X upseconds %u nat_elapsed %d our_elapsed %d", AddrReply->opcode, AddrReply->upseconds, nat_elapsed, our_elapsed);
-
-    // We compute a conservative estimate of how much the NAT gateways's clock should have advanced
-    // 1. We subtract 12.5% from our own measured elapsed time, to allow for NAT gateways that have an inacurate clock that runs slowly
-    // 2. We add a two-second safety margin to allow for rounding errors: e.g.
-    //    -- if NAT gateway sends a packet at t=2.000 seconds, then one at t=7.999, that's approximately 6 real seconds,
-    //       but based on the values in the packet (2,7) the apparent difference according to the packet is only 5 seconds
-    //    -- if we're slow handling packets and/or we have coarse clock granularity,
-    //       we could receive the t=2 packet at our t=1.999 seconds, which we round down to 1
-    //       and the t=7.999 packet at our t=8.000 seconds, which we record as 8,
-    //       giving an apparent local time difference of 7 seconds
-    //    The two-second safety margin coves this possible calculation discrepancy
-    if (AddrReply->upseconds < m->LastNATupseconds || nat_elapsed + 2 < our_elapsed - our_elapsed/8)
-    { LogMsg("NAT-PMP epoch time check failed: assuming NAT gateway %#a rebooted", &m->Router); RecreateNATMappings(m, 0); }
-
-    m->LastNATupseconds      = AddrReply->upseconds;
-    m->LastNATReplyLocalTime = m->timenow;
-#ifdef _LEGACY_NAT_TRAVERSAL_
-    LNT_ClearState(m);
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-    if (AddrReply->opcode == NATOp_AddrResponse)
-    {
-        if (!AddrReply->err && len < sizeof(NATAddrReply)) { LogMsg("NAT-PMP AddrResponse message too short (%d bytes)", len); return; }
-        natTraversalHandleAddressReply(m, AddrReply->err, AddrReply->ExtAddr);
-    }
-    else if (AddrReply->opcode == NATOp_MapUDPResponse || AddrReply->opcode == NATOp_MapTCPResponse)
-    {
-        mDNSu8 Protocol = AddrReply->opcode & 0x7F;
-        if (!PortMapReply->err)
-        {
-            if (len < sizeof(NATPortMapReply)) { LogMsg("NAT-PMP PortMapReply message too short (%d bytes)", len); return; }
-            PortMapReply->NATRep_lease = (mDNSu32) ((mDNSu32)pkt[12] << 24 | (mDNSu32)pkt[13] << 16 | (mDNSu32)pkt[14] << 8 | pkt[15]);
-        }
-
-        // Since some NAT-PMP server implementations don't return the requested internal port in
-        // the reply, we can't associate this reply with a particular NATTraversalInfo structure.
-        // We globally keep track of the most recent error code for mappings.
-        m->LastNATMapResultCode = PortMapReply->err;
-
-        for (ptr = m->NATTraversals; ptr; ptr=ptr->next)
-            if (ptr->Protocol == Protocol && mDNSSameIPPort(ptr->IntPort, PortMapReply->intport))
-                natTraversalHandlePortMapReply(m, ptr, InterfaceID, PortMapReply->err, PortMapReply->extport, PortMapReply->NATRep_lease, NATTProtocolNATPMP);
-    }
-    else { LogMsg("Received NAT-PMP response with unknown opcode 0x%X", AddrReply->opcode); return; }
-
-    // Don't need an SSDP socket if we get a NAT-PMP packet
-    if (m->SSDPSocket) { debugf("uDNS_ReceiveNATPMPPacket destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
-}
-
-mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len)
-{
-    NATTraversalInfo *ptr;
-    PCPMapReply *reply = (PCPMapReply*)pkt;
-    mDNSu32 client_delta, server_delta;
-    mDNSBool checkEpochValidity = m->LastNATupseconds != 0;
-    mDNSu8 strippedOpCode;
-    mDNSv4Addr mappedAddress = zerov4Addr;
-    mDNSu8 protocol = 0;
-    mDNSIPPort intport = zeroIPPort;
-    mDNSIPPort extport = zeroIPPort;
-
-    // Minimum PCP packet is 24 bytes
-    if (len < 24)
-    {
-        LogMsg("uDNS_ReceivePCPPacket: message too short (%d bytes)", len);
-        return;
-    }
-
-    strippedOpCode = reply->opCode & 0x7f;
-
-    if ((reply->opCode & 0x80) == 0x00 || (strippedOpCode != PCPOp_Announce && strippedOpCode != PCPOp_Map))
-    {
-        LogMsg("uDNS_ReceivePCPPacket: unhandled opCode %u", reply->opCode);
-        return;
-    }
-
-    // Read multi-byte values
-    reply->lifetime = (mDNSs32)((mDNSs32)pkt[4] << 24 | (mDNSs32)pkt[5] << 16 | (mDNSs32)pkt[ 6] << 8 | pkt[ 7]);
-    reply->epoch    = (mDNSs32)((mDNSs32)pkt[8] << 24 | (mDNSs32)pkt[9] << 16 | (mDNSs32)pkt[10] << 8 | pkt[11]);
-
-    client_delta = (m->timenow - m->LastNATReplyLocalTime) / mDNSPlatformOneSecond;
-    server_delta = reply->epoch - m->LastNATupseconds;
-    debugf("uDNS_ReceivePCPPacket: %X %X upseconds %u client_delta %d server_delta %d", reply->opCode, reply->result, reply->epoch, client_delta, server_delta);
-
-    // If seconds since the epoch is 0, use 1 so we'll check epoch validity next time
-    m->LastNATupseconds      = reply->epoch ? reply->epoch : 1;
-    m->LastNATReplyLocalTime = m->timenow;
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-    LNT_ClearState(m);
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-    // Don't need an SSDP socket if we get a PCP packet
-    if (m->SSDPSocket) { debugf("uDNS_ReceivePCPPacket: destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
-
-    if (checkEpochValidity && (client_delta + 2 < server_delta - server_delta / 16 || server_delta + 2 < client_delta - client_delta / 16))
-    {
-        // If this is an ANNOUNCE packet, wait a random interval up to 5 seconds
-        // otherwise, refresh immediately
-        mDNSu32 waitTicks = strippedOpCode ? 0 : mDNSRandom(PCP_WAITSECS_AFTER_EPOCH_INVALID * mDNSPlatformOneSecond);
-        LogMsg("uDNS_ReceivePCPPacket: Epoch invalid, %#a likely rebooted, waiting %u ticks", &m->Router, waitTicks);
-        RecreateNATMappings(m, waitTicks);
-        // we can ignore the rest of this packet, as new requests are about to go out
-        return;
-    }
-
-    if (strippedOpCode == PCPOp_Announce)
-        return;
-
-    // We globally keep track of the most recent error code for mappings.
-    // This seems bad to do with PCP, but best not change it now.
-    m->LastNATMapResultCode = reply->result;
-
-    if (!reply->result)
-    {
-        if (len < sizeof(PCPMapReply))
-        {
-            LogMsg("uDNS_ReceivePCPPacket: mapping response too short (%d bytes)", len);
-            return;
-        }
-
-        // Check the nonce
-        if (reply->nonce[0] != m->PCPNonce[0] || reply->nonce[1] != m->PCPNonce[1] || reply->nonce[2] != m->PCPNonce[2])
-        {
-            LogMsg("uDNS_ReceivePCPPacket: invalid nonce, ignoring. received { %x %x %x } expected { %x %x %x }",
-                   reply->nonce[0], reply->nonce[1], reply->nonce[2],
-                    m->PCPNonce[0],  m->PCPNonce[1],  m->PCPNonce[2]);
-            return;
-        }
-
-        // Get the values
-        protocol = reply->protocol;
-        intport = reply->intPort;
-        extport = reply->extPort;
-
-        // Get the external address, which should be mapped, since we only support IPv4
-        if (!mDNSAddrIPv4FromMappedIPv6(&reply->extAddress, &mappedAddress))
-        {
-            LogMsg("uDNS_ReceivePCPPacket: unexpected external address: %.16a", &reply->extAddress);
-            reply->result = NATErr_NetFail;
-            // fall through to report the error
-        }
-        else if (mDNSIPv4AddressIsZero(mappedAddress))
-        {
-            // If this is the deletion case, we will have sent the zero IPv4-mapped address
-            // in our request, and the server should reflect it in the response, so we
-            // should not log about receiving a zero address. And in this case, we no
-            // longer have a NATTraversal to report errors back to, so it's ok to set the
-            // result here.
-            // In other cases, a zero address is an error, and we will have a NATTraversal
-            // to report back to, so set an error and fall through to report it.
-            // CheckNATMappings will log the error.
-            reply->result = NATErr_NetFail;
-        }
-    }
-    else
-    {
-        LogInfo("uDNS_ReceivePCPPacket: error received from server. opcode %X result %X lifetime %X epoch %X",
-                reply->opCode, reply->result, reply->lifetime, reply->epoch);
-
-        // If the packet is long enough, get the protocol & intport for matching to report
-        // the error
-        if (len >= sizeof(PCPMapReply))
-        {
-            protocol = reply->protocol;
-            intport = reply->intPort;
-        }
-    }
-
-    for (ptr = m->NATTraversals; ptr; ptr=ptr->next)
-    {
-        mDNSu8 ptrProtocol = ((ptr->Protocol & NATOp_MapTCP) == NATOp_MapTCP ? PCPProto_TCP : PCPProto_UDP);
-        if ((protocol == ptrProtocol && mDNSSameIPPort(ptr->IntPort, intport)) ||
-            (!ptr->Protocol && protocol == PCPProto_TCP && mDNSSameIPPort(DiscardPort, intport)))
-        {
-            natTraversalHandlePortMapReplyWithAddress(m, ptr, InterfaceID, reply->result ? NATErr_NetFail : NATErr_None, mappedAddress, extport, reply->lifetime, NATTProtocolPCP);
-        }
-    }
-}
-
-mDNSexport void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len)
-{
-    if (len == 0)
-        LogMsg("uDNS_ReceiveNATPacket: zero length packet");
-    else if (pkt[0] == PCP_VERS)
-        uDNS_ReceivePCPPacket(m, InterfaceID, pkt, len);
-    else if (pkt[0] == NATMAP_VERS)
-        uDNS_ReceiveNATPMPPacket(m, InterfaceID, pkt, len);
-    else
-        LogMsg("uDNS_ReceiveNATPacket: packet with version %u (expected %u or %u)", pkt[0], PCP_VERS, NATMAP_VERS);
-}
-
-// Called from mDNSCoreReceive with the lock held
-mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
-{
-    DNSQuestion *qptr;
-    mStatus err = mStatus_NoError;
-
-    mDNSu8 StdR    = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
-    mDNSu8 UpdateR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
-    mDNSu8 QR_OP   = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
-    mDNSu8 rcode   = (mDNSu8)(msg->h.flags.b[1] & kDNSFlag1_RC_Mask);
-
-    (void)srcport; // Unused
-
-    debugf("uDNS_ReceiveMsg from %#-15a with "
-           "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
-           srcaddr,
-           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", end - msg->data);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (NumUnreachableDNSServers > 0)
-        SymptomReporterDNSServerReachable(m, srcaddr);
-#endif
-
-    if (QR_OP == StdR)
-    {
-        //if (srcaddr && recvLLQResponse(m, msg, end, srcaddr, srcport)) return;
-        for (qptr = m->Questions; qptr; qptr = qptr->next)
-            if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW)
-            {
-                if (!srcaddr) LogMsg("uDNS_ReceiveMsg: TCP DNS response had TC bit set: ignoring");
-                else
-                {
-                    uDNS_RestartQuestionAsTCP(m, qptr, srcaddr, srcport);
-                }
-            }
-    }
-
-    if (QR_OP == UpdateR)
-    {
-        mDNSu32 pktlease = 0;
-        mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease);
-        mDNSu32 lease = gotlease ? pktlease : 60 * 60; // If lease option missing, assume one hour
-        mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond;
-        mDNSu32 random = mDNSRandom((mDNSs32)lease * mDNSPlatformOneSecond/10);
-
-        //rcode = kDNSFlag1_RC_ServFail;    // Simulate server failure (rcode 2)
-
-        // Walk through all the records that matches the messageID. There could be multiple
-        // records if we had sent them in a group
-        if (m->CurrentRecord)
-            LogMsg("uDNS_ReceiveMsg ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
-        m->CurrentRecord = m->ResourceRecords;
-        while (m->CurrentRecord)
-        {
-            AuthRecord *rptr = m->CurrentRecord;
-            m->CurrentRecord = m->CurrentRecord->next;
-            if (AuthRecord_uDNS(rptr) && mDNSSameOpaque16(rptr->updateid, msg->h.id))
-            {
-                err = checkUpdateResult(m, rptr->resrec.name, rcode, msg, end);
-                if (!err && rptr->uselease && lease)
-                    if (rptr->expire - expire >= 0 || rptr->state != regState_UpdatePending)
-                    {
-                        rptr->expire = expire;
-                        rptr->refreshCount = 0;
-                    }
-                // We pass the random value to make sure that if we update multiple
-                // records, they all get the same random value
-                hndlRecordUpdateReply(m, rptr, err, random);
-            }
-        }
-    }
-    debugf("Received unexpected response: ID %d matches no active records", mDNSVal16(msg->h.id));
-}
-
-// ***************************************************************************
-// MARK: - Query Routines
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
-{
-    mDNSu8 *end;
-    LLQOptData llq;
-
-    if (q->ReqLease)
-        if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "Unable to refresh LLQ " PRI_DM_NAME " (" PUB_S ") - will retry in %d seconds",
-                DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), LLQ_POLL_INTERVAL / mDNSPlatformOneSecond);
-            StartLLQPolling(m,q);
-            return;
-        }
-
-    llq.vers     = kLLQ_Vers;
-    llq.llqOp    = kLLQOp_Refresh;
-    llq.err      = q->tcp ? GetLLQEventPort(m, &q->servAddr) : LLQErr_NoError;  // If using TCP tell server what UDP port to send notifications to
-    llq.id       = q->id;
-    llq.llqlease = q->ReqLease;
-
-    InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-    end = putLLQ(&m->omsg, m->omsg.data, q, &llq);
-    if (!end)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "sendLLQRefresh: putLLQ failed " PRI_DM_NAME " (" PUB_S ")", DM_NAME_PARAM(&q->qname),
-            DNSTypeName(q->qtype));
-        return;
-    }
-
-    {
-        mStatus err;
-
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "sendLLQRefresh: using existing UDP session " PRI_DM_NAME " (" PUB_S ")", DM_NAME_PARAM(&q->qname),
-            DNSTypeName(q->qtype));
-
-        err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->tcp ? q->tcp->sock : mDNSNULL, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSfalse);
-        if (err)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "sendLLQRefresh: mDNSSendDNSMessage" PUB_S " failed: %d", q->tcp ? " (TCP)" : "", err);
-            if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
-        }
-    }
-
-    q->ntries++;
-
-    debugf("sendLLQRefresh ntries %d %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype));
-
-    q->LastQTime = m->timenow;
-    SetNextQueryTime(m, q);
-}
-
-mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo)
-{
-    DNSQuestion *q = (DNSQuestion *)zoneInfo->ZoneDataContext;
-
-    mDNS_Lock(m);
-
-    // If we get here it means that the GetZoneData operation has completed.
-    // We hold on to the zone data if it is AutoTunnel as we use the hostname
-    // in zoneInfo during the TLS connection setup.
-    q->servAddr = zeroAddr;
-    q->servPort = zeroIPPort;
-
-    if (!err && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0])
-    {
-        q->servAddr = zoneInfo->Addr;
-        q->servPort = zoneInfo->Port;
-        // We don't need the zone data as we use it only for the Host information which we
-        // don't need if we are not going to use TLS connections.
-        if (q->nta)
-        {
-            if (q->nta != zoneInfo) LogMsg("LLQGotZoneData: nta (%p) != zoneInfo (%p)  %##s (%s)", q->nta, zoneInfo, q->qname.c, DNSTypeName(q->qtype));
-            CancelGetZoneData(m, q->nta);
-            q->nta = mDNSNULL;
-        }
-        q->ntries = 0;
-        debugf("LLQGotZoneData %#a:%d", &q->servAddr, mDNSVal16(q->servPort));
-        startLLQHandshake(m, q);
-    }
-    else
-    {
-        if (q->nta)
-        {
-            if (q->nta != zoneInfo) LogMsg("LLQGotZoneData: nta (%p) != zoneInfo (%p)  %##s (%s)", q->nta, zoneInfo, q->qname.c, DNSTypeName(q->qtype));
-            CancelGetZoneData(m, q->nta);
-            q->nta = mDNSNULL;
-        }
-        StartLLQPolling(m,q);
-        if (err == mStatus_NoSuchNameErr)
-        {
-            // this actually failed, so mark it by setting address to all ones
-            q->servAddr.type = mDNSAddrType_IPv4;
-            q->servAddr.ip.v4 = onesIPv4Addr;
-        }
-    }
-
-    mDNS_Unlock(m);
-}
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-mDNSlocal mDNSBool SubscribeToDNSPushServer(mDNS *m, DNSQuestion *q,
-    DNSPushZone **const outZone, DNSPushServer **const outServer);
-
-mDNSlocal const char *DNSPushServerConnectStateToString(DNSPushServer_ConnectState state);
-
-mDNSexport void DNSPushGotZoneData(mDNS *const m, const mStatus err, const ZoneData *const zoneInfo)
-{
-    DNSQuestion *const q = (DNSQuestion *)zoneInfo->ZoneDataContext;
-    const mDNSu32 requestID = q->request_id;
-    const mDNSu16 questionID = mDNSVal16(q->TargetQID);
-    const mDNSu16 subquestionID = mDNSVal16(zoneInfo->question.TargetQID);
-    mDNSBool succeeded;
-    mDNS_Lock(m);
-
-    if (err != mStatus_NoError)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[R%u->Q%u->subQ%u] Failed to get the zone data - err: %d.",
-            requestID, questionID, subquestionID, err);
-        succeeded = mDNSfalse;
-        goto exit;
-    }
-
-    // If we get here it means that the GetZoneData operation has completed.
-    q->servAddr = zeroAddr;
-    q->servPort = zeroIPPort;
-
-    // We should always have zone information if no error happens.
-    if (zoneInfo == mDNSNULL || mDNSIPPortIsZero(zoneInfo->Port) || zoneInfo->Host.c[0] == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "[R%u->Q%u->subQ%u] Invalid zoneInfo.", requestID,
-            questionID, subquestionID);
-        succeeded = mDNSfalse;
-        goto exit;
-    }
-
-    // Start connecting to the DNS push server we found.
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u->subQ%u] Found a new DNS push server for the served zone - "
-        "server: " PRI_DM_NAME ":%d, zone: " PRI_DM_NAME ".", requestID, questionID, subquestionID,
-        DM_NAME_PARAM(&zoneInfo->Host), mDNSVal16(zoneInfo->Port), DM_NAME_PARAM(&zoneInfo->ZoneName));
-
-    q->state = LLQ_DNSPush_Connecting;
-    succeeded = SubscribeToDNSPushServer(m, q, &q->dnsPushZone, &q->dnsPushServer);
-    if (!succeeded)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[R%u->Q%u] Failed to connect to the DNS push server.",
-            requestID, questionID);
-        goto exit;
-    }
-
-    const DNSPushServer_ConnectState state = q->dnsPushServer->connectState;
-    // Valid state checking, should never fail.
-    if (state != DNSPushServerConnectionInProgress &&
-        state != DNSPushServerConnected &&
-        state != DNSPushServerSessionEstablished)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "[R%u->Q%u->PushS%u] Invalid DNS push server state - "
-            "state: " PUB_S ".", requestID, questionID, q->dnsPushServer->serial,
-            DNSPushServerConnectStateToString(state));
-        DNSPushServerCancel(q->dnsPushServer, mDNSfalse);
-        goto exit;
-    }
-
-exit:
-    if (!succeeded)
-    {
-        // If we are unable to connect to the DNS push server for some reason, fall back to LLQ poll.
-        StartLLQPolling(m, q);
-    }
-    mDNS_Unlock(m);
-}
-#endif
-
-// ***************************************************************************
-// MARK: - Dynamic Updates
-
-// Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1)
-mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
-{
-    AuthRecord *newRR;
-    AuthRecord *ptr;
-    int c1, c2;
-
-    if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; }
-
-    newRR = (AuthRecord*)zoneData->ZoneDataContext;
-
-    if (newRR->nta != zoneData)
-        LogMsg("RecordRegistrationGotZoneData: nta (%p) != zoneData (%p)  %##s (%s)", newRR->nta, zoneData, newRR->resrec.name->c, DNSTypeName(newRR->resrec.rrtype));
-
-    mDNS_VerifyLockState("Check Lock", mDNSfalse, m->mDNS_busy, m->mDNS_reentrancy, __func__, __LINE__);
-
-    // make sure record is still in list (!!!)
-    for (ptr = m->ResourceRecords; ptr; ptr = ptr->next) if (ptr == newRR) break;
-    if (!ptr)
-    {
-        LogMsg("RecordRegistrationGotZoneData - RR no longer in list.  Discarding.");
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    // check error/result
-    if (err)
-    {
-        if (err != mStatus_NoSuchNameErr) LogMsg("RecordRegistrationGotZoneData: error %d", err);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    if (newRR->resrec.rrclass != zoneData->ZoneClass)
-    {
-        LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)", newRR->resrec.rrclass, zoneData->ZoneClass);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    // Don't try to do updates to the root name server.
-    // We might be tempted also to block updates to any single-label name server (e.g. com, edu, net, etc.) but some
-    // organizations use their own private pseudo-TLD, like ".home", etc, and we don't want to block that.
-    if (zoneData->ZoneName.c[0] == 0)
-    {
-        LogInfo("RecordRegistrationGotZoneData: No name server found claiming responsibility for \"%##s\"!", newRR->resrec.name->c);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    // Store discovered zone data
-    c1 = CountLabels(newRR->resrec.name);
-    c2 = CountLabels(&zoneData->ZoneName);
-    if (c2 > c1)
-    {
-        LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" is longer than \"%##s\"", zoneData->ZoneName.c, newRR->resrec.name->c);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-    newRR->zone = SkipLeadingLabels(newRR->resrec.name, c1-c2);
-    if (!SameDomainName(newRR->zone, &zoneData->ZoneName))
-    {
-        LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" does not match \"%##s\" for \"%##s\"", newRR->zone->c, zoneData->ZoneName.c, newRR->resrec.name->c);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr) || !zoneData->Host.c[0])
-    {
-        LogInfo("RecordRegistrationGotZoneData: No _dns-update._udp service found for \"%##s\"!", newRR->resrec.name->c);
-        CancelGetZoneData(m, newRR->nta);
-        newRR->nta = mDNSNULL;
-        return;
-    }
-
-    newRR->Private      = zoneData->ZonePrivate;
-    debugf("RecordRegistrationGotZoneData: Set zone information for %##s %##s to %#a:%d",
-           newRR->resrec.name->c, zoneData->ZoneName.c, &zoneData->Addr, mDNSVal16(zoneData->Port));
-
-    // If we are deregistering, uDNS_DeregisterRecord will do that as it has the zone data now.
-    if (newRR->state == regState_DeregPending)
-    {
-        mDNS_Lock(m);
-        uDNS_DeregisterRecord(m, newRR);
-        mDNS_Unlock(m);
-        return;
-    }
-
-    if (newRR->resrec.rrtype == kDNSType_SRV)
-    {
-        const domainname *target;
-        // Reevaluate the target always as NAT/Target could have changed while
-        // we were fetching zone data.
-        mDNS_Lock(m);
-        target = GetServiceTarget(m, newRR);
-        mDNS_Unlock(m);
-        if (!target || target->c[0] == 0)
-        {
-            domainname *t = GetRRDomainNameTarget(&newRR->resrec);
-            LogInfo("RecordRegistrationGotZoneData - no target for %##s", newRR->resrec.name->c);
-            if (t) t->c[0] = 0;
-            newRR->resrec.rdlength = newRR->resrec.rdestimate = 0;
-            newRR->state = regState_NoTarget;
-            CancelGetZoneData(m, newRR->nta);
-            newRR->nta = mDNSNULL;
-            return;
-        }
-    }
-    // If we have non-zero service port (always?)
-    // and a private address, and update server is non-private
-    // and this service is AutoTarget
-    // then initiate a NAT mapping request. On completion it will do SendRecordRegistration() for us
-    if (newRR->resrec.rrtype == kDNSType_SRV && !mDNSIPPortIsZero(newRR->resrec.rdata->u.srv.port) &&
-        mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && newRR->nta && !mDNSAddrIsRFC1918(&newRR->nta->Addr) &&
-        newRR->AutoTarget == Target_AutoHostAndNATMAP)
-    {
-        // During network transitions, we are called multiple times in different states. Setup NAT
-        // state just once for this record.
-        if (!newRR->NATinfo.clientContext)
-        {
-            LogInfo("RecordRegistrationGotZoneData StartRecordNatMap %s", ARDisplayString(m, newRR));
-            newRR->state = regState_NATMap;
-            StartRecordNatMap(m, newRR);
-            return;
-        }
-        else LogInfo("RecordRegistrationGotZoneData: StartRecordNatMap for %s, state %d, context %p", ARDisplayString(m, newRR), newRR->state, newRR->NATinfo.clientContext);
-    }
-    mDNS_Lock(m);
-    // We want IsRecordMergeable to check whether it is a record whose update can be
-    // sent with others. We set the time before we call IsRecordMergeable, so that
-    // it does not fail this record based on time. We are interested in other checks
-    // at this time. If a previous update resulted in error, then don't reset the
-    // interval. Preserve the back-off so that we don't keep retrying aggressively.
-    if (newRR->updateError == mStatus_NoError)
-    {
-        newRR->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-        newRR->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-    }
-    if (IsRecordMergeable(m, newRR, m->timenow + MERGE_DELAY_TIME))
-    {
-        // Delay the record registration by MERGE_DELAY_TIME so that we can merge them
-        // into one update
-        LogInfo("RecordRegistrationGotZoneData: Delayed registration for %s", ARDisplayString(m, newRR));
-        newRR->LastAPTime += MERGE_DELAY_TIME;
-    }
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
-{
-    mDNSu8 *ptr = m->omsg.data;
-    mDNSu8 *limit;
-    DomainAuthInfo *AuthInfo;
-
-    mDNS_CheckLock(m);
-
-    if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
-    {
-        LogMsg("SendRecordDeRegistration: No zone info for Resource record %s RecordType %d", ARDisplayString(m, rr), rr->resrec.RecordType);
-        return;
-    }
-
-    limit = ptr + AbsoluteMaxDNSMessageData;
-    AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
-    limit -= RRAdditionalSize(AuthInfo);
-
-    rr->updateid = mDNS_NewMessageID(m);
-    InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags);
-
-    // set zone
-    ptr = putZone(&m->omsg, ptr, limit, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
-    if (!ptr) goto exit;
-
-    ptr = BuildUpdateMessage(m, ptr, rr, limit);
-
-    if (!ptr) goto exit;
-
-    if (rr->Private)
-    {
-        LogInfo("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
-        if (rr->tcp) LogInfo("SendRecordDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr));
-        if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
-        if (!rr->nta) { LogMsg("SendRecordDeregistration:Private:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
-        rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->nta->Addr, rr->nta->Port, &rr->nta->Host, mDNSNULL, rr);
-    }
-    else
-    {
-        mStatus err;
-        LogInfo("SendRecordDeregistration UDP %s", ARDisplayString(m, rr));
-        if (!rr->nta) { LogMsg("SendRecordDeregistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
-        err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, mDNSNULL, &rr->nta->Addr, rr->nta->Port, GetAuthInfoForName_internal(m, rr->resrec.name), mDNSfalse);
-        if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err);
-        //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr);        // Don't touch rr after this
-    }
-    SetRecordRetry(m, rr, 0);
-    return;
-exit:
-    LogMsg("SendRecordDeregistration: Error formatting message for %s", ARDisplayString(m, rr));
-}
-
-mDNSexport mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr)
-{
-    DomainAuthInfo *info;
-
-    LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: Resource Record " PRI_S ", state %d", ARDisplayString(m, rr), rr->state);
-
-    switch (rr->state)
-    {
-    case regState_Refresh:
-    case regState_Pending:
-    case regState_UpdatePending:
-    case regState_Registered: break;
-    case regState_DeregPending: break;
-
-    case regState_NATError:
-    case regState_NATMap:
-    // A record could be in NoTarget to start with if the corresponding SRV record could not find a target.
-    // It is also possible to reenter the NoTarget state when we move to a network with a NAT that has
-    // no {PCP, NAT-PMP, UPnP/IGD} support. In that case before we entered NoTarget, we already deregistered with
-    // the server.
-    case regState_NoTarget:
-    case regState_Unregistered:
-    case regState_Zero:
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: State %d for " PRI_DM_NAME " type " PUB_S,
-            rr->state, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype));
-        // This function may be called during sleep when there are no sleep proxy servers
-        if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) CompleteDeregistration(m, rr);
-        return mStatus_NoError;
-    }
-
-    // if unsent rdata is queued, free it.
-    //
-    // The data may be queued in QueuedRData or InFlightRData.
-    //
-    // 1) If the record is in Registered state, we store it in InFlightRData and copy the same in "rdata"
-    //   *just* before sending the update to the server. Till we get the response, InFlightRData and "rdata"
-    //   in the resource record are same. We don't want to free in that case. It will be freed when "rdata"
-    //   is freed. If they are not same, the update has not been sent and we should free it here.
-    //
-    // 2) If the record is in UpdatePending state, we queue the update in QueuedRData. When the previous update
-    //   comes back from the server, we copy it from QueuedRData to InFlightRData and repeat (1). This implies
-    //   that QueuedRData can never be same as "rdata" in the resource record. As long as we have something
-    //   left in QueuedRData, we should free it here.
-
-    if (rr->InFlightRData && rr->UpdateCallback)
-    {
-        if (rr->InFlightRData != rr->resrec.rdata)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: Freeing InFlightRData for " PRI_S, ARDisplayString(m, rr));
-            rr->UpdateCallback(m, rr, rr->InFlightRData, rr->InFlightRDLen);
-            rr->InFlightRData = mDNSNULL;
-        }
-        else
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: InFlightRData same as rdata for " PRI_S, ARDisplayString(m, rr));
-    }
-
-    if (rr->QueuedRData && rr->UpdateCallback)
-    {
-        if (rr->QueuedRData == rr->resrec.rdata)
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: ERROR!! QueuedRData same as rdata for " PRI_S, ARDisplayString(m, rr));
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: Freeing QueuedRData for " PRI_S, ARDisplayString(m, rr));
-            rr->UpdateCallback(m, rr, rr->QueuedRData, rr->QueuedRDLen);
-            rr->QueuedRData = mDNSNULL;
-        }
-    }
-
-    // If a current group registration is pending, we can't send this deregisration till that registration
-    // has reached the server i.e., the ordering is important. Previously, if we did not send this
-    // registration in a group, then the previous connection will be torn down as part of sending the
-    // deregistration. If we send this in a group, we need to locate the resource record that was used
-    // to send this registration and terminate that connection. This means all the updates on that might
-    // be lost (assuming the response is not waiting for us at the socket) and the retry will send the
-    // update again sometime in the near future.
-    //
-    // NOTE: SSL handshake failures normally free the TCP connection immediately. Hence, you may not
-    // find the TCP below there. This case can happen only when tcp is trying to actively retransmit
-    // the request or SSL negotiation taking time i.e resource record is actively trying to get the
-    // message to the server. During that time a deregister has to happen.
-
-    if (!mDNSOpaque16IsZero(rr->updateid))
-    {
-        AuthRecord *anchorRR;
-        mDNSBool found = mDNSfalse;
-        for (anchorRR = m->ResourceRecords; anchorRR; anchorRR = anchorRR->next)
-        {
-            if (AuthRecord_uDNS(rr) && mDNSSameOpaque16(anchorRR->updateid, rr->updateid) && anchorRR->tcp)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: Found Anchor RR " PRI_S " terminated", ARDisplayString(m, anchorRR));
-                if (found)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNS_DeregisterRecord: ERROR: Another anchorRR " PRI_S " found",
-                        ARDisplayString(m, anchorRR));
-                }
-                DisposeTCPConn(anchorRR->tcp);
-                anchorRR->tcp = mDNSNULL;
-                found = mDNStrue;
-            }
-        }
-        if (!found)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_DEFAULT, "uDNSDeregisterRecord: Cannot find the anchor Resource Record for " PRI_S ", not an error",
-                ARDisplayString(m, rr));
-        }
-    }
-
-    // Retry logic for deregistration should be no different from sending registration the first time.
-    // Currently ThisAPInterval most likely is set to the refresh interval
-    rr->state          = regState_DeregPending;
-    rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-    rr->LastAPTime     = m->timenow - INIT_RECORD_REG_INTERVAL;
-    info = GetAuthInfoForName_internal(m, rr->resrec.name);
-    if (IsRecordMergeable(m, rr, m->timenow + MERGE_DELAY_TIME))
-    {
-        // Delay the record deregistration by MERGE_DELAY_TIME so that we can merge them
-        // into one update. If the domain is being deleted, delay by 2 * MERGE_DELAY_TIME
-        // so that we can merge all the AutoTunnel records and the service records in
-        // one update (they get deregistered a little apart)
-        if (info && info->deltime) rr->LastAPTime += (2 * MERGE_DELAY_TIME);
-        else rr->LastAPTime += MERGE_DELAY_TIME;
-    }
-    // IsRecordMergeable could have returned false for several reasons e.g., DontMerge is set or
-    // no zone information. Most likely it is the latter, CheckRecordUpdates will fetch the zone
-    // data when it encounters this record.
-
-    if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-        m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr)
-{
-    LogInfo("uDNS_UpdateRecord: Resource Record %##s, state %d", rr->resrec.name->c, rr->state);
-    switch(rr->state)
-    {
-    case regState_DeregPending:
-    case regState_Unregistered:
-        // not actively registered
-        goto unreg_error;
-
-    case regState_NATMap:
-    case regState_NoTarget:
-        // change rdata directly since it hasn't been sent yet
-        if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->resrec.rdata, rr->resrec.rdlength);
-        SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
-        rr->NewRData = mDNSNULL;
-        return mStatus_NoError;
-
-    case regState_Pending:
-    case regState_Refresh:
-    case regState_UpdatePending:
-        // registration in-flight. queue rdata and return
-        if (rr->QueuedRData && rr->UpdateCallback)
-            // if unsent rdata is already queued, free it before we replace it
-            rr->UpdateCallback(m, rr, rr->QueuedRData, rr->QueuedRDLen);
-        rr->QueuedRData = rr->NewRData;
-        rr->QueuedRDLen = rr->newrdlength;
-        rr->NewRData = mDNSNULL;
-        return mStatus_NoError;
-
-    case regState_Registered:
-        rr->OrigRData = rr->resrec.rdata;
-        rr->OrigRDLen = rr->resrec.rdlength;
-        rr->InFlightRData = rr->NewRData;
-        rr->InFlightRDLen = rr->newrdlength;
-        rr->NewRData = mDNSNULL;
-        rr->state = regState_UpdatePending;
-        rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
-        rr->LastAPTime = m->timenow - INIT_RECORD_REG_INTERVAL;
-        SetNextuDNSEvent(m, rr);
-        return mStatus_NoError;
-
-    case regState_Zero:
-    case regState_NATError:
-        LogMsg("ERROR: uDNS_UpdateRecord called for record %##s with bad state regState_NATError", rr->resrec.name->c);
-        return mStatus_UnknownErr;      // states for service records only
-    }
-    LogMsg("uDNS_UpdateRecord: Unknown state %d for %##s", rr->state, rr->resrec.name->c);
-
-unreg_error:
-    LogMsg("uDNS_UpdateRecord: Requested update of record %##s type %d, in erroneous state %d",
-           rr->resrec.name->c, rr->resrec.rrtype, rr->state);
-    return mStatus_Invalid;
-}
-
-// ***************************************************************************
-// MARK: - Periodic Execution Routines
-
-mDNSlocal const char *LLQStateToString(LLQ_State state);
-
-mDNSlocal void uDNS_HandleLLQState(mDNS *const NONNULL m, DNSQuestion *const NONNULL q)
-{
-    const LLQ_State prevState = q->state;
-    mDNSBool fallBackToLLQPoll = mDNSfalse;
-
-#if !MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    (void)m;  // Only used for LLQ
-#endif
-
-    switch (prevState)
-    {
-        case LLQ_Init:
-            // If DNS Push isn't supported, LLQ_Init falls through to LLQ_InitialRequest.
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-            // First attempt to use DNS Push.
-            DiscoverDNSPushServer(m, q);
-            break;
-        case LLQ_DNSPush_ServerDiscovery:
-            // If mDNResponder is still looking for the available DNS push server, the question should not have a DNS
-            // push server assigned.
-            if (q->dnsPushServer != mDNSNULL)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[Q%u->PushS%u] Already have a DNS push server while DNS push server discovery is in progress - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ", server state: " PUB_S ".", mDNSVal16(q->TargetQID),
-                    q->dnsPushServer->serial, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-                    DNSPushServerConnectStateToString(q->dnsPushServer->connectState));
-                // This is an invalid case. It means the DNS push server assigned to this question is not valid.
-                // Therefore, the question should undo all the operation related to this DNS push server, and fall back
-                // to LLQ poll.
-                UnsubscribeQuestionFromDNSPushServer(m, q, mDNSfalse);
-                fallBackToLLQPoll = mDNStrue;
-            }
-            break;
-        case LLQ_DNSPush_Connecting:
-            // If mDNSResponder is in the middle of connecting to the DNS push server, then it should already have
-            // a DNS push server assigned.
-            if (q->dnsPushServer == mDNSNULL)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[Q%u] Have no DNS push server assigned while the connection to the DNS push server is in progress - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype));
-                // This is an invalid case. It means the question is in a bad state where it has no DNS push server
-                // assigned but it thought it has. Therefore, the question should fall back to LLQ poll.
-                if (q->dnsPushZone != mDNSNULL)
-                {
-                    DNS_PUSH_RELEASE(q->dnsPushZone, DNSPushZoneFinalize);
-                    q->dnsPushZone = mDNSNULL;
-                }
-                fallBackToLLQPoll = mDNStrue;
-            }
-            else if (q->dnsPushServer->connectState != DNSPushServerConnectionInProgress &&
-                     q->dnsPushServer->connectState != DNSPushServerConnected &&
-                     q->dnsPushServer->connectState != DNSPushServerSessionEstablished)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[Q%u->PushS%u] Question state is LLQ_DNSPush_Connecting but the corresponding DNS push server is not in the right state - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ", server state: " PUB_S ".", mDNSVal16(q->TargetQID),
-                    q->dnsPushServer->serial, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-                    DNSPushServerConnectStateToString(q->dnsPushServer->connectState));
-                // This is an invalid case. It means the question's state and the DNS push server's state do not match.
-                // In which case, the question should fall back to LLQ poll.
-                UnsubscribeQuestionFromDNSPushServer(m, q, mDNSfalse);
-                fallBackToLLQPoll = mDNStrue;
-            }
-            break;
-        case LLQ_DNSPush_Established:
-            // If the question state indicates that the session has been established, then the question must have
-            // a DNS push server assigned.
-            if (q->dnsPushServer != mDNSNULL)
-            {
-                if (q->dnsPushServer->connectState != DNSPushServerSessionEstablished)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                        "[Q%u->PushS%u] server state does not match question state - "
-                        ", qname: " PRI_DM_NAME ", question state: " PUB_S ", server state: " PUB_S ".",
-                        mDNSVal16(q->TargetQID), q->dnsPushServer->serial, DM_NAME_PARAM(&q->qname),
-                        LLQStateToString(q->state), DNSPushServerConnectStateToString(q->dnsPushServer->connectState));
-                    // This is an invalid case. It means the question's state and the DNS push server's state do not match.
-                    // In which case, the question should fall back to LLQ poll.
-                    UnsubscribeQuestionFromDNSPushServer(m, q, mDNSfalse);
-                    fallBackToLLQPoll = mDNStrue;
-                }
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[Q%u] DNS push session is established but the question does not have DNS push server assigned - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype));
-                // This is an invalid case. It means that the question is in a bad state. Therefore the question should
-                // fall back to LLQ poll.
-                if (q->dnsPushZone != mDNSNULL)
-                {
-                    DNS_PUSH_RELEASE(q->dnsPushZone, DNSPushZoneFinalize);
-                    q->dnsPushZone = mDNSNULL;
-                }
-                fallBackToLLQPoll = mDNStrue;
-            }
-            break;
-#else // MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-        // These are never reached without DNS Push support.
-        case LLQ_DNSPush_ServerDiscovery:
-        case LLQ_DNSPush_Connecting:
-        case LLQ_DNSPush_Established:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "[Q%u] Question is in DNS push state but DNS push is not supported - "
-                "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-                DNSTypeName(q->qtype));
-            break;
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-        case LLQ_InitialRequest:   startLLQHandshake(m, q); break;
-        case LLQ_SecondaryRequest: sendChallengeResponse(m, q, mDNSNULL); break;
-        case LLQ_Established:      sendLLQRefresh(m, q); break;
-        case LLQ_Poll:             break;       // Do nothing (handled below)
-        case LLQ_Invalid:          break;
-#else
-        case LLQ_InitialRequest:   // Fall through to poll
-        case LLQ_SecondaryRequest: // Fall through to poll
-        case LLQ_Established:      // Fall through to poll
-        case LLQ_Poll:
-            fallBackToLLQPoll = mDNStrue;
-            break;
-        case LLQ_Invalid:          break;
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
-    }
-
-    if (fallBackToLLQPoll)
-    {
-        StartLLQPolling(m, q);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u->PushS%u] LLQ_State changes - "
-        "from: " PUB_S ", to: " PUB_S ", qname: " PRI_DM_NAME ", qtype: " PUB_S ".", q->request_id,
-        mDNSVal16(q->TargetQID), q->dnsPushServer != mDNSNULL ? q->dnsPushServer->serial : DNS_PUSH_SERVER_INVALID_SERIAL,
-        LLQStateToString(prevState), LLQStateToString(q->state), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-#else
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] LLQ_State changes - "
-        "from: " PUB_S ", to: " PUB_S ", qname: " PRI_DM_NAME ", qtype: " PUB_S ".", q->request_id,
-        mDNSVal16(q->TargetQID), LLQStateToString(prevState), LLQStateToString(q->state), DM_NAME_PARAM(&q->qname),
-        DNSTypeName(q->qtype));
-#endif
-}
-
-// The question to be checked is not passed in as an explicit parameter;
-// instead it is implicit that the question to be checked is m->CurrentQuestion.
-mDNSlocal void uDNS_CheckCurrentQuestion(mDNS *const m)
-{
-    DNSQuestion *q = m->CurrentQuestion;
-    if (m->timenow - NextQSendTime(q) < 0) return;
-
-    if (q->LongLived)
-    {
-        uDNS_HandleLLQState(m,q);
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-        // If the question is doing DNS push, then we do not give it to the querier to send the regular unicast query,
-        // until the DNS push fails.
-        if (DNS_PUSH_IN_PROGRESS(q->state))
-        {
-            if (!q->LongLived)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[Q%u] DNS Push is active for this question, but the question is not long-lived - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype));
-            }
-            q->LastQTime = m->timenow;
-            return;
-        }
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    Querier_HandleUnicastQuestion(q);
-#else
-    // We repeat the check above (rather than just making this the "else" case) because startLLQHandshake can change q->state to LLQ_Poll
-    if (!(q->LongLived && q->state != LLQ_Poll))
-    {
-        if (q->unansweredQueries >= MAX_UCAST_UNANSWERED_QUERIES)
-        {
-            DNSServer *orig = q->qDNSServer;
-            if (orig)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u->Q%u] uDNS_CheckCurrentQuestion: Sent %d unanswered queries for " PRI_DM_NAME " (" PUB_S ") to " PRI_IP_ADDR ":%d (" PRI_DM_NAME ")",
-                          q->request_id, mDNSVal16(q->TargetQID), q->unansweredQueries, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), &orig->addr, mDNSVal16(orig->port), DM_NAME_PARAM(&orig->domain));
-            }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-            SymptomReporterDNSServerUnreachable(orig);
-#endif
-            PenalizeDNSServer(m, q, zeroID);
-            q->noServerResponse = 1;
-        }
-        // There are two cases here.
-        //
-        // 1. We have only one DNS server for this question. It is not responding even after we sent MAX_UCAST_UNANSWERED_QUERIES.
-        //    In that case, we need to keep retrying till we get a response. But we need to backoff as we retry. We set
-        //    noServerResponse in the block above and below we do not touch the question interval. When we come here, we
-        //    already waited for the response. We need to send another query right at this moment. We do that below by
-        //    reinitializing dns servers and reissuing the query.
-        //
-        // 2. We have more than one DNS server. If at least one server did not respond, we would have set noServerResponse
-        //    either now (the last server in the list) or before (non-last server in the list). In either case, if we have
-        //    reached the end of DNS server list, we need to try again from the beginning. Ideally we should try just the
-        //    servers that did not respond, but for simplicity we try all the servers. Once we reached the end of list, we
-        //    set triedAllServersOnce so that we don't try all the servers aggressively. See PenalizeDNSServer.
-        if (!q->qDNSServer && q->noServerResponse)
-        {
-            DNSServer *new;
-            DNSQuestion *qptr;
-            q->triedAllServersOnce = mDNStrue;
-            // Re-initialize all DNS servers for this question. If we have a DNSServer, DNSServerChangeForQuestion will
-            // handle all the work including setting the new DNS server.
-            SetValidDNSServers(m, q);
-            new = GetServerForQuestion(m, q);
-            if (new)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u->Q%u] uDNS_checkCurrentQuestion: Retrying question %p " PRI_DM_NAME " (" PUB_S ") DNS Server " PRI_IP_ADDR ":%d ThisQInterval %d",
-                          q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), new ? &new->addr : mDNSNULL, mDNSVal16(new ? new->port : zeroIPPort), q->ThisQInterval);
-                DNSServerChangeForQuestion(m, q, new);
-            }
-            for (qptr = q->next ; qptr; qptr = qptr->next)
-                if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
-        }
-        if (q->qDNSServer)
-        {
-            mDNSu8 *end;
-            mStatus err = mStatus_NoError;
-            mDNSOpaque16 HeaderFlags = uQueryFlags;
-
-            InitializeDNSMessage(&m->omsg.h, q->TargetQID, HeaderFlags);
-            end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
-
-            if (end > m->omsg.data)
-            {
-                debugf("uDNS_CheckCurrentQuestion sending %p %##s (%s) %#a:%d UnansweredQueries %d",
-                       q, q->qname.c, DNSTypeName(q->qtype),
-                       q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->unansweredQueries);
-                if (!q->LocalSocket)
-                {
-                    q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort);
-                    if (q->LocalSocket)
-                    {
-                        mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, mDNSAddrType_IPv4, q);
-                        mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, mDNSAddrType_IPv6, q);
-                    }
-                }
-                if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time
-                else
-                {
-                    err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, mDNSNULL, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, q->UseBackgroundTraffic);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-                    if (!err)
-                    {
-                        bool isForCell  = q->qDNSServer->isCell;
-                        dnssd_analytics_update_dns_query_size(isForCell, dns_transport_Do53, (uint32_t)(end - (mDNSu8 *)&m->omsg));
-                        if (q->metrics.answered)
-                        {
-                            q->metrics.querySendCount = 0;
-                            q->metrics.answered       = mDNSfalse;
-                        }
-                        if (q->metrics.querySendCount++ == 0)
-                        {
-                            q->metrics.firstQueryTime = NonZeroTime(m->timenow);
-                        }
-                    }
-#endif
-				}
-            }
-
-            if (err == mStatus_HostUnreachErr)
-            {
-                DNSServer *newServer;
-
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u->Q%u] uDNS_CheckCurrentQuestion: host unreachable error for DNS server " PRI_IP_ADDR " for question [%p] " PRI_DM_NAME " (" PUB_S ")",
-                          q->request_id, mDNSVal16(q->TargetQID), &q->qDNSServer->addr, q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-
-                if (!StrictUnicastOrdering)
-                {
-                    q->qDNSServer->penaltyTime = NonZeroTime(m->timenow + DNSSERVER_PENALTY_TIME);
-                }
-
-                newServer = GetServerForQuestion(m, q);
-                if (!newServer)
-                {
-                    q->triedAllServersOnce = mDNStrue;
-                    SetValidDNSServers(m, q);
-                    newServer = GetServerForQuestion(m, q);
-                }
-                if (newServer)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[R%u->Q%u] uDNS_checkCurrentQuestion: Retrying question %p " PRI_DM_NAME " (" PUB_S ") DNS Server " PRI_IP_ADDR ":%u ThisQInterval %d",
-                              q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-                              newServer ? &newServer->addr : mDNSNULL, mDNSVal16(newServer ? newServer->port : zeroIPPort), q->ThisQInterval);
-                    DNSServerChangeForQuestion(m, q, newServer);
-                }
-                if (q->triedAllServersOnce)
-                {
-                    q->LastQTime = m->timenow;
-                }
-                else
-                {
-                    q->ThisQInterval = InitialQuestionInterval;
-                    q->LastQTime     = m->timenow - q->ThisQInterval;
-                }
-                q->unansweredQueries = 0;
-            }
-            else
-            {
-                if (err != mStatus_TransientErr)   // if it is not a transient error backoff and DO NOT flood queries unnecessarily
-                {
-                    // If all DNS Servers are not responding, then we back-off using the multiplier UDNSBackOffMultiplier(*2).
-                    // Only increase interval if send succeeded
-
-                    q->ThisQInterval = q->ThisQInterval * UDNSBackOffMultiplier;
-                    if ((q->ThisQInterval > 0) && (q->ThisQInterval < MinQuestionInterval))  // We do not want to retx within 1 sec
-                        q->ThisQInterval = MinQuestionInterval;
-
-                    q->unansweredQueries++;
-                    if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL)
-                        q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
-                    if (q->qDNSServer->isCell)
-                    {
-                        // We don't want to retransmit too soon. Schedule our first retransmisson at
-                        // MIN_UCAST_RETRANS_TIMEOUT seconds.
-                        if (q->ThisQInterval < MIN_UCAST_RETRANS_TIMEOUT)
-                            q->ThisQInterval = MIN_UCAST_RETRANS_TIMEOUT;
-                    }
-                    debugf("uDNS_CheckCurrentQuestion: Increased ThisQInterval to %d for %##s (%s), cell %d", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer->isCell);
-                }
-                q->LastQTime = m->timenow;
-            }
-            SetNextQueryTime(m, q);
-        }
-        else
-        {
-            // If we have no server for this query, or the only server is a disabled one, then we deliver
-            // a transient failure indication to the client. This is important for things like iPhone
-            // where we want to return timely feedback to the user when no network is available.
-            // After calling MakeNegativeCacheRecord() we store the resulting record in the
-            // cache so that it will be visible to other clients asking the same question.
-            // (When we have a group of identical questions, only the active representative of the group gets
-            // passed to uDNS_CheckCurrentQuestion -- we only want one set of query packets hitting the wire --
-            // but we want *all* of the questions to get answer callbacks.)
-            CacheRecord *cr;
-            const mDNSu32 slot = HashSlotFromNameHash(q->qnamehash);
-            CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
-
-            if (!q->qDNSServer)
-            {
-                if (!mDNSOpaque128IsZero(&q->validDNSServers))
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                              "[R%u->Q%u] uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x 0x%x 0x%x for question " PRI_DM_NAME " (" PUB_S ")",
-                              q->request_id, mDNSVal16(q->TargetQID), q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0], DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-                // If we reached the end of list while picking DNS servers, then we don't want to deactivate the
-                // question. Try after 60 seconds. We find this by looking for valid DNSServers for this question,
-                // if we find any, then we must have tried them before we came here. This avoids maintaining
-                // another state variable to see if we had valid DNS servers for this question.
-                SetValidDNSServers(m, q);
-                if (mDNSOpaque128IsZero(&q->validDNSServers))
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[R%u->Q%u] uDNS_CheckCurrentQuestion: no DNS server for " PRI_DM_NAME " (" PUB_S ")",
-                              q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-                    q->ThisQInterval = 0;
-                }
-                else
-                {
-                    DNSQuestion *qptr;
-                    // Pretend that we sent this question. As this is an ActiveQuestion, the NextScheduledQuery should
-                    // be set properly. Also, we need to properly backoff in cases where we don't set the question to
-                    // MaxQuestionInterval when we answer the question e.g., LongLived, we need to keep backing off
-                    q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep;
-                    q->LastQTime = m->timenow;
-                    SetNextQueryTime(m, q);
-                    // Pick a new DNS server now. Otherwise, when the cache is 80% of its expiry, we will try
-                    // to send a query and come back to the same place here and log the above message.
-                    q->qDNSServer = GetServerForQuestion(m, q);
-                    for (qptr = q->next ; qptr; qptr = qptr->next)
-                        if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[R%u->Q%u] uDNS_checkCurrentQuestion: Tried all DNS servers, retry question %p SuppressUnusable %d " PRI_DM_NAME " (" PUB_S ") with DNS Server " PRI_IP_ADDR ":%d after 60 seconds, ThisQInterval %d",
-                              q->request_id, mDNSVal16(q->TargetQID), q, q->SuppressUnusable, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-                              q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->ThisQInterval);
-                }
-            }
-            else
-            {
-                q->ThisQInterval = 0;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u->Q%u] uDNS_CheckCurrentQuestion DNS server " PRI_IP_ADDR ":%d for " PRI_DM_NAME " is disabled",
-                          q->request_id, mDNSVal16(q->TargetQID), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), DM_NAME_PARAM(&q->qname));
-            }
-
-            if (cg)
-            {
-                for (cr = cg->members; cr; cr=cr->next)
-                {
-                    if (SameNameCacheRecordAnswersQuestion(cr, q))
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                                  "[R%u->Q%u] uDNS_CheckCurrentQuestion: Purged resourcerecord " PRI_S,
-                                  q->request_id, mDNSVal16(q->TargetQID), CRDisplayString(m, cr));
-                        mDNS_PurgeCacheResourceRecord(m, cr);
-                    }
-                }
-            }
-            // For some of the WAB queries that we generate form within the mDNSResponder, most of the home routers
-            // don't understand and return ServFail/NXDomain. In those cases, we don't want to try too often. We try
-            // every fifteen minutes in that case
-            q->unansweredQueries = 0;
-            const mDNSOpaque16 responseFlags = !mDNSOpaque16IsZero(q->responseFlags) ? q->responseFlags : ResponseFlags;
-            MakeNegativeCacheRecordForQuestion(m, &m->rec.r, q, (DomainEnumQuery(&q->qname) ? 60 * 15 : 60),
-                mDNSInterface_Any, responseFlags);
-            // We're already using the m->CurrentQuestion pointer, so CacheRecordAdd can't use it to walk the question list.
-            // To solve this problem we set cr->DelayDelivery to a nonzero value (which happens to be 'now') so that we
-            // momentarily defer generating answer callbacks until mDNS_Execute time.
-            CreateNewCacheEntry(m, slot, cg, NonZeroTime(m->timenow), mDNStrue, mDNSNULL);
-            ScheduleNextCacheCheckTime(m, slot, NonZeroTime(m->timenow));
-            m->rec.r.responseFlags = zeroID;
-            mDNSCoreResetRecord(m);
-            // MUST NOT touch m->CurrentQuestion (or q) after this -- client callback could have deleted it
-        }
-    }
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-}
-
-mDNSexport void CheckNATMappings(mDNS *m)
-{
-    mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4);
-    mDNSBool HaveRoutable = !rfc1918 && !mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4);
-    m->NextScheduledNATOp = m->timenow + FutureTime;
-
-    if (HaveRoutable) m->ExtAddress = m->AdvertisedV4.ip.v4;
-
-    if (m->NATTraversals && rfc1918)            // Do we need to open a socket to receive multicast announcements from router?
-    {
-        if (m->NATMcastRecvskt == mDNSNULL)     // If we are behind a NAT and the socket hasn't been opened yet, open it
-        {
-            // we need to log a message if we can't get our socket, but only the first time (after success)
-            static mDNSBool needLog = mDNStrue;
-            m->NATMcastRecvskt = mDNSPlatformUDPSocket(NATPMPAnnouncementPort);
-            if (!m->NATMcastRecvskt)
-            {
-                if (needLog)
-                {
-                    LogMsg("CheckNATMappings: Failed to allocate port 5350 UDP multicast socket for PCP & NAT-PMP announcements");
-                    needLog = mDNSfalse;
-                }
-            }
-            else
-                needLog = mDNStrue;
-        }
-    }
-    else                                        // else, we don't want to listen for announcements, so close them if they're open
-    {
-        if (m->NATMcastRecvskt) { mDNSPlatformUDPClose(m->NATMcastRecvskt); m->NATMcastRecvskt = mDNSNULL; }
-        if (m->SSDPSocket)      { debugf("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
-    }
-
-    uDNS_RequestAddress(m);
-
-    if (m->CurrentNATTraversal) LogMsg("WARNING m->CurrentNATTraversal already in use");
-    m->CurrentNATTraversal = m->NATTraversals;
-
-    while (m->CurrentNATTraversal)
-    {
-        NATTraversalInfo *cur = m->CurrentNATTraversal;
-        mDNSv4Addr EffectiveAddress = HaveRoutable ? m->AdvertisedV4.ip.v4 : cur->NewAddress;
-        m->CurrentNATTraversal = m->CurrentNATTraversal->next;
-
-        if (HaveRoutable)       // If not RFC 1918 address, our own address and port are effectively our external address and port
-        {
-            cur->ExpiryTime = 0;
-            cur->NewResult  = mStatus_NoError;
-        }
-        else // Check if it's time to send port mapping packet(s)
-        {
-            if (m->timenow - cur->retryPortMap >= 0) // Time to send a mapping request for this packet
-            {
-                if (cur->ExpiryTime && cur->ExpiryTime - m->timenow < 0)    // Mapping has expired
-                {
-                    cur->ExpiryTime    = 0;
-                    cur->retryInterval = NATMAP_INIT_RETRY;
-                }
-
-                uDNS_SendNATMsg(m, cur, mDNStrue, mDNSfalse); // Will also do UPnP discovery for us, if necessary
-
-                if (cur->ExpiryTime)                        // If have active mapping then set next renewal time halfway to expiry
-                    NATSetNextRenewalTime(m, cur);
-                else                                        // else no mapping; use exponential backoff sequence
-                {
-                    if      (cur->retryInterval < NATMAP_INIT_RETRY            ) cur->retryInterval = NATMAP_INIT_RETRY;
-                    else if (cur->retryInterval < NATMAP_MAX_RETRY_INTERVAL / 2) cur->retryInterval *= 2;
-                    else cur->retryInterval = NATMAP_MAX_RETRY_INTERVAL;
-                    cur->retryPortMap = m->timenow + cur->retryInterval;
-                }
-            }
-
-            if (m->NextScheduledNATOp - cur->retryPortMap > 0)
-            {
-                m->NextScheduledNATOp = cur->retryPortMap;
-            }
-        }
-
-        // Notify the client if necessary. We invoke the callback if:
-        // (1) We have an effective address,
-        //     or we've tried and failed a couple of times to discover it
-        // AND
-        // (2) the client requested the address only,
-        //     or the client won't need a mapping because we have a routable address,
-        //     or the client has an expiry time and therefore a successful mapping,
-        //     or we've tried and failed a couple of times (see "Time line" below)
-        // AND
-        // (3) we have new data to give the client that's changed since the last callback
-        //
-        // Time line is: Send, Wait 500ms, Send, Wait 1sec, Send, Wait 2sec, Send
-        // At this point we've sent three requests without an answer, we've just sent our fourth request,
-        // retryInterval is now 4 seconds, which is greater than NATMAP_INIT_RETRY * 8 (2 seconds),
-        // so we return an error result to the caller.
-        if (!mDNSIPv4AddressIsZero(EffectiveAddress) || cur->retryInterval > NATMAP_INIT_RETRY * 8)
-        {
-            const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&EffectiveAddress) ? mStatus_DoubleNAT : mStatus_NoError;
-            const mDNSIPPort ExternalPort = HaveRoutable ? cur->IntPort :
-                                            !mDNSIPv4AddressIsZero(EffectiveAddress) && cur->ExpiryTime ? cur->RequestedPort : zeroIPPort;
-
-            if (!cur->Protocol || HaveRoutable || cur->ExpiryTime || cur->retryInterval > NATMAP_INIT_RETRY * 8)
-            {
-                if (!mDNSSameIPv4Address(cur->ExternalAddress, EffectiveAddress) ||
-                    !mDNSSameIPPort     (cur->ExternalPort,       ExternalPort)    ||
-                    cur->Result != EffectiveResult)
-                {
-                    //LogMsg("NAT callback %d %d %d", cur->Protocol, cur->ExpiryTime, cur->retryInterval);
-                    if (cur->Protocol && mDNSIPPortIsZero(ExternalPort) && !mDNSIPv4AddressIsZero(m->Router.ip.v4))
-                    {
-                        if (!EffectiveResult)
-                            LogInfo("CheckNATMapping: Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d",
-                                    cur, &m->Router, &EffectiveAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult);
-                        else
-                            LogMsg("CheckNATMapping: Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d",
-                                   cur, &m->Router, &EffectiveAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult);
-                    }
-
-                    cur->ExternalAddress = EffectiveAddress;
-                    cur->ExternalPort    = ExternalPort;
-                    cur->Lifetime        = cur->ExpiryTime && !mDNSIPPortIsZero(ExternalPort) ?
-                                           (cur->ExpiryTime - m->timenow + mDNSPlatformOneSecond/2) / mDNSPlatformOneSecond : 0;
-                    cur->Result          = EffectiveResult;
-                    mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
-                    if (cur->clientCallback)
-                        cur->clientCallback(m, cur);
-                    mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
-                    // MUST NOT touch cur after invoking the callback
-                }
-            }
-        }
-    }
-}
-
-mDNSlocal mDNSs32 CheckRecordUpdates(mDNS *m)
-{
-    AuthRecord *rr;
-    mDNSs32 nextevent = m->timenow + FutureTime;
-
-    CheckGroupRecordUpdates(m);
-
-    for (rr = m->ResourceRecords; rr; rr = rr->next)
-    {
-        if (!AuthRecord_uDNS(rr)) continue;
-        if (rr->state == regState_NoTarget) {debugf("CheckRecordUpdates: Record %##s in NoTarget", rr->resrec.name->c); continue;}
-        // While we are waiting for the port mapping, we have nothing to do. The port mapping callback
-        // will take care of this
-        if (rr->state == regState_NATMap) {debugf("CheckRecordUpdates: Record %##s in NATMap", rr->resrec.name->c); continue;}
-        if (rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending ||
-            rr->state == regState_Refresh || rr->state == regState_Registered)
-        {
-            if (rr->LastAPTime + rr->ThisAPInterval - m->timenow <= 0)
-            {
-                if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
-                if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
-                {
-                    // Zero out the updateid so that if we have a pending response from the server, it won't
-                    // be accepted as a valid response. If we accept the response, we might free the new "nta"
-                    if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); }
-                    rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
-
-                    // We have just started the GetZoneData. We need to wait for it to finish. SetRecordRetry here
-                    // schedules the update timer to fire in the future.
-                    //
-                    // There are three cases.
-                    //
-                    // 1) When the updates are sent the first time, the first retry is intended to be at three seconds
-                    //    in the future. But by calling SetRecordRetry here we set it to nine seconds. But it does not
-                    //    matter because when the answer comes back, RecordRegistrationGotZoneData resets the interval
-                    //    back to INIT_RECORD_REG_INTERVAL. This also gives enough time for the query.
-                    //
-                    // 2) In the case of update errors (updateError), this causes further backoff as
-                    //    RecordRegistrationGotZoneData does not reset the timer. This is intentional as in the case of
-                    //    errors, we don't want to update aggressively.
-                    //
-                    // 3) We might be refreshing the update. This is very similar to case (1). RecordRegistrationGotZoneData
-                    //    resets it back to INIT_RECORD_REG_INTERVAL.
-                    //
-                    SetRecordRetry(m, rr, 0);
-                }
-                else if (rr->state == regState_DeregPending) SendRecordDeregistration(m, rr);
-                else SendRecordRegistration(m, rr);
-            }
-        }
-        if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0)
-            nextevent = (rr->LastAPTime + rr->ThisAPInterval);
-    }
-    return nextevent;
-}
-
-mDNSexport void uDNS_Tasks(mDNS *const m)
-{
-    mDNSs32 nexte;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer *d;
-#endif
-
-    m->NextuDNSEvent = m->timenow + FutureTime;
-
-    nexte = CheckRecordUpdates(m);
-    if (m->NextuDNSEvent - nexte > 0)
-        m->NextuDNSEvent = nexte;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    for (d = m->DNSServers; d; d=d->next)
-        if (d->penaltyTime)
-        {
-            if (m->timenow - d->penaltyTime >= 0)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "DNS server " PRI_IP_ADDR ":%d out of penalty box", &d->addr, mDNSVal16(d->port));
-                d->penaltyTime = 0;
-            }
-            else
-            if (m->NextuDNSEvent - d->penaltyTime > 0)
-                m->NextuDNSEvent = d->penaltyTime;
-        }
-#endif
-
-    if (m->CurrentQuestion)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "uDNS_Tasks ERROR m->CurrentQuestion already set: " PRI_DM_NAME " (" PRI_S ")",
-                  DM_NAME_PARAM(&m->CurrentQuestion->qname), DNSTypeName(m->CurrentQuestion->qtype));
-    }
-    m->CurrentQuestion = m->Questions;
-    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-    {
-        DNSQuestion *const q = m->CurrentQuestion;
-        if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID))
-        {
-            uDNS_CheckCurrentQuestion(m);
-            if (q == m->CurrentQuestion)
-                if (m->NextuDNSEvent - NextQSendTime(q) > 0)
-                    m->NextuDNSEvent = NextQSendTime(q);
-        }
-        // If m->CurrentQuestion wasn't modified out from under us, advance it now
-        // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion()
-        // depends on having m->CurrentQuestion point to the right question
-        if (m->CurrentQuestion == q)
-            m->CurrentQuestion = q->next;
-    }
-    m->CurrentQuestion = mDNSNULL;
-}
-
-// ***************************************************************************
-// MARK: - Startup, Shutdown, and Sleep
-
-mDNSexport void SleepRecordRegistrations(mDNS *m)
-{
-    AuthRecord *rr;
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        if (AuthRecord_uDNS(rr))
-        {
-            // Zero out the updateid so that if we have a pending response from the server, it won't
-            // be accepted as a valid response.
-            if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
-
-            if (rr->NATinfo.clientContext)
-            {
-                mDNS_StopNATOperation_internal(m, &rr->NATinfo);
-                rr->NATinfo.clientContext = mDNSNULL;
-            }
-            // We are waiting to update the resource record. The original data of the record is
-            // in OrigRData and the updated value is in InFlightRData. Free the old and the new
-            // one will be registered when we come back.
-            if (rr->state == regState_UpdatePending)
-            {
-                // act as if the update succeeded, since we're about to delete the name anyway
-                rr->state = regState_Registered;
-                // deallocate old RData
-                if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData, rr->OrigRDLen);
-                SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen);
-                rr->OrigRData = mDNSNULL;
-                rr->InFlightRData = mDNSNULL;
-            }
-
-            // If we have not begun the registration process i.e., never sent a registration packet,
-            // then uDNS_DeregisterRecord will not send a deregistration
-            uDNS_DeregisterRecord(m, rr);
-
-            // When we wake, we call ActivateUnicastRegistration which starts at StartGetZoneData
-        }
-    }
-}
-
-mDNSexport void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID)
-{
-    SearchListElem **p;
-    SearchListElem *tmp = mDNSNULL;
-
-    // Check to see if we already have this domain in our list
-    for (p = &SearchList; *p; p = &(*p)->next)
-        if (((*p)->InterfaceID == InterfaceID) && SameDomainName(&(*p)->domain, domain))
-        {
-            // If domain is already in list, and marked for deletion, unmark the delete
-            // Be careful not to touch the other flags that may be present
-            LogInfo("mDNS_AddSearchDomain already in list %##s", domain->c);
-            if ((*p)->flag & SLE_DELETE) (*p)->flag &= ~SLE_DELETE;
-            tmp = *p;
-            *p = tmp->next;
-            tmp->next = mDNSNULL;
-            break;
-        }
-
-
-    // move to end of list so that we maintain the same order
-    while (*p) p = &(*p)->next;
-
-    if (tmp) *p = tmp;
-    else
-    {
-        // if domain not in list, add to list, mark as add (1)
-        *p = (SearchListElem *) mDNSPlatformMemAllocateClear(sizeof(**p));
-        if (!*p) { LogMsg("ERROR: mDNS_AddSearchDomain - malloc"); return; }
-        AssignDomainName(&(*p)->domain, domain);
-        (*p)->next = mDNSNULL;
-        (*p)->InterfaceID = InterfaceID;
-        LogInfo("mDNS_AddSearchDomain created new %##s, InterfaceID %p", domain->c, InterfaceID);
-    }
-}
-
-mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;    // unused
-    if (result == mStatus_MemFree) mDNSPlatformMemFree(rr->RecordContext);
-}
-
-mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    SearchListElem *slElem = question->QuestionContext;
-    mStatus err;
-    const char *name;
-
-    if (answer->rrtype != kDNSType_PTR) return;
-    if (answer->RecordType == kDNSRecordTypePacketNegative) return;
-    if (answer->InterfaceID == mDNSInterface_LocalOnly) return;
-
-    if      (question == &slElem->BrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
-    else if (question == &slElem->DefBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
-    else if (question == &slElem->AutomaticBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseAutomatic];
-    else if (question == &slElem->RegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
-    else if (question == &slElem->DefRegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
-    else { LogMsg("FoundDomain - unknown question"); return; }
-
-    LogInfo("FoundDomain: %p %s %s Q %##s A %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", name, question->qname.c, RRDisplayString(m, answer));
-
-    if (AddRecord)
-    {
-        ARListElem *arElem = (ARListElem *) mDNSPlatformMemAllocateClear(sizeof(*arElem));
-        if (!arElem) { LogMsg("ERROR: FoundDomain out of memory"); return; }
-        mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, arElem);
-        MakeDomainNameFromDNSNameString(&arElem->ar.namestorage, name);
-        AppendDNSNameString            (&arElem->ar.namestorage, "local");
-        AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
-        LogInfo("FoundDomain: Registering %s", ARDisplayString(m, &arElem->ar));
-        err = mDNS_Register(m, &arElem->ar);
-        if (err) { LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err); mDNSPlatformMemFree(arElem); return; }
-        arElem->next = slElem->AuthRecs;
-        slElem->AuthRecs = arElem;
-    }
-    else
-    {
-        ARListElem **ptr = &slElem->AuthRecs;
-        while (*ptr)
-        {
-            if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, &answer->rdata->u.name))
-            {
-                ARListElem *dereg = *ptr;
-                *ptr = (*ptr)->next;
-                LogInfo("FoundDomain: Deregistering %s", ARDisplayString(m, &dereg->ar));
-                err = mDNS_Deregister(m, &dereg->ar);
-                if (err) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err);
-                // Memory will be freed in the FreeARElemCallback
-            }
-            else
-                ptr = &(*ptr)->next;
-        }
-    }
-}
-
-
-// This should probably move to the UDS daemon -- the concept of legacy clients and automatic registration / automatic browsing
-// is really a UDS API issue, not something intrinsic to uDNS
-
-mDNSlocal void uDNS_DeleteWABQueries(mDNS *const m, SearchListElem *ptr, int delete)
-{
-    const char *name1 = mDNSNULL;
-    const char *name2 = mDNSNULL;
-    ARListElem **arList = &ptr->AuthRecs;
-    domainname namestorage1, namestorage2;
-    mStatus err;
-
-    // "delete" parameter indicates the type of query.
-    switch (delete)
-    {
-    case UDNS_WAB_BROWSE_QUERY:
-        mDNS_StopGetDomains(m, &ptr->BrowseQ);
-        mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
-        name1 = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
-        name2 = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
-        break;
-    case UDNS_WAB_LBROWSE_QUERY:
-        mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
-        name1 = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseAutomatic];
-        break;
-    case UDNS_WAB_REG_QUERY:
-        mDNS_StopGetDomains(m, &ptr->RegisterQ);
-        mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
-        name1 = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
-        name2 = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
-        break;
-    default:
-        LogMsg("uDNS_DeleteWABQueries: ERROR!! returning from default");
-        return;
-    }
-    // When we get the results to the domain enumeration queries, we add a LocalOnly
-    // entry. For example, if we issue a domain enumeration query for b._dns-sd._udp.xxxx.com,
-    // and when we get a response, we add a LocalOnly entry b._dns-sd._udp.local whose RDATA
-    // points to what we got in the response. Locate the appropriate LocalOnly entries and delete
-    // them.
-    if (name1)
-    {
-        MakeDomainNameFromDNSNameString(&namestorage1, name1);
-        AppendDNSNameString(&namestorage1, "local");
-    }
-    if (name2)
-    {
-        MakeDomainNameFromDNSNameString(&namestorage2, name2);
-        AppendDNSNameString(&namestorage2, "local");
-    }
-    while (*arList)
-    {
-        ARListElem *dereg = *arList;
-        if ((name1 && SameDomainName(&dereg->ar.namestorage, &namestorage1)) ||
-            (name2 && SameDomainName(&dereg->ar.namestorage, &namestorage2)))
-        {
-            LogInfo("uDNS_DeleteWABQueries: Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
-            *arList = dereg->next;
-            err = mDNS_Deregister(m, &dereg->ar);
-            if (err) LogMsg("uDNS_DeleteWABQueries:: ERROR!! mDNS_Deregister returned %d", err);
-            // Memory will be freed in the FreeARElemCallback
-        }
-        else
-        {
-            LogInfo("uDNS_DeleteWABQueries: Skipping PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
-            arList = &(*arList)->next;
-        }
-    }
-}
-
-mDNSexport void uDNS_SetupWABQueries(mDNS *const m)
-{
-    SearchListElem **p = &SearchList, *ptr;
-    mStatus err;
-    int action = 0;
-
-    // step 1: mark each element for removal
-    for (ptr = SearchList; ptr; ptr = ptr->next)
-        ptr->flag |= SLE_DELETE;
-
-    // Make sure we have the search domains from the platform layer so that if we start the WAB
-    // queries below, we have the latest information.
-    mDNS_Lock(m);
-    if (!mDNSPlatformSetDNSConfig(mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL, mDNSfalse))
-    {
-        // If the configuration did not change, clear the flag so that we don't free the searchlist.
-        // We still have to start the domain enumeration queries as we may not have started them
-        // before.
-        for (ptr = SearchList; ptr; ptr = ptr->next)
-            ptr->flag &= ~SLE_DELETE;
-        LogInfo("uDNS_SetupWABQueries: No config change");
-    }
-    mDNS_Unlock(m);
-
-    if (m->WABBrowseQueriesCount)
-        action |= UDNS_WAB_BROWSE_QUERY;
-    if (m->WABLBrowseQueriesCount)
-        action |= UDNS_WAB_LBROWSE_QUERY;
-    if (m->WABRegQueriesCount)
-        action |= UDNS_WAB_REG_QUERY;
-
-
-    // delete elems marked for removal, do queries for elems marked add
-    while (*p)
-    {
-        ptr = *p;
-        LogInfo("uDNS_SetupWABQueries:action 0x%x: Flags 0x%x,  AuthRecs %p, InterfaceID %p %##s", action, ptr->flag, ptr->AuthRecs, ptr->InterfaceID, ptr->domain.c);
-        // If SLE_DELETE is set, stop all the queries, deregister all the records and free the memory.
-        // Otherwise, check to see what the "action" requires. If a particular action bit is not set and
-        // we have started the corresponding queries as indicated by the "flags", stop those queries and
-        // deregister the records corresponding to them.
-        if ((ptr->flag & SLE_DELETE) ||
-            (!(action & UDNS_WAB_BROWSE_QUERY) && (ptr->flag & SLE_WAB_BROWSE_QUERY_STARTED)) ||
-            (!(action & UDNS_WAB_LBROWSE_QUERY) && (ptr->flag & SLE_WAB_LBROWSE_QUERY_STARTED)) ||
-            (!(action & UDNS_WAB_REG_QUERY) && (ptr->flag & SLE_WAB_REG_QUERY_STARTED)))
-        {
-            if (ptr->flag & SLE_DELETE)
-            {
-                ARListElem *arList = ptr->AuthRecs;
-                ptr->AuthRecs = mDNSNULL;
-                *p = ptr->next;
-
-                // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
-                // We suppressed the domain enumeration for scoped search domains below. When we enable that
-                // enable this.
-                if ((ptr->flag & SLE_WAB_BROWSE_QUERY_STARTED) &&
-                    !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-                {
-                    LogInfo("uDNS_SetupWABQueries: DELETE  Browse for domain  %##s", ptr->domain.c);
-                    mDNS_StopGetDomains(m, &ptr->BrowseQ);
-                    mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
-                }
-                if ((ptr->flag & SLE_WAB_LBROWSE_QUERY_STARTED) &&
-                    !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-                {
-                    LogInfo("uDNS_SetupWABQueries: DELETE  Legacy Browse for domain  %##s", ptr->domain.c);
-                    mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
-                }
-                if ((ptr->flag & SLE_WAB_REG_QUERY_STARTED) &&
-                    !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-                {
-                    LogInfo("uDNS_SetupWABQueries: DELETE  Registration for domain  %##s", ptr->domain.c);
-                    mDNS_StopGetDomains(m, &ptr->RegisterQ);
-                    mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
-                }
-
-                mDNSPlatformMemFree(ptr);
-
-                // deregister records generated from answers to the query
-                while (arList)
-                {
-                    ARListElem *dereg = arList;
-                    arList = arList->next;
-                    LogInfo("uDNS_SetupWABQueries: DELETE Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
-                    err = mDNS_Deregister(m, &dereg->ar);
-                    if (err) LogMsg("uDNS_SetupWABQueries:: ERROR!! mDNS_Deregister returned %d", err);
-                    // Memory will be freed in the FreeARElemCallback
-                }
-                continue;
-            }
-
-            // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
-            // We suppressed the domain enumeration for scoped search domains below. When we enable that
-            // enable this.
-            if (!(action & UDNS_WAB_BROWSE_QUERY) && (ptr->flag & SLE_WAB_BROWSE_QUERY_STARTED) &&
-                !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                LogInfo("uDNS_SetupWABQueries: Deleting Browse for domain  %##s", ptr->domain.c);
-                ptr->flag &= ~SLE_WAB_BROWSE_QUERY_STARTED;
-                uDNS_DeleteWABQueries(m, ptr, UDNS_WAB_BROWSE_QUERY);
-            }
-
-            if (!(action & UDNS_WAB_LBROWSE_QUERY) && (ptr->flag & SLE_WAB_LBROWSE_QUERY_STARTED) &&
-                !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                LogInfo("uDNS_SetupWABQueries: Deleting Legacy Browse for domain  %##s", ptr->domain.c);
-                ptr->flag &= ~SLE_WAB_LBROWSE_QUERY_STARTED;
-                uDNS_DeleteWABQueries(m, ptr, UDNS_WAB_LBROWSE_QUERY);
-            }
-
-            if (!(action & UDNS_WAB_REG_QUERY) && (ptr->flag & SLE_WAB_REG_QUERY_STARTED) &&
-                !SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                LogInfo("uDNS_SetupWABQueries: Deleting Registration for domain  %##s", ptr->domain.c);
-                ptr->flag &= ~SLE_WAB_REG_QUERY_STARTED;
-                uDNS_DeleteWABQueries(m, ptr, UDNS_WAB_REG_QUERY);
-            }
-
-            // Fall through to handle the ADDs
-        }
-
-        if ((action & UDNS_WAB_BROWSE_QUERY) && !(ptr->flag & SLE_WAB_BROWSE_QUERY_STARTED))
-        {
-            // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries.
-            // Also, suppress the domain enumeration for scoped search domains for now until there is a need.
-            if (!SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                mStatus err1, err2;
-                err1 = mDNS_GetDomains(m, &ptr->BrowseQ,          mDNS_DomainTypeBrowse,              &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
-                if (err1)
-                {
-                    LogMsg("uDNS_SetupWABQueries: GetDomains for domain %##s returned error(s):\n"
-                           "%d (mDNS_DomainTypeBrowse)\n", ptr->domain.c, err1);
-                }
-                else
-                {
-                    LogInfo("uDNS_SetupWABQueries: Starting Browse for domain %##s", ptr->domain.c);
-                }
-                err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ,       mDNS_DomainTypeBrowseDefault,       &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
-                if (err2)
-                {
-                    LogMsg("uDNS_SetupWABQueries: GetDomains for domain %##s returned error(s):\n"
-                           "%d (mDNS_DomainTypeBrowseDefault)\n", ptr->domain.c, err2);
-                }
-                else
-                {
-                    LogInfo("uDNS_SetupWABQueries: Starting Default Browse for domain %##s", ptr->domain.c);
-                }
-                // For simplicity, we mark a single bit for denoting that both the browse queries have started.
-                // It is not clear as to why one would fail to start and the other would succeed in starting up.
-                // If that happens, we will try to stop both the queries and one of them won't be in the list and
-                // it is not a hard error.
-                if (!err1 || !err2)
-                {
-                    ptr->flag |= SLE_WAB_BROWSE_QUERY_STARTED;
-                }
-            }
-        }
-        if ((action & UDNS_WAB_LBROWSE_QUERY) && !(ptr->flag & SLE_WAB_LBROWSE_QUERY_STARTED))
-        {
-            // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries.
-            // Also, suppress the domain enumeration for scoped search domains for now until there is a need.
-            if (!SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                mStatus err1;
-                err1 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic,     &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
-                if (err1)
-                {
-                    LogMsg("uDNS_SetupWABQueries: GetDomains for domain %##s returned error(s):\n"
-                           "%d (mDNS_DomainTypeBrowseAutomatic)\n",
-                           ptr->domain.c, err1);
-                }
-                else
-                {
-                    ptr->flag |= SLE_WAB_LBROWSE_QUERY_STARTED;
-                    LogInfo("uDNS_SetupWABQueries: Starting Legacy Browse for domain %##s", ptr->domain.c);
-                }
-            }
-        }
-        if ((action & UDNS_WAB_REG_QUERY) && !(ptr->flag & SLE_WAB_REG_QUERY_STARTED))
-        {
-            // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries.
-            // Also, suppress the domain enumeration for scoped search domains for now until there is a need.
-            if (!SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
-            {
-                mStatus err1, err2;
-                err1 = mDNS_GetDomains(m, &ptr->RegisterQ,        mDNS_DomainTypeRegistration,        &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
-                if (err1)
-                {
-                    LogMsg("uDNS_SetupWABQueries: GetDomains for domain %##s returned error(s):\n"
-                           "%d (mDNS_DomainTypeRegistration)\n", ptr->domain.c, err1);
-                }
-                else
-                {
-                    LogInfo("uDNS_SetupWABQueries: Starting Registration for domain %##s", ptr->domain.c);
-                }
-                err2 = mDNS_GetDomains(m, &ptr->DefRegisterQ,     mDNS_DomainTypeRegistrationDefault, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
-                if (err2)
-                {
-                    LogMsg("uDNS_SetupWABQueries: GetDomains for domain %##s returned error(s):\n"
-                           "%d (mDNS_DomainTypeRegistrationDefault)", ptr->domain.c, err2);
-                }
-                else
-                {
-                    LogInfo("uDNS_SetupWABQueries: Starting Default Registration for domain %##s", ptr->domain.c);
-                }
-                if (!err1 || !err2)
-                {
-                    ptr->flag |= SLE_WAB_REG_QUERY_STARTED;
-                }
-            }
-        }
-
-        p = &ptr->next;
-    }
-}
-
-// mDNS_StartWABQueries is called once per API invocation where normally
-// one of the bits is set.
-mDNSexport void uDNS_StartWABQueries(mDNS *const m, int queryType)
-{
-    if (queryType & UDNS_WAB_BROWSE_QUERY)
-    {
-        m->WABBrowseQueriesCount++;
-        LogInfo("uDNS_StartWABQueries: Browse query count %d", m->WABBrowseQueriesCount);
-    }
-    if (queryType & UDNS_WAB_LBROWSE_QUERY)
-    {
-        m->WABLBrowseQueriesCount++;
-        LogInfo("uDNS_StartWABQueries: Legacy Browse query count %d", m->WABLBrowseQueriesCount);
-    }
-    if (queryType & UDNS_WAB_REG_QUERY)
-    {
-        m->WABRegQueriesCount++;
-        LogInfo("uDNS_StartWABQueries: Reg query count %d", m->WABRegQueriesCount);
-    }
-    uDNS_SetupWABQueries(m);
-}
-
-// mDNS_StopWABQueries is called once per API invocation where normally
-// one of the bits is set.
-mDNSexport void uDNS_StopWABQueries(mDNS *const m, int queryType)
-{
-    if (queryType & UDNS_WAB_BROWSE_QUERY)
-    {
-        m->WABBrowseQueriesCount--;
-        LogInfo("uDNS_StopWABQueries: Browse query count %d", m->WABBrowseQueriesCount);
-    }
-    if (queryType & UDNS_WAB_LBROWSE_QUERY)
-    {
-        m->WABLBrowseQueriesCount--;
-        LogInfo("uDNS_StopWABQueries: Legacy Browse query count %d", m->WABLBrowseQueriesCount);
-    }
-    if (queryType & UDNS_WAB_REG_QUERY)
-    {
-        m->WABRegQueriesCount--;
-        LogInfo("uDNS_StopWABQueries: Reg query count %d", m->WABRegQueriesCount);
-    }
-    uDNS_SetupWABQueries(m);
-}
-
-mDNSexport domainname  *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, int *searchIndex, mDNSBool ignoreDotLocal)
-{
-    SearchListElem *p = SearchList;
-    int count = *searchIndex;
-
-    if (count < 0) { LogMsg("uDNS_GetNextSearchDomain: count %d less than zero", count); return mDNSNULL; }
-
-    // Skip the  domains that we already looked at before. Guard against "p"
-    // being NULL. When search domains change we may not set the SearchListIndex
-    // of the question to zero immediately e.g., domain enumeration query calls
-    // uDNS_SetupWABQueries which reads in the new search domain but does not
-    // restart the questions immediately. Questions are restarted as part of
-    // network change and hence temporarily SearchListIndex may be out of range.
-
-    for (; count && p; count--)
-        p = p->next;
-
-    while (p)
-    {
-        int labels = CountLabels(&p->domain);
-        if (labels > 0)
-        {
-            const domainname *d = SkipLeadingLabels(&p->domain, labels - 1);
-            if (SameDomainLabel(d->c, (const mDNSu8 *)"\x4" "arpa"))
-            {
-                LogInfo("uDNS_GetNextSearchDomain: skipping search domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
-                (*searchIndex)++;
-                p = p->next;
-                continue;
-            }
-            if (ignoreDotLocal && SameDomainLabel(d->c, (const mDNSu8 *)"\x5" "local"))
-            {
-                LogInfo("uDNS_GetNextSearchDomain: skipping local domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
-                (*searchIndex)++;
-                p = p->next;
-                continue;
-            }
-        }
-        // Point to the next one in the list which we will look at next time.
-        (*searchIndex)++;
-        if (p->InterfaceID == InterfaceID)
-        {
-            LogInfo("uDNS_GetNextSearchDomain returning domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
-            return &p->domain;
-        }
-        LogInfo("uDNS_GetNextSearchDomain skipping domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
-        p = p->next;
-    }
-    return mDNSNULL;
-}
-
-mDNSexport void uDNS_RestartQuestionAsTCP(mDNS *m, DNSQuestion *const q, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
-{
-    // Don't reuse TCP connections. We might have failed over to a different DNS server
-    // while the first TCP connection is in progress. We need a new TCP connection to the
-    // new DNS server. So, always try to establish a new connection.
-    if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
-    q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, q, mDNSNULL);
-}
-
-mDNSlocal void FlushAddressCacheRecords(mDNS *const m)
-{
-    mDNSu32 slot;
-    CacheGroup *cg;
-    CacheRecord *cr;
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->resrec.InterfaceID) continue;
-
-        // If resource records can answer A, AAAA or are RRSIGs that cover A/AAAA, they need to be flushed so that we
-        // will deliver an ADD or RMV.
-
-        RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Here we are checking if the record should be decided on whether to deliver the remove event to the callback,
-        // RRSIG that covers kDNSType_A or kDNSType_AAAA should always be checked.
-        // Note that setting the two flags below will not necessarily deliver the remove event for RRSIG
-        // that covers kDNSType_A or kDNSType_AAAA records. It still needs to go through the "IsAnswer" process to
-        // determine whether to deliver the remove event.
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRValidated;
-    #endif
-        const mDNSBool typeMatches = RRTypeAnswersQuestionType(&cr->resrec, kDNSType_A, flags) ||
-                                     RRTypeAnswersQuestionType(&cr->resrec, kDNSType_AAAA, flags);
-        if (!typeMatches)
-        {
-            continue;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "FlushAddressCacheRecords: Purging Resourcerecord - "
-            "record description: " PRI_S ".", CRDisplayString(m, cr));
-
-        mDNS_PurgeCacheResourceRecord(m, cr);
-    }
-}
-
-// Retry questions which has seach domains appended
-mDNSexport void RetrySearchDomainQuestions(mDNS *const m)
-{
-    DNSQuestion *q;
-    mDNSBool found = mDNSfalse;
-
-    // Check to see if there are any questions which needs search domains to be applied.
-    // If there is none, search domains can't possibly affect them.
-    for (q = m->Questions; q; q = q->next)
-    {
-        if (q->AppendSearchDomains)
-        {
-            found = mDNStrue;
-            break;
-        }
-    }
-    if (!found)
-    {
-        LogInfo("RetrySearchDomainQuestions: Questions with AppendSearchDomain not found");
-        return;
-    }
-    LogInfo("RetrySearchDomainQuestions: Question with AppendSearchDomain found %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-    // Purge all the A/AAAA cache records and restart the queries. mDNSCoreRestartAddressQueries
-    // does this. When we restart the question,  we first want to try the new search domains rather
-    // than use the entries that is already in the cache. When we appended search domains, we might
-    // have created cache entries which is no longer valid as there are new search domains now
-    mDNSCoreRestartAddressQueries(m, mDNStrue, FlushAddressCacheRecords, mDNSNULL, mDNSNULL);
-}
-
-// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
-// 1) query for b._dns-sd._udp.local on LocalOnly interface
-//    (.local manually generated via explicit callback)
-// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
-// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
-// 4) result above should generate a callback from question in (1).  result added to global list
-// 5) global list delivered to client via GetSearchDomainList()
-// 6) client calls to enumerate domains now go over LocalOnly interface
-//    (!!!KRS may add outgoing interface in addition)
-
-struct CompileTimeAssertionChecks_uDNS
-{
-    // 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_tcpInfo_t     [(sizeof(tcpInfo_t)      <=  9056) ? 1 : -1];
-    char sizecheck_SearchListElem[(sizeof(SearchListElem) <=  6381) ? 1 : -1];
-};
-
-// MARK: - DNS Push functions
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-mDNSlocal void DNSPushProcessResponse(mDNS *const m, const DNSMessage *const msg,
-                                      DNSPushServer *server, ResourceRecord *mrr)
-{
-    // "(CacheRecord*)1" is a special (non-zero) end-of-list marker
-    // We use this non-zero marker so that records in our CacheFlushRecords list will always have NextInCFList
-    // set non-zero, and that tells GetCacheEntity() that they're not, at this moment, eligible for recycling.
-    CacheRecord *CacheFlushRecords = (CacheRecord*)1;
-    CacheRecord **cfp = &CacheFlushRecords;
-    enum { removeName, removeClass, removeRRset, removeRR, addRR } action;
-
-    // Ignore records we don't want to cache.
-
-    // Don't want to cache OPT or TSIG pseudo-RRs
-    if (mrr->rrtype == kDNSType_TSIG)
-    {
-        return;
-    }
-    if (mrr->rrtype == kDNSType_OPT)
-    {
-        return;
-    }
-
-    if ((mrr->rrtype == kDNSType_CNAME) && SameDomainName(mrr->name, &mrr->rdata->u.name))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[PushS%u] DNSPushProcessResponse: Found a CNAME loop - "
-            "rrname: " PRI_DM_NAME ".", server->serial, DM_NAME_PARAM(mrr->name));
-        return;
-    }
-
-    // TTL == -1: delete individual record
-    // TTL == -2: wildcard delete
-    //   CLASS != ANY, TYPE != ANY: delete all records of specified type and class
-    //   CLASS != ANY, TYPE == ANY: delete all RRs of specified class
-    //   CLASS == ANY: delete all RRs on the name, regardless of type or class (TYPE is ignored).
-    // If TTL is zero, this is a delete, not an add.
-    if ((mDNSs32)mrr->rroriginalttl == -1)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u] DNSPushProcessResponse: Removing a record - "
-            "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ", rdlength: %u, rdata: " PRI_S ".",
-            server->serial, DM_NAME_PARAM(mrr->name), DNSTypeName(mrr->rrtype), mrr->rdlength, RRDisplayString(m, mrr));
-        action = removeRR;
-    }
-    else if ((mDNSs32)mrr->rroriginalttl == -2)
-    {
-        if (mrr->rrclass == kDNSQClass_ANY)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u] DNSPushProcessResponse: Removing all records with the same name - rrname: " PRI_DM_NAME ".",
-                server->serial, DM_NAME_PARAM(mrr->name));
-            action = removeName;
-        }
-        else if (mrr->rrtype == kDNSQType_ANY)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u] DNSPushProcessResponse: Removing all records with the same name and class - "
-                "rrname: " PRI_DM_NAME ", rrclass: %d" ".", server->serial, DM_NAME_PARAM(mrr->name), mrr->rrclass);
-            action = removeClass;
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u] DNSPushProcessResponse: Removing the specified RRSet - "
-                "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ", rdlength: %u.",
-                server->serial, DM_NAME_PARAM(mrr->name), DNSTypeName(mrr->rrtype), mrr->rdlength);
-            action = removeRRset;
-        }
-    }
-    else
-    {
-        action = addRR;
-    }
-
-    if (action != addRR)
-    {
-        if (m->rrcache_size)
-        {
-            CacheRecord *rr;
-            // Remember the unicast question that we found, which we use to make caching
-            // decisions later on in this function
-            CacheGroup *cg = CacheGroupForName(m, mrr->namehash, mrr->name);
-            for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-            {
-                if ( action == removeName  ||
-                    (action == removeClass && rr->resrec.rrclass == mrr->rrclass) ||
-                    (rr->resrec.rrclass == mrr->rrclass &&
-                     ((action == removeRRset && rr->resrec.rrtype == mrr->rrtype) ||
-                      (action == removeRR    && rr->resrec.rrtype == mrr->rrtype  &&
-                       SameRDataBody(mrr, &rr->resrec.rdata->u, SameDomainName)))))
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "[PushS%u] DNSPushProcessResponse: Purging RR - "
-                        "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ", rdata: " PRI_S ".", server->serial,
-                        DM_NAME_PARAM(rr->resrec.name), DNSTypeName(rr->resrec.rrtype), CRDisplayString(m, rr));
-
-                    // We've found a cache entry to delete.   Now what?
-                    mDNS_PurgeCacheResourceRecord(m, rr);
-                }
-            }
-        }
-    }
-    else
-    {
-        // It's an add.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u] DNSPushProcessResponse: Adding a record - "
-            "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ", rdlength: %u, rdata: " PRI_S ".",
-            server->serial, DM_NAME_PARAM(mrr->name), DNSTypeName(mrr->rrtype), mrr->rdlength, RRDisplayString(m, mrr));
-
-        // Use the DNS Server we remember from the question that created this DNS Push server structure.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-		mdns_replace(&mrr->dnsservice, server->dnsservice);
-#else
-        mrr->rDNSServer = server->qDNSServer;
-#endif
-
-        // 2. See if we want to add this packet resource record to our cache
-        // We only try to cache answers if we have a cache to put them in
-        if (m->rrcache_size)
-        {
-            const mDNSu32 slot = HashSlotFromNameHash(mrr->namehash);
-            CacheGroup *cg = CacheGroupForName(m, mrr->namehash, mrr->name);
-            CacheRecord *rr = mDNSNULL;
-
-            // 2a. Check if this packet resource record is already in our cache.
-            rr = mDNSCoreReceiveCacheCheck(m, msg, uDNS_LLQ_Events, slot, cg, &cfp, mDNSNULL);
-
-            // 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 && mrr->rroriginalttl > 0)
-            {
-                rr = CreateNewCacheEntryEx(m, slot, cg, 0, mDNStrue, &server->connection->transport->remote_addr,
-                                           kCreateNewCacheEntryFlagsDNSPushSubscribed);
-                if (rr)
-                {
-                    // Not clear that this is ever used, but for verisimilitude, set this to look like
-                    // an authoritative response to a regular query.
-                    rr->responseFlags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA;
-                    rr->responseFlags.b[1] = kDNSFlag1_RC_NoErr;
-                }
-            }
-        }
-    }
-}
-
-mDNSlocal void DNSPushProcessResponses(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *firstAnswer,
-                                           const mDNSu8 *const end, DNSPushServer *server)
-{
-    DNSQuestion *q;
-    const mDNSu8 *ptr = firstAnswer;
-    mDNSIPPort port;
-    port.NotAnInteger = 0;
-    ResourceRecord *mrr = &m->rec.r.resrec;
-
-    // Validate the contents of the message
-    // XXX Right now this code will happily parse all the valid data and then hit invalid data
-    // and give up.  I don't think there's a risk here, but we should discuss it.
-    // XXX what about source validation?   Like, if we have a VPN, are we safe?   I think yes, but let's think about it.
-    while ((ptr = GetLargeResourceRecord(m, msg, ptr, end, mDNSNULL, kDNSRecordTypePacketAns, &m->rec)))
-    {
-        int gotOne = 0;
-        for (q = m->Questions; q; q = q->next)
-        {
-            if (q->LongLived &&
-                (q->qtype == mrr->rrtype || q->qtype == kDNSServiceType_ANY)
-                && q->qnamehash == mrr->namehash && SameDomainName(&q->qname, mrr->name))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[R%u->Q%u] DNSPushProcessResponses found the matched question - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ", LLQ state: " PUB_S ", q's DNS push server: " PRI_S
-                    ", DNS push server: " PRI_S ".", q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype), LLQStateToString(q->state),
-                    q->dnsPushServer ? (q->dnsPushServer->connection
-                                      ? q->dnsPushServer->connection->remote_name
-                                      : "<no DNS push connection>") : "<no DNS push server>",
-                    server->connection->remote_name
-                );
-
-                if (q->dnsPushServer == server)
-                {
-                    gotOne++;
-                    DNSPushProcessResponse(m, msg, server, mrr);
-                    break; // question list may have changed
-                }
-            }
-        }
-        if (!gotOne)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "[PushS%u->DSO%u] DNSPushProcessResponses found no matched question - "
-                "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ".", server->serial, server->connection->serial,
-                DM_NAME_PARAM(mrr->name), DNSTypeName(mrr->rrtype));
-        }
-        mrr->RecordType = 0;     // Clear RecordType to show we're not still using it
-    }
-}
-
-static void
-DNSPushStartConnecting(DNSPushServer *server)
-{
-    if (server->connectInfo == NULL) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[PushS%u] DNSPushStartConnecting: can't connect to server " PRI_DM_NAME "%%%u: no connectInfo",
-                  server->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-        return;
-    }
-    if (dso_connect(server->connectInfo))
-    {
-        server->connectState = DNSPushServerConnectionInProgress;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSOC%u] Connecting to DNS push server - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, server->connectInfo->serial,
-            DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-    }
-    else
-    {
-        server->connectState = DNSPushServerConnectFailed;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSOC%u] Failed connect to DNS push server - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, server->connectInfo->serial,
-            DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-    }
-}
-
-static DNSPushZone *DNSPushZoneCreate(const domainname *const name, DNSPushServer *const server, mDNS *const m)
-{
-    DNSPushZone *const zone = mDNSPlatformMemAllocateClear(sizeof(*zone));
-    if (zone == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    AssignDomainName(&zone->zoneName, name);
-    zone->server = server;
-    DNS_PUSH_RETAIN(zone->server); // This new zone holds a reference to the existing server.
-
-    // Add the new zone to the beginning of the m->DNSPushZone list.
-    zone->next = m->DNSPushZones;
-    m->DNSPushZones = zone;
-    DNS_PUSH_RETAIN(m->DNSPushZones); // The m->DNSPushZones list holds a reference to the new zone.
-
-    DNS_PUSH_RETAIN(zone); // This create function will return an object that is retained.
-exit:
-    return zone;
-}
-
-// Release the DNSPushZone held by DNSQuestion.
-static void ReleaseDNSPushZoneForQuestion(DNSQuestion *const q)
-{
-    if (q->dnsPushZone != mDNSNULL)
-    {
-        DNS_PUSH_RELEASE(q->dnsPushZone, DNSPushZoneFinalize);
-        q->dnsPushZone = mDNSNULL;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[Q%u] Question does not have a associated DNS Push zone - qname: " PRI_DM_NAME ".",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname));
-    }
-}
-
-// Release the DNSPushServer held by DNSQuestion.
-static void ReleaseDNSPushServerForQuestion(DNSQuestion *const q)
-{
-    if (q->dnsPushServer != mDNSNULL)
-    {
-        // Cannot cancel the server here by calling CancelDNSPushServer(), because there can be other
-        // active questions that also use the current DNS push server, only call CancelDNSPushServer() when
-        // we know the connection to server is invalid, for example, when the DNS server configuration changes.
-        DNS_PUSH_RELEASE(q->dnsPushServer, DNSPushServerFinalize);
-        q->dnsPushServer = mDNSNULL;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[Q%u] Question does not have a associated DNS Push server - qname: " PRI_DM_NAME ".",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname));
-    }
-}
-
-// Release the DNSPushZone and DNSPushServer reference held by DNSQuestion.
-static void ReleaseDNSPushZoneAndServerForQuestion(DNSQuestion *q)
-{
-    if (q->dnsPushZone != mDNSNULL && q->dnsPushServer != mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[Q%u->PushS%u] Releasing the DNS push zone and server"
-            " - zone: " PRI_DM_NAME ", server: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID), q->dnsPushServer->serial,
-            DM_NAME_PARAM(&q->dnsPushZone->zoneName), DM_NAME_PARAM(&q->dnsPushServer->serverName));
-    }
-    ReleaseDNSPushZoneForQuestion(q);
-    ReleaseDNSPushServerForQuestion(q);
-}
-
-static const char kDNSPushActivity_Subscription[] = "dns-push-subscription";
-
-static void DNSPushSendKeepalive(DNSPushServer *server, mDNSu32 inactivity_timeout, mDNSu32 keepalive_interval)
-{
-    dso_message_t state;
-    dso_transport_t *transport = server->connection->transport;
-    if (transport == NULL || transport->outbuf == NULL)
-    {
-        // Should be impossible, don't crash.
-        LogInfo("DNSPushSendSubscribe: no transport!");
-        return;
-    }
-    dso_make_message(&state, transport->outbuf, transport->outbuf_size, server->connection, false, false, 0, 0, 0);
-    dso_start_tlv(&state, kDSOType_Keepalive);
-    dso_add_tlv_u32(&state, inactivity_timeout);
-    dso_add_tlv_u32(&state, keepalive_interval);
-    dso_finish_tlv(&state);
-    dso_message_write(server->connection, &state, mDNSfalse);
-}
-
-static void DNSPushSendSubscriptionChange(mDNSBool subscribe, dso_state_t *dso, DNSQuestion *q)
-{
-    dso_message_t state;
-    dso_transport_t *transport = dso->transport;
-    mDNSu16 len;
-    if (transport == NULL || transport->outbuf == NULL) {
-        // Should be impossible, don't crash.
-        LogInfo("DNSPushSendSubscribe: no transport!");
-        return;
-    }
-    dso_make_message(&state, transport->outbuf, transport->outbuf_size, dso, subscribe ? false : true, false, 0, 0, q);
-    dso_start_tlv(&state, subscribe ? kDSOType_DNSPushSubscribe : kDSOType_DNSPushUnsubscribe);
-    len = DomainNameLengthLimit(&q->qname, q->qname.c + (sizeof q->qname));
-    dso_add_tlv_bytes(&state, q->qname.c, len);
-    dso_add_tlv_u16(&state, q->qtype);
-    dso_add_tlv_u16(&state, q->qclass);
-    dso_finish_tlv(&state);
-    dso_message_write(dso, &state, mDNSfalse);
-}
-
-void DNSPushZoneRemove(mDNS *const m, const DNSPushServer *const server)
-{
-    mDNSBool found = mDNSfalse;
-    for (DNSPushZone **ptrToZoneRef = &m->DNSPushZones; *ptrToZoneRef != mDNSNULL;)
-    {
-        DNSPushZone *zone = *ptrToZoneRef;
-
-        if (zone->server == server)
-        {
-            *ptrToZoneRef = zone->next;
-            DNS_PUSH_RELEASE(zone, DNSPushZoneFinalize);
-            found = mDNStrue;
-        }
-        else
-        {
-            ptrToZoneRef = &(zone->next);
-        }
-    }
-
-    if (!found)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[PushS%u] DNS push zone is not found in the system's list - server name: " PRI_DM_NAME ", refCount: %u.",
-            server->serial, DM_NAME_PARAM(&server->serverName), server->refCount);
-    }
-}
-
-// Remove the DNSPushServer entirely from the system, and its corresponding DNSPushZone is also removed from the system.
-static void DNSPushServerRemove(mDNS *const m, DNSPushServer *server)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[PushS%u] Removing DNS push server - name: " PRI_DM_NAME ", refCount: %u.", server->serial,
-        DM_NAME_PARAM(&server->serverName), server->refCount);
-
-    // 1. Release all the DNS push zones that use this server from the m->DNSPushZones list.
-    DNSPushZoneRemove(m, server);
-
-    // 2. Remove the server from the mDNSResponder's list.
-    DNSPushServer **server_ptr = &m->DNSPushServers;
-    while ((*server_ptr != mDNSNULL) && (*server_ptr != server))
-    {
-        server_ptr = &(*server_ptr)->next;
-    }
-
-    if (*server_ptr != mDNSNULL)
-    {
-        *server_ptr = server->next;
-        server->next = mDNSNULL;
-        DNS_PUSH_RELEASE(server, DNSPushServerFinalize);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[PushS%u] DNS push server is removed but it is not found in the system's list - "
-            "name: " PRI_DM_NAME ", refCount: %u.", server->serial, DM_NAME_PARAM(&server->serverName),
-            server->refCount);
-    }
-}
-
-// Cancel the the DNSPushServer completely:
-// 1. All the existing questions should not use it: completed by UnsubscribeAllQuestionsFromDNSPushServer().
-// 2. All the question created in the future should not use it: completed by DNSPushServerRemove() or by the caller
-//    of DNSPushServerCancel() if alreadyRemovedFromSystem is true.
-// 3. All the underlying objects that are active should be canceled/released/freed.
-// When alreadyRemovedFromSystem is set to true, this function will not iterate the m->DNSPushServers and remove it from
-// the list. When it is true, we will assume that the DNS push server passed in has been removed from the list before
-// the function is called.
-mDNSexport void DNSPushServerCancel(DNSPushServer *server, const mDNSBool alreadyRemovedFromSystem)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u] Canceling DNS push server - "
-        "server name: " PRI_DM_NAME ".", server->serial, DM_NAME_PARAM(&server->serverName));
-
-    // 1. All the existing questions that have the active subscription should unsubscribe from the DNS push server, and
-    // fall back to LLQ poll.
-    UnsubscribeAllQuestionsFromDNSPushServer(server->m, server);
-
-    // 2. All the questions created in the future should not use it, so remove it from the system's list.
-    if (!alreadyRemovedFromSystem)
-    {
-        DNSPushServerRemove(server->m, server);
-    }
-
-    // 3. All the underlying objects that are active should be canceled/released/freed.
-    server->canceling = mDNStrue;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_forget(&server->dnsservice);
-#else
-    server->qDNSServer = mDNSNULL;
-#endif
-    if (server->connection)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u->DSO%u] Canceling dso_state_t for DNS push server - server: " PRI_DM_NAME ":%u.",
-            server->serial, server->connection->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-
-        dso_state_cancel(server->connection);
-
-        // server->connection will be freed in dso_idle().
-        server->connection = mDNSNULL;
-    }
-    if (server->connectInfo)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u->DSOC%u] Canceling dso_connect_state_t for DNS push server - server: " PRI_DM_NAME ":%u.",
-            server->serial, server->connectInfo->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-        dso_connect_state_cancel(server->connectInfo);
-
-        // server->connectInfo will be freed in dso_transport_idle().
-        server->connectInfo = mDNSNULL;
-    }
-}
-
-static void DNSPushDSOCallback(void *context, void *event_context,
-                               dso_state_t *dso, dso_event_type_t eventType)
-{
-    DNSPushServer *const server = context;
-
-    const uint32_t dso_serial = dso != mDNSNULL ? dso->serial : DSO_STATE_INVALID_SERIAL;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[DSO%u] New DNSPushDSOCallback - "
-        "context: %p, event_context: %p, dso: %p, eventType: " PUB_S ", server state: " PUB_S ".",
-        dso_serial, context, event_context, dso, dso_event_type_to_string(eventType),
-        server != mDNSNULL ? DNSPushServerConnectStateToString(server->connectState) : "No server");
-
-    if (dso == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Calling DNSPushDSOCallback with NULL dso");
-        return;
-    }
-
-    const DNSMessage *message;
-    dso_message_payload_t *payload;
-    dso_activity_t *activity;
-    const dso_query_receive_context_t *receive_context;
-    const dso_disconnect_context_t *disconnect_context;
-    const dso_keepalive_context_t *keepalive_context;
-    DNSQuestion *q;
-    uint16_t rcode;
-    mDNSs32 reconnect_when = 0;
-    mDNS *m = server->m;
-
-    mDNS_CheckLock(m);
-
-    switch(eventType)
-    {
-    case kDSOEventType_DNSMessage:
-        // We shouldn't get here because we won't use this connection for DNS messages.
-        payload = event_context;
-        message = (const DNSMessage *)payload->message;
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[PushS%u->DSO%u] Received an unexpected DNS message from the DSO connection - "
-            "opcode: %d, server: " PRI_DM_NAME ":%u.", server->serial, dso_serial,
-            (message->h.flags.b[0] & kDNSFlag0_OP_Mask) >> 3, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-        break;
-
-    case kDSOEventType_DNSResponse:
-        // We shouldn't get here because we already handled any DNS messages.
-        payload = event_context;
-        message = (const DNSMessage *)payload->message;
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[PushS%u->DSO%u] Received an unexpected DNS response from the DSO connection - "
-            "opcode: %d, server: " PRI_DM_NAME ":%u.", server->serial, dso_serial,
-            (message->h.flags.b[0] & kDNSFlag0_OP_Mask) >> 3, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-        break;
-
-    case kDSOEventType_DSOMessage:
-        payload = event_context;
-        message = (const DNSMessage *)payload->message;
-        if (dso->primary.opcode == kDSOType_DNSPushUpdate)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u->DSO%u] Received a DSO message from the DSO connection - "
-                "server: " PRI_DM_NAME ":%u, message length: %u.", server->serial, dso_serial,
-                DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port), dso->primary.length);
-
-            DNSPushProcessResponses(server->m, message, dso->primary.payload,
-                                    dso->primary.payload + dso->primary.length, server);
-        }
-        else
-        {
-            dso_send_not_implemented(dso, &message->h);
-
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "[PushS%u->DSO%u] Received an unknown DSO response from the DSO connection - "
-                "primary tlv: %d, server: " PRI_DM_NAME ":%u.", server->serial, dso_serial, dso->primary.opcode,
-                DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-        }
-        break;
-
-    case kDSOEventType_DSOResponse:
-        receive_context = event_context;
-        q = receive_context->query_context;
-        rcode = receive_context->rcode;
-        if (q)
-        {
-            // If we got an error on a subscribe, we need to evaluate what went wrong.
-            if (rcode == kDNSFlag1_RC_NoErr)
-            {
-                // It is possible that we get duplicate session established responses from the server in a race
-                // condition, where the previous session establishing request has finished but the corresponding query
-                // has been canceled. In which case, indicate that in the log.
-                const mDNSBool sessionEstablishedPreviously = (server->connectState == DNSPushServerSessionEstablished);
-
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[R%u->Q%u->PushS%u->DSO%u] Received a DSO response from the DSO connection. Subscription SUCCEEDS - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ", server: " PRI_DM_NAME ":%u" PUB_S ".", q->request_id,
-                    mDNSVal16(q->TargetQID), server->serial, dso_serial, DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype), DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port),
-                    sessionEstablishedPreviously ? ", session established previously" : "");
-
-                q->state = LLQ_DNSPush_Established;
-                server->connectState = DNSPushServerSessionEstablished;
-
-                // If the subscription succeeds, then all the records that are cached before the subscription should
-                // be purged. From now on, we rely on the DNS push server to give us the correct notification.
-                mDNS_CheckLock(m);
-                CacheGroup *const cache_group = CacheGroupForName(m, q->qnamehash, &q->qname);
-                if (cache_group != mDNSNULL)
-                {
-                    for (CacheRecord *cache_record = cache_group->members; cache_record != mDNSNULL;
-                         cache_record = cache_record->next)
-                    {
-                        if (!SameNameCacheRecordAnswersQuestion(cache_record, q))
-                        {
-                            continue;
-                        }
-                        if (cache_record->DNSPushSubscribed)
-                        {
-                            const ResourceRecord *const rr = &cache_record->resrec;
-                            // If the session has been established previously, it is possible that the server has
-                            // sent some responses back that can be used to answer queries. In which case, it is
-                            // valid that the record from the responses is DNS-push-subscribed. However, we still
-                            // want to purge it soon because the record might have been updated by the server. The
-                            // current subscription will let the server send the new(or duplicate if the records do not
-                            // change) responses, which will replace or rescue the old ones. If it has not been
-                            // established yet, then it is invalid to have a subscribed record in the cache.
-                            if (!sessionEstablishedPreviously)
-                            {
-                                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                                    "[R%u->Q%u->PushS%u->DSO%u] Already have an existing DNS push subscribed record in the cache - "
-                                    "rrname: " PRI_DM_NAME ", rrtype: " PUB_S ", rdlength: %u, rdata: " PRI_S ".",
-                                    q->request_id, mDNSVal16(q->TargetQID), server->serial, dso_serial,
-                                    DM_NAME_PARAM(rr->name), DNSTypeName(rr->rrtype), rr->rdlength,
-                                    RRDisplayString(m, rr));
-                            }
-                            cache_record->DNSPushSubscribed = mDNSfalse;
-                        }
-                        // Instead of purging the record immediately, we give the record 1 second to be rescued by a
-                        // possible following subscription add event to avoid unnecessary add/remove/add sequence.
-                        RefreshCacheRecord(m, cache_record, 1);
-                    }
-                }
-            }
-            else
-            {
-                // Don't use this server.
-                server->connectState = DNSPushServerNoDNSPush;
-                StartLLQPolling(m, q);
-
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                    "[R%u->Q%u->PushS%u->DSO%u] Received a DSO response with non-zero error code from the DSO connection. Subscription FAILED, fall back to LLQ poll - "
-                    "qname: " PRI_DM_NAME ", qtype: " PUB_S ", server: " PRI_DM_NAME ":%u, rcode: %d.", q->request_id,
-                    mDNSVal16(q->TargetQID), server->serial, dso_serial, DM_NAME_PARAM(&q->qname),
-                    DNSTypeName(q->qtype), DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port), rcode);
-            }
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u->DSO%u] Received a DSO response from DSO connection. Session ESTABLISHED, but the query has been canceled. - "
-                "primary tlv: %d, rcode: %d, server: " PRI_DM_NAME ":%u.", server->serial, dso_serial,
-                dso->primary.opcode, receive_context->rcode, DM_NAME_PARAM(&server->serverName),
-                mDNSVal16(server->port));
-
-            server->connectState = DNSPushServerSessionEstablished;
-        }
-        break;
-
-    case kDSOEventType_Finalize:
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSO%u] Finalizing dso_state_t - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-
-        if (dso->context_callback != NULL)
-        {
-            // Give the context a callback with dso_life_cycle_free state, so that the context can do the final cleanup.
-            dso->context_callback(dso_life_cycle_free, dso->context, dso);
-        }
-        mDNSPlatformMemFree(dso);
-        break;
-
-    case kDSOEventType_Connected:
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSO%u] DNS push server CONNECTED - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-
-        server->connectState = DNSPushServerConnected;
-        for (activity = dso->activities; activity; activity = activity->next)
-        {
-            DNSPushSendSubscriptionChange(mDNStrue, dso, activity->context);
-        }
-        break;
-
-    case kDSOEventType_ConnectFailed:
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[PushS%u->DSO%u] DNS push server FAILED TO CONNECT - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-        DNSPushServerCancel(server, mDNSfalse);
-        break;
-
-    case kDSOEventType_Disconnected:
-        disconnect_context = event_context;
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[PushS%u->DSO%u] DNS push server disconnected - "
-                  "server name: " PRI_DM_NAME ":%u, delay = %u, " PUB_S, server->serial, dso->serial,
-                  DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port), disconnect_context->reconnect_delay,
-                  server->connectInfo ? "connectable" : "stale");
-
-        // We can get a disconnect event after the connection has been canceled from our end; in this case, we don't
-        // have any work to do.
-        if (server->connectInfo == NULL) {
-            break;
-        }
-
-        // If a network glitch broke the connection, try to reconnect immediately.  But if this happens
-        // twice, don't just blindly reconnect.
-        if (disconnect_context->reconnect_delay == 0)
-        {
-            if (m->timenow - server->lastDisconnect < 90 * mDNSPlatformOneSecond)
-            {
-                reconnect_when = 60; // If we get two disconnects in quick succession, wait a minute before trying again.
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[PushS%u->DSO%u] Connection to the DNS push server disconnected, trying immediate reconnect - "
-                    "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-                    mDNSVal16(server->port));
-
-                DNSPushStartConnecting(server);
-            }
-        }
-        else
-        {
-            reconnect_when = disconnect_context->reconnect_delay;
-        }
-        if (reconnect_when != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[PushS%u->DSO%u] Holding the DNS push server out as not reconnectable for a while - "
-                "duration: %d, server name: " PRI_DM_NAME ":%u.",
-                server->serial, dso->serial, reconnect_when,
-                DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-
-            dso_schedule_reconnect(m, server->connectInfo, reconnect_when);
-        }
-        server->lastDisconnect = m->timenow;
-        break;
-
-        // We get this event when a connection has been dropped and it's time to reconnect. This can happen either
-        // because we got a hard connection drop, or because we got a RetryDelay DSO message. In the latter case,
-        // the expectation is that we will get this callback when the delay has expired. This is actually set up
-        // in this same function when we get a kDSOEventType_RetryDelay event.
-    case kDSOEventType_ShouldReconnect:
-        // This should be unnecessary, but it would be bad to accidentally have a question pointing at
-        // a server that had been freed, so make sure we don't.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u->DSO%u] ShouldReconnect timer fired for the DNS push server: reconnecting - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-        if (server->connectInfo == NULL) {
-            DNSPushStartConnecting(server);
-        } else {
-            server->connection = dso;
-            dso_reconnect(server->connectInfo, dso);
-        }
-        break;
-
-    case kDSOEventType_Keepalive:
-        if (server->connection == NULL || server->connection->transport == NULL) {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "[PushS%u->DSO%u] Keepalive: connection to the DNS push server missing - server name: " PRI_DM_NAME ":%u.",
-                      server->serial, dso->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-        } else {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "[PushS%u->DSO%u] Keepalive timer for the DNS push server fired - server name: " PRI_DM_NAME ":%u.",
-                      server->serial, dso->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-            keepalive_context = event_context;
-
-            DNSPushSendKeepalive(server, keepalive_context->inactivity_timeout, keepalive_context->keepalive_interval);
-        }
-        break;
-
-    case kDSOEventType_KeepaliveRcvd:
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[PushS%u->DSO%u] Keepalive message received from the DNS push server - server name: " PRI_DM_NAME ":%u.",
-            server->serial, dso->serial, DM_NAME_PARAM(&server->serverName), mDNSVal16(server->port));
-        break;
-
-    case kDSOEventType_Inactive:
-        // The set of activities went to zero, and we set the idle timeout.   And it expired without any
-        // new activities starting.   So we can disconnect.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSO%u] Connection is inactive now - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-
-        DNSPushServerCancel(server, mDNSfalse);
-        break;
-
-    case kDSOEventType_RetryDelay:
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSO%u] Planning reconnecting - "
-            "server name: " PRI_DM_NAME ":%u.", server->serial, dso->serial, DM_NAME_PARAM(&server->serverName),
-            mDNSVal16(server->port));
-
-        disconnect_context = event_context;
-        dso_schedule_reconnect(m, server->connectInfo, disconnect_context->reconnect_delay);
-        break;
-    }
-}
-
-static DNSPushServer *DNSPushServerCreate(const domainname *const name, const mDNSIPPort port,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mdns_dns_service_t dnsService,
-#else
-    DNSServer *const qDNSServer,
-#endif
-    mDNS *const m);
-
-// This function retains the DNSPushZone and DNSPushServer returned in *outZone and *outServer.
-static mDNSBool DNSPushZoneAndServerCopy(mDNS *m, DNSQuestion *q,
-    DNSPushZone **const outZone, DNSPushServer **const outServer)
-{
-    DNSPushZone   *newZone = mDNSNULL;
-    DNSPushServer *newServer = mDNSNULL;
-
-    *outZone = NULL;
-    *outServer = NULL;
-
-    // If we already have a question for this zone and if the server is the same, reuse it.
-    for (DNSPushZone *zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[Q%u] Comparing zone with the question's zone - "
-            "zone: " PRI_DM_NAME ", question zone: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID),
-            DM_NAME_PARAM(&zone->zoneName), DM_NAME_PARAM(&q->nta->ZoneName));
-
-        if (!SameDomainName(&q->nta->ZoneName, &zone->zoneName))
-        {
-            continue;
-        }
-
-        DNSPushServer *const zoneServer = zone->server;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[Q%u] Comparing server with the question's target host - "
-            "server name: " PRI_DM_NAME ", question target host: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID),
-            DM_NAME_PARAM(&zoneServer->serverName), DM_NAME_PARAM(&q->nta->Host));
-
-        if (zoneServer == mDNSNULL || !SameDomainName(&q->nta->Host, &zoneServer->serverName))
-        {
-            continue;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[Q%u->PushS%u] Retaining an existing DNS push zone and server for the question - "
-            "zone name: " PRI_DM_NAME ", server name: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID), zoneServer->serial,
-            DM_NAME_PARAM(&zone->zoneName), DM_NAME_PARAM(&zoneServer->serverName));
-
-        *outZone = zone;
-        DNS_PUSH_RETAIN(*outZone);
-        *outServer = zoneServer;
-        DNS_PUSH_RETAIN(*outServer);
-
-        goto exit;
-    }
-
-    // If we have a connection to this server but it is for a different zone, create a new zone entry and reuse the connection.
-    for (DNSPushServer *server = m->DNSPushServers; server != mDNSNULL; server = server->next)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[Q%u] Comparing server with the question's target host - "
-            "server name: " PRI_DM_NAME ", question target host: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID),
-            DM_NAME_PARAM(&server->serverName), DM_NAME_PARAM(&q->nta->Host));
-
-        if (!SameDomainName(&q->nta->Host, &server->serverName))
-        {
-            continue;
-        }
-
-        newZone = DNSPushZoneCreate(&q->nta->ZoneName, server, m);
-        if (newZone == mDNSNULL)
-        {
-            goto exit;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[Q%u->PushS%u] Retaining a new DNS push zone and an existing server for the question - "
-            "new zone name: " PRI_DM_NAME ", server name: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID), server->serial,
-            DM_NAME_PARAM(&newZone->zoneName), DM_NAME_PARAM(&server->serverName));
-
-        *outZone = newZone;
-        // newZone = mDNSNULL; The ownership is now transferred.
-        *outServer = server;
-        DNS_PUSH_RETAIN(*outServer);
-
-        goto exit;
-    }
-
-    // If we do not have any existing connections, create a new connection.
-    newServer = DNSPushServerCreate(&q->nta->Host, q->nta->Port,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                                    q->dnsservice,
-#else
-                                    q->qDNSServer,
-#endif
-                                    m);
-    if (newServer == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    newZone = DNSPushZoneCreate(&q->nta->ZoneName, newServer, m);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[Q%u->PushS%u] Retaining a new DNS push zone and a new server for the question - "
-        "new zone name: " PRI_DM_NAME ", server name: " PRI_DM_NAME ".", mDNSVal16(q->TargetQID), newServer->serial,
-        DM_NAME_PARAM(&newZone->zoneName), DM_NAME_PARAM(&newServer->serverName));
-
-    *outZone = newZone;
-    // newZone = mDNSNULL; The ownership is now transferred.
-    *outServer = newServer;
-    newServer = mDNSNULL;
-
-exit:
-    if (newServer != mDNSNULL)
-    {
-        // Revert the work done by DNSPushZoneCreate().
-        DNSPushServerCancel(newServer, mDNSfalse);
-        DNS_PUSH_RELEASE(newServer, DNSPushServerFinalize); // newServer removes the reference to it.
-        // newServer = mDNSNULL; The reference held is released.
-        // Then the last reference of the newServer will be released in DNSPushDSOCallback() when dso_idle() cleans
-        // dso_connections_needing_cleanup list.
-    }
-    return *outZone != mDNSNULL && *outServer != mDNSNULL;
-}
-
-static bool DSOLifeCycleContextCallBack(const dso_life_cycle_t life_cycle, void *const context,
-                                        dso_state_t *const dso)
-{
-    DNSPushServer *server = context;
-    bool status = false;
-    if (server == mDNSNULL || dso == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "DSOLifeCycleContextCallBack gets called with NULL pointer - server: %p, dso: %p.",
-            context, dso);
-        goto exit;
-    }
-
-    switch (life_cycle)
-    {
-        case dso_life_cycle_create:
-            DNS_PUSH_RETAIN(server);
-            break;
-        case dso_life_cycle_cancel:
-            // If the DNS Push server is being canceled, then and only then do we want the dso to be collected.
-            if (server->canceling) {
-                status = true;
-            }
-            // Otherwise, we expect the DSO object to continue to be used for the next connection attempt to a
-            // working DSO server.
-            break;
-        case dso_life_cycle_free:
-            DNS_PUSH_RELEASE(server, DNSPushServerFinalize);
-            dso->context = mDNSNULL;
-            break;
-    }
-exit:
-    return status;
-}
-
-static bool DSOConnectLifeCycleContextCallBack(const dso_connect_life_cycle_t life_cycle, void *const context,
-                                               dso_connect_state_t *const dso_connect)
-{
-    DNSPushServer *server = context;
-    bool status = false;
-
-    // Only check the parameter for dso_connect_life_cycle_create and dso_connect_life_cycle_cancel.
-    if (life_cycle == dso_connect_life_cycle_create || life_cycle == dso_connect_life_cycle_cancel)
-    {
-        if (server == mDNSNULL || dso_connect == mDNSNULL)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "DSOConnectLifeCycleContextCallBack gets called with NULL pointer - context: %p, dso_connect: %p.",
-                context, dso_connect);
-            goto exit;
-        }
-    }
-
-    switch (life_cycle)
-    {
-        case dso_connect_life_cycle_create:
-            DNS_PUSH_RETAIN(server);
-            break;
-        case dso_connect_life_cycle_cancel:
-            DNS_PUSH_RELEASE(server, DNSPushServerFinalize);
-            dso_connect->context = mDNSNULL;
-            status = true;
-            break;
-        case dso_connect_life_cycle_free:
-            // Do nothing, the context has been freed in dso_connect_life_cycle_cancel case above.
-            break;
-    }
-exit:
-    return status;
-}
-
-static DNSPushServer *DNSPushServerCreate(const domainname *const name, const mDNSIPPort port,
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mdns_dns_service_t dnsService,
-#else
-    DNSServer *const qDNSServer,
-#endif
-    mDNS *const m)
-{
-    DNSPushServer *serverToReturn = mDNSNULL;
-    DNSPushServer *server = mDNSNULL;
-
-    server = mDNSPlatformMemAllocateClear(sizeof(*server));
-    if (server == mDNSNULL)
-    {
-        goto exit;
-    }
-    DNS_PUSH_RETAIN(server); // This create function will return an object that is retained.
-
-    // Used to uniquely mark DNSPushServer objects, incremented once for each DNSPushServer created.
-    // DNS_PUSH_SERVER_INVALID_SERIAL(0) is used to identify the invalid DNSPushServer.
-    static uint32_t serial = DNS_PUSH_SERVER_INVALID_SERIAL + 1;
-    server->serial = serial++;
-
-    AssignDomainName(&server->serverName, name);
-    server->port = port;
-    server->m = m;
-    server->canceling = mDNSfalse;
-
-    char serverNameCStr[MAX_ESCAPED_DOMAIN_NAME];
-    ConvertDomainNameToCString(name, serverNameCStr);
-    // server is being passed to dso_state_create() to create dso_state_t, so dso_state_t also holds a reference to the
-    // new server. server will be retained in DSOLifeCycleContextCallBack: case dso_life_cycle_create.
-    server->connection = dso_state_create(mDNSfalse, 10, serverNameCStr, DNSPushDSOCallback, server,
-                                          DSOLifeCycleContextCallBack, mDNSNULL);
-    if (server->connection == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    // server is being passed to dso_connect_state_create() to create dso_connect_state_t, so dso_connect_state_t also
-    // holds a reference to the new server. server will be retained in DSOConnectLifeCycleContextCallBack: case
-    // dso_life_cycle_create. If dso_connect_state_t creates a new dso_state_t later in dso_connection_succeeded(),
-    // server will also be retained in DSOLifeCycleContextCallBack: case dso_life_cycle_create, when calling
-    // dso_state_create().
-    server->connectInfo = dso_connect_state_create(serverNameCStr, mDNSNULL, port, 10, AbsoluteMaxDNSMessageData,
-        AbsoluteMaxDNSMessageData, DNSPushDSOCallback, server->connection, server,
-        DSOLifeCycleContextCallBack, DSOConnectLifeCycleContextCallBack, "DNSPushServerCreate");
-    if (server->connectInfo != mDNSNULL)
-    {
-        dso_connect_state_use_tls(server->connectInfo);
-        DNSPushStartConnecting(server);
-    }
-    else
-    {
-        server->connectState = DNSPushServerConnectFailed;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_replace(&server->dnsservice, dnsService);
-#else
-    server->qDNSServer = qDNSServer;
-#endif
-
-    server->next = m->DNSPushServers;
-    m->DNSPushServers = server;
-    DNS_PUSH_RETAIN(m->DNSPushServers); // The m->DNSPushServers holds a new reference to the new server.
-
-    serverToReturn = server;
-    server = mDNSNULL; // The ownership is now transferred.
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u->DSO%u->DSOC%u] New DNSPushServer created - "
-        "server: %p, server name: " PRI_DM_NAME ".", serverToReturn->serial, serverToReturn->connection->serial,
-        serverToReturn->connectInfo != mDNSNULL ? serverToReturn->connectInfo->serial : DSO_CONNECT_STATE_INVALID_SERIAL,
-        serverToReturn, DM_NAME_PARAM(&serverToReturn->serverName));
-
-exit:
-    mDNSPlatformMemFree(server);
-    return serverToReturn;
-}
-
-mDNSexport void DNSPushServerFinalize(DNSPushServer *const server)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[PushS%u] DNSPushServer finalizing - "
-        "server: %p, server name: " PRI_DM_NAME ".", server->serial, server, DM_NAME_PARAM(&server->serverName));
-
-    if (server->connection != mDNSNULL || server->connectInfo != mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "[PushS%u] server was not canceled before it gets finalized - "
-            "server name: " PRI_DM_NAME ", server->connection: %p, server->connectInfo: %p.", server->serial,
-            DM_NAME_PARAM(&server->serverName), server->connection, server->connectInfo);
-    }
-    mDNSPlatformMemFree(server);
-}
-
-mDNSexport void DNSPushZoneFinalize(DNSPushZone *const zone)
-{
-    if (zone->server != mDNSNULL)
-    {
-        DNS_PUSH_RELEASE(zone->server, DNSPushServerFinalize);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "The zone being released does not have any DNS push server associated - zone: " PRI_DM_NAME,
-            DM_NAME_PARAM(&zone->zoneName));
-    }
-
-    mDNSPlatformMemFree(zone);
-}
-
-static mDNSBool SubscribeToDNSPushServer(mDNS *m, DNSQuestion *q,
-    DNSPushZone **const outZone, DNSPushServer **const outServer)
-{
-    DNSPushZone *zoneSelected = mDNSNULL;
-    DNSPushServer *serverSelected = mDNSNULL;
-    mDNSBool succeeded = DNSPushZoneAndServerCopy(m, q, &zoneSelected, &serverSelected);
-    if (!succeeded)
-    {
-        goto exit;
-    }
-
-    // server->connection should never be NULL here.
-    if (serverSelected->connection == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-            "The zone being subscribed does not have any DSO object associated - zone: " PRI_DM_NAME,
-            DM_NAME_PARAM(&zoneSelected->zoneName));
-        goto exit;
-    }
-
-    char name[MAX_ESCAPED_DOMAIN_NAME + 9];  // type(hex)+class(hex)+name
-    dso_activity_t *activity;
-
-    // Now we have a connection to a push notification server.   It may be pending, or it may be active,
-    // but either way we can add a DNS Push subscription to the server object.
-    mDNS_snprintf(name, sizeof name, "%04x%04x", q->qtype, q->qclass);
-    ConvertDomainNameToCString(&q->qname, &name[8]);
-    activity = dso_add_activity(serverSelected->connection, name, kDNSPushActivity_Subscription, q, mDNSNULL);
-    if (activity == mDNSNULL)
-    {
-        succeeded = mDNSfalse;
-        goto exit;
-    }
-
-    // If we're already connected, send the subscribe request immediately.
-    if (serverSelected->connectState == DNSPushServerConnected ||
-        serverSelected->connectState == DNSPushServerSessionEstablished)
-    {
-        DNSPushSendSubscriptionChange(mDNStrue, serverSelected->connection, q);
-    }
-
-    *outZone = zoneSelected;
-    zoneSelected = mDNSNULL;
-    *outServer = serverSelected;
-    serverSelected = mDNSNULL;
-
-exit:
-    // When dso_add_activity fails, release the reference we previously retained.
-    if (zoneSelected != mDNSNULL)
-    {
-        DNS_PUSH_RELEASE(zoneSelected, DNSPushZoneFinalize);
-    }
-    if (serverSelected != mDNSNULL)
-    {
-        DNS_PUSH_RELEASE(serverSelected, DNSPushServerFinalize);
-    }
-    return succeeded;
-}
-
-mDNSexport void DiscoverDNSPushServer(mDNS *m, DNSQuestion *q)
-{
-    q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10);    // Retry in approx 15 minutes
-    q->LastQTime     = m->timenow;
-    SetNextQueryTime(m, q);
-    if (q->nta) CancelGetZoneData(m, q->nta);
-    q->nta = StartGetZoneData(m, &q->qname, ZoneServiceDNSPush, DNSPushGotZoneData, q);
-    q->state = LLQ_DNSPush_ServerDiscovery;
-    if (q->nta != mDNSNULL)
-    {
-        q->nta->question.request_id = q->request_id;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u->subQ%u] Starting DNS push server discovery - "
-        "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", q->request_id, mDNSVal16(q->TargetQID),
-        q->nta != mDNSNULL ? mDNSVal16(q->nta->question.TargetQID) : 0, DM_NAME_PARAM(&q->qname),
-        DNSTypeName(q->qtype));
-}
-
-mDNSexport void UnsubscribeQuestionFromDNSPushServer(mDNS *const NONNULL m, DNSQuestion *const NONNULL q,
-                                                     const mDNSBool fallBackToLLQPoll)
-{
-    const DNSPushServer *const server = q->dnsPushServer;
-    dso_state_t *const dso = (server != mDNSNULL) ? server->connection : mDNSNULL;
-    const uint32_t qid = mDNSVal16(q->TargetQID);
-    const uint32_t server_serial = (server != mDNSNULL) ? server->serial : DNS_PUSH_SERVER_INVALID_SERIAL;
-    const uint32_t dso_serial = (dso != mDNSNULL) ? dso->serial : DSO_STATE_INVALID_SERIAL;
-
-    if (server == mDNSNULL || dso == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[Q%u->PushS%u->DSO%u] Unsubscribing question from the DNS push server - "
-        "server name: " PRI_DM_NAME ", connect state: " PUB_S ".", qid, server_serial, dso_serial,
-        DM_NAME_PARAM(&server->serverName), DNSPushServerConnectStateToString(server->connectState));
-
-    // Stop any active DSO query.
-    const uint32_t disassociated_count = dso_ignore_further_responses(dso, q);
-    if (disassociated_count != 0)
-    {
-        if (server->connectState != DNSPushServerConnected && server->connectState != DNSPushServerSessionEstablished)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "[Q%u->PushS%u->DSO%u] Having unexpected outstanding queries while the DNS Push server is not in the connected or session established state - "
-                "server name: " PRI_DM_NAME ", connect state: " PUB_S " outstanding queries: %u.", qid, server_serial,
-                dso_serial, DM_NAME_PARAM(&server->serverName), DNSPushServerConnectStateToString(server->connectState),
-                disassociated_count);
-        }
-    }
-
-    if (dso->has_session)
-    {
-        // When we as a client has an established connection to the server, we will not have an established
-        // DSO session to the server until we receive an acknowledgment from the server. Therefore, only send
-        // subscription change if we have an established DSO session.
-        DNSPushSendSubscriptionChange(mDNSfalse, dso, q);
-    }
-
-    // Remove any activity associated with the question.
-    dso_activity_t *const activity = dso_find_activity(dso, mDNSNULL, kDNSPushActivity_Subscription, q);
-    if (activity != mDNSNULL)
-    {
-        dso_drop_activity(dso, activity);
-    }
-
-    // The cached answer added by the subscription above should be changed back to a regular one, which ages according
-    // to the original TTL specified by the DNS push server.
-    mDNS_CheckLock(m);
-    CacheGroup *const cache_group = CacheGroupForName(m, q->qnamehash, &q->qname);
-    if (cache_group == mDNSNULL)
-    {
-        goto exit;
-    }
-
-    for (CacheRecord *cache_record = cache_group->members; cache_record != mDNSNULL; cache_record = cache_record->next)
-    {
-        if (!SameNameCacheRecordAnswersQuestion(cache_record, q))
-        {
-            continue;
-        }
-
-        // When a subscription is canceled, this original TTL needs to be restored and the record aging resumes.
-        // See https://tools.ietf.org/html/rfc8765#section-6.3.1: "The TTL of an added record is stored by the client."
-        cache_record->DNSPushSubscribed = mDNSfalse;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[Q%u->PushS%u->DSO%u] the cached record aging resumes due to the unsubscribed activity - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_S ", TTL: %us.", qid, server_serial, dso_serial,
-            DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), cache_record->resrec.rroriginalttl);
-    }
-
-exit:
-    // Release the question's reference to the DNS push zone and the DNS push server.
-    ReleaseDNSPushZoneAndServerForQuestion(q);
-    // If the question is still active when unsubscription happens, it falls back to LLQ poll.
-    if (fallBackToLLQPoll)
-    {
-        // Since the question loses its DNSPushServer, it cannot use DNS push, so fall back to regular unicast
-        // DNS(LLQ Poll).
-        StartLLQPolling(m, q);
-    }
-    return;
-}
-
-mDNSexport void UnsubscribeAllQuestionsFromDNSPushServer(mDNS *const NONNULL m, DNSPushServer *const NONNULL server)
-{
-    for (DNSQuestion *q = m->Questions; q != mDNSNULL; q = q->next)
-    {
-        if (q->dnsPushServer != server)
-        {
-            continue;
-        }
-        // Since we are unsubscribing all questions' activities from the DNS push server, and some questions might still
-        // be active and waiting for the response, the questions should fall back to LLQ poll.
-        UnsubscribeQuestionFromDNSPushServer(m, q, mDNStrue);
-    }
-}
-
-// Update the duplicate question to the new primary question when the original primary question is being stopped.
-mDNSexport void
-DNSPushUpdateQuestionDuplicate(DNSQuestion *const NONNULL primary, DNSQuestion *const NONNULL duplicate)
-{
-    if (primary->dnsPushZone != mDNSNULL)
-    {
-        // Transfer the ownership of the DNS push zone.
-        duplicate->dnsPushZone   = primary->dnsPushZone;
-        DNS_PUSH_RETAIN(duplicate->dnsPushZone);
-        DNS_PUSH_RELEASE(primary->dnsPushZone, DNSPushZoneFinalize);
-        primary->dnsPushZone = mDNSNULL;
-    }
-    if (primary->dnsPushServer != mDNSNULL)
-    {
-        if (primary->dnsPushServer->connection != mDNSNULL)
-        {
-            // Also update the context of the dso_activity_t since we are replacing the original primary question with
-            // the new one(which is previously a duplicate of the primary question).
-            dso_activity_t *const activity = dso_find_activity(primary->dnsPushServer->connection, mDNSNULL,
-                                                               kDNSPushActivity_Subscription, primary);
-            if (activity != mDNSNULL)
-            {
-                activity->context = duplicate;
-            }
-        }
-
-        // Transfer the ownership of the DNS push server.
-        duplicate->dnsPushServer = primary->dnsPushServer;
-        DNS_PUSH_RETAIN(duplicate->dnsPushServer);
-        DNS_PUSH_RELEASE(primary->dnsPushServer, DNSPushServerFinalize);
-        primary->dnsPushServer = mDNSNULL;
-    }
-}
-
-mDNSlocal const char *DNSPushServerConnectStateToString(const DNSPushServer_ConnectState state)
-{
-#define CASE_TO_STR(s) case s: return (#s)
-    switch (state)
-    {
-        CASE_TO_STR(DNSPushServerDisconnected);
-        CASE_TO_STR(DNSPushServerConnectFailed);
-        CASE_TO_STR(DNSPushServerConnectionInProgress);
-        CASE_TO_STR(DNSPushServerConnected);
-        CASE_TO_STR(DNSPushServerSessionEstablished);
-        CASE_TO_STR(DNSPushServerNoDNSPush);
-    }
-#undef CASE_TO_STR
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Invalid DNSPushServer_ConnectState - state: %u", state);
-    return "<INVALID DNSPushServer_ConnectState>";
-}
-
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-
-mDNSlocal const char *LLQStateToString(const LLQ_State state)
-{
-#define CASE_TO_STR(s) case s: return (#s)
-    switch (state)
-    {
-        CASE_TO_STR(LLQ_Invalid);
-        CASE_TO_STR(LLQ_Init);
-        CASE_TO_STR(LLQ_DNSPush_ServerDiscovery);
-        CASE_TO_STR(LLQ_DNSPush_Connecting);
-        CASE_TO_STR(LLQ_DNSPush_Established);
-        CASE_TO_STR(LLQ_InitialRequest);
-        CASE_TO_STR(LLQ_SecondaryRequest);
-        CASE_TO_STR(LLQ_Established);
-        CASE_TO_STR(LLQ_Poll);
-    }
-#undef CASE_TO_STR
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Invalid LLQ_State - state: %u", state);
-    return "<INVALID LLQ_State>";
-}
-
-// MARK: -
-#else // !UNICAST_DISABLED
-
-mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr)
-{
-    (void) m;
-    (void) rr;
-
-    return mDNSNULL;
-}
-
-mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name)
-{
-    (void) m;
-    (void) name;
-
-    return mDNSNULL;
-}
-
-mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q)
-{
-    (void) m;
-    (void) q;
-
-    return mDNSNULL;
-}
-
-mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
-{
-    (void) m;
-    (void) q;
-}
-
-mDNSexport void DisposeTCPConn(struct tcpInfo_t *tcp)
-{
-    (void) tcp;
-}
-
-mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
-{
-    (void) m;
-    (void) traversal;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
-{
-    (void) m;
-    (void) traversal;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
-{
-    (void) m;
-    (void) q;
-}
-
-mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *ZoneDataContext)
-{
-    (void) m;
-    (void) name;
-    (void) target;
-    (void) callback;
-    (void) ZoneDataContext;
-
-    return mDNSNULL;
-}
-
-mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
-{
-    (void) m;
-    (void) err;
-    (void) zoneData;
-}
-
-mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-                                             const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion)
-{
-    (void) m;
-    (void) msg;
-    (void) end;
-    (void) srcaddr;
-    (void) srcport;
-    (void) matchQuestion;
-
-    return uDNS_LLQ_Not;
-}
-
-mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags)
-{
-    (void) m;
-    (void) q;
-    (void) responseFlags;
-}
-
-mDNSexport void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID)
-{
-    (void) domain;
-    (void) InterfaceID;
-}
-
-mDNSexport void RetrySearchDomainQuestions(mDNS *const m)
-{
-    (void) m;
-}
-
-mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port)
-{
-    (void) m;
-    (void) info;
-    (void) domain;
-    (void) keyname;
-    (void) b64keydata;
-    (void) hostname;
-    (void) port;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport domainname  *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal)
-{
-    (void) InterfaceID;
-    (void) searchIndex;
-    (void) ignoreDotLocal;
-
-    return mDNSNULL;
-}
-
-mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name)
-{
-    (void) m;
-    (void) name;
-
-    return mDNSNULL;
-}
-
-mDNSexport mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal)
-{
-    (void) m;
-    (void) traversal;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal)
-{
-    (void) m;
-    (void) traversal;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSs32 serviceID, const mDNSAddr *addr,
-                                        const mDNSIPPort port, ScopeType scopeType, mDNSu32 timeout, mDNSBool isCell, mDNSBool isExpensive, mDNSBool isConstrained, mDNSBool isCLAT46,
-                                        mDNSu32 resGroupID, mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO)
-{
-    (void) m;
-    (void) d;
-    (void) interface;
-    (void) serviceID;
-    (void) addr;
-    (void) port;
-    (void) scopeType;
-    (void) timeout;
-    (void) isCell;
-    (void) isExpensive;
-    (void) isCLAT46;
-    (void) isConstrained;
-    (void) resGroupID;
-    (void) reqA;
-    (void) reqAAAA;
-    (void) reqDO;
-
-    return mDNSNULL;
-}
-
-mDNSexport void uDNS_SetupWABQueries(mDNS *const m)
-{
-    (void) m;
-}
-
-mDNSexport void uDNS_StartWABQueries(mDNS *const m, int queryType)
-{
-    (void) m;
-    (void) queryType;
-}
-
-mDNSexport void uDNS_StopWABQueries(mDNS *const m, int queryType)
-{
-    (void) m;
-    (void) queryType;
-}
-
-mDNSexport void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
-{
-    (void) m;
-    (void) fqdn;
-    (void) StatusCallback;
-    (void) StatusContext;
-}
-mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router)
-{
-    (void) m;
-    (void) v4addr;
-    (void) v6addr;
-    (void) router;
-}
-
-mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn)
-{
-    (void) m;
-    (void) fqdn;
-}
-
-mDNSexport void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks)
-{
-    (void) m;
-    (void) waitTicks;
-}
-
-mDNSexport mDNSBool IsGetZoneDataQuestion(DNSQuestion *q)
-{
-    (void)q;
-
-    return mDNSfalse;
-}
-
-mDNSexport void SubscribeToDNSPushServer(mDNS *m, DNSQuestion *q)
-{
-    (void)m;
-    (void)q;
-}
-
-mDNSexport void UnsubscribeQuestionFromDNSPushServer(mDNS *m, DNSQuestion *q)
-{
-    (void)m;
-    (void)q;
-}
-
-mDNSexport void DiscoverDNSPushServer(mDNS *m, DNSQuestion *q)
-{
-    (void)m;
-    (void)q;
-}
-
-#endif // !UNICAST_DISABLED
-
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/mDNSCore/uDNS.h b/mDNSCore/uDNS.h
deleted file mode 100644
index 45e1764..0000000
--- a/mDNSCore/uDNS.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2002-2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __UDNS_H_
-#define __UDNS_H_
-
-#include "nullability.h"
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-#include <sys/types.h>
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-#include "dso.h"
-#include "dso-transport.h"
-#endif
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#define RESTART_GOODBYE_DELAY    (6 * mDNSPlatformOneSecond) // delay after restarting LLQ before nuking previous known answers (avoids flutter if we restart before we have networking up)
-#define INIT_UCAST_POLL_INTERVAL (3 * mDNSPlatformOneSecond) // this interval is used after send failures on network transitions
-                                                             // which typically heal quickly, so we start agressively and exponentially back off
-#define MAX_UCAST_POLL_INTERVAL (60 * 60 * mDNSPlatformOneSecond)
-//#define MAX_UCAST_POLL_INTERVAL (1 * 60 * mDNSPlatformOneSecond)
-#define LLQ_POLL_INTERVAL       (15 * 60 * mDNSPlatformOneSecond) // Polling interval for zones w/ an advertised LLQ port (ie not static zones) if LLQ fails due to NAT, etc.
-#define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond)         // require server responses within one minute of request
-#define MAX_UCAST_UNANSWERED_QUERIES 2                       // number of unanswered queries from any one uDNS server before trying another server
-#define DNSSERVER_PENALTY_TIME (60 * mDNSPlatformOneSecond)  // number of seconds for which new questions don't pick this server
-
-// On some interfaces, we want to delay the first retransmission to a minimum of 2 seconds
-// rather than the default (1 second).
-#define MIN_UCAST_RETRANS_TIMEOUT (2 * mDNSPlatformOneSecond)
-
-#define DEFAULT_UPDATE_LEASE 7200
-
-#define QuestionIntervalStep 3
-#define QuestionIntervalStep2 (QuestionIntervalStep*QuestionIntervalStep)
-#define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep)
-#define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep)
-#define MaxQuestionInterval         (3600 * mDNSPlatformOneSecond)
-#define UDNSBackOffMultiplier 2 
-#define MinQuestionInterval (1 * mDNSPlatformOneSecond)
-
-// For Unicast record registrations, we initialize the interval to 1 second. When we send any query for
-// the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep
-// so that the first retry does not happen until 3 seconds which should be enough for TCP/TLS to be done.
-#define INIT_RECORD_REG_INTERVAL (1 * mDNSPlatformOneSecond)
-#define MAX_RECORD_REG_INTERVAL (15 * 60 * mDNSPlatformOneSecond)
-#define MERGE_DELAY_TIME    (1 * mDNSPlatformOneSecond)
-
-// If we are refreshing, we do it at least 5 times with a min update frequency of
-// 5 minutes
-#define MAX_UPDATE_REFRESH_COUNT    5
-#define MIN_UPDATE_REFRESH_TIME     (5 * 60 * mDNSPlatformOneSecond)
-
-// For questions that use kDNSServiceFlagsTimeout and we don't have a matching resolver e.g., no dns servers,
-// then use the default value of 30 seconds
-#define DEFAULT_UDNS_TIMEOUT    30 // in seconds
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-
-// Reference count helper for DNSPushServer and DNSPushZone.
-#define DNS_PUSH_RETAIN(OBJ)                                                                                    \
-    do                                                                                                          \
-    {                                                                                                           \
-        (OBJ)->refCount++;                                                                                      \
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,                                                    \
-            "DNS push object retained - object: %p, refCount after retaining: %u.", (OBJ), (OBJ)->refCount);    \
-    } while (mDNSfalse)
-
-#define DNS_PUSH_RELEASE(OBJ, FINALIZER)                                                                        \
-    do                                                                                                          \
-    {                                                                                                           \
-        (OBJ)->refCount--;                                                                                      \
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,                                                    \
-            "DNS push object released - object: %p, refCount after releasing: %u.", (OBJ), (OBJ)->refCount);    \
-        if ((OBJ)->refCount == 0)                                                                               \
-        {                                                                                                       \
-            FINALIZER((OBJ));                                                                                   \
-            (OBJ) = NULL;                                                                                       \
-        }                                                                                                       \
-    } while (mDNSfalse)
-
-// Push notification structures.
-struct mDNS_DNSPushServer
-{
-    uint32_t                   serial;            // The serial number that can be used to identify a specific server.
-    uint32_t                   refCount;          // Reference count used by DNS_PUSH_RETAIN and DNS_PUSH_RELEASE.
-    dso_connect_state_t       *connectInfo;       // DSO Connection state information.
-    dso_state_t               *connection;        // DNS Stateful Operations/TCP Connection pointer, might be null.
-    DNSPushServer_ConnectState connectState;      // Current status of connection attempt to this server.
-    mDNSs32                    lastDisconnect;    // Last time we got a disconnect, used to avoid constant reconnects.
-    domainname                 serverName;        // The hostname returned by the _dns-push-tls._tcp.<zone> SRV lookup.
-    mDNSIPPort                 port;              // The port from the SRV lookup.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_dns_service_t         dnsservice;
-#else
-    DNSServer                 *qDNSServer;        // DNS server stolen from the question that created this server structure.
-#endif
-    mDNS                      *m;
-    mDNSBool                   canceling;         // Indicates if the current server is being canceled.
-    DNSPushServer *next;
-} ;
-
-struct mDNS_DNSPushZone
-{
-    uint32_t refCount;                // Reference count used by DNS_PUSH_RETAIN and DNS_PUSH_RELEASE.
-    domainname zoneName;
-    DNSPushServer *server; // DNS Push Servers for this zone.
-    DNSPushZone *next;
-} ;
-#endif
-
-// Entry points into unicast-specific routines
-
-extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
-extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
-extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-extern void DNSPushGotZoneData(mDNS *m, mStatus err, const ZoneData *zoneInfo);
-extern void DiscoverDNSPushServer(mDNS *m, DNSQuestion *q);
-extern void UnsubscribeQuestionFromDNSPushServer(mDNS *m, DNSQuestion *q, mDNSBool fallBackToLLQPoll);
-extern void UnsubscribeAllQuestionsFromDNSPushServer(mDNS *m, DNSPushServer *server);
-extern void DNSPushZoneRemove(mDNS *m, const DNSPushServer *server);
-extern void DNSPushZoneFinalize(DNSPushZone *zone);
-extern void DNSPushServerCancel(DNSPushServer *server, mDNSBool alreadyRemovedFromSystem);
-extern void DNSPushServerFinalize(DNSPushServer *server);
-extern void DNSPushUpdateQuestionDuplicate(DNSQuestion *primary, DNSQuestion *duplicate);
-#endif
-
-extern void SleepRecordRegistrations(mDNS *m);
-
-// uDNS_UpdateRecord
-// following fields must be set, and the update validated, upon entry.
-// rr->NewRData
-// rr->newrdlength
-// rr->UpdateCallback
-
-extern mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr);
-
-extern void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q);
-extern mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr);
-extern mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt);
-extern mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question);
-extern mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question);
-extern mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalInfo *traversal);
-
-extern void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData);
-extern mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr);
-extern const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr);
-
-// integer fields of msg header must be in HOST byte order before calling this routine
-extern void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-                            const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
-
-extern void uDNS_Tasks(mDNS *const m);
-extern void UpdateAllSRVRecords(mDNS *m);
-extern void CheckNATMappings(mDNS *m);
-
-extern mStatus         uDNS_SetupDNSConfig(mDNS *const m);
-
-// uDNS_SetupWABQueries reads search domains from the platform layer and starts the Wide Area Bonjour
-// (WAB) domain enumeration queries if necessary.
-
-#define UDNS_WAB_BROWSE_QUERY    0x00000001 // Browse queries (b, db)
-#define UDNS_WAB_LBROWSE_QUERY   0x00000002 // Browse queries (lb)
-#define UDNS_WAB_REG_QUERY       0x00000004 // Registration queries (r and dr)
-
-extern void uDNS_SetupWABQueries(mDNS *const m);
-extern void uDNS_StartWABQueries(mDNS *const m, int queryType);
-extern void uDNS_StopWABQueries(mDNS *const m, int queryType);
-extern domainname      *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, int *searchIndex, mDNSBool ignoreDotLocal);
-    
-extern void uDNS_RestartQuestionAsTCP(mDNS *m, DNSQuestion *const q, const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
-
-extern uDNS_LLQType    uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion);
-extern DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name);
-extern DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q);
-extern void DisposeTCPConn(struct tcpInfo_t *tcp);
-
-// NAT traversal
-extern void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len); // Called for each received PCP or NAT-PMP packet
-extern void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr);
-extern void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol);
-
-extern CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage *const response, uDNS_LLQType LLQType,
-											  const mDNSu32 slot, CacheGroup *cg,
-                                              CacheRecord ***cfp, mDNSInterfaceID InterfaceID);
-#ifdef  __cplusplus
-}
-#endif
-
-#endif // __UDNS_H_
diff --git a/mDNSMacOSX/ApplePlatformFeatures.h b/mDNSMacOSX/ApplePlatformFeatures.h
deleted file mode 100644
index 8bdb590..0000000
--- a/mDNSMacOSX/ApplePlatformFeatures.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __ApplePlatformFeatures_h
-#define __ApplePlatformFeatures_h
-
-#include <TargetConditionals.h>
-
-// Feature: Add audit token to questions
-// Radar:   <rdar://problem/59042213>
-// Enabled: On all Apple platforms
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_AUDIT_TOKEN)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_AUDIT_TOKEN                1
-#endif
-
-// Feature: When flushing mDNS cache records received via AWDL, flush them immediately.
-// Radar:   <rdar://problem/91523757>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_AWDL_FAST_CACHE_FLUSH)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_AWDL_FAST_CACHE_FLUSH      1
-#endif
-
-// Feature: Background Assets Support
-// Radar:   <rdar://problem/91014171>
-// Enabled: iOS (non-reality) & macOS
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_BACKGROUND_ASSETS)
-    #if ((TARGET_OS_IOS ) || TARGET_OS_OSX)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_BACKGROUND_ASSETS      1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_BACKGROUND_ASSETS      0
-    #endif
-#endif
-
-// Feature: Bonjour-On-Demand
-// Radar:   <rdar://problem/23523784>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_BONJOUR_ON_DEMAND)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_BONJOUR_ON_DEMAND          1
-#endif
-
-// Feature: Support for Analytics For Cache
-// Radar:   <rdar://problem/52206048>
-// Enabled: iOS & macOS
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_CACHE_ANALYTICS)
-    #if !(defined(TARGET_OS_IOS) && defined(TARGET_OS_OSX))
-        #error "Expected TARGET_OS_IOS && TARGET_OS_OSX to be defined."
-    #endif
-    #if (TARGET_OS_IOS || TARGET_OS_OSX)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_CACHE_ANALYTICS        1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_CACHE_ANALYTICS        0
-    #endif
-#endif
-
-// Feature: Cache memory limit
-// Radar:   <rdar://problem/15629764>
-// Enabled: Yes, but only for device OSes, such as iOS, tvOS, and watchOS, i.e., when TARGET_OS_IPHONE is 1.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_CACHE_MEM_LIMIT)
-    #if !defined(TARGET_OS_IPHONE)
-        #error "Expected TARGET_OS_IPHONE to be defined."
-    #endif
-    #if TARGET_OS_IPHONE
-        #define MDNSRESPONDER_SUPPORTS_APPLE_CACHE_MEM_LIMIT        1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_CACHE_MEM_LIMIT        0
-    #endif
-#endif
-
-// Feature: D2D
-// Radar:   <rdar://problem/28062515>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_D2D)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_D2D                        1
-#endif
-
-// Feature: Support for DNS Analytics
-// Radar:   <rdar://problem/57972792>, <rdar://problem/57970914>
-// Enabled: iOS & macOS
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_DNS_ANALYTICS)
-    #if !(defined(TARGET_OS_IOS) && defined(TARGET_OS_OSX))
-        #error "Expected TARGET_OS_IOS && TARGET_OS_OSX to be defined."
-    #endif
-    #if (TARGET_OS_IOS || TARGET_OS_OSX)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_DNS_ANALYTICS          1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_DNS_ANALYTICS          0
-    #endif
-#endif
-
-// Feature: DNS64 support for DNS proxy
-// Radar:   <rdar://problem/56505415>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_DNS_PROXY_DNS64)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_DNS_PROXY_DNS64            1
-#endif
-
-// Feature: DNS64 IPv6 synthesis.
-// Radar:   <rdar://problem/32297396>
-// Enabled: Yes, but only for iOS and macOS, which support the DNS proxy network extension.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_DNS64)
-    #if (!defined(TARGET_OS_IOS) || !defined(TARGET_OS_OSX))
-        #error "Expected TARGET_OS_IOS and TARGET_OS_OSX to be defined."
-    #endif
-    #if (TARGET_OS_IOS || TARGET_OS_OSX)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_DNS64                  1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_DNS64                  0
-    #endif
-#endif
-
-// Feature: DNS-SD XPC service
-// Radar:   <rdar://problem/43866363>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_DNSSD_XPC_SERVICE)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_DNSSD_XPC_SERVICE          1
-#endif
-
-// Feature: DNSSEC support
-// Radar:   <rdar://problem/55275552>
-// Enabled: On all Apple platforms
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_DNSSECv2)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_DNSSECv2                   1
-#endif
-
-// Feature: Ignore /etc/hosts file on customer builds.
-// Radar:   <rdar://problem/34745220>
-// Enabled: Yes, except for macOS.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_IGNORE_HOSTS_FILE)
-    #if !defined(TARGET_OS_OSX)
-        #error "Expected TARGET_OS_OSX to be defined."
-    #endif
-    #if !TARGET_OS_OSX
-        #define MDNSRESPONDER_SUPPORTS_APPLE_IGNORE_HOSTS_FILE      1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_IGNORE_HOSTS_FILE      0
-    #endif
-#endif
-
-// Feature: Change privacy level of logs and state dump on the internal build.
-// Radar:   <rdar://79636882>
-// Enabled: On all internal Apple platforms.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_LOG_PRIVACY_LEVEL)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_LOG_PRIVACY_LEVEL          1
-#endif
-
-// Feature: No system wake for network access.
-// Radar:   <rdar://problem/28079659&55038229>
-// Enabled: Yes, but only for iOS and watchOS, which shouldn't act as sleep-proxy clients.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_NO_WAKE_FOR_NET_ACCESS)
-    #if (!defined(TARGET_OS_IOS) || !defined(TARGET_OS_WATCH))
-        #error "Expected TARGET_OS_IOS and TARGET_OS_WATCH to be defined."
-    #endif
-    #if (TARGET_OS_IOS || TARGET_OS_WATCH)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_NO_WAKE_FOR_NET_ACCESS 1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_NO_WAKE_FOR_NET_ACCESS 0
-    #endif
-#endif
-
-// Feature: Support for having finer granularity of log redaction, by using os_log based-log routine.
-// Radar:   <rdar://problem/42814956>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_OS_LOG)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_OS_LOG                     1
-#endif
-
-// Radar:   <rdar://82445644>
-// Enabled: On all Apple platforms.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_OS_UNFAIR_LOCK)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_OS_UNFAIR_LOCK             1
-#endif
-
-// Feature: Use mdns_querier objects for DNS transports.
-// Radar:   <rdar://problem/55746371>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_QUERIER)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_QUERIER                    1
-#endif
-
-// Feature: Randomized AWDL Hostname
-// Radar:   <rdar://problem/47525004>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_RANDOM_AWDL_HOSTNAME)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_RANDOM_AWDL_HOSTNAME       1
-#endif
-
-// Feature: Reachability trigger
-// Radar:   <rdar://problem/11374446>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_REACHABILITY_TRIGGER)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_REACHABILITY_TRIGGER       1
-#endif
-
-// Feature: Support more secure TSIG HMAC algorithms.
-// Radar:   <rdar://86257052>
-// Enabled: All (but TSIG update feature that uses TSIG is only available on macOS)
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_SECURE_HMAC_ALGORITHM_2022)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_SECURE_HMAC_ALGORITHM_2022 1
-#endif
-
-// Feature: Support validated/signed requests
-// Radar:   <rdar://83999760>
-// Enabled: All (depends on MDNSRESPONDER_SUPPORTS_APPLE_IPC_TLV)
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_SIGNED_RESULTS)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_SIGNED_RESULTS             1
-#endif
-
-// Feature: "SlowActivation" processing for flapping interfaces.
-//          Disabled to address stale Bonjour record issues during flapping network interface transitions.
-// Radar:   <rdar://problem/44694746>
-// Enabled: No.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_SLOW_ACTIVATION)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_SLOW_ACTIVATION            0
-#endif
-
-// Feature: Symptoms Reporting
-// Radar:   <rdar://problem/20194922>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_SYMPTOMS)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_SYMPTOMS                   1
-#endif
-
-// Feature: Tracker Reporting
-// Radar:   <rdar://problem/70222299>, <rdar://problem/74789124>
-// Enabled: Yes. (depends on MDNSRESPONDER_SUPPORTS_APPLE_AUDIT_TOKEN)
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_TRACKER_STATE)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_TRACKER_STATE              1
-#endif
-
-// Feature: TLV support DNS-SD API's Unix domain socket IPC.
-// Radar:   <rdar://problem/59295752>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_IPC_TLV)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_IPC_TLV                    1
-#endif
-
-// Feature: Enforce entitlements prompts
-// Radar:   <rdar://problem/55922132>
-// Enabled: iOS only (depends on MDNSRESPONDER_SUPPORTS_APPLE_AUDIT_TOKEN)
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_TRUST_ENFORCEMENT)
-    #if (TARGET_OS_IOS)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_TRUST_ENFORCEMENT      1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_TRUST_ENFORCEMENT      0
-    #endif
-#endif
-
-// Feature: Unicast device discovery
-// Radar:   <rdar://problem/98406195>
-// Enabled: iOS only (with dependencies)
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_UNICAST_DISCOVERY)
-    #if (TARGET_OS_IOS)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_UNICAST_DISCOVERY      1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_UNICAST_DISCOVERY      0
-    #endif
-#endif
-
-// Feature: Support for performing dot-local queries via mDNS and DNS in parallel.
-// Radar:   <rdar://problem/4786302>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_UNICAST_DOTLOCAL)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_UNICAST_DOTLOCAL           1
-#endif
-
-// Feature: Allow browses and registrations over interfaces that aren't ready yet.
-// Radar:   <rdar://problem/20181903>
-// Enabled: Yes.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_UNREADY_INTERFACES)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_UNREADY_INTERFACES         1
-#endif
-
-
-// Feature: Support for Analytics For WAB (Wide Area Bonjour)
-// Radar:   <rdar://problem/52136688>
-// Enabled: iOS & macOS
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_WAB_ANALYTICS)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_WAB_ANALYTICS              0
-#endif
-// Feature: Support for Web Content Filter
-// Radar:   <rdar://problem/7409981>
-// Enabled: Yes, if SDK has <WebFilterDNS/WebFilterDNS.h>.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_APPLE_WEB_CONTENT_FILTER)
-    #if __has_include(<WebFilterDNS/WebFilterDNS.h>)
-        #define MDNSRESPONDER_SUPPORTS_APPLE_WEB_CONTENT_FILTER     1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_APPLE_WEB_CONTENT_FILTER     0
-    #endif
-#endif
-
-// Feature Groups
-// These are pseudo-features that represent the logical OR of multiple similar features for convenience.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS) || \
-    MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)   || \
-    MDNSRESPONDER_SUPPORTS(APPLE, WAB_ANALYTICS)
-    #define MDNSRESPONDER_SUPPORTS_APPLE_ANALYTICS                  1
-#else
-    #define MDNSRESPONDER_SUPPORTS_APPLE_ANALYTICS                  0
-#endif
-
-// Feature Dependency Checks
-
-// MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) should always be true if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-// is true, except for only one case, the Tests target that runs XCTest. In the XCTest,
-// MDNSRESPONDER_SUPPORTS_APPLE_DNSSECv2 is predefined in the preprocess which does not check what
-// MDNSRESPONDER_SUPPORTS checks. In order to test DNSSEC functions in XCtest without querier support, we
-// will wrap all DNSSEC code that calls querier, since the code will never be executed in XCTest.
-
-#if !defined(MDNSRESPONDER_DISABLE_DNSSECv2_DEPENDENCY_CHECK_FOR_QUERIER)
-    #define MDNSRESPONDER_DISABLE_DNSSECv2_DEPENDENCY_CHECK_FOR_QUERIER  0
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && !MDNSRESPONDER_DISABLE_DNSSECv2_DEPENDENCY_CHECK_FOR_QUERIER
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2) depends on MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)."
-    #endif
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS) depends on MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)."
-    #endif
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE) depends on MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)."
-    #endif
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT) depends on MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)."
-    #endif
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY) depends on MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)."
-    #endif
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY) depends on MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)."
-    #endif
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        #error "MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY) depends on MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)."
-    #endif
-#endif
-
-#endif  // __ApplePlatformFeatures_h
diff --git a/mDNSMacOSX/Bonjour Safari Extension/CNServiceBrowserView.h b/mDNSMacOSX/Bonjour Safari Extension/CNServiceBrowserView.h
deleted file mode 100644
index 9af0289..0000000
--- a/mDNSMacOSX/Bonjour Safari Extension/CNServiceBrowserView.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Copyright (c) 2017 Apple 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.
- */
-
-#import <Cocoa/Cocoa.h>
-
-@protocol CNServiceBrowserViewDelegate;
-
-IB_DESIGNABLE
-
-@interface CNServiceBrowserView : NSView
-
-@property (strong) IBInspectable	NSArray *							serviceTypes;
-@property (strong) IBInspectable	NSDictionary *						localizedServiceTypesDictionary;
-@property (weak)   IBOutlet			id<CNServiceBrowserViewDelegate>	delegate;
-
-- (void)newServiceBrowse:(NSArray *)domainPath;
-
-@end
-
-@protocol CNServiceBrowserViewDelegate <NSObject>
-
-@optional
-
-- (void)bonjourServiceSelected:(NSString *)service type:(NSString *)type atDomain:(NSString *)domain;
-- (void)doubleAction:(NSURL *)url;
-
-@end
-
diff --git a/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionHandler.h b/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionHandler.h
deleted file mode 100644
index ce8f793..0000000
--- a/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionHandler.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *
- * Copyright (c) 2017 Apple 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.
- */
-
-#import <SafariServices/SafariServices.h>
-
-@interface SafariExtensionHandler : SFSafariExtensionHandler
-
-@end
diff --git a/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionViewController.h b/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionViewController.h
deleted file mode 100644
index abb1cb8..0000000
--- a/mDNSMacOSX/Bonjour Safari Extension/SafariExtensionViewController.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Copyright (c) 2017 Apple 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.
- */
-
-#import <SafariServices/SafariServices.h>
-
-#import "CNServiceBrowserView.h"
-#import "CNDomainBrowserView.h"
-
-@interface SafariExtensionViewController : SFSafariExtensionViewController
-
-@property (weak)   IBOutlet            NSSplitView *                mainSplitView;
-@property (weak)   IBOutlet            CNServiceBrowserView *       serviceBrowserView;
-@property (weak)   IBOutlet            CNDomainBrowserView *        domainBrowserView;
-
-+ (SafariExtensionViewController *)sharedController;
-
-@end
diff --git a/mDNSMacOSX/Bonjour Safari Menu/AppDelegate.h b/mDNSMacOSX/Bonjour Safari Menu/AppDelegate.h
deleted file mode 100644
index 96c3556..0000000
--- a/mDNSMacOSX/Bonjour Safari Menu/AppDelegate.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * Copyright (c) 2017 Apple 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.
- */
-
-#import <Cocoa/Cocoa.h>
-
-@interface AppDelegate : NSObject <NSApplicationDelegate>
-
-
-@end
-
diff --git a/mDNSMacOSX/Bonjour Safari Menu/ViewController.h b/mDNSMacOSX/Bonjour Safari Menu/ViewController.h
deleted file mode 100644
index 6a1f407..0000000
--- a/mDNSMacOSX/Bonjour Safari Menu/ViewController.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * Copyright (c) 2017 Apple 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.
- */
-
-#import <Cocoa/Cocoa.h>
-
-@interface ViewController : NSViewController
-
-
-@end
-
diff --git a/mDNSMacOSX/BonjourEvents.c b/mDNSMacOSX/BonjourEvents.c
deleted file mode 100644
index 1257d83..0000000
--- a/mDNSMacOSX/BonjourEvents.c
+++ /dev/null
@@ -1,1003 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2010-2015, 2020 Apple 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.
- */
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreFoundation/CFXPCBridge.h>
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnullability-extension"
-#include "dns_sd.h"
-#pragma clang diagnostic pop
-#include <UserEventAgentInterface.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <os/log.h>
-#include <xpc/xpc.h>
-
-
-#pragma mark -
-#pragma mark Types
-#pragma mark -
-static const char*          sPluginIdentifier       = "com.apple.bonjour.events";
-
-// PLIST Keys
-static const CFStringRef sServiceNameKey         = CFSTR("ServiceName");
-static const CFStringRef sServiceTypeKey         = CFSTR("ServiceType");
-static const CFStringRef sServiceDomainKey       = CFSTR("ServiceDomain");
-
-static const CFStringRef sOnServiceAddKey        = CFSTR("OnServiceAdd");
-static const CFStringRef sOnServiceRemoveKey     = CFSTR("OnServiceRemove");
-
-static const CFStringRef sLaunchdTokenKey        = CFSTR("LaunchdToken");
-static const CFStringRef sLaunchdDictKey         = CFSTR("LaunchdDict");
-
-
-/************************************************
-* Launch Event Dictionary (input from launchd)
-* Passed To: ManageEventsCallback
-*-----------------------------------------------
-* Typing in this dictionary is not enforced
-* above us. So this may not be true. Type check
-* all input before using it.
-*-----------------------------------------------
-* sServiceNameKey		- CFString (Optional)
-* sServiceTypeKey		- CFString
-* sServiceDomainKey	- CFString
-*
-* One or more of the following.
-*-----------------------------------
-* sOnServiceAddKey			- CFBoolean
-* sOnServiceRemoveKey		- CFBoolean
-* sWhileServiceExistsKey	- CFBoolean
-************************************************/
-
-/************************************************
-* Browser Dictionary
-*-----------------------------------------------
-* sServiceDomainKey - CFString
-* sServiceTypeKey   - CFString
-************************************************/
-
-/************************************************
-* Event Dictionary
-*-----------------------------------------------
-* sServiceNameKey	 - CFString (Optional)
-* sLaunchdTokenKey	 - CFNumber
-************************************************/
-
-typedef struct {
-    UserEventAgentInterfaceStruct*      _UserEventAgentInterface;
-    CFUUIDRef _factoryID;
-    UInt32 _refCount;
-
-    void*                               _pluginContext;
-
-    CFMutableDictionaryRef _tokenToBrowserMap;                  // Maps a token to a browser that can be used to scan the remaining dictionaries.
-    CFMutableDictionaryRef _browsers;                           // A Dictionary of Browser Dictionaries where the resposible browser is the key.
-    CFMutableDictionaryRef _onAddEvents;                        // A Dictionary of Event Dictionaries that describe events to trigger on a service appearing.
-    CFMutableDictionaryRef _onRemoveEvents;                     // A Dictionary of Event Dictionaries that describe events to trigger on a service disappearing.
-} BonjourUserEventsPlugin;
-
-typedef struct {
-    CFIndex refCount;
-    DNSServiceRef browserRef;
-} NetBrowserInfo;
-
-#pragma mark -
-#pragma mark Prototypes
-#pragma mark -
-// COM Stuff
-static HRESULT  QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv);
-static ULONG    AddRef(void* instance);
-static ULONG    Release(void* instance);
-
-static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID);
-static void Dealloc(BonjourUserEventsPlugin* plugin);
-
-void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID);
-
-// Plugin Management
-static void Install(void* instance);
-static void ManageEventsCallback(
-    UserEventAgentLaunchdAction action,
-    CFNumberRef token,
-    CFTypeRef eventMatchDict,
-    void                      * vContext);
-
-
-// Plugin Guts
-void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters);
-void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchToken);
-
-NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain);
-NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef);
-void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key);
-void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken);
-
-// Net Service Browser Stuff
-void ServiceBrowserCallback (DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* serviceName, const char* regtype, const char* replyDomain, void* context);
-void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary);
-
-// Convence Stuff
-const char* CStringFromCFString(CFStringRef string);
-
-// NetBrowserInfo "Object"
-NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context);
-const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info);
-void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info);
-Boolean NetBrowserInfoEqual(const void *value1, const void *value2);
-CFHashCode  NetBrowserInfoHash(const void *value);
-CFStringRef NetBrowserInfoCopyDescription(const void *value);
-
-static const CFDictionaryKeyCallBacks kNetBrowserInfoDictionaryKeyCallbacks = {
-    0,
-    NetBrowserInfoRetain,
-    NetBrowserInfoRelease,
-    NetBrowserInfoCopyDescription,
-    NetBrowserInfoEqual,
-    NetBrowserInfoHash
-};
-
-static const CFDictionaryValueCallBacks kNetBrowserInfoDictionaryValueCallbacks = {
-    0,
-    NetBrowserInfoRetain,
-    NetBrowserInfoRelease,
-    NetBrowserInfoCopyDescription,
-    NetBrowserInfoEqual
-};
-
-// COM type definition goop.
-static UserEventAgentInterfaceStruct UserEventAgentInterfaceFtbl = {
-    NULL,                   // Required padding for COM
-    QueryInterface,         // Query Interface
-    AddRef,                 // AddRef()
-    Release,                // Release()
-    Install                 // Install
-};
-
-#pragma mark -
-#pragma mark COM Management
-#pragma mark -
-
-/*****************************************************************************
-*****************************************************************************/
-static HRESULT QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv)
-{
-    CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(NULL, iid);
-
-    // Test the requested ID against the valid interfaces.
-    if(CFEqual(interfaceID, kUserEventAgentInterfaceID))
-    {
-        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
-        *ppv = myInstance;
-        CFRelease(interfaceID);
-        return S_OK;
-    }
-    else if(CFEqual(interfaceID, IUnknownUUID))
-    {
-        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
-        *ppv = myInstance;
-        CFRelease(interfaceID);
-        return S_OK;
-    }
-    else //  Requested interface unknown, bail with error.
-    {
-        *ppv = NULL;
-        CFRelease(interfaceID);
-        return E_NOINTERFACE;
-    }
-}
-
-/*****************************************************************************
-*****************************************************************************/
-static ULONG AddRef(void* instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-    return ++plugin->_refCount;
-}
-
-/*****************************************************************************
-*****************************************************************************/
-static ULONG Release(void* instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-
-    if (plugin->_refCount != 0)
-        --plugin->_refCount;
-
-    if (plugin->_refCount == 0)
-    {
-        Dealloc(instance);
-        return 0;
-    }
-
-    return plugin->_refCount;
-}
-
-/*****************************************************************************
-* Alloc
-* -
-* Functionas as both +[alloc] and -[init] for the plugin. Add any
-* initalization of member variables here.
-*****************************************************************************/
-static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID)
-{
-    BonjourUserEventsPlugin* plugin = malloc(sizeof(BonjourUserEventsPlugin));
-
-    plugin->_UserEventAgentInterface = &UserEventAgentInterfaceFtbl;
-    plugin->_pluginContext = NULL;
-
-    if (factoryID)
-    {
-        plugin->_factoryID = (CFUUIDRef)CFRetain(factoryID);
-        CFPlugInAddInstanceForFactory(factoryID);
-    }
-
-    plugin->_refCount = 1;
-    plugin->_tokenToBrowserMap = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kNetBrowserInfoDictionaryValueCallbacks);
-    plugin->_browsers = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-    plugin->_onAddEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-    plugin->_onRemoveEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-
-    return plugin;
-}
-
-/*****************************************************************************
-* Dealloc
-* -
-* Much like Obj-C dealloc this method is responsible for releasing any object
-* this plugin is holding. Unlike ObjC, you call directly free() instead of
-* [super dalloc].
-*****************************************************************************/
-static void Dealloc(BonjourUserEventsPlugin* plugin)
-{
-    CFUUIDRef factoryID = plugin->_factoryID;
-
-    if (factoryID)
-    {
-        CFPlugInRemoveInstanceForFactory(factoryID);
-        CFRelease(factoryID);
-    }
-
-    if (plugin->_tokenToBrowserMap)
-        CFRelease(plugin->_tokenToBrowserMap);
-
-    if (plugin->_browsers)
-        CFRelease(plugin->_browsers);
-
-    if (plugin->_onAddEvents)
-        CFRelease(plugin->_onAddEvents);
-
-    if (plugin->_onRemoveEvents)
-        CFRelease(plugin->_onRemoveEvents);
-
-    free(plugin);
-}
-
-/*******************************************************************************
-*******************************************************************************/
-void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID)
-{
-    (void)allocator;
-    BonjourUserEventsPlugin * result = NULL;
-
-    if (typeID && CFEqual(typeID, kUserEventAgentTypeID))
-    {
-        result = Alloc(kUserEventAgentFactoryID);
-    }
-
-    return (void *)result;
-}
-
-#pragma mark -
-#pragma mark Plugin Management
-#pragma mark -
-/*****************************************************************************
-* Install
-* -
-* This is invoked once when the plugin is loaded to do initial setup and
-* allow us to register with launchd. If UserEventAgent crashes, the plugin
-* will need to be reloaded, and hence this will get invoked again.
-*****************************************************************************/
-static void Install(void *instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-
-    plugin->_pluginContext = UserEventAgentRegisterForLaunchEvents(sPluginIdentifier, &ManageEventsCallback, plugin);
-
-    if (!plugin->_pluginContext)
-    {
-        fprintf(stderr, "%s:%s failed to register for launch events.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-}
-
-/*****************************************************************************
-* ManageEventsCallback
-* -
-* This is invoked when launchd loads a event dictionary and needs to inform
-* us what a daemon / agent is looking for.
-*****************************************************************************/
-static void ManageEventsCallback(UserEventAgentLaunchdAction action, CFNumberRef token, CFTypeRef eventMatchDict, void* vContext)
-{
-    if (action == kUserEventAgentLaunchdAdd)
-    {
-        if (!eventMatchDict)
-        {
-            fprintf(stderr, "%s:%s empty dictionary\n", sPluginIdentifier, __FUNCTION__);
-            return;
-        }
-        if (CFGetTypeID(eventMatchDict) != CFDictionaryGetTypeID())
-        {
-            fprintf(stderr, "%s:%s given non-dict for event dictionary, action %d\n", sPluginIdentifier, __FUNCTION__, action);
-            return;
-        }
-        // Launchd wants us to add a launch event for this token and matching dictionary.
-        os_log_info(OS_LOG_DEFAULT, "%s:%s calling AddEventToPlugin", sPluginIdentifier, __FUNCTION__);
-        AddEventToPlugin((BonjourUserEventsPlugin*)vContext, token, (CFDictionaryRef)eventMatchDict);
-    }
-    else if (action == kUserEventAgentLaunchdRemove)
-    {
-        // Launchd wants us to remove the event hook we setup for this token / matching dictionary.
-        // Note: eventMatchDict can be NULL for Remove.
-        os_log_info(OS_LOG_DEFAULT, "%s:%s calling RemoveEventToPlugin", sPluginIdentifier, __FUNCTION__);
-        RemoveEventFromPlugin((BonjourUserEventsPlugin*)vContext, token);
-    }
-    else
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s unknown callback event\n", sPluginIdentifier, __FUNCTION__);
-    }
-}
-
-
-#pragma mark -
-#pragma mark Plugin Guts
-#pragma mark -
-
-/*****************************************************************************
-* AddEventToPlugin
-* -
-* This method is invoked when launchd wishes the plugin to setup a launch
-* event matching the parameters in the dictionary.
-*****************************************************************************/
-void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters)
-{
-    CFStringRef domain = CFDictionaryGetValue(eventParameters, sServiceDomainKey);
-    CFStringRef type = CFDictionaryGetValue(eventParameters, sServiceTypeKey);
-    CFStringRef name = CFDictionaryGetValue(eventParameters, sServiceNameKey);
-    CFBooleanRef cfOnAdd = CFDictionaryGetValue(eventParameters, sOnServiceAddKey);
-    CFBooleanRef cfOnRemove = CFDictionaryGetValue(eventParameters, sOnServiceRemoveKey);
-
-    Boolean onAdd = false;
-    Boolean onRemove = false;
-
-    if (cfOnAdd && CFGetTypeID(cfOnAdd) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnAdd))
-        onAdd = true;
-
-    if (cfOnRemove && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnRemove))
-        onRemove = true;
-
-    // A type is required. If none is specified, BAIL
-    if (!type || CFGetTypeID(type) != CFStringGetTypeID())
-    {
-        fprintf(stderr, "%s:%s: a LaunchEvent is missing a service type.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If we aren't suppose to launch on services appearing or disappearing, this service does nothing. Ignore.
-    if (!onAdd && !onRemove)
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent is missing both onAdd and onRemove events\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If no domain is specified, assume local.
-    if (!domain)
-    {
-        domain = CFSTR("local");
-    }
-    else if (CFGetTypeID(domain) != CFStringGetTypeID() ) // If the domain is not a string, fail
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If we have a name filter, but it's not a string. This event is broken, bail.
-    if (name && CFGetTypeID(name) != CFStringGetTypeID())
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // Get us a browser
-    NetBrowserInfo* browser = CreateBrowser(plugin, type, domain);
-
-    if (!browser)
-    {
-        fprintf(stderr, "%s:%s cannot create browser\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // Create Event Dictionary
-    CFMutableDictionaryRef eventDictionary = CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-    // We store both the Token and the Dictionary. UserEventAgentSetLaunchEventState needs
-    // the token and UserEventAgentSetFireEvent needs both the token and the dictionary
-    CFDictionarySetValue(eventDictionary, sLaunchdTokenKey, launchdToken);
-    CFDictionarySetValue(eventDictionary, sLaunchdDictKey, eventParameters);
-
-    if (name)
-        CFDictionarySetValue(eventDictionary, sServiceNameKey, name);
-
-    // Add to the correct dictionary.
-    if (onAdd)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Adding browser to AddEvents", sPluginIdentifier, __FUNCTION__);
-        AddEventDictionary(eventDictionary, plugin->_onAddEvents, browser);
-    }
-
-    if (onRemove)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Adding browser to RemoveEvents", sPluginIdentifier, __FUNCTION__);
-        AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
-    }
-
-    // Add Token Mapping
-    CFDictionarySetValue(plugin->_tokenToBrowserMap, launchdToken, browser);
-
-    // Release Memory
-    CFRelease(eventDictionary);
-}
-
-/*****************************************************************************
-* RemoveEventFromPlugin
-* -
-* This method is invoked when launchd wishes the plugin to setup a launch
-* event matching the parameters in the dictionary.
-*****************************************************************************/
-void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken)
-{
-    NetBrowserInfo* browser = (NetBrowserInfo*)CFDictionaryGetValue(plugin->_tokenToBrowserMap, launchdToken);
-    Boolean othersUsingBrowser = false;
-
-    if (!browser)
-    {
-        long long value = 0;
-        CFNumberGetValue(launchdToken, kCFNumberLongLongType, &value);
-        fprintf(stderr, "%s:%s Launchd asked us to remove a token we did not register! ==Token:%lld== \n", sPluginIdentifier, __FUNCTION__, value);
-        return;
-    }
-
-    CFMutableArrayRef onAddEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onAddEvents, browser);
-    CFMutableArrayRef onRemoveEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onRemoveEvents, browser);
-
-    if (onAddEvents)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Calling RemoveEventFromArray for OnAddEvents", sPluginIdentifier, __FUNCTION__);
-        RemoveEventFromArray(onAddEvents, launchdToken);
-
-        // Is the array now empty, clean up
-        if (CFArrayGetCount(onAddEvents) == 0)
-        {
-            os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing the browser from AddEvents", sPluginIdentifier, __FUNCTION__);
-            CFDictionaryRemoveValue(plugin->_onAddEvents, browser);
-        }
-    }
-
-    if (onRemoveEvents)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Calling RemoveEventFromArray for OnRemoveEvents", sPluginIdentifier, __FUNCTION__);
-        RemoveEventFromArray(onRemoveEvents, launchdToken);
-
-        // Is the array now empty, clean up
-        if (CFArrayGetCount(onRemoveEvents) == 0)
-        {
-            os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing the browser from RemoveEvents", sPluginIdentifier, __FUNCTION__);
-            CFDictionaryRemoveValue(plugin->_onRemoveEvents, browser);
-        }
-    }
-
-    // Remove ourselves from the token dictionary.
-    CFDictionaryRemoveValue(plugin->_tokenToBrowserMap, launchdToken);
-
-    // Check to see if anyone else is using this browser.
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_tokenToBrowserMap);
-    NetBrowserInfo** browsers = malloc(((size_t)count) * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the token dictionary
-    CFDictionaryGetKeysAndValues(plugin->_tokenToBrowserMap, NULL, (const void**)browsers);
-
-    for (i = 0; i < count; ++i)
-    {
-        if (NetBrowserInfoEqual(browsers[i], browser))
-        {
-            othersUsingBrowser = true;
-            break;
-        }
-    }
-
-    // If no one else is useing our browser, clean up!
-    if (!othersUsingBrowser)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing browser %p from _browsers", sPluginIdentifier, __FUNCTION__, browser);
-        CFDictionaryRemoveValue(plugin->_browsers, browser); // This triggers release and dealloc of the browser
-    }
-    else
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Decrementing browsers %p count", sPluginIdentifier, __FUNCTION__, browser);
-        // Decrement my reference count (it was incremented when it was added to _browsers in CreateBrowser)
-        NetBrowserInfoRelease(NULL, browser);
-    }
-
-    free(browsers);
-}
-
-
-/*****************************************************************************
-* CreateBrowser
-* -
-* This method returns a NetBrowserInfo that is looking for a type of
-* service in a domain. If no browser exists, it will create one and return it.
-*****************************************************************************/
-NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain)
-{
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
-    NetBrowserInfo* browser = NULL;
-    CFDictionaryRef* dicts = malloc(((size_t)count) * sizeof(CFDictionaryRef));
-    NetBrowserInfo** browsers = malloc(((size_t)count) * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the browser dictionary
-    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, (const void**)dicts);
-
-
-    // Loop thru the browsers list and see if we can find a matching one.
-    for (i = 0; i < count; ++i)
-    {
-        CFDictionaryRef browserDict = dicts[i];
-
-        CFStringRef browserType = CFDictionaryGetValue(browserDict, sServiceTypeKey);
-        CFStringRef browserDomain = CFDictionaryGetValue(browserDict, sServiceDomainKey);
-
-        // If we have a matching browser, break
-        if ((CFStringCompare(browserType, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) &&
-            (CFStringCompare(browserDomain, domain, kCFCompareCaseInsensitive) == kCFCompareEqualTo))
-        {
-            os_log_info(OS_LOG_DEFAULT, "%s:%s: found a duplicate browser\n", sPluginIdentifier, __FUNCTION__);
-            browser = browsers[i];
-            NetBrowserInfoRetain(NULL, browser);
-            break;
-        }
-    }
-
-    // No match found, lets create one!
-    if (!browser)
-    {
-
-        browser = NetBrowserInfoCreate(type, domain, plugin);
-
-        if (!browser)
-        {
-            fprintf(stderr, "%s:%s failed to search for %s.%s", sPluginIdentifier, __FUNCTION__, CStringFromCFString(type), CStringFromCFString(domain));
-            free(dicts);
-            free(browsers);
-            return NULL;
-        }
-
-        // Service browser created, lets add this to ourselves to the dictionary.
-        CFMutableDictionaryRef browserDict = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-        CFDictionarySetValue(browserDict, sServiceTypeKey, type);
-        CFDictionarySetValue(browserDict, sServiceDomainKey, domain);
-
-        // Add the dictionary to the browsers dictionary.
-        CFDictionarySetValue(plugin->_browsers, browser, browserDict);
-
-        // Release Memory
-        CFRelease(browserDict);
-    }
-
-    free(dicts);
-    free(browsers);
-
-    return browser;
-}
-
-/*****************************************************************************
-* BrowserForSDRef
-* -
-* This method returns a NetBrowserInfo that matches the calling SDRef passed
-* in via the callback.
-*****************************************************************************/
-NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef)
-{
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
-    NetBrowserInfo* browser = NULL;
-    NetBrowserInfo** browsers = malloc(((size_t)count) * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the browser dictionary
-    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, NULL);
-
-    // Loop thru the browsers list and see if we can find a matching one.
-    for (i = 0; i < count; ++i)
-    {
-        NetBrowserInfo* currentBrowser = browsers[i];
-
-        if (currentBrowser->browserRef == sdRef)
-        {
-            browser = currentBrowser;
-            break;
-        }
-    }
-
-
-    free(browsers);
-
-    return browser;
-}
-
-/*****************************************************************************
-* AddEventDictionary
-* -
-* Adds a event to a browser's event dictionary
-*****************************************************************************/
-
-void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key)
-{
-    CFMutableArrayRef eventsForBrowser = (CFMutableArrayRef)CFDictionaryGetValue(allEventsDictionary, key);
-
-    if (!eventsForBrowser) // We have no events for this browser yet, lets add him.
-    {
-        eventsForBrowser = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-        CFDictionarySetValue(allEventsDictionary, key, eventsForBrowser);
-        os_log_info(OS_LOG_DEFAULT, "%s:%s creating a new array", sPluginIdentifier, __FUNCTION__);
-    }
-    else
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s Incrementing refcount", sPluginIdentifier, __FUNCTION__);
-        CFRetain(eventsForBrowser);
-    }
-
-    CFArrayAppendValue(eventsForBrowser, eventDict);
-    CFRelease(eventsForBrowser);
-}
-
-/*****************************************************************************
-* RemoveEventFromArray
-* -
-* Searches a Array of Event Dictionaries to find one with a matching launchd
-* token and remove it.
-*****************************************************************************/
-
-void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken)
-{
-    CFIndex i;
-    CFIndex count = CFArrayGetCount(array);
-
-    // Loop thru looking for us.
-    for (i = 0; i < count; )
-    {
-        CFDictionaryRef eventDict = CFArrayGetValueAtIndex(array, i);
-        CFNumberRef token = CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
-
-        if (CFEqual(token, launchdToken)) // This is the same event?
-        {
-            os_log_info(OS_LOG_DEFAULT, "%s:%s found token", sPluginIdentifier, __FUNCTION__);
-            CFArrayRemoveValueAtIndex(array, i);    // Remove the event,
-            break; // The token should only exist once, so it makes no sense to continue.
-        }
-        else
-        {
-            ++i; // If it's not us, advance.
-        }
-    }
-    if (i == count) os_log_info(OS_LOG_DEFAULT, "%s:%s did not find token", sPluginIdentifier, __FUNCTION__);
-}
-
-#pragma mark -
-#pragma mark Net Service Browser Stuff
-#pragma mark -
-
-/*****************************************************************************
-* ServiceBrowserCallback
-* -
-* This method is the heart of the plugin. It's the runloop callback annoucing
-* the appearence and disappearance of network services.
-*****************************************************************************/
-
-void ServiceBrowserCallback (DNSServiceRef sdRef,
-                             DNSServiceFlags flags,
-                             uint32_t interfaceIndex,
-                             DNSServiceErrorType errorCode,
-                             const char*                serviceName,
-                             const char*                regtype,
-                             const char*                replyDomain,
-                             void*                      context )
-{
-    (void)interfaceIndex;
-    (void)regtype;
-    (void)replyDomain;
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)context;
-    NetBrowserInfo* browser = BrowserForSDRef(plugin, sdRef);
-
-    if (!browser) // Missing browser?
-    {
-        fprintf(stderr, "%s:%s ServiceBrowserCallback: missing browser\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    if (errorCode != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "%s:%s ServiceBrowserCallback: errcode set %d\n", sPluginIdentifier, __FUNCTION__, errorCode);
-        return;
-    }
-
-    CFStringRef cfServiceName = CFStringCreateWithCString(NULL, serviceName, kCFStringEncodingUTF8);
-    if (cfServiceName == NULL)
-    {
-        static int msgCount = 0;
-        if (msgCount < 1000)
-        {
-            os_log_info(OS_LOG_DEFAULT, "%s:%s Can not create CFString for serviceName %s", sPluginIdentifier, __FUNCTION__, serviceName);
-            msgCount++;
-        }
-        return;
-    }
-
-    if (flags & kDNSServiceFlagsAdd)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s calling HandleTemporaryEventsForService Add\n", sPluginIdentifier, __FUNCTION__);
-        HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onAddEvents);
-    }
-    else
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s calling HandleTemporaryEventsForService Remove\n", sPluginIdentifier, __FUNCTION__);
-        HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onRemoveEvents);
-    }
-
-    CFRelease(cfServiceName);
-}
-
-/*****************************************************************************
-* HandleTemporaryEventsForService
-* -
-* This method handles the firing of one shot events. Aka. Events that are
-* signaled when a service appears / disappears. They have a temporarly
-* signaled state.
-*****************************************************************************/
-void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary)
-{
-    CFArrayRef events = (CFArrayRef)CFDictionaryGetValue(eventsDictionary, browser); // Get events for the browser we passed in.
-    CFIndex i;
-    CFIndex count;
-
-    if (!events)  // Somehow we have a orphan browser...
-        return;
-
-    count = CFArrayGetCount(events);
-
-    // Go thru the events and run filters, notifity if they pass.
-    for (i = 0; i < count; ++i)
-    {
-        CFDictionaryRef eventDict = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i);
-        CFStringRef eventServiceName = (CFStringRef)CFDictionaryGetValue(eventDict, sServiceNameKey);
-        CFNumberRef token = (CFNumberRef) CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
-        CFDictionaryRef dict = (CFDictionaryRef) CFDictionaryGetValue(eventDict, sLaunchdDictKey);
-
-        // Currently we only filter on service name, that makes this as simple as...
-        if (!eventServiceName || CFEqual(serviceName, eventServiceName))
-        {
-            uint64_t tokenUint64;
-            // Signal Event: This is edge trigger. When the action has been taken, it will not
-            // be remembered anymore.
-
-            os_log_info(OS_LOG_DEFAULT, "%s:%s HandleTemporaryEventsForService signal\n", sPluginIdentifier, __FUNCTION__);
-            CFNumberGetValue(token, kCFNumberLongLongType, &tokenUint64);
-
-            xpc_object_t jobRequest = _CFXPCCreateXPCObjectFromCFObject(dict);
-
-            UserEventAgentFireEvent(plugin->_pluginContext, tokenUint64, jobRequest);
-            xpc_release(jobRequest);
-        }
-    }
-}
-
-#pragma mark -
-#pragma mark Convenience
-#pragma mark -
-
-/*****************************************************************************
-* CStringFromCFString
-* -
-* Silly convenence function for dealing with non-critical CFSTR -> cStr
-* conversions.
-*****************************************************************************/
-
-const char* CStringFromCFString(CFStringRef string)
-{
-    const char* defaultString = "??????";
-    const char* cstring;
-
-    if (!string)
-        return defaultString;
-
-    cstring = CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
-
-    return (cstring) ? cstring : defaultString;
-
-}
-
-#pragma mark -
-#pragma mark NetBrowserInfo "Object"
-#pragma mark -
-/*****************************************************************************
-* NetBrowserInfoCreate
-* -
-* The method creates a NetBrowserInfo Object and initalizes it.
-*****************************************************************************/
-NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context)
-{
-    NetBrowserInfo* outObj = NULL;
-    DNSServiceRef browserRef = NULL;
-    char* cServiceType = NULL;
-    char* cDomain = NULL;
-    Boolean success = true;
-
-    CFIndex serviceSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(serviceType), kCFStringEncodingUTF8);
-    cServiceType = calloc((size_t)serviceSize, 1);
-    success = CFStringGetCString(serviceType, cServiceType, serviceSize, kCFStringEncodingUTF8);
-
-
-    if (domain)
-    {
-        CFIndex domainSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(domain), kCFStringEncodingUTF8);
-        if (domainSize)
-        {
-            cDomain = calloc((size_t)domainSize, 1);
-            success = success && CFStringGetCString(domain, cDomain, domainSize, kCFStringEncodingUTF8);
-        }
-    }
-
-    if (!success)
-    {
-        fprintf(stderr, "%s:%s LaunchEvent has badly encoded service type or domain.\n", sPluginIdentifier, __FUNCTION__);
-        free(cServiceType);
-
-        if (cDomain)
-            free(cDomain);
-
-        return NULL;
-    }
-
-    DNSServiceErrorType err = DNSServiceBrowse(&browserRef, 0, 0, cServiceType, cDomain, ServiceBrowserCallback, context);
-
-    if (err != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "%s:%s Failed to create browser for %s, %s\n", sPluginIdentifier, __FUNCTION__, cServiceType, cDomain);
-        free(cServiceType);
-
-        if (cDomain)
-            free(cDomain);
-
-        return NULL;
-    }
-
-    DNSServiceSetDispatchQueue(browserRef, dispatch_get_main_queue());
-
-
-    outObj = malloc(sizeof(NetBrowserInfo));
-
-    outObj->refCount = 1;
-    outObj->browserRef = browserRef;
-
-    os_log_info(OS_LOG_DEFAULT, "%s:%s: created new object %p", sPluginIdentifier, __FUNCTION__, outObj);
-
-    free(cServiceType);
-
-    if (cDomain)
-        free(cDomain);
-
-    return outObj;
-}
-
-/*****************************************************************************
-* NetBrowserInfoRetain
-* -
-* The method retains a NetBrowserInfo object.
-*****************************************************************************/
-const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info)
-{
-    (void)allocator;
-    NetBrowserInfo* obj = (NetBrowserInfo*)info;
-
-    if (!obj)
-        return NULL;
-
-    ++obj->refCount;
-    os_log_info(OS_LOG_DEFAULT, "%s:%s: Incremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
-
-    return obj;
-}
-
-/*****************************************************************************
-* NetBrowserInfoRelease
-* -
-* The method releases a NetBrowserInfo object.
-*****************************************************************************/
-void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info)
-{
-    (void)allocator;
-    NetBrowserInfo* obj = (NetBrowserInfo*)info;
-
-    if (!obj)
-        return;
-
-    if (obj->refCount == 1)
-    {
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: DNSServiceRefDeallocate %p", sPluginIdentifier, __FUNCTION__, obj->browserRef);
-        DNSServiceRefDeallocate(obj->browserRef);
-        free(obj);
-    }
-    else
-    {
-        --obj->refCount;
-        os_log_info(OS_LOG_DEFAULT, "%s:%s: Decremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
-    }
-
-}
-
-/*****************************************************************************
-* NetBrowserInfoEqual
-* -
-* The method is used to compare two NetBrowserInfo objects for equality.
-*****************************************************************************/
-Boolean NetBrowserInfoEqual(const void *value1, const void *value2)
-{
-    NetBrowserInfo* obj1 = (NetBrowserInfo*)value1;
-    NetBrowserInfo* obj2 = (NetBrowserInfo*)value2;
-
-    if (obj1->browserRef == obj2->browserRef)
-        return true;
-
-    return false;
-}
-
-/*****************************************************************************
-* NetBrowserInfoHash
-* -
-* The method is used to make a hash for the object. We can cheat and use the
-* browser pointer.
-*****************************************************************************/
-CFHashCode  NetBrowserInfoHash(const void *value)
-{
-    return (CFHashCode)((NetBrowserInfo*)value)->browserRef;
-}
-
-
-/*****************************************************************************
-* NetBrowserInfoCopyDescription
-* -
-* Make CF happy.
-*****************************************************************************/
-CFStringRef NetBrowserInfoCopyDescription(const void *value)
-{
-    (void)value;
-    return CFStringCreateWithCString(NULL, "NetBrowserInfo: No useful description", kCFStringEncodingUTF8);
-}
-
diff --git a/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp b/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp
deleted file mode 100644
index e495cc6..0000000
--- a/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp
+++ /dev/null
@@ -1,2036 +0,0 @@
-//
-//  BonjourTop.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <ncurses.h>
-
-#include "BonjourTop.h"
-#include "DNSFrame.h"
-#include "CaptureFile.h"
-#include "bjsocket.h"
-#include "bjstring.h"
-
-#include <sys/sysctl.h>
-#include <mach/mach.h>
-
-#define SERVICE_IPV4    0
-#define SERVICE_IPV6    1
-#define APP_IPV4        2
-#define APP_IPV6        3
-
-#define TRACE_PLATFORM_UNKNOWN              0
-#define TRACE_PLATFORM_OSX                  1
-#define TRACE_PLATFORM_iOS                  2
-#define TRACE_PLATFORM_APPLE_TV             3
-#define TRACE_PLATFORM_NON_APPLE_PLATFORM   4
-#define DISCOVERYD_TRACE_PLATFORM_OSX                   (1 | 0x80)
-#define DISCOVERYD_TRACE_PLATFORM_iOS                   (2 | 0x80)
-#define DISCOVERYD_TRACE_PLATFORM_APPLE_TV              (3 | 0x80)
-#define DISCOVERYD_TRACE_PLATFORM_NON_APPLE_PLATFORM    (4 | 0x80)
-
-int CDeviceNode::nCreateCount = 0;
-static integer_t Usage(void);
-
-char CVSFileNameExample[] ="BonjourTop";
-char DeviceNameExample[] ="BonjourTopDevice.csv";
-
-char Service2App[][50] = {
-    // Service_Name,             Application_Name,    Browse_OS_Type, Register_OS_Type
-    "_device-info._tcp.local.",     "Device-Info",  "?" , "?",
-    "_rfb._tcp.local.",             "Finder",       "X" , "?",
-    "_afpovertcp._tcp.local.",      "Finder",       "?" , "X",
-    "_adisk._tcp.local.",           "Finder",       "?" , "X",
-    "_odisk._tcp.local.",           "Finder",       "?" , "X",
-    "_smb._tcp.local.",             "Finder",       "X" , "X",
-    "_smb2._tcp.local.",            "Finder",       "X" , "X",
-    "_workstation._tcp.local.",     "Finder",       "X" , "X",
-    "_kerberos.",                   "Finder",       "X" , "X",
-    "_nfs._tcp.local.",             "Finder",       "X" , "X",
-    "_ftp._tcp.local.",             "Finder",       "X" , "X",
-
-    "_appletv._tcp.local.",         "AppleTV",      "?" , "t",
-    "_appletv-v2._tcp.local.",      "AppleTV",      "?" , "?",
-    "_appletv-pair._tcp.local.",    "AppleTV",      "?" , "?",
-
-    "A",                            "LinkLocal",    "?" , "?",
-    "AAAA",                         "LinkLocal",    "?" , "?",
-    "*.ip6.arpa.",                  "LinkLocal",     "?" , "?",
-    "*.arpa.",                      "LinkLocal",    "?" , "?",
-
-    "_airplay._tcp.local.",         "AirPlay",      "?" , "t",
-    "_airplayTXT",                  "AirPlay","?" , "t",
-    "_raop._tcp.local.",            "AirPlay","?" , "?",
-
-    "_ubd._tcp.local.",             "Ubiquity",     "?" , "?",
-    "_ubiquity._tcp.local.",        "Ubiquity",     "?" , "?",
-    "_ubiquityV1._tcp.local.",        "Ubiquity",     "?" , "?",
-    "_ubiquityV2._tcp.local.",        "Ubiquity",     "?" , "?",
-
-    " _ipps._tcp.local.",           "Printing",     "?" , "?",
-    "_ipp._tcp.local.",             "Printing",     "?" , "?",
-    "_ipps._tcp.local.",            "Printing",     "?" , "?",
-    "_ipp-tls._tcp.local.",         "Printing",     "?" , "?",
-    "_printer._tcp.local.",         "Printing",     "?" , "?",
-    "_scanner._tcp.local.",         "Printing",     "?" , "?",
-    "_pdl-datastream._tcp.local.",  "Printing",     "?" , "?",
-    "_fax-ipp._tcp.local.",         "Printing",     "?" , "?",
-
-    "_apple-mobdev._tcp.local.",    "iTunes-WiFiSync","?" , "i",
-    "_daap._tcp.local.",            "iTunes",       "?" , "?",
-
-    "_sftp-ssh._tcp.local.",        "Terminal",     "?" , "X",
-    "_ssh._tcp.local.",             "Terminal",     "?" , "X",
-
-    "_sleep-proxy._udp.local.",     "Sleep Proxy",  "?" , "?",
-    "_keepalive._dns-sd._udp.local.","Sleep Proxy", "X" , "?",
-    "_services._dns-sd._udp.local.", "Services",    "?" , "?",
-    "ANY *.ip6.arpa.",              "Sleep Proxy",  "?" , "?",
-    "ANY *.arpa.",                  "Sleep Proxy",  "?" , "?",
-
-    "AirPort_presence._tcp.local.", "AirPort",      "?" , "?",
-    "_airport._tcp.local.",         "AirPort",      "?" , "?",
-    "_presence._tcp.local.",        "iChat",        "X" , "X",
-    "_home-sharing._tcp.local.",    "HomeSharing",  "?" , "X",
-
-    "_ptp._tcp.local.",             "iPhoto",       "?" , "X",
-    "_ica-networking2._tcp.local.", "iPhoto",       "X" , "X",
-    "_mobileiphoto._udp.local.",    "iPhoto",       "?" , "?",
-    "_mobileiphoto2._udp.local.",   "iPhoto",       "?" , "?",
-    "_dpap._tcp.local.",            "iPhoto",       "?" , "X",
-    "_airdrop._tcp.local.",         "AirDrop",      "?" , "?",
-    "_http._tcp.local.",            "Safari",       "X" , "X",
-    "_net-assistant._udp.local.","Apple Remote Desktop","X" , "X",
-    "_servermgr._tcp.local.",       "OSX Server",   "X" , "X",
-    ""
-};
-
-char DeviceInfo2DeviceOS[][50] = {
-    // deviceModel,   deviceType
-    "MacBookAir",       "X",
-    "MacBookPro",       "X",
-    "Macmini",          "X",
-    "iMac",             "X",
-    "MacPro",           "X",
-    "MacBook",          "X",
-    "AAPLJ15",          "X",
-    "AAPLJ41",          "X",
-    "AAPLJ43",          "X",
-    "AAPLJ45",          "X",
-    "AAPLJ90",          "X",
-    "AAPLJ17",          "X",
-    "PowerMac",         "X",
-
-
-    "J33AP",            "t",
-    "J33iAP",           "t",
-    "J71AP",            "i",
-    "J72AP",            "i",
-    "J75AP",            "i",
-    "J85DEV",           "i",
-    "K66AP",            "t",
-    "N41AP",            "i",
-    "N42AP",            "i",
-    "N48AP",            "i",
-    "N51AP",            "i",
-    "N53AP",            "i",
-    "N78AP",            "i",
-    "P101AP",           "i",
-    "P102AP",           "i",
-    "P103AP",           "i",
-    "P105AP",           "i",
-    "P106AP",           "i",
-    "P107AP",           "i",
-    "AirPort",          "b",
-    "TimeCapsule",          "b",
-    ""
-};
-
-char Name2DeviceOS[][50] = {
-    // Name contains,   osType
-    "iPhone",           "i",
-    "phone",            "i",
-    "Phone",            "i",
-    "iPod",             "i",
-    "iPad",             "i",
-    "ipad",             "i",
-    "Apple-TV",         "t",
-    "AppleTV",          "t",
-    "MacBook",          "X",
-    "macbook",          "X",
-    "iMac",             "X",
-    "macmini",          "X",
-    ""
-};
-
-BJ_UINT64 Hash(const char* pStr);
-BJ_UINT64 Hash2(char* pStr);
-
-
-CSocketStats::CSocketStats()
-{
-    Init();
-
-}
-void CSocketStats::Init()
-{
-    m_nFrameCount = 0;
-
-    m_nQuestionOnlyFrames = 0;
-    m_nAnswerOnlyFrames = 0;
-    m_nQandAFrames = 0;
-
-    m_SampleDay = 0;
-}
-
-void CSocketStats::Clear()
-{
-    Init();
-}
-
-CBonjourTop::CBonjourTop()
-{
-
-    m_bCursers = true;
-    m_pTcpDumpFileName = NULL;
-    m_pExportFileName = CVSFileNameExample;
-    m_DeviceFileName = DeviceNameExample;
-
-    m_nFrameCount = 0;
-    m_nTotalBytes = 0;
-
-    m_StartTime = m_EndTime = time(NULL);
-
-    m_SnapshotSeconds = 0;
-
-    m_MinAnswerCountForTruncatedFrames = 0;
-    m_AvgAnswerCountForTruncatedFrames = 0;
-    m_MaxAnswerCountForTruncatedFrames = 0;
-
-    window_size_changed = false;
-    m_bImportExportDeviceMap = false;
-
-    // loadup application mapping
-    for(int i=0; Service2App[i][0] != 0;)
-    {
-        BJString a(Service2App[i++]);
-
-        m_Service2AppMap.FindwithAddRecord(&a)->value = Service2App[i++];
-        m_Service2osBrowseMap.FindwithAddRecord(&a)->value = Service2App[i++];
-        m_Service2osRegisterMap.FindwithAddRecord(&a)->value = Service2App[i++];
-
-    }
-
-
-    m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
-  //  m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
-
-    Usage();
-
-}
-
-static int CbClearDataDevice(const void* pNode, const void*)
-{
-    CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
-
-    pDeviceRecord->ClearData();
-    return 0;
-}
-
-void CBonjourTop::Reset()
-{
-    m_nFrameCount = 0;
-    m_nTotalBytes = 0;
-
-    m_MinAnswerCountForTruncatedFrames = 0;
-    m_AvgAnswerCountForTruncatedFrames = 0;
-    m_MaxAnswerCountForTruncatedFrames = 0;
-
-    m_StartTime = m_EndTime = time(NULL);
-
-    m_ServicePtrCache.ClearAll();
-    m_ApplPtrCache.ClearAll();
-
-    m_ServicePtrCacheIPv6.ClearAll();
-    m_ApplPtrCacheIPv6.ClearAll();
-
-    // Clear all data in the map
-    m_AppBreakdownIPv4OSX.clear();
-    m_AppBreakdownIPv4iOS.clear();
-    m_AppBreakdownIPv6OSX.clear();
-    m_AppBreakdownIPv6iOS.clear();
-
-    m_ServiceBreakdownIPv4OSX.clear();
-    m_ServiceBreakdownIPv4iOS.clear();
-    m_ServiceBreakdownIPv6OSX.clear();
-    m_ServiceBreakdownIPv6iOS.clear();
-
-    // Clear Socket Status
-    for (int i = 0; i < NUM_SOCKET_STATUS; i++)
-    {
-        m_SocketStatus[i].Clear();
-    }
-
-    for (int i = 0; i < HOURS_IN_DAY; i++)
-    {
-        for (int j = 0; j < MINUTES_IN_HOUR; j++)
-        {
-            m_MinSnapshot[i][j].Clear();
-        }
-    }
-
-    CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
-    if (pDeviceNode)
-    {
-        pDeviceNode->CallBack(&CbClearDataDevice,NULL);
-    }
-
-}
-
-void CBonjourTop::SetIPAddr(const char* pStr)
-{
-    m_IPv4Addr.Set(pStr);
-
-}
-
-void CBonjourTop::UpdateRecord(CStringTree&  Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
-{
-    BJ_UINT64 nHashValue = 0;
-    char deviceOS = '?';
-
-    nHashValue = Hash(RecordName.GetBuffer());
-    CStringNode* pRecord = Cache.Find(&nHashValue);
-    if (pRecord == NULL)
-    {
-        pRecord = (CStringNode*) Cache.FindwithAddRecord(&nHashValue);
-        strlcpy(pRecord->m_Value, RecordName.GetBuffer(), sizeof(pRecord->m_Value));
-    }
-
-    if (pRecord == NULL)
-        return;
-    CDeviceNode dummyDevice;
-    CDeviceNode *device;
-    CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
-
-    device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
-    pRecord->m_nBytes += 10 + nBytes;
-    deviceOS = device->GetDeviceOS();
-    device->frameTotal.Increment(m_nFrameCount);
-
-    if (pRecord->m_nLastFrameIndex != m_nFrameCount)
-    {
-        pRecord->m_nLastFrameIndex = m_nFrameCount;
-
-        pRecord->m_nFrames++;
-        if (deviceOS == 't' || deviceOS == 'i')
-        {
-            pRecord->m_nFramesiOS++;
-        }
-        else if (deviceOS == 'X')
-        {
-            pRecord->m_nFramesOSX++;
-        }
-    }
-
-    // Update Total Device Count
-    if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-    {
-        pRecord->m_nDeviceTotalCount++;
-        pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-    }
-
-    if (m_Frame.IsQueryFrame())
-    {
-        GetOSTypeFromQuery(pDNSRecord, ServiceName);
-        device->questionFrame.Increment(m_nFrameCount);
-        if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
-
-            pRecord->m_nQuestionFrames++;
-
-            if (deviceOS == 't' || deviceOS == 'i')
-            {
-                pRecord->m_nQuestionFramesiOS++;
-            }
-            else if (deviceOS == 'X')
-            {
-                pRecord->m_nQuestionFramesOSX++;
-            }
-
-            if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-            {
-                pRecord->m_nDeviceAskingCount++;
-                pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-            }
-        }
-    }
-    else
-    {
-        GetOSTypeFromRegistration(pDNSRecord,ServiceName);
-
-        device->answerFrame.Increment(m_nFrameCount);
-        if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
-
-            pRecord->m_nAnswerFrames++;
-            if (deviceOS == 't' || deviceOS == 'i')
-            {
-                pRecord->m_nAnswerFramesiOS++;
-            }
-            else if (deviceOS == 'X')
-            {
-                pRecord->m_nAnswerFramesOSX++;
-            }
-
-            if (bGoodbye)
-            {
-                pRecord->m_nGoodbyeFrames++;
-            }
-
-            if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-            {
-                pRecord->m_nDeviceAnsweringCount++;
-                pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-            }
-        }
-    }
-
-    if (m_Frame.IsWakeFrame())
-    {
-        if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
-            if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
-            {
-                pRecord->m_nWakeFrames++;
-                pRecord->m_lastQUFrameTime = m_Frame.GetTime();
-                device->QUFrame.Increment(m_nFrameCount);
-            }
-            pRecord->m_lastQUFrameTime = m_Frame.GetTime();
-        }
-    }
-
-
-}
-
-void CBonjourTop::UpdateShortRecordHelper(BJ_UINT32 cacheType, BJ_UINT32 tracePlatform, BJ_UINT32 traceVersion, char deviceOS, CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
-{
-    bool isOSX = false;
-    BJString versionNumber = "mDNSResponder-";
-    const int version_max_length = 11; // largest number is 0xffffffff = 4294967295
-    char versionChar[version_max_length];
-
-    CStringShortTree *cache;
-    map<BJString, CStringShortTree*>* myMap;
-
-    if ((tracePlatform | 0x80) == tracePlatform)
-    {
-        versionNumber = "Discoveryd-";
-    }
-
-    snprintf(versionChar, sizeof(versionChar), "%u", 0); // Set versionChar to "0" by default
-    if (tracePlatform == TRACE_PLATFORM_UNKNOWN) // Pre iOS 7 or Pre OSX 10.9
-    {
-        if (deviceOS == 'i' || deviceOS == 't') // Pre iOS 7
-        {
-            isOSX = false;
-        }
-        else if (deviceOS == 'X') // Pre OSX 10.9
-        {
-            isOSX = true;
-        }
-    }
-    else if ((tracePlatform == TRACE_PLATFORM_OSX) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_OSX)) // >= OSX 10.9
-    {
-        isOSX = true;
-        snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
-    }
-    else if ((tracePlatform == TRACE_PLATFORM_iOS) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_iOS)) // >= iOS 7.x
-    {
-        isOSX = false;
-        snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
-    }
-    else if ((tracePlatform == TRACE_PLATFORM_APPLE_TV) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_APPLE_TV))
-    {
-        snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
-    }
-
-    versionNumber += (const char*)versionChar;
-
-    switch (cacheType) {
-        case SERVICE_IPV4:
-            if (isOSX)
-            {
-                myMap = &m_ServiceBreakdownIPv4OSX;
-            }
-            else
-            {
-                myMap = &m_ServiceBreakdownIPv4iOS;
-            }
-            break;
-        case SERVICE_IPV6:
-            if (isOSX)
-            {
-                myMap = &m_ServiceBreakdownIPv6OSX;
-            }
-            else
-            {
-                myMap = &m_ServiceBreakdownIPv6iOS;
-            }
-            break;
-        case APP_IPV4:
-            if (isOSX)
-            {
-                myMap = &m_AppBreakdownIPv4OSX;
-            }
-            else
-            {
-                myMap = &m_AppBreakdownIPv4iOS;
-            }
-            break;
-        case APP_IPV6:
-            if (isOSX)
-            {
-                myMap = &m_AppBreakdownIPv6OSX;
-            }
-            else
-            {
-                myMap = &m_AppBreakdownIPv6iOS;
-            }
-            break;
-
-        default:
-            return;
-            break;
-    }
-
-    if (myMap->find(versionNumber) == myMap->end()) // Version number not found. Create new record
-    {
-        myMap->insert(std::pair<BJString, CStringShortTree*>(versionNumber, new CStringShortTree()));
-    }
-    cache = (*myMap)[versionNumber];
-    UpdateShortRecord(cache, pDNSRecord, RecordName, ServiceName, nBytes, bGoodbye);
-}
-
-void CBonjourTop::UpdateShortRecord(CStringShortTree*  Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
-{
-    if (Cache == NULL)
-    {
-        return;
-    }
-
-    BJ_UINT64 nHashValue = 0;
-
-    nHashValue = Hash(RecordName.GetBuffer());
-    CStringShortNode* pRecord = Cache->Find(&nHashValue);
-    if (pRecord == NULL)
-    {
-        pRecord = (CStringShortNode*) Cache->FindwithAddRecord(&nHashValue);
-        if (pRecord)
-            strlcpy(pRecord->m_Value, RecordName.GetBuffer(), sizeof(pRecord->m_Value));
-    }
-
-    if (pRecord == NULL)
-    {
-        return;
-    }
-
-    CDeviceNode dummyDevice;
-    CDeviceNode *device;
-    CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
-
-    device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
-    pRecord->m_nBytes += 10 + nBytes;
-    device->frameTotal.Increment(m_nFrameCount);
-
-    if (pRecord->m_nLastFrameIndex != m_nFrameCount)
-    {
-        pRecord->m_nLastFrameIndex = m_nFrameCount;
-        pRecord->m_nFrames++;
-    }
-
-    // Update Total Device Count
-    if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-    {
-        pRecord->m_nDeviceTotalCount++;
-        pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-    }
-
-    if (m_Frame.IsQueryFrame())
-    {
-        GetOSTypeFromQuery(pDNSRecord, ServiceName);
-        device->questionFrame.Increment(m_nFrameCount);
-        if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
-
-            pRecord->m_nQuestionFrames++;
-
-            if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-            {
-                pRecord->m_nDeviceAskingCount++;
-                pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-            }
-
-        }
-    }
-    else
-    {
-        GetOSTypeFromRegistration(pDNSRecord,ServiceName);
-
-        device->answerFrame.Increment(m_nFrameCount);
-        if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
-
-            pRecord->m_nAnswerFrames++;
-
-            if (bGoodbye)
-            {
-                pRecord->m_nGoodbyeFrames++;
-            }
-
-            if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
-            {
-                pRecord->m_nDeviceAnsweringCount++;
-                pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-            }
-        }
-    }
-
-    if (m_Frame.IsWakeFrame())
-    {
-        if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
-        {
-            pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
-            if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
-            {
-                pRecord->m_nWakeFrames++;
-                pRecord->m_lastQUFrameTime = m_Frame.GetTime();
-                device->QUFrame.Increment(m_nFrameCount);
-            }
-            pRecord->m_lastQUFrameTime = m_Frame.GetTime();
-        }
-    }
-
-
-}
-
-void CBonjourTop::GetOSTypeFromQuery(CDNSRecord *pDNSRecord,BJString& ServiceName)
-{
-    if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
-    {
-        StringMapNode* pStringNode = m_Service2osBrowseMap.Find(&ServiceName);
-        if (pStringNode && *pStringNode->value.GetBuffer() != '?')
-        {
-            CIPDeviceNode *ipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-            if (ipNode->pDeviceNode)
-            {
-                StringMapNode* pStringNode_temp = m_Service2osBrowseMap.Find(&ServiceName);
-                ipNode->pDeviceNode->SetDeviceOS(*pStringNode_temp->value.GetBuffer(),ServiceName.GetBuffer());
-            }
-        }
-    }
-}
-
-void CBonjourTop::GetOSTypeFromRegistration(CDNSRecord *pDNSRecord,BJString& ServiceName)
-{
-    CDeviceNode* deviceNode = NULL;
-    BJString sDeviceName;
-
-    if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
-    {
-        BJString sInstanceName;
-        pDNSRecord->GetRdata(sInstanceName,0,99);
-        CDNSRecord* pSRVRecord = m_Frame.FindAdditionRecord(sInstanceName, DNS_TYPE_SRV);
-        if (pSRVRecord)
-        {
-            pSRVRecord->GetRdata(sDeviceName,0,1);
-        }
-        else
-        {
-            sDeviceName = sInstanceName;
-        }
-        deviceNode = m_DeviceMap.Find(&sDeviceName);
-    }
-
-    // Name guess
-     if (Name2OSType(sDeviceName,deviceNode))
-         return;
-
-    StringMapNode* pStringNode = m_Service2osRegisterMap.Find(&ServiceName);
-
-    if (pStringNode == NULL || *pStringNode->value.GetBuffer() == '?')
-        return;
-
-
-
-    if (sDeviceName.GetLength() > 0)
-    {
-        // update global device table with os type
-        if (deviceNode)
-        {
-            deviceNode->SetDeviceOS(*pStringNode->value.GetBuffer(),ServiceName.GetBuffer());
-        }
-    }
-}
-bool CBonjourTop::Name2OSType(BJString name,CDeviceNode* device)
-{
-    if (device == NULL)
-        return false;
-    // try to set device type from common names
-    for (int i=0; Name2DeviceOS[i][0] != 0; i +=2)
-    {
-        if (name.Contains(Name2DeviceOS[i]))
-        {
-            device->SetDeviceOS(Name2DeviceOS[i+1][0], "Name Mapping");
-            return true;
-        }
-    }
-    return false;
-}
-void CBonjourTop::ProcessFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength,BJ_UINT64 nFrameTime)
-{
-
-    m_Frame.ParseDNSFrame(pBuffer, nLength, nFrameTime);
-
-    if (m_Collection.IsValid())
-    {
-        // setup static collectby
-        CollectByPacketCount::nFrameIndex = m_nFrameCount;
-        CollectBySameSubnetDiffSubnet::bSameSubnet = m_Frame.m_SourceIPAddress.IsIPv6()? true: m_IPv4Addr.IsSameSubNet(&m_Frame.m_SourceIPAddress);
-        m_Collection.ProcessFrame(&m_Frame);
-        return;
-    }
-
-    if (m_Frame.IsTruncatedFrame())
-    {
-        if (m_Frame.GetAnswerCount() > 0)
-        {
-            if (m_AvgAnswerCountForTruncatedFrames)
-            {
-                m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
-                m_AvgAnswerCountForTruncatedFrames /=2;
-            }
-            else
-                m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
-
-            if (m_MinAnswerCountForTruncatedFrames > m_Frame.GetAnswerCount() || m_MinAnswerCountForTruncatedFrames == 0)
-                m_MinAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
-            if (m_MaxAnswerCountForTruncatedFrames < m_Frame.GetAnswerCount())
-                m_MaxAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
-
-        }
-    }
-
-    // find min snapshot bucket
-    time_t now = time(NULL);
-    struct tm* timeStruct = localtime(&now);
-    if (m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay != timeStruct->tm_mday)
-    {
-        //Reset Snapshot 24 hour wrap around
-        m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].Init();
-        m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay = timeStruct->tm_mday;
-
-    }
-    m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_nFrameCount++;
-
-    if (m_Frame.GetQuestionCount() == 0 && m_Frame.GetAnswerCount() > 0)
-        m_SocketStatus[0].m_nAnswerOnlyFrames++;
-    else if (m_Frame.GetQuestionCount() > 0 && m_Frame.GetAnswerCount() == 0)
-        m_SocketStatus[0].m_nQuestionOnlyFrames++;
-    else
-        m_SocketStatus[0].m_nQandAFrames++;
-
-    BJString InstanceName;
-    BJString RecordName;
-    BJString ApplRecordName;
-
-    /// first get the name to address
-    for (int dnsItemsIndex =m_Frame.GetQuestionCount(); dnsItemsIndex < m_Frame.GetMaxRecords();dnsItemsIndex++)
-    {
-        CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
-        if (pDNSRecord == NULL)
-            continue;
-
-        if (pDNSRecord->m_RecType == DNS_TYPE_A)
-        {
-            BJString sName;
-            pDNSRecord->GetDnsRecordName(sName, 0, 1);
-            BJIPAddr ip;
-            ip.Setv4Raw(pDNSRecord->GetStartofRdata());
-
-            CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
-            device->ipAddressv4 = ip;
-
-            // create ip to name mapping
-            CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
-
-            if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName &&  pipNode->pDeviceNode->m_Key != device->m_Key)
-            {
-                pipNode->pDeviceNode->bDuplicate = true;
-                device->MergeData(pipNode->pDeviceNode);
-                pipNode->pDeviceNode->ClearData();
-                // remap IPv6
-                if (!pipNode->pDeviceNode->ipAddressv6.IsEmpty())
-                {
-                    CIPDeviceNode* ipv6Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv6);
-                    if (ipv6Node)
-                        ipv6Node->pDeviceNode = device;
-                }
-            }
-
-            pipNode->pDeviceNode = device;
-            Name2OSType(sName,device);
-        }
-
-        if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
-        {
-            BJString sName;
-            pDNSRecord->GetDnsRecordName(sName, 0, 1);
-            BJIPAddr ip;
-            ip.Setv6Raw(pDNSRecord->GetStartofRdata());
-
-            if (ip.IsIPv6LinkLocal())
-            {
-                CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
-                device->ipAddressv6 = ip;
-
-                // create ip to name mapping
-                CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
-
-                if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName && pipNode->pDeviceNode->m_Key != device->m_Key)
-                {
-                    pipNode->pDeviceNode->bDuplicate = true;
-                    device->MergeData(pipNode->pDeviceNode);
-                    pipNode->pDeviceNode->ClearData();
-                    // remap IPv4
-                    if (!pipNode->pDeviceNode->ipAddressv4.IsEmpty())
-                    {
-                        CIPDeviceNode* ipv4Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv4);
-                        if (ipv4Node)
-                            ipv4Node->pDeviceNode = device;
-                    }
-                }
-
-                pipNode->pDeviceNode = device;
-                Name2OSType(sName,device);
-            }
-        }
-        if (pDNSRecord->m_RecType == DNS_TYPE_SRV)
-        {   // Save SVR to Target
-            BJString sName;
-            pDNSRecord->GetDnsRecordName(sName, 0, 1);
-            StringMapNode *node = SVRtoDeviceName.FindwithAddRecord(&sName);
-            pDNSRecord->GetRdata(node->value, 0, 1);
-        }
-    }
-
-    CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
-    CDeviceNode* device = pipNode->pDeviceNode;
-    if (device == NULL)
-    {
-        // find the device by mac address
-        CMACAddrDeviceNode *macDevice = m_MACtoDevice.FindwithAddRecord(&m_Frame.m_SourceMACAddress);
-        device = macDevice->device;
-        if (device == NULL)
-        {
-            // auto create a device record
-            BJString name = m_Frame.m_SourceIPAddress.GetString();
-            device = m_DeviceMap.FindwithAddRecord(&name);
-            device->bIPName = true;
-            macDevice->device = device;
-        }
-
-        if (m_Frame.m_SourceIPAddress.IsIPv4())
-            device->ipAddressv4 = m_Frame.m_SourceIPAddress;
-        else
-            device->ipAddressv6 = m_Frame.m_SourceIPAddress;
-        if (device->macAddress.IsEmpty())
-            device->macAddress = m_Frame.m_SourceMACAddress;
-
-        pipNode->pDeviceNode = device;
-    }
-    device->bHasFrames = true;
-    // update mac address
-    if (m_Frame.IsQueryFrame() ||  device->GetDeviceOS() == 'i' ) // iOS don't use BSP so we can use SourceIP
-    {
-        if (m_Frame.m_SourceIPAddress.IsIPv4())
-            device->ipAddressv4 = m_Frame.m_SourceIPAddress;
-        if (m_Frame.m_SourceIPAddress.IsIPv6())
-            device->ipAddressv6 =m_Frame.m_SourceIPAddress;
-        device->macAddress = m_Frame.m_SourceMACAddress;
-    }
-
-    BJ_UINT8 traceplatform = TRACE_PLATFORM_UNKNOWN;
-    BJ_UINT32 traceversion = 0;
-    BJMACAddr traceMac;
-    if (device /*&& device->GetDeviceOS() == '?' */&& m_Frame.GetTracingInfo(traceplatform, traceversion, traceMac))
-    {
-   //     printf("Tracing Data found platform=%d traceversion=%d\n",traceplatform,traceversion);
-        char platformMap[]= "?Xitw";
-        device->SetDeviceOS((traceplatform < 5) ? platformMap[traceplatform] : '?', "EDNS0 Trace");
-        if ((traceplatform == TRACE_PLATFORM_OSX) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_OSX))
-        {
-             device->bOSXWithEDNSField = true;
-        }
-        else if ((traceplatform == TRACE_PLATFORM_iOS) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_iOS))
-        {
-            device->biOSWithEDNSField = true;
-        }
-    }
-
-    for (int dnsItemsIndex =0; dnsItemsIndex < m_Frame.GetQuestionCount()+m_Frame.GetAnswerCount();dnsItemsIndex++)
-    {
-        RecordName = "";
-        ApplRecordName = "";
-        InstanceName = "";
-        //    printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer),0));
-
-        CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
-        if (pDNSRecord == NULL)
-            continue;
-
-        pDNSRecord->GetDnsRecordName(RecordName,0,99);
-        InstanceName = RecordName;
-
-        if (RecordName.Contains("_kerberos."))
-        {
-            RecordName = "_kerberos.";
-        }
-        else
-            pDNSRecord->GetDnsRecordName(RecordName, (pDNSRecord->m_RecType == DNS_TYPE_PTR)?0:1,99);
-
-        if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
-        {
-            if (RecordName.Contains(".ip6.arpa."))
-                RecordName = "*.ip6.arpa.";
-            else if (RecordName.Contains(".arpa."))
-                RecordName = "*.arpa.";
-        }
-        if (pDNSRecord->m_RecType == DNS_TYPE_A)
-            RecordName = "A";
-        if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
-           RecordName = "AAAA";
-        if (pDNSRecord->m_RecType == 255)
-        {
-            if (RecordName.Contains(".ip6.arpa."))
-                RecordName = "ANY *.ip6.arpa.";
-            else if (RecordName.Contains(".arpa."))
-                RecordName = "ANY *.arpa.";
-            else
-                RecordName = "Any";
-        }
-        if (RecordName.Contains("_sub."))
-        {
-            pDNSRecord->GetDnsRecordName(RecordName,2,99); /// skip first label and _sub. label
-        }
-
-        BJ_UINT32 nBytes =  pDNSRecord->m_nNameLength + pDNSRecord->m_nRdataLen;
-
-        m_nTotalBytes += 10 + nBytes;
-
-        if (m_Frame.m_SourceIPAddress.IsIPv4())
-        {
-            UpdateRecord(m_ServicePtrCache,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-            UpdateShortRecordHelper(SERVICE_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-        }
-        else
-        {
-            UpdateRecord(m_ServicePtrCacheIPv6,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-            UpdateShortRecordHelper(SERVICE_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-        }
-
-        // Add application to cache
-        if (RecordName.GetLength() != 0)
-        {
-
-            ApplRecordName = RecordName;
-            StringMapNode* pNode;
-            pNode = m_Service2AppMap.Find(&ApplRecordName);
-            if (pNode && ApplRecordName.GetBuffer() != NULL)
-            {
-                ApplRecordName = pNode->value.GetBuffer();
-                if ( ApplRecordName == "Device-Info")
-                {
-                    // find device record
-                    BJString svrName;
-                    pDNSRecord->GetDnsRecordName(svrName, 0, 1);
-                    StringMapNode *nodeName = SVRtoDeviceName.Find(&svrName);
-
-                    CDeviceNode* pDeviceNode = nodeName ? m_DeviceMap.Find(&nodeName->value) : NULL;
-
-                    if (pDeviceNode)
-                    {
-                        BJString DeviceInfo;
-                        DeviceInfo.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,50));
-                        char osType = '?';
-
-                        for (int i=0; DeviceInfo2DeviceOS[i][0] != 0; i+=2)
-                        {
-                            if (DeviceInfo.Contains(DeviceInfo2DeviceOS[i]))
-                            {
-                                osType = *DeviceInfo2DeviceOS[i+1];
-                                if (pDeviceNode->GetDeviceOS() != *DeviceInfo2DeviceOS[i])
-                                {
-                                    pDeviceNode->SetDeviceOS(osType,"_device-info._tcp.local.");
-                                    pDeviceNode->SetModel(DeviceInfo2DeviceOS[i]);
-                                }
-                                break;
-                            }
-                        }
-
-
-                        if (osType == 'X' ||  (pDeviceNode && pDeviceNode->GetDeviceOS() == 'X'))
-                            ApplRecordName = "Finder";
-                        if (osType == 't' ||  (pDeviceNode && pDeviceNode->GetDeviceOS() == 't'))
-                            ApplRecordName = "AirPlay";
-
-                        if (pDeviceNode && pDeviceNode->GetDeviceOS() == '?' && pDNSRecord->m_nRdataLen > 0)
-                        {
-                            BJString DeviceInfo_temp;
-                            DeviceInfo_temp.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,25));
-                        }
-                    }
-                }
-            }
-            else
-            {
-                ApplRecordName = "Other";
-            }
-
-            if (m_Frame.m_SourceIPAddress.IsIPv4())
-            {
-                UpdateRecord(m_ApplPtrCache,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-                UpdateShortRecordHelper(APP_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-
-            }
-            else
-            {
-                UpdateRecord(m_ApplPtrCacheIPv6,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-                UpdateShortRecordHelper(APP_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
-            }
-
-        }
-
-    }
-}
-
-
-class CSortOptions
-{
-
-public:
-    CStringTree m_SortedCache;
-    int m_nSortCol;
-
-};
-static int CbPrintResults(const void* pNode, const void* pParam)
-{
-    CStringNode* pRecord = (CStringNode*)pNode;
-    CSortOptions* pSortedOption = (CSortOptions*)pParam;
-
-    CStringNode* pNewRecord;
-
-    BJ_UINT64 SortKey =0;
-    switch (pSortedOption->m_nSortCol) {
-        case 0:
-            SortKey = Hash2(pRecord->m_Value); // cheat the sort to the first 8 char
-            break;
-        case 1:
-            SortKey = pRecord->m_nBytes;
-            break;
-        case 2:
-            SortKey = pRecord->m_nFrames;
-            break;
-        case 3:
-            SortKey = pRecord->m_nQuestionFrames;
-            break;
-        case 4:
-            SortKey = pRecord->m_nAnswerFrames;
-            break;
-        default:
-            break;
-    }
-
-
-    pNewRecord = pSortedOption->m_SortedCache.AddRecord(&SortKey);
-
-    if (pNewRecord)
-    {
-        pNewRecord->CopyNode(pRecord);
-
-    }
-
-    return 0;
-}
-
-#if 0 // Not used 
-static int CbPrintUnknownDevice(const void* pNode, const void*)
-{
-    CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
-
-    if (pDeviceRecord->GetDeviceOS() != '?')
-        return 0;
-
-  //  printf("%s %s\n",pDeviceRecord->m_Key.GetBuffer(), pDeviceRecord->macAddress.GetString());
-    return 0;
-
-}
-#endif
-
-static int CbBuildMacMap(const void* pNode, const void* pParam)
-{
-    CDeviceNode* pDeviceNode = (CDeviceNode*)pNode;
-    CMACAddrTree* pMacMap = (CMACAddrTree*)pParam;
-
-
-    BJMACAddr vendorMac;
-    vendorMac.CopyVendor(pDeviceNode->macAddress);
-    if (vendorMac.IsEmpty())
-        return 0;
-
-
-
-    if (pDeviceNode->GetDeviceOS() == '?')
-    {
-        // try to set device type from MAC address
-        CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
-        if (pMacRecord != NULL && pDeviceNode->GetDeviceOS() == '?')
-        {
-            pDeviceNode->SetDeviceOS(pMacRecord->deviceOS, "MAC Mapping");
-//            printf("update device %s %c\n",vendorMac.GetStringVendor(),pMacRecord->deviceOS);
-        }
-
-        if (pDeviceNode->GetDeviceOS() == '?')
-            return 0;
-    }
-
-
-    CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
-    if (pMacRecord == NULL)
-    {
-        pMacRecord = pMacMap->FindwithAddRecord(&vendorMac);
-        pMacRecord->deviceOS = pDeviceNode->GetDeviceOS();
-        pMacRecord->model = pDeviceNode->model;
-        pMacRecord->method = pDeviceNode->settingService;
-    }
-    else
-    {
-        // Check mapping
-  ///      if (pMacRecord && pMacRecord->deviceOS != pDeviceNode->GetDeviceOS())
-   //        printf("Mac Mapping Bad deviceOS %c != %c %s %s %s\n", pMacRecord->deviceOS, pDeviceNode->GetDeviceOS(),pMacRecord->method.GetBuffer(), pDeviceNode->settingService.GetBuffer(),vendorMac.GetStringVendor());
-    //    if (pMacRecord && !(pMacRecord->model == pDeviceNode->model) && pMacRecord->model.GetLength() > 0 && pDeviceNode->model.GetLength() > 0)
-    //        printf("Mac Mapping Bad model %s != %s\n", pMacRecord->model.GetBuffer(), pDeviceNode->model.GetBuffer());
-
-    }
-    return 0;
-
-}
-
-CStringNode* CBonjourTop::GetCurrentDisplayRoot(BJString &sTitle)
-{
-    CStringNode* pRecord = NULL;
-
-    switch(m_CurrentDisplay)
-    {
-        case BJ_DISPLAY_APP:
-            pRecord = m_ApplPtrCache.GetRoot();
-            sTitle = "Application (IPv4)";
-            break;
-        case BJ_DISPLAY_APPv6:
-            pRecord = m_ApplPtrCacheIPv6.GetRoot();
-            sTitle = "Application (IPv6)";
-            break;
-        case BJ_DISPLAY_SERVICE:
-            pRecord = m_ServicePtrCache.GetRoot();
-            sTitle = "Services (IPv4)";
-            break;
-        case BJ_DISPLAY_SERVICEv6:
-            pRecord = m_ServicePtrCacheIPv6.GetRoot();
-            sTitle = "Services (IPv6)";
-            break;
-        case BJ_DISPLAY_24_MIN:
-            printf("Error");
-            break;
-    }
-    return pRecord;
-}
-void CBonjourTop::UpdateOSCounts()
-{
-
-
-    CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
-    if (pDeviceNode)
-    {
-        pDeviceNode->CallBack(&CbBuildMacMap,&m_MacMap);
-        //        pDeviceNode->CallBack(&CbPrintUnknownDevice,NULL);
-    }
-
-
-    // Update Application Caches
-    CStringNode* pCacheRoot = m_ApplPtrCache.GetRoot();
-
-    if (pCacheRoot)
-    {
-        pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
-    }
-    pCacheRoot = m_ApplPtrCacheIPv6.GetRoot();
-
-    if (pCacheRoot)
-    {
-        pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
-    }
-
-    // Update Service caches
-    pCacheRoot = m_ServicePtrCache.GetRoot();
-
-    if (pCacheRoot)
-    {
-        pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
-    }
-    pCacheRoot = m_ServicePtrCacheIPv6.GetRoot();
-
-    if (pCacheRoot)
-    {
-        pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
-    }
-
-
-}
-void CBonjourTop::PrintResults(int nSortCol, bool bSortAsc)
-{
-
-    BJString sTitle;
-    GetCurrentDisplayRoot(sTitle);
-    device_count devCount;
-    BJString sTableTitle;
-
-    UpdateOSCounts();
-
-    /////
-    BJ_UINT64 nRate = 0;
-    BJ_UINT64 nElapsedTime = m_EndTime-m_StartTime;
-    if (nElapsedTime > 0)
-    {
-            nRate = (m_nFrameCount *3600) /nElapsedTime;
-    }
-    if (m_bCursers)
-    {
-        resizeterm(0,0);
-        clear();
-
-        printw("While running the follow keys may be used:\n");
-        printw("[p = sort by Packets (default)], [b = sort by Bytes], [n = sort by Name]\n");
-        printw("[a = Display Application Names (default)], [s = Display Services Names], [t = Display 24 hour packet per min]\n");
-        printw("[o = flip sort order], [e = export to BonjourTop.csv], [q = quit]\n\n");
-
-        printw("Total Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
-        printw("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
-        printw("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
-        printw("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
-        printw("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
-
-        bzero(&devCount, sizeof(devCount));
-        m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
-        printw("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu)\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField, devCount.OSX,devCount.OSXWithEDNSField);
-    }
-    else
-    {
-        printf("\nTotal Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
-        printf("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
-        printf("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
-        printf("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
-
-        bzero(&devCount, sizeof(devCount));
-        m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
-
-        printf("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu), unknown Devices %llu\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField,devCount.OSX,devCount.OSXWithEDNSField,devCount.unknownOS);
-        printf("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
-    }
-    PrintDetailResults(nSortCol, bSortAsc);
-    if (m_bCursers)
-        refresh();
-}
-void CBonjourTop::PrintDetailResults(int nSortCol, bool bSortAsc)
-{
-    BJString sTitle;
-    CStringNode* pCacheRoot = GetCurrentDisplayRoot(sTitle);
-
-    if (m_bCursers)
-    {
-        if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
-        {
-            printw("    ");
-            for(int i=0;i<24;i++)
-                printw("   %02d ",i);
-            printw("\n");
-        }
-        else
-        {
-            printw("\n%s\n",sTitle.GetBuffer());
-            printw("     %- 30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
-            printw("     %- 30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets(  iOS/  OSX)","Packets(  iOS/  OSX)","Packets(  iOS/  OSX)","Devices(  iOS/  OSX)","Devices(  iOS/  OSX)","Devices(  iOS/  OSX)", "QU Bit","Goodbye");
-        }
-    }
-    else
-    {
-        if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
-        {
-
-        }
-        else
-        {
-            printf("\n%s\n",sTitle.GetBuffer());
-            printf("     %-30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
-            printf("     %-30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets(  iOS/  OSX)","Packets(  iOS/  OSX)","Packets(  iOS/  OSX)","Devices(  iOS/  OSX)","Devices(  iOS/  OSX)","Devices(  iOS/  OSX)", "QU Bit","Goodbye");
-        }
-    }
-    if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
-    {
-
-        for(int m=0;m<60;m++)
-        {
-            printw(" %02d ",m);
-            for (int h=0;h<24;h++)
-                printw("%5d ",m_MinSnapshot[h][m].m_nFrameCount);
-            printw("\n");
-        }
-    }
-    else
-    {
-    // sort list
-        CSortOptions SortOptions;
-        SortOptions.m_nSortCol = nSortCol;
-
-        if (pCacheRoot)
-            pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
-
-        if (pCacheRoot)
-            pCacheRoot->CallBack(&CbPrintResults,&SortOptions);
-
-        // print list
-
-        CStringNode* pRecord = SortOptions.m_SortedCache.GetRoot();
-        BJ_UINT32 nIndex = 1;
-
-        if (pRecord)
-            pRecord->Print(m_bCursers,bSortAsc, nIndex,0,40);
-    }
-
-
-}
-
-void CBonjourTop::LiveCapture()
-{
-    /// Live Capture
-    const BJ_UINT16 BonjourPort = 5353;
-    BJSocket Sockv4;
-    BJSocket Sockv6;
-    BJSelect SockSelect;
-
-    Sockv4.CreateListenerIPv4(interfaceName);
-    Sockv6.CreateListenerIPv6(interfaceName);
-
-    SockSelect.Add(Sockv4);
-    SockSelect.Add(Sockv6);
-
-
-    m_StartTime = time(NULL);
-
-    bool bSortAsc = false;
-    int nSortCol = 1;
-
-    while (1)
-    {
-        SockSelect.Add(Sockv4);
-        SockSelect.Add(Sockv6);
-
-        int result = SockSelect.Wait(1);
-        if (result < 0)
-        {
-            // if SockSelect.Wait failed due to an interrupt, then we want to continue processing the packets
-            if (errno == EINTR)
-            {
-                continue;
-            }
-            printf("Error in Select\n");
-            break;
-        }
-
-        if (SockSelect.IsReady(Sockv4))
-        {
-
-            int recvsize = Sockv4.Read();
-
-            if ((recvsize != 0) &&
-                (Sockv4.GetSrcAddr()->GetPortNumber() == BonjourPort))
-            {
-                m_nFrameCount++;
-                m_SocketStatus[Sockv4.IsMulticastPacket()? 0:2].m_nFrameCount++;
-
-                if (!m_IPv4Addr.IsSameSubNet(Sockv4.GetSrcAddr()))
-                {
-                    m_SocketStatus[4].m_nFrameCount++;
-                }
-                m_Frame.m_SourceIPAddress = *Sockv4.GetSrcAddr();
-                ProcessFrame(Sockv4.GetBuffer(),recvsize,Sockv4.m_CurrentFrame.GetTime());
-            }
-        }
-
-        if (SockSelect.IsReady(Sockv6))
-        {
-            int recvsize = Sockv6.Read();
-            if ((recvsize != 0) &&
-                (Sockv6.GetSrcAddr()->GetPortNumber() == BonjourPort))
-            {
-                m_nFrameCount++;
-                m_SocketStatus[Sockv6.IsMulticastPacket()? 1:3].m_nFrameCount++;
-                m_Frame.m_SourceIPAddress = *Sockv6.GetSrcAddr();
-
-                ProcessFrame(Sockv6.GetBuffer(),recvsize,Sockv6.m_CurrentFrame.GetTime());
-            }
-        }
-
-        if (m_bCursers)
-        {
-            int ch = getch();
-            switch (ch)
-            {
-                case 'o':
-                    bSortAsc = !bSortAsc;
-                    result = 0; // force an update
-                    break;
-                case 'n':
-                    nSortCol = 0;
-                    result = 0; // force an update
-                    break;
-                case 'b':
-                    nSortCol = 1;
-                    result = 0; // force an update
-                    break;
-                case 'p':
-                    if (nSortCol == 2)
-                        nSortCol = 3;
-                    else if (nSortCol == 3)
-                        nSortCol = 4;
-                    else
-                        nSortCol = 2;
-                    result = 0; // force an update
-                    break;
-                case 'a':
-                case 'A':
-                    if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_APP)
-                        m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APPv6;
-                    else
-                        m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
-
-                    result = 0;
-                    break;
-                case 's':
-                case 'S':
-                    if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_SERVICE)
-                        m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICEv6;
-                    else
-                        m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
-                    result = 0;
-                    break;
-                case 't':
-                case 'T':
-                   m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_24_MIN;
-                    result = 0;
-                    break;
-                case 'q':
-                    return;
-                case 'e':
-                    ExportResults();
-                    printf("\a");
-                    break;
-                case KEY_RESIZE:
-                    endwin();
-                    initscr();
-                    result = 0; // force an update
-                    break;
-                case KEY_DOWN:
-                    result = 0; // force an update
-                    break;
-            }
-            if (window_size_changed)
-            {
-                endwin();
-                initscr();
-                window_size_changed = false;
-            }
-        }
-        if (m_EndTime != time(NULL) || result == 0)
-        {
-            m_EndTime = time(NULL);
-            PrintResults(nSortCol,bSortAsc);
-            if (m_SnapshotSeconds && (time(NULL) - m_StartTime) > m_SnapshotSeconds)
-            {
-                ExportResults();
-                if (m_bImportExportDeviceMap)
-                {
-                    WriteDeviceFile();
-                    WriteVendorFile();
-                }
-                Reset();
-            }
-        }
-    }
-}
-
-
-
-void CBonjourTop::CaptureFile()
-{
-    CCaptureFile CaptureFile;
-    BJIPAddr* pIPSrcAddr;
-    BJIPAddr* pIPDestAddr;
-
-    CIPAddrMap LocalSubnetIPv6;
-
-
-    CaptureFile.Open(m_pTcpDumpFileName);
-
-    m_StartTime = 0;
-    int nFrameIndex  = 0;
-
-    while (CaptureFile.NextFrame())
-    {
-        nFrameIndex++;
-
-        BJ_UINT8* pBonjourBuffer = (BJ_UINT8*)CaptureFile.m_CurrentFrame.GetBonjourStart();
-        if (!pBonjourBuffer)
-            continue;
-
-        m_nFrameCount++;
-        m_nTotalBytes += CaptureFile.GetWiredLength();
-
-        pIPSrcAddr = CaptureFile.m_CurrentFrame.GetSrcIPAddr();
-        pIPDestAddr = CaptureFile.m_CurrentFrame.GetDestIPAddr();
-        m_Frame.m_SourceIPAddress = *CaptureFile.m_CurrentFrame.GetSrcIPAddr();;
-        m_Frame.m_SourceMACAddress = *CaptureFile.m_CurrentFrame.GetSrcMACAddr();
-
-        if (pIPSrcAddr->IsIPv4())
-        {
-            // check fragment flag
-            BJ_UINT8* pIP = CaptureFile.m_CurrentFrame.GetIPStart();
-            BJ_UINT16 flags = * ((BJ_UINT16*)(pIP+6));
-            if (flags)
-                continue;
-
-            if (!m_IPv4Addr.IsEmptySubnet())
-            {
-                if (m_IPv4Addr.IsSameSubNet(pIPSrcAddr))
-                {
-                    BJ_UINT8* pSourceMac = CaptureFile.m_CurrentFrame.GetEthernetStart()+6;
-                    BJIPAddr IPv6Addr;
-                    IPv6Addr.CreateLinkLocalIPv6(pSourceMac);
-                    LocalSubnetIPv6.FindwithAddRecord(&IPv6Addr);
-
-                }
-                else
-                {
-                    m_SocketStatus[4].m_nFrameCount++;
-
-                    if (!m_Collection.IsValid())
-                        continue;
-                }
-            }
-            m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?0:2].m_nFrameCount++;
-        }
-        if (pIPSrcAddr->IsIPv6())
-        {
-            if (!LocalSubnetIPv6.Find(pIPSrcAddr) && !m_IPv4Addr.IsEmptySubnet())
-            {
-                m_SocketStatus[5].m_nFrameCount++;
-                 if (!m_Collection.IsValid())
-                     continue;
-            }
-            m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?1:3].m_nFrameCount++;
-        }
-
-        ProcessFrame(pBonjourBuffer,CaptureFile.GetBufferLen((pBonjourBuffer)),CaptureFile.m_CurrentFrame.GetTime());
-
-    }
-    m_EndTime = CaptureFile.GetDeltaTime();
-
-    PrintResults(2,false);
-    if ( m_CurrentDisplay ==  BJ_DISPLAY_APP)
-        m_CurrentDisplay =  BJ_DISPLAY_APPv6;
-    else
-        m_CurrentDisplay =  BJ_DISPLAY_SERVICEv6;
-
-    PrintDetailResults(2,false);
-
-}
-
-void CBonjourTop::ExportPtrCache(FILE* hFile, BJString sTitle,CStringNode* pRoot)
-{
-    fprintf(hFile,"%s\n",sTitle.GetBuffer());
-    fprintf(hFile,"Name,Bytes,Total Packets,Total Packets iOS,Total Packets OSX,Question Packets,Question Packets iOS,Question Packets OSX,Answer Packets,Answer Packets iOS,Answer Packets OSX,Asking Devices, Asking Devices iOS,Asking Devices OSX,Answering Devices,Answering Devices iOS,Answering Devices OSX,Total Devices,Total Devices iOS, Total Devices OSX,QU Bit,Goodbye\n");
-
-    if (pRoot)
-        pRoot->Export(hFile);
-}
-
-void CBonjourTop::ExportShortCacheHelper(FILE* hFile, BJString sTitle, CStringShortNode* pRoot)
-{
-    fprintf(hFile,"%s\n",sTitle.GetBuffer());
-    fprintf(hFile,"Name,Bytes,Total Packets,Question Packets,Answer Packets,Asking Devices,Answering Devices,Total Devices,QU Bit,Goodbye\n");
-
-    if (pRoot)
-    {
-        pRoot->Export(hFile);
-    }
-
-}
-
-void CBonjourTop::ExportShortCache(FILE* hFile, BJString sTitle, map<BJString, CStringShortTree*>* myMap)
-{
-    CStringShortTree* cache;
-    BJString versionNumber;
-
-    fprintf(hFile,"%s\n",sTitle.GetBuffer());
-
-    for (map<BJString, CStringShortTree*>::iterator it = myMap->begin(); it != myMap->end(); ++it)
-    {
-        versionNumber = (*it).first;
-        cache = (*it).second;
-
-        ExportShortCacheHelper(hFile, versionNumber, cache->GetRoot());
-    }
-}
-
-void CBonjourTop::ExportResults()
-{
-
-    BJString sTempFileName;
-    device_count devCount;
-    sTempFileName = m_pExportFileName;
-
-    if (m_SnapshotSeconds)
-    {
-        BJString sTimeStamp;
-        sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
-        sTempFileName += "_";
-        sTempFileName += sTimeStamp;
-    }
-    sTempFileName += ".csv";
-
-    if (m_Collection.IsValid())
-    {
-        m_Collection.ExportCollection(sTempFileName);
-        return;
-    }
-
-    FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
-
-    if (hFile == NULL)
-    {
-        printf("file open failed %s\n",m_pExportFileName);
-        return;
-    }
-
-    fprintf(hFile,"Total Number of Frames, %llu\n",m_nFrameCount);
-    fprintf(hFile,"Total Number of Bytes, %llu\n",m_nTotalBytes);
-    fprintf(hFile,"Total Number of Sec, %llu\n",m_EndTime-m_StartTime);
-
-    bzero(&devCount, sizeof(devCount));
-    m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
-    fprintf(hFile,"Total Number of Devices, %llu\n\n",devCount.iOS+devCount.OSX+devCount.unknownOS);
-    fprintf(hFile,"Total Number of iOS Devices, %llu\n",devCount.iOS);
-    fprintf(hFile,"Total Number of iOS Devices (>= iOS7), %llu\n", devCount.iOSWithEDNSField);
-    fprintf(hFile,"Total Number of OSX Devices, %llu\n",devCount.OSX);
-    fprintf(hFile,"Total Number of OSX Devices (>= OSX 10.9), %llu\n",devCount.OSXWithEDNSField);
-
-    fprintf(hFile,"IPv4 multicast, %llu\n",m_SocketStatus[0].m_nFrameCount);
-    fprintf(hFile,"IPv6 multicast, %llu\n",m_SocketStatus[1].m_nFrameCount);
-    fprintf(hFile,"IPv4 Unicast, %llu\n",m_SocketStatus[2].m_nFrameCount);
-    fprintf(hFile,"IPv6 Unicast, %llu\n",m_SocketStatus[3].m_nFrameCount);
-    fprintf(hFile,"IPv4 Wrong subnet, %llu\n",m_SocketStatus[4].m_nFrameCount);
-    fprintf(hFile,"IPv6 Wrong subnet, %llu\n\n",m_SocketStatus[5].m_nFrameCount);
-
-    fprintf(hFile,"QuestionOnly Packets, %llu\n", m_SocketStatus[0].m_nQuestionOnlyFrames);
-    fprintf(hFile,"AnswerOnly Packets, %llu\n", m_SocketStatus[0].m_nAnswerOnlyFrames);
-    fprintf(hFile,"Q&A Packets, %llu\n\n", m_SocketStatus[0].m_nQandAFrames);
-
-    fprintf(hFile,"AnswerCount for truncated frames min, %llu\n", m_MinAnswerCountForTruncatedFrames);
-    fprintf(hFile,"AnswerCount for truncated frames avg, %llu\n", m_AvgAnswerCountForTruncatedFrames);
-    fprintf(hFile,"AnswerCount for truncated frames max, %llu\n\n", m_MaxAnswerCountForTruncatedFrames);
-
-    // Export Cache
-    UpdateOSCounts();
-    ExportPtrCache(hFile,"Application IPv4 Cache",m_ApplPtrCache.GetRoot());
-    ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv4OSX);
-    ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv4iOS);
-
-    ExportPtrCache(hFile,"Application IPv6 Cache",m_ApplPtrCacheIPv6.GetRoot());
-    ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv6OSX);
-    ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv6iOS);
-
-    ExportPtrCache(hFile,"Service IPv4 Cache",m_ServicePtrCache.GetRoot());
-    ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv4OSX);
-    ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv4iOS);
-
-    ExportPtrCache(hFile,"Service IPv6 Cache",m_ServicePtrCacheIPv6.GetRoot());
-    ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv6OSX);
-    ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv6iOS);
-
-    /// min snapshot table
-
-    fprintf(hFile,"Min Snapshot table\n");
-
-    for (int h=0;h<24;h++)
-    {
-        for(int m=0;m<60;m++)
-        {
-            if (m_MinSnapshot[h][m].m_nFrameCount)
-            {
-                fprintf(hFile,"%02d:%02d,%llu\n",h,m,m_MinSnapshot[h][m].m_nFrameCount);
-            }
-        }
-
-    }
-
-    fclose(hFile);
-
-}
-
-void CBonjourTop::WriteDeviceFile()
-{
-    BJString sTempFileName;
-    BJString sTimeStamp;
-
-    sTempFileName = m_DeviceFileName;
-    sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
-    sTempFileName += "_";
-    sTempFileName += sTimeStamp;
-    sTempFileName += ".csv";
-
-    FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
-
-    if (hFile == NULL)
-    {
-        printf("file open failed %s\n",sTempFileName.GetBuffer());
-        return;
-    }
-
-    fprintf(hFile,"\"Name\",\"IPv4Address\",\"IPv6Address\",\"MACAddress\",O,\"Model\",\"Method\",\"total frames\",\"question frames\",\"QU frames\",\"answer frames\"\n");
-
-    CDeviceNode *pDeviceNode = m_DeviceMap.GetRoot();
-
-    if (pDeviceNode)
-        pDeviceNode->Export(hFile);
-
-    fclose(hFile);
-
-    printf("devicemap count %llu %d\n",m_DeviceMap.GetCount(),CDeviceNode::nCreateCount);
-
-}
-
-void CBonjourTop::WriteVendorFile()
-{
-    BJString sTempFileName = "BonjourTopVendor";
-    BJString sTimeStamp;
-
-    sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
-    sTempFileName += "_";
-    sTempFileName += sTimeStamp;
-    sTempFileName += ".csv";
-
-    FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
-
-    if (hFile == NULL)
-    {
-        printf("file open failed %s\n",sTempFileName.GetBuffer());
-        return;
-    }
-    fprintf(hFile,"\"MACAddress\",O,\"Model\",\"Method\"\n");
-
-    CMACAddrNode *node = m_MacMap.GetRoot();
-
-    if (node)
-        node->Export(hFile);
-
-    fclose(hFile);
-}
-
-void CBonjourTop::WindowSizeChanged()
-{
-    window_size_changed = true;
-}
-
-BJ_UINT64 Hash(const char* pStr)
-{
-    // to fix
-    BJ_UINT64 hash = 0;
-    int c;
-
-    while ((c = *pStr++))
-        hash += c;
-
-    return hash;
-
-
-}
-
-BJ_UINT64 Hash2(char* pStr)
-{
-    // to fix
-    BJ_UINT64 hash = 0;
-    int c;
-    int i = 0;
-
-    while ((c = *pStr++) && i++ < 8)
-    {
-        hash = hash << 8;
-        hash |= c;
-    }
-
-    return hash;
-
-
-}
-
-static integer_t Usage(void)
-{
-    task_t targetTask = mach_task_self();
-    struct task_basic_info ti;
-    mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
-
-    kern_return_t kr = task_info(targetTask, TASK_BASIC_INFO_64,
-                                 (task_info_t) &ti, &count);
-    if (kr != KERN_SUCCESS)
-    {
-        printf("Kernel returned error during memory usage query");
-        return 0;
-    }
-
-    // On Mac OS X, the resident_size is in bytes, not pages!
-    // (This differs from the GNU Mach kernel)
-   // return ti.resident_size;
-    return ti.user_time.seconds;
-}
-
-///////////////
-
-
-/* CStringNode */
-
-void CStringNode::UpdateOSTypeCounts(CDeviceMap* pGlobalDeviceMap,CIPAddrMap *pIp2NameMap)
-{
-    if (m_rbLeft)
-        ((CStringNode*)m_rbLeft)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
-    if (m_rbRight)
-        ((CStringNode*)m_rbRight)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
-
-    BJ_UINT64  nDeviceUnknown = 0;
-    m_nDeviceAskingiOSCount = 0;
-    m_nDeviceAskingOSXCount = 0;
-    m_nDeviceAnsweringiOSCount = 0;
-    m_nDeviceAnsweringOSXCount = 0;
-    m_nDeviceTotaliOSCount = 0;
-    m_nDeviceTotalOSXCount = 0;
-    m_DeviceAskingTree.GetDeviceOSTypes(m_DeviceAskingTree.GetRoot(),pIp2NameMap,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,nDeviceUnknown);
-    nDeviceUnknown = 0;
-    m_DeviceAnsweringTree.GetDeviceOSTypes(m_DeviceAnsweringTree.GetRoot(),pIp2NameMap,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,nDeviceUnknown);
-    nDeviceUnknown = 0;
-    m_DeviceTotalTree.GetDeviceOSTypes(m_DeviceTotalTree.GetRoot(), pIp2NameMap, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, nDeviceUnknown);
-}
-
-void CStringNode::Print(bool bCursers,bool bDescendingSort,BJ_UINT32 &nIndex, BJ_UINT32 nStartIndex,BJ_UINT32 nEndIndex)
-{
-    if (bDescendingSort)
-    {
-        if (m_rbLeft)
-            ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
-
-        if (nIndex >= nStartIndex && nIndex <= nEndIndex)
-        {
-            if (bCursers)
-            {
-                printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu)  %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
-
-            }
-            else
-            {
-                printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu)  %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
-
-            }
-        }
-        nIndex++;
-        if (m_rbRight)
-            ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
-    }
-    else
-    {
-        if (m_rbRight)
-            ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
-
-        if (nIndex >= nStartIndex && nIndex <= nEndIndex)
-        {
-            if (bCursers)
-            {
-                printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu)  %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
-            }
-            else
-            {
-                printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu)  %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
-            }
-        }
-        nIndex++;
-        if (m_rbLeft)
-            ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
-    }
-
-}
-void CStringNode::Export(FILE* hFile)
-{
-    fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
-            (char*)&(m_Value),m_nBytes,
-            m_nFrames, m_nFramesiOS, m_nFramesOSX,
-            m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX,
-            m_nAnswerFrames, m_nAnswerFramesiOS, m_nAnswerFramesOSX,
-            m_nDeviceAskingCount, m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,
-            m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,
-            m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount,
-            m_nWakeFrames,m_nGoodbyeFrames);
-
-    if (m_rbLeft)
-        ((CStringNode*)m_rbLeft)->Export(hFile);
-    if (m_rbRight)
-        ((CStringNode*)m_rbRight)->Export(hFile);
-
-}
-
-/* CStringShortNode */
-
-void CStringShortNode::Export(FILE *hFile)
-{
-    fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
-            (char*)&(m_Value),m_nBytes,
-            m_nFrames, m_nQuestionFrames, m_nAnswerFrames,
-            m_nDeviceAskingCount, m_nDeviceAnsweringCount, m_nDeviceTotalCount,
-            m_nWakeFrames,m_nGoodbyeFrames);
-
-
-    if (m_rbLeft)
-    {
-        ((CStringShortNode*)m_rbLeft)->Export(hFile);
-    }
-    if (m_rbRight)
-    {
-        ((CStringShortNode*)m_rbRight)->Export(hFile);
-    }
-}
-
-/* CDeviceMap */
-
-void CDeviceMap::GetDeviceOSTypes(CDeviceNode *node, CDeviceMap *pGlobalDeviceMap, device_count& dev_cnt)
-{
-    if (node == NULL)
-        return;
-
-    GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbLeft),pGlobalDeviceMap, dev_cnt);
-    GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbRight),pGlobalDeviceMap, dev_cnt);
-
-    if (node->bDuplicate || !node->bHasFrames)
-        return;
-
-    char deviceType = '?';
-    if (pGlobalDeviceMap)
-    {
-        CDeviceNode* globalDevice = pGlobalDeviceMap->Find(&node->m_Key);
-        if (globalDevice)
-        {
-            deviceType = globalDevice->GetDeviceOS();
-
-            if (globalDevice->bOSXWithEDNSField && deviceType == 'X')
-            {
-                dev_cnt.OSXWithEDNSField++;
-            }
-            else if (globalDevice->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
-            {
-                dev_cnt.iOSWithEDNSField++;
-            }
-        }
-    }
-    else
-    {
-        deviceType = node->GetDeviceOS();
-        if (node->bOSXWithEDNSField && deviceType == 'X')
-        {
-            dev_cnt.OSXWithEDNSField++;
-        }
-        else if (node->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
-        {
-            dev_cnt.iOSWithEDNSField++;
-        }
-    }
-    switch (deviceType)
-    {
-        case 'i':
-        case 't':
-            dev_cnt.iOS++;
-            break;
-        case 'X':
-            dev_cnt.OSX++;
-            break;
-        default:
-            dev_cnt.unknownOS++;
-            break;
-    }
-}
-
-void CIPAddrMap::GetDeviceOSTypes(CIPDeviceNode* node, CIPAddrMap* pGobalMap, BJ_UINT64& iOS,BJ_UINT64& OSX,BJ_UINT64& unknowOS)
-{
-    if (node == NULL)
-        return;
-
-    GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbLeft),pGobalMap, iOS, OSX, unknowOS);
-    GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbRight),pGobalMap,iOS, OSX, unknowOS);
-
-    char deviceType = '?';
-    if (pGobalMap)
-    {
-        CIPDeviceNode *ipDevice = pGobalMap->Find(&node->m_Key);
-
-        if (ipDevice && ipDevice->pDeviceNode )
-            deviceType = ipDevice->pDeviceNode->GetDeviceOS();
-
-    }
-
-    switch (deviceType)
-    {
-        case 'i':
-        case 't':
-            iOS++;
-            break;
-        case 'X':
-            OSX++;
-            break;
-        default:
-            unknowOS++;
-    }
-
-}
-
-
-///////////
-
diff --git a/mDNSMacOSX/BonjourTop/source/BonjourTop.h b/mDNSMacOSX/BonjourTop/source/BonjourTop.h
deleted file mode 100644
index d915b54..0000000
--- a/mDNSMacOSX/BonjourTop/source/BonjourTop.h
+++ /dev/null
@@ -1,577 +0,0 @@
-//
-//  BonjourTop.h
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#ifndef __TestTB__BonjourTop__
-#define __TestTB__BonjourTop__
-
-#include <iostream>
-#include <stdio.h>
-#include <map>
-#include <utility>
-
-#include "bjtypes.h"
-#include "bjsocket.h"
-#include "LLRBTree.h"
-#include "DNSFrame.h"
-#include "bjStringtoStringMap.h"
-#include "bjstring.h"
-
-#include "CollectBy.h"
-
-using namespace std;
-
-typedef struct device_count {
-    BJ_UINT64 iOS = 0;
-    BJ_UINT64 OSX = 0;
-    BJ_UINT64 unknownOS = 0;
-    BJ_UINT64 OSXWithEDNSField = 0;
-    BJ_UINT64 iOSWithEDNSField = 0;
-} device_count;
-
-class CSocketStats
-{
-public:
-    CSocketStats();
-    void Init();
-    void Clear();
-    BJ_UINT64 m_nFrameCount;
-
-    BJ_UINT64 m_nQuestionOnlyFrames;
-    BJ_UINT64 m_nAnswerOnlyFrames;
-    BJ_UINT64 m_nQandAFrames;
-
-    BJ_INT32 m_SampleDay;
-
-};
-
-class FrameCount
-{
-public:
-    FrameCount() { count = 0;lastFrameNumber = -1;};
-    void Increment(BJ_UINT64 frameNumber)
-    {
-        if (frameNumber != lastFrameNumber)
-            count++;
-        lastFrameNumber = frameNumber;
-
-    };
-    BJ_UINT64 GetValue() const {return count;};
-    void Reset() { count = 0;lastFrameNumber = -1;};
-    FrameCount &operator+=(const FrameCount &src) { count += src.count; return *this;};
-
-private:
-    BJ_UINT64       count;
-    BJ_UINT64       lastFrameNumber;
-};
-
-////////////////
-class CDeviceMap;
-class CDeviceNode;
-
-class CIPDeviceNode : public CRBNode<BJIPAddr>
-{
-public:
-    CIPDeviceNode(BJIPAddr* pSrc) {m_Key = *pSrc; /* temp deviceOS = '?';lastQUFrame = 0;*/pDeviceNode=NULL;};
-    CIPDeviceNode(){ /*deviceOS = '?';lastQUFrame = 0; */pDeviceNode=NULL;};
-    ~CIPDeviceNode(){};
-    inline virtual BJ_COMPARE Compare(BJIPAddr* pKey) {return m_Key.Compare(pKey);};
-    inline virtual void CopyNode(CRBNode* pSrc)
-    {
-        m_Key.Set(((BJIPAddr*)pSrc)->Getin6_addr());
-        pDeviceNode = ((CIPDeviceNode*)pSrc)->pDeviceNode;
-    };
-    void Init() {};
-    void Clear() {};
-
-
-    CDeviceNode* pDeviceNode;
-
-};
-
-class CIPAddrMap: public CLLRBTree<BJIPAddr,CIPDeviceNode>
-{
-public:
-    void GetDeviceOSTypes(CIPDeviceNode* node, CIPAddrMap* pGobalMap, BJ_UINT64& iOS,BJ_UINT64& OSX,BJ_UINT64& unknowOS);
-};
-
-////////////////////
-class CDeviceNode : public CRBNode<BJString>
-{
-public:
-    CDeviceNode(BJString* pSrc) {m_Key = *pSrc; deviceOS = '?'; bOSXWithEDNSField = false; biOSWithEDNSField = false; bDuplicate = false; bIPName = false; bHasFrames = false; nCreateCount++;};
-    CDeviceNode(){deviceOS = '?'; bDuplicate = false; bIPName = false;  bHasFrames = false; nCreateCount++;};
-    ~CDeviceNode(){nCreateCount--;};
-    inline virtual BJ_COMPARE Compare(BJString* pKey) {return m_Key.Compare(*pKey);};
-    inline virtual void CopyNode(CRBNode* pSource)
-    {
-        m_Key = pSource->m_Key;
-        deviceOS = dynamic_cast<CDeviceNode*>(pSource)->deviceOS;
-        model = dynamic_cast<CDeviceNode*>(pSource)->model;
-        settingService = dynamic_cast<CDeviceNode*>(pSource)->settingService;
-        macAddress = dynamic_cast<CDeviceNode*>(pSource)->macAddress;
-        ipAddressv4 = dynamic_cast<CDeviceNode*>(pSource)->ipAddressv4;
-        ipAddressv6 = dynamic_cast<CDeviceNode*>(pSource)->ipAddressv6;
-        bOSXWithEDNSField = dynamic_cast<CDeviceNode*>(pSource)->bOSXWithEDNSField;
-        biOSWithEDNSField = dynamic_cast<CDeviceNode*>(pSource)->biOSWithEDNSField;
-        bHasFrames = dynamic_cast<CDeviceNode*>(pSource)->bHasFrames;
-    };
-    inline virtual void MergeData(CDeviceNode* src)
-    {
-        deviceOS = src->deviceOS;
-        model = src->model;
-        settingService = src->settingService;
-        macAddress = src->macAddress;
-        bOSXWithEDNSField = src->bOSXWithEDNSField;
-        biOSWithEDNSField = src->biOSWithEDNSField;
-
-        frameTotal += src->frameTotal;
-        questionFrame += src->questionFrame;
-        QUFrame += src->QUFrame;
-        answerFrame += src->answerFrame;
-        bHasFrames |=  src->bHasFrames;
-    };
-    void ClearData()
-    {
-        frameTotal.Reset();
-        questionFrame.Reset();
-        QUFrame.Reset();
-        answerFrame.Reset();
-        bHasFrames = false;
-    }
-    void Init() {deviceOS = '?';};
-
-    void Clear() {};
-    char GetDeviceOS() {return deviceOS;};
-    void SetDeviceOS(char t,const char* pSettingService)
-    {
-        BJString EDNS0 = "EDNS0 Trace";
-        if (pSettingService == NULL)
-            printf("SetDeviceOS: pSettingService is NULL\n");
-
-        if (settingService != EDNS0 || EDNS0 == pSettingService)
-        {
-            settingService = pSettingService;;
-            deviceOS = t;
-        }
-   //     if ( t != deviceOS && deviceOS != '?' && (deviceOS != 'b' ))
-    //         printf("SetDeviceOS: %s deviceOS not equal %c by %s != %c by %s\n", m_Key.GetBuffer(),deviceOS,settingService.GetBuffer(),t,pSettingService);
-    };
-    void SetModel(char* pModel) {model = pModel;};
-    void Export(FILE* file)
-    {
-        //  fprintf(hFile,"Name,IPAddress,MACAddress,OSType,Model,Method\n");
-        if (m_rbRight)
-            dynamic_cast<CDeviceNode*>(m_rbRight)->Export(file);
-
-        if (!bDuplicate || frameTotal.GetValue() > 0)
-        {
-            fprintf(file,"\"%s\",\"%s\",\"%s\",\"%s\",%c,\"%s\",\"%s\",%llu,%llu,%llu,%llu\n",
-                m_Key.GetBuffer(),
-                ipAddressv4.GetString(),
-                ipAddressv6.GetString(),
-                macAddress.GetString(),
-                deviceOS,
-                model.GetBuffer()?model.GetBuffer():" ",
-                (bDuplicate)?"dup":settingService.GetBuffer()?settingService.GetBuffer():" ",
-                frameTotal.GetValue(),
-                questionFrame.GetValue(),
-                QUFrame.GetValue(),
-                answerFrame.GetValue());
-        }
-
-        if (m_rbLeft)
-            dynamic_cast<CDeviceNode*>(m_rbLeft)->Export(file);
-    };
-
-    BJMACAddr macAddress;
-    BJIPAddr ipAddressv4;
-    BJIPAddr ipAddressv6;
-    BJString model;
-    BJString settingService;
-    bool     biOSWithEDNSField;
-    bool     bOSXWithEDNSField;
-    bool     bDuplicate;
-    bool     bIPName;
-    bool     bHasFrames;
-
-    FrameCount frameTotal;
-    FrameCount questionFrame;
-    FrameCount QUFrame;
-    FrameCount answerFrame;
-    static int nCreateCount;
-
-private:
-    char deviceOS;
-};
-
-class CDeviceMap: public CLLRBTree<BJString,CDeviceNode>
-{
-public:
-    void GetDeviceOSTypes(CDeviceNode *node, CDeviceMap *pGobalMap, device_count& dev_cnt);
-};
-
-//////////////
-class CMACAddrNode: public CRBNode<BJMACAddr>
-{
-public:
-    CMACAddrNode(BJMACAddr* pSrc) {m_Key.Set(pSrc->Get()); deviceOS = '?'; };
-    CMACAddrNode(){deviceOS = '?';};
-    ~CMACAddrNode(){};
-    inline virtual BJ_COMPARE Compare(BJMACAddr* pKey) {return m_Key.Compare(pKey);};
-    inline virtual void CopyNode(CRBNode* pSource)
-    {
-        m_Key.Set( pSource->m_Key.Get());
-        deviceOS = dynamic_cast<CMACAddrNode*>(pSource)->deviceOS;
-        model = dynamic_cast<CMACAddrNode*>(pSource)->model;
-        method = dynamic_cast<CMACAddrNode*>(pSource)->method;
-    };
-    void Export(FILE* file)
-    {
-        if (m_rbRight)
-            dynamic_cast<CMACAddrNode*>(m_rbRight)->Export(file);
-
-
-        fprintf(file,"\"%s\",%c,\"%s\",\"%s\"\n",
-                m_Key.GetString(),
-                deviceOS,
-                model.GetBuffer()?model.GetBuffer():" ",
-                method.GetBuffer()?method.GetBuffer():" ");
-
-
-        if (m_rbLeft)
-            dynamic_cast<CMACAddrNode*>(m_rbLeft)->Export(file);
-    };
-
-    void Init() {deviceOS = '?';};
-    void Clear(){};
-    char deviceOS;
-    BJString model;
-    BJString method;
-
-};
-
-class CMACAddrTree: public CLLRBTree<BJMACAddr,CMACAddrNode>
-{
-public:
-
-};
-class CMACAddrDeviceNode: public CRBNode<BJMACAddr>
-{
-public:
-    CMACAddrDeviceNode(BJMACAddr* pSrc) {m_Key.Set(pSrc->Get()); device = NULL; };
-    CMACAddrDeviceNode(){device = NULL;};
-    ~CMACAddrDeviceNode(){};
-    inline virtual BJ_COMPARE Compare(BJMACAddr* pKey) {return m_Key.Compare(pKey);};
-    inline virtual void CopyNode(CRBNode* pSource)
-    {
-        m_Key.Set( pSource->m_Key.Get());
-        device = dynamic_cast<CMACAddrDeviceNode*>(pSource)->device;
-    };
-    void Init() {device = NULL;};
-    void Clear(){};
-    CDeviceNode *device;
-
-};
-
-class CMACDeviceMap: public CLLRBTree<BJMACAddr,CMACAddrDeviceNode>
-{
-
-};
-
-/////////////
-
-class CStringNode : public CRBNode<BJ_UINT64>
-{
-public:
-    CStringNode(){Init();};
-    CStringNode ( BJ_UINT64* Key) { Init(); m_Key = *Key;};
-    inline virtual BJ_COMPARE Compare(BJ_UINT64* pKey)
-	{
-
-		if (m_Key < *pKey)
-			return (BJ_GT);
-		else if (m_Key > *pKey)
-			return (BJ_LT);
-		else
-			return (BJ_EQUAL);
-	}
-    inline virtual void CopyNode(CRBNode* pSource)
-	{
-		CStringNode* pSrc = (CStringNode*) pSource;
-
-		//  m_Key = pSrc->m_Key;
-		m_nBytes = pSrc->m_nBytes;
-		m_nFrames = pSrc->m_nFrames;
-		m_nFramesiOS = pSrc->m_nFramesiOS;
-		m_nFramesOSX = pSrc->m_nFramesOSX;
-		m_nQuestionFrames = pSrc->m_nQuestionFrames;
-		m_nQuestionFramesiOS = pSrc->m_nQuestionFramesiOS;
-		m_nQuestionFramesOSX = pSrc->m_nQuestionFramesOSX;
-		m_nAnswerFrames = pSrc->m_nAnswerFrames;
-		m_nAnswerFramesiOS = pSrc->m_nAnswerFramesiOS;
-		m_nAnswerFramesOSX = pSrc->m_nAnswerFramesOSX;
-		strlcpy(m_Value,pSrc->m_Value,sizeof(m_Value));
-		m_nDeviceAskingCount = pSrc->m_nDeviceAskingCount;
-		m_nDeviceAskingiOSCount = pSrc->m_nDeviceAskingiOSCount;
-		m_nDeviceAskingOSXCount = pSrc->m_nDeviceAskingOSXCount;
-		m_nDeviceAnsweringCount = pSrc->m_nDeviceAnsweringCount;
-		m_nDeviceAnsweringiOSCount = pSrc->m_nDeviceAnsweringiOSCount;
-		m_nDeviceAnsweringOSXCount = pSrc->m_nDeviceAnsweringOSXCount;
-		m_nDeviceTotalCount = pSrc->m_nDeviceTotalCount;
-		m_nDeviceTotaliOSCount = pSrc->m_nDeviceTotaliOSCount;
-		m_nDeviceTotalOSXCount = pSrc->m_nDeviceTotalOSXCount;
-		m_nWakeFrames = pSrc->m_nWakeFrames;
-		m_nLastWakeFrameIndex =  pSrc->m_nLastWakeFrameIndex;
-		m_nGoodbyeFrames = pSrc->m_nGoodbyeFrames;
-	}
-
-    inline void Init() {
-        m_nBytes = 0;
-        m_nFrames = m_nFramesiOS = m_nFramesOSX = m_nQuestionFrames = m_nQuestionFramesiOS = m_nQuestionFramesOSX = m_nAnswerFrames = m_nAnswerFramesiOS = m_nAnswerFramesOSX = 0;
-        m_nLastFrameIndex = 0;
-        m_nLastQueryFrameIndex = 0;
-        m_nLastRespondsFrameIndex = 0;
-        m_nDeviceAskingCount = m_nDeviceAskingiOSCount = m_nDeviceAskingOSXCount = 0;
-        m_nDeviceAnsweringCount = m_nDeviceAnsweringiOSCount = m_nDeviceAnsweringOSXCount = 0;
-        m_nDeviceTotalCount = m_nDeviceTotaliOSCount = m_nDeviceTotalOSXCount = 0;
-        m_nWakeFrames = 0;
-        m_nGoodbyeFrames = 0;
-        m_lastQUFrameTime = 0;
-    };
-    inline void Clear() {};
-
-    void UpdateOSTypeCounts(CDeviceMap* pGobalMap,CIPAddrMap *pIp2NameMap);
-
-    void Print(bool bCursers,bool bDescendingSort,BJ_UINT32 &nIndex,BJ_UINT32 nStartIndex,BJ_UINT32 nEndIndex);
-    void Export(FILE* hFile);
-
-    //  BJ_UINT64        m_Key;
-    char            m_Value[255];
-    BJ_UINT64       m_nBytes;
-    BJ_UINT64       m_nFrames;
-    BJ_UINT64       m_nFramesiOS;
-    BJ_UINT64       m_nFramesOSX;
-    BJ_UINT64       m_nQuestionFrames;
-    BJ_UINT64       m_nQuestionFramesiOS;
-    BJ_UINT64       m_nQuestionFramesOSX;
-    BJ_UINT64       m_nAnswerFrames;
-    BJ_UINT64       m_nAnswerFramesiOS;
-    BJ_UINT64       m_nAnswerFramesOSX;
-    BJ_UINT64       m_nLastFrameIndex;
-    BJ_UINT64       m_nLastQueryFrameIndex;
-    BJ_UINT64       m_nLastRespondsFrameIndex;
-    BJ_UINT64       m_nLastWakeFrameIndex;
-    CIPAddrMap      m_DeviceAskingTree;
-    BJ_UINT64       m_nDeviceAskingCount;
-    BJ_UINT64       m_nDeviceAskingiOSCount;
-    BJ_UINT64       m_nDeviceAskingOSXCount;
-    CIPAddrMap      m_DeviceAnsweringTree;
-    BJ_UINT64       m_nDeviceAnsweringCount;
-    BJ_UINT64       m_nDeviceAnsweringiOSCount;
-    BJ_UINT64       m_nDeviceAnsweringOSXCount;
-    CIPAddrMap      m_DeviceTotalTree;
-    BJ_UINT64       m_nDeviceTotalCount;
-    BJ_UINT64       m_nDeviceTotaliOSCount;
-    BJ_UINT64       m_nDeviceTotalOSXCount;
-    BJ_UINT64       m_nWakeFrames;
-    BJ_UINT64       m_lastQUFrameTime;
-    BJ_UINT64       m_nGoodbyeFrames;
-};
-
-class CStringTree: public CLLRBTree<BJ_UINT64,CStringNode>
-{
-public:
-
-};
-
-///////////
-
-class CStringShortNode: public CRBNode<BJ_UINT64>
-{
-public:
-    CStringShortNode(BJ_UINT64* key) {Init(); m_Key = *key;};
-	inline virtual BJ_COMPARE Compare(BJ_UINT64* pKey)
-	{
-
-		if (m_Key < *pKey)
-			return (BJ_GT);
-		else if (m_Key > *pKey)
-			return (BJ_LT);
-		else
-			return (BJ_EQUAL);
-	}
-
-    inline virtual void CopyNode(CRBNode* pSource)
-	{
-		CStringShortNode* pSrc = (CStringShortNode*) pSource;
-
-		//  m_Key = pSrc->m_Key;
-		m_nBytes = pSrc->m_nBytes;
-		m_nFrames = pSrc->m_nFrames;
-		m_nQuestionFrames = pSrc->m_nQuestionFrames;
-		m_nAnswerFrames = pSrc->m_nAnswerFrames;
-		strlcpy(m_Value,pSrc->m_Value,sizeof(m_Value));
-		m_nDeviceAskingCount = pSrc->m_nDeviceAskingCount;
-		m_nDeviceAnsweringCount = pSrc->m_nDeviceAnsweringCount;
-		m_nDeviceTotalCount = pSrc->m_nDeviceTotalCount;
-		m_nWakeFrames = pSrc->m_nWakeFrames;
-		m_nLastWakeFrameIndex =  pSrc->m_nLastWakeFrameIndex;
-		m_nGoodbyeFrames = pSrc->m_nGoodbyeFrames;
-	}
-
-    inline void Init() {
-        m_nBytes = 0;
-        m_nFrames = m_nQuestionFrames = m_nAnswerFrames = 0;
-        m_nLastFrameIndex = m_nLastQueryFrameIndex = m_nLastRespondsFrameIndex = m_nLastWakeFrameIndex = 0;
-        m_nDeviceAskingCount = m_nDeviceAnsweringCount = m_nDeviceTotalCount = 0;
-        m_nWakeFrames = m_lastQUFrameTime = m_nGoodbyeFrames = 0;
-    };
-    inline void Clear(){};
-
-    void Export(FILE* hFile);
-
-    //  BJ_UINT64        m_Key;
-    char            m_Value[255];
-    BJ_UINT64       m_nBytes;
-    BJ_UINT64       m_nFrames;
-    BJ_UINT64       m_nQuestionFrames;
-    BJ_UINT64       m_nAnswerFrames;
-    BJ_UINT64       m_nLastFrameIndex;
-    BJ_UINT64       m_nLastQueryFrameIndex;
-    BJ_UINT64       m_nLastRespondsFrameIndex;
-    BJ_UINT64       m_nLastWakeFrameIndex;
-    CIPAddrMap      m_DeviceAskingTree;
-    BJ_UINT64       m_nDeviceAskingCount;
-    CIPAddrMap      m_DeviceAnsweringTree;
-    BJ_UINT64       m_nDeviceAnsweringCount;
-    CIPAddrMap      m_DeviceTotalTree;
-    BJ_UINT64       m_nDeviceTotalCount;
-    BJ_UINT64       m_nWakeFrames;
-    BJ_UINT64       m_lastQUFrameTime;
-    BJ_UINT64       m_nGoodbyeFrames;
-};
-
-class CStringShortTree: public CLLRBTree<BJ_UINT64, CStringShortNode>
-{
-public:
-};
-
-///////////
-
-
-class CBonjourTop
-{
-public:
-    CBonjourTop();
-
-    void SetIPAddr(const char*);
-    void LiveCapture();
-    void CaptureFile();
-
-    void PrintResults(int nSortCol, bool bSortAsc);
-    void UpdateOSCounts();
-    void PrintDetailResults(int nSortCol, bool bSortAsc);
-    void ExportResults();
-    void Reset();
-
-    void WriteDeviceFile();
-    void WriteVendorFile();
-
-    void ProcessFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime);
-    bool Name2OSType(BJString name,CDeviceNode* device);
-
-    void UpdateRecord(CStringTree &Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
-
-    void UpdateShortRecordHelper(BJ_UINT32 cacheType, BJ_UINT32 tracePlatform, BJ_UINT32 traceVersion, char deviceOS, CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
-
-    void UpdateShortRecord(CStringShortTree* Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
-
-    void GetOSTypeFromQuery(CDNSRecord *pDNSRecord,BJString& ServiceName);
-    void GetOSTypeFromRegistration(CDNSRecord *pDNSRecord,BJString& ServiceName);
-
-    CStringNode* GetCurrentDisplayRoot(BJString &sTitle);
-    void ExportPtrCache(FILE* hFile, BJString sTitle, CStringNode* pRoot);
-    void ExportShortCache(FILE* hFile, BJString sTitle, map<BJString, CStringShortTree*>* myMap);
-    void ExportShortCacheHelper(FILE* hFile, BJString sTitle, CStringShortNode* pRoot);
-
-    void WindowSizeChanged();
-
-    bool m_bCursers;
-    const char* m_pTcpDumpFileName;
-    const char* m_pExportFileName;
-    bool window_size_changed;
-    bool m_bImportExportDeviceMap;
-    BJString m_DeviceFileName;
-
-    CDNSFrame m_Frame;
-
-#define NUM_SOCKET_STATUS   6
-#define HOURS_IN_DAY        24
-#define MINUTES_IN_HOUR     60
-
-    CSocketStats m_SocketStatus[NUM_SOCKET_STATUS];
-
-    CSocketStats m_MinSnapshot[HOURS_IN_DAY][MINUTES_IN_HOUR];
-
-    BJ_UINT64 m_nFrameCount;
-    BJ_UINT64 m_nTotalBytes;
-    long m_StartTime;
-    long m_EndTime;
-    BJ_UINT64 m_MinAnswerCountForTruncatedFrames;
-    BJ_UINT64 m_AvgAnswerCountForTruncatedFrames;
-    BJ_UINT64 m_MaxAnswerCountForTruncatedFrames;
-
-    BJIPAddr m_IPv4Addr;
-
-    BJStringtoStringMap m_Service2AppMap;
-
-    BJStringtoStringMap m_Service2osRegisterMap;
-    BJStringtoStringMap m_Service2osBrowseMap;
-
-    enum BJ_DISPLAY_MODE_ENUM {
-        BJ_DISPLAY_APP,
-        BJ_DISPLAY_APPv6,
-        BJ_DISPLAY_SERVICE,
-        BJ_DISPLAY_SERVICEv6,
-        BJ_DISPLAY_24_MIN
-    } m_CurrentDisplay ;
-
-    BJ_INT32 m_SnapshotSeconds;
-
-    CStringTree m_ServicePtrCache;
-    CStringTree m_ApplPtrCache;
-
-    CStringTree m_ServicePtrCacheIPv6;
-    CStringTree m_ApplPtrCacheIPv6;
-
-    map<BJString, CStringShortTree*> m_ServiceBreakdownIPv4OSX;
-    map<BJString, CStringShortTree*> m_ServiceBreakdownIPv4iOS;
-    map<BJString, CStringShortTree*> m_ServiceBreakdownIPv6OSX;
-    map<BJString, CStringShortTree*> m_ServiceBreakdownIPv6iOS;
-
-    map<BJString, CStringShortTree*> m_AppBreakdownIPv4OSX;
-    map<BJString, CStringShortTree*> m_AppBreakdownIPv4iOS;
-    map<BJString, CStringShortTree*> m_AppBreakdownIPv6OSX;
-    map<BJString, CStringShortTree*> m_AppBreakdownIPv6iOS;
-
-    CDeviceMap m_DeviceMap;
-
-    CMACAddrTree m_MacMap;
-    CIPAddrMap  m_IPtoNameMap;
-    CMACDeviceMap m_MACtoDevice;
-    BJStringtoStringMap SVRtoDeviceName;
-
-    Collection m_Collection;
-
-    BJString interfaceName;
-    BJString filterApplicationName;
-
-
-};
-
-#endif /* defined(__TestTB__BonjourTop__) */
diff --git a/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp b/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp
deleted file mode 100644
index 5dc3349..0000000
--- a/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-//
-//  CaptureFile.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 9/14/12.
-//
-//
-
-#include "CaptureFile.h"
-#include <stdio.h>
-#include <pcap.h>
-#include <sys/types.h>
-
-#define BJ_MAX_PACKET (1024*20)
-
-struct packetheader
-{
-    __uint32_t sec;
-    __uint32_t usec;
-    __uint32_t captureLen;
-    __uint32_t origLen;
-
-};
-
-
-CCaptureFile::CCaptureFile()
-{
-    m_pFileHeader = NULL;
-    m_pFrameData = NULL;
-    m_pFrameHeader = NULL;
-    m_hFile = NULL;
-
-    m_nFirstFrameTime = 0;
-
-    if (!Init())
-        Clear();
-}
-CCaptureFile::~CCaptureFile()
-{
-    Clear();
-}
-
-bool CCaptureFile::Init()
-{
-    m_pFileHeader = new BJ_UINT8[sizeof(pcap_file_header)];
-    m_pFrameHeader = new BJ_UINT8[sizeof(packetheader)];
-    m_pFrameData = new BJ_UINT8[BJ_MAX_PACKET];
-
-    return (m_pFrameHeader && m_pFrameData && m_pFileHeader);
-}
-
-bool CCaptureFile::Clear()
-{
-    delete m_pFileHeader; m_pFileHeader = NULL;
-    delete m_pFrameData; m_pFrameData = NULL;
-    delete m_pFrameHeader; m_pFrameHeader = NULL;
-
-    fclose(m_hFile); m_hFile = NULL;
-    return true;
-}
-
-bool CCaptureFile::Open(const char* pFileName)
-{
-    m_hFile = fopen(pFileName, "r");
-
-    if (!m_hFile)
-    {
-        printf("Failed to open %s\n",pFileName);
-        return false;
-    }
-
-
-    fread(m_pFileHeader, sizeof(pcap_file_header), 1,m_hFile);
-
-   //  pcap_file_header* pHeader = (pcap_file_header*)m_pFileHeader;
-   // int magic = pHeader->magic;
-   // int nType = pHeader->linktype;
-
-    pcap_file_header* pHeader = (pcap_file_header*)m_pFileHeader;
-    m_datalinkType = (Frame::BJ_DATALINKTYPE) pHeader->linktype;
-    m_CurrentFrame.SetDatalinkType(m_datalinkType);
-    return true;
-}
-
-bool CCaptureFile::NextFrame()
-{
-    packetheader* pFrameHeader = NULL;
-
-    if(!m_hFile)
-        return false;
-
-    if (fread(m_pFrameHeader,1,sizeof(packetheader),m_hFile)< sizeof(packetheader))
-        return false;
-
-    pFrameHeader = (packetheader*) m_pFrameHeader;
-
-    m_nWireLen = pFrameHeader->origLen;
-    m_TimeSec = pFrameHeader->sec;
-    if (m_nFirstFrameTime == 0)
-        m_nFirstFrameTime = m_TimeSec;
-    m_nCaptureLen = pFrameHeader->captureLen; // to do handle frames bigger than buffer
-
-    long nSkip = 0;
-    if (m_nCaptureLen >  BJ_MAX_PACKET)
-    {   // force truncate the packet ...
-        nSkip = m_nCaptureLen - BJ_MAX_PACKET;
-        m_nCaptureLen = BJ_MAX_PACKET;
-    }
-
-    if (fread(m_pFrameData,1,m_nCaptureLen,m_hFile) < m_nCaptureLen)
-        return false;
-
-    if (nSkip)
-        fseek(m_hFile, nSkip, SEEK_CUR);
-
-    m_CurrentFrame.Set(m_pFrameData, m_nCaptureLen,pFrameHeader->sec*1000000ll + pFrameHeader->usec);
-
-
-    return true;
-}
-
-bool CCaptureFile::Close()
-{
-
-    return true;
-}
-
-__uint32_t CCaptureFile::GetDeltaTime()
-{
-    return m_TimeSec-m_nFirstFrameTime;
-}
-
-__uint32_t CCaptureFile::GetBufferLen(BJ_UINT8* pStart)
-{
-    return m_nCaptureLen -  (__uint32_t) (pStart - m_pFrameData);
-}
-
-
-
-
-
diff --git a/mDNSMacOSX/BonjourTop/source/CaptureFile.h b/mDNSMacOSX/BonjourTop/source/CaptureFile.h
deleted file mode 100644
index ea625ba..0000000
--- a/mDNSMacOSX/BonjourTop/source/CaptureFile.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-//  CaptureFile.h
-//  TestTB
-//
-//  Created by Terrin Eager on 9/14/12.
-//
-//
-
-#ifndef __TestTB__CaptureFile__
-#define __TestTB__CaptureFile__
-
-#include <iostream>
-#include "bjtypes.h"
-#include "bjsocket.h"
-#include "Frame.h"
-
-class CCaptureFile
-{
-public:
-    CCaptureFile();
-    virtual ~CCaptureFile();
-    bool Open(const char* pFileName);
-    bool NextFrame();
-    bool Close();
-
-    Frame m_CurrentFrame;
-
-
-
-    __uint32_t GetDeltaTime();
-
-    __uint32_t GetBufferLen(BJ_UINT8* pStart);
-
-    __uint32_t GetWiredLength(){ return m_nWireLen;};
-
-
-private:
-    bool Init();
-    bool Clear();
-
-    FILE* m_hFile;
-    BJ_UINT8* m_pFrameHeader;
-    BJ_UINT8* m_pFrameData;
-    BJ_UINT8* m_pFileHeader;
-    __uint32_t  m_nCaptureLen;
-    __uint32_t  m_nWireLen;
-    __uint32_t  m_TimeSec;
-
-    __uint32_t m_nFirstFrameTime;
-
-    Frame::BJ_DATALINKTYPE m_datalinkType;
-
-};
-
-#endif /* defined(__TestTB__CaptureFile__) */
diff --git a/mDNSMacOSX/BonjourTop/source/CollectBy.cpp b/mDNSMacOSX/BonjourTop/source/CollectBy.cpp
deleted file mode 100644
index c42822c..0000000
--- a/mDNSMacOSX/BonjourTop/source/CollectBy.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-//
-//  CollectBy.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 3/17/13.
-//
-//
-
-#include <iostream>
-#include "bjtypes.h"
-#include "DNSFrame.h"
-#include "bjstring.h"
-#include "LLRBTree.h"
-
-#include "CollectBy.h"
-
-
-//////////////////////
-// Collection
-void Collection::Init(BJ_COLLECTBY_TYPE collectByList[])
-{
-    CollectByAbstract* pLastCollectBy = nullptr;
-
-    for (int i=0; i<20 && collectByList[i] != CBT_NOT_SET;i++)
-    {
-        m_CollectByList[i] = collectByList[i];
-        if (i==0)
-        {
-            m_pHeaderCollectBy = Factory(m_CollectByList[i]);
-            pLastCollectBy = m_pHeaderCollectBy;
-            m_pFirstCollectBy = pLastCollectBy->Factory();
-        }
-        else
-        {
-            pLastCollectBy->pNext = Factory(m_CollectByList[i]);
-            pLastCollectBy = pLastCollectBy->pNext;
-        }
-    }
-}
-
-void Collection::ProcessFrame(CDNSFrame* pFrame)
-{
-    m_pFirstCollectBy->Collect(pFrame,m_pHeaderCollectBy->pNext);
-}
-
-void Collection::ExportCollection(BJString sFileName)
-{
-    FILE* hFile = fopen(sFileName.GetBuffer(),"w");
-
-    if (hFile == NULL)
-    {
-        printf("file open failed %s\n",sFileName.GetBuffer());
-        return;
-    }
-
-    // Export Header Line
-    CollectByAbstract *collectBy = m_pHeaderCollectBy;
-    BJString sHeader;
-    while (collectBy)
-    {
-        if (sHeader.GetBufferLength() != 0)
-            sHeader += ",";
-        sHeader += collectBy->GetTitle();
-        collectBy = collectBy->pNext;
-    }
-    fprintf(hFile, "%s\n",sHeader.GetBuffer());
-
-    m_pFirstCollectBy->Export(hFile,"");
-
-    fclose(hFile);
-}
-
-CollectByAbstract* Collection::Factory(BJ_COLLECTBY_TYPE type)
-{
-    switch (type)
-    {
-        case CBT_NOT_SET:
-            return NULL;
-        case CBT_SERVICE:
-            return new CollectByService();
-        case CBT_REQUEST_RESPONDS:
-            return new CollectByRequestResponds();
-        case CBT_SAME_DIFF_SUBNET:
-            return new CollectBySameSubnetDiffSubnet();
-        case CBT_IP_ADDRESS_TYPE:
-            return new CollectByIPAddressType();
-        case CBT_PACKET:
-            return new CollectByPacketCount();
-        default:
-            return NULL;
-    }
-
-}
-
-/////////////
-// CollectByService
-
-void CServiceNode::Export(FILE* hFile,BJString sPrevColumns)
-{
-    if (pNext)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += m_Key;
-        pNext->Export(hFile,sTemp);
-    }
-    if (m_rbLeft)
-     dynamic_cast<CServiceNode*>(m_rbLeft)->Export(hFile,sPrevColumns);
-    if (m_rbRight)
-        dynamic_cast<CServiceNode*>(m_rbRight)->Export(hFile,sPrevColumns);
-}
-
-void CollectByService::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
-{
-    for (int dnsItemsIndex =0; dnsItemsIndex < pFrame->GetQuestionCount()+pFrame->GetAnswerCount();dnsItemsIndex++)
-    {
-        BJString RecordName;
-        CDNSRecord* pDNSRecord = pFrame->GetDnsRecord(dnsItemsIndex);
-        if (pDNSRecord == NULL)
-            continue;
-
-        pDNSRecord->GetDnsRecordName(RecordName,0,99);
-
-        if (RecordName.Contains("_kerberos."))
-        {
-            RecordName = "_kerberos.";
-        }
-        else
-            pDNSRecord->GetDnsRecordName(RecordName, (pDNSRecord->m_RecType == 12)?0:1,99);
-
-        if (pDNSRecord->m_RecType == 12)
-        {
-            if (RecordName.Contains(".ip6.arpa."))
-                RecordName = "*.ip6.arpa.";
-            else if (RecordName.Contains(".arpa."))
-                RecordName = "*.arpa.";
-        }
-        if (pDNSRecord->m_RecType == 1)
-            RecordName = "A";
-        if (pDNSRecord->m_RecType == 28)
-            RecordName = "AAAA";
-        if (pDNSRecord->m_RecType == 255)
-        {
-            if (RecordName.Contains(".ip6.arpa."))
-                RecordName = "ANY *.ip6.arpa.";
-            else if (RecordName.Contains(".arpa."))
-                RecordName = "ANY *.arpa.";
-            else
-                RecordName = "Any";
-        }
-        if (RecordName.Contains("_sub."))
-        {
-            pDNSRecord->GetDnsRecordName(RecordName,2,99); /// skip first label and _sub. label
-        }
-
-
-        CServiceNode *pNode= m_Cache.FindwithAddRecord(&RecordName);
-        if ((pNode->pNext == NULL) && nextCollectBy)
-            pNode->pNext = nextCollectBy->Factory();
-        if (pNode->pNext)
-            pNode->pNext->Collect(pFrame,nextCollectBy?nextCollectBy->pNext:NULL);
-
-    }
-
-}
-
-
-
-
-void CollectByService::Export(FILE* hFile,BJString sPrevColumns)
-{
-
-    // loop thur list
-    CServiceNode *pNode = m_Cache.GetRoot();
-
-    if (pNode)
-        pNode->Export(hFile,sPrevColumns);
-}
-
-/////////////
-//  CollectByRequestResponds
-void CollectByRequestResponds::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
-{
-    if (pFrame->IsQueryFrame())
-    {
-        if (pRequestNext == NULL)
-            pRequestNext = nextCollectBy->Factory();
-        pRequestNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-    else
-    {
-        if (pRespondsNext == NULL)
-            pRespondsNext = nextCollectBy->Factory();
-        pRespondsNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-}
-
-void CollectByRequestResponds::Export(FILE* hFile,BJString sPrevColumns)
-{
-    if (pRequestNext)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "Request";
-        pRequestNext->Export(hFile,sTemp);
-    }
-    if (pRespondsNext)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "Responds";
-        pRespondsNext->Export(hFile,sTemp);
-    }
-}
-/////////////
-//  CollectByIPAddressType
-void CollectByIPAddressType::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
-{
-    if (pFrame->m_SourceIPAddress.IsIPv4())
-    {
-        if (pIPv4Next == NULL)
-            pIPv4Next = nextCollectBy->Factory();
-        pIPv4Next->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-    if (pFrame->m_SourceIPAddress.IsIPv6())
-    {
-        if ((pIPv6Next == NULL) && nextCollectBy)
-            pIPv6Next = nextCollectBy->Factory();
-        if (pIPv6Next)
-            pIPv6Next->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-}
-void CollectByIPAddressType::Export(FILE* hFile,BJString sPrevColumns)
-{
-    if (pIPv4Next)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "IPv4";
-        pIPv4Next->Export(hFile,sTemp);
-    }
-    if (pIPv6Next)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "IPv6";
-        pIPv6Next->Export(hFile,sTemp);
-    }
-}
-/////////////
-// CollectBySameSubnetDiffSubnet:
-
-// static
-bool CollectBySameSubnetDiffSubnet::bSameSubnet = true;
-
-void CollectBySameSubnetDiffSubnet::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
-{
-    if (bSameSubnet)
-    {
-        if (pSameSubnetNext == NULL)
-            pSameSubnetNext = nextCollectBy->Factory();
-        pSameSubnetNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-    else
-    {
-        if (pDiffSubnetNext == NULL)
-            pDiffSubnetNext = nextCollectBy->Factory();
-        pDiffSubnetNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
-    }
-
-}
-void CollectBySameSubnetDiffSubnet::Export(FILE* hFile,BJString sPrevColumns)
-{
-    if (pSameSubnetNext)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "SameSubnet";
-        pSameSubnetNext->Export(hFile,sTemp);
-    }
-    if (pDiffSubnetNext)
-    {
-        BJString sTemp = sPrevColumns;
-        if (sPrevColumns.GetBufferLength())
-            sTemp += ",";
-        sTemp += "WrongSubnet";
-        pDiffSubnetNext->Export(hFile,sTemp);
-    }
-}
-/////////////
-// CollectByPacketCount
-
-// staticCollectByPacketCount
-BJ_INT64 CollectByPacketCount::nFrameIndex = 0;
-
-void CollectByPacketCount::Collect(CDNSFrame* ,CollectByAbstract* )
-{
-    if (nFrameIndex != nLastFrameIndex)
-    {
-        nFrameCount++;
-        nLastFrameIndex = nFrameIndex;
-    }
-}
-void CollectByPacketCount::Export(FILE* hFile,BJString sPrevColumns)
-{
-
-    fprintf(hFile,"%s,%llu\n",sPrevColumns.GetBuffer(),nFrameCount);
-}
-
-
diff --git a/mDNSMacOSX/BonjourTop/source/CollectBy.h b/mDNSMacOSX/BonjourTop/source/CollectBy.h
deleted file mode 100644
index 80ff0d5..0000000
--- a/mDNSMacOSX/BonjourTop/source/CollectBy.h
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-//  CollectBy.h
-//  TestTB
-//
-//  Created by Terrin Eager on 3/17/13.
-//
-//
-
-#ifndef __TestTB__CollectBy__
-#define __TestTB__CollectBy__
-
-#include <iostream>
-#include "bjtypes.h"
-#include "DNSFrame.h"
-#include "bjstring.h"
-#include "LLRBTree.h"
-
-
-// Service request/Respond v4/v6 sameSubnet/DifferentSubnet
-
-enum BJ_COLLECTBY_TYPE
-{
-    CBT_NOT_SET,
-    CBT_SERVICE,
-    CBT_REQUEST_RESPONDS,
-    CBT_SAME_DIFF_SUBNET,
-    CBT_IP_ADDRESS_TYPE,
-    CBT_PACKET
-};
-
-class CollectByAbstract;
-class Collection
-{
-public:
-    Collection() {m_pHeaderCollectBy = NULL;m_pFirstCollectBy = NULL;};
-
-    void Init(BJ_COLLECTBY_TYPE collectByList[]);
-    void ProcessFrame(CDNSFrame* pFrame);
-
-    void ExportCollection(BJString sFileName);
-    bool IsValid() { return (m_pFirstCollectBy != NULL);};
-private:
-    CollectByAbstract* Factory(BJ_COLLECTBY_TYPE type);
-
-    BJ_COLLECTBY_TYPE m_CollectByList[20];
-    CollectByAbstract* m_pHeaderCollectBy;
-    CollectByAbstract* m_pFirstCollectBy;
-
-};
-
-class CollectByAbstract
-{
-public:
-    CollectByAbstract()
-    {
-        pNext = NULL;
-    }
-
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)=0;
-    virtual const char* GetTitle()=0;
-    virtual CollectByAbstract* Factory()=0;
-    virtual void Export(FILE* hFile,BJString sPrevColumns)=0;
-
-    CollectByAbstract* pNext;
-};
-/////////////
-// Service
-class CServiceNode : public CRBNode<BJString>
-{
-public:
-    CServiceNode() {pNext = NULL;};
-    CServiceNode(BJString* pKey){ m_Key = *pKey;};
-    ~CServiceNode(){};
-    inline virtual BJ_COMPARE Compare(BJString* pKey) { return m_Key.Compare(*pKey);};
-    inline virtual void CopyNode(CRBNode* pSource) {pNext = dynamic_cast<CServiceNode*>(pSource)->pNext;} ;
-    inline virtual void Init(){};
-    inline virtual void Clear() {};
-    void Export(FILE* hFile,BJString sPrevColumns);
-    CollectByAbstract* pNext;
-
-};
-
-class CServiceToCollectByMap : public CLLRBTree<BJString, CServiceNode>
-{
-public:
-
-
-};
-
-class CollectByService:public CollectByAbstract
-{
-public:
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
-    virtual const char* GetTitle() {return "Service";};
-    virtual CollectByAbstract* Factory(){ return new CollectByService();};
-    virtual void Export(FILE* hFile,BJString sPrevColumns);
-private:
-    CServiceToCollectByMap m_Cache;
-};
-
-class CollectByRequestResponds:public CollectByAbstract
-{
-public:
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
-    virtual const char* GetTitle() {return "Request/Responds";};
-    virtual CollectByAbstract* Factory(){ return new CollectByRequestResponds();};
-    virtual void Export(FILE* hFile,BJString sPrevColumns);
-
-private:
-    CollectByAbstract* pRequestNext;
-    CollectByAbstract* pRespondsNext;
-};
-
-class CollectByIPAddressType:public CollectByAbstract
-{
-public:
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
-    virtual const char* GetTitle() {return "V4/V6";};
-    virtual CollectByAbstract* Factory(){ return new CollectByIPAddressType();};
-    virtual void Export(FILE* hFile,BJString sPrevColumns);
-private:
-    CollectByAbstract* pIPv4Next;
-    CollectByAbstract* pIPv6Next;
-};
-
-class CollectBySameSubnetDiffSubnet:public CollectByAbstract
-{
-public:
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
-    virtual const char* GetTitle() {return "SameSubnet/DiffSubnet";};
-    virtual CollectByAbstract* Factory(){ return new CollectBySameSubnetDiffSubnet();};
-    virtual void Export(FILE* hFile,BJString sPrevColumns);
-
-    static bool bSameSubnet;
-private:
-    CollectByAbstract* pSameSubnetNext;
-    CollectByAbstract* pDiffSubnetNext;
-};
-
-class CollectByPacketCount:public CollectByAbstract
-{
-
-public:
-    virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
-    virtual const char* GetTitle() {return "Packets";};
-    virtual CollectByAbstract* Factory(){ return new CollectByPacketCount();};
-    virtual void Export(FILE* hFile,BJString sPrevColumns);
-
-    BJ_INT64 nFrameCount;
-    BJ_INT64 nLastFrameIndex;
-    static BJ_INT64 nFrameIndex;
-};
-
-
-#endif /* defined(__TestTB__CollectBy__) */
diff --git a/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp b/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp
deleted file mode 100644
index fc85a83..0000000
--- a/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-//
-//  DNSFrame.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#include "DNSFrame.h"
-
-#define DNS_LABEL_MAX_LENGTH    63
-#define DNS_NAME_MAX_LENGTH     255
-
-void CDNSRecord::GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
-{
-    GetDnsRecordNameFromBuffer(m_pStartofRec, ReturnString, nLabelToSkip, nMaxLabel);
-}
-
-void CDNSRecord::GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
-{
-    BJ_UINT8* pNameBuffer = NULL;
-    int nOffset = 0;
-   // char* pTemp = pReturnBuffer;
-    int nCharCount  = 0;
-    int nSkippedLabels = 0;
-    int nLabelProcessed = 0;
-    ReturnString.Set(NULL,255);
-
-    if (ReturnString.GetBuffer() == NULL)
-        return;
-
-    pNameBuffer = pBuffer;
-    if (pNameBuffer == NULL)
-    {
-        return;
-    }
-
-    while (ReturnString.GetBufferLength() < 1024)
-    {
-        nCharCount = *pNameBuffer++;
-        if (nCharCount == 0)
-            break;
-
-        if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
-        {
-            nOffset = *pNameBuffer++;
-            nOffset |= (nCharCount&(~DNS_NAME_OFFSET_MASK)) << 8;
-            pNameBuffer = m_pDNSFrame->GetBuffer() + nOffset;
-            continue;
-        }
-
-        if (nCharCount > DNS_LABEL_MAX_LENGTH)
-        {
-            printf("label too long %d\n",nCharCount);
-            break;
-        }
-
-        if (ReturnString.GetLength() + nCharCount + 1 > DNS_NAME_MAX_LENGTH) // + 1 is for the '.' added later on
-        {
-            printf("Name exceeded limit allowed for DNS: %d\n", ReturnString.GetLength() + nCharCount + 1);
-            break;
-        }
-
-        if (nLabelToSkip > nSkippedLabels)
-        {
-            nSkippedLabels++;
-            pNameBuffer += nCharCount;
-            continue;
-        }
-        ReturnString.Append((char*)pNameBuffer, nCharCount);
-        pNameBuffer+= nCharCount;
-        nLabelProcessed++;
-
-        if (nLabelProcessed >= nMaxLabel)
-            return;
-
-        ReturnString += ".";
-    }
-}
-
-
-
-
-CDNSFrame::CDNSFrame()
-{
-
-    for(int nIndex=0; nIndex < MAX_DNS_RECORDS_PER_FRAME; nIndex++)
-        m_dnsItems[nIndex].m_pDNSFrame = this;
-
-}
-
-CDNSRecord* CDNSFrame::GetDnsRecord(int nIndex)
-{
-    if (nIndex > m_nMaxItems)
-        return NULL;
-    return &m_dnsItems[nIndex];
-}
-
-bool CDNSFrame::ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime)
-{
-    if (pBuffer == NULL)
-        return false;
-
-    int nIndex = 0;
-
-    m_Servicev4Address.Empty();
-    m_Servicev6Address.Empty();
-
-    m_pStartBuffer = pBuffer;
-    m_nFrameLen = (BJ_UINT32) nLength;
-
-    m_pCurrentBuffer = m_pStartBuffer;
-    m_pEndBuffer = m_pStartBuffer + m_nFrameLen;
-    m_Time = frameTime;
-
-    m_nId = PF_GET_UINT16(m_pStartBuffer,0);
-    m_nFlags = PF_GET_UINT16(m_pStartBuffer,2);
-    m_nQuestionCount = PF_GET_UINT16(m_pStartBuffer,4);
-    m_nAnswersCount = PF_GET_UINT16(m_pStartBuffer,6);
-    m_NSCOUNT = PF_GET_UINT16(m_pStartBuffer,8);
-    m_ARCOUNT = PF_GET_UINT16(m_pStartBuffer,10);
-
-    m_nMaxItems = 0;
-
-
-
-    // printf("FrameNum= %d,nQuestionCount= %d nAnswersCount= %d NSCOUNT= %d ARCOUNT= %d\n",nFrameCount++,m_nQuestionCount, m_nAnswersCount,m_NSCOUNT,  m_ARCOUNT);
-
-    m_pCurrentBuffer = m_pStartBuffer + 12;
-
-
-    for (nIndex =0; nIndex < m_nQuestionCount;nIndex++)
-    {
-        //      printf("FramePosition= %ld  ",m_pCurrentBuffer);
-        ParseDnsRecord(CDNSRecord::Question);
-
-    }
-    for (nIndex =0; nIndex < m_nAnswersCount;nIndex++)
-    {
-        //      printf("FramePosition= %ld  ",m_pCurrentBuffer);
-        ParseDnsRecord(CDNSRecord::Answer);
-    }
-    for (nIndex =0; nIndex < m_NSCOUNT;nIndex++)
-    {
-        //      printf("FramePosition= %ld  ",m_pCurrentBuffer);
-        ParseDnsRecord(CDNSRecord::Answer);
-    }
-    for (nIndex =0; nIndex < m_ARCOUNT;nIndex++)
-    {
-        //      printf("FramePosition= %ld  ",m_pCurrentBuffer);
-        ParseDnsRecord(CDNSRecord::Answer);
-        CDNSRecord* pRecord =  &m_dnsItems[m_nMaxItems-1];
-        if (pRecord->m_RecType == DNS_TYPE_AAAA && m_Servicev6Address.IsEmpty())
-        {
-            m_Servicev6Address.Setv6Raw(pRecord->GetStartofRdata());
-        }
-        if (pRecord->m_RecType == DNS_TYPE_A && m_Servicev4Address.IsEmpty())
-        {
-            m_Servicev4Address.Setv4Raw(pRecord->GetStartofRdata());
-        }
-    }
-    //
-    ///   for (dnsItemsIndex =0; dnsItemsIndex < m_nQuestionCount+m_nAnswersCount;dnsItemsIndex++)
-    ///   {
-    ///       printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer)));
-    //   }
-    return true;
-}
-
-BJ_BOOL CDNSFrame::ParseDnsRecord(CDNSRecord::dnsItemType eItemType)
-{
-    unsigned char nCharCount = 0;
-    BJ_UINT8* pTemp = m_pCurrentBuffer;
-    CDNSRecord* pRecord =  &m_dnsItems[m_nMaxItems++];
-
-    //temp
-    BJ_UINT16 nRdataLen = 0;
-
-    if (pTemp > m_pEndBuffer)
-    {
-        printf("Error in ParseDnsRecord pBuffer > pEndBuffer\n");
-        pRecord->m_pStartofRec = NULL;
-        pRecord->m_nNameLength = 0;
-        return false;
-    }
-
-
-    pRecord->m_pStartofRec = pTemp;
-    pRecord->m_nNameLength = 0;
-    pRecord->m_nRdataLen = 0;
-
-
-    // Skip over Name;
-    while (pTemp < m_pEndBuffer)
-    {
-        nCharCount = *pTemp;
-        pTemp++;
-
-        if (nCharCount == 0)
-            break;
-
-        if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
-        {  // offset string
-            pTemp++;
-            break;
-        }
-
-        if (nCharCount > DNS_LABEL_MAX_LENGTH)
-        {
-            printf("%d. label too long %d\n",m_nMaxItems-1,nCharCount);
-        }
-
-        if (pTemp + nCharCount < m_pEndBuffer)
-            pTemp += nCharCount;
-        else
-            pTemp = m_pEndBuffer;
-    }
-
-    pRecord->m_nNameLength = (BJ_UINT32)(pTemp - pRecord->m_pStartofRec);
-
-    if (eItemType == CDNSRecord::Question)
-    {
-        pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
-        pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
-        pRecord->m_nTTL = PF_GET_UINT16(pTemp,4);
-
-        //   printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,nType,nClass,nTTL,nRdataLen);
-
-        pTemp += 4;
-    }
-    else
-    {
-
-        pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
-        pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
-
-        pRecord->m_nTTL = PF_GET_UINT32(pTemp,4);
-        pRecord->m_nRdataLen = PF_GET_UINT16(pTemp,8);
-        if (nRdataLen > 1024*10)
-        {
-            printf("large Rdata ??");
-        }
-        //    printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,m_dnsItems[ndnsIndex].RecType,nClass,nTTL,m_dnsItems[ndnsIndex].nRdataLen);
-        pTemp += 10 + pRecord->m_nRdataLen;
-    }
-
-    m_pCurrentBuffer = pTemp;
-
-    return true;
-}
-
-BJ_BOOL CDNSFrame::IsQueryFrame()
-{
-    return !(m_nFlags&0x8000);
-}
-
-#define UNICAST_RESPONDS_REQUESTED 0x8000
-BJ_BOOL CDNSFrame::IsWakeFrame()
-{
-
-    for (int i=0; i < m_nQuestionCount; i++)
-    {
-        if (m_dnsItems[i].m_RecType == DNS_TYPE_PTR &&  m_dnsItems[i].m_RecClass & UNICAST_RESPONDS_REQUESTED)
-            return true;
-    }
-
-    return false;
-}
-#define DNS_HEADER_TRUNCATEED 0x0200
-BJ_BOOL  CDNSFrame::IsTruncatedFrame()
-{
-       return (m_nFlags&DNS_HEADER_TRUNCATEED);
-}
-
-
-BJ_BOOL CDNSFrame::HasOnlyService(BJString sName, BJ_INT16 nRecType)
-{
- /*   if (IsQueryFrame())
-    {
-        for (int i=0; i < m_nQuestionCount; i++)
-        {
-            CBJString sRecordName;
-            m_dnsItems[i].GetDnsRecordName(sRecordName, 0);
-            if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
-                return false;
-
-            if (!sRecordName.Contains(sName.GetBuffer()))
-                return false;
-        }
-    }
-    else*/
-    {
-        for (int i=0; i < m_nQuestionCount+m_nAnswersCount; i++)
-        {
-            BJString sRecordName;
-            m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
-            if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
-                return false;
-
-            if (!sRecordName.Contains(sName.GetBuffer()))
-                return false;
-        }
-
-
-    }
-
-
-    return true;
-}
-
-CDNSRecord* CDNSFrame::FindAdditionRecord(BJString& sName,BJ_INT16 nRecType)
-{
-    for (int i = 0; i < m_nMaxItems; i++)
-    {
-        if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
-            continue;
-        BJString sRecordName;
-        m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
-        if (sRecordName == sName)
-            return &m_dnsItems[i];
-    }
-    return NULL;
-}
-
-void CDNSFrame::SetAddress(BJIPAddr *pSourceIPAddress,BJMACAddr *pSourceMACAddress)
-{
-    m_SourceIPAddress = *pSourceIPAddress;
-    m_SourceMACAddress = *pSourceMACAddress;
-
-
-}
-
-
-bool CDNSFrame::GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &)
-{
-    // Find OPT record
-    for (int i = m_nQuestionCount + m_nAnswersCount + m_NSCOUNT; i < m_nMaxItems; i++)
-    {
-        if (m_dnsItems[i].m_RecType == DNS_TYPE_OPT)
-        {
-            BJ_UINT8* rdata = m_dnsItems[i].GetStartofRdata();
-
-            BJ_UINT8* rdataEnd = rdata +  m_dnsItems[i].m_nRdataLen;
-
-            while (rdata < rdataEnd)
-            {
-                BJ_UINT16 type = PF_GET_UINT16(rdata,0);
-                BJ_UINT16 len = PF_GET_UINT16(rdata,2);
-
-                if (type == DNS_EDNS0_TRACE)
-                {
-                    platform = PF_GET_UINT8(rdata,4);
-                    if (len == 3)   // EDNS field of length 3 <rdar://15101783>
-                    {
-                        version = static_cast<BJ_UINT32>(PF_GET_UINT16(rdata,5));
-                    }
-                    else if (len == 5) // EDNS field of length 5 <rdar://15235603>
-                    {
-                        version = static_cast<BJ_UINT32>(PF_GET_UINT32(rdata, 5));
-                    }
-                    else
-                    {
-                        return false;
-                    }
-                    return true;
-                }
-
-
-                rdata += sizeof(BJ_UINT16)*2 + len;
-            }
-
-        }
-    }
-    return false;
-
-}
-
-
-
-
-
diff --git a/mDNSMacOSX/BonjourTop/source/DNSFrame.h b/mDNSMacOSX/BonjourTop/source/DNSFrame.h
deleted file mode 100644
index 8e7ded7..0000000
--- a/mDNSMacOSX/BonjourTop/source/DNSFrame.h
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-//  DNSFrame.h
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#ifndef __TestTB__DNSFrame__
-#define __TestTB__DNSFrame__
-
-#include <iostream>
-#include "bjtypes.h"
-#include "bjstring.h"
-#include "bjIPAddr.h"
-#include "bjMACAddr.h"
-
-#define MAX_DNS_RECORDS_PER_FRAME 500
-
-#define DNS_TYPE_PTR    12
-#define DNS_TYPE_SRV    33
-#define DNS_TYPE_TXT    16
-#define DNS_TYPE_A      1
-#define DNS_TYPE_AAAA   28
-#define DNS_TYPE_OPT    41
-
-#define DNS_EDNS0_TRACE 65001
-
-class CDNSFrame;
-
-
-
-
-class CDNSRecord
-{
-public:
-    typedef enum {Question,Answer,ns,ar} dnsItemType;
-
-    void GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel);
-    void GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel);
-
-    BJ_UINT8* GetStartofRdata() {return m_pStartofRec+m_nNameLength+10;}; // 10 = type(2) +class(2) + ttl(4) + datalen(2)
-    void GetRdata(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
-    {
-        if (m_RecType == DNS_TYPE_SRV)
-            GetDnsRecordNameFromBuffer(GetStartofRdata()+6, ReturnString, nLabelToSkip, nMaxLabel); // 6 = Priority + Weight + Port
-        else
-            GetDnsRecordNameFromBuffer(GetStartofRdata(), ReturnString, nLabelToSkip, nMaxLabel);
-    }
-    dnsItemType m_dnsType;
-    BJ_UINT8*   m_pStartofRec;
-    BJ_UINT32   m_nNameLength;
-    BJ_INT16    m_RecType;
-    BJ_INT16    m_RecClass;
-    BJ_UINT32   m_nTTL;
-    BJ_UINT32   m_nRdataLen;
-
-    CDNSFrame*  m_pDNSFrame;
-};
-
-
-
-class CDNSFrame
-{
-public:
-
-    CDNSFrame();
-    bool ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength,BJ_UINT64 frameTime);
-
-
-    CDNSRecord* GetDnsRecord(int nIndex);
-    CDNSRecord* FindAdditionRecord(BJString& sName, BJ_INT16 nType);
-
-    BJ_UINT16 GetQuestionCount() {return m_nQuestionCount;};
-    BJ_UINT16 GetAnswerCount(){return m_nAnswersCount;};
-    BJ_UINT16 GetMaxRecords(){return m_nMaxItems;};
-    BJ_UINT8* GetBuffer() { return m_pStartBuffer;};
-
-    BJ_BOOL ParseDnsRecord(CDNSRecord::dnsItemType eItemType);
-
-    BJ_BOOL IsQueryFrame();
-    BJ_BOOL IsWakeFrame();
-    BJ_BOOL IsTruncatedFrame();
-
-    BJ_BOOL HasOnlyService(BJString sName, BJ_INT16 nRecType);
-
-    void SetAddress(BJIPAddr *SourceIPAddress,BJMACAddr *SourceMACAddress);
-
-    bool GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &mac);
-
-    BJ_UINT64 GetTime() {return m_Time;};
-
-
-    BJIPAddr m_Servicev4Address;
-    BJIPAddr m_Servicev6Address;
-
-    BJIPAddr   m_SourceIPAddress;
-    BJMACAddr  m_SourceMACAddress;
-
-protected:
-
-
-    BJ_UINT8* m_pStartBuffer;
-    BJ_UINT8* m_pEndBuffer;
-    BJ_UINT8* m_pCurrentBuffer;
-    BJ_INT32  m_nBufferLen;
-
-    BJ_INT32 m_nFrameLen;
-
-    // Header
-    BJ_UINT16 m_nId;
-    BJ_UINT16 m_nFlags;
-
-    BJ_UINT16 m_nQuestionCount;
-    BJ_UINT16 m_nAnswersCount;
-    BJ_UINT16 m_NSCOUNT;
-    BJ_UINT16 m_ARCOUNT;
-
-
-    CDNSRecord m_dnsItems[MAX_DNS_RECORDS_PER_FRAME];
-
-    int m_nMaxItems;
-
-    BJ_UINT64 m_Time;
-
-};
-
-
-
-
-
-#endif /* defined(__TestTB__DNSFrame__) */
diff --git a/mDNSMacOSX/BonjourTop/source/Frame.cpp b/mDNSMacOSX/BonjourTop/source/Frame.cpp
deleted file mode 100644
index bbc1d82..0000000
--- a/mDNSMacOSX/BonjourTop/source/Frame.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-//
-//  Frame.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 1/19/13.
-//
-//
-
-#include "Frame.h"
-
-#define EthernetHeaderStart 14
-
-void Frame::Set(BJ_UINT8* data,BJ_UINT32 len,BJ_UINT64 t)
-{
-    frameData = data;
-    length = len;
-    frameTime = t;
-}
-
-BJ_UINT8* Frame::GetEthernetStart()
-{
-    //todo Support other media types
-    return frameData;
-}
-BJ_UINT8* Frame::GetIPStart()
-{
-    BJ_UINT8* ether = GetEthernetStart();
-
-    return ether + 14;
-
-}
-BJ_UINT8* Frame::GetUDPStart()
-{
-    BJ_UINT8* ip = GetIPStart();
-
-    BJ_UINT16 nSize = *((__uint16_t*) (ip));
-    BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
-    if (nVerison == 0x4)
-    {
-        m_bCurrentFrameIPversion = 4;
-
-        nSize &= 0x0f;
-        nSize *= 4;
-
-
-        BJ_UINT8 nProtocol = *(ip+9);
-
-        if (nProtocol != 17) // Not UDP
-            return NULL;
-    }
-    else if (nVerison == 0x6)
-    {
-        m_bCurrentFrameIPversion = 6;
-        BJ_UINT8 nProtocol = *(ip+6);
-
-        if (nProtocol != 17) // Not UDP
-            return NULL;
-        nSize = 40;
-
-    }
-
-    return ip+nSize;
-}
-
-BJ_UINT8* Frame::GetBonjourStart()
-{
-    BJ_UINT8* udp = GetUDPStart();
-
-
-    if (udp == NULL)
-        return NULL;
-
-    BJ_UINT16 nSourcePort = *((__uint16_t*)(udp));
-    BJ_UINT16 nDestPort = *((__uint16_t*)(udp+2));
-    BJ_UINT16 nBonjourPort  = htons(5353);
-
-    if (nSourcePort == nBonjourPort && nDestPort == nBonjourPort)
-        return (udp+8);
-    else
-        return NULL;
-
-}
-
-
-
-BJIPAddr* Frame::GetSrcIPAddr()
-{
-    BJ_UINT8* ip = GetIPStart();
-
-    BJ_UINT16 nSize = (__uint16_t) (*ip);
-    BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
-    if (nVerison == 0x4)
-    {
-        m_bCurrentFrameIPversion = 4;
-
-        struct in_addr* ipi_addr;
-
-        ipi_addr = (in_addr*)(ip+12);
-
-        sourceIPAddr.Set(ipi_addr);
-
-    }
-    else if (nVerison == 0x6)
-    {
-        m_bCurrentFrameIPversion = 6;
-        BJ_UINT8* ipi_addr;
-
-        ipi_addr = (ip+8);
-
-        sourceIPAddr.Setv6Raw(ipi_addr);
-
-    }
-
-    return &sourceIPAddr;
-}
-
-BJIPAddr* Frame::GetDestIPAddr()
-{
-    BJ_UINT8* ip = GetIPStart();
-
-    BJ_UINT16 nSize = *((__uint16_t*) (ip));
-    BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
-    if (nVerison == 0x4)
-    {
-        m_bCurrentFrameIPversion = 4;
-
-        struct in_addr* ipi_addr;
-
-        ipi_addr = (in_addr*)(ip+16);
-
-        destIPAddr.Set(ipi_addr);
-
-    }
-    else if (nVerison == 0x6)
-    {
-        m_bCurrentFrameIPversion = 6;
-        struct in6_addr* ipi_addr;
-
-        ipi_addr = (in6_addr*)(ip+24);
-
-        destIPAddr.Set(ipi_addr);
-
-    }
-    return &destIPAddr;
-}
-
-BJMACAddr* Frame::GetSrcMACAddr()
-{
-    sourceMACAddr.Set(GetEthernetStart()+6);
-
-    return &sourceMACAddr;
-}
-
-BJMACAddr* Frame::GetDestMACAddr()
-{
-    destMACAddr.Set(GetEthernetStart());
-
-    return &destMACAddr;
-}
-
-void Frame::SetDatalinkType(BJ_DATALINKTYPE datalinkType)
-{
-    m_datalinkType = datalinkType;
-}
-
-BJ_UINT32 Frame::GetLinklayerHeaderLength()
-{
-    switch (m_datalinkType)
-    {
-        case (BJ_DLT_EN10MB):
-            return EthernetHeaderStart;
-        case (BJ_DLT_IEEE802_11):
-            return Get80211HeaderLength();
-        default:
-            // Default to Ethernet
-            return EthernetHeaderStart;
-    }
-}
-
-BJ_UINT32 Frame::Get80211HeaderLength()
-{
-    // XXX: 802.11 header is tricky since it has no "length" field.
-    // We should look at "FrameControl" and derive the length manually for each frame.
-    BJ_UINT16 * frameControl = (BJ_UINT16*)GetEthernetStart();
-
-    // [SubType] [Type - Ver]
-
-    bool isFrameData = (0x0C & *frameControl) == 0x08;
-    bool isQosData   = ((0xF0 & *frameControl) == 0x80) && isFrameData;
-
-    if (isQosData)
-    {
-        //Standard (24) + QoS (2) + LLC (3) + SNAP (5)
-        return 24 + 2 + 3 + 5;
-    }
-    else
-    {
-        //Standard (24) + LLC (3) + SNAP (5)
-        return 24 + 3 + 5;
-    }
-}
diff --git a/mDNSMacOSX/BonjourTop/source/Frame.h b/mDNSMacOSX/BonjourTop/source/Frame.h
deleted file mode 100644
index f8e3ade..0000000
--- a/mDNSMacOSX/BonjourTop/source/Frame.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-//  Frame.h
-//  TestTB
-//
-//  Created by Terrin Eager on 1/19/13.
-//
-//
-
-#ifndef __TestTB__Frame__
-#define __TestTB__Frame__
-
-#include "bjtypes.h"
-#include "bjIPAddr.h"
-#include "bjMACAddr.h"
-
-class Frame
-{
-public:
-    void Set(BJ_UINT8* data,BJ_UINT32 len,BJ_UINT64 t);
-    BJ_UINT8* GetEthernetStart();
-    BJ_UINT8* GetIPStart();
-    BJ_UINT8* GetUDPStart();
-    BJ_UINT8* GetBonjourStart();
-
-    BJIPAddr* GetSrcIPAddr();
-    BJIPAddr* GetDestIPAddr();
-
-    BJMACAddr* GetSrcMACAddr();
-    BJMACAddr* GetDestMACAddr();
-
-    int m_bCurrentFrameIPversion;
-
-    BJ_UINT64 GetTime(){ return frameTime; };
-
-    enum BJ_DATALINKTYPE {
-        BJ_DLT_EN10MB = 1,
-        BJ_DLT_IEEE802_11=105
-    };
-
-    void SetDatalinkType (BJ_DATALINKTYPE datalinkType);
-private:
-
-    BJ_UINT32 GetLinklayerHeaderLength();
-
-    //Get the header length of the current 802.11 frame.
-    BJ_UINT32 Get80211HeaderLength();
-
-    BJ_UINT8* frameData;
-    BJ_UINT32 length;
-
-    BJIPAddr sourceIPAddr;
-    BJIPAddr destIPAddr;
-
-    BJMACAddr sourceMACAddr;
-    BJMACAddr destMACAddr;
-
-    BJ_UINT64 frameTime; // in microseconds
-
-
-    BJ_DATALINKTYPE m_datalinkType = BJ_DLT_EN10MB;
-
-
-};
-
-
-#endif /* defined(__TestTB__Frame__) */
diff --git a/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp b/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp
deleted file mode 100644
index 37ce9d7..0000000
--- a/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-//  LLRBTree.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 7/9/12.
-//
-//
-
-#include "LLRBTree.h"
-
-
-
-#include <stdio.h>
-#import <stdlib.h>
-#include <string.h>
-#include <curses.h>
-
-#include "bjtypes.h"
-
-#include <time.h>
-
-void test3();
-
-
-
-
-
-
-////////////////////
-
-////////////////
-// test case
-// Integrity checks
-
-/*********************
-BJ_BOOL isBST(CRBNode* pRecord, BJ_UINT64 min, BJ_UINT64 max);
-BJ_BOOL is234(CRBNode* pRecord);
-BJ_BOOL isBalanced(CLLRBTree* pCache);
-BJ_BOOL isBalancedNode(CRBNode* pRecord, int black);
-
-BJ_BOOL check(CLLRBTree* pCache)
-{  // Is this tree a red-black tree?
-    BJ_BOOL bBST = isBST(pCache->GetRoot(),pCache->minRecord(pCache->GetRoot())->nKey,pCache->maxRecord(pCache->GetRoot())->nKey);
-    BJ_BOOL b234 = is234(pCache->GetRoot());
-    BJ_BOOL bisBalanced = isBalanced(pCache);
-
-    printf("Bst=%d,234=%d, Balanced=%d",bBST,b234,bisBalanced);
-
-    return bBST && b234 && bisBalanced;
-}
-
-
-BJ_BOOL isBST(CRBNode* pRecord, BJ_UINT64 min, BJ_UINT64 max)
-{  // Are all the values in the BST rooted at x between min and max,
-    // and does the same property hold for both subtrees?
-    if (pRecord == NULL) return 1;
-    if ((pRecord->nKey > min) || (max > pRecord->nKey)) return 0;
-    return isBST(pRecord->m_rbLeft, min, pRecord->nKey) && isBST(pRecord->m_rbRight, pRecord->nKey, max);
-}
-BJ_BOOL is234(CRBNode* pRecord)
-{  // Does the tree have no red right links, and at most two (left)
-    // red links in a row on any path?
-    if (pRecord == NULL) return 1;
-    if (IsRed(pRecord->m_rbRight)) return 0;
-    if (IsRed(pRecord))
-        if (IsRed(pRecord->m_rbLeft))
-            if (IsRed(pRecord->m_rbLeft->m_rbLeft)) return 0;
-    return is234(pRecord->m_rbLeft) && is234(pRecord->m_rbRight);
-}
-
-BJ_BOOL isBalanced(CLLRBTree* pCache)
-{ // Do all paths from root to leaf have same number of black edges?
-    int black = 0;     // number of black links on path from root to min
-    CRBNode* pRecord = pCache->m_Root;
-    while (pRecord != NULL)
-    {
-        if (!IsRed(pRecord)) black++;
-        pRecord = pRecord->m_rbLeft;
-    }
-    return isBalancedNode(pCache->root, black);
-}
-
-BJ_BOOL isBalancedNode(CRBNode* pRecord, int black)
-{ // Does every path from the root to a leaf have the given number
-    // of black links?
-    if      (pRecord == NULL && black == 0) return 1;
-    else if (pRecord == NULL && black != 0) return 0;
-    if (!IsRed(pRecord)) black--;
-    return isBalancedNode(pRecord->m_rbLeft, black) && isBalancedNode(pRecord->m_rbRight, black);
-}
-****************/
-
-/**
-// sample code for testing
-void CStringNode_test()
-{
-    CStringTree Cache;
-
-
-    char DummyData[] = {'a','b','d','x'};
-    BJ_UINT64 i = 0;
-    CStringNode* pRecord;
-
-    while (i++ < sizeof(DummyData))
-    {
-
-        pRecord = (CStringNode*)Cache.FindwithAddRecord(&i);
-        if (pRecord)
-            pRecord->m_Value[0] = DummyData[i];
-    }
-
-    i = 2;
-    pRecord = (CStringNode*)Cache.Find(&i);
-
-
-    test3();
-
-}
-
-void test3()
-{
-    //  float nSaveCPU =0;
-
-    CStringTree Cache;
-
-    CStringNode test;
-
-
-    BJ_UINT64 i = 0;
-    long starttime = clock();
-    float elapsedtime = 0;
-    CStringNode* pRecord;
-
-    // nSaveCPU = getCPUtime();
-    while (i++ < 1000000)
-    {
-        pRecord = (CStringNode*) Cache.FindwithAddRecord(&i);
-        if (pRecord)
-            memccpy(pRecord->m_Value, "test",4, 1);
-
-        // snprintf(pRecord->m_Value,sizeof(pRecord->m_Value),"%llx",key.m_nKey);
-    }
-    elapsedtime = clock() - starttime;
-    elapsedtime /= CLOCKS_PER_SEC;
-
-    // elapsedtime = getCPUtime() - nSaveCPU;
-
-    printf("Test elapsed time %f, check = %d\n",elapsedtime,0);
-
-
-
-
-}
-
-*****/
-///////////////
-
diff --git a/mDNSMacOSX/BonjourTop/source/LLRBTree.h b/mDNSMacOSX/BonjourTop/source/LLRBTree.h
deleted file mode 100644
index 7b7ea0f..0000000
--- a/mDNSMacOSX/BonjourTop/source/LLRBTree.h
+++ /dev/null
@@ -1,460 +0,0 @@
-//
-//  LLRBTree.h
-//  TestTB
-//
-//  Created by Terrin Eager on 7/9/12.
-//
-//  based on rbtree.h but converted to C++
-//  ll from http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf
-
-#ifndef __TestTB__LLRBTree__
-#define __TestTB__LLRBTree__
-
-#include <iostream>
-#include "bjtypes.h"
-#include <sys/socket.h>
-#include "bjstring.h"
-#include "bjIPAddr.h"
-
-template <class KeyType>
-class CRBNode
-{
-public:
-    CRBNode() {m_bIsRed = true; m_rbLeft = m_rbRight = NULL;};
-    virtual ~CRBNode();
-
-    inline virtual BJ_COMPARE Compare(KeyType* pKey) = 0; // Key values are equal
-
-    inline virtual void CopyNode(CRBNode* pSource) = 0;
-    inline virtual void Init()=0;
-    inline virtual void Clear()=0;
-
-    CRBNode* GetMinNode();
-    CRBNode* GetMaxNode();
-
-
-    inline CRBNode* RotateNodeLeft();
-    inline CRBNode* RotateNodeRight();
-
-
-    CRBNode* AddRecord(CRBNode* pNewRecord);
-
-    void FlipColor();
-
-    BJ_UINT64 GetCount();
-
-    CRBNode* Fixup();
-
-    CRBNode* MoveRedLeft();
-    CRBNode* MoveRedRight();
-
-    void  CallBack(int(*callback)(const void*, const void*),void* pParam);
-
-
-    bool  m_bIsRed;
-
-//protected:
-    KeyType  m_Key;
-    CRBNode* m_rbLeft;
-    CRBNode* m_rbRight;
-
-
-};
-
-template <class KeyType, class NodeType>
-class CLLRBTree
-{
-
-public:
-    CLLRBTree();
-    virtual ~CLLRBTree() { if (m_Root) delete m_Root;};
-
-    NodeType* Find(KeyType* pKey);
-
-    NodeType* FindwithAddRecord(KeyType* pKey);
-    NodeType* AddRecord(KeyType* pKey);
-    void RemoveRecord(KeyType* pKey);
-
-    NodeType* GetRoot() { return m_Root;};
-    void ClearAll() { delete m_Root; m_Root = NULL;};
-
-    BJ_UINT64 GetCount();
-
-
-    NodeType* GetMinNode();
-    NodeType* GetMaxNode();
-
-    NodeType* deleteMin(NodeType* pRecord);
-
-
-private:
-    NodeType* RemoveRecord(NodeType* pRecord,KeyType* pKey);
-
-    virtual NodeType* newNode(KeyType* pKey) { return new NodeType(pKey);}
-    virtual void freeNode(NodeType * pNode){ delete pNode;};
-
-
-    NodeType* m_Root;
-
-
-};
-/////////////////
-
-
-template<class KeyType>
-CRBNode<KeyType>::~CRBNode()
-{
-    if (m_rbLeft)
-        delete m_rbLeft;
-    if (m_rbRight)
-        delete m_rbRight;
-
-}
-
-
-
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::RotateNodeLeft()
-{
-    CRBNode<KeyType>* pTemp = m_rbRight;
-    m_rbRight = pTemp->m_rbLeft;
-    pTemp->m_rbLeft = this;
-    pTemp->m_bIsRed = pTemp->m_rbLeft->m_bIsRed;
-    pTemp->m_rbLeft->m_bIsRed = 1;
-
-    return pTemp;
-}
-
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::RotateNodeRight()
-{
-    CRBNode<KeyType>* pTemp = m_rbLeft;
-    m_rbLeft = pTemp->m_rbRight;
-    pTemp->m_rbRight = this;
-    pTemp->m_bIsRed = pTemp->m_rbRight->m_bIsRed;
-    pTemp->m_rbRight->m_bIsRed = 1;
-
-    return pTemp;
-}
-
-template<class KeyType>
-BJ_UINT64 CRBNode<KeyType>::GetCount()
-{
-    BJ_UINT64 Num = 1;
-    if (m_rbLeft)
-        Num += m_rbLeft->GetCount();
-    if (m_rbRight)
-        Num += m_rbRight->GetCount();
-
-    return Num;
-
-}
-
-template<class KeyType>
-void CRBNode<KeyType>::FlipColor()
-{
-    m_bIsRed = !m_bIsRed;
-    if (m_rbLeft)
-        m_rbLeft->m_bIsRed = !m_rbLeft->m_bIsRed;
-    if (m_rbRight)
-        m_rbRight->m_bIsRed = !m_rbRight->m_bIsRed;
-
-}
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::Fixup()
-{
-    // fix the tree balance
-    CRBNode<KeyType>* pNode = this;
-
-    if (m_rbRight && m_rbRight->m_bIsRed) // fix right leaning reds on the way up
-        pNode = RotateNodeLeft();
-
-    if (pNode && pNode->m_rbLeft && pNode->m_rbLeft->m_bIsRed && pNode->m_rbLeft->m_rbLeft && pNode->m_rbLeft->m_rbLeft->m_bIsRed) // fix two reds in a row on the way up
-        pNode = RotateNodeRight();
-
-    if (pNode && pNode->m_rbRight && pNode->m_rbRight->m_bIsRed && pNode->m_rbLeft && pNode->m_rbLeft->m_bIsRed) //split 4-nodes on the way up
-        pNode->FlipColor();
-
-    return pNode;
-}
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::MoveRedLeft()
-{
-    CRBNode* pNode = this;
-    FlipColor();
-
-    if (m_rbRight && m_rbRight->m_rbLeft && m_rbRight->m_rbLeft->m_bIsRed)
-    {
-        m_rbRight = m_rbRight->RotateNodeRight();
-        pNode = RotateNodeLeft();
-        if (pNode)
-            pNode->FlipColor();
-    }
-    return pNode;
-}
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::MoveRedRight()
-{
-    CRBNode* pNode = this;
-    FlipColor();
-
-    if (m_rbLeft && m_rbLeft->m_rbLeft && m_rbLeft->m_rbLeft->m_bIsRed)
-    {
-        pNode = RotateNodeRight();
-        if (pNode)
-            pNode->FlipColor();
-    }
-
-    return pNode;
-}
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::AddRecord(CRBNode* pNewRecord)
-{
-
-    switch (Compare(&pNewRecord->m_Key))
-    {
-        case BJ_GT:
-            if (m_rbRight)
-                m_rbRight = m_rbRight->AddRecord(pNewRecord);
-            else
-                m_rbRight = pNewRecord;
-
-            break;
-        case BJ_LT:
-            if (m_rbLeft)
-                m_rbLeft = m_rbLeft->AddRecord(pNewRecord);
-            else
-                m_rbLeft = pNewRecord;
-
-            break;
-        default: // equal
-            pNewRecord->m_bIsRed = false;
-            pNewRecord->m_rbLeft = m_rbLeft;
-            m_rbLeft = pNewRecord;
-            return this;
-    };
-
-    // fix the tree balance
-    CRBNode* pRecord = this;
-
-    // fix the tree balance
-
-    if (pRecord && pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed) // fix right leaning reds on the way up
-        pRecord = pRecord->RotateNodeLeft();
-
-    if (pRecord && pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed && pRecord->m_rbLeft->m_rbLeft && pRecord->m_rbLeft->m_rbLeft->m_bIsRed) // fix two reds in a row on the way up
-        pRecord = pRecord->RotateNodeRight();
-
-    if (pRecord && pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed && pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed) //split 4-nodes on the way up
-        pRecord->FlipColor();
-
-
-    return pRecord;
-}
-
-
-
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::GetMinNode()
-{
-    CRBNode* pRecord = this;
-    while (pRecord && pRecord->m_rbLeft)
-        pRecord = pRecord->m_rbLeft;
-
-    return pRecord;
-}
-template<class KeyType>
-CRBNode<KeyType>* CRBNode<KeyType>::GetMaxNode()
-{
-    CRBNode* pRecord = this;
-    while (pRecord && pRecord->m_rbRight)
-        pRecord = pRecord->m_rbRight;
-
-    return pRecord;
-}
-
-template<class KeyType>
-void  CRBNode<KeyType>::CallBack(int(*callback)(const void*, const void*),void* pParam)
-{
-
-    if (m_rbLeft)
-        m_rbLeft->CallBack(callback,pParam);
-
-    callback(this,pParam);
-
-    if (m_rbRight)
-        m_rbRight->CallBack(callback,pParam);
-
-
-}
-
-
-
-///////////
-template<class KeyType,class NodeType>
-CLLRBTree<KeyType,NodeType>::CLLRBTree()
-{
-    m_Root = NULL;
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::Find(KeyType* pKey)
-{
-
-    CRBNode<KeyType>* pNode = m_Root;
-
-    while (pNode)
-    {
-        switch (pNode->Compare(pKey))
-        {
-            case BJ_GT:
-                pNode = pNode->m_rbRight;
-                break;
-            case BJ_LT:
-                pNode = pNode->m_rbLeft;
-                break;
-            default:
-                return (NodeType*)pNode;
-                break;
-        }
-    }
-
-    return NULL;
-
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::AddRecord(KeyType* pKey)
-{
-    NodeType* pRecord = newNode(pKey);
-    if (m_Root)
-        m_Root = (NodeType*) m_Root->AddRecord(pRecord);
-    else
-        m_Root = pRecord;
-
-    if (m_Root)
-        m_Root->m_bIsRed = false;
-
-    return pRecord;
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::FindwithAddRecord(KeyType* pKey)
-{
-    NodeType* pRecord = NULL;
-
-    pRecord = Find(pKey);
-
-    if (pRecord == NULL)
-        pRecord = AddRecord(pKey);
-
-    return pRecord;
-}
-
-template<class KeyType,class NodeType>
-void CLLRBTree<KeyType,NodeType>::RemoveRecord(KeyType* pKey)
-{
-    m_Root = RemoveRecord(m_Root,pKey);
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::deleteMin(NodeType* pRecord)
-{
-    if (pRecord->m_rbLeft == NULL)
-    {
-        freeNode(pRecord);
-        return NULL;
-    }
-
-    if (!(pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed)  && !(pRecord->m_rbLeft &&  pRecord->m_rbLeft->m_rbLeft &&pRecord->m_rbLeft->m_rbLeft->m_bIsRed))
-        pRecord = (NodeType*)pRecord->MoveRedLeft();
-
-    pRecord->m_rbLeft = deleteMin((NodeType*)pRecord->m_rbLeft);
-
-    return (NodeType*)pRecord->Fixup();
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::RemoveRecord(NodeType* pRecord,KeyType* pKey)
-{
-    NodeType* pTempRecord = NULL;
-
-    if (pRecord == NULL)
-        return NULL;
-
-    if (pRecord->Compare(pKey) == BJ_LT)
-    {
-        if (!(pRecord->m_rbLeft &&pRecord->m_rbLeft->m_bIsRed)  && !(pRecord->m_rbLeft &&  pRecord->m_rbLeft->m_rbLeft &&pRecord->m_rbLeft->m_rbLeft->m_bIsRed))
-            pRecord->MoveRedLeft();
-        pRecord = RemoveRecord((NodeType*)pRecord->m_rbLeft, pKey);
-    }
-    else
-    {
-        if (pRecord->m_rbLeft &&pRecord->m_rbLeft->m_bIsRed)
-            pRecord->RotateNodeRight();
-
-        if(pRecord->Compare(pKey) == BJ_EQUAL && pRecord->m_rbRight == NULL)
-        {
-            freeNode(pRecord);
-            return NULL;
-        }
-
-        if (!(pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed) && !(pRecord->m_rbRight && pRecord->m_rbRight->m_rbLeft && pRecord->m_rbRight->m_rbLeft->m_bIsRed))
-            pRecord = (NodeType*)pRecord->MoveRedRight();
-
-        if (pRecord->Compare(pKey) == BJ_EQUAL)
-        {
-            pTempRecord = (NodeType*)pRecord->GetMinNode();
-            pRecord->CopyNode(pTempRecord);
-            pRecord->m_rbRight = deleteMin((NodeType*)pRecord->m_rbRight);
-        }
-        else
-        {
-            pRecord->m_rbRight = RemoveRecord((NodeType*)pRecord->m_rbRight, pKey);
-        }
-    }
-    return pRecord?(NodeType*)pRecord->Fixup():NULL;
-}
-
-
-
-
-template<class KeyType,class NodeType>
-BJ_UINT64 CLLRBTree<KeyType,NodeType>::GetCount()
-{
-    if (m_Root)
-        return m_Root->GetCount();
-    else
-        return 0;
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::GetMinNode()
-{
-    if (m_Root)
-        return m_Root->GetMinNode();
-    else
-        return NULL;
-
-}
-
-template<class KeyType,class NodeType>
-NodeType* CLLRBTree<KeyType,NodeType>::GetMaxNode()
-{
-    if (m_Root)
-        return m_Root->GetMaxNode();
-    else
-        return NULL;
-
-}
-
-
-
-
-
-#endif /* defined(__TestTB__LLRBTree__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp b/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp
deleted file mode 100644
index da885c0..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-//
-//  bjIPAddr.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 1/19/13.
-//
-//
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "bjIPAddr.h"
-#include "bjstring.h"
-
-
-//   static
-sockaddr_storage BJIPAddr::emptySockAddrStorage;
-
-
-
-BJIPAddr::BJIPAddr()
-{
-    memset(&emptySockAddrStorage,0,sizeof(emptySockAddrStorage));
-    Empty();
-}
-
-BJIPAddr::BJIPAddr(const BJIPAddr& src)
-{
-    *this = src;
-}
-
-BJIPAddr &BJIPAddr::operator=(const BJIPAddr& src)
-{
-    memcpy(&sockAddrStorage,&src.sockAddrStorage,sizeof(sockAddrStorage));
-    IPv4SubNet = src.IPv4SubNet;
-    return *this;
-}
-
-void BJIPAddr::Empty()
-{
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    IPv4SubNet = 0;
-
-}
-
-bool BJIPAddr::IsBonjourMulticast()
-{
-    bool bResult = false;
-
-    struct in_addr  BonjourMulicastAddrIPv4= {0xFB0000E0};
-
-    struct in6_addr BonjourMulicastAddrIPv6 = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
-
-
-    if (sockAddrStorage.ss_family == AF_INET)
-    {
-        struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
-        return (pAddrIn->sin_addr.s_addr == BonjourMulicastAddrIPv4.s_addr);
-    }
-
-    if (sockAddrStorage.ss_family == AF_INET6)
-    {
-        struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-        return (memcmp(&pAddrIn->sin6_addr,&BonjourMulicastAddrIPv6,sizeof(in6_addr)) == 0);
-    }
-
-
-    return bResult;
-
-}
-
-bool BJIPAddr::IsSameSubNet(BJIPAddr* pCheckAddr)
-{
-
-    if (IPv4SubNet == 0)
-        return true;
-
-    if (!pCheckAddr->IsIPv4())
-        return true;
-
-    in_addr_t Mask = 0xFFFFFFFF;
-
-    Mask = Mask << (32-IPv4SubNet);
-
-    endian_swap(Mask);
-
-    struct sockaddr_in* pMyAddrIn = (sockaddr_in*) &sockAddrStorage;
-    in_addr_t myNetworkAddress = pMyAddrIn->sin_addr.s_addr & Mask;
-
-    struct sockaddr_in* pCheckAddrIn = (sockaddr_in*) pCheckAddr->GetRawValue();
-    in_addr_t CheckNetworkAddress = pCheckAddrIn->sin_addr.s_addr & Mask;
-
-
-    return (myNetworkAddress == CheckNetworkAddress);
-}
-
-
-bool BJIPAddr::IsIPv4()
-{
-    return (sockAddrStorage.ss_family == AF_INET);
-}
-
-bool BJIPAddr::IsIPv6()
-{
-    return (sockAddrStorage.ss_family == AF_INET6);
-}
-
-bool BJIPAddr::IsIPv6LinkLocal()
-{
-     struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-    return (pAddrIn->sin6_addr.__u6_addr.__u6_addr8[0] == 0xfe &&
-            pAddrIn->sin6_addr.__u6_addr.__u6_addr8[1] == 0x80);
-}
-bool BJIPAddr::IsEmpty()
-{
-    return (memcmp(&sockAddrStorage,&emptySockAddrStorage,sizeof(sockAddrStorage)) == 0);
-}
-
-bool BJIPAddr::IsEmptySubnet()
-{
-    return (IPv4SubNet == 0);
-}
-
-void BJIPAddr::Setv6(const char* pIPaddr)
-{
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-
-    if (inet_pton(AF_INET6, pIPaddr, &pAddrIn->sin6_addr) && memcmp(&sockAddrStorage,&emptySockAddrStorage,sizeof(sockAddrStorage)) == 0)
-            pAddrIn->sin6_family = AF_INET6;
-}
-
-void BJIPAddr::Set(const char* pIPaddr)
-{
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-
-    if (pIPaddr == NULL || strlen(pIPaddr) == 0)
-        return;
-
-    BJString sIPAddr;
-    BJString sMask;
-
-    const char* pSeperator = strstr(pIPaddr,"/");
-    if (pSeperator)
-    {
-        sIPAddr.Set(pIPaddr, (BJ_UINT32)(pSeperator - pIPaddr));
-        sMask.Set(pSeperator+1);
-    }
-    else
-    {
-        sIPAddr.Set(pIPaddr);
-    }
-
-    struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
-    pAddrIn->sin_family = AF_INET;
-    pAddrIn->sin_addr.s_addr = inet_addr(sIPAddr.GetBuffer());
-
-    IPv4SubNet = sMask.GetUINT32();
-
-}
-void BJIPAddr::Setv4Raw(BJ_UINT8* ipi4_addr)
-{
-
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
-    pAddrIn->sin_family = AF_INET;
-    memcpy(&pAddrIn->sin_addr, ipi4_addr, sizeof(pAddrIn->sin_addr));
-
-}
-void BJIPAddr::Setv6Raw(BJ_UINT8* ipi6_addr)
-{
-
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-
-    pAddrIn->sin6_family = AF_INET6;
-    memcpy(&pAddrIn->sin6_addr, ipi6_addr, sizeof(pAddrIn->sin6_addr));
-}
-
-void BJIPAddr::Set(struct in6_addr* ipi6_addr)
-{
-
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-
-    pAddrIn->sin6_family = AF_INET6;
-    memcpy(&pAddrIn->sin6_addr, ipi6_addr, sizeof(pAddrIn->sin6_addr));
-}
-
-void BJIPAddr::Set(struct in_addr* ip_addr)
-{
-
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
-    pAddrIn->sin_family = AF_INET;
-    pAddrIn->sin_addr = *ip_addr;
-}
-
-void BJIPAddr::Set(struct sockaddr_storage* pStorage)
-{
-    memcpy(&sockAddrStorage,pStorage,sizeof(sockAddrStorage));
-}
-
-sockaddr_storage* BJIPAddr::GetRawValue()
-{
-    return &sockAddrStorage;
-}
-
-struct in6_addr* BJIPAddr::Getin6_addr()
-{
-    struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-    return &pAddrIn->sin6_addr;
-}
-
-BJ_UINT16 BJIPAddr::GetPortNumber()
-{
-    BJ_UINT16 port = 0;
-    if (sockAddrStorage.ss_family == AF_INET)
-    {
-        struct sockaddr_in* pAddrIn = (struct sockaddr_in*)&sockAddrStorage;
-        port = ntohs(pAddrIn->sin_port);
-    }
-    else if (sockAddrStorage.ss_family == AF_INET6)
-    {
-        struct sockaddr_in6* pAddrIn = (struct sockaddr_in6*)&sockAddrStorage;
-        port = ntohs(pAddrIn->sin6_port);
-    }
-    return port;
-}
-
-BJ_COMPARE BJIPAddr::Compare(BJIPAddr* pIPAddr)
-{
-    if (sockAddrStorage.ss_family > pIPAddr->sockAddrStorage.ss_family)
-        return BJ_GT;
-    if (sockAddrStorage.ss_family < pIPAddr->sockAddrStorage.ss_family)
-        return BJ_LT;
-
-    if (sockAddrStorage.ss_family == AF_INET)
-    {
-        struct sockaddr_in* pMyAddrIn = (sockaddr_in*) &sockAddrStorage;
-        struct sockaddr_in* pAddrIn = (sockaddr_in*) &pIPAddr->sockAddrStorage;
-        if (pMyAddrIn->sin_addr.s_addr > pAddrIn->sin_addr.s_addr)
-            return BJ_GT;
-        if (pMyAddrIn->sin_addr.s_addr < pAddrIn->sin_addr.s_addr)
-            return BJ_LT;
-        return BJ_EQUAL;
-
-    }
-    else
-    {
-        struct sockaddr_in6* pMyAddrIn = (sockaddr_in6*) &sockAddrStorage;
-        struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &pIPAddr->sockAddrStorage;
-
-        int result = memcmp(&pMyAddrIn->sin6_addr, &pAddrIn->sin6_addr, sizeof(sockaddr_in6));
-
-        if (result > 0)
-            return BJ_GT;
-        if (result < 0)
-            return BJ_LT;
-        return BJ_EQUAL;
-    }
-
-
-}
-
-/*
-
- take the mac address: for example 52:74:f2:b1:a8:7f
- throw ff:fe in the middle: 52:74:f2:ff:fe:b1:a8:7f
- reformat to IPv6 notation 5274:f2ff:feb1:a87f
- convert the first octet from hexadecimal to binary: 52 -> 01010010
- invert the bit at position 6 (counting from 0): 01010010 -> 01010000
- convert octet back to hexadecimal: 01010000 -> 50
- replace first octet with newly calculated one: 5074:f2ff:feb1:a87f
- prepend the link-local prefix: fe80::5074:f2ff:feb1:a87f
- */
-
-void BJIPAddr::CreateLinkLocalIPv6(BJ_UINT8* pmac)
-{
-    memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
-    struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-
-    pAddrIn->sin6_family = AF_INET6;
-
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[0] = 0xfe;
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[1] = 0x80;
-
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[8] = *pmac;
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[8] ^= 1 << 1; // invert 6 bit
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[9] = *(pmac+1);
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[10] = *(pmac+2);
-
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[11] = 0xff;
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[12] = 0xfe;
-
-
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[13] = *(pmac+3);
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[14] = *(pmac+4);
-    pAddrIn->sin6_addr.__u6_addr.__u6_addr8[15] = *(pmac+5);
-
-
-}
-
-char* BJIPAddr::GetString()
-{
-    memset(stringbuffer,0,sizeof(stringbuffer));
-    if (IsIPv6())
-    {
-        struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
-        inet_ntop(AF_INET6, &pAddrIn->sin6_addr, stringbuffer, sizeof(stringbuffer));
-    }
-    else
-    {
-        struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
-        inet_ntop(AF_INET, &pAddrIn->sin_addr, stringbuffer, sizeof(stringbuffer));
-    }
-    return stringbuffer;
-}
-
diff --git a/mDNSMacOSX/BonjourTop/source/bjIPAddr.h b/mDNSMacOSX/BonjourTop/source/bjIPAddr.h
deleted file mode 100644
index 8a14473..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjIPAddr.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-//  bjIPAddr.h
-//  TestTB
-//
-//  Created by Terrin Eager on 1/19/13.
-//
-//
-
-#ifndef __TestTB__bjIPAddr__
-#define __TestTB__bjIPAddr__
-
-#include <iostream>
-#include <sys/socket.h>
-#include "bjtypes.h"
-
-class BJIPAddr
-{
-public:
-    BJIPAddr();
-    BJIPAddr(const BJIPAddr& src);
-    BJIPAddr &operator=(const BJIPAddr& src);
-
-    void Empty();
-
-    bool IsBonjourMulticast();
-    bool IsSameSubNet(BJIPAddr* addr);
-
-    bool IsIPv4();
-    bool IsIPv6();
-    bool IsIPv6LinkLocal();
-    bool IsEmpty();
-    bool IsEmptySubnet();
-
-    void Set(const char* addr);
-    void Setv6(const char* addr);
-    void Set(struct in6_addr* ipi6_addr);
-    void Set(struct in_addr* ip_addr);
-    void Set(struct sockaddr_storage* sockStorage);
-    void Setv4Raw(BJ_UINT8* ipi4_addr);
-    void Setv6Raw(BJ_UINT8* ipi6_addr);
-
-    sockaddr_storage* GetRawValue();
-    struct in6_addr* Getin6_addr();
-
-    void CreateLinkLocalIPv6(BJ_UINT8* mac);
-    BJ_COMPARE Compare(BJIPAddr* addr);
-    BJ_UINT16 GetPortNumber();
-    char* GetString();
-private:
-    sockaddr_storage sockAddrStorage;
-    BJ_INT32 IPv4SubNet;
-    char stringbuffer[100];
-    static sockaddr_storage emptySockAddrStorage;
-};
-
-
-#endif /* defined(__TestTB__bjIPAddr__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp b/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp
deleted file mode 100644
index 78d2a8d..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-//  bjMACAddr.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 3/23/13.
-//
-//
-
-
-#include "bjMACAddr.h"
-
diff --git a/mDNSMacOSX/BonjourTop/source/bjMACAddr.h b/mDNSMacOSX/BonjourTop/source/bjMACAddr.h
deleted file mode 100644
index ced9550..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjMACAddr.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-//  bjMACAddr.h
-//  TestTB
-//
-//  Created by Terrin Eager on 3/23/13.
-//
-//
-
-#ifndef __TestTB__bjMACAddr__
-#define __TestTB__bjMACAddr__
-
-#include <iostream>
-#include <sys/socket.h>
-#include "bjtypes.h"
-
-class BJMACAddr
-{
-public:
-    BJMACAddr() { memset(addr,0,sizeof(addr));};
-    BJMACAddr(const BJMACAddr& Src) { memcpy(addr,Src.addr,sizeof(addr)); };
-
-    void operator=(const BJMACAddr& Src) { memcpy(addr,Src.addr,sizeof(addr)); };
-
-    void Set(unsigned char* newAddr) {memcpy(addr,newAddr,sizeof(addr));};
-    void SetString(char* newAddrString)
-    {
-        int newAddr[6] = {0,0,0,0,0,0};
-        sscanf(newAddrString, "%02X:%02X:%02X:%02X:%02X:%02X", &newAddr[0],&newAddr[1],&newAddr[2],&newAddr[3],&newAddr[4],&newAddr[5]);
-        for (int i=0; i< 6; i++)
-            addr[i] = newAddr[i];
-    };
-    unsigned char* Get() {return addr;};
-
-    void CopyVendor(BJMACAddr& src) { memset(addr,0,sizeof(addr)); memcpy(addr,src.addr,4);}; // 3 is standar vendor But 4 is better with apple products
-
-    char* GetString() {sprintf(buffer,"%02X:%02X:%02X:%02X:%02X:%02X", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); return buffer;};
-    char* GetStringVendor() {sprintf(buffer,"%02X:%02X:%02X", addr[0],addr[1],addr[2]); return buffer;};
-    BJ_COMPARE Compare(BJMACAddr* compareAddr)
-    {
-        int result = memcmp(addr, compareAddr->addr, sizeof(addr));
-        if (result > 0)
-            return BJ_GT;
-        if (result < 0)
-            return BJ_LT;
-        return BJ_EQUAL;
-    };
-    bool IsEmpty() { return (addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0;};
-
-private:
-    unsigned char addr[6];
-    char buffer[25];
-};
-
-#endif /* defined(__TestTB__bjMACAddr__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp b/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp
deleted file mode 100644
index 3c5db73..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-//  bjStringtoStringMap.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 12/21/12.
-//
-//
-
-#include "bjStringtoStringMap.h"
-
-/////////////////////
-
-StringMapNode::StringMapNode()
-{
-
-
-}
-
-StringMapNode::StringMapNode(BJString* pKey)
-{
-    m_Key = *pKey;
-}
-
-StringMapNode::~StringMapNode()
-{
-
-}
-
-void StringMapNode::CopyNode(CRBNode* pSource)
-{
-    m_Key = ((StringMapNode*)pSource)->m_Key;
-}
-
-BJ_COMPARE StringMapNode::Compare(BJString* pKey)
-{
-
-    return m_Key.Compare(*pKey);
-
-}
-
diff --git a/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h b/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h
deleted file mode 100644
index 4e44d9d..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-//  bjStringtoStringMap.h
-//  TestTB
-//
-//  Created by Terrin Eager on 12/21/12.
-//
-//
-
-#ifndef __TestTB__bjStringtoStringMap__
-#define __TestTB__bjStringtoStringMap__
-
-#include <iostream>
-#include "bjstring.h"
-#include "LLRBTree.h"
-
-class StringMapNode : public CRBNode<BJString>
-{
-public:
-    StringMapNode();
-    StringMapNode(BJString* pKey);
-    ~StringMapNode();
-    inline virtual BJ_COMPARE Compare(BJString* pKey);
-    inline virtual void CopyNode(CRBNode* pSource);
-    inline virtual void Init(){};
-    inline virtual void Clear() {};
-
-
-    BJString value;
-
-};
-
-class BJStringtoStringMap : public CLLRBTree<BJString, StringMapNode>
-{
-public:
-
-
-};
-
-
-
-
-#endif /* defined(__TestTB__bjStringtoStringMap__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjsocket.cpp b/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
deleted file mode 100644
index da3ce4a..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-//
-//  bjsocket.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 10/24/12.
-//
-//
-#define __APPLE_USE_RFC_2292
-
-#include <unistd.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-
-#include "bjsocket.h"
-#include "bjstring.h"
-
-
-////////////////////////////
-/// BJSocket
-///////////////////////////
-const BJ_UINT16 BonjourPort = 5353;
-
-BJSocket::BJSocket()
-{
-    socketHandle = 0;
-    buffer = NULL;
-    IPVersion = 0;
-    interfaceID = 0;
-}
-
-BJSocket::~BJSocket()
-{
-
-}
-
-bool BJSocket::Init()
-{
-
-    socketHandle = 0;
-    buffer = (BJ_UINT8*)malloc(MAX_FRAME_SIZE);
-
-    if (buffer == NULL)
-        return false;
-
-    //Setup msghdr;
-    memset(&socketMsghdr, '\0', sizeof(socketMsghdr));
-    socketMsghdr.msg_name = &peerAddr;
-    socketMsghdr.msg_namelen = sizeof(peerAddr);
-    socketMsghdr.msg_iov = socketIovec;
-    socketMsghdr.msg_iovlen = 1;
-    socketIovec[0].iov_base = (char *) buffer;
-    socketIovec[0].iov_len = MAX_FRAME_SIZE;
-
-
-    socketMsghdr.msg_control = socketCmsghdr;
-    socketMsghdr.msg_controllen = sizeof(socketCmsghdr);
-
-    return true;
-
-}
-
-bool BJSocket::CreateListenerIPv4(BJString interfaceName)
-{
-    bool bResult = true;
-    const int onoptval = 1;
-
-    if (socketHandle)
-        Close();
-
-    Init();
-
-
-    if (interfaceName.GetLength() > 0)
-        interfaceID  = if_nametoindex(interfaceName.GetBuffer());
-
-
-    socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
-//     socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_RAW);
-
-    if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
-    {
-        printf("setsockopt for SO_REUSEPORT failed");
-        Close();
-        return false;
-    }
-
-    JoinMulticastv4(interfaceName);
-
-    // set PktInfo to get dest address
-
-    if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_PKTINFO, &onoptval, sizeof(onoptval)))
-    {
-        printf("setsockopt for IP_PKTINFO failed");
-        Close();
-        return false;
-    }
-
-    // bind to socket
-
-    struct sockaddr_in sa;
-    memset(&sa,0,sizeof(sockaddr_in));
-    sa.sin_len = sizeof(sockaddr_in);
-    sa.sin_family = AF_INET;
-    sa.sin_addr.s_addr = INADDR_ANY;
-    sa.sin_port = htons(BonjourPort);
-
-    if (-1 == bind(socketHandle,(struct sockaddr*)&sa,sizeof(sa)))
-    {
-        printf("error in bind: %s\n",strerror(errno));
-        Close();
-        return false;
-    }
-    IPVersion = 4;
-
-    return bResult;
-}
-
-bool BJSocket::CreateListenerIPv6(BJString interfaceName)
-{
-    bool bResult = true;
-    const int onoptval=1;
-
-    if (socketHandle)
-        Close();
-
-    Init();
-
-    if (interfaceName.GetLength() > 0)
-        interfaceID  = if_nametoindex(interfaceName.GetBuffer());
-
-   socketHandle = socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
-
-    if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
-    {
-        printf("setsockopt for SO_REUSEPORT failed");
-        Close();
-        return false;
-    }
-
-    JoinMulticastv6(interfaceName);
-
-    // set PktInfo to get dest address
-    if (-1 == setsockopt(socketHandle, IPPROTO_IPV6, IPV6_PKTINFO, &onoptval, sizeof(onoptval)))
-    {
-        printf("setsockopt for IP_PKTINFO failed");
-        Close();
-        return false;
-    }
-
-    // bind to socket
-    struct sockaddr_in6 sa6;
-    memset(&sa6,0,sizeof(sockaddr_in6));
-    sa6.sin6_len = sizeof(sockaddr_in6);
-    sa6.sin6_family = AF_INET6;
-    sa6.sin6_addr = in6addr_any;
-    sa6.sin6_port = htons(BonjourPort);
-
-    if (-1 == bind(socketHandle,(struct sockaddr*)&sa6,sizeof(sa6)))
-    {
-        printf("error in bind: %s\n",strerror(errno));
-        Close();
-        return false;
-    }
-    IPVersion = 6;
-
-    return bResult;
-}
-
-bool BJSocket::Close()
-{
-    bool bResult = true;
-
-    if (socketHandle)
-        close(socketHandle);
-
-    socketHandle = 0;
-
-    return bResult;
-}
-
-int BJSocket::Read()
-{
-    int nLength = (int) recvmsg(socketHandle, &socketMsghdr,0);
-    if (!CheckInterface())
-        return 0;
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    m_CurrentFrame.Set(buffer-14-40-8,nLength,tv.tv_sec*1000000ll + tv.tv_usec);
-    return nLength;
-}
-
-BJIPAddr* BJSocket::GetSrcAddr()
-{
-    sourceAddr.Set(&peerAddr);
-    return &sourceAddr;
-}
-
-BJIPAddr* BJSocket::GetDestAddr()
-{
-
-    struct cmsghdr *cmsg;
-
-    for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
-    {
-
-        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
-        {
-            struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
-
-            destAddr.Set(&pPktInfo->ipi_addr);
-        }
-        if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
-        {
-            struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
-            destAddr.Set(&pPktInfo->ipi6_addr);
-        }
-    }
-    return &destAddr;
-}
-
-bool BJSocket::CheckInterface()
-{
-    if (interfaceID ==0)
-        return true;
-    struct cmsghdr *cmsg;
-
-    bool bFound = false;
-
-    for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
-    {
-
-        if ((cmsg->cmsg_level == IPPROTO_IP) && cmsg->cmsg_type == IP_PKTINFO)
-        {
-            bFound = true;
-            struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
-            if (pPktInfo->ipi_ifindex == interfaceID)
-                return true;
-            else
-            {
-                if (pPktInfo->ipi_ifindex != 4)
-                {
-                    sourceAddr.Set(&peerAddr);
-                    printf("address:%d %s \n",pPktInfo->ipi_ifindex,sourceAddr.GetString());
-                }
-            }
-        }
-        if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
-        {
-            bFound = true;
-            struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
-            if (pPktInfo->ipi6_ifindex == interfaceID)
-                return true;
-        }
-    }
-    if (!bFound)
-         printf("PKTINFO not found \n");
-    return false;
-}
-
-bool BJSocket::IsMulticastPacket()
-{
-    return GetDestAddr()->IsBonjourMulticast();
-
-}
-
-int BJSocket::GetSockectHandle()
-{
-    return socketHandle;
-}
-
-BJ_UINT8* BJSocket::GetBuffer()
-{
-    return buffer;
-}
-
-void BJSocket::JoinMulticastv4(BJString interfaceName)
-{
-   if (interfaceName.GetLength() == 0)
-   {
-       // join Multicast group
-       struct ip_mreq imr;
-       imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
-       imr.imr_interface.s_addr = INADDR_ANY;
-       if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
-       {
-           printf("setsockopt for IP_ADD_MEMBERSHIP failed");
-       }
-       return;
-   }
-
-    struct ifaddrs *ifa, *orig;
-
-    getifaddrs(&ifa);
-
-    orig = ifa;
-
-    for ( ; ifa; ifa = ifa->ifa_next)
-    {
-        if (interfaceName == ifa->ifa_name  && ifa->ifa_addr->sa_family == AF_INET)
-        {
-            struct sockaddr_in *ifa_addr = (struct sockaddr_in *)ifa->ifa_addr;
-            struct ip_mreq imr;
-            imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
-            imr.imr_interface.s_addr = ifa_addr->sin_addr.s_addr;
-            if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
-            {
-                printf("setsockopt for IP_ADD_MEMBERSHIP failed");
-            }
-        }
-    }
-
-    freeifaddrs(orig);
-
-}
-
-void BJSocket::JoinMulticastv6(BJString interfaceName)
-{
-
-    if (interfaceName.GetLength() == 0)
-        return;
-
-    // join Multicast group
-    struct in6_addr BonjourMultiaddr = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
-    struct ipv6_mreq i6mr;
-    memset(&i6mr,0,sizeof(i6mr));
-    memcpy(&i6mr.ipv6mr_multiaddr, &BonjourMultiaddr, sizeof(BonjourMultiaddr));
-    if (interfaceName.GetLength() > 0)
-        i6mr.ipv6mr_interface = interfaceID;
-    else
-        i6mr.ipv6mr_interface = __IPV6_ADDR_SCOPE_SITELOCAL;
-    int err = setsockopt(socketHandle, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
-    if (err < 0 && (errno != EADDRINUSE))
-    {
-        printf("setsockopt for IPV6_JOIN_GROUP failed %d",errno);
-    }
-}
-
-////////////////////////////////////////
-// BJSelect
-///////////////////////////////////////
-
-
-BJSelect::BJSelect()
-{
-    FD_ZERO(&socketSet);
-    maxSocket = 0;
-
-}
-
-bool BJSelect::Add(BJSocket& s)
-{
-    int sock = s.GetSockectHandle();
-    FD_SET(sock, &socketSet);
-    if (sock > maxSocket)
-        maxSocket = sock;
-
-    return true;
-
-}
-
-int BJSelect::Wait(int sec)
-{
-    struct timeval tv;
-    memset(&tv, 0, sizeof(tv));
-    tv.tv_sec = sec;
-
-    int result = select(maxSocket+1, &socketSet, NULL, NULL, &tv);
-    return result;
-
-}
-
-bool BJSelect::IsReady(BJSocket& Socket)
-{
-    int bIsSet = FD_ISSET(Socket.GetSockectHandle(), &socketSet);
-    return (bIsSet != 0);
-}
-
-
-
-
diff --git a/mDNSMacOSX/BonjourTop/source/bjsocket.h b/mDNSMacOSX/BonjourTop/source/bjsocket.h
deleted file mode 100644
index c85e384..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjsocket.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-//  bjsocket.h
-//  TestTB
-//
-//  Created by Terrin Eager on 10/24/12.
-//
-//
-
-#ifndef __TestTB__bjsocket__
-#define __TestTB__bjsocket__
-
-#include <iostream>
-
-#include <sys/socket.h>
-
-#include "bjtypes.h"
-#include "bjIPAddr.h"
-#include "bjstring.h"
-
-#include "Frame.h"
-
-
-class BJSocket
-{
-public:
-
-    BJSocket();
-    virtual ~BJSocket();
-
-    bool Init();
-
-    bool CreateListenerIPv4(BJString interfaceName);
-    bool CreateListenerIPv6(BJString interfaceName);
-
-    bool Close();
-
-    int Read();
-
-    Frame m_CurrentFrame;
-
-    bool IsMulticastPacket();
-
-    int GetSockectHandle();
-
-    BJ_UINT8* GetBuffer();
-    BJIPAddr* GetSrcAddr();
-    BJIPAddr* GetDestAddr();
-
-private:
-    void JoinMulticastv4(BJString interfaceName);
-    void JoinMulticastv6(BJString interfaceName);
-
-    bool CheckInterface();
-
-    BJ_UINT32 interfaceID;
-
-    int socketHandle;
-    BJ_UINT8* buffer;
-
-
-    int IPVersion;
-    BJIPAddr sourceAddr;
-    BJIPAddr destAddr;
-
-    struct msghdr socketMsghdr;
-    sockaddr_storage peerAddr;
-    struct iovec socketIovec[1];
-    struct cmsghdr socketCmsghdr[10];
-
-};
-
-class BJSelect
-{
-public:
-    BJSelect();
-
-    bool Add(BJSocket& s);
-    int Wait(int sec);
-
-    bool IsReady(BJSocket& s);
-
-private:
-    fd_set socketSet;
-    int maxSocket;
-
-};
-
-#endif /* defined(__TestTB__bjsocket__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjstring.cpp b/mDNSMacOSX/BonjourTop/source/bjstring.cpp
deleted file mode 100644
index 5fbcf59..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjstring.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-//
-//  bjstring.cpp
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#include "bjstring.h"
-#include <time.h>
-
-
-BJString::BJString()
-{
-    buffer = NULL;
-    length = 0;
-}
-
-BJString::BJString(const BJString& scr)
-{
-    buffer = NULL;
-    length = 0;
-    Set(scr.GetBuffer());
-}
-BJString::BJString(const char* str)
-{
-    buffer = NULL;
-    length = 0;
-    Set(str);
-}
-
-BJString::~BJString()
-{
-    delete[] buffer;
-    buffer = NULL;
-}
-
-
-BJString& BJString::operator=(const char* str)
-{
-    Set(str);
-    return *this;
-}
-
-BJString& BJString::operator=(const BJString& str)
-{
-    if (&str != this)
-        Set(str.GetBuffer());
-    return *this;
-}
-bool BJString::operator==(const char* str)
-{
-    if (buffer == NULL && str == NULL)
-        return true;
-    if (buffer == NULL || str == NULL)
-        return false;
-
-    return (strcmp(str,buffer) == 0);
-}
-bool BJString::operator==(const BJString& str)
-{
-    if (buffer == NULL && str.GetBuffer() == NULL)
-        return true;
-    if (buffer == NULL || str.GetBuffer() == NULL)
-        return false;
-    return (strcmp(str.GetBuffer(),buffer) == 0);
-}
-
-bool BJString::operator<(const BJString& str) const
-{
-    const char* myBuff = GetBuffer();
-    const char* otherBuff = str.GetBuffer();
-
-    if (myBuff == NULL && otherBuff == NULL)
-        return false;
-    if (myBuff != NULL && otherBuff == NULL)
-        return false;
-    if (myBuff == NULL && otherBuff != NULL)
-        return true;
-
-    int cmp = strcmp(myBuff, otherBuff);
-
-    if (cmp < 0)
-        return true;
-    else
-        return false;
-
-}
-
-BJ_COMPARE BJString::Compare(const BJString& str)
-{
-    const char* myBuff = GetBuffer();
-    const char* otherBuff = str.GetBuffer();
-
-    if (myBuff == NULL && otherBuff == NULL)
-        return BJ_EQUAL;
-    if (myBuff != NULL && otherBuff == NULL)
-        return BJ_GT;
-    if (myBuff == NULL && otherBuff != NULL)
-        return BJ_LT;
-
-    int cmp = strcmp(myBuff, otherBuff);
-
-    if (cmp > 0)
-        return (BJ_GT);
-    else if (cmp < 0)
-        return (BJ_LT);
-    else
-        return (BJ_EQUAL);
-
-}
-
-BJString& BJString::operator+=(const char* str)
-{
-    if (buffer == NULL)
-        return operator=(str);
-    if (str == NULL)
-        return *this;
-
-    BJString temp = buffer;
-    Create((BJ_UINT32)(strlen(buffer) + strlen(str)));
-    strlcpy(buffer, temp.GetBuffer(), length + 1);
-    strlcat(buffer, str, length + 1);
-    return *this;
-}
-BJString& BJString::operator+=(const BJString&str)
-{
-    operator+=(str.GetBuffer());
-    return *this;
-}
-
-
-const char* BJString::GetBuffer() const
-{
-    return buffer;
-}
-
-void BJString::Set(const char* str)
-{
-
-    BJ_UINT32 len = str?(BJ_UINT32)strlen(str):0;
-    if (len > 255)
-        len = 250;
-    Create(len);
-    if (buffer && str)
-        strlcpy(buffer, str, length + 1);
-
-}
-void BJString::Set(const char* str, BJ_UINT32 len)
-{
-    Create(len);
-    if (buffer)
-    {
-        if (str)
-            strncpy(buffer, str, len);
-        else
-            memset(buffer, 0, length);
-    }
-}
-
-void BJString::Append(const char* str, BJ_UINT32 len)
-{
-    if (length < (strlen(buffer) + strlen(str)))
-    {
-        BJString temp = buffer;
-        Create((BJ_UINT32)(strlen(buffer) + strlen(str)));
-        if (buffer && temp.buffer)
-            strlcpy(buffer, temp.GetBuffer(), length + 1);
-    }
-    strncat(buffer,str,len);
-}
-
-bool BJString::Contains(const char* str)
-{
-    if (buffer == NULL && str == NULL)
-        return true;
-    if (buffer == NULL ||  str == NULL)
-        return false;
-    return (strstr(buffer,str) != NULL);
-}
-
-BJ_UINT32 BJString::GetUINT32()
-{
-    if (buffer == NULL)
-        return 0;
-
-    return atoi(buffer);
-}
-
-void BJString::Format(BJ_UINT64 number,BJ_FORMAT_STYLE style)
-{
-    switch (style) {
-        case BJSS_BYTE:
-            Create(32);
-            sprintf(buffer,"%llu",number);
-            break;
-        case BJSS_TIME:
-        {
-            char formatedTime[24];
-            time_t timeValue = number;
-            struct tm* timeStruct = localtime(&timeValue);
-            strftime(formatedTime, sizeof(formatedTime), "%Y-%m-%d_%T_%a", timeStruct);
-            Set(formatedTime);
-            break;
-        }
-        default:
-            break;
-    }
-}
-
-
-void BJString::Create(BJ_UINT32 len)
-{
-    if (buffer)
-    {
-        if (length >= len)
-        {
-            memset(buffer, 0, len + 1);
-            return;
-        }
-        delete buffer;
-        buffer = NULL;
-        length = 0;
-    }
-
-    buffer = new char[len+1];
-    if (buffer)
-    {
-        memset(buffer, 0, len+1);
-        length = len;
-    }
-}
-
-BJ_UINT32 BJString::GetLength()
-{
-    return  buffer?(BJ_UINT32)strlen(buffer):0;
-}
diff --git a/mDNSMacOSX/BonjourTop/source/bjstring.h b/mDNSMacOSX/BonjourTop/source/bjstring.h
deleted file mode 100644
index 428f90d..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjstring.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-//  bjstring.h
-//  TestTB
-//
-//  Created by Terrin Eager on 9/26/12.
-//
-//
-
-#ifndef __TestTB__bjstring__
-#define __TestTB__bjstring__
-
-#include <iostream>
-#include "bjtypes.h"
-
-class BJString
-{
-
-public:
-    BJString();
-    BJString(const BJString& scr);
-    BJString(const char* str);
-    virtual ~BJString();
-
-    BJString& operator=(const char* str);
-    BJString& operator=(const BJString& str);
-    bool operator==(const char* str);
-    bool operator!=(const char* str){return !operator==(str);}
-    bool operator==(const BJString& str);
-    bool operator!=(const BJString& str) {return !operator==(str);}
-    bool operator<(const BJString& str) const;
-
-    BJ_COMPARE Compare(const BJString& str);
-
-
-    BJString& operator+=(const char* str);
-    BJString& operator+=(const BJString& str);
-
-    const char* GetBuffer() const;
-
-    void Set(const char* str);
-    void Set(const char* str,BJ_UINT32 len);
-
-    void Append(const char* str, BJ_UINT32 len);
-
-    bool Contains(const char* str);
-
-    BJ_UINT32 GetUINT32();
-
-    enum BJ_FORMAT_STYLE {BJSS_BYTE,BJSS_TIME} ;
-    void Format(BJ_UINT64 number,BJ_FORMAT_STYLE style);
-
-    BJ_UINT32 GetLength();
-
-    BJ_UINT32 GetBufferLength(){return length;};
-
-private:
-
-    void Create(BJ_UINT32 len);
-    char* buffer;
-    BJ_UINT32 length;
-};
-
-#endif /* defined(__TestTB__bjstring__) */
diff --git a/mDNSMacOSX/BonjourTop/source/bjtypes.h b/mDNSMacOSX/BonjourTop/source/bjtypes.h
deleted file mode 100644
index 59de273..0000000
--- a/mDNSMacOSX/BonjourTop/source/bjtypes.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-//  bjtypes.h
-//  TestTB
-//
-//  Created by Terrin Eager on 4/24/12.
-//
-//
-
-
-#ifndef TestTB_bjtypes_h
-#define TestTB_bjtypes_h
-typedef bool BJ_BOOL;
-
-typedef char BJ_INT8;
-typedef unsigned char BJ_UINT8;
-
-typedef short int BJ_INT16;
-typedef unsigned short int BJ_UINT16;
-
-typedef  int BJ_INT32;
-typedef unsigned  int BJ_UINT32;
-
-typedef  long long BJ_INT64;
-typedef unsigned  long long BJ_UINT64;
-
-#define DNS_NAME_OFFSET_MASK 0xc0
-
-#define MAX_FRAME_SIZE 0x2800
-
-
-enum BJ_COMPARE {BJ_GT,BJ_LT,BJ_EQUAL};
-
-#define PF_GET_UINT8(pBuffer,offset) ( (BJ_UINT8)pBuffer[offset] )
-#define PF_GET_UINT16(pBuffer,offset) ((((BJ_UINT16)pBuffer[offset]) << 8) | ((BJ_UINT16)pBuffer[offset+1]))
-#define PF_GET_UINT32(pBuffer,offset) ((pBuffer[offset] << 24) | (pBuffer[offset+1] << 16) | (pBuffer[offset+2] << 8) | (pBuffer[offset+3]))
-
-
-inline void endian_swap(BJ_UINT8& x)
-{
-    x = (x>>8) |(x<<8);
-}
-
-inline void endian_swap(BJ_UINT32& x)
-{
-    x = (x>>24) |
-        ((x<<8) & 0x00FF0000) |
-        ((x>>8) & 0x0000FF00) |
-        (x<<24);
-}
-
-
-inline void endian_swap(BJ_UINT64& x)
-{
-    x = (x>>56) |
-    ((x<<40) & 0x00FF000000000000) |
-    ((x<<24) & 0x0000FF0000000000) |
-    ((x<<8)  & 0x000000FF00000000) |
-    ((x>>8)  & 0x00000000FF000000) |
-    ((x>>24) & 0x0000000000FF0000) |
-    ((x>>40) & 0x000000000000FF00) |
-    (x<<56);
-}
-
-#endif
diff --git a/mDNSMacOSX/BonjourTop/source/main.cpp b/mDNSMacOSX/BonjourTop/source/main.cpp
deleted file mode 100644
index 52107bb..0000000
--- a/mDNSMacOSX/BonjourTop/source/main.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-//
-//  main.cpp
-//  BonjourTop
-//
-//  Created by Terrin Eager on 4/24/13.
-//  Copyright (c) 2013-2014 Apple Inc. All rights reserved.
-//
-
-#include <stdio.h>
-#include <curses.h>
-
-#include "bjtypes.h"
-#include "BonjourTop.h"
-
-#include <signal.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-
-#define BJ_VERSION_MAJOR 0
-#define BJ_VERSION_MINOR 23
-CBonjourTop BjTop;
-
-static void
-usage()
-{
-    printf("bonjourtop usage: bonjourTop (Version: %d.%d)\n",BJ_VERSION_MAJOR,BJ_VERSION_MINOR);
-    printf("\t\t\t [-t tcptrace_filename ]\n");
-    printf("\t\t\t [-i interfaceName]\n");
-    printf("\t\t\t [-m ipaddress/subnetmask]  ie 17.255.45.12/17\n");
-    printf("\t\t\t [-e export_filename]  \n");
-    printf("\t\t\t [-x seconds]  'Snapshot export every x seconds'\n");
-    printf("\t\t\t [-s] 'service information'\n");
-    printf("\t\t\t [-v] 'report the version number'  \n");
-    printf("\t\t\t [-d] filename 'export device map. Adds timestamp and csv extension to the filename'  \n");
-    printf("\t\t\t [-f application] 'filter application for device map (only available with -t -d options)'  \n");
-    printf("While running the follow keys may be used:\n");
-    printf("\t b - sort by Bytes\n");
-    printf("\t p - sort by Packets (default)\n");
-    printf("\t n - sort by Name\n");
-    printf("\t a - Display Application Names (default) \n");
-    printf("\t s - Display Services Names  \n");
-    printf("\t t - Display 24 hour packet per min  \n");
-
-    printf("\t o - flip sort order\n");
-    printf("\t e - export to BonjourTop.csv\n");
-    printf("\t q - quit\n\n");
-}
-
-static void
-handle_window_change(int signal) {
-    switch (signal) {
-        case SIGWINCH:
-            BjTop.WindowSizeChanged();
-            break;
-        default:
-            break;
-    }
-}
-
-int main(int argc, char * const *argv)
-{
-
-    sigset_t sset, oldsset;
-    int c;
-
-    static struct option longopts[] = {
-        {   "trace", required_argument, NULL, 't' },
-        {   "interface", required_argument, NULL, 'i' },
-        {   "ipaddr_subnet", required_argument, NULL, 'm' },
-        {   "export", required_argument, NULL, 'e' },
-        {   "snapshot", required_argument, NULL, 'x' },
-        {   "service", no_argument, NULL, 's' },
-        {   "version", no_argument, NULL, 'v' },
-        {   "devicemap", required_argument, NULL, 'd' },
-        {   "filter", required_argument, NULL, 'f' },
-        {   NULL, 0, NULL, 0 }
-    };
-
-	sigemptyset(&sset);
-
-    /* Block SIGWINCH signals while we are in a relayout. */
-    if(-1 == sigprocmask(SIG_BLOCK, &sset, &oldsset)) {
-        perror("sigprocmask");
-        exit(EXIT_FAILURE);
-    }
-
-    BJ_COLLECTBY_TYPE TypeList[] = {CBT_SERVICE,CBT_REQUEST_RESPONDS,CBT_SAME_DIFF_SUBNET,CBT_IP_ADDRESS_TYPE,CBT_PACKET};
-    BJString sTemp;
-
-    bool bLiveCapture = true;
-    bool bExport = false;
-
-    while ((c = getopt_long(argc, argv, "t:i:m:e:x:svd:f:phb", longopts, NULL)) != -1) {
-        switch (c) {
-            case 't':
-                BjTop.m_pTcpDumpFileName = optarg; // TCP Dump Filename
-                bLiveCapture = false;
-                BjTop.m_bCursers = false;
-                break;
-            case 'p':
-                BjTop.m_bCursers = false;
-                break;
-            case 'e':
-                bExport = true;
-                BjTop.m_pExportFileName = optarg;   // Export filename
-                break;
-            case 'i':
-                BjTop.interfaceName = optarg;       // Interface name
-                break;
-            case 'm':
-                BjTop.SetIPAddr(optarg);            // TODO: verify that the argument is an ip address
-                break;
-            case 'x':
-                sTemp = optarg;                     // time in seconds for snapshots
-                BjTop.m_SnapshotSeconds = sTemp.GetUINT32();
-                break;
-            case 'd':
-                BjTop.m_bImportExportDeviceMap = true;
-                BjTop.m_DeviceFileName = optarg;
-                break;
-            case 'f':
-                BjTop.filterApplicationName = optarg;
-                break;
-            case 's':
-                BjTop.m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
-                break;
-            case 'v':
-                printf("\nbonjourtop Version: %d.%d\n\n",BJ_VERSION_MAJOR,BJ_VERSION_MINOR);
-                exit(0);
-                break;
-            case 'b':
-                BjTop.m_Collection.Init(TypeList);
-                bExport = true;
-                break;
-            case 'h':
-                usage();
-                exit(0);
-                break;
-            default:
-                usage();
-                break;
-        }
-    }
-
-    if (BjTop.m_bCursers)
-    {
-        signal(SIGWINCH, handle_window_change);
-        initscr();
-        timeout(0);
-        BjTop.PrintResults(1,false);
-    }
-
-    if (bLiveCapture)
-        BjTop.LiveCapture();
-    else
-        BjTop.CaptureFile();
-
-
-    if (bExport)
-    {
-        BjTop.ExportResults();
-        return 0;
-    }
-
-    if (BjTop.m_bCursers)
-        endwin();
-
-    if (BjTop.m_bImportExportDeviceMap)
-    {
-        BjTop.WriteDeviceFile();
-        BjTop.WriteVendorFile();
-    }
-
-    return 0;
-}
-
-
diff --git a/mDNSMacOSX/D2D.c b/mDNSMacOSX/D2D.c
deleted file mode 100644
index 9d0c574..0000000
--- a/mDNSMacOSX/D2D.c
+++ /dev/null
@@ -1,1271 +0,0 @@
-/*
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "D2D.h"
-#include "mDNSEmbeddedAPI.h"        // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "mDNSMacOSX.h"             // Defines the specific types needed to run mDNS on this platform
-#include "dns_sd.h"                 // For mDNSInterface_LocalOnly etc.
-#include "dns_sd_internal.h"
-#include "misc_utilities.h"
-#include "uds_daemon.h"
-#include <mdns/powerlog.h>
-#include "mdns_strict.h"
-
-#define D2DIsTransportLikeAWDL(X) ((X) == D2DAWDLTransport || (X) == D2DWiFiAwareTransport)
-
-D2DStatus D2DInitialize(CFRunLoopRef runLoop, D2DServiceCallback serviceCallback, void* userData) __attribute__((weak_import));
-D2DStatus D2DRetain(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
-D2DStatus D2DStopAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DRelease(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
-D2DStatus D2DStartAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DStartBrowsingForKeyOnTransport(const Byte *key, const size_t keySize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DStopBrowsingForKeyOnTransport(const Byte *key, const size_t keySize, D2DTransportType transport) __attribute__((weak_import));
-void D2DStartResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-void D2DStopResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DTerminate(void) __attribute__((weak_import));
-
-#pragma mark - D2D Support
-
-mDNSexport void D2D_start_advertising_interface(NetworkInterfaceInfo *interface)
-{
-    // AWDL wants the address and reverse address PTR record communicated
-    // via the D2D interface layer.
-    if (interface->InterfaceID == AWDLInterfaceID || interface->InterfaceID == WiFiAwareInterfaceID)
-    {
-        // only log if we have a valid record to start advertising
-        if (interface->RR_A.resrec.RecordType || interface->RR_PTR.resrec.RecordType)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2D_start_advertising_interface - ifname: " PUB_S,
-                interface->ifname);
-        }
-
-        if (interface->RR_A.resrec.RecordType)
-            external_start_advertising_service(&interface->RR_A.resrec, 0, 0);
-        if (interface->RR_PTR.resrec.RecordType)
-            external_start_advertising_service(&interface->RR_PTR.resrec, 0, 0);
-    }
-}
-
-mDNSexport void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface)
-{
-    if (interface->InterfaceID == AWDLInterfaceID || interface->InterfaceID == WiFiAwareInterfaceID)
-    {
-        // only log if we have a valid record to stop advertising
-        if (interface->RR_A.resrec.RecordType || interface->RR_PTR.resrec.RecordType)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2D_stop_advertising_interface - ifname: " PUB_S,
-                interface->ifname);
-        }
-
-        if (interface->RR_A.resrec.RecordType)
-            external_stop_advertising_service(&interface->RR_A.resrec, 0, 0);
-        if (interface->RR_PTR.resrec.RecordType)
-            external_stop_advertising_service(&interface->RR_PTR.resrec, 0, 0);
-    }
-}
-
-// If record would have been advertised to the D2D plugin layer, stop that advertisement.
-mDNSexport void D2D_stop_advertising_record(AuthRecord *ar)
-{
-    DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
-    if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
-    {
-        external_stop_advertising_service(&ar->resrec, flags, 0);
-    }
-}
-
-// If record should be advertised to the D2D plugin layer, start that advertisement.
-mDNSexport void D2D_start_advertising_record(AuthRecord *ar)
-{
-    DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
-    if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
-    {
-        external_start_advertising_service(&ar->resrec, flags, 0);
-    }
-}
-
-// Name compression items for fake packet version number 1
-static const mDNSu8 compression_packet_v1 = 0x01;
-
-static DNSMessage compression_base_msg = { { {{0}}, {{0}}, 2, 1, 0, 0 }, "\x04_tcp\x05local\x00\x00\x0C\x00\x01\x04_udp\xC0\x11\x00\x0C\x00\x01" };
-static mDNSu8 *const compression_limit = (mDNSu8 *) &compression_base_msg + sizeof(DNSMessage);
-static mDNSu8 *const compression_lhs = (mDNSu8 *const) compression_base_msg.data + 27;
-
-mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-typedef struct D2DRecordListElem
-{
-    struct D2DRecordListElem *next;
-    D2DServiceInstance       instanceHandle;
-    D2DTransportType         transportType;
-    AuthRecord               ar;    // must be last in the structure to accomodate extra space
-                                    // allocated for large records.
-} D2DRecordListElem;
-
-static D2DRecordListElem *D2DRecords = NULL; // List of records returned with D2DServiceFound events
-
-typedef struct D2DBrowseListElem
-{
-    struct D2DBrowseListElem *next;
-    domainname name;
-    mDNSu16 type;
-    unsigned int refCount;
-} D2DBrowseListElem;
-
-D2DBrowseListElem* D2DBrowseList = NULL;
-
-mDNSlocal mDNSu8 *putVal16(mDNSu8 *ptr, mDNSu16 val)
-{
-    ptr[0] = (mDNSu8)((val >> 8 ) & 0xFF);
-    ptr[1] = (mDNSu8)((val      ) & 0xFF);
-    return ptr + sizeof(mDNSu16);
-}
-
-mDNSlocal mDNSu8 *putVal32(mDNSu8 *ptr, mDNSu32 val)
-{
-    ptr[0] = (mDNSu8)((val >> 24) & 0xFF);
-    ptr[1] = (mDNSu8)((val >> 16) & 0xFF);
-    ptr[2] = (mDNSu8)((val >>  8) & 0xFF);
-    ptr[3] = (mDNSu8)((val      ) & 0xFF);
-    return ptr + sizeof(mDNSu32);
-}
-
-mDNSlocal void DomainnameToLower(const domainname * const in, domainname * const out)
-{
-    const mDNSu8 * const start = (const mDNSu8 * const)in;
-    const mDNSu8 *ptr = (const mDNSu8*)start;
-    while(*ptr)
-    {
-        mDNSu8 c = *ptr;
-        out->c[ptr-start] = *ptr;
-        ptr++;
-        for (; c; c--,ptr++) out->c[ptr-start] = mDNSIsUpperCase(*ptr) ? (*ptr - 'A' + 'a') : *ptr;
-    }
-    out->c[ptr-start] = *ptr;
-}
-
-mDNSlocal mDNSu8 * DNSNameCompressionBuildLHS(const domainname* typeDomain, mDNSu16 qtype)
-{
-    mDNSu8 *ptr = putDomainNameAsLabels(&compression_base_msg, compression_lhs, compression_limit, typeDomain);
-    if (!ptr) return ptr;
-    *ptr = (qtype >> 8) & 0xff;
-    ptr += 1;
-    *ptr = qtype & 0xff;
-    ptr += 1;
-    *ptr = compression_packet_v1;
-    return ptr + 1;
-}
-
-mDNSlocal mDNSu8 * DNSNameCompressionBuildRHS(mDNSu8 *start, const ResourceRecord *const resourceRecord)
-{
-    return putRData(&compression_base_msg, start, compression_limit, resourceRecord);
-}
-
-mDNSlocal void PrintHelper(const char *const tag, const mDNSu8 *lhs, mDNSu16 lhs_len, const mDNSu8 *rhs, mDNSu16 rhs_len)
-{
-    if (mDNS_LoggingEnabled)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEBUG, PUB_S ": LHS: (%d bytes) " PRI_HEX, tag, lhs_len, HEX_PARAM(lhs, lhs_len));
-        if (rhs)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEBUG, PUB_S ": RHS: (%d bytes) " PRI_HEX, tag, rhs_len, HEX_PARAM(rhs, rhs_len));
-        }
-    }
-}
-
-mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;  // unused
-    if (result == mStatus_MemFree)
-    {
-        D2DRecordListElem **ptr = &D2DRecords;
-        D2DRecordListElem *tmp;
-        while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
-        if (!*ptr)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "FreeD2DARElemCallback: Could not find in D2DRecords: " PRI_S, ARDisplayString(m, rr));
-            return;
-        }
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "FreeD2DARElemCallback: Found in D2DRecords: " PRI_S, ARDisplayString(m, rr));
-        tmp = *ptr;
-        *ptr = (*ptr)->next;
-        // Just because we stoppped browsing, doesn't mean we should tear down the PAN connection.
-        mDNSPlatformMemFree(tmp);
-    }
-}
-
-mDNSexport void external_connection_release(const domainname *instance)
-{
-    (void) instance;
-    D2DRecordListElem *ptr = D2DRecords;
-
-    for ( ; ptr ; ptr = ptr->next)
-    {
-        if ((ptr->ar.resrec.rrtype == kDNSServiceType_PTR) &&
-             SameDomainName(&ptr->ar.rdatastorage.u.name, instance))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "external_connection_release: Calling D2DRelease - "
-                "instanceHandle: %p, transportType: %d", ptr->instanceHandle, ptr->transportType);
-            if (D2DRelease) D2DRelease(ptr->instanceHandle, ptr->transportType);
-        }
-    }
-}
-
-mDNSlocal void xD2DClearCache(const domainname *regType, mDNSu16 qtype)
-{
-    D2DRecordListElem *ptr = D2DRecords;
-    while (ptr)
-    {
-        D2DRecordListElem *tmp = ptr;
-        ptr = ptr->next;
-        if ((tmp->ar.resrec.rrtype == qtype) && SameDomainName(&tmp->ar.namestorage, regType))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT,
-                "xD2DClearCache: Clearing and deregistering cache record - "
-                "name: " PRI_DM_NAME ", rrtype: " PUB_DNS_TYPE ", auth record: " PRI_S, DM_NAME_PARAM(regType),
-                DNS_TYPE_PARAM(qtype), ARDisplayString(&mDNSStorage, &tmp->ar));
-
-            mDNS_Deregister(&mDNSStorage, &tmp->ar);
-            // Memory will be freed and element removed in FreeD2DARElemCallback
-        }
-    }
-}
-
-mDNSlocal D2DBrowseListElem ** D2DFindInBrowseList(const domainname *const name, mDNSu16 type)
-{
-    D2DBrowseListElem **ptr = &D2DBrowseList;
-
-    for ( ; *ptr; ptr = &(*ptr)->next)
-        if ((*ptr)->type == type && SameDomainName(&(*ptr)->name, name))
-            break;
-
-    return ptr;
-}
-
-mDNSlocal unsigned int D2DBrowseListRefCount(const domainname *const name, mDNSu16 type)
-{
-    D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
-    return *ptr ? (*ptr)->refCount : 0;
-}
-
-mDNSlocal void D2DBrowseListRetain(const domainname *const name, mDNSu16 type)
-{
-    D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
-
-    if (!*ptr)
-    {
-        *ptr = (D2DBrowseListElem *) mDNSPlatformMemAllocateClear(sizeof(**ptr));
-        (*ptr)->type = type;
-        AssignDomainName(&(*ptr)->name, name);
-    }
-    (*ptr)->refCount += 1;
-
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2DBrowseListRetain - "
-        "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", ref count: %u", DM_NAME_PARAM(&(*ptr)->name),
-        DNS_TYPE_PARAM((*ptr)->type), (*ptr)->refCount);
-}
-
-// Returns true if found in list, false otherwise
-mDNSlocal bool D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
-{
-    D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
-
-    if (!*ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2DBrowseListRelease item not found in the list - "
-            "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE, DM_NAME_PARAM(name), DNS_TYPE_PARAM(type));
-        return false;
-    }
-
-    (*ptr)->refCount -= 1;
-
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2DBrowseListRelease - "
-        "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", ref count: %u", DM_NAME_PARAM(&(*ptr)->name),
-        DNS_TYPE_PARAM((*ptr)->type), (*ptr)->refCount);
-
-    if (!(*ptr)->refCount)
-    {
-        D2DBrowseListElem *tmp = *ptr;
-        *ptr = (*ptr)->next;
-        mDNSPlatformMemFree(tmp);
-    }
-    return true;
-}
-
-mDNSlocal mDNSBool LabelPairIsForService(const mDNSu8 *const firstLabel)
-{
-    // See <https://datatracker.ietf.org/doc/html/rfc6763#section-7> for more info.
-    const int firstLabelLen = *firstLabel;
-    if ((firstLabelLen > 0) && (firstLabel[1] == '_'))
-    {
-        const mDNSu8 *const secondLabel = firstLabel + 1 + firstLabelLen;
-        const mDNSu8 *const protoLabelTCP = (const mDNSu8 *)"\x4" "_tcp";
-        const mDNSu8 *const protoLabelUDP = (const mDNSu8 *)"\x4" "_udp";
-        if (SameDomainLabel(secondLabel, protoLabelTCP) || SameDomainLabel(secondLabel, protoLabelUDP))
-        {
-            return mDNStrue;
-        }
-    }
-    return mDNSfalse;
-}
-
-mDNSlocal mDNSBool DomainNameIsForBrowsing(const domainname *const name)
-{
-    // Check if the domain name is used for DNS-SD browsing. Specifically, check if the domain name is used for Service
-    // Instance Enumeration, i.e., of the form <service>.<parent domain>, or for Selective Instance Enumeration, i.e.,
-    // of the form <subtype>._sub.<service>.<parent domain>. Note that <subtype> is a single label and <service> is a
-    // pair of labels starting with a service name label, followed by a protocol label, either "_tcp" or "_udp". See
-    // <https://datatracker.ietf.org/doc/html/rfc6763#section-7>.
-    int labelLen;
-    const mDNSu8 *label3 = mDNSNULL;
-    const mDNSu8 *label2 = mDNSNULL;
-    for (const mDNSu8 *label1 = name->c; (labelLen = *label1) != 0; label1 += (1 + labelLen))
-    {
-        if (!label3 && !label2 && label1)
-        {
-            if (LabelPairIsForService(label1))
-            {
-                return mDNStrue;
-            }
-        }
-        else if (label3 && label2 && label1)
-        {
-            const mDNSu8 *const subLabel  = (const mDNSu8 *)"\x4" "_sub";
-            if (SameDomainLabel(label2, subLabel) && LabelPairIsForService(label1))
-            {
-                return mDNStrue;
-            }
-            break;
-        }
-        label3 = label2;
-        label2 = label1;
-    }
-    return mDNSfalse;
-}
-
-mDNSlocal mStatus xD2DParseCompressedPacket(const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, const mDNSu32 ttl, mDNSu8 ** const out_ptr)
-{
-    // Sanity check that key array (lhs) has one domain name, followed by the record type and single byte D2D
-    // plugin protocol version number.
-    // Note, we don't have a DNSMessage pointer at this point, so just pass in the lhs value as the lower bound
-    // of the input bytes we are processing.  skipDomainName() does not try to follow name compression pointers,
-    // so it is safe to pass it the key byte array since it will stop parsing the DNS name and return a pointer
-    // to the byte after the first name compression pointer it encounters.
-    const mDNSu8 *keyp = skipDomainName((const DNSMessage *const) lhs, lhs, lhs + lhs_len);
-
-    // There should be 3 bytes remaining in a valid key,
-    // two for the DNS record type, and one for the D2D protocol version number.
-    if (keyp == NULL || (keyp + 3 != (lhs + lhs_len)))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DParseCompressedPacket: Could not parse DNS name in key");
-        return mStatus_Incompatible;
-    }
-    const mDNSu16 recordType = ((mDNSu16)(keyp[0] << 8)) | keyp[1];
-    keyp += 2;   // point to D2D compression packet format version byte
-    if (*keyp != compression_packet_v1)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DParseCompressedPacket: Invalid D2D packet version - "
-            "version: %d", *keyp);
-        return mStatus_Incompatible;
-    }
-
-    if (mDNS_LoggingEnabled)
-    {
-        const int len = (int)(compression_lhs - (mDNSu8*)&compression_base_msg);
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DParseCompressedPacket: Static Bytes - "
-            "len: %d, Hex: " PUB_HEX, len, HEX_PARAM(&compression_base_msg, len));
-    }
-
-    mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet
-
-    // Check to make sure we're not going to go past the end of the DNSMessage data
-    // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH
-    if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr;
-
-    // Copy the LHS onto our fake wire packet
-    const mDNSu8 *const recordNamePtr = ptr;
-    mDNSPlatformMemCopy(ptr, lhs, lhs_len);
-    ptr += lhs_len - 1;
-
-    // Check the 'fake packet' version number, to ensure that we know how to decompress this data
-    if (*ptr != compression_packet_v1) return mStatus_Incompatible;
-
-    // two bytes of CLASS
-    mDNSu8 *const recordClassPtr = ptr;
-    ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet);
-
-    // four bytes of TTL
-    ptr = putVal32(ptr, ttl);
-
-    // Copy the RHS length into the RDLENGTH of our fake wire packet
-    ptr = putVal16(ptr, rhs_len);
-
-    // Copy the RHS onto our fake wire packet
-    mDNSPlatformMemCopy(ptr, rhs, rhs_len);
-    ptr += rhs_len;
-    *out_ptr = ptr;
-
-    // If the record answers a DNS-SD PTR browsing query, then clear the cache-flush bit. Such records are part of a
-    // shared resource record set since PTR records for instances of a given service type can come from more than one
-    // mDNS responder. From <https://datatracker.ietf.org/doc/html/rfc6762#section-10.2>:
-    //
-    //    The cache-flush bit MUST NOT ever be set in any shared resource
-    //    record.  To do so would cause all the other shared versions of this
-    //    resource record with different rdata from different responders to be
-    //    immediately deleted from all the caches on the network.
-    if (recordType == kDNSServiceType_PTR)
-    {
-        domainname recordName;
-        if (getDomainName(&compression_base_msg, recordNamePtr, compression_limit, &recordName) &&
-            DomainNameIsForBrowsing(&recordName))
-        {
-            putVal16(recordClassPtr, kDNSClass_IN);
-        }
-    }
-    if (mDNS_LoggingEnabled)
-    {
-        const int len = (int)(ptr - compression_lhs);
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DParseCompressedPacket: Our Bytes - "
-            "len: %d, Hex: " PRI_HEX, len, HEX_PARAM(compression_lhs, len));
-    }
-    return mStatus_NoError;
-}
-
-mDNSlocal mStatus xD2DParse(const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, D2DRecordListElem **D2DListp)
-{
-    mDNS *const m = &mDNSStorage;
-    mStatus err;
-    mDNSu8 *ptr;
-    err = xD2DParseCompressedPacket(lhs, lhs_len, rhs, rhs_len, 120, &ptr);
-    if (err != mStatus_NoError)  return err;
-
-    const mDNSu8 *const next = GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec);
-    if (!next || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DParse: failed to get large RR");
-        mDNSCoreResetRecord(m);
-        return mStatus_UnknownErr;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DParse got record - "
-            "name: " PRI_DM_NAME ", rrtype: " PUB_DNS_TYPE ", rdata: " PRI_S, DM_NAME_PARAM(m->rec.r.resrec.name),
-            DNS_TYPE_PARAM(m->rec.r.resrec.rrtype), CRDisplayString(m, &m->rec.r));
-    }
-
-    *D2DListp = (D2DRecordListElem *) mDNSPlatformMemAllocateClear(sizeof(D2DRecordListElem) + (m->rec.r.resrec.rdlength <= sizeof(RDataBody) ? 0 : m->rec.r.resrec.rdlength - sizeof(RDataBody)));
-    if (!*D2DListp) return mStatus_NoMemoryErr;
-
-    AuthRecord *rr = &(*D2DListp)->ar;
-    mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL);
-    AssignDomainName(&rr->namestorage, &m->rec.namestorage);
-    rr->resrec.rdlength = m->rec.r.resrec.rdlength;
-    rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
-    mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength);
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-
-    mDNSCoreResetRecord(m);
-
-    return mStatus_NoError;
-}
-
-mDNSlocal void xD2DReceiveResponse(const DNSMessage *const response, const mDNSu8 *end, D2DTransportType transportType)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNS_Lock(m);
-    mDNSCoreReceiveD2DResponse(m, response, end, mDNSNULL, MulticastDNSPort, &AllDNSLinkGroup_v6, MulticastDNSPort,
-        (transportType == D2DAWDLTransport) ? AWDLInterfaceID : WiFiAwareInterfaceID);
-    mDNS_Unlock(m);
-}
-
-mDNSexport void xD2DAddToCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
-    mDNS *const m = &mDNSStorage;
-    if (result == kD2DSuccess)
-    {
-        if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DAddToCache: NULL Byte * passed in or length == 0");
-            return;
-        }
-
-        mStatus err;
-        if (D2DIsTransportLikeAWDL(transportType))
-        {
-            mDNSu8 *end_ptr; // pointer to the end of our fake packet
-            err = xD2DParseCompressedPacket(key, (mDNSu16)keySize, value, (mDNSu16)valueSize, kStandardTTL, &end_ptr);
-            if (err != mStatus_NoError)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DAddToCache: xD2DParseCompressedPacket failed - "
-                    "error: %d", err);
-                return;
-            }
-            xD2DReceiveResponse(&compression_base_msg, end_ptr, transportType);
-        }
-        else
-        {
-            D2DRecordListElem *ptr = NULL;
-
-            err = xD2DParse((const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr);
-            if (err)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DAddToCache: xD2DParse failed - "
-                    "error: %d", err);
-                PrintHelper(__func__, key, (mDNSu16)keySize, value, (mDNSu16)valueSize);
-                if (ptr)
-                    mDNSPlatformMemFree(ptr);
-                return;
-            }
-            err = mDNS_Register(m, &ptr->ar);
-            if (err)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DAddToCache: mDNS_Register failed - "
-                    "error: %d, name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", auth record: " PRI_S, err,
-                    DM_NAME_PARAM(ptr->ar.resrec.name), DNS_TYPE_PARAM(ptr->ar.resrec.rrtype),
-                    ARDisplayString(m, &ptr->ar));
-                mDNSPlatformMemFree(ptr);
-                return;
-            }
-
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DAddToCache: mDNS_Register succeeded - "
-                "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", Interface ID: %p, auth record: " PRI_S,
-                DM_NAME_PARAM(ptr->ar.resrec.name), DNS_TYPE_PARAM(ptr->ar.resrec.rrtype), ptr->ar.resrec.InterfaceID,
-                ARDisplayString(m, &ptr->ar));
-
-            ptr->instanceHandle = instanceHandle;
-            ptr->transportType = transportType;
-            ptr->next = D2DRecords;
-            D2DRecords = ptr;
-       }
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DAddToCache: Unexpected result - result: %d", result);
-    }
-}
-
-mDNSlocal D2DRecordListElem * xD2DFindInList(const Byte *const key, const size_t keySize, const Byte *const value, const size_t valueSize)
-{
-    D2DRecordListElem *ptr = D2DRecords;
-    D2DRecordListElem *arptr = NULL;
-
-    if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DFindInList: NULL Byte * passed in or length == 0");
-        return NULL;
-    }
-
-    mStatus err = xD2DParse((const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr);
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DFindInList: xD2DParse failed - error: %d", err);
-        PrintHelper(__func__, key, (mDNSu16)keySize, value, (mDNSu16)valueSize);
-        if (arptr)
-            mDNSPlatformMemFree(arptr);
-        return NULL;
-    }
-
-    while (ptr)
-    {
-        if (IdenticalResourceRecord(&arptr->ar.resrec, &ptr->ar.resrec)) break;
-        ptr = ptr->next;
-    }
-
-    if (!ptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DFindInList: Could not find in D2DRecords - "
-            "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", auth record: " PRI_S, DM_NAME_PARAM(arptr->ar.resrec.name),
-            DNS_TYPE_PARAM(arptr->ar.resrec.rrtype), ARDisplayString(&mDNSStorage, &arptr->ar));
-    }
-    mDNSPlatformMemFree(arptr);
-    return ptr;
-}
-
-mDNSexport void xD2DRemoveFromCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
-    (void)instanceHandle; // We don't care about this, yet.
-
-    if (result == kD2DSuccess)
-    {
-        if (D2DIsTransportLikeAWDL(transportType))
-        {
-            mDNSu8 *end_ptr; // pointer to the end of our fake packet
-            mStatus err = xD2DParseCompressedPacket(key, (mDNSu16)keySize, value, (mDNSu16)valueSize, 0, &end_ptr);
-            if (err != mStatus_NoError)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DRemoveFromCache: xD2DParseCompressedPacket failed"
-                    " - error: %d", err);
-                return;
-            }
-            xD2DReceiveResponse(&compression_base_msg, end_ptr, transportType);
-        }
-        else
-        {
-            D2DRecordListElem *ptr = xD2DFindInList(key, keySize, value, valueSize);
-            if (ptr)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DRemoveFromCache: removing record from cache - "
-                    "name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE ", auth record: " PRI_S,
-                    DM_NAME_PARAM(ptr->ar.resrec.name), DNS_TYPE_PARAM(ptr->ar.resrec.rrtype),
-                    ARDisplayString(&mDNSStorage, &ptr->ar));
-                mDNS_Deregister(&mDNSStorage, &ptr->ar);
-            }
-        }
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DRemoveFromCache: Unexpected result - result: %d", result);
-    }
-}
-
-mDNSlocal void xD2DServiceResolved(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
-    (void)key;
-    (void)keySize;
-    (void)value;
-    (void)valueSize;
-
-    if (result == kD2DSuccess)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DServiceResolved: Starting up PAN connection - "
-            "instanceHandle: %p", instanceHandle);
-
-        if (D2DRetain) D2DRetain(instanceHandle, transportType);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DServiceResolved: Unexpected result - result: %d", result);
-    }
-}
-
-mDNSlocal void xD2DRetainHappened(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
-    (void)instanceHandle;
-    (void)transportType;
-    (void)key;
-    (void)keySize;
-    (void)value;
-    (void)valueSize;
-
-    if (result == kD2DSuccess)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DRetainHappened: Opening up PAN connection - "
-            "instanceHandle: %p", instanceHandle);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DRetainHappened: Unexpected result - result: %d", result);
-    }
-}
-
-mDNSlocal void xD2DReleaseHappened(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
-    (void)instanceHandle;
-    (void)transportType;
-    (void)key;
-    (void)keySize;
-    (void)value;
-    (void)valueSize;
-
-    if (result == kD2DSuccess)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DReleaseHappened: Closing PAN connection - "
-            "instanceHandle: %p", instanceHandle);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DReleaseHappened: Unexpected result - result: %d", result);
-    }
-}
-
-mDNSlocal void removeCachedPeerRecords(const mDNSInterfaceID interface, const mDNSAddr *const peerAddr)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNS_Lock(m);
-    mDNSu32 slot;
-    const CacheGroup *cg;
-    CacheRecord *cr;
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        const ResourceRecord *const rr = &cr->resrec;
-        if ((rr->InterfaceID == interface) && mDNSSameAddress(&cr->sourceAddress, peerAddr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_INFO,
-                "Removing cached peer record -- peer address: " PRI_IP_ADDR ", name: " PRI_DM_NAME ", type: " PUB_DNS_TYPE,
-                peerAddr, DM_NAME_PARAM(rr->name), DNS_TYPE_PARAM(rr->rrtype));
-            mDNS_PurgeCacheResourceRecord(m, cr);
-        }
-    }
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void xD2DPeerLostHappened(const D2DStatus result, __unused const D2DServiceInstance instanceHandle,
-    const D2DTransportType transportType, __unused const Byte *const key, __unused const size_t keySize,
-    const Byte *const value, const size_t valueSize)
-{
-    require_quiet(result == kD2DSuccess, exit);
-
-    // Deduce the interface based on the transport type. Currently, only AWDL and WiFiAware transports are supported.
-    mDNSInterfaceID interface;
-    switch (transportType)
-    {
-    case D2DAWDLTransport:
-        interface = AWDLInterfaceID;
-        break;
-    case D2DWiFiAwareTransport:
-        interface = WiFiAwareInterfaceID;
-        break;
-    case D2DBluetoothTransport:
-    case D2DWifiPeerToPeerTransport:
-    default:
-        goto exit;
-    }
-
-    // The peer's IPv6 address is passed in value byte array as an in6_addr_t. See <rdar://98848070>.
-    in6_addr_t ipv6Addr;
-    require_quiet(valueSize == sizeof(ipv6Addr), exit);
-
-    memcpy(&ipv6Addr, value, sizeof(ipv6Addr));
-    const mDNSAddr peerAddr = mDNSAddr_from_in6_addr(&ipv6Addr);
-    removeCachedPeerRecords(interface, &peerAddr);
-
-exit:
-    return;
-}
-
-mDNSlocal void xD2DServiceCallback(D2DServiceEvent event, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize, void *userData)
-{
-    const char *eventString = "unknown";
-
-    KQueueLock();
-
-    if (keySize   > 0xFFFF)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DServiceCallback: keySize too large - "
-            "key size: %zu", keySize);
-    }
-    if (valueSize > 0xFFFF)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "xD2DServiceCallback: valueSize too large - "
-            "value size: %zu", valueSize);
-    }
-
-    switch (event)
-    {
-    case D2DServiceFound:
-        eventString = "D2DServiceFound";
-        break;
-    case D2DServiceLost:
-        eventString = "D2DServiceLost";
-        break;
-    case D2DServiceResolved:
-        eventString = "D2DServiceResolved";
-        break;
-    case D2DServiceRetained:
-        eventString = "D2DServiceRetained";
-        break;
-    case D2DServiceReleased:
-        eventString = "D2DServiceReleased";
-        break;
-    case D2DServicePeerLost:
-        eventString = "D2DServicePeerLost";
-        break;
-    default:
-        break;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DServiceCallback - event: " PUB_S
-        ", result: %d, instanceHandle: %p, transportType: %u, LHS: %p (%zu), RHS: %p (%zu), userData: %p",
-        eventString, result, instanceHandle, transportType, key, keySize, value, valueSize, userData);
-    PrintHelper(__func__, key, (mDNSu16)keySize, value, (mDNSu16)valueSize);
-
-    switch (event)
-    {
-    case D2DServiceFound:
-        xD2DAddToCache(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    case D2DServiceLost:
-        xD2DRemoveFromCache(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    case D2DServiceResolved:
-        xD2DServiceResolved(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    case D2DServiceRetained:
-        xD2DRetainHappened(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    case D2DServiceReleased:
-        xD2DReleaseHappened(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    case D2DServicePeerLost:
-        xD2DPeerLostHappened(result, instanceHandle, transportType, key, keySize, value, valueSize);
-        break;
-    default:
-        break;
-    }
-
-    // Need to tickle the main kqueue loop to potentially handle records we removed or added.
-    KQueueUnlock("xD2DServiceCallback");
-}
-
-// Map interface index and flags to a specific D2D transport type or D2DTransportMax if all installed plugins should be called.
-// When D2DTransportMax is returned, if a specific transport should not be called, *excludedTransportType 
-// will be set to the excluded transport value, otherwise, it will be set to D2DTransportMax to include all transports.
-// If the return value is not D2DTransportMax, *excludedTransportType is undefined.
-//
-// The following D2D plugin types are currently defined in the DeviceToDeviceManager project.
-//
-//  D2DBluetoothTransport:      Legacy Bluetooth Person Area Network (PAN)
-//  D2DWifiPeerToPeerTransport: Deprecated transport used for first generation of AirDrop on macOS. This plugin is no
-//                              longer installed and thus the DeviceToDeviceManager will simply return if called with this value.
-//  D2DAWDLTransport:           AWDL transport
-//  D2DWiFiAwareTransport:      NAN transport
-//
-// See the logic below for when a given plugin call is enabled.
-// If additional D2DTransportType values are defined in the future, this routine should be refactored to just
-// return a set of D2DTransportType values to simplify the logic in the call sites and support the newly defined D2DTransportType values.
-
-mDNSlocal D2DTransportType xD2DMapToTransportType(mDNSInterfaceID InterfaceID, DNSServiceFlags flags, D2DTransportType * excludedTransportType)
-{
-    // Set default to deprecated plugin value.
-    *excludedTransportType = D2DWifiPeerToPeerTransport;
-
-    // Call all D2D plugins when both kDNSServiceFlagsIncludeP2P and kDNSServiceFlagsIncludeAWDL are set.
-    if ((flags & kDNSServiceFlagsIncludeP2P) && (flags & kDNSServiceFlagsIncludeAWDL))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: call all active plugins since both "
-            "kDNSServiceFlagsIncludeP2P and kDNSServiceFlagsIncludeAWDL are set");
-        return D2DTransportMax;
-    } 
-    // Call D2DBluetoothTransport plugin when only kDNSServiceFlagsIncludeP2P is set.
-    else if (flags & kDNSServiceFlagsIncludeP2P)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: returning D2DBluetoothTransport since only "
-            "kDNSServiceFlagsIncludeP2P is set");
-        return D2DBluetoothTransport;
-    }
-    // Call both D2DAWDLTransport and D2DWiFiAwareTransport plugins when only kDNSServiceFlagsIncludeAWDL is set.
-    else if (flags & kDNSServiceFlagsIncludeAWDL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: call AWDL and NAN plugins since kDNSServiceFlagsIncludeAWDL is set");
-        *excludedTransportType = D2DBluetoothTransport;
-        return D2DTransportMax;
-    }
-
-    // Call only D2DBluetoothTransport plugin when psuedo interface mDNSInterface_P2P is used.
-    if (InterfaceID == mDNSInterface_P2P)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: returning D2DBluetoothTransport for interface index "
-            "mDNSInterface_P2P");
-        return D2DBluetoothTransport;
-    }
-
-    // Compare to cached AWDL interface ID.
-    if (AWDLInterfaceID && (InterfaceID == AWDLInterfaceID))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: returning D2DAWDLTransport for interface index %p", InterfaceID);
-        return D2DAWDLTransport;
-    }
-    if (WiFiAwareInterfaceID && (InterfaceID == WiFiAwareInterfaceID))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: returning D2DWiFiAwareTransport for interface index %p", InterfaceID);
-        return D2DWiFiAwareTransport;
-    }
-
-    // Return the deprecated and no longer installed plugin value for no matches to this point since it will result
-    // in no plugins being called.
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "xD2DMapToTransportType: no matching plugins for interface index %p", InterfaceID);
-    return D2DWifiPeerToPeerTransport;
-}
-
-mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID)
-{
-    internal_start_browsing_for_service(InterfaceID, typeDomain, qtype, flags, clientPID);
-}
-
-mDNSexport void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-
-    DomainnameToLower(typeDomain, &lower);
-
-    if (!D2DBrowseListRefCount(&lower, qtype))
-    {
-        D2DTransportType transportType, excludedTransport;
-
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "internal_start_browsing_for_service: starting browse - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_DNS_TYPE, DM_NAME_PARAM(&lower), DNS_TYPE_PARAM(qtype));
-
-        mDNSu8 *const end = DNSNameCompressionBuildLHS(&lower, qtype);
-        const size_t keyLen = (size_t)(end - compression_lhs);
-        PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, mDNSNULL, 0);
-
-        transportType = xD2DMapToTransportType(InterfaceID, flags, & excludedTransport);
-        if (transportType == D2DTransportMax)
-        {
-            D2DTransportType i;
-            for (i = 0; i < D2DTransportMax; i++)
-            {
-                if (i == excludedTransport) continue;
-                if (D2DStartBrowsingForKeyOnTransport)
-                {
-                    if (D2DIsTransportLikeAWDL(i))
-                    {
-                        mdns_powerlog_awdl_browse_start(typeDomain->c, qtype, clientPID);
-                    }
-                    D2DStartBrowsingForKeyOnTransport(compression_lhs, keyLen, i);
-                }
-            }
-        }
-        else
-        {
-            if (D2DStartBrowsingForKeyOnTransport)
-            {
-                if (D2DIsTransportLikeAWDL(transportType))
-                {
-                    mdns_powerlog_awdl_browse_start(typeDomain->c, qtype, clientPID);
-                }
-                D2DStartBrowsingForKeyOnTransport(compression_lhs, keyLen, transportType);
-            }
-        }
-    }
-    D2DBrowseListRetain(&lower, qtype);
-}
-
-mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID)
-{
-    internal_stop_browsing_for_service(InterfaceID, typeDomain, qtype, flags, clientPID);
-}
-
-mDNSexport void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-
-    DomainnameToLower(typeDomain, &lower);
-
-    // If found in list and this is the last reference to this browse, remove the key from the D2D plugins.
-    if (D2DBrowseListRelease(&lower, qtype) && !D2DBrowseListRefCount(&lower, qtype))
-    {
-        D2DTransportType transportType, excludedTransport;
-
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "internal_stop_browsing_for_service: stopping browse - "
-            "qname: " PRI_DM_NAME ", qtype: " PUB_DNS_TYPE, DM_NAME_PARAM(&lower), DNS_TYPE_PARAM(qtype));
-
-        mDNSu8 *const end = DNSNameCompressionBuildLHS(&lower, qtype);
-        const size_t keyLen = (size_t)(end - compression_lhs);
-        PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, mDNSNULL, 0);
-
-        transportType = xD2DMapToTransportType(InterfaceID, flags, & excludedTransport);
-        if (transportType == D2DTransportMax)
-        {
-            D2DTransportType i;
-            for (i = 0; i < D2DTransportMax; i++)
-            {
-                if (i == excludedTransport) continue;
-                if (D2DStopBrowsingForKeyOnTransport)
-                {
-                    D2DStopBrowsingForKeyOnTransport(compression_lhs, keyLen, i);
-                    if (D2DIsTransportLikeAWDL(i))
-                    {
-                        mdns_powerlog_awdl_browse_stop(typeDomain->c, qtype, clientPID);
-                    }
-                }
-            }
-        }
-        else
-        {
-            if (D2DStopBrowsingForKeyOnTransport)
-            {
-                D2DStopBrowsingForKeyOnTransport(compression_lhs, keyLen, transportType);
-                if (D2DIsTransportLikeAWDL(transportType))
-                {
-                    mdns_powerlog_awdl_browse_stop(typeDomain->c, qtype, clientPID);
-                }
-            }
-        }
-
-        // The D2D driver may not generate the D2DServiceLost event for this key after
-        // the D2DStopBrowsingForKey*() call above.  So, we flush the key from the D2D 
-        // record cache now.
-        xD2DClearCache(&lower, qtype);
-    }
-}
-
-mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID)
-{
-    internal_start_advertising_service(resourceRecord, flags, clientPID);
-}
-
-mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(resourceRecord->name, &lower);
-
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "internal_start_advertising_service - "
-        "name: " PRI_DM_NAME ", rrtype: " PUB_DNS_TYPE, DM_NAME_PARAM(resourceRecord->name),
-        DNS_TYPE_PARAM(resourceRecord->rrtype));
-
-    mDNSu8 *const rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
-    const mDNSu8 *const end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
-    const size_t keyLen = (size_t)(rhs - compression_lhs);
-    const size_t valueLen = (size_t)(end - rhs);
-    PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, rhs, (mDNSu16)valueLen);
-
-    transportType = xD2DMapToTransportType(resourceRecord->InterfaceID, flags, & excludedTransport);
-    if (transportType == D2DTransportMax)
-    {
-        D2DTransportType i;
-        for (i = 0; i < D2DTransportMax; i++)
-        {
-            if (i == excludedTransport) continue;
-            if (D2DStartAdvertisingPairOnTransport)
-            {
-                if (D2DIsTransportLikeAWDL(i))
-                {
-                    mdns_powerlog_awdl_advertise_start(lower.c, resourceRecord->rrtype, clientPID);
-                }
-                D2DStartAdvertisingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, i);
-            }
-        }
-    }
-    else
-    {
-        if (D2DStartAdvertisingPairOnTransport)
-        {
-            if (D2DIsTransportLikeAWDL(transportType))
-            {
-                mdns_powerlog_awdl_advertise_start(lower.c, resourceRecord->rrtype, clientPID);
-            }
-            D2DStartAdvertisingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, transportType);
-        }
-    }
-}
-
-mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID)
-{
-    internal_stop_advertising_service(resourceRecord, flags, clientPID);
-}
-
-mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(resourceRecord->name, &lower);
-
-    LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "internal_stop_advertising_service: " PRI_S,
-        RRDisplayString(&mDNSStorage, resourceRecord));
-
-    mDNSu8 *const rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
-    const mDNSu8 *const end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
-    const size_t keyLen = (size_t)(rhs - compression_lhs);
-    const size_t valueLen = (size_t)(end - rhs);
-    PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, rhs, (mDNSu16)valueLen);
-
-    transportType = xD2DMapToTransportType(resourceRecord->InterfaceID, flags, & excludedTransport);
-    if (transportType == D2DTransportMax)
-    {
-        D2DTransportType i;
-        for (i = 0; i < D2DTransportMax; i++)
-        {
-            if (i == excludedTransport) continue;
-            if (D2DStopAdvertisingPairOnTransport)
-            {
-                D2DStopAdvertisingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, i);
-                if (D2DIsTransportLikeAWDL(i))
-                {
-                    mdns_powerlog_awdl_advertise_stop(lower.c, resourceRecord->rrtype, clientPID);
-                }
-            }
-        }
-    }
-    else
-    {
-        if (D2DStopAdvertisingPairOnTransport)
-        {
-            D2DStopAdvertisingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, transportType);
-            if (D2DIsTransportLikeAWDL(transportType))
-            {
-                mdns_powerlog_awdl_advertise_stop(lower.c, resourceRecord->rrtype, clientPID);
-            }
-        }
-    }
-}
-
-mDNSexport void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "external_start_resolving_service - "
-        "fqdn: " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-
-    mDNSu8 *const rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
-    const mDNSu8 *const end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
-    const size_t keyLen = (size_t)(rhs - compression_lhs);
-    const size_t valueLen = (size_t)(end - rhs);
-    PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, rhs, (mDNSu16)valueLen);
-
-    transportType = xD2DMapToTransportType(InterfaceID, flags, & excludedTransport);
-    if (transportType == D2DTransportMax)
-    {
-        // Resolving over all the transports, except for excludedTransport if set.
-        D2DTransportType i;
-        for (i = 0; i < D2DTransportMax; i++)
-        {
-            if (i == excludedTransport) continue;
-            if (D2DStartResolvingPairOnTransport)
-            {
-                if (D2DIsTransportLikeAWDL(i))
-                {
-                    mdns_powerlog_awdl_resolve_start(lower.c, kDNSType_PTR, clientPID);
-                }
-                D2DStartResolvingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, i);
-            }
-        }
-    }
-    else
-    {
-        // Resolving over one specific transport.
-        if (D2DStartResolvingPairOnTransport)
-        {
-            if (D2DIsTransportLikeAWDL(transportType))
-            {
-                mdns_powerlog_awdl_resolve_start(lower.c, kDNSType_PTR, clientPID);
-            }
-            D2DStartResolvingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, transportType);
-        }
-    }
-
-}
-
-mDNSexport void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags, pid_t clientPID)
-{
-    domainname lower;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "external_stop_resolving_service - "
-        "fqdn: " PRI_DM_NAME, DM_NAME_PARAM(fqdn));
-
-    mDNSu8 *const rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
-    const mDNSu8 *const end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
-    const size_t keyLen = (size_t)(rhs - compression_lhs);
-    const size_t valueLen = (size_t)(end - rhs);
-    PrintHelper(__func__, compression_lhs, (mDNSu16)keyLen, rhs, (mDNSu16)valueLen);
-
-    transportType = xD2DMapToTransportType(InterfaceID, flags, & excludedTransport);
-    if (transportType == D2DTransportMax)
-    {
-        D2DTransportType i;
-        for (i = 0; i < D2DTransportMax; i++)
-        {
-            if (i == excludedTransport) continue;
-            if (D2DStopResolvingPairOnTransport)
-            {
-                D2DStopResolvingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, i);
-                if (D2DIsTransportLikeAWDL(i))
-                {
-                    mdns_powerlog_awdl_resolve_stop(lower.c, kDNSType_PTR, clientPID);
-                }
-            }
-        }
-    }
-    else
-    {
-        if (D2DStopResolvingPairOnTransport)
-        {
-            D2DStopResolvingPairOnTransport(compression_lhs, keyLen, rhs, valueLen, transportType);
-            if (D2DIsTransportLikeAWDL(transportType))
-            {
-                mdns_powerlog_awdl_resolve_stop(lower.c, kDNSType_PTR, clientPID);
-            }
-        }
-    }
-}
-
-mDNSexport mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags)
-{
-    // Only call D2D layer routines if request applies to a D2D interface and the domain is "local".
-    if (    (((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL | kDNSServiceFlagsAutoTrigger)))
-            || mDNSPlatformInterfaceIsD2D(InterfaceID) || (InterfaceID == mDNSInterface_BLE))
-        && IsLocalDomain(domain))
-    {
-        return mDNStrue;
-    }
-    else
-        return mDNSfalse;
-}
-
-// Used to derive the original D2D specific flags specified by the client in the registration
-// when we don't have access to the original flag (kDNSServiceFlags*) values.
-mDNSexport mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType)
-{
-    mDNSu32 flags = 0;
-    if ((authRecType == AuthRecordAnyIncludeP2P) || (authRecType == AuthRecordAnyIncludeAWDLandP2P))
-        flags |= kDNSServiceFlagsIncludeP2P;
-    else if ((authRecType == AuthRecordAnyIncludeAWDL) || (authRecType == AuthRecordAnyIncludeAWDLandP2P))
-        flags |= kDNSServiceFlagsIncludeAWDL;
-    return flags;
-}
-
-void initializeD2DPlugins(mDNS *const m)
-{
-        // We only initialize if mDNSCore successfully initialized.
-        if (D2DInitialize)
-        {
-            D2DStatus ds = D2DInitialize(CFRunLoopGetMain(), xD2DServiceCallback, m);
-            if (ds != kD2DSuccess)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "D2DInitialiize failed: %d", ds);
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2DInitialize succeeded");
-            }
-        }
-}
-
-void terminateD2DPlugins(void)
-{
-    if (D2DTerminate)
-    {
-        D2DStatus ds = D2DTerminate();
-        if (ds != kD2DSuccess)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_ERROR, "D2DTerminate failed: %d", ds);
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "D2DTerminate succeeded");
-        }
-
-    }
-}
-
-#ifdef UNIT_TEST
-#pragma mark - Unit test support routines
-
-// These unit test support routines are called from unittests/ framework
-// and are not compiled for the mDNSResponder runtime code paths.
-
-void D2D_unitTest(void)
-{
-}
-
-#endif  //  UNIT_TEST
diff --git a/mDNSMacOSX/D2D.h b/mDNSMacOSX/D2D.h
deleted file mode 100644
index 928789b..0000000
--- a/mDNSMacOSX/D2D.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2015-2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef _D2D_H_
-#define _D2D_H_
-
-#include "mDNSEmbeddedAPI.h"        // Defines the interface provided to the client layer above
-#include "dnssd_ipc.h"
-#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
-
-extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID);
-extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID);
-extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID);
-extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID);
-
-void xD2DAddToCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
-void xD2DRemoveFromCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
-
-extern mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags);
-extern mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType);
-extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID);
-extern void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, mDNSu16 qtype, DNSServiceFlags flags, pid_t clientPID);
-extern void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID);
-extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags, pid_t clientPID);
-extern void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags, pid_t clientPID);
-extern void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags, pid_t clientPID);
-extern void external_connection_release(const domainname *instance);
-
-extern void D2D_start_advertising_interface(NetworkInterfaceInfo *interface);
-extern void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface);
-extern void D2D_start_advertising_record(AuthRecord *ar);
-extern void D2D_stop_advertising_record(AuthRecord *ar);
-
-#ifdef UNIT_TEST
-#pragma mark - Unit test declarations
-
-// Unit test entry points, which are not used in the mDNSResponder runtime code paths.
-void D2D_unitTest(void);
-
-#endif  //  UNIT_TEST
-
-#endif /* _D2D_H_ */
diff --git a/mDNSMacOSX/DNS64.c b/mDNSMacOSX/DNS64.c
deleted file mode 100644
index 228b221..0000000
--- a/mDNSMacOSX/DNS64.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Copyright (c) 2017-2021 Apple 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
- *
- *     https://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.
- */
-
-#include "DNS64.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
-
-#include <AssertMacros.h>
-#include <CoreUtils/CommonServices.h>
-#include <nw/private.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dns_sd.h"
-#include "dns_sd_internal.h"
-#include "mDNSMacOSX.h"
-#include "uDNS.h"
-#include "mdns_strict.h"
-
-//===========================================================================================================================
-//  Constants
-//===========================================================================================================================
-
-#define kDNS64IPv4OnlyFQDNString    "\x8" "ipv4only" "\x4" "arpa"
-#define kDNS64IPv4OnlyFQDN          ((const domainname *) kDNS64IPv4OnlyFQDNString)
-#define kDNS64IPv4OnlyFQDNLength    15  // 9 bytes for first label, 5 bytes for second label, and 1 byte for the root label.
-
-check_compile_time(sizeof(kDNS64IPv4OnlyFQDNString) == kDNS64IPv4OnlyFQDNLength);
-check_compile_time(sizeof_field(DNSQuestion, qname) >= kDNS64IPv4OnlyFQDNLength);
-check_compile_time(sizeof_field(DNS64, qnameStash)  == kDNS64IPv4OnlyFQDNLength);
-
-//===========================================================================================================================
-//  Local Prototypes
-//===========================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mStatus   _DNS64GetIPv6Addrs(mDNS *m, mdns_dns_service_t inDNSService, struct in6_addr **outAddrs, uint32_t *outAddrCount);
-#else
-mDNSlocal mStatus   _DNS64GetIPv6Addrs(mDNS *m, mDNSu32 inResGroupID, struct in6_addr **outAddrs, uint32_t *outAddrCount);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mStatus   _DNS64GetPrefixes(mDNS *m, mdns_dns_service_t inDNSService, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount);
-#else
-mDNSlocal mStatus   _DNS64GetPrefixes(mDNS *m, mDNSu32 inResGroupID, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount);
-#endif
-mDNSlocal mDNSu32   _DNS64IPv4OnlyFQDNHash(void);
-mDNSlocal void      _DNS64RestartQuestion(mDNS *m, DNSQuestion *q, DNS64State newState);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mDNSBool  _DNS64InterfaceSupportsNAT64(mdns_dns_service_t inDNSService);
-#else
-mDNSlocal mDNSBool  _DNS64InterfaceSupportsNAT64(uint32_t inIfIndex);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mDNSBool  _DNS64TestIPv6Synthesis(mDNS *m, mdns_dns_service_t inDNSService, const mDNSv4Addr *inV4Addr);
-#else
-mDNSlocal mDNSBool  _DNS64TestIPv6Synthesis(mDNS *m, mDNSu32 inResGroupID, const mDNSv4Addr *inV4Addr);
-#endif
-
-//===========================================================================================================================
-//  DNS64StateMachine
-//===========================================================================================================================
-
-mDNSexport mDNSBool DNS64StateMachine(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult)
-{
-    // If this is an mDNS question, then exit early. DNS64 is only for unicast DNS questions.
-
-    if (mDNSOpaque16IsZero(inQ->TargetQID)) return (mDNSfalse);
-
-    switch (inQ->dns64.state)
-    {
-    // If this question is going to be answered with a negative AAAA record and the question is not for "ipv4only.arpa." and
-    // the question's DNS server's interface supports NAT64, then restart the question as an "ipv4only.arpa." AAAA question.
-    // Otherwise, do nothing.
-
-    case kDNS64State_Initial:
-        if ((inRR->RecordType == kDNSRecordTypePacketNegative) && (inResult == QC_add))
-        {
-            if ((inQ->qtype      == kDNSType_AAAA) &&
-                (inRR->rrtype    == kDNSType_AAAA) &&
-                (inRR->rrclass   == kDNSClass_IN) &&
-                ((inQ->qnamehash != _DNS64IPv4OnlyFQDNHash()) || !SameDomainName(&inQ->qname, kDNS64IPv4OnlyFQDN)) &&
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                inQ->dnsservice && _DNS64InterfaceSupportsNAT64(inQ->dnsservice))
-#else
-                inQ->qDNSServer &&
-                _DNS64InterfaceSupportsNAT64((uint32_t)((uintptr_t)inQ->qDNSServer->interface)))
-#endif
-            {
-                _DNS64RestartQuestion(m, inQ, kDNS64State_PrefixDiscovery);
-                return (mDNStrue);
-            }
-            else if ((inQ->qtype == kDNSType_PTR) &&
-                (inRR->rrtype    == kDNSType_PTR) &&
-                (inRR->rrclass   == kDNSClass_IN) &&
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                inQ->dnsservice && _DNS64InterfaceSupportsNAT64(inQ->dnsservice) &&
-#else
-                inQ->qDNSServer &&
-                _DNS64InterfaceSupportsNAT64((uint32_t)((uintptr_t)inQ->qDNSServer->interface)) &&
-#endif
-                GetReverseIPv6Addr(&inQ->qname, NULL))
-            {
-                _DNS64RestartQuestion(m, inQ, kDNS64State_PrefixDiscoveryPTR);
-                return (mDNStrue);
-            }
-        }
-        break;
-
-    // If the "ipv4only.arpa." question is going to be answered with a positive AAAA record, then restart it as a question
-    // for an A record with the original AAAA qname.
-    // Otherwise, restart the question for the original AAAA record.
-
-    case kDNS64State_PrefixDiscovery:
-        if ((inRR->RecordType != kDNSRecordTypePacketNegative) &&
-            (inResult         == QC_add) &&
-            (inRR->rrtype     == kDNSType_AAAA) &&
-            (inRR->rrclass    == kDNSClass_IN))
-        {
-            _DNS64RestartQuestion(m, inQ, kDNS64State_QueryA);
-        }
-        else
-        {
-            _DNS64RestartQuestion(m, inQ, kDNS64State_QueryAAAA);
-        }
-        return (mDNStrue);
-
-    // The "ipv4only.arpa." question is going to be answered. Restart the question now. DNS64HandleNewQuestion() will decide
-    // whether or not to change it to a reverse IPv4 question.
-
-    case kDNS64State_PrefixDiscoveryPTR:
-        _DNS64RestartQuestion(m, inQ, kDNS64State_QueryPTR);
-        return (mDNStrue);
-
-    // If this question is going to be answered with a CNAME, then do nothing.
-    // If this question is going to be answered with a positive A record that's synthesizable, then set the state to
-    // QueryARecord2.
-    // Otherwise, restart the question for the original AAAA record.
-
-    case kDNS64State_QueryA:
-        if (inRR->rrtype != kDNSType_CNAME)
-        {
-            if ((inRR->RecordType != kDNSRecordTypePacketNegative) &&
-                (inResult         == QC_add) &&
-                (inRR->rrtype     == kDNSType_A) &&
-                (inRR->rrclass    == kDNSClass_IN) &&
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                inQ->dnsservice &&
-                _DNS64TestIPv6Synthesis(m, inQ->dnsservice, &inRR->rdata->u.ipv4))
-#else
-                inQ->qDNSServer &&
-                _DNS64TestIPv6Synthesis(m, inQ->qDNSServer->resGroupID, &inRR->rdata->u.ipv4))
-#endif
-            {
-                inQ->dns64.state = kDNS64State_QueryA2;
-            }
-            else
-            {
-                _DNS64RestartQuestion(m, inQ, kDNS64State_QueryAAAA);
-                return (mDNStrue);
-            }
-        }
-        break;
-
-    // For all other states, do nothing.
-
-    case kDNS64State_QueryA2:
-    case kDNS64State_QueryAAAA:
-    case kDNS64State_QueryPTR:
-    case kDNS64State_ReverseIPv4:
-    case kDNS64State_ReverseIPv6:
-        break;
-
-    CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-    default:
-    CUClangWarningIgnoreEnd();
-        LogMsg("DNS64StateMachine: unrecognized DNS64 state %d", inQ->dns64.state);
-        break;
-    }
-
-    return (mDNSfalse);
-}
-
-//===========================================================================================================================
-//  DNS64AnswerCurrentQuestion
-//===========================================================================================================================
-
-mDNSexport mStatus DNS64AnswerCurrentQuestion(mDNS *m, const ResourceRecord *inRR, QC_result inResult)
-{
-    mStatus                 err;
-    ResourceRecord          newRR;
-    RData                   rdata;
-    nw_nat64_prefix_t *     prefixes = NULL;
-    uint32_t                prefixCount;
-    uint32_t                i;
-    struct in_addr          v4Addr;
-    struct in6_addr         synthV6;
-    DNSQuestion * const     q = m->CurrentQuestion;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    require_action_quiet(q->dnsservice, exit, err = mStatus_BadParamErr);
-#else
-    require_action_quiet(q->qDNSServer, exit, err = mStatus_BadParamErr);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    err = _DNS64GetPrefixes(m, q->dnsservice, &prefixes, &prefixCount);
-#else
-    err = _DNS64GetPrefixes(m, q->qDNSServer->resGroupID, &prefixes, &prefixCount);
-#endif
-    require_noerr_quiet(err, exit);
-
-    newRR               = *inRR;
-    newRR.rrtype        = kDNSType_AAAA;
-    newRR.rdlength      = 16;
-    rdata.MaxRDLength   = newRR.rdlength;
-    newRR.rdata         = &rdata;
-
-    memcpy(&v4Addr.s_addr, inRR->rdata->u.ipv4.b, 4);
-    for (i = 0; i < prefixCount; i++)
-    {
-        if (nw_nat64_synthesize_v6(&prefixes[i], &v4Addr, &synthV6))
-        {
-            memcpy(rdata.u.ipv6.b, synthV6.s6_addr, 16);
-            q->QuestionCallback(m, q, &newRR, inResult);
-            if (m->CurrentQuestion != q) break;
-        }
-    }
-    err = mStatus_NoError;
-
-exit:
-    ForgetMem(&prefixes);
-    return (err);
-}
-
-//===========================================================================================================================
-//  DNS64HandleNewQuestion
-//===========================================================================================================================
-
-mDNSexport void DNS64HandleNewQuestion(mDNS *m, DNSQuestion *inQ)
-{
-    if (inQ->dns64.state == kDNS64State_QueryPTR)
-    {
-        struct in6_addr     v6Addr;
-
-        inQ->dns64.state = kDNS64State_ReverseIPv6;
-        memset(&v6Addr, 0, sizeof(v6Addr));
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (inQ->dnsservice && GetReverseIPv6Addr(&inQ->qname, v6Addr.s6_addr))
-#else
-        if (inQ->qDNSServer && GetReverseIPv6Addr(&inQ->qname, v6Addr.s6_addr))
-#endif
-        {
-            mStatus                 err;
-            nw_nat64_prefix_t *     prefixes;
-            uint32_t                prefixCount;
-            uint32_t                i;
-            struct in_addr          v4Addr;
-            char                    qnameStr[MAX_REVERSE_MAPPING_NAME_V4];
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            err = _DNS64GetPrefixes(m, inQ->dnsservice, &prefixes, &prefixCount);
-#else
-            err = _DNS64GetPrefixes(m, inQ->qDNSServer->resGroupID, &prefixes, &prefixCount);
-#endif
-            require_noerr_quiet(err, exit);
-
-            for (i = 0; i < prefixCount; i++)
-            {
-                if (nw_nat64_extract_v4(&prefixes[i], &v6Addr, &v4Addr))
-                {
-                    const mDNSu8 * const        a = (const mDNSu8 *)&v4Addr.s_addr;
-
-                    snprintf(qnameStr, sizeof(qnameStr), "%u.%u.%u.%u.in-addr.arpa.", a[3], a[2], a[1], a[0]);
-                    MakeDomainNameFromDNSNameString(&inQ->qname, qnameStr);
-                    inQ->qnamehash   = DomainNameHashValue(&inQ->qname);
-                    inQ->dns64.state = kDNS64State_ReverseIPv4;
-                    break;
-                }
-            }
-            ForgetMem(&prefixes);
-        }
-    }
-
-exit:
-    return;
-}
-
-//===========================================================================================================================
-//  DNS64ResetState
-//===========================================================================================================================
-
-// Called from mDNS_StopQuery_internal().
-
-mDNSexport void DNS64ResetState(DNSQuestion *inQ)
-{
-    switch (inQ->dns64.state)
-    {
-    case kDNS64State_PrefixDiscoveryPTR:
-        inQ->qtype = kDNSType_PTR;  // Restore qtype to PTR and fall through.
-
-    case kDNS64State_PrefixDiscovery:
-        memcpy(&inQ->qname, inQ->dns64.qnameStash, sizeof(inQ->dns64.qnameStash));  // Restore the previous qname.
-        inQ->qnamehash = DomainNameHashValue(&inQ->qname);
-        break;
-
-    case kDNS64State_QueryA:
-    case kDNS64State_QueryA2:
-        inQ->qtype = kDNSType_AAAA; // Restore qtype to AAAA.
-        break;
-
-    // Do nothing for the other states.
-
-    case kDNS64State_Initial:
-    case kDNS64State_QueryAAAA:
-    case kDNS64State_QueryPTR:
-    case kDNS64State_ReverseIPv4:
-    case kDNS64State_ReverseIPv6:
-        break;
-
-    CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-    default:
-    CUClangWarningIgnoreEnd();
-        LogMsg("DNS64ResetState: unrecognized DNS64 state %d", inQ->dns64.state);
-        break;
-    }
-    inQ->dns64.state = kDNS64State_Initial;
-}
-
-//===========================================================================================================================
-//  DNS64RestartQuestions
-//===========================================================================================================================
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport void DNS64RestartQuestions(mDNS *m)
-{
-    DNSQuestion *       q;
-    DNSQuestion *       restartList = NULL;
-    DNSServer *         newServer;
-
-    m->RestartQuestion = m->Questions;
-    while (m->RestartQuestion)
-    {
-        q = m->RestartQuestion;
-        m->RestartQuestion = q->next;
-        if (q->dns64.state != kDNS64State_Initial)
-        {
-            SetValidDNSServers(m, q);
-            q->triedAllServersOnce = mDNSfalse;
-            newServer = GetServerForQuestion(m, q);
-            if (q->qDNSServer != newServer)
-            {
-                if (!CacheRecordRmvEventsForQuestion(m, q))
-                {
-                    LogInfo("DNS64RestartQuestions: Question deleted while delivering RMV events from cache");
-                }
-                else
-                {
-                    LogInfo("DNS64RestartQuestions: Stop question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-                    mDNS_StopQuery_internal(m, q);
-                    q->next = restartList;
-                    restartList = q;
-                }
-            }
-        }
-    }
-    while ((q = restartList) != NULL)
-    {
-        restartList = restartList->next;
-        q->next = NULL;
-        LogInfo("DNS64RestartQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
-        mDNS_StartQuery_internal(m, q);
-    }
-}
-#endif
-
-//===========================================================================================================================
-//  _DNS64GetIPv6Addrs
-//===========================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#define IsPositiveAAAAFromDNSService(RR, DNS_SERVICE)       \
-    (((RR)->dnsservice == (DNS_SERVICE))  &&                \
-    ((RR)->rrtype == kDNSType_AAAA) &&                      \
-    ((RR)->RecordType != kDNSRecordTypePacketNegative) &&   \
-    !(RR)->InterfaceID)
-#else
-#define IsPositiveAAAAFromResGroup(RR, RES_GROUP_ID)        \
-    ((RR)->rDNSServer &&                                    \
-    ((RR)->rDNSServer->resGroupID == RES_GROUP_ID) &&       \
-    ((RR)->rrtype == kDNSType_AAAA) &&                      \
-    ((RR)->RecordType != kDNSRecordTypePacketNegative) &&   \
-    !(RR)->InterfaceID)
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mStatus _DNS64GetIPv6Addrs(mDNS *m, mdns_dns_service_t inDNSService, struct in6_addr **outAddrs, uint32_t *outAddrCount)
-#else
-mDNSlocal mStatus _DNS64GetIPv6Addrs(mDNS *m, const mDNSu32 inResGroupID, struct in6_addr **outAddrs, uint32_t *outAddrCount)
-#endif
-{
-    mStatus                 err;
-    const CacheGroup *      cg;
-    const CacheRecord *     cr;
-    struct in6_addr *       addrs = NULL;
-    uint32_t                addrCount;
-    uint32_t                recordCount;
-
-    cg = CacheGroupForName(m, _DNS64IPv4OnlyFQDNHash(), kDNS64IPv4OnlyFQDN);
-    require_action_quiet(cg, exit, err = mStatus_NoSuchRecord);
-
-    recordCount = 0;
-    for (cr = cg->members; cr; cr = cr->next)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (IsPositiveAAAAFromDNSService(&cr->resrec, inDNSService))
-#else
-        if (IsPositiveAAAAFromResGroup(&cr->resrec, inResGroupID))
-#endif
-        {
-            recordCount++;
-        }
-    }
-    require_action_quiet(recordCount > 0, exit, err = mStatus_NoSuchRecord);
-
-    addrs = (struct in6_addr *)mdns_calloc(recordCount, sizeof(*addrs));
-    require_action_quiet(addrs, exit, err = mStatus_NoMemoryErr);
-
-    addrCount = 0;
-    for (cr = cg->members; cr && (addrCount < recordCount); cr = cr->next)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        if (IsPositiveAAAAFromDNSService(&cr->resrec, inDNSService))
-#else
-        if (IsPositiveAAAAFromResGroup(&cr->resrec, inResGroupID))
-#endif
-        {
-            memcpy(addrs[addrCount].s6_addr, cr->resrec.rdata->u.ipv6.b, 16);
-            addrCount++;
-        }
-    }
-
-    *outAddrs = addrs;
-    addrs = NULL;
-    *outAddrCount = addrCount;
-    err = mStatus_NoError;
-
-exit:
-    ForgetMem(&addrs);
-    return (err);
-}
-
-//===========================================================================================================================
-//  _DNS64GetPrefixes
-//===========================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mStatus _DNS64GetPrefixes(mDNS *m, mdns_dns_service_t inDNSService, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount)
-#else
-mDNSlocal mStatus _DNS64GetPrefixes(mDNS *m, mDNSu32 inResGroupID, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount)
-#endif
-{
-    mStatus                 err;
-    struct in6_addr *       v6Addrs;
-    uint32_t                v6AddrCount;
-    nw_nat64_prefix_t *     prefixes;
-    int32_t                 prefixCount;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    err = _DNS64GetIPv6Addrs(m, inDNSService, &v6Addrs, &v6AddrCount);
-#else
-    err = _DNS64GetIPv6Addrs(m, inResGroupID, &v6Addrs, &v6AddrCount);
-#endif
-    require_noerr_quiet(err, exit);
-
-    prefixCount = nw_nat64_copy_prefixes_from_ipv4only_records(v6Addrs, v6AddrCount, &prefixes);
-    ForgetMem(&v6Addrs);
-    require_action_quiet(prefixCount > 0, exit, err = mStatus_UnknownErr);
-
-    *outPrefixes    = prefixes;
-    *outPrefixCount = (uint32_t)prefixCount;
-
-exit:
-    return (err);
-}
-
-//===========================================================================================================================
-//  _DNS64IPv4OnlyFQDNHash
-//===========================================================================================================================
-
-mDNSlocal mDNSu32 _DNS64IPv4OnlyFQDNHash(void)
-{
-    static dispatch_once_t      sHashOnce;
-    static mDNSu32              sHash;
-
-    dispatch_once(&sHashOnce, ^{ sHash = DomainNameHashValue(kDNS64IPv4OnlyFQDN); });
-
-    return (sHash);
-}
-
-//===========================================================================================================================
-//  _DNS64RestartQuestion
-//===========================================================================================================================
-
-mDNSlocal void _DNS64RestartQuestion(mDNS *const m, DNSQuestion *inQ, DNS64State inNewState)
-{
-    mDNS_StopQuery_internal(m, inQ);
-
-    inQ->dns64.state = inNewState;
-    switch (inQ->dns64.state)
-    {
-    case kDNS64State_Initial:
-        break;
-
-    case kDNS64State_PrefixDiscovery:
-    case kDNS64State_PrefixDiscoveryPTR:
-        // Save the first 15 bytes from the original qname that are displaced by setting qname to "ipv4only.arpa.".
-
-        memcpy(inQ->dns64.qnameStash, &inQ->qname, sizeof(inQ->dns64.qnameStash));
-        AssignDomainName(&inQ->qname, kDNS64IPv4OnlyFQDN);
-        inQ->qnamehash = _DNS64IPv4OnlyFQDNHash();
-        inQ->qtype = kDNSType_AAAA;
-        break;
-
-    case kDNS64State_QueryA:
-    case kDNS64State_QueryA2:
-        inQ->qtype = kDNSType_A;
-        break;
-
-    case kDNS64State_QueryPTR:
-    case kDNS64State_ReverseIPv4:
-    case kDNS64State_ReverseIPv6:
-        inQ->qtype = kDNSType_PTR;
-        break;
-
-    case kDNS64State_QueryAAAA:
-        inQ->qtype = kDNSType_AAAA;
-        break;
-
-    CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-    default:
-    CUClangWarningIgnoreEnd();
-        LogMsg("DNS64RestartQuestion: unrecognized DNS64 state %d", inQ->dns64.state);
-        break;
-    }
-
-    mDNS_StartQuery_internal(m, inQ);
-}
-
-//===========================================================================================================================
-//  _DNS64InterfaceSupportsNAT64
-//===========================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mDNSBool _DNS64InterfaceSupportsNAT64(mdns_dns_service_t inDNSService)
-{
-    if (mdns_dns_service_is_default(inDNSService) && !mdns_dns_service_interface_has_ipv4_connectivity(inDNSService) &&
-        mdns_dns_service_interface_has_ipv6_connectivity(inDNSService))
-    {
-        return (mDNStrue);
-    }
-    else
-    {
-        return (mDNSfalse);
-    }
-}
-#else
-mDNSlocal mDNSBool _DNS64InterfaceSupportsNAT64(uint32_t inIfIndex)
-{
-    mdns_interface_monitor_t monitor = GetInterfaceMonitorForIndex(inIfIndex);
-    if (monitor && !mdns_interface_monitor_has_ipv4_connectivity(monitor) &&
-        mdns_interface_monitor_has_ipv6_connectivity(monitor))
-    {
-        return (mDNStrue);
-    }
-    return (mDNSfalse);
-}
-#endif
-
-//===========================================================================================================================
-//  _DNS64TestIPv6Synthesis
-//===========================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal mDNSBool _DNS64TestIPv6Synthesis(mDNS *m, mdns_dns_service_t inDNSService, const mDNSv4Addr *inV4Addr)
-#else
-mDNSlocal mDNSBool _DNS64TestIPv6Synthesis(mDNS *m, mDNSu32 inResGroupID, const mDNSv4Addr *inV4Addr)
-#endif
-{
-    mStatus                 err;
-    nw_nat64_prefix_t *     prefixes    = NULL;
-    uint32_t                prefixCount;
-    uint32_t                i;
-    struct in_addr          v4Addr;
-    struct in6_addr         synthV6;
-    mDNSBool                result      = mDNSfalse;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    err = _DNS64GetPrefixes(m, inDNSService, &prefixes, &prefixCount);
-#else
-    err = _DNS64GetPrefixes(m, inResGroupID, &prefixes, &prefixCount);
-#endif
-    require_noerr_quiet(err, exit);
-
-    memcpy(&v4Addr.s_addr, inV4Addr->b, 4);
-    for (i = 0; i < prefixCount; i++)
-    {
-        if (nw_nat64_synthesize_v6(&prefixes[i], &v4Addr, &synthV6))
-        {
-            result = mDNStrue;
-            break;
-        }
-    }
-
-exit:
-    ForgetMem(&prefixes);
-    return (result);
-}
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
diff --git a/mDNSMacOSX/DNS64.h b/mDNSMacOSX/DNS64.h
deleted file mode 100644
index 2e21613..0000000
--- a/mDNSMacOSX/DNS64.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Apple 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.
- */
-
-#ifndef __DNS64_h
-#define __DNS64_h
-
-#include "mDNSEmbeddedAPI.h"
-
-#define DNS64IsQueryingARecord(STATE)       (((STATE) == kDNS64State_QueryA) || ((STATE) == kDNS64State_QueryA2))
-#define DNS64ShouldAnswerQuestion(Q, RR)    (DNS64IsQueryingARecord((Q)->dns64.state) && ((RR)->rrtype == kDNSType_A))
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-mDNSexport mDNSBool DNS64StateMachine(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult);
-mDNSexport mStatus  DNS64AnswerCurrentQuestion(mDNS *m, const ResourceRecord *inRR, QC_result inResult);
-mDNSexport void     DNS64HandleNewQuestion(mDNS *m, DNSQuestion *inQ);
-mDNSexport void     DNS64ResetState(DNSQuestion *inQ);
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport void     DNS64RestartQuestions(mDNS *m);
-#endif
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif // __DNS64_h
diff --git a/mDNSMacOSX/DNS64State.h b/mDNSMacOSX/DNS64State.h
deleted file mode 100644
index 1a84790..0000000
--- a/mDNSMacOSX/DNS64State.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017 Apple 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.
- */
-
-#ifndef __DNS64State_h
-#define __DNS64State_h
-
-typedef enum
-{
-    kDNS64State_Initial             = 0,    // Initial state.
-    kDNS64State_PrefixDiscovery     = 1,    // Querying for "ipv4only.arpa." AAAA records to discover NAT64 IPv6 prefix(es).
-    kDNS64State_PrefixDiscoveryPTR  = 2,    // Same as PrefixDiscovery, but discoverying for "ip6.arpa." PTR record queries.
-    kDNS64State_QueryA              = 3,    // Querying for A record with same QNAME as AAAA record query.
-    kDNS64State_QueryA2             = 4,    // Continuing A record query after being answered with a synthesizable A record.
-    kDNS64State_QueryAAAA           = 5,    // Querying for original AAAA record.
-    kDNS64State_QueryPTR            = 6,    // Determining whether to query for reverse IPV4 or reverse IPv6 PTR record.
-    kDNS64State_ReverseIPv4         = 7,    // Querying for reverse IPV4 (in-addr.arpa.) PTR record.
-    kDNS64State_ReverseIPv6         = 8     // Querying for the original reverse IPv6 (ip6.arpa.) PTR record.
-
-}   DNS64State;
-
-typedef struct
-{
-    DNS64State      state;          // Current state.
-    mDNSu8          qnameStash[15]; // Temporary space to hold the up to 15 bytes that are displaced in a DNSQuestion's qname
-                                    // when it's set to "ipv4only.arpa." during prefix discovery.
-}   DNS64;
-
-#endif // __DNS64State_h
diff --git a/mDNSMacOSX/DNSProxySupport.c b/mDNSMacOSX/DNSProxySupport.c
deleted file mode 100644
index 99a744a..0000000
--- a/mDNSMacOSX/DNSProxySupport.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Copyright (c) 2011-2020 Apple 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.
- */
-
-#include "mDNSEmbeddedAPI.h"
-#include "mDNSMacOSX.h"
-#include "mdns_strict.h"
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/event.h>
-#include <netinet/tcp.h>
-
-extern mDNS mDNSStorage;
-
-#define ValidSocket(s) ((s) >= 0)
-
-// Global to store the 4 DNS Proxy Listeners (UDPv4/6, TCPv4/6)
-static int dp_listener[4];
-
-#define NUM_PROXY_TCP_CONNS 100
-
-typedef struct
-{
-    TCPSocket   sock;
-    DNSMessage  *reply;
-    mDNSu16     replyLen;
-    mDNSu32     nread;
-} ProxyTCPInfo_t;
-
-// returns -1 for failures including the other end closing the socket
-// returns 0 if successful in reading data, but still not read the data fully
-// returns 1 if successful in reading all the data
-mDNSlocal int ProxyTCPRead(ProxyTCPInfo_t *tcpInfo)
-{
-    long n;
-    mDNSBool closed; 
-
-    if (tcpInfo->nread < 2)         // First read the two-byte length preceeding the DNS message
-    {
-        mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replyLen;
-        n = mDNSPlatformReadTCP(&tcpInfo->sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed);
-        if (n < 0 || closed)
-        {
-            LogMsg("ProxyTCPRead: attempt to read message length failed");
-            return -1;
-        }
-
-        tcpInfo->nread += (unsigned long)n;
-        if (tcpInfo->nread < 2)
-        {
-            LogMsg("ProxyTCPRead: nread %d, n %d", tcpInfo->nread, n);
-            return 0;
-        }
-
-        tcpInfo->replyLen = (mDNSu16)((mDNSu16)lenptr[0] << 8 | lenptr[1]);
-        if (tcpInfo->replyLen < sizeof(DNSMessageHeader))
-        {
-            LogMsg("ProxyTCPRead: Message length too short (%d bytes)", tcpInfo->replyLen);
-            return -1;
-        }
-
-        tcpInfo->reply = (DNSMessage *) mallocL("ProxyTCPInfo", tcpInfo->replyLen);
-        if (!tcpInfo->reply)
-        {
-            LogMsg("ProxyTCPRead: Memory failure");
-            return -1;
-        }
-    }
-
-    n = mDNSPlatformReadTCP(&tcpInfo->sock, ((char *)tcpInfo->reply) + (tcpInfo->nread - 2), tcpInfo->replyLen - (tcpInfo->nread - 2), &closed);
-
-    if (n < 0 || closed)
-    {
-        LogMsg("ProxyTCPRead: read failure n %d, closed %d", n, closed);
-        return -1;
-    }
-    tcpInfo->nread += (unsigned long)n;
-    if ((tcpInfo->nread - 2) != tcpInfo->replyLen)
-        return 0;
-    else 
-        return 1;
-}
-
-mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
-{
-    int ret;
-    struct sockaddr_storage from;
-    struct sockaddr_storage to;
-    mDNSAddr senderAddr, destAddr;
-    mDNSIPPort senderPort;
-    ProxyTCPInfo_t *ti = (ProxyTCPInfo_t *)context;
-    TCPSocket *sock = &ti->sock;
-    struct tcp_info tcp_if;
-    socklen_t size = sizeof(tcp_if);
-    int32_t intf_id = 0;
-
-    (void) filter;
-
-    ret = ProxyTCPRead(ti);
-    if (ret == -1)
-    {
-        mDNSPlatformDisposeProxyContext(ti);
-        return; 
-    }
-    else if (!ret)
-    {
-        debugf("ProxyTCPReceive: Not yet read completely Actual length %d, Read length %d", ti->replyLen, ti->nread);
-        return;
-    }
-    // We read all the data and hence not interested in read events anymore
-    KQueueSet(s1, EV_DELETE, EVFILT_READ, &sock->kqEntry);
-
-    mDNSPlatformMemZero(&to, sizeof(to));
-    mDNSPlatformMemZero(&from, sizeof(from));
-    socklen_t len = sizeof(to);
-    ret = getsockname(s1, (struct sockaddr*) &to, &len);
-    if (ret < 0)
-    {
-        LogMsg("ProxyTCPReceive: getsockname(fd=%d) errno %d", s1, errno);
-        mDNSPlatformDisposeProxyContext(ti);
-        return;
-    }
-    ret = getpeername(s1, (struct sockaddr*) &from, &len);
-    if (ret < 0)
-    {
-        LogMsg("ProxyTCPReceive: getpeername(fd=%d) errno %d", s1, errno);
-        mDNSPlatformDisposeProxyContext(ti);
-        return;
-    }
-    if (getsockopt(s1, IPPROTO_TCP, TCP_INFO, &tcp_if, &size) != 0)
-    {
-        LogMsg("ProxyTCPReceive: getsockopt for TCP_INFO failed (fd=%d) errno %d", s1, errno);
-        return;
-    }
-    intf_id = tcp_if.tcpi_last_outif;
-
-    if (from.ss_family == AF_INET)
-    {
-        struct sockaddr_in *s = (struct sockaddr_in*)&from;
-
-        senderAddr.type = mDNSAddrType_IPv4;
-        senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
-        senderPort.NotAnInteger = s->sin_port;
-
-        s = (struct sockaddr_in *)&to;
-        destAddr.type = mDNSAddrType_IPv4;
-        destAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
-
-        LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
-                ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
-    }
-    else if (from.ss_family == AF_INET6)
-    {
-        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
-        senderAddr.type = mDNSAddrType_IPv6;
-        senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
-        senderPort.NotAnInteger = sin6->sin6_port;
-
-        sin6 = (struct sockaddr_in6 *)&to;
-        destAddr.type = mDNSAddrType_IPv6;
-        destAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
-
-        LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
-                ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
-    }
-    else
-    {
-        LogMsg("ProxyTCPReceive from is unknown address family %d", from.ss_family);
-        mDNSPlatformDisposeProxyContext(ti);
-        return;
-    }
-
-    // We pass sock for the TCPSocket and the "ti" for context as that's what we want to free at the end.
-    // In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument)
-    // would be NULL.
-    ti->sock.m->p->TCPProxyCallback(sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr,
-        UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti);
-}
-
-mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
-{
-    int newfd;
-    struct sockaddr_storage ss;
-    socklen_t sslen = sizeof(ss);
-    const int on = 1;
-    TCPSocket *listenSock = (TCPSocket *)context;
-
-    (void) filter;
-
-    while ((newfd = accept(s1, (struct sockaddr *)&ss, &sslen)) != -1)
-    {
-        int err;
-
-        // Even though we just need a single KQueueEntry, for simplicity we re-use
-        // the KQSocketSet
-        ProxyTCPInfo_t * const ti = (ProxyTCPInfo_t *)callocL("ProxyTCPContext", sizeof(*ti));
-        if (!ti)
-        {
-            LogMsg("ProxyTCPAccept: cannot allocate TCPSocket");
-            close(newfd);
-            return;
-        }
-        TCPSocket * const sock = &ti->sock;
-        sock->fd = -1;
-        sock->m  = listenSock->m;
-
-        fcntl(newfd, F_SETFL, fcntl(newfd, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
-        if (ss.ss_family == AF_INET)
-        {
-            // Receive interface identifiers
-            err = setsockopt(newfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
-            if (err)
-            {
-                LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd, errno, strerror(errno));
-                mDNSPlatformDisposeProxyContext(ti);
-                close(newfd);
-                return;
-            }
-        }
-        else
-        {
-            // We want to receive destination addresses and receive interface identifiers
-            err = setsockopt(newfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-            if (err)
-            {
-                LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd, errno, strerror(errno));
-                mDNSPlatformDisposeProxyContext(ti);
-                close(newfd);
-                return;
-            }
-        }
-        // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
-        // from which we can infer the destination address family. Hence we need to remember that here.
-        // Instead of remembering the address family, we remember the right fd.
-        sock->fd = newfd;
-        sock->kqEntry.KQcallback = ProxyTCPSocketCallBack;
-        sock->kqEntry.KQcontext  = ti;
-        sock->kqEntry.KQtask     = "TCP Proxy packet reception";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        sock->kqEntry.readSource = mDNSNULL;
-        sock->kqEntry.writeSource = mDNSNULL;
-        sock->kqEntry.fdClosed = mDNSfalse;
-#endif
-        sock->connected = mDNStrue;
-        sock->m = listenSock->m;
-        KQueueSet(newfd, EV_ADD, EVFILT_READ, &sock->kqEntry);
-    }
-}
-
-mDNSlocal mStatus SetupUDPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
-{
-    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
-    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
-    const int on = 1;
-    mStatus err = mStatus_NoError;
-
-    cp->m = &mDNSStorage;
-    cp->closeFlag = mDNSNULL;
-
-    // set default traffic class
-    // setTrafficClass(skt, mDNSfalse);
-    (void) useBackgroundTrafficClass;
-
-    if (sa_family == AF_INET)
-    {
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
-        if (err < 0)
-        {
-            LogMsg("SetupUDPProxySocket: IP_RECVDSTADDR %d errno %d (%s)", skt, errno, strerror(errno));
-            return err;
-        }
-
-        // We want to receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
-        if (err < 0)
-        {
-            LogMsg("SetupUDPProxySocket: IP_RECVIF %d errno %d (%s)", skt, errno, strerror(errno));
-            return err;
-        }
-    }
-    else if (sa_family == AF_INET6)
-    {
-        // We want to receive destination addresses and receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-        if (err < 0)
-        {
-            LogMsg("SetupUDPProxySocket: IPV6_RECVPKTINFO %d errno %d (%s)", skt, errno, strerror(errno));
-            return err;
-        }
-
-        // We want to receive packet hop count value so we can check it
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
-        if (err < 0)
-        {
-            LogMsg("SetupUDPProxySocket: IPV6_RECVHOPLIMIT %d errno %d (%s)", skt, errno, strerror(errno));
-            return err;
-        }
-    }
-    else
-    {
-        LogMsg("SetupUDPProxySocket: wrong family %d", sa_family);
-        return -1;
-    }
-
-    if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) < 0)
-    {
-        LogMsg("SetupUDPProxySocket: fnctl failed %d", errno);
-        return -1;
-    }
-
-    *s = skt;
-    //k->KQcallback = ProxyUDPSocketCallBack;
-    k->KQcallback  = myKQSocketCallBack;
-    k->KQcontext   = cp;
-    k->KQtask      = "UDP Proxy packet reception";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    k->readSource  = mDNSNULL;
-    k->writeSource = mDNSNULL;
-    k->fdClosed    = mDNSfalse;
-#endif
-
-    KQueueSet(*s, EV_ADD, EVFILT_READ, k);
-
-    return(err);
-}
-
-mDNSlocal mStatus SetupTCPProxySocket(int skt, TCPSocket *sock, u_short sa_family, mDNSBool useBackgroundTrafficClass)
-{
-    mStatus err;
-    mDNS *m = &mDNSStorage;
-
-    // for TCP sockets, the traffic class is set once and not changed
-    // setTrafficClass(skt, useBackgroundTrafficClass);
-    (void) useBackgroundTrafficClass;
-    (void) sa_family;
-
-    // All the socket setup has already been done 
-    err = listen(skt, NUM_PROXY_TCP_CONNS);
-    if (err)
-    {
-        LogMsg("SetupTCPProxySocket: listen %d errno %d (%s)", skt, errno, strerror(errno));
-        return err;
-    }
-    fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
-    
-    sock->fd = skt;
-    sock->kqEntry.KQcallback  = ProxyTCPAccept;
-    sock->kqEntry.KQcontext   = sock;
-    sock->kqEntry.KQtask      = "TCP Accept";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    sock->kqEntry.readSource  = mDNSNULL;
-    sock->kqEntry.writeSource = mDNSNULL;
-    sock->kqEntry.fdClosed    = mDNSfalse;
-#endif
-    sock->m = m;
-    KQueueSet(skt, EV_ADD, EVFILT_READ, &sock->kqEntry);
-    return mStatus_NoError;
-}
-
-mDNSlocal void BindDPSocket(int fd, int sa_family, int type)
-{
-    int err;
-    const int on = 1;
-
-    if (type == SOCK_STREAM)
-    {
-        err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-        if (err != 0)
-        {
-            const int setsockopt_errno = errno;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "BindDPSocket: setsockopt SO_REUSEADDR failed for " PUB_S " %d errno %d (" PUB_S ")",
-                (sa_family == AF_INET) ? "IPv4" : "IPv6", fd, setsockopt_errno, strerror(setsockopt_errno));
-            return;
-        }
-    }
-    if (sa_family == AF_INET)
-    {
-        struct sockaddr_in addr;
-
-        memset(&addr, 0, sizeof(addr));
-        addr.sin_family = AF_INET;
-        addr.sin_port = htons(53);
-
-        err = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
-        if (err)
-        {
-            LogMsg("BindDPSocket: bind %d errno %d (%s)", fd, errno, strerror(errno));
-            return;
-        }
-    }
-    else
-    {
-        struct sockaddr_in6 addr6;
-
-        // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
-        // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
-        err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
-        if (err < 0)
-        {
-            LogMsg("DPFBindSocket: setsockopt IPV6_V6ONLY %d errno %d (%s)", fd, errno, strerror(errno));
-            return;
-        }
-        memset(&addr6, 0, sizeof(addr6));
-        addr6.sin6_family = AF_INET6;
-        addr6.sin6_port = htons(53);
-
-        err = bind(fd, (struct sockaddr*) &addr6, sizeof(addr6));
-        if (err)
-        {
-            LogMsg("BindDPSocket: bind6 %d errno %d (%s)", fd, errno, strerror(errno));
-            return;
-        }
-    }
-}
-
-// Setup DNS Proxy Skts in main kevent loop and set the skt options
-mDNSlocal void SetupDNSProxySkts(int fd[4])
-{
-    mDNS *const m = &mDNSStorage;
-    int i;
-    mStatus err;
-    KQSocketSet *udpSS;
-    TCPSocket *v4, *v6;
-
-    udpSS       = &m->p->UDPProxy.ss;
-    udpSS->port = UnicastDNSPort;
-    v4 = &m->p->TCPProxyV4;
-    v6 = &m->p->TCPProxyV6;
-    v4->m = m;
-    v4->port = UnicastDNSPort;
-    v6->m = m;
-    v6->port = UnicastDNSPort;
-
-    LogMsg("SetupDNSProxySkts: %d, %d, %d, %d", fd[0], fd[1], fd[2], fd[3]);
-
-    // myKQSocketCallBack checks for proxy and calls the m->p->ProxyCallback instead of mDNSCoreReceive
-    udpSS->proxy = mDNStrue;
-    err = SetupUDPProxySocket(fd[0], udpSS, AF_INET, mDNSfalse);
-    if (err)
-        LogMsg("SetupDNSProxySkts: ERROR!! UDPv4 Socket");
-
-    err = SetupUDPProxySocket(fd[1], udpSS, AF_INET6, mDNSfalse);
-    if (err)
-        LogMsg("SetupDNSProxySkts: ERROR!! UDPv6 Socket");
-
-    err = SetupTCPProxySocket(fd[2], v4, AF_INET, mDNSfalse);
-    if (err)
-        LogMsg("SetupDNSProxySkts: ERROR!! TCPv4 Socket");
-
-    err = SetupTCPProxySocket(fd[3], v6, AF_INET6, mDNSfalse);
-    if (err)
-        LogMsg("SetupDNSProxySkts: ERROR!! TCPv6 Socket");
-
-    for (i = 0; i < 4; i++)
-        dp_listener[i] = fd[i];   
-} 
-
-// Create and bind the DNS Proxy Skts for use
-mDNSexport void mDNSPlatformInitDNSProxySkts(ProxyCallback UDPCallback, ProxyCallback TCPCallback)
-{
-    int dpskt[4];
-    
-    dpskt[0] = socket(AF_INET,  SOCK_DGRAM,  IPPROTO_UDP);
-    dpskt[1] = socket(AF_INET6, SOCK_DGRAM,  IPPROTO_UDP);
-    dpskt[2] = socket(AF_INET,  SOCK_STREAM, IPPROTO_TCP);
-    dpskt[3] = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
-
-    // Close all DNS Proxy skts in case any of them are invalid
-    if (!ValidSocket(dpskt[0]) || !ValidSocket(dpskt[1]) ||
-        !ValidSocket(dpskt[2]) || !ValidSocket(dpskt[3]))
-    {   
-        if (ValidSocket(dpskt[0]))
-            close(dpskt[0]);
-        if (ValidSocket(dpskt[1]))
-            close(dpskt[1]);
-        if (ValidSocket(dpskt[2]))
-            close(dpskt[2]);
-        if (ValidSocket(dpskt[3]))
-            close(dpskt[3]);
-    }
-
-    BindDPSocket(dpskt[0], AF_INET, SOCK_DGRAM);
-    BindDPSocket(dpskt[1], AF_INET6, SOCK_DGRAM);
-    BindDPSocket(dpskt[2], AF_INET, SOCK_STREAM);
-    BindDPSocket(dpskt[3], AF_INET6, SOCK_STREAM);
-
-    LogInfo("mDNSPlatformInitDNSProxySkts: Opened Listener Sockets for DNS Proxy : %d, %d, %d, %d", 
-             dpskt[0], dpskt[1], dpskt[2], dpskt[3]);
-
-    mDNSStorage.p->UDPProxyCallback = UDPCallback;
-    mDNSStorage.p->TCPProxyCallback = TCPCallback;
-
-    SetupDNSProxySkts(dpskt);
-}
-
-mDNSexport void mDNSPlatformCloseDNSProxySkts(mDNS *const m)
-{
-    (void) m;
-    int i;
-    for (i = 0; i < 4; i++)
-        close(dp_listener[i]);
-    LogInfo("mDNSPlatformCloseDNSProxySkts: Closing DNS Proxy Listener Sockets");  
-}
-
-mDNSexport void mDNSPlatformDisposeProxyContext(void *context)
-{
-    ProxyTCPInfo_t *ti;
-    TCPSocket *sock;
-
-    if (!context)
-        return;
-
-    ti = (ProxyTCPInfo_t *)context;
-    sock = &ti->sock;
-
-    if (sock->fd >= 0)
-    {
-        mDNSPlatformCloseFD(&sock->kqEntry, sock->fd);
-        sock->fd = -1;
-    }
-
-    if (ti->reply)
-        freeL("ProxyTCPInfoLen", ti->reply);
-    freeL("ProxyTCPContext", ti);
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h b/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h
deleted file mode 100644
index 682b972..0000000
--- a/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Foundation/Foundation.h>
-
-NSString * DomainPathToDNSDomain(NSArray * domainPath);
-NSArray *  DNSDomainToDomainPath(NSString * domain);
-NSString * TrimCharactersFromDNSDomain(NSString * domain);
diff --git a/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h b/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h
deleted file mode 100644
index 89e5c2f..0000000
--- a/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Foundation/Foundation.h>
-#import <dispatch/queue.h>
-
-extern const NSString *    _CNSubDomainKey_defaultFlag;
-extern const NSString *    _CNSubDomainKey_subPath;
-
-@protocol _CNDomainBrowserDelegate;
-
-@interface _CNDomainBrowser : NSObject
-
-@property (nonatomic) BOOL              browseRegistration;
-@property (nonatomic) BOOL              ignoreLocal;
-@property (nonatomic) BOOL              ignoreBTMM;
-@property (strong)    dispatch_queue_t  callbackQueue;
-@property (readonly)  BOOL              isBrowsing;
-
-- (instancetype)initWithDelegate:(id<_CNDomainBrowserDelegate>)delegate;
-- (void)startBrowser;
-- (void)stopBrowser;
-
-- (BOOL)foundInstanceInMoreThanLocalDomain;
-
-@property (readonly) NSArray *          defaultDomainPath;
-@property (readonly) NSArray *          flattenedDNSDomains;
-
-- (NSArray *)subDomainsAtDomainPath:(NSArray *)domainPath;
-
-@end
-
-@protocol _CNDomainBrowserDelegate <NSObject>
-
-- (void)bonjourBrowserDomainUpdate:(NSArray *)defaultDomainPath;
-
-@end
diff --git a/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h b/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h
deleted file mode 100644
index bf70f88..0000000
--- a/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <UIKit/UIKit.h>
-
-IB_DESIGNABLE
-
-@protocol CNDomainBrowserViewControllerDelegate;
-
-@interface CNTableViewController : UITableViewController
-@end
-
-@interface CNDomainBrowserViewController : CNTableViewController
-
-@property (nonatomic) IBInspectable BOOL                                        browseRegistration;
-@property (nonatomic) IBInspectable BOOL                                        ignoreLocal;
-@property (weak)      IBOutlet		id<CNDomainBrowserViewControllerDelegate>   delegate;
-
-@property (readonly)                NSString *                                  selectedDNSDomain;
-@property (readonly)                NSString *                                  defaultDNSDomain;
-@property (readonly)                NSArray *                                   flattenedDNSDomains;
-
-@property (readonly)                BOOL                                        isBrowsing;
-
-- (void)startBrowse;
-- (void)stopBrowse;
-
-@end
-
-@protocol CNDomainBrowserViewControllerDelegate <NSObject>
-
-@optional
-
-- (void)domainBrowserDomainSelected:(NSString *)domain;
-- (void)bonjourBrowserDomainUpdate:(NSString *)defaultDomain;
-
-@end
diff --git a/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h b/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h
deleted file mode 100644
index 4a740bf..0000000
--- a/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <UIKit/UIKit.h>
-
-//! Project version number for DomainBrowser.
-FOUNDATION_EXPORT double DomainBrowserVersionNumber;
-
-//! Project version string for DomainBrowser.
-FOUNDATION_EXPORT const unsigned char DomainBrowserVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import <DomainBrowser/PublicHeader.h>
-
-
-#import <DomainBrowser/CNDomainBrowserViewController.h>
-#import <DomainBrowser/CNDomainBrowserPathUtils.h>
diff --git a/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h b/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h
deleted file mode 100644
index d5f3624..0000000
--- a/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Cocoa/Cocoa.h>
-
-@protocol CNDomainBrowserViewDelegate;
-
-IB_DESIGNABLE
-
-@interface CNDomainBrowserView : NSView
-
-@property (nonatomic) IBInspectable BOOL                                        browseRegistration;
-@property (nonatomic) IBInspectable BOOL                                        ignoreLocal;
-@property (nonatomic) IBInspectable BOOL                                        ignoreBTMM;
-@property (weak)      IBOutlet		id<CNDomainBrowserViewDelegate>             delegate;
-
-@property (readonly)                NSString *                                  selectedDNSDomain;
-@property (readonly)                NSString *                                  defaultDNSDomain;
-@property (readonly)                NSArray *                                   flattenedDNSDomains;
-
-@property (readonly)                BOOL                                        isBrowsing;
-
-- (void)startBrowse;
-- (void)stopBrowse;
-
-- (CGFloat)minimumHeight;
-- (void)showSelectedRow;
-- (BOOL)foundInstanceInMoreThanLocalDomain;
-
-@end
-
-@protocol CNDomainBrowserViewDelegate <NSObject>
-
-@optional
-
-- (void)domainBrowserDomainSelected:(NSString *)domain;
-- (void)domainBrowserDomainUpdate:(NSString *)defaultDomain;
-
-@end
-
-@interface CNBonjourDomainCell : NSCell
-@end
-
-@interface CNBonjourDomainView : NSView
-
-@property(strong, nonatomic)   NSString *	domain;
-
-@end
diff --git a/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h b/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h
deleted file mode 100644
index bdc9a87..0000000
--- a/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Cocoa/Cocoa.h>
-
-//! Project version number for DomainBrowser.
-FOUNDATION_EXPORT double DomainBrowserVersionNumber;
-
-//! Project version string for DomainBrowser.
-FOUNDATION_EXPORT const unsigned char DomainBrowserVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import <DomainBrowser/PublicHeader.h>
-
-
-#import <DomainBrowser/CNDomainBrowserView.h>
-#import <DomainBrowser/CNDomainBrowserPathUtils.h>
diff --git a/mDNSMacOSX/LegacyNATTraversal.c b/mDNSMacOSX/LegacyNATTraversal.c
deleted file mode 100644
index 2d44058..0000000
--- a/mDNSMacOSX/LegacyNATTraversal.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * Copyright (c) 2004-2019, 2022 Apple 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.
- */
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-
-#include "stdlib.h"         // For strtol()
-#include "string.h"         // For strlcpy(), For strncpy(), strncasecmp()
-#include "assert.h"         // For assert()
-#include "mdns_strict.h"
-
-#if defined( WIN32 )
-#   include "CommonServices.h"
-#   include <winsock2.h>
-#   include <ws2tcpip.h>
-
-static int
-inet_pton( int family, const char * addr, void * dst )
-{
-    struct sockaddr_storage ss;
-    int sslen = sizeof( ss );
-
-    ZeroMemory( &ss, sizeof( ss ) );
-    ss.ss_family = (ADDRESS_FAMILY)family;
-
-    if ( WSAStringToAddressA( (LPSTR)addr, family, NULL, ( struct sockaddr* ) &ss, &sslen ) == 0 )
-    {
-        if ( family == AF_INET ) { memcpy( dst, &( ( struct sockaddr_in* ) &ss)->sin_addr, sizeof( IN_ADDR ) ); return 1; }
-        else if ( family == AF_INET6 ) { memcpy( dst, &( ( struct sockaddr_in6* ) &ss)->sin6_addr, sizeof( IN6_ADDR ) ); return 1; }
-        else return 0;
-    }
-    else return 0;
-}
-#else
-#   include <arpa/inet.h>       // For inet_pton()
-#endif
-
-#include "mDNSEmbeddedAPI.h"
-#include "uDNS.h"           // For natTraversalHandleAddressReply() etc.
-
-// used to format SOAP port mapping arguments
-typedef struct Property_struct
-{
-    char *name;
-    char *type;
-    char *value;
-} Property;
-
-// All of the text parsing in this file is intentionally transparent so that we know exactly
-// what's being done to the text, with an eye towards preventing security problems.
-
-// This is an evolving list of useful acronyms to know. Please add to it at will.
-// ST      Service Type
-// NT      Notification Type
-// USN     Unique Service Name
-// UDN     Unique Device Name
-// UUID    Universally Unique Identifier
-// URN/urn Universal Resource Name
-
-// Forward declaration because of circular reference:
-// SendPortMapRequest -> SendSOAPMsgControlAction -> MakeTCPConnection -> tcpConnectionCallback -> handleLNTPortMappingResponse
-// In the event of a port conflict, handleLNTPortMappingResponse then increments tcpInfo->retries and calls back to SendPortMapRequest to try again
-mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n);
-
-#define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (mDNSu16)(n)->tcpInfo.retries)
-
-// Note that this function assumes src is already NULL terminated
-mDNSlocal void AllocAndCopy(char **const dst, const char *const src)
-{
-    size_t srcLen;
-    if (src == mDNSNULL) return;
-    srcLen = strlen(src) + 1;
-    if ((srcLen > UINT32_MAX) || ((*dst = mDNSPlatformMemAllocate((mDNSu32)srcLen)) == mDNSNULL))
-    {
-        LogMsg("AllocAndCopy: can't allocate string");
-        return;
-    }
-    memcpy(*dst, src, srcLen);
-}
-
-// This function does a simple parse of an HTTP URL that may include a hostname, port, and path
-// If found in the URL, addressAndPort and path out params will point to newly allocated space (and will leak if they were previously pointing at allocated space)
-mDNSlocal mStatus ParseHttpUrl(const mDNSu8 *ptr, const mDNSu8 *const end, char **const addressAndPort, mDNSIPPort *const port, char **const path)
-{
-    // if the data begins with "http://", we assume there is a hostname and possibly a port number
-    if (end - ptr >= 7 && strncasecmp((const char*)ptr, "http://", 7) == 0)
-    {
-        int i;
-        const mDNSu8 *stop = end;
-        const mDNSu8 *addrPtr = mDNSNULL;
-
-        ptr += 7; //skip over "http://"
-        if (ptr >= end) { LogInfo("ParseHttpUrl: past end of buffer parsing host:port"); return mStatus_BadParamErr; }
-
-        // find the end of the host:port
-        addrPtr = ptr;
-        for (i = 0; addrPtr && addrPtr != end; i++, addrPtr++) if (*addrPtr == '/') break;
-        i++; // Add room for null
-
-        if ((*addressAndPort = mDNSPlatformMemAllocate(i)) == mDNSNULL)
-        { LogMsg("ParseHttpUrl: can't allocate address string"); return mStatus_NoMemoryErr; }
-        mdns_strlcpy((char*)*addressAndPort, (const char*)ptr, i);
-
-        // find the port number in the string, by looking backwards for the ':'
-        stop = ptr;    // can't go back farther than the original start
-        ptr = addrPtr; // move ptr to the path part
-
-        for (addrPtr--; addrPtr>stop; addrPtr--)
-        {
-            if (*addrPtr == ':')
-            {
-                addrPtr++; // skip over ':'
-                *port = mDNSOpaque16fromIntVal((mDNSu16)strtol((const char*)addrPtr, mDNSNULL, 10)); // store it properly converted
-                break;
-            }
-        }
-    }
-
-    // ptr should now point to the first character we haven't yet processed
-    // everything that remains is the path
-    if (path && ptr < end)
-    {
-        const mDNSu32 len = (mDNSu32)(end - ptr) + 1;
-        if ((*path = mDNSPlatformMemAllocate(len)) == mDNSNULL)
-        { LogMsg("ParseHttpUrl: can't mDNSPlatformMemAllocate path"); return mStatus_NoMemoryErr; }
-        mdns_strlcpy((char*)*path, (const char*)ptr, len);
-    }
-
-    return mStatus_NoError;
-}
-
-enum
-{
-    HTTPCode_NeedMoreData = -1, // No code found in stream
-    HTTPCode_Other        = -2, // Valid code other than those below found in stream
-    HTTPCode_Bad          = -3,
-    HTTPCode_200          = 200,
-    HTTPCode_404          = 404,
-    HTTPCode_500          = 500,
-};
-
-mDNSlocal mDNSs16 ParseHTTPResponseCode(const mDNSu8 **const data, const mDNSu8 *const end)
-{
-    const mDNSu8 *ptr = *data;
-    const mDNSu8 *code;
-
-    if (end - ptr < 5) return HTTPCode_NeedMoreData;
-    if (strncasecmp((const char*)ptr, "HTTP/", 5) != 0) return HTTPCode_Bad;
-    ptr += 5;
-    // should we care about the HTTP protocol version?
-
-    // look for first space, which must come before first LF
-    while (ptr && ptr != end)
-    {
-        if (*ptr == '\n') return HTTPCode_Bad;
-        if (*ptr == ' ') break;
-        ptr++;
-    }
-    if (ptr == end) return HTTPCode_NeedMoreData;
-    ptr++;
-
-    if (end - ptr < 3) return HTTPCode_NeedMoreData;
-
-    code = ptr;
-    ptr += 3;
-    while (ptr && ptr != end)
-    {
-        if (*ptr == '\n') break;
-        ptr++;
-    }
-    if (ptr == end) return HTTPCode_NeedMoreData;
-    *data = ++ptr;
-
-    if (memcmp((const char*)code, "200", 3) == 0) return HTTPCode_200;
-    if (memcmp((const char*)code, "404", 3) == 0) return HTTPCode_404;
-    if (memcmp((const char*)code, "500", 3) == 0) return HTTPCode_500;
-
-    LogInfo("ParseHTTPResponseCode found unexpected result code: %c%c%c", code[0], code[1], code[2]);
-    return HTTPCode_Other;
-}
-
-// This function parses the xml body of the device description response from the router. Basically, we look to
-// make sure this is a response referencing a service we care about (WANIPConnection or WANPPPConnection),
-// look for the "controlURL" header immediately following, and copy the addressing and URL info we need
-mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
-{
-    mDNS    *m    = tcpInfo->m;
-    const mDNSu8 *ptr  = tcpInfo->Reply;
-    const mDNSu8 *end  = tcpInfo->Reply + tcpInfo->nread;
-    const mDNSu8 *stop;
-    mDNSs16 http_result;
-
-    if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return; // already have the info we need
-
-    http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
-    if (http_result == HTTPCode_404) LNT_ClearState(m);
-    if (http_result != HTTPCode_200)
-    {
-        LogInfo("handleLNTDeviceDescriptionResponse: HTTP Result code: %d", http_result);
-        return;
-    }
-
-    // Always reset our flag to use WANIPConnection.  We'll use WANPPPConnection if we find it and don't find WANIPConnection.
-    m->UPnPWANPPPConnection = mDNSfalse;
-
-    // find either service we care about
-    while (ptr && ptr < end)
-    {
-        if ((*ptr & 0xDF) == 'W' && (strncasecmp((const char*)ptr, "WANIPConnection:1", 17) == 0)) break;
-        ptr++;
-    }
-    if (ptr == end)
-    {
-        ptr = tcpInfo->Reply;
-        while (ptr && ptr < end)
-        {
-            if ((*ptr & 0xDF) == 'W' && (strncasecmp((const char*)ptr, "WANPPPConnection:1", 18) == 0))
-            {
-                m->UPnPWANPPPConnection = mDNStrue;
-                break;
-            }
-            ptr++;
-        }
-    }
-    if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find WANIPConnection:1 or WANPPPConnection:1 string"); return; }
-
-    // find "controlURL", starting from where we left off
-    while (ptr && ptr < end)
-    {
-        if ((*ptr & 0xDF) == 'C' && (strncasecmp((const char*)ptr, "controlURL", 10) == 0)) break;            // find the first 'c'; is this controlURL? if not, keep looking
-        ptr++;
-    }
-    if (ptr == mDNSNULL || ptr == end) { LogInfo("handleLNTDeviceDescriptionResponse: didn't find controlURL string"); return; }
-    ptr += 11;                          // skip over "controlURL>"
-    if (ptr >= end) { LogInfo("handleLNTDeviceDescriptionResponse: past end of buffer and no body!"); return; } // check ptr again in case we skipped over the end of the buffer
-
-    // find the end of the controlURL element
-    for (stop = ptr; stop < end; stop++) { if (*stop == '<') { end = stop; break; } }
-
-    // fill in default port
-    m->UPnPSOAPPort = m->UPnPRouterPort;
-
-    // free string pointers and set to NULL
-    if (m->UPnPSOAPAddressString != mDNSNULL)
-    {
-        mDNSPlatformMemFree(m->UPnPSOAPAddressString);
-        m->UPnPSOAPAddressString = mDNSNULL;
-    }
-    if (m->UPnPSOAPURL != mDNSNULL)
-    {
-        mDNSPlatformMemFree(m->UPnPSOAPURL);
-        m->UPnPSOAPURL = mDNSNULL;
-    }
-
-    if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, &m->UPnPSOAPURL) != mStatus_NoError) return;
-    // the SOAPURL should look something like "/uuid:0013-108c-4b3f0000f3dc"
-
-    if (m->UPnPSOAPAddressString == mDNSNULL)
-    {
-        ptr = tcpInfo->Reply;
-        while (ptr && ptr < end)
-        {
-            if ((*ptr & 0xDF) == 'U' && (strncasecmp((const char*)ptr, "URLBase", 7) == 0)) break;
-            ptr++;
-        }
-
-        if (ptr < end)      // found URLBase
-        {
-            LogInfo("handleLNTDeviceDescriptionResponse: found URLBase");
-            ptr += 8; // skip over "URLBase>"
-            // find the end of the URLBase element
-            for (stop = ptr; stop < end; stop++) { if (stop && *stop == '<') { end = stop; break; } }
-            if (ParseHttpUrl(ptr, end, &m->UPnPSOAPAddressString, &m->UPnPSOAPPort, mDNSNULL) != mStatus_NoError)
-            {
-                LogInfo("handleLNTDeviceDescriptionResponse: failed to parse URLBase");
-            }
-        }
-
-        // if all else fails, use the router address string
-        if (m->UPnPSOAPAddressString == mDNSNULL) AllocAndCopy(&m->UPnPSOAPAddressString, m->UPnPRouterAddressString);
-    }
-    if (m->UPnPSOAPAddressString == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPAddressString is NULL");
-    else LogInfo("handleLNTDeviceDescriptionResponse: SOAP address string [%s]", m->UPnPSOAPAddressString);
-
-    if (m->UPnPSOAPURL == mDNSNULL) AllocAndCopy(&m->UPnPSOAPURL, m->UPnPRouterURL);
-    if (m->UPnPSOAPURL == mDNSNULL) LogMsg("handleLNTDeviceDescriptionResponse: UPnPSOAPURL is NULL");
-    else LogInfo("handleLNTDeviceDescriptionResponse: SOAP URL [%s]", m->UPnPSOAPURL);
-}
-
-mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
-{
-    mDNS       *m = tcpInfo->m;
-    mDNSu16 err = NATErr_None;
-    mDNSv4Addr ExtAddr;
-    const mDNSu8 *ptr = tcpInfo->Reply;
-    const mDNSu8 *end = tcpInfo->Reply + tcpInfo->nread;
-    mDNSu8       *addrend;
-    static char tagname[20] = { 'N','e','w','E','x','t','e','r','n','a','l','I','P','A','d','d','r','e','s','s' };
-    // Array NOT including a terminating nul
-
-//	LogInfo("handleLNTGetExternalAddressResponse: %s", ptr);
-
-    mDNSs16 http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
-    if (http_result == HTTPCode_404) LNT_ClearState(m);
-    if (http_result != HTTPCode_200)
-    {
-        LogInfo("handleLNTGetExternalAddressResponse: HTTP Result code: %d", http_result);
-        return;
-    }
-
-    while (ptr < end && strncasecmp((const char*)ptr, tagname, sizeof(tagname))) ptr++;
-    ptr += sizeof(tagname);                     // Skip over "NewExternalIPAddress"
-    while (ptr < end && *ptr != '>') ptr++;
-    ptr += 1;                                   // Skip over ">"
-
-    // Find the end of the address and terminate the string so inet_pton() can convert it
-    // (Might be better to copy this to a local string here -- this is overwriting tcpInfo->Reply in-place
-    addrend = (mDNSu8*)ptr;
-    while (addrend < end && (mDNSIsDigit(*addrend) || *addrend == '.')) addrend++;
-    if (addrend >= end) return;
-    *addrend = 0;
-
-    if (inet_pton(AF_INET, (const char*)ptr, &ExtAddr) <= 0)
-    {
-        LogMsg("handleLNTGetExternalAddressResponse: Router returned bad address %s", ptr);
-        err = NATErr_NetFail;
-        ExtAddr = zerov4Addr;
-    }
-    if (!err) LogInfo("handleLNTGetExternalAddressResponse: External IP address is %.4a", &ExtAddr);
-
-    natTraversalHandleAddressReply(m, err, ExtAddr);
-}
-
-mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
-{
-    mDNS             *m         = tcpInfo->m;
-    mDNSIPPort extport   = zeroIPPort;
-    const mDNSu8     *ptr       = tcpInfo->Reply;
-    const mDNSu8     *const end = tcpInfo->Reply + tcpInfo->nread;
-    NATTraversalInfo *natInfo;
-    mDNSs16 http_result;
-
-    for (natInfo = m->NATTraversals; natInfo; natInfo=natInfo->next) { if (natInfo == tcpInfo->parentNATInfo) break;}
-
-    if (!natInfo) { LogInfo("handleLNTPortMappingResponse: can't find matching tcpInfo in NATTraversals!"); return; }
-
-    http_result = ParseHTTPResponseCode(&ptr, end); // Note: modifies ptr
-    if (http_result == HTTPCode_200)
-    {
-        LogInfo("handleLNTPortMappingResponse: got a valid response, sending reply to natTraversalHandlePortMapReply(internal %d external %d retries %d)",
-                mDNSVal16(natInfo->IntPort), RequestedPortNum(natInfo), tcpInfo->retries);
-
-        // Make sure to compute extport *before* we zero tcpInfo->retries
-        extport = mDNSOpaque16fromIntVal(RequestedPortNum(natInfo));
-        tcpInfo->retries = 0;
-        natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, mStatus_NoError, extport, NATMAP_DEFAULT_LEASE, NATTProtocolUPNPIGD);
-    }
-    else if (http_result == HTTPCode_500)
-    {
-        while (ptr && ptr != end)
-        {
-            if (((*ptr & 0xDF) == 'C' && end - ptr >= 8 && strncasecmp((const char*)ptr, "Conflict", 8) == 0) ||
-                (*ptr == '>' && end - ptr >= 15 && strncasecmp((const char*)ptr, ">718</errorCode", 15) == 0))
-            {
-                if (tcpInfo->retries < 100)
-                {
-                    tcpInfo->retries++; SendPortMapRequest(tcpInfo->m, natInfo);
-                    LogInfo("handleLNTPortMappingResponse: Conflict retry %d", tcpInfo->retries);
-                }
-                else
-                {
-                    LogMsg("handleLNTPortMappingResponse too many conflict retries %d %d", mDNSVal16(natInfo->IntPort), mDNSVal16(natInfo->RequestedPort));
-                    natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0, NATTProtocolUPNPIGD);
-                }
-                return;
-            }
-            ptr++;
-        }
-    }
-    else if (http_result == HTTPCode_Bad) LogMsg("handleLNTPortMappingResponse got data that was not a valid HTTP response");
-    else if (http_result == HTTPCode_Other) LogMsg("handleLNTPortMappingResponse got unexpected response code");
-    else if (http_result == HTTPCode_404) LNT_ClearState(m);
-    if (http_result != HTTPCode_200 && http_result != HTTPCode_500)
-        LogInfo("handleLNTPortMappingResponse: HTTP Result code: %d", http_result);
-}
-
-mDNSlocal void DisposeInfoFromUnmapList(mDNS *m, tcpLNTInfo *tcpInfo)
-{
-    tcpLNTInfo **ptr = &m->tcpInfoUnmapList;
-    while (*ptr && *ptr != tcpInfo) ptr = &(*ptr)->next;
-    if (*ptr) { *ptr = (*ptr)->next; mDNSPlatformMemFree(tcpInfo); }    // If we found it, cut it from our list and free the memory
-}
-
-mDNSlocal void tcpConnectionCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err)
-{
-    mStatus status  = mStatus_NoError;
-    tcpLNTInfo *tcpInfo = (tcpLNTInfo *)context;
-    mDNSBool closed  = mDNSfalse;
-    long n       = 0;
-    long nsent   = 0;
-    static mDNSu32 LNTERRORcount = 0;
-
-    if (tcpInfo->sock != sock)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: WARNING- tcpInfo->sock(%p) != sock(%p) !!! Printing tcpInfo struct",
-            tcpInfo->sock, sock);
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: tcpInfo->Address:Port [" PRI_IP_ADDR ":%d] "
-            "tcpInfo->op[%d] tcpInfo->retries[%d] tcpInfo->Request[" PRI_S "] tcpInfo->Reply[" PRI_S "]",
-            &tcpInfo->Address, mDNSVal16(tcpInfo->Port), tcpInfo->op, tcpInfo->retries, tcpInfo->Request,
-            tcpInfo->Reply);
-    }
-        
-    // The handlers below expect to be called with the lock held
-    mDNS_Lock(tcpInfo->m);
-
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: received error");
-        goto exit;
-    }
-
-    if (ConnectionEstablished)      // connection is established - send the message
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: connection established, sending message");
-        nsent = mDNSPlatformWriteTCP(sock, (char*)tcpInfo->Request, tcpInfo->requestLen);
-        if (nsent != (long)tcpInfo->requestLen)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: error writing");
-            status = mStatus_UnknownErr;
-            goto exit;
-        }
-    }
-    else
-    {
-        n = mDNSPlatformReadTCP(sock, (char*)tcpInfo->Reply + tcpInfo->nread, tcpInfo->replyLen - tcpInfo->nread, &closed);
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: mDNSPlatformReadTCP read %ld bytes", n);
-
-        if (n < 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback - read returned %ld", n);
-            status = mStatus_ConnFailed;
-            goto exit;
-        }
-        else if (closed)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: socket closed by remote end %lu", tcpInfo->nread);
-            status = mStatus_ConnFailed;
-            goto exit;
-        }
-
-        tcpInfo->nread += n;
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback tcpInfo->nread %lu", tcpInfo->nread);
-        if (tcpInfo->nread > LNT_MAXBUFSIZE)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "result truncated...");
-            tcpInfo->nread = LNT_MAXBUFSIZE;
-        }
-
-        switch (tcpInfo->op)
-        {
-        case LNTDiscoveryOp:     handleLNTDeviceDescriptionResponse (tcpInfo); break;
-        case LNTExternalAddrOp:  handleLNTGetExternalAddressResponse(tcpInfo); break;
-        case LNTPortMapOp:       handleLNTPortMappingResponse       (tcpInfo); break;
-        case LNTPortMapDeleteOp: status = mStatus_ConfigChanged;               break;
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcovered-switch-default"
-#endif
-        default:
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: bad tcp operation! %d",
-                tcpInfo->op);
-            status = mStatus_Invalid;
-            break;
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-        }
-    }
-exit:
-    if (err || status)
-    {
-        mDNS *const m = tcpInfo->m;
-        static mDNSs32 lastErrorTime = 0;
-
-        if ((LNTERRORcount > 0) && (((mDNSu32)(m->timenow - lastErrorTime)) >= ((mDNSu32)mDNSPlatformOneSecond)))
-        {
-            LNTERRORcount = 0;
-        }
-        lastErrorTime = m->timenow;
-        if ((++LNTERRORcount % 1000) == 0)
-        {   
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "ERROR: tcpconnectioncallback -> got error status %u times", LNTERRORcount);
-            assert(LNTERRORcount < 1000);
-            // Recovery Mechanism to bail mDNSResponder out of trouble: It has been seen that we can get into 
-            // this loop: [tcpKQSocketCallback()--> doTcpSocketCallback()-->tcpconnectionCallback()-->mDNSASLLog()],
-            // if mDNSPlatformTCPCloseConnection() does not close the TCPSocket. Instead of calling mDNSASLLog()
-            // repeatedly and logging the same error msg causing 100% CPU usage, we 
-            // crash mDNSResponder using assert() and restart fresh. See advantages below:
-            // 1.Better User Experience 
-            // 2.CrashLogs frequency can be monitored 
-            // 3.StackTrace can be used for more info 
-        }   
-
-        switch (tcpInfo->op)
-        {
-        case LNTDiscoveryOp:
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: DeviceDescription SOAP address " PRI_S " SOAP path " PRI_S,
-                m->UPnPSOAPAddressString ? m->UPnPSOAPAddressString : "NULL", m->UPnPSOAPURL ? m->UPnPSOAPURL : "NULL");
-            break;
-        case LNTExternalAddrOp:
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: AddressRequest " PUB_S,
-                mDNSIPv4AddressIsZero(m->ExtAddress) ? "failure" : "success");
-            break;
-        case LNTPortMapOp:
-            if (tcpInfo->parentNATInfo)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "tcpConnectionCallback: PortMapRequest " PUB_S " result %d",
-                    (tcpInfo->parentNATInfo->Result) ? "failure" : "success", tcpInfo->parentNATInfo->Result);
-            }
-            break;
-        case LNTPortMapDeleteOp: break;
-        }
-
-        mDNSPlatformTCPCloseConnection(sock);
-        tcpInfo->sock = mDNSNULL;
-        if (tcpInfo->Request) { mDNSPlatformMemFree(tcpInfo->Request); tcpInfo->Request = mDNSNULL; }
-        if (tcpInfo->Reply  ) { mDNSPlatformMemFree(tcpInfo->Reply);   tcpInfo->Reply   = mDNSNULL; }
-    }
-    else
-    {
-        LNTERRORcount = 0;  // clear LNTERRORcount
-    }
-
-    if (tcpInfo) mDNS_Unlock(tcpInfo->m);
-
-    if (status == mStatus_ConfigChanged) DisposeInfoFromUnmapList(tcpInfo->m, tcpInfo);
-}
-
-mDNSlocal mStatus MakeTCPConnection(mDNS *const m, tcpLNTInfo *info, const mDNSAddr *const Addr, const mDNSIPPort Port, LNTOp_t op)
-{
-    mStatus err = mStatus_NoError;
-    mDNSIPPort srcport = zeroIPPort;
-
-    if (mDNSIPv4AddressIsZero(Addr->ip.v4) || mDNSIPPortIsZero(Port))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "LNT MakeTCPConnection: bad address/port " PRI_IP_ADDR ":%d", Addr, mDNSVal16(Port));
-        return(mStatus_Invalid);
-    }
-    info->m         = m;
-    info->Address   = *Addr;
-    info->Port      = Port;
-    info->op        = op;
-    info->nread     = 0;
-    info->replyLen  = LNT_MAXBUFSIZE;
-    if      (info->Reply != mDNSNULL) mDNSPlatformMemZero(info->Reply, LNT_MAXBUFSIZE);   // reuse previously allocated buffer
-    else if ((info->Reply = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "can't allocate reply buffer");
-        return (mStatus_NoMemoryErr);
-    }
-
-    if (info->sock)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "MakeTCPConnection: closing previous open connection");
-        mDNSPlatformTCPCloseConnection(info->sock);
-        info->sock = mDNSNULL;
-    }
-    info->sock = mDNSPlatformTCPSocket(kTCPSocketFlags_Zero, Addr->type, &srcport, mDNSNULL, mDNSfalse);
-    if (!info->sock)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "LNT MakeTCPConnection: unable to create TCP socket");
-        mDNSPlatformMemFree(info->Reply);
-        info->Reply = mDNSNULL;
-        return(mStatus_NoMemoryErr);
-    }
-    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "MakeTCPConnection: connecting to " PRI_IP_ADDR ":%d", &info->Address, mDNSVal16(info->Port));
-    err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpConnectionCallback, info);
-
-    if      (err == mStatus_ConnPending) err = mStatus_NoError;
-    else if (err == mStatus_ConnEstablished)
-    {
-        mDNS_DropLockBeforeCallback();
-        tcpConnectionCallback(info->sock, info, mDNStrue, mStatus_NoError);
-        mDNS_ReclaimLockAfterCallback();
-        err = mStatus_NoError;
-    }
-    else
-    {
-        // Don't need to log this in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "LNT MakeTCPConnection: connection failed");
-        mDNSPlatformTCPCloseConnection(info->sock); // Dispose the socket we created with mDNSPlatformTCPSocket() above
-        info->sock = mDNSNULL;
-        mDNSPlatformMemFree(info->Reply);
-        info->Reply = mDNSNULL;
-    }
-    return(err);
-}
-
-mDNSlocal unsigned int AddSOAPArguments(char *const buf, const unsigned int maxlen, const int numArgs, const Property *const a)
-{
-    static const char f1[] = "<%s>%s</%s>";
-    static const char f2[] = "<%s xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"%s\">%s</%s>";
-    int i, len = 0;
-    *buf = 0;
-    for (i = 0; i < numArgs; i++)
-    {
-        if (a[i].type) len += mDNS_snprintf(buf + len, maxlen - len, f2, a[i].name, a[i].type, a[i].value, a[i].name);
-        else len += mDNS_snprintf(buf + len, maxlen - len, f1, a[i].name,            a[i].value, a[i].name);
-    }
-    return(len);
-}
-
-mDNSlocal mStatus SendSOAPMsgControlAction(mDNS *m, tcpLNTInfo *info, const char *const Action, const int numArgs, const Property *const Arguments, const LNTOp_t op)
-{
-    // SOAP message header format -
-    //  - control URL
-    //  - action (string)
-    //  - router's host/port ("host:port")
-    //  - content-length
-    static const char header[] =
-        "POST %s HTTP/1.1\r\n"
-        "Content-Type: text/xml; charset=\"utf-8\"\r\n"
-        "SOAPAction: \"urn:schemas-upnp-org:service:WAN%sConnection:1#%s\"\r\n"
-        "User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows 9x)\r\n"
-        "Host: %s\r\n"
-        "Content-Length: %d\r\n"
-        "Connection: close\r\n"
-        "Pragma: no-cache\r\n"
-        "\r\n"
-        "%s\r\n";
-
-    static const char body1[] =
-        "<?xml version=\"1.0\"?>\r\n"
-        "<SOAP-ENV:Envelope"
-        " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\""
-        " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
-        "<SOAP-ENV:Body>"
-        "<m:%s xmlns:m=\"urn:schemas-upnp-org:service:WAN%sConnection:1\">";
-
-    static const char body2[] =
-        "</m:%s>"
-        "</SOAP-ENV:Body>"
-        "</SOAP-ENV:Envelope>\r\n";
-
-    mStatus err;
-    char   *body = (char*)&m->omsg;         // Typically requires 1110-1122 bytes; m->omsg is 8952 bytes, which is plenty
-    int bodyLen;
-
-    if (mDNSIPPortIsZero(m->UPnPSOAPPort) || m->UPnPSOAPURL == mDNSNULL || m->UPnPSOAPAddressString == mDNSNULL)    // if no SOAP URL or address exists get out here
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "SendSOAPMsgControlAction: no SOAP port, URL or address string");
-        return mStatus_Invalid;
-    }
-
-    // Create body
-    bodyLen  = mDNS_snprintf   (body,           sizeof(m->omsg),           body1,   Action,   m->UPnPWANPPPConnection ? "PPP" : "IP");
-    bodyLen += AddSOAPArguments(body + bodyLen, sizeof(m->omsg) - bodyLen, numArgs, Arguments);
-    bodyLen += mDNS_snprintf   (body + bodyLen, sizeof(m->omsg) - bodyLen, body2,   Action);
-
-    // Create info->Request; the header needs to contain the bodyLen in the "Content-Length" field
-    if (!info->Request) info->Request = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE);
-    if (!info->Request)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "SendSOAPMsgControlAction: Can't allocate info->Request");
-        return mStatus_NoMemoryErr;
-    }
-    info->requestLen = mDNS_snprintf((char*)info->Request, LNT_MAXBUFSIZE, header, m->UPnPSOAPURL, m->UPnPWANPPPConnection ? "PPP" : "IP", Action, m->UPnPSOAPAddressString, bodyLen, body);
-
-    err = MakeTCPConnection(m, info, &m->Router, m->UPnPSOAPPort, op);
-    if (err) { mDNSPlatformMemFree(info->Request); info->Request = mDNSNULL; }
-    return err;
-}
-
-// Build port mapping request with new port (up to max) and send it
-mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n)
-{
-    char externalPort[6];
-    char internalPort[6];
-    char localIPAddrString[30];
-    char publicPortString[40];
-    Property propArgs[8];
-    mDNSu16 ReqPortNum = RequestedPortNum(n);
-    NATTraversalInfo *n2 = m->NATTraversals;
-
-    // Scan our m->NATTraversals list to make sure the external port we're requesting is locally unique.
-    // UPnP gateways will report conflicts if different devices request the same external port, but if two
-    // clients on the same device request the same external port the second one just stomps over the first.
-    // One way this can happen is like this:
-    // 1. Client A binds local port 80
-    // 2. Client A requests external port 80 -> internal port 80
-    // 3. UPnP NAT gateway refuses external port 80 (some other client already has it)
-    // 4. Client A tries again, and successfully gets external port 80 -> internal port 81
-    // 5. Client B on same machine tries to bind local port 80, and fails
-    // 6. Client B tries again, and successfully binds local port 81
-    // 7. Client B now requests external port 81 -> internal port 81
-    // 8. UPnP NAT gateway allows this, stomping over Client A's existing mapping
-
-    while (n2)
-    {
-        if (n2 == n || RequestedPortNum(n2) != ReqPortNum) n2=n2->next;
-        else
-        {
-            if (n->tcpInfo.retries < 100)
-            {
-                n->tcpInfo.retries++;
-                ReqPortNum = RequestedPortNum(n);   // Pick a new port number
-                n2 = m->NATTraversals;              // And re-scan the list looking for conflicts
-            }
-            else
-            {
-                natTraversalHandlePortMapReply(m, n, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0, NATTProtocolUPNPIGD);
-                return mStatus_NoError;
-            }
-        }
-    }
-
-    // create strings to use in the message
-    mDNS_snprintf(externalPort,      sizeof(externalPort),      "%u",   ReqPortNum);
-    mDNS_snprintf(internalPort,      sizeof(internalPort),      "%u",   mDNSVal16(n->IntPort));
-    mDNS_snprintf(publicPortString,  sizeof(publicPortString),  "iC%u", ReqPortNum);
-    mDNS_snprintf(localIPAddrString, sizeof(localIPAddrString), "%u.%u.%u.%u",
-                  m->AdvertisedV4.ip.v4.b[0], m->AdvertisedV4.ip.v4.b[1], m->AdvertisedV4.ip.v4.b[2], m->AdvertisedV4.ip.v4.b[3]);
-
-    // build the message
-    mDNSPlatformMemZero(propArgs, sizeof(propArgs));
-    propArgs[0].name  = "NewRemoteHost";
-    propArgs[0].type  = "string";
-    propArgs[0].value = "";
-    propArgs[1].name  = "NewExternalPort";
-    propArgs[1].type  = "ui2";
-    propArgs[1].value = externalPort;
-    propArgs[2].name  = "NewProtocol";
-    propArgs[2].type  = "string";
-    propArgs[2].value = (n->Protocol == NATOp_MapUDP) ? "UDP" : "TCP";
-    propArgs[3].name  = "NewInternalPort";
-    propArgs[3].type  = "ui2";
-    propArgs[3].value = internalPort;
-    propArgs[4].name  = "NewInternalClient";
-    propArgs[4].type  = "string";
-    propArgs[4].value = localIPAddrString;
-    propArgs[5].name  = "NewEnabled";
-    propArgs[5].type  = "boolean";
-    propArgs[5].value = "1";
-    propArgs[6].name  = "NewPortMappingDescription";
-    propArgs[6].type  = "string";
-    propArgs[6].value = publicPortString;
-    propArgs[7].name  = "NewLeaseDuration";
-    propArgs[7].type  = "ui4";
-    propArgs[7].value = "0";
-
-    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "SendPortMapRequest: internal %u external %u", mDNSVal16(n->IntPort), ReqPortNum);
-    return SendSOAPMsgControlAction(m, &n->tcpInfo, "AddPortMapping", 8, propArgs, LNTPortMapOp);
-}
-
-mDNSexport mStatus LNT_MapPort(mDNS *m, NATTraversalInfo *const n)
-{
-    LogInfo("LNT_MapPort");
-    if (n->tcpInfo.sock) return(mStatus_NoError);   // If we already have a connection up don't make another request for the same thing
-    n->tcpInfo.parentNATInfo = n;
-    n->tcpInfo.retries       = 0;
-    return SendPortMapRequest(m, n);
-}
-
-mDNSexport mStatus LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n)
-{
-    char externalPort[10];
-    Property propArgs[3];
-    tcpLNTInfo  *info;
-    tcpLNTInfo  **infoPtr = &m->tcpInfoUnmapList;
-    mStatus err;
-
-    // If no NAT gateway to talk to, no need to do all this work for nothing
-    if (mDNSIPPortIsZero(m->UPnPSOAPPort) || !m->UPnPSOAPURL || !m->UPnPSOAPAddressString) return mStatus_NoError;
-
-    mDNS_snprintf(externalPort, sizeof(externalPort), "%u", mDNSVal16(mDNSIPPortIsZero(n->RequestedPort) ? n->IntPort : n->RequestedPort));
-
-    mDNSPlatformMemZero(propArgs, sizeof(propArgs));
-    propArgs[0].name  = "NewRemoteHost";
-    propArgs[0].type  = "string";
-    propArgs[0].value = "";
-    propArgs[1].name  = "NewExternalPort";
-    propArgs[1].type  = "ui2";
-    propArgs[1].value = externalPort;
-    propArgs[2].name  = "NewProtocol";
-    propArgs[2].type  = "string";
-    propArgs[2].value = (n->Protocol == NATOp_MapUDP) ? "UDP" : "TCP";
-
-    n->tcpInfo.parentNATInfo = n;
-
-    // clean up previous port mapping requests and allocations
-    if (n->tcpInfo.sock)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "LNT_UnmapPort: closing previous open connection");
-    }
-    if (n->tcpInfo.sock   ) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock    = mDNSNULL; }
-    if (n->tcpInfo.Request) { mDNSPlatformMemFree(n->tcpInfo.Request);         n->tcpInfo.Request = mDNSNULL; }
-    if (n->tcpInfo.Reply  ) { mDNSPlatformMemFree(n->tcpInfo.Reply);           n->tcpInfo.Reply   = mDNSNULL; }
-
-    // make a copy of the tcpInfo that we can clean up later (the one passed in will be destroyed by the client as soon as this returns)
-    if ((info = (tcpLNTInfo *) mDNSPlatformMemAllocate(sizeof(*info))) == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "LNT_UnmapPort: can't allocate tcpInfo");
-        return(mStatus_NoMemoryErr);
-    }
-    *info = n->tcpInfo;
-
-    while (*infoPtr) infoPtr = &(*infoPtr)->next;   // find the end of the list
-    *infoPtr = info;    // append
-
-    err = SendSOAPMsgControlAction(m, info, "DeletePortMapping", 3, propArgs, LNTPortMapDeleteOp);
-    if (err) DisposeInfoFromUnmapList(m, info);
-    return err;
-}
-
-mDNSexport mStatus LNT_GetExternalAddress(mDNS *m)
-{
-    return SendSOAPMsgControlAction(m, &m->tcpAddrInfo, "GetExternalIPAddress", 0, mDNSNULL, LNTExternalAddrOp);
-}
-
-mDNSlocal mStatus GetDeviceDescription(mDNS *m, tcpLNTInfo *info)
-{
-    // Device description format -
-    //  - device description URL
-    //  - host/port
-    static const char szSSDPMsgDescribeDeviceFMT[] =
-        "GET %s HTTP/1.1\r\n"
-        "Accept: text/xml, application/xml\r\n"
-        "User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1)\r\n"
-        "Host: %s\r\n"
-        "Connection: close\r\n"
-        "\r\n";
-
-    if (!mDNSIPPortIsZero(m->UPnPSOAPPort)) return mStatus_NoError; // already have the info we need
-
-    if (m->UPnPRouterURL == mDNSNULL || m->UPnPRouterAddressString == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "GetDeviceDescription: no router URL or address string!");
-        return (mStatus_Invalid);
-    }
-
-    // build message
-    if      (info->Request != mDNSNULL) mDNSPlatformMemZero(info->Request, LNT_MAXBUFSIZE); // reuse previously allocated buffer
-    else if ((info->Request = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "can't allocate send buffer for discovery");
-        return (mStatus_NoMemoryErr);
-    }
-    info->requestLen = mDNS_snprintf((char*)info->Request, LNT_MAXBUFSIZE, szSSDPMsgDescribeDeviceFMT, m->UPnPRouterURL, m->UPnPRouterAddressString);
-    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "Describe Device: [" PUB_S "]", info->Request);
-    return MakeTCPConnection(m, info, &m->Router, m->UPnPRouterPort, LNTDiscoveryOp);
-}
-
-// This function parses the response to our SSDP discovery message. Basically, we look to make sure this is a response
-// referencing a service we care about (WANIPConnection or WANPPPConnection), then look for the "Location:" header and copy the addressing and
-// URL info we need.
-mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len)
-{
-    const mDNSu8 *ptr = data;
-    const mDNSu8 *end = data + len;
-    const mDNSu8 *stop;
-
-    if (!mDNSIPPortIsZero(m->UPnPRouterPort)) return; // already have the info we need
-
-    // The formatting of the HTTP header is not always the same when it comes to the placement of
-    // the service and location strings, so we just look for each of them from the beginning for every response
-
-    // figure out if this is a message from a service we care about
-    while (ptr && ptr != end)
-    {
-        if ((*ptr & 0xDF) == 'W' && (strncasecmp((const char*)ptr, "WANIPConnection:1", 17) == 0)) break;
-        ptr++;
-    }
-    if (ptr == end)
-    {
-        ptr = data;
-        while (ptr && ptr != end)
-        {
-            if ((*ptr & 0xDF) == 'W' && (strncasecmp((const char*)ptr, "WANPPPConnection:1", 18) == 0)) break;
-            ptr++;
-        }
-    }
-    if (ptr == mDNSNULL || ptr == end) return;  // not a message we care about
-
-    // find "Location:", starting from the beginning
-    ptr = data;
-    while (ptr && ptr != end)
-    {
-        if ((*ptr & 0xDF) == 'L' && (strncasecmp((const char*)ptr, "Location:", 9) == 0)) break;          // find the first 'L'; is this Location? if not, keep looking
-        ptr++;
-    }
-    if (ptr == mDNSNULL || ptr == end)
-    {
-        LogInfo("LNT_ConfigureRouterInfo: Location field not found");
-        return; // not a message we care about
-    }
-    ptr += 9; //Skip over 'Location:'
-    while (*ptr == ' ' && ptr < end) ptr++; // skip over spaces
-    if (ptr >= end) return;
-
-    // find the end of the line
-    for (stop = ptr; stop != end; stop++) { if (*stop == '\r') { end = stop; break; } }
-
-    // fill in default port
-    m->UPnPRouterPort = mDNSOpaque16fromIntVal(80);
-
-    // free string pointers and set to NULL
-    if (m->UPnPRouterAddressString != mDNSNULL)
-    {
-        mDNSPlatformMemFree(m->UPnPRouterAddressString);
-        m->UPnPRouterAddressString = mDNSNULL;
-    }
-    if (m->UPnPRouterURL != mDNSNULL)
-    {
-        mDNSPlatformMemFree(m->UPnPRouterURL);
-        m->UPnPRouterURL = mDNSNULL;
-    }
-
-    // the Router URL should look something like "/dyndev/uuid:0013-108c-4b3f0000f3dc"
-    if (ParseHttpUrl(ptr, end, &m->UPnPRouterAddressString, &m->UPnPRouterPort, &m->UPnPRouterURL) != mStatus_NoError)
-    {
-        LogInfo("LNT_ConfigureRouterInfo: Failed to parse URL");
-        return;
-    }
-
-    m->UPnPInterfaceID = InterfaceID;
-
-    if (m->UPnPRouterAddressString == mDNSNULL)
-    {
-        LogMsg("LNT_ConfigureRouterInfo: UPnPRouterAddressString is NULL");
-    }
-    else LogInfo("LNT_ConfigureRouterInfo: Router address string [%s]", m->UPnPRouterAddressString);
-
-    if (m->UPnPRouterURL == mDNSNULL)
-    {
-        LogMsg("LNT_ConfigureRouterInfo: UPnPRouterURL is NULL");
-    }
-    else LogInfo("LNT_ConfigureRouterInfo: Router URL [%s]", m->UPnPRouterURL);
-
-    LogInfo("LNT_ConfigureRouterInfo: Router port %d", mDNSVal16(m->UPnPRouterPort));
-    LogInfo("LNT_ConfigureRouterInfo: Router interface %d", m->UPnPInterfaceID);
-
-    // Don't need the SSDP socket anymore
-    if (m->SSDPSocket) { debugf("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
-
-    // now send message to get the device description
-    GetDeviceDescription(m, &m->tcpDeviceInfo);
-}
-
-mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
-{
-    static const char msg[] =
-        "M-SEARCH * HTTP/1.1\r\n"
-        "Host:239.255.255.250:1900\r\n"
-        "ST:urn:schemas-upnp-org:service:WAN%sConnection:1\r\n"
-        "Man:\"ssdp:discover\"\r\n"
-        "MX:3\r\n\r\n";
-    static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } };
-
-    mDNSu8 *const buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
-    unsigned int bufLen;
-
-    if (m->SleepState != SleepState_Awake) return;
-    if (!mDNSIPPortIsZero(m->UPnPRouterPort))
-    {
-        if (m->SSDPSocket) { debugf("LNT_SendDiscoveryMsg destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
-        if (mDNSIPPortIsZero(m->UPnPSOAPPort) && !m->tcpDeviceInfo.sock) GetDeviceDescription(m, &m->tcpDeviceInfo);
-        return;
-    }
-
-    // Always query for WANIPConnection in the first SSDP packet
-    if (m->retryIntervalGetAddr <= NATMAP_INIT_RETRY) m->SSDPWANPPPConnection = mDNSfalse;
-
-    // Create message
-    bufLen = mDNS_snprintf((char*)buf, sizeof(m->omsg), msg, m->SSDPWANPPPConnection ? "PPP" : "IP");
-
-    debugf("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExtAddress);
-
-    if (!mDNSIPv4AddressIsZero(m->Router.ip.v4))
-    {
-        if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(zeroIPPort); debugf("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
-        mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &m->Router,     SSDPPort, mDNSfalse);
-        mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &multicastDest, SSDPPort, mDNSfalse);
-    }
-
-    m->SSDPWANPPPConnection = !m->SSDPWANPPPConnection;
-}
-
-mDNSexport void LNT_ClearState(mDNS *const m)
-{
-    if (m->tcpAddrInfo.sock)   { mDNSPlatformTCPCloseConnection(m->tcpAddrInfo.sock);   m->tcpAddrInfo.sock   = mDNSNULL; }
-    if (m->tcpDeviceInfo.sock) { mDNSPlatformTCPCloseConnection(m->tcpDeviceInfo.sock); m->tcpDeviceInfo.sock = mDNSNULL; }
-    m->UPnPSOAPPort = m->UPnPRouterPort = zeroIPPort;   // Reset UPnP ports
-}
-
-#endif /* _LEGACY_NAT_TRAVERSAL_ */
diff --git a/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h b/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h
deleted file mode 100644
index 02d9771..0000000
--- a/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Foundation/Foundation.h>
-#import "BonjourPrefToolProtocol.h"
-
-// This object implements the protocol which we have defined. It provides the actual behavior for the service.
-// It is 'exported' by the service to make it available to the process hosting the service over an NSXPCConnection.
-@interface BonjourPrefTool : NSObject <BonjourPrefToolProtocol>
-@end
diff --git a/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h b/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h
deleted file mode 100644
index e82bfdf..0000000
--- a/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Foundation/Foundation.h>
-
-// The protocol that this service will vend as its API. This header file will
-// also need to be visible to the process hosting the service.
-@protocol BonjourPrefToolProtocol
-
-- (void) setKeychainEntry:(NSDictionary *_Nonnull)secretDictionary withStatus:(void (^ _Nonnull)(OSStatus))status;
-
-@end
-
diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
deleted file mode 100644
index 36bfee8..0000000
--- a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-    File: DNSServiceDiscoveryPref.h
-
-    Abstract: System Preference Pane for Dynamic DNS and Wide-Area DNS Service Discovery
-
-    Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-
-    Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
-    ("Apple") in consideration of your agreement to the following terms, and your
-    use, installation, modification or redistribution of this Apple software
-    constitutes acceptance of these terms.  If you do not agree with these terms,
-    please do not use, install, modify or redistribute this Apple software.
-
-    In consideration of your agreement to abide by the following terms, and subject
-    to these terms, Apple grants you a personal, non-exclusive license, under Apple's
-    copyrights in this original Apple software (the "Apple Software"), to use,
-    reproduce, modify and redistribute the Apple Software, with or without
-    modifications, in source and/or binary forms; provided that if you redistribute
-    the Apple Software in its entirety and without modifications, 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 Computer, 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.
-
-    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.
- */
-
-#import <PreferencePanes/PreferencePanes.h>
-#import <SecurityInterface/SFAuthorizationView.h>
-#import <dns_sd.h>
-
-@class CNBonjourDomainView;
-@class CNDomainBrowserView;
-
-@interface DNSServiceDiscoveryPref : NSPreferencePane
-{
-    IBOutlet NSTextField          *hostName;
-    IBOutlet NSTextField          *sharedSecretName;
-    IBOutlet NSSecureTextField    *sharedSecretValue;
-    IBOutlet NSTextField          *browseDomainTextField;
-	IBOutlet NSTextField          *regDomainTextField;
-	IBOutlet CNBonjourDomainView  *regDomainView;
-    IBOutlet NSButton             *wideAreaCheckBox;
-    IBOutlet NSButton             *hostNameSharedSecretButton;
-	IBOutlet NSButton             *registrationSelectButton;
-	IBOutlet NSButton             *registrationSharedSecretButton;
-    IBOutlet NSButton             *applyButton;
-    IBOutlet NSButton             *revertButton;
-    IBOutlet NSWindow             *sharedSecretWindow;
-	IBOutlet NSWindow             *addBrowseDomainWindow;
-	IBOutlet NSWindow             *addBrowseDomainManualWindow;
-	IBOutlet NSWindow             *selectRegistrationDomainWindow;
-	IBOutlet NSWindow             *selectRegistrationDomainManualWindow;
-    IBOutlet NSButton             *addBrowseDomainButton;
-    IBOutlet NSButton             *removeBrowseDomainButton;
-    IBOutlet NSButton             *secretOKButton;
-    IBOutlet NSButton             *secretCancelButton;
-    IBOutlet NSImageView          *statusImageView;
-    IBOutlet NSTabView            *tabView;
-	IBOutlet NSTableView          *browseDomainList;
-	IBOutlet CNDomainBrowserView  *bonjourBrowserView;
-	IBOutlet CNDomainBrowserView  *registrationBrowserView;
-    IBOutlet SFAuthorizationView  *comboAuthButton;
-
-    NSWindow            *mainWindow;
-    NSString            *currentHostName;
-    NSString            *currentRegDomain;
-    NSArray             *currentBrowseDomainsArray;
-    NSMutableArray      *browseDomainsArray;
-    NSString            *defaultRegDomain;
-
-    NSString            *hostNameSharedSecretName;
-    NSString            *hostNameSharedSecretValue;
-    NSString            *regSharedSecretName;
-    NSString            *regSharedSecretValue;
-    BOOL                currentWideAreaState;
-    BOOL                prefsNeedUpdating;
-    BOOL                browseDomainListEnabled;
-    NSImage             *successImage;
-    NSImage             *inprogressImage;
-    NSImage             *failureImage;
-
-    NSMutableArray      *registrationDataSource;
-}
-
--(IBAction)applyClicked : (id)sender;
--(IBAction)enableBrowseDomainClicked : (id)sender;
--(IBAction)addBrowseDomainClicked : (id)sender;
--(IBAction)removeBrowseDomainClicked : (id)sender;
--(IBAction)revertClicked : (id)sender;
--(IBAction)changeButtonPressed : (id)sender;
--(IBAction)closeMyCustomSheet : (id)sender;
--(IBAction)wideAreaCheckBoxChanged : (id)sender;
-
-
--(NSMutableArray *)registrationDataSource;
--(NSString *)currentRegDomain;
--(NSArray *)currentBrowseDomainsArray;
--(NSString *)currentHostName;
--(NSString *)defaultRegDomain;
--(void)setDefaultRegDomain : (NSString *)domain;
-
-
--(void)enableApplyButton;
--(void)disableApplyButton;
--(void)applyCurrentState;
--(void)setupInitialValues;
--(void)toggleWideAreaBonjour : (BOOL)state;
--(void)updateApplyButtonState;
--(void)enableControls;
--(void)disableControls;
--(void)validateTextFields;
--(void)readPreferences;
--(void)savePreferences;
--(void)restorePreferences;
--(void)watchForPreferenceChanges;
--(void)updateStatusImageView;
-
-
--(NSString *)sharedSecretKeyName : (NSString * )domain;
--(NSString *)domainForHostName : (NSString *)hostNameString;
--(int)statusForHostName : (NSString * )domain;
--(NSData *)dataForDomainArray : (NSArray *)domainArray;
--(NSData *)dataForDomain : (NSString *)domainName isEnabled : (BOOL)enabled;
--(NSDictionary *)dictionaryForSharedSecret : (NSString *)secret domain : (NSString *)domainName key : (NSString *)keyName;
--(BOOL)domainAlreadyInList : (NSString *)domainString;
--(NSString *)trimCharactersFromDomain : (NSString *)domain;
-
-
-// Delegate methods
--(void)authorizationViewDidAuthorize : (SFAuthorizationView *)view;
--(void)authorizationViewDidDeauthorize : (SFAuthorizationView *)view;
--(void)mainViewDidLoad;
--(void)controlTextDidChange : (NSNotification *) notification;
-
-@end
diff --git a/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h b/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h
deleted file mode 100644
index 3f063e3..0000000
--- a/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <ViewBridge/NSViewService.h>
-#import <PreferencePanes/NSPrefRemoteViewService.h>
-
-@interface BonjourPrefRemoteViewService : NSPrefRemoteViewService
-@end
diff --git a/mDNSMacOSX/QuerierSupport.c b/mDNSMacOSX/QuerierSupport.c
deleted file mode 100644
index 20b17b2..0000000
--- a/mDNSMacOSX/QuerierSupport.c
+++ /dev/null
@@ -1,1178 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "QuerierSupport.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "dns_sd_internal.h"
-#include "mDNSMacOSX.h"
-#include "uDNS.h"
-
-#include <CoreUtils/CommonServices.h>
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec.h"
-#include "dnssec_mdns_core.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-#include "discover_resolver.h"
-#endif
-
-#include "cf_support.h"
-#include <AssertMacros.h>
-#include <mach/mach_time.h>
-#include <mdns/preferences.h>
-#include <mdns/system.h>
-#include <mdns/ticks.h>
-#include <mdns/xpc.h>
-#include <os/variant_private.h>
-#include "mdns_strict.h"
-
-int PQWorkaroundThreshold = 0;
-
-extern mDNS mDNSStorage;
-
-mDNSlocal mDNSBool _Querier_QuestionBelongsToSelf(const DNSQuestion *q);
-
-mDNSlocal void _Querier_LogDNSServices(const mdns_dns_service_manager_t manager)
-{
-    __block mDNSu32 count = 0;
-    const mDNSu32 total = (mDNSu32)mdns_dns_service_manager_get_count(manager);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Updated DNS services (%u)", total);
-    mdns_dns_service_manager_enumerate(manager,
-    ^ bool (const mdns_dns_service_t service)
-    {
-        count++;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "DNS service (%u/%u) -- %@", count, total, service);
-        return true;
-    });
-}
-
-mDNSlocal dispatch_queue_t _Querier_InternalQueue(void)
-{
-    static dispatch_once_t sOnce = 0;
-    static dispatch_queue_t sQueue = NULL;
-
-    dispatch_once(&sOnce,
-    ^{
-        sQueue = dispatch_queue_create("com.apple.mDNSResponder.querier-support-queue", DISPATCH_QUEUE_SERIAL);
-    });
-    return sQueue;
-}
-
-mDNSexport mdns_dns_service_manager_t Querier_GetDNSServiceManager(void)
-{
-    mDNS *const m = &mDNSStorage;
-    static mdns_dns_service_manager_t sDNSServiceManager = NULL;
-    if (sDNSServiceManager)
-    {
-        return sDNSServiceManager;
-    }
-    const mdns_dns_service_manager_t manager = mdns_dns_service_manager_create(_Querier_InternalQueue(), NULL);
-    if (!manager)
-    {
-        return NULL;
-    }
-    mdns_dns_service_manager_set_report_symptoms(manager, true);
-    mdns_dns_service_manager_enable_fail_fast_mode_for_odoh(manager, true);
-    mdns_dns_service_manager_enable_problematic_qtype_workaround(manager, PQWorkaroundThreshold);
-    if (os_variant_has_internal_diagnostics(kMDNSResponderIDStr))
-    {
-        const CFStringRef key = CFSTR("DDRRetryIntervalSecs");
-        const uint32_t intervalSecs = mdns_preferences_get_uint32_clamped(kMDNSResponderID, key, 0, NULL);
-        if (intervalSecs != 0)
-        {
-            mdns_dns_service_manager_set_ddr_retry_interval(manager, intervalSecs);
-        }
-    }
-    mdns_dns_service_manager_set_event_handler(manager,
-    ^(mdns_event_t event, __unused OSStatus error)
-    {
-        KQueueLock();
-        switch (event)
-        {
-            case mdns_event_error:
-                mdns_dns_service_manager_invalidate(manager);
-                if (sDNSServiceManager == manager)
-                {
-                    mdns_forget(&sDNSServiceManager);
-                }
-                break;
-
-            case mdns_event_update:
-                mdns_dns_service_manager_apply_pending_updates(manager);
-                mDNS_Lock(m);
-                Querier_ProcessDNSServiceChanges();
-                _Querier_LogDNSServices(manager);
-                mDNS_Unlock(m);
-                break;
-
-            case mdns_event_invalidated:
-                mdns_release(manager);
-                break;
-        }
-        KQueueUnlock("DNS Service Manager event handler");
-    });
-    sDNSServiceManager = manager;
-    mdns_retain(sDNSServiceManager);
-    mdns_dns_service_manager_activate(sDNSServiceManager);
-    return sDNSServiceManager;
-}
-
-mDNSlocal mdns_dns_service_t _Querier_GetNativeDNSService(const mdns_dns_service_manager_t manager,
-    const DNSQuestion * const q)
-{
-    mdns_dns_service_t service;
-    if (q->InterfaceID)
-    {
-        const uint32_t ifIndex = (uint32_t)((uintptr_t)q->InterfaceID);
-        service = mdns_dns_service_manager_get_interface_scoped_native_service(manager, q->qname.c, ifIndex);
-    }
-    else
-    {
-        service = mdns_dns_service_manager_get_unscoped_native_service(manager, q->qname.c);
-    }
-    return service;
-}
-
-mDNSlocal mdns_dns_service_t _Querier_GetNonNativeDNSService(const mdns_dns_service_manager_t manager,
-    const DNSQuestion * const q, const mDNSBool excludeEncryptedDNS)
-{
-    mdns_dns_service_t service;
-    const uint32_t ifIndex = (uint32_t)((uintptr_t)q->InterfaceID);
-    const mdns_dns_service_opts_t options = excludeEncryptedDNS ? mdns_dns_service_opt_none :
-        mdns_dns_service_opt_prefer_discovered;
-    if (!excludeEncryptedDNS && !uuid_is_null(q->ResolverUUID))
-    {
-        service = mdns_dns_service_manager_get_uuid_scoped_service(manager, q->ResolverUUID, ifIndex);
-        if (service && (mdns_dns_service_get_class(service) == nw_resolver_class_oblivious) && !q->InterfaceID)
-        {
-            mdns_dns_service_t discovered_service = mdns_dns_service_manager_get_discovered_service(manager, q->qname.c);
-            if (discovered_service && (mdns_dns_service_get_class(discovered_service) == nw_resolver_class_designated))
-            {
-                // Prefer discovered resolver for unscoped queries that would use oblivious resolvers,
-                // even if they have a resolver UUID.
-                service = discovered_service;
-            }
-			else
-			{
-				mdns_dns_service_t oblivious_service = mdns_dns_service_manager_get_discovered_oblivious_service(manager, service, q->qname.c);
-				if (oblivious_service && (mdns_dns_service_get_class(oblivious_service) == nw_resolver_class_oblivious))
-				{
-					// Prefer discovered oblivious resolver
-					service = oblivious_service;
-				}
-			}
-        }
-    }
-    else if (q->InterfaceID)
-    {
-        service = mdns_dns_service_manager_get_interface_scoped_system_service_with_options(manager, q->qname.c, ifIndex,
-            options);
-    }
-    else if (q->ServiceID >= 0)
-    {
-        service = mdns_dns_service_manager_get_service_scoped_system_service(manager, q->qname.c, (uint32_t)q->ServiceID);
-    }
-    else
-    {
-        service = mDNSNULL;
-        if (!excludeEncryptedDNS)
-        {
-            // Check for a matching discovered resolver for unscoped queries
-            service = mdns_dns_service_manager_get_discovered_service(manager, q->qname.c);
-        }
-        if (!service)
-        {
-            service = mdns_dns_service_manager_get_unscoped_system_service_with_options(manager, q->qname.c, options);
-        }
-    }
-    if (!excludeEncryptedDNS && service && !mdns_dns_service_interface_is_vpn(service))
-    {
-        // Check for encryption, and if the service isn't encrypted, fallback or fail
-        const mDNSBool lacksRequiredEncryption = q->RequireEncryption && !mdns_dns_service_is_encrypted(service);
-        if (lacksRequiredEncryption || mdns_dns_service_has_connection_problems(service))
-        {
-            if (lacksRequiredEncryption)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[R%u->Q%u] DNS service %llu lacks required encryption",
-                     q->request_id, mDNSVal16(q->TargetQID), mdns_dns_service_get_id(service));
-                service = NULL;
-            }
- 
-            // Check for a fallback service
-            if (q->CustomID != 0)
-            {
-                service = mdns_dns_service_manager_get_custom_service(manager, q->CustomID);
-            }
-        }
-    }
-    // Check if the final service is a fail-fast service.
-    if (service && mdns_dns_service_fail_fast_mode_enabled(service))
-    {
-        // If it's having connection problems and the DNSQuestion has already been used to probe if the service is back
-        // up and running. This way the client requests can fail quicker.
-        if (mdns_dns_service_has_connection_problems(service) && q->UsedAsFailFastProbe)
-        {
-            service = NULL;
-        }
-    }
-    return service;
-}
-
-mDNSlocal mDNSBool _Querier_QuestionIsEligibleForNonNativeDNSService(const DNSQuestion *const q)
-{
-    mDNSBool eligible = mDNStrue;
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    if (IsSubdomain(&q->qname, THREAD_DOMAIN_NAME))
-    {
-        // We do not want the query ends with "openthread.thread.home.arpa." to choose a non-native DNS service to go
-        // outside of the home network.
-        eligible = mDNSfalse;
-    }
-#endif
-
-    return eligible;
-}
-
-mDNSlocal mdns_dns_service_t _Querier_GetDNSService(const DNSQuestion *q, const mDNSBool excludeEncryptedDNS)
-{
-    mdns_dns_service_t service = mDNSNULL;
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (!manager)
-    {
-        return NULL;
-    }
-
-    service = _Querier_GetNativeDNSService(manager, q);
-    if (!service && _Querier_QuestionIsEligibleForNonNativeDNSService(q))
-    {
-        service = _Querier_GetNonNativeDNSService(manager, q, excludeEncryptedDNS);
-    }
-    return service;
-}
-
-mDNSlocal pid_t _Querier_GetMyPID(void)
-{
-    static dispatch_once_t sOnce = 0;
-    static pid_t sPID = 0;
-    dispatch_once(&sOnce,
-    ^{
-        sPID = getpid();
-    });
-    return sPID;
-}
-
-mDNSlocal const mDNSu8 *_Querier_GetMyUUID(void)
-{
-    static dispatch_once_t sOnce = 0;
-    static mDNSu8 sUUID[16];
-    dispatch_once(&sOnce,
-    ^{
-        mdns_system_pid_to_uuid(_Querier_GetMyPID(), sUUID);
-    });
-    return sUUID;
-}
-
-mDNSlocal mDNSBool _Querier_QuestionBelongsToSelf(const DNSQuestion *q)
-{
-    if (q->pid != 0)
-    {
-        return ((q->pid == _Querier_GetMyPID()) ? mDNStrue : mDNSfalse);
-    }
-    else
-    {
-        return ((uuid_compare(q->uuid, _Querier_GetMyUUID()) == 0) ? mDNStrue : mDNSfalse);
-    }
-}
-
-mDNSlocal mDNSBool _Querier_DNSServiceIsUnscopedAndLacksPrivacy(const mdns_dns_service_t service)
-{
-    if ((mdns_dns_service_get_scope(service) == mdns_dns_service_scope_none) &&
-        !mdns_dns_service_is_encrypted(service) && !mdns_dns_service_interface_is_vpn(service))
-    {
-        return mDNStrue;
-    }
-    else
-    {
-        return mDNSfalse;
-    }
-}
-
-#define kQuerierLogFullDNSServicePeriodSecs 60
-
-mDNSlocal mDNSBool _Querier_ShouldLogFullDNSService(const mdns_dns_service_t service)
-{
-    uint64_t *lastFullLogTicks = (uint64_t *)mdns_dns_service_get_context(service);
-    if (lastFullLogTicks)
-    {
-        const uint64_t nowTicks = mach_continuous_time();
-        const uint64_t diffTicks = nowTicks - *lastFullLogTicks;
-        if ((diffTicks / mdns_mach_ticks_per_second()) < kQuerierLogFullDNSServicePeriodSecs)
-        {
-            return mDNSfalse;
-        }
-        *lastFullLogTicks = nowTicks;
-    }
-    else
-    {
-        lastFullLogTicks = (uint64_t *)mdns_malloc(sizeof(*lastFullLogTicks));
-        if (lastFullLogTicks)
-        {
-            *lastFullLogTicks = mach_continuous_time();
-            mdns_dns_service_set_context(service, lastFullLogTicks);
-            mdns_dns_service_set_context_finalizer(service, mdns_free_context_finalizer);
-        }
-    }
-    return mDNStrue;
-}
-
-mDNSlocal mDNSBool _Querier_VPNDNSServiceExistsForQName(const domainname *const qname)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        const mdns_dns_service_t service = mdns_dns_service_manager_get_unscoped_system_service(manager, qname->c);
-        if (service && mdns_dns_service_interface_is_vpn(service))
-        {
-            return mDNStrue;
-        }
-    }
-    return mDNSfalse;
-}
-
-// So far, ODoH/DoH/DoT DNS services may be specified without any server IP addresses, just a hostname. In such a case,
-// the underlying nw_connection will need to resolve the DNS service's hostname. To avoid potential dependency cycles
-// because of mDNSResponder issuing GAI requests to itself, we simply prevent DNSQuestions with mDNSResponder's PID or
-// Mach-O UUID from using ODoH/DoH/DoT services.
-//
-// A client may have explicitly requested that use of encrypted DNS protocols is prohibited for similar dependency cycle
-// reasons. In this case, ProhibitEncryptedDNS will be set to true.
-//
-// Also, if a DNSQuestion's QNAME is in a special-use mDNS local domain, and is being sent via unicast DNS as a
-// workaround for private internal networks that incorrectly use these domains for their network's DNS, then
-// ODoH/DoH/DoT should not be used. It only makes sense to send the DNS queries to DNS servers belonging to the network,
-// e.g., those specified via DHCP.
-mDNSlocal mDNSBool _Querier_ExcludeEncryptedDNSServices(const DNSQuestion *const q)
-{
-    return (_Querier_QuestionBelongsToSelf(q) || q->ProhibitEncryptedDNS || IsLocalDomain(&q->qname));
-}
-
-mDNSexport void Querier_SetDNSServiceForQuestion(DNSQuestion *q)
-{
-    const mDNSBool excludeEncryptedDNS = _Querier_ExcludeEncryptedDNSServices(q);
-    if (!uuid_is_null(q->ResolverUUID) && excludeEncryptedDNS)
-    {
-        uuid_clear(q->ResolverUUID);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[R%u->Q%u] Cleared resolver UUID for question: " PRI_DM_NAME " (" PUB_S ")",
-            q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
-    }
-    mdns_forget(&q->dnsservice);
-    mdns_dns_service_t service = _Querier_GetDNSService(q, excludeEncryptedDNS);
-    if (!excludeEncryptedDNS)
-    {
-        mDNSBool retryPathEval = mDNSfalse;
-        const char *retryReason = "<unspecified>";
-        if (service)
-        {
-            // Check whether path evaluation needs to be retried if path evaluation for the original QNAME was done by the
-            // client, a CNAME traversal has taken place, the DNSQuestion is not interface-scoped, and the current DNS
-            // service is not native.
-            if ((q->flags & kDNSServiceFlagsPathEvaluationDone) && (q->lastDNSServiceID != MDNS_DNS_SERVICE_INVALID_ID) &&
-                !q->InterfaceID && !mdns_dns_service_is_native(service))
-            {
-                // If the current DNS service isn't identical to the previous DNS service, and the DNS service is unscoped
-                // and lacks privacy, then retry path evaluation. A path evaluation with the new QNAME may result in using
-                // a DNS service that offers privacy.
-                if ((mdns_dns_service_get_id(service) != q->lastDNSServiceID) &&
-                    _Querier_DNSServiceIsUnscopedAndLacksPrivacy(service))
-                {
-                    retryReason = "avoid non-private DNS service";
-                    retryPathEval = mDNStrue;
-                }
-                // If the DNSQuestion is UUID-scoped, but there exists a VPN DNS service for its QNAME, then retry path
-                // evaluation in case the VPN DNS service should be used for the new QNAME.
-                else if (!uuid_is_null(q->ResolverUUID) && _Querier_VPNDNSServiceExistsForQName(&q->qname))
-                {
-                    retryReason = "QNAME is in a VPN DNS service's domain";
-                    retryPathEval = mDNStrue;
-                }
-            }
-        }
-        else if (!uuid_is_null(q->ResolverUUID))
-        {
-            // If the ResolverUUID is not null, but we didn't get a DNS service, then the ResolverUUID may be stale, i.e.,
-            // the resolver configuration with that UUID may have been deleted, so retry path evaluation.
-            retryReason = "ResolverUUID may be stale";
-            retryPathEval = mDNStrue;
-        }
-        if (retryPathEval)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "[R%u->Q%u] Retrying path evaluation -- qname: " PRI_DM_NAME ", qtype: " PUB_S ", reason: " PUB_S,
-                q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), retryReason);
-            mDNSPlatformGetDNSRoutePolicy(q);
-            service = _Querier_GetDNSService(q, excludeEncryptedDNS);
-        }
-    }
-    q->dnsservice = service;
-    mdns_retain_null_safe(q->dnsservice);
-
-    mDNSBool enablesDNSSEC = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    enablesDNSSEC = dns_question_is_dnssec_requestor(q);
-#endif
-
-    if (!q->dnsservice || _Querier_ShouldLogFullDNSService(q->dnsservice))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[R%u->Q%u] Question for " PRI_DM_NAME " (" PUB_S PUB_S ") assigned DNS service -- %@",
-            q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-            enablesDNSSEC ? ", DNSSEC" : "", q->dnsservice);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[R%u->Q%u] Question for " PRI_DM_NAME " (" PUB_S PUB_S ") assigned DNS service %llu",
-            q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
-            enablesDNSSEC ? ", DNSSEC" : "", mdns_dns_service_get_id(q->dnsservice));
-    }
-}
-
-mDNSexport void Querier_RegisterPathResolver(const uuid_t resolverUUID)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_register_path_resolver(manager, resolverUUID);
-    }
-}
-
-mDNSexport mdns_dns_service_id_t Querier_RegisterCustomDNSService(const xpc_object_t resolverConfigDict)
-{
-    mdns_dns_service_id_t ident = 0;
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        ident = mdns_dns_service_manager_register_custom_service(manager, resolverConfigDict);
-    }
-    return ident;
-}
-
-mDNSexport mdns_dns_service_id_t Querier_RegisterCustomDNSServiceWithPListData(const uint8_t *dataPtr, size_t dataLen)
-{
-    mdns_dns_service_id_t ident = 0;
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        xpc_object_t resolverConfigDict = mdns_xpc_create_dictionary_from_plist_data(dataPtr, dataLen, NULL);
-        if (resolverConfigDict)
-        {
-            ident = mdns_dns_service_manager_register_custom_service(manager, resolverConfigDict);
-            xpc_forget(&resolverConfigDict);
-        }
-    }
-    return ident;
-}
-
-mDNSexport void Querier_DeregisterCustomDNSService(const mdns_dns_service_id_t ident)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_deregister_custom_service(manager, ident);
-    }
-}
-
-mDNSexport mdns_dns_service_id_t Querier_RegisterNativeDNSService(const mdns_dns_service_definition_t dns_service_definition)
-{
-    mdns_dns_service_id_t ident = MDNS_DNS_SERVICE_INVALID_ID;
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        OSStatus err = kNoErr;
-        ident = mdns_dns_service_manager_register_native_service(manager, dns_service_definition, &err);
-        if (err != kNoErr)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-                "Failed to register native DNS service - error: %d.", (int)err);
-        }
-    }
-    return ident;
-}
-
-mDNSexport void Querier_DeregisterNativeDNSService(const mdns_dns_service_id_t ident)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_deregister_native_service(manager, ident);
-    }
-}
-
-mDNSexport void Querier_RegisterDoHURI(const char *doh_uri, const char *domain)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_register_doh_uri(manager, doh_uri, domain);
-    }
-}
-
-mDNSexport void Querier_ApplyDNSConfig(const dns_config_t *config)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_apply_dns_config(manager, config);
-        _Querier_LogDNSServices(manager);
-    }
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-mDNSlocal void _Querier_UpdateQuestionMetrics(DNSQuestion *const q, const mdns_querier_t querier)
-{
- 	if (querier && (mdns_querier_get_resolver_type(querier) != mdns_resolver_type_null))
-	{
-		q->metrics.querySendCount += mdns_querier_get_send_count(querier);
-	}
-}
-
-mDNSlocal void _Querier_UpdateDNSMessageSizeAnalytics(const mdns_querier_t querier)
-{
-	const mdns_dns_service_t dnsservice = (mdns_dns_service_t)mdns_querier_get_context(querier);
-	bool is_cellular = mdns_dns_service_interface_is_cellular(dnsservice);
-	dns_transport_t	transport = dnssd_analytics_dns_transport_for_resolver_type(mdns_querier_get_resolver_type(querier));
-	if (mdns_querier_get_send_count(querier) > 0)
-	{
-		const mDNSu32 len = mdns_querier_get_query_length(querier);
-		if (len > 0)
-		{
-			dnssd_analytics_update_dns_query_size(is_cellular, transport, len);
-		}
-	}
-	if ((mdns_querier_get_result_type(querier) == mdns_querier_result_type_response) &&
-		!mdns_querier_response_is_fabricated(querier))
-	{
-		const mDNSu32 len = mdns_querier_get_response_length(querier);
-		if (len > 0)
-		{
-			dnssd_analytics_update_dns_reply_size(is_cellular, transport, len);
-		}
-	}
-}
-#endif
-
-#define kOrphanedQuerierMaxCount 10
-
-mDNSlocal CFMutableSetRef _Querier_GetOrphanedQuerierSet(void)
-{
-    static CFMutableSetRef sOrphanedQuerierSet = NULL;
-    if (!sOrphanedQuerierSet)
-    {
-        static const CFSetCallBacks sSetCallbacks =
-        {
-            .version         = 0,
-            .retain          = mdns_cf_callback_retain,
-            .release         = mdns_cf_callback_release,
-            .copyDescription = mdns_cf_callback_copy_description
-        };
-        sOrphanedQuerierSet = CFSetCreateMutable(kCFAllocatorDefault, 0, &sSetCallbacks);
-    }
-    return sOrphanedQuerierSet;
-}
-
-mDNSlocal void _Querier_HandleQuerierResponse(const mdns_querier_t querier)
-{
-    KQueueLock();
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[Q%u] Handling concluded querier: %@", mdns_querier_get_user_id(querier), querier);
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    _Querier_UpdateDNSMessageSizeAnalytics(querier);
-#endif
-    mDNS *const m = &mDNSStorage;
-    const mdns_querier_result_type_t resultType = mdns_querier_get_result_type(querier);
-    const mdns_dns_service_t dnsservice = (mdns_dns_service_t)mdns_querier_get_context(querier);
-    if (resultType == mdns_querier_result_type_response)
-    {
-        if (!mdns_dns_service_is_defunct(dnsservice))
-        {
-            size_t copyLen = mdns_querier_get_response_length(querier);
-            if (copyLen > sizeof(m->imsg.m))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[Q%u] Large %lu-byte response will be truncated to fit mDNSCore's %lu-byte message buffer",
-                    mdns_querier_get_user_id(querier), (unsigned long)copyLen, (unsigned long)sizeof(m->imsg.m));
-                copyLen = sizeof(m->imsg.m);
-            }
-            memcpy(&m->imsg.m, mdns_querier_get_response_ptr(querier), copyLen);
-            const mDNSu8 *const end = ((mDNSu8 *)&m->imsg.m) + copyLen;
-            mDNSCoreReceiveForQuerier(m, &m->imsg.m, end, querier, dnsservice);
-        }
-    }
-    const CFMutableSetRef set = _Querier_GetOrphanedQuerierSet();
-    if (set)
-    {
-		CFSetRemoveValue(set, querier);
-    }
-    mDNSBool qIsNew = mDNSfalse;
-    DNSQuestion *q = Querier_GetDNSQuestion(querier, &qIsNew);
-    if (q)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-        _Querier_UpdateQuestionMetrics(q, q->querier);
-#endif
-        mdns_forget(&q->querier);
-        const mDNSBool needUpdatedQuerier = q->NeedUpdatedQuerier;
-        q->NeedUpdatedQuerier = mDNSfalse;
-        // If the DNSQuestion became suppressed, then it doesn't need a new querier.
-        // If the DNSQuestion is now on the m->NewQuestions sub-list (due to a restart), then it will be handled by the
-        // normal AnswerNewQuestion() code path, so don't start a new querier.
-        if (!q->Suppressed && !qIsNew)
-        {
-            mDNSBool startNewQuerier = mDNSfalse;
-            switch (resultType)
-            {
-                case mdns_querier_result_type_response:
-                    // If the querier was for a previous QNAME, then start a new querier for the new QNAME.
-                    startNewQuerier = needUpdatedQuerier;
-                    break;
-
-                case mdns_querier_result_type_timeout:
-                    // If the querier timed out, then the DNSQuestion was using an orphaned querier.
-                    // Querier_HandleUnicastQuestion() will attempt to give it a new querier.
-                    startNewQuerier = mDNStrue;
-                    break;
-
-                case mdns_querier_result_type_error:
-                    // The querier encountered a fatal error, which should be rare. There's nothing we can do but try again.
-                    // This usually happens if there's resource exhaustion, so be conservative and wait five seconds before
-                    // trying again.
-                    mDNS_Lock(m);
-                    q->ThisQInterval = 5 * mDNSPlatformOneSecond;
-                    q->LastQTime = m->timenow;
-                    SetNextQueryTime(m, q);
-                    mDNS_Unlock(m);
-                    break;
-
-                case mdns_querier_result_type_connection_problem:
-                    // If we haven't yet received the connection problem update from the DNS service manager, try to apply
-                    // it now, so that the DNSQuestion restart can notice that the DNS service is indeed having connection
-                    // problems. It could be that the overall connection problems status has cleared by the time we got
-                    // this connection problem result. Either way, restart the DNSQuestion and all of its duplicates so
-                    // that they can make progress.
-                    if (!mdns_dns_service_has_connection_problems(dnsservice))
-                    {
-                        const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-                        if (manager)
-                        {
-                            mdns_dns_service_manager_apply_pending_connection_problem_updates(manager);
-                        }
-                    }
-                    mDNS_Lock(m);
-                    // Re-assign the querier, so that if the DNSQuestion is the leader of a set of duplicates, we can
-                    // iteratively identify each subsequent duplicate as each member of the set gets restarted. This is
-                    // because when a DNSQuestion is stopped, its querier gets passed to the next duplicate if one exists.
-                    // If a duplicate doesn't exist, then the querier gets released.
-                    mdns_replace(&q->querier, querier);
-                    while (q)
-                    {
-                        mDNS_StopQuery_internal(m, q);
-                        q->UsedAsFailFastProbe = mDNStrue;
-                        mDNS_StartQuery_internal(m, q);
-                        q = Querier_GetDNSQuestion(querier, &qIsNew);
-                        if (q && qIsNew)
-                        {
-                            // If we reach the NewQuestions sub-list, we're done. Just forget the querier because it has
-                            // already concluded and is no longer useful. AnswerNewQuestion() will handle the new
-                            // DNSQuestion as normal.
-                            mdns_forget(&q->querier);
-                            q = mDNSNULL;
-                        }
-                    }
-                    mDNS_Unlock(m);
-                    break;
-
-                case mdns_querier_result_type_null:
-                case mdns_querier_result_type_invalidation:
-                case mdns_querier_result_type_resolver_invalidation:
-                    break;
-            }
-            if (startNewQuerier)
-            {
-                mDNS_Lock(m);
-                Querier_HandleUnicastQuestion(q);
-                mDNS_Unlock(m);
-            }
-        }
-    }
-    KQueueUnlock("_Querier_HandleQuerierResponse");
-}
-
-mDNSexport void Querier_HandleUnicastQuestion(DNSQuestion *q)
-{
-    mDNS *const m = &mDNSStorage;
-    mdns_querier_t querier = NULL;
-
-    if (q->querier || !q->dnsservice)
-    {
-        if (q->querier)
-        {
-            q->NeedUpdatedQuerier = !mdns_querier_match(q->querier, q->qname.c, q->qtype, q->qclass);
-        }
-        goto exit;
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    const bool needDNSSEC = dns_question_is_primary_dnssec_requestor(q);
-#endif
-    const CFMutableSetRef set = _Querier_GetOrphanedQuerierSet();
-    if (set)
-    {
-        __block mdns_querier_t orphan = NULL;
-        mdns_cfset_enumerate(set,
-        ^ bool (const mdns_querier_t _Nonnull candidate)
-        {
-            const mdns_dns_service_t dnsservice = (mdns_dns_service_t)mdns_querier_get_context(candidate);
-            if ((dnsservice == q->dnsservice) && mdns_querier_match(candidate, q->qname.c, q->qtype, q->qclass))
-            {
-            #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                if ((mdns_querier_get_dnssec_ok(candidate) == needDNSSEC) &&
-                    (mdns_querier_get_checking_disabled(candidate) == needDNSSEC))
-            #endif
-                {
-                    orphan = candidate;
-                }
-            }
-            const bool proceed = (orphan == NULL);
-            return proceed;
-        });
-        if (orphan)
-        {
-            q->querier = orphan;
-            mdns_retain(q->querier);
-            CFSetRemoveValue(set, q->querier);
-            mdns_querier_set_time_limit_ms(q->querier, 0);
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u->Q%u] Adopted orphaned querier", mDNSVal16(q->TargetQID), mdns_querier_get_user_id(q->querier));
-        }
-    }
-    if (!q->querier)
-    {
-        querier = mdns_dns_service_create_querier(q->dnsservice, NULL);
-        require_quiet(querier, exit);
-
-        const OSStatus err = mdns_querier_set_query(querier, q->qname.c, q->qtype, q->qclass);
-        require_noerr_quiet(err, exit);
-
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        if (needDNSSEC)
-        {
-            mdns_querier_set_dnssec_ok(querier, true);
-            mdns_querier_set_checking_disabled(querier, true);
-        }
-    #endif
-        if (q->pid != 0)
-        {
-            mdns_querier_set_delegator_pid(querier, q->pid);
-        }
-        else
-        {
-            mdns_querier_set_delegator_uuid(querier, q->uuid);
-        }
-        mdns_retain(q->dnsservice);
-        mdns_querier_set_context(querier, q->dnsservice);
-        mdns_querier_set_context_finalizer(querier, mdns_object_context_finalizer);
-        mdns_querier_set_queue(querier, _Querier_InternalQueue());
-        mdns_retain(querier);
-        mdns_querier_set_result_handler(querier,
-        ^{
-            _Querier_HandleQuerierResponse(querier);
-            mdns_release(querier);
-        });
-        mdns_querier_set_log_label(querier, "Q%u", mDNSVal16(q->TargetQID));
-        mdns_querier_set_user_id(querier, mDNSVal16(q->TargetQID));
-        q->querier = querier;
-        mdns_retain(q->querier);
-        mdns_querier_activate(q->querier);
-    }
-    q->NeedUpdatedQuerier = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-    if (mdns_querier_get_resolver_type(q->querier) != mdns_resolver_type_null)
-    {
-        if (q->metrics.answered)
-        {
-            uDNSMetricsClear(&q->metrics);
-        }
-        if (q->metrics.firstQueryTime == 0)
-        {
-            q->metrics.firstQueryTime = NonZeroTime(m->timenow);
-        }
-    }
-    else
-    {
-        q->metrics.firstQueryTime = 0;
-    }
-#endif
-
-exit:
-    q->ThisQInterval = (!q->dnsservice || q->querier) ? FutureTime : mDNSPlatformOneSecond;
-    q->LastQTime = m->timenow;
-    SetNextQueryTime(m, q);
-    mdns_forget(&querier);
-}
-
-mDNSlocal mDNSu32 _Querier_GetQuestionCount(void)
-{
-    mDNSu32 count = 0;
-    for (const DNSQuestion *q = mDNSStorage.Questions; q; q = q->next)
-    {
-        count++;
-    }
-    return count;
-}
-
-mDNSexport void Querier_ProcessDNSServiceChanges(void)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSu32 slot;
-    CacheGroup *cg;
-    CacheRecord *cr;
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    DNSPushServer **psp;
-#endif
-
-    const mDNSu32 count = _Querier_GetQuestionCount();
-    m->RestartQuestion = m->Questions;
-    for (mDNSu32 i = 0; (i < count) && m->RestartQuestion; i++)
-    {
-        DNSQuestion *const q = m->RestartQuestion;
-        if (mDNSOpaque16IsZero(q->TargetQID))
-        {
-            m->RestartQuestion = q->next;
-            continue;
-        }
-        const mDNSBool excludeEncryptedDNS = _Querier_ExcludeEncryptedDNSServices(q);
-        mdns_dns_service_t newService = _Querier_GetDNSService(q, excludeEncryptedDNS);
-        mDNSBool forcePathEval = mDNSfalse;
-        if (q->dnsservice != newService)
-        {
-            // If the DNS service would change, the DNSQuestion is not interface-scoped, and either there is no new DNS
-            // service or it lacks privacy, then force a path evaluation when the DNSQuestion restarts to determine if
-            // there's a DNS service that offers privacy that should be used. This DNSQuestion's resolver UUID may have
-            // been cleared so that it can use a VPN DNS service, but that service may have just become defunct.
-            if (!q->InterfaceID && (!newService || _Querier_DNSServiceIsUnscopedAndLacksPrivacy(newService)))
-            {
-                forcePathEval = mDNStrue;
-            }
-        }
-        else
-        {
-            // If the DNS service wouldn't change and the DNS service is UUID-scoped, perform a path evaluation now to
-            // see if a DNS service change occurs. This might happen if a DNSQuestion was UUID-scoped to a DoH or DoT
-            // service, but there's a new VPN DNS service that handles the DNSQuestion's QNAME.
-            if (q->dnsservice && (mdns_dns_service_get_scope(q->dnsservice) == mdns_dns_service_scope_uuid))
-            {
-                mDNSPlatformGetDNSRoutePolicy(q);
-                newService = _Querier_GetDNSService(q, excludeEncryptedDNS);
-            }
-        }
-        mDNSBool restart = mDNSfalse;
-        if (q->dnsservice != newService)
-        {
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-            // If this question had a DNS Push server associated with it, substitute the new server for the
-            // old one.   If there is no new server, then we'll clean up the push server later.
-            if (!q->DuplicateOf && q->dnsPushServer)
-            {
-                if (q->dnsPushServer->dnsservice == q->dnsservice)
-                {
-                    mdns_replace(&q->dnsPushServer->dnsservice, newService);
-                }
-                // If it is null, cancel the DNS push server.
-                if (!q->dnsPushServer->dnsservice)
-                {
-                    DNSPushServerCancel(q->dnsPushServer, mDNSfalse);
-                }
-            }
-#endif
-            restart = mDNStrue;
-        }
-        else
-        {
-            mDNSBool newSuppressed = ShouldSuppressUnicastQuery(q, newService);
-            if (!q->Suppressed != !newSuppressed) restart = mDNStrue;
-        }
-        if (restart)
-        {
-            if (!q->Suppressed)
-            {
-                CacheRecordRmvEventsForQuestion(m, q);
-                if (m->RestartQuestion == q) LocalRecordRmvEventsForQuestion(m, q);
-            }
-            if (m->RestartQuestion == q)
-            {
-            #if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-                // Since we are restarting the question, retain the resolver discovery object to prevent it from being
-                // stopped and deallocated.
-                const domainname *domain_to_discover_resolver = mDNSNULL;
-                if (dns_question_requires_resolver_discovery(q, &domain_to_discover_resolver))
-                {
-                    resolver_discovery_add(domain_to_discover_resolver, mDNSfalse);
-                }
-            #endif
-                mDNS_StopQuery_internal(m, q);
-                q->ForcePathEval = forcePathEval;
-                q->next = mDNSNULL;
-                mDNS_StartQuery_internal(m, q);
-            #if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-                // Release the resolver discovery object retained above so that the reference count of the object goes
-                // back to its original value, after the restart process has finished.
-                if (dns_question_requires_resolver_discovery(q, &domain_to_discover_resolver))
-                {
-                    resolver_discovery_remove(domain_to_discover_resolver, mDNSfalse);
-                }
-            #endif
-            }
-        }
-        if (m->RestartQuestion == q) m->RestartQuestion = q->next;
-    }
-    m->RestartQuestion = mDNSNULL;
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    // The above code may have found some DNS Push servers that are no longer valid.   Now that we
-    // are done running through the code, we need to drop our connections to those servers.
-    // When we get here, any such servers should have zero questions associated with them.
-    for (psp = &m->DNSPushServers; *psp != mDNSNULL; )
-    {
-        DNSPushServer *server = *psp;
-
-        // It's possible that a push server whose DNS server has been deleted could be still connected but
-        // not referenced by any questions.  In this case, we just delete the push server rather than trying
-        // to figure out with which DNS server (if any) to associate it.
-        if (server->dnsservice == mDNSNULL || mdns_dns_service_is_defunct(server->dnsservice))
-        {
-            // Since we are changing the m->DNSPushServers that DNSPushServerCancel() will iterate later, we will do the
-            // server removal for it. And tell it to not touch the m->DNSPushServers by passing alreadyRemovedFromSystem
-            // == true.
-            // Unlink from the m->DNSPushServers list.
-            *psp = server->next;
-            server->next = mDNSNULL;
-            // Release all the DNS push zones that use this server from the m->DNSPushZones list.
-            DNSPushZoneRemove(m, server);
-            // Cancel the server.
-            DNSPushServerCancel(server, mDNStrue);
-            // Release the reference to the server that m->DNSPushServers list holds.
-            DNS_PUSH_RELEASE(server, DNSPushServerFinalize);
-        }
-        else
-        {
-            psp = &(server->next);
-        }
-    }
-#endif
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if (cr->resrec.InterfaceID) continue;
-        if (!cr->resrec.dnsservice || mdns_dns_service_is_defunct(cr->resrec.dnsservice))
-        {
-            mdns_forget(&cr->resrec.dnsservice);
-            mDNS_PurgeCacheResourceRecord(m, cr);
-        }
-    }
-}
-
-mDNSexport DNSQuestion *Querier_GetDNSQuestion(const mdns_querier_t querier, mDNSBool *const outIsNew)
-{
-    DNSQuestion *q;
-    mDNS *const m = &mDNSStorage;
-    mDNSBool isNew = mDNSfalse;
-    for (q = m->Questions; q; q = q->next)
-    {
-        if (!isNew && (q == m->NewQuestions))
-        {
-            isNew = mDNStrue;
-        }
-        if (q->querier == querier)
-        {
-            break;
-        }
-    }
-    if (outIsNew)
-    {
-        *outIsNew = q ? isNew : mDNSfalse;
-    }
-    return q;
-}
-
-mDNSexport mDNSBool Querier_ResourceRecordIsAnswer(const ResourceRecord * const rr, const mdns_querier_t querier)
-{
-    mDNSBool isAnswer;
-    const mDNSu16 qtype = mdns_querier_get_qtype(querier);
-    const mDNSu8 *const qname = mdns_querier_get_qname(querier);
-
-    if (qname == mDNSNULL)
-    {
-        isAnswer = mDNSfalse;
-        goto exit;
-    }
-
-    if (rr->rrclass != mdns_querier_get_qclass(querier))
-    {
-        isAnswer = mDNSfalse;
-        goto exit;
-    }
-
-    RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    const mDNSBool requiresRRToValidate = mdns_querier_get_dnssec_ok(querier) && mdns_querier_get_checking_disabled(querier);
-    if (requiresRRToValidate)
-    {
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-    }
-#endif
-
-    isAnswer = RRTypeAnswersQuestionType(rr, qtype, flags);
-    if (!isAnswer)
-    {
-        goto exit;
-    }
-
-    isAnswer = SameDomainName(rr->name, (const domainname *)qname);
-
-exit:
-    return isAnswer;
-}
-
-mDNSexport mDNSBool Querier_SameNameCacheRecordIsAnswer(const CacheRecord *const cr, const mdns_querier_t querier)
-{
-    mDNSBool isAnswer;
-    const ResourceRecord *const rr = &cr->resrec;
-    const mDNSu16 qtype = mdns_querier_get_qtype(querier);
-
-    if (rr->rrclass != mdns_querier_get_qclass(querier))
-    {
-        isAnswer = mDNSfalse;
-        goto exit;
-    }
-
-    RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    const mDNSBool requiresRRToValidate = mdns_querier_get_dnssec_ok(querier) && mdns_querier_get_checking_disabled(querier);
-    if (requiresRRToValidate)
-    {
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-    }
-#endif
-    isAnswer = RRTypeAnswersQuestionType(rr, qtype, flags);
-
-exit:
-    return isAnswer;
-}
-
-#define kOrphanedQuerierTimeLimitSecs 5
-
-mDNSexport void Querier_HandleStoppedDNSQuestion(DNSQuestion *q)
-{
-    if (q->querier && !mdns_querier_has_concluded(q->querier))
-    {
-        const mdns_dns_service_t dnsservice = (mdns_dns_service_t)mdns_querier_get_context(q->querier);
-        if (!mdns_dns_service_is_defunct(dnsservice))
-        {
-            const CFMutableSetRef set = _Querier_GetOrphanedQuerierSet();
-            if (set && (CFSetGetCount(set) < kOrphanedQuerierMaxCount))
-            {
-				CFSetAddValue(set, q->querier);
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[Q%u] Keeping orphaned querier for up to " StringifyExpansion(kOrphanedQuerierTimeLimitSecs) " seconds",
-                    mdns_querier_get_user_id(q->querier));
-                mdns_querier_set_time_limit_ms(q->querier, kOrphanedQuerierTimeLimitSecs * 1000);
-                mdns_forget(&q->querier);
-            }
-        }
-    }
-    mdns_querier_forget(&q->querier);
-    mdns_forget(&q->dnsservice);
-}
-
-mDNSexport mdns_querier_t Querier_HandlePreCNAMERestart(DNSQuestion *const q)
-{
-    q->lastDNSServiceID = q->dnsservice ? mdns_dns_service_get_id(q->dnsservice) : MDNS_DNS_SERVICE_MAX_ID;
-    const mdns_querier_t querier = q->querier;
-    q->querier = NULL;
-    return querier;
-}
-
-mDNSexport void Querier_HandlePostCNAMERestart(DNSQuestion *const q, const mdns_querier_t querier)
-{
-    if (querier)
-    {
-        mDNSBool keptQuerier = mDNSfalse;
-        if (!q->DuplicateOf && !q->querier && q->dnsservice)
-        {
-            const mdns_dns_service_t dnsservice = (mdns_dns_service_t)mdns_querier_get_context(querier);
-            if (mdns_dns_service_get_id(q->dnsservice) == mdns_dns_service_get_id(dnsservice))
-            {
-                q->querier = querier;
-                mdns_retain(q->querier);
-                keptQuerier = mDNStrue;
-            }
-        }
-        if (!keptQuerier)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-            _Querier_UpdateQuestionMetrics(q, querier);
-#endif
-            mdns_querier_invalidate(querier);
-        }
-    }
-}
-
-mDNSexport void Querier_PrepareQuestionForUnwindRestart(DNSQuestion *const q)
-{
-    q->lastDNSServiceID = MDNS_DNS_SERVICE_INVALID_ID;
-    // Force a path evaluation if the DNSQuestion isn't interface-scoped.
-    if (!q->InterfaceID)
-    {
-        q->ForcePathEval = mDNStrue;
-    }
-}
-
-mDNSexport void Querier_HandleSleep(void)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_handle_sleep(manager);
-    }
-}
-
-mDNSexport void Querier_HandleWake(void)
-{
-    const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-    if (manager)
-    {
-        mdns_dns_service_manager_handle_wake(manager);
-    }
-}
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
diff --git a/mDNSMacOSX/QuerierSupport.h b/mDNSMacOSX/QuerierSupport.h
deleted file mode 100644
index 195d038..0000000
--- a/mDNSMacOSX/QuerierSupport.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __QUERIER_SUPPORT_H__
-#define __QUERIER_SUPPORT_H__
-
-#include "mDNSEmbeddedAPI.h"
-#include <mdns/private.h>
-
-// Threshold value for problematic QTYPE workaround.
-extern int PQWorkaroundThreshold;
-
-extern mdns_dns_service_manager_t Querier_GetDNSServiceManager(void);
-extern void Querier_SetDNSServiceForQuestion(DNSQuestion *q);
-extern void Querier_ApplyDNSConfig(const dns_config_t *config);
-extern void Querier_HandleUnicastQuestion(DNSQuestion *q);
-extern void Querier_ProcessDNSServiceChanges(void);
-extern void Querier_RegisterPathResolver(const uuid_t resolverUUID);
-extern mdns_dns_service_id_t Querier_RegisterCustomDNSService(xpc_object_t resolverConfigDict);
-extern mdns_dns_service_id_t Querier_RegisterCustomDNSServiceWithPListData(const uint8_t *dataPtr, size_t dataLen);
-extern void Querier_DeregisterCustomDNSService(mdns_dns_service_id_t ident);
-extern mdns_dns_service_id_t Querier_RegisterNativeDNSService(mdns_dns_service_definition_t dns_service_definition);
-extern void Querier_DeregisterNativeDNSService(mdns_dns_service_id_t ident);
-extern DNSQuestion *Querier_GetDNSQuestion(mdns_querier_t querier, mDNSBool *outIsNew);
-extern mDNSBool Querier_ResourceRecordIsAnswer(const ResourceRecord *rr, mdns_querier_t querier);
-extern mDNSBool Querier_SameNameCacheRecordIsAnswer(const CacheRecord *cr, mdns_querier_t querier);
-extern void Querier_HandleStoppedDNSQuestion(DNSQuestion *q);
-extern void Querier_RegisterDoHURI(const char *doh_uri, const char *domain);
-extern mdns_querier_t Querier_HandlePreCNAMERestart(DNSQuestion *q);
-extern void Querier_HandlePostCNAMERestart(DNSQuestion *q, mdns_querier_t querier);
-extern void Querier_PrepareQuestionForUnwindRestart(DNSQuestion *q);
-extern void Querier_HandleSleep(void);
-extern void Querier_HandleWake(void);
-
-#endif  // __QUERIER_SUPPORT_H__
diff --git a/mDNSMacOSX/SettingsBundle/BonjourConstants.h b/mDNSMacOSX/SettingsBundle/BonjourConstants.h
deleted file mode 100644
index 189b58d..0000000
--- a/mDNSMacOSX/SettingsBundle/BonjourConstants.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-//  BonjourSettingsController.m
-//  mDNSResponder
-//
-//  Created by Phil on 7/28/16.
-//
-//
-
-#import <Preferences/Preferences.h>
-
-@interface BonjourSettingsController: PSListItemsController {
-    
-}
-
-@end
diff --git a/mDNSMacOSX/SettingsBundle/BonjourSCStore.h b/mDNSMacOSX/SettingsBundle/BonjourSCStore.h
deleted file mode 100644
index 15b12a6..0000000
--- a/mDNSMacOSX/SettingsBundle/BonjourSCStore.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <SystemConfiguration/SystemConfiguration.h>
-#import <Security/Security.h>
-
-#define SC_DYNDNS_PREFS_KEY         CFSTR("com.apple.preference.bonjour")
-#define SC_DYNDNS_SYSTEM_KEY        CFSTR("/System/Network/DynamicDNS")
-#define SC_DYNDNS_REGDOMAINS_KEY    CFSTR("RegistrationDomains")
-#define SC_DYNDNS_BROWSEDOMAINS_KEY CFSTR("BrowseDomains")
-#define SC_DYNDNS_HOSTNAMES_KEY     CFSTR("HostNames")
-#define SC_DYNDNS_DOMAIN_KEY        CFSTR("Domain")
-#define SC_DYNDNS_KEYNAME_KEY       CFSTR("KeyName")
-#define SC_DYNDNS_SECRET_KEY        CFSTR("Secret")
-#define SC_DYNDNS_ENABLED_KEY       CFSTR("Enabled")
-#define SC_DYNDNS_STATUS_KEY        CFSTR("Status")
-
-#define SC_DYNDNS_SETUP_KEY         CFSTR("Setup:/Network/DynamicDNS")
-#define SC_DYNDNS_STATE_KEY         CFSTR("State:/Network/DynamicDNS")
-
-@interface BonjourSCStore : NSObject
-
-+ (NSArray *_Nullable)objectForKey:(NSString *_Nonnull)key;
-+ (void)setObject:(NSArray *_Nullable)value forKey:(NSString *_Nonnull)key;
-
-@end
diff --git a/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h b/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h
deleted file mode 100644
index 0f3d95b..0000000
--- a/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <Preferences/Preferences.h>
-
-@interface BonjourSettingsController: PSListItemsController {
-    
-}
-
-@end
diff --git a/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h b/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h
deleted file mode 100644
index da6813e..0000000
--- a/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <UIKit/UIKit.h>
-
-@protocol CNBrowseDomainsDelegate;
-
-@interface CNBrowseDomainsController : UITableViewController
-
-@property (weak)   IBOutlet			id<CNBrowseDomainsDelegate> delegate;
-@property (strong)                  NSArray *                   browseDomainsA;
-
-- (void)addBrowseDomain:(NSString *)fullPath;
-
-@end
-
-@protocol CNBrowseDomainsDelegate <NSObject>
-
-@optional
-
-- (void)domainBrowserDomainSelected:(NSString *)domain;
-
-@end
diff --git a/mDNSMacOSX/SettingsBundle/HostnameController.h b/mDNSMacOSX/SettingsBundle/HostnameController.h
deleted file mode 100644
index f683546..0000000
--- a/mDNSMacOSX/SettingsBundle/HostnameController.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * Copyright (c) 2016 Apple 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.
- */
-
-#import <UIKit/UIKit.h>
-
-@interface HostnameController : UITableViewController {
-    
-}
-@property (strong) NSString *               bonjourHostname;
-
-@end
diff --git a/mDNSMacOSX/SymptomReporter.c b/mDNSMacOSX/SymptomReporter.c
deleted file mode 100644
index ec6fea0..0000000
--- a/mDNSMacOSX/SymptomReporter.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2015-2019 Apple 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.
- */
-
-#include "SymptomReporter.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "mdns_strict.h"
-#include <arpa/inet.h>
-#include <dlfcn.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/socket.h>
-#include <AvailabilityMacros.h>
-#include <SymptomReporter/SymptomReporter.h>
-
-#define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID  101
-#define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID     "com.apple.mDNSResponder"
-
-#define SYMPTOM_DNS_NO_REPLIES          0x00065001
-#define SYMPTOM_DNS_RESUMED_RESPONDING  0x00065002
-
-mDNSu32 NumUnreachableDNSServers;
-
-static symptom_framework_t symptomReporter = mDNSNULL;
-static symptom_framework_t (*symptom_framework_init_f)(symptom_ident_t id, const char *originator_string) = mDNSNULL;
-static symptom_t (*symptom_new_f)(symptom_framework_t framework, symptom_ident_t id) = mDNSNULL;
-static int (*symptom_set_additional_qualifier_f)(symptom_t symptom, uint32_t qualifier_type, size_t qualifier_len, void *qualifier_data) = mDNSNULL;
-static int (*symptom_send_f)(symptom_t symptom) = mDNSNULL;
-
-mDNSlocal mStatus SymptomReporterInitCheck(void)
-{
-    mStatus err;
-    static mDNSBool triedInit = mDNSfalse;
-    static void *symptomReporterLib = mDNSNULL;
-    static const char path[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter";
-
-    if (!triedInit)
-    {
-        triedInit = mDNStrue;
-
-        symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
-        if (!symptomReporterLib)
-            goto exit;
-
-        symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init");
-        if (!symptom_framework_init_f)
-            goto exit;
-
-        symptom_new_f = dlsym(symptomReporterLib, "symptom_new");
-        if (!symptom_new_f)
-            goto exit;
-
-        symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier");
-        if (!symptom_set_additional_qualifier_f)
-            goto exit;
-
-        symptom_send_f = dlsym(symptomReporterLib, "symptom_send");
-        if (!symptom_send_f)
-            goto exit;
-
-        symptomReporter = symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID);
-    }
-
-exit:
-    err = symptomReporter ? mStatus_NoError : mStatus_NotInitializedErr;
-    return err;
-}
-
-mDNSlocal mStatus SymptomReporterReportDNSReachability(const mDNSAddr *addr, mDNSBool isReachable)
-{
-    mStatus err;
-    symptom_t symptom;
-    struct sockaddr_storage sockAddr;
-    size_t sockAddrSize;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "SymptomReporterReportDNSReachability: DNS server " PRI_IP_ADDR " is " PUB_S "reachable", addr, isReachable ? "" : "un");
-
-    if (addr->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *sin = (struct sockaddr_in *)&sockAddr;
-        sockAddrSize = sizeof(*sin);
-        mDNSPlatformMemZero(sin, sockAddrSize);
-        sin->sin_len = sockAddrSize;
-        sin->sin_family = AF_INET;
-        sin->sin_addr.s_addr = addr->ip.v4.NotAnInteger;
-    }
-    else if (addr->type == mDNSAddrType_IPv6)
-    {
-        struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&sockAddr;
-        sockAddrSize = sizeof(*sin6);
-        mDNSPlatformMemZero(sin6, sockAddrSize);
-        sin6->sin6_len = sockAddrSize;
-        sin6->sin6_family = AF_INET6;
-        sin6->sin6_addr = *(struct in6_addr *)&addr->ip.v6;
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "SymptomReporterReportDNSReachability: addr is not an IPv4 or IPv6 address!");
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    symptom = symptom_new_f(symptomReporter, isReachable ? SYMPTOM_DNS_RESUMED_RESPONDING : SYMPTOM_DNS_NO_REPLIES);
-    symptom_set_additional_qualifier_f(symptom, 1, sockAddrSize, (void *)&sockAddr);
-    symptom_send_f(symptom);
-    err = mStatus_NoError;
-
-exit:
-    return err;
-}
-
-mDNSexport mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr)
-{
-    mStatus err;
-    DNSServer *s;
-    mDNSBool found = mDNSfalse;
-
-    err = SymptomReporterInitCheck();
-    if (err != mStatus_NoError)
-        goto exit;
-
-    for (s = m->DNSServers; s; s = s->next)
-    {
-        if (s->flags & DNSServerFlag_Delete)
-            continue;
-        if ((s->flags & DNSServerFlag_Unreachable) && mDNSSameAddress(addr, &s->addr))
-        {
-            s->flags &= ~DNSServerFlag_Unreachable;
-            NumUnreachableDNSServers--;
-            found = mDNStrue;
-        }
-    }
-
-    if (!found)
-    {
-        err = mStatus_NoSuchNameErr;
-        goto exit;
-    }
-
-    err = SymptomReporterReportDNSReachability(addr, mDNStrue);
-
-exit:
-    return err;
-}
-
-mDNSexport mStatus SymptomReporterDNSServerUnreachable(DNSServer *s)
-{
-    mStatus err;
-
-    err = SymptomReporterInitCheck();
-    if (err != mStatus_NoError)
-        goto exit;
-
-    if ((s->flags & DNSServerFlag_Delete) || (s->flags & DNSServerFlag_Unreachable))
-        goto exit;
-
-    s->flags |= DNSServerFlag_Unreachable;
-    NumUnreachableDNSServers++;
-
-    err = SymptomReporterReportDNSReachability(&s->addr, mDNSfalse);
-
-exit:
-    return err;
-}
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
diff --git a/mDNSMacOSX/SymptomReporter.h b/mDNSMacOSX/SymptomReporter.h
deleted file mode 100644
index 75c3bdc..0000000
--- a/mDNSMacOSX/SymptomReporter.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2018 Apple 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.
- */
-
-#ifndef __SymptomReporter_h
-#define __SymptomReporter_h
-
-#include "mDNSEmbeddedAPI.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS) && !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-extern mDNSu32 NumUnreachableDNSServers;
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-extern mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr);
-extern mStatus SymptomReporterDNSServerUnreachable(DNSServer *s);
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
-#endif // __SymptomReporter_h
diff --git a/mDNSMacOSX/Tests/Fuzzing/DNSMessageToString.c b/mDNSMacOSX/Tests/Fuzzing/DNSMessageToString.c
deleted file mode 100644
index 7393e43..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/DNSMessageToString.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stddef.h>
-
-#include <mdns/DNSMessage.h>
-
-#ifdef FUZZING_DNSMESSAGETOSTRING
-int LLVMFuzzerTestOneInput(const char* Data, const size_t Length)
-{
-    if(Length < 2) {
-        return 0;
-    }
-
-    int flags = Data[0];
-    uint8_t* copy = malloc(Length - 1);
-    char* outString = NULL;
-
-    memcpy(copy, Data+1, Length - 1);
-
-    DNSMessageToString(copy, Length - 1, (DNSMessageToStringFlags) flags, &outString);
-
-    free(copy);
-    if(outString) {
-        free(outString);
-    }
-
-    return 0;
-}
-#endif
diff --git a/mDNSMacOSX/Tests/Fuzzing/dns_message_received.c b/mDNSMacOSX/Tests/Fuzzing/dns_message_received.c
deleted file mode 100644
index 92d373d..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/dns_message_received.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* dns_message_received.c
- *
- * Copyright (c) 2020-2021 Apple 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
- *
- *     https://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.
- *
- */
-
-#include <stdio.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <string.h>
-#include <assert.h>
-
-#include <netdb.h>              // For gethostbyname()
-#include <sys/socket.h>         // For AF_INET, AF_INET6, etc.
-#include <net/if.h>             // For IF_NAMESIZE
-#include <netinet/in.h>         // For INADDR_NONE
-#include <netinet/tcp.h>        // For SOL_TCP, TCP_NOTSENT_LOWAT
-#include <arpa/inet.h>          // For inet_addr()
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "dns_sd.h"
-#include "DNSCommon.h"
-#include "mDNSEmbeddedAPI.h"
-#include "dso.h"
-#include "dso-transport.h"
-
-#ifdef FUZZING_DNS_MESSAGE_RECEIVED
-
-/*
-typedef struct
-{
-    mDNSOpaque16 id;
-    mDNSOpaque16 flags;
-    mDNSu16 numQuestions;
-    mDNSu16 numAnswers;
-    mDNSu16 numAuthorities;
-    mDNSu16 numAdditionals;
-} DNSMessageHeader;
-*/
-
-/*
-struct dso_state {
-    dso_state_t *next;
-    void *context;                   // The context of the next layer up (e.g., a Discovery Proxy)
-    dso_event_callback_t cb;         // Called when an event happens
-
-    // Transport state; handled separately for reusability
-    dso_transport_t *transport;      // The transport (e.g., dso-transport.c or other).
-    dso_transport_finalize_t transport_finalize;
-
-    uint32_t serial;                 // Unique serial number which can be used after the DSO has been dropped.
-    bool is_server;                  // True if the endpoint represented by this DSO state is a server
-                                     // (according to the DSO spec)
-    bool has_session;                // True if DSO session establishment has happened for this DSO endpoint
-    event_time_t response_awaited;   // If we are waiting for a session-establishing response, when it's
-                                     // expected; otherwise zero.
-    uint32_t keepalive_interval;     // Time between keepalives (to be sent, on client, expected, on server)
-    uint32_t inactivity_timeout;     // Session can't be inactive more than this amount of time.
-    event_time_t keepalive_due;      // When the next keepalive is due (to be received or sent)
-    event_time_t inactivity_due;     // When next activity has to happen for connection to remain active
-    dso_activity_t *activities;      // Outstanding DSO activities.
-
-    dso_tlv_t primary;               // Primary TLV for current message
-    dso_tlv_t additl[MAX_ADDITLS];   // Additional TLVs
-    int num_additls;                 // Number of additional TLVs in this message
-
-    char *remote_name;
-
-    dso_outstanding_query_state_t *outstanding_queries;
-};
-*/
-
-dso_state_t *dso_state_create(bool is_server, int max_outstanding_queries, const char *remote_name,
-                              dso_event_callback_t callback, void *const context,
-                              const dso_life_cycle_context_callback_t context_callback,
-                              dso_transport_t *transport);
-
-void dns_message_received(dso_state_t *dso, const uint8_t *message, size_t message_length);
-
-int
-LLVMFuzzerTestOneInput
-(
-    const char      * Data,
-    const size_t    Length
-)
-{
-    if(Length < sizeof(DNSMessageHeader)) {
-        return 0;
-    }
-
-    dso_state_t            *dso = dso_state_create(false, 1, "remote", 0, 0, 0, 0);
-    DNSMessageHeader    message;
-
-    memcpy(&message, Data, sizeof(message));
-
-    // dns_message_received(dso, (char*) &message, Length);
-
-    free(dso);
-
-    return 0;
-}
-
-
-
-#endif /* ifdef FUZZING_DNS_MESSAGE_RECEIVED */
diff --git a/mDNSMacOSX/Tests/Fuzzing/dns_wire_parse.c b/mDNSMacOSX/Tests/Fuzzing/dns_wire_parse.c
deleted file mode 100644
index 6272f34..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/dns_wire_parse.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "srp.h"
-#include "dns-msg.h"
-
-#ifdef FUZZING_DNS_WIRE_PARSE
-int LLVMFuzzerTestOneInput(const char* Data, const size_t Length)
-{
-    dns_message_t *message = 0;
-    dns_wire_t wire = {0};
-    unsigned len = (unsigned) Length;
-
-    // At least one byte of data is needed
-    if (Length < 1 + __builtin_offsetof(dns_wire_t, data))
-        return 0;
-
-    // Too much data
-    if (Length > sizeof(wire))
-        return 0;
-
-    // Initialize the wire struct with the fuzzing data
-    memcpy(&wire, Data, Length);
-
-    // Parse!
-    dns_wire_parse(&message, &wire, len);
-
-    if(message)
-        free(message);
-
-    return 0;
-}
-#endif
diff --git a/mDNSMacOSX/Tests/Fuzzing/icmp_callback.c b/mDNSMacOSX/Tests/Fuzzing/icmp_callback.c
deleted file mode 100644
index 70c5c94..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/icmp_callback.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "srp.h"
-#include "dns-msg.h"
-
-#include "ioloop.h"
-#include "srp-gw.h"
-#include "srp-proxy.h"
-#include "srp-mdns-proxy.h"
-#include "route.h"
-
-#ifdef FUZZING_ICMP_CALLBACK
-
-void icmp_callback(io_t *io, void *context);
-extern interface_t *interfaces;
-extern char *thread_interface_name;
-interface_t interface = {0};
-
-void hexdump(const char* Data, ssize_t Length) {
-    for(ssize_t i = 0; i < Length; i++) {
-        dprintf(2, "%02x", (unsigned char) Data[i]);
-    }
-    dprintf(2, "\n");
-}
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
-    interfaces = &interface;
-    interface.next = 0;
-    interface.name = "fuzz0";
-    // interface.deconfigure_wakeup = calloc(sizeof(interface.deconfigure_wakeup), 1);
-
-    thread_interface_name = "fuzz0";
-
-    return 0;
-}
-
-
-int LLVMFuzzerTestOneInput(const char* Data, const size_t Length)
-{
-    io_t io = {0};
-    ssize_t written = 0;
-
-    // Minimum size for ICMP header
-    if(Length < 8) {
-        return 0;
-    }
-
-    // hexdump(Data, Length);
-
-    int filedes[2];
-    if(pipe(filedes)) {
-        perror("pipe(2) failed!");
-        return 1;
-    }
-
-    written = write(filedes[1], Data, Length);
-    if(written <= 0) {
-        return 1;
-    }
-
-    io.fd = filedes[0];
-    icmp_callback(&io, 0);
-
-    close(filedes[0]);
-    close(filedes[1]);
-
-    return 0;
-}
-#endif
diff --git a/mDNSMacOSX/Tests/Fuzzing/mDNS_snprintf.c b/mDNSMacOSX/Tests/Fuzzing/mDNS_snprintf.c
deleted file mode 100644
index 17fd80a..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/mDNS_snprintf.c
+++ /dev/null
@@ -1,120 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "DNSCommon.h"
-
-#ifdef FUZZING_MDNS_SNPRINTF
-
-void hexdump(const void* Data, ssize_t Length) {
-    const uint8_t* bytes = (const uint8_t*) Data;
-    dprintf(2, "[%4d] ", Length);
-    for(ssize_t i = 0; i < Length; i++) {
-        dprintf(2, "%02x", bytes[i]);
-    }
-    dprintf(2, "\n");
-}
-
-// Large enough to be a uint64_t
-const size_t numBuffers = 32;
-const size_t bufferSize = 16; // Large enough to hold an IPv6 address
-char **buffers[numBuffers];
-
-size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
-size_t LLVMFuzzerCustomMutator(char *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
-    Size = LLVMFuzzerMutate((uint8_t*) Data, Size, MaxSize);
-
-    // Ensure there is a NULL terminator somewhere in the buffer
-    Data[MaxSize-3] = '\0';
-    Size = strlen(Data) + 1;
-
-    // Input values for the format buffer will be ASCII printable
-    for(size_t i = 0; i < Size; i++) {
-        Data[i] = Data[i] & 0x7f;
-    }
-
-    // Only have up to numBuffers format specifiers
-    // XXX: Can actually only have half that amount, because e.g. %.*s consumes two values
-    char* percent = Data;
-    size_t i = 0;
-
-    for(i = 0; percent && i < numBuffers / 2; i++) {
-        percent = strchr(percent, '%');
-
-        if(percent) {
-            percent++;
-        }
-    }
-
-    if(percent) {
-        *percent = '\0';
-    }
-
-    Size = strlen(Data) + 1;
-
-    // XXX: Due to rdar://68121985
-    Data[Size++] = 0;
-    return Size;
-}
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
-    static int initialized = 0;
-
-    if(initialized) {
-        return 0;
-    }
-
-    for(size_t i = 0; i < numBuffers; i++) {
-        buffers[i] = malloc(bufferSize);
-    }
-
-    initialized = 1;
-
-    return 0;
-}
-
-
-void setup() {
-    for(size_t i = 0; i < numBuffers; i++) {
-        memset(&buffers[i][0], 0, bufferSize);
-        memset(&buffers[i][0], 'A' + i, bufferSize-1);
-    }
-}
-
-int LLVMFuzzerTestOneInput(const char* Data, const size_t Size)
-{
-    // For some reason, the Release build doesn't call LLVMFuzzerInitialize so
-    // we do it manually here.
-    LLVMFuzzerInitialize(0, NULL);
-
-    // Skip short inputs
-    if(Size < 1 || !memchr(Data, 0, Size)) {
-        return 0;
-    }
-
-    // Require that there is a NULL terminator somewhere in the buffer
-    // char *copy = malloc(Size);
-    // memcpy(copy, Data, Size);
-
-    // Setup printed buffers
-    setup();
-
-    // Output buffer and run snprintf
-    size_t printBufferSize = 128;
-    // char printBuffer[printBufferSize]; // Repro
-    char* printBuffer = malloc(printBufferSize); // No repro
-    mDNS_snprintf(printBuffer, printBufferSize, Data, 
-                    buffers[000], buffers[001], buffers[002], buffers[003], buffers[004], buffers[005], buffers[006], buffers[007], 
-                    buffers[010], buffers[011], buffers[012], buffers[013], buffers[014], buffers[015], buffers[016], buffers[017], 
-                    buffers[020], buffers[021], buffers[022], buffers[023], buffers[024], buffers[025], buffers[026], buffers[027],
-                    buffers[030], buffers[031], buffers[032], buffers[033], buffers[034], buffers[035], buffers[036], buffers[037]);
-
-    free(printBuffer);
-    return 0;
-}
-#endif
diff --git a/mDNSMacOSX/Tests/Fuzzing/setrdata.c b/mDNSMacOSX/Tests/Fuzzing/setrdata.c
deleted file mode 100644
index d7557bf..0000000
--- a/mDNSMacOSX/Tests/Fuzzing/setrdata.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "DNSCommon.h"
-
-#ifdef FUZZING_SETRDATA
-
-#ifdef JUST_FOR_REFERENCE
-typedef struct
-{
-    DNSMessageHeader h;                     // Note: Size 12 bytes
-    mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
-} DNSMessage;
-
-struct ResourceRecord_struct
-{
-    mDNSu8 RecordType;                  // See kDNSRecordTypes enum.
-    mDNSu8 negativeRecordType;          // If RecordType is kDNSRecordTypePacketNegative, specifies type of negative record.
-    MortalityState mortality;           // Mortality of this resource record (See MortalityState enum)
-    mDNSu16 rrtype;                     // See DNS_TypeValues enum.
-    mDNSu16 rrclass;                    // See DNS_ClassValues enum.
-    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)
-    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)
-    domainname      *name;
-    RData           *rdata;             // Pointer to storage for this rdata
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_dns_service_t dnsservice;
-    mdns_resolver_type_t protocol;
-#else
-    DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry; null for multicast
-#endif
-
-};
-
-typedef struct { mDNSu8 c[256]; } domainname;
-
-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;
-
-#endif
-
-// #define min(x,y) (x<y ? x : y)
-
-int LLVMFuzzerTestOneInput(char* Data, size_t Length)
-{
-    if(Length < 3) {
-        return 0;
-    }
-
-    // First three bytes are type and length
-    // We have to use a two-byte length, since RDataBody2 is pretty big
-    uint8_t recordType = (uint8_t) Data[0];
-    uint16_t rdlen = *(uint16_t*)&Data[1];
-
-    rdlen &= 0x7ff;
-
-    Data += 3;
-    Length -= 3;
-
-    // Make sure not to go over MTU size
-    if(rdlen > AbsoluteMaxDNSMessageData) {
-        return 0;
-    }
-
-    // Make sure we have enough data for everything else
-    if(Length < rdlen + sizeof(domainname)) {
-        return 0;
-    }
-
-    // Fill the domainname with random data
-    domainname *name = malloc(sizeof(*name));
-    memcpy(name, Data, sizeof(*name));
-    
-    Data += sizeof(*name);
-    Length -= sizeof(*name);
-
-    // Allocate an RData object of variable length
-    size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
-    RData *rdata = malloc((sizeof(RData) - sizeof(RDataBody)) + rdcapacity);
-    rdata->MaxRDLength = (uint16_t) rdcapacity;
-
-    // Use a random record type
-    ResourceRecord *rr = malloc(sizeof(*rr));
-    rr->rrtype = recordType;
-    rr->name = name;
-    rr->rdata = rdata;
-
-    // Check against the number of bytes we have
-    if(Length >= rdlen) {
-        // The rest of the buffer goes as input
-        uint8_t *buffer = malloc(rdlen);
-        uint8_t *end = (uint8_t*) buffer + rdlen;
-        memcpy(buffer, Data, rdlen);
-
-        // SetRData copies the record data out of "buffer" and into "rr.rdata"
-        SetRData(0, buffer, end, rr, rdlen);
-
-        free(buffer);
-    }
-
-
-    free(rr);
-    free(name);
-    free(rdata);
-    return 0;
-}
-#endif
diff --git a/mDNSMacOSX/clientstub/dnssd_clientstub_apple.c b/mDNSMacOSX/clientstub/dnssd_clientstub_apple.c
deleted file mode 100644
index 69332dd..0000000
--- a/mDNSMacOSX/clientstub/dnssd_clientstub_apple.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dnssd_clientstub_apple.h"
-
-#include "dns_sd_private.h"
-#include "dnssd_clientstub.h"
-
-#include <CoreUtils/CommonServices.h>
-#include <CoreUtils/DebugServices.h>
-#include <os/lock.h>
-#include "mdns_strict.h"
-
-#define kDNSServiceDefaultsKey_RequirePrivacy          "require_privacy"
-#define kDNSServiceDefaultsKey_ResolverConfigPListData "resolver_config_plist_data"
-
-static xpc_object_t		g_defaults_dict = NULL;
-static os_unfair_lock	g_defaults_lock = OS_UNFAIR_LOCK_INIT;
-
-DNSServiceErrorType DNSSD_API
-DNSServiceSetResolverDefaults(const void * const plist_data_ptr, const size_t plist_data_len, bool require_privacy)
-{
-	DNSServiceErrorType err;
-	require_action_quiet(plist_data_len <= (32 * CUBytesPerKibiByte), exit, err = kDNSServiceErr_Invalid);
-
-	const xpc_object_t new_dict = xpc_dictionary_create(NULL, NULL, 0);
-	require_action_quiet(new_dict, exit, err = kDNSServiceErr_NoMemory);
-
-	xpc_dictionary_set_bool(new_dict, kDNSServiceDefaultsKey_RequirePrivacy, require_privacy);
-	if (plist_data_ptr && (plist_data_len > 0)) {
-		xpc_dictionary_set_data(new_dict, kDNSServiceDefaultsKey_ResolverConfigPListData, plist_data_ptr,
-			plist_data_len);
-	}
-	os_unfair_lock_lock(&g_defaults_lock);
-	xpc_object_t old_dict = g_defaults_dict;
-	g_defaults_dict = new_dict;
-	os_unfair_lock_unlock(&g_defaults_lock);
-
-	xpc_forget(&old_dict);
-	err = kDNSServiceErr_NoError;
-
-exit:
-	return err;
-}
-
-DNSServiceErrorType DNSSD_API
-DNSServiceBrowseEx(DNSServiceRef *sdRef, DNSServiceFlags flags,
-	uint32_t interfaceIndex, const char *regtype, const char *domain, const DNSServiceAttribute * const attr,
-	DNSServiceBrowseReply callBack, void *context)
-{
-	return DNSServiceBrowseInternal(sdRef, flags, interfaceIndex, regtype, domain, attr, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API
-DNSServiceResolveEx(DNSServiceRef *sdRef, DNSServiceFlags flags,
-	uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain,
-	const DNSServiceAttribute * const attr, DNSServiceResolveReply callBack, void *context)
-{
-	return DNSServiceResolveInternal(sdRef, flags, interfaceIndex, name, regtype, domain, attr, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API
-DNSServiceGetAddrInfoEx(DNSServiceRef *sdRef, DNSServiceFlags flags,
-	uint32_t interfaceIndex, DNSServiceProtocol protocol, const char *hostname, const DNSServiceAttribute * const attr,
-	DNSServiceGetAddrInfoReply callBack, void *context)
-{
-	return DNSServiceGetAddrInfoInternal(sdRef, flags, interfaceIndex, protocol, hostname, attr, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API
-DNSServiceQueryRecordEx(DNSServiceRef * const sdRef, const DNSServiceFlags flags, const uint32_t ifindex,
-	const char * const name, const uint16_t rrtype, const uint16_t rrclass, const DNSServiceAttribute * const attr,
-	const DNSServiceQueryRecordReply callback, void * const context)
-{
-	return DNSServiceQueryRecordInternal(sdRef, flags, ifindex, name, rrtype, rrclass, attr, callback, context);
-}
-
-xpc_object_t
-DNSServiceGetRetainedResolverDefaults(void)
-{
-	os_unfair_lock_lock(&g_defaults_lock);
-	const xpc_object_t dict_copy = g_defaults_dict ? xpc_retain(g_defaults_dict) : NULL;
-	os_unfair_lock_unlock(&g_defaults_lock);
-	return dict_copy;
-}
-
-DNSServiceAttrRef
-DNSServiceAttrCreate(void)
-{
-	return DNSServiceAttributeCreate();
-}
-
-void
-DNSServiceAttrFree(DNSServiceAttrRef attr)
-{
-	DNSServiceAttributeDeallocate(attr);
-}
-
-size_t
-get_required_tlv_length_for_defaults(const xpc_object_t defaults)
-{
-	size_t len = 0;
-	size_t plist_len = 0;
-	// Add length for IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA.
-	if (xpc_dictionary_get_data(defaults, kDNSServiceDefaultsKey_ResolverConfigPListData, &plist_len)) {
-		len += get_required_tlv_length((uint16_t)plist_len);
-	}
-	// Add length for IPC_TLV_TYPE_REQUIRE_PRIVACY.
-	len += get_required_tlv_uint8_length();
-	return len;
-}
-
-const uint8_t *
-get_validation_data_from_tlvs(const uint8_t * const ptr, const uint8_t * const limit, size_t * const length)
-{
-	size_t len = 0;
-	const uint8_t *const data = get_tlv(ptr, limit, IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA, &len);
-	if (length)
-	{
-		*length = len;
-	}
-	return data;
-}
-
-void
-put_tlvs_for_defaults(const xpc_object_t defaults, ipc_msg_hdr * const hdr, uint8_t ** const ptr,
-	const uint8_t * const limit)
-{
-	size_t len = 0;
-	const uint8_t * const data = xpc_dictionary_get_data(defaults, kDNSServiceDefaultsKey_ResolverConfigPListData,
-		&len);
-	if (data) {
-		put_tlv(IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, (uint16_t)len, data, ptr, limit);
-	}
-	const uint8_t require_privacy = xpc_dictionary_get_bool(defaults, kDNSServiceDefaultsKey_RequirePrivacy) ? 1 : 0;
-	put_tlv_uint8(IPC_TLV_TYPE_REQUIRE_PRIVACY, require_privacy, ptr, limit);
-	hdr->ipc_flags |= IPC_FLAGS_TRAILING_TLVS;
-}
diff --git a/mDNSMacOSX/clientstub/dnssd_clientstub_apple.h b/mDNSMacOSX/clientstub/dnssd_clientstub_apple.h
deleted file mode 100644
index 9a5a8dc..0000000
--- a/mDNSMacOSX/clientstub/dnssd_clientstub_apple.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dns_sd_private.h"
-#include "dnssd_ipc.h"
-
-#include <xpc/xpc.h>
-
-xpc_object_t
-DNSServiceGetRetainedResolverDefaults(void);
-
-size_t
-get_required_tlv_length_for_validation_attr(const DNSServiceAttribute *attr);
-
-size_t
-get_required_tlv_length_for_defaults(xpc_object_t defaults);
-
-size_t
-get_required_tlv_length_for_service_attr(const DNSServiceAttribute *attr);
-
-const uint8_t *
-get_validation_data_from_tlvs(const uint8_t * const ptr, const uint8_t * const limit, size_t * const length);
-
-void
-put_tlvs_for_validation_attr(const DNSServiceAttribute * const attr, ipc_msg_hdr * const hdr, uint8_t ** const ptr,
-	const uint8_t * const limit);
-
-void
-put_tlvs_for_defaults(xpc_object_t defaults, ipc_msg_hdr *hdr, uint8_t **ptr, const uint8_t *limit);
diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c
deleted file mode 100644
index d1a78a3..0000000
--- a/mDNSMacOSX/daemon.c
+++ /dev/null
@@ -1,1765 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil -*-
- *
- * Copyright (c) 2002-2021 Apple 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
- *
- *     https://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.
- */
-
-#include <AssertMacros.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-#include <paths.h>
-#include <fcntl.h>
-#include <launch.h>
-#include <launch_priv.h>         // for launch_socket_service_check_in()
-#include <pwd.h>
-#include <sys/event.h>
-#include <pthread.h>
-#include <sandbox.h>
-#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
-#include <err.h>
-#include <sysexits.h>
-#include <TargetConditionals.h>
-
-#include "uDNS.h"
-#include "DNSCommon.h"
-#include "mDNSMacOSX.h"             // Defines the specific types needed to run mDNS on this platform
-
-#include "uds_daemon.h"             // Interface to the server side implementation of dns_sd.h
-#include "xpc_services.h"
-#include "xpc_service_dns_proxy.h"
-#include "xpc_service_log_utility.h"
-#include "helper.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
-#include "dnssd_server.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include <mdns/managed_defaults.h>
-#include "QuerierSupport.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-#include "resolved_cache.h"
-#endif
-
-#include <mdns/power.h>
-#include "mrcs_server.h"
-#include "mdns_strict.h"
-
-#ifndef USE_SELECT_WITH_KQUEUEFD
-#define USE_SELECT_WITH_KQUEUEFD 0
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_MEM_LIMIT)
-#include <os/feature_private.h>
-#endif
-
-// Used on OSX(10.11.x onwards) for manipulating mDNSResponder program arguments
-
-//*************************************************************************************************************
-// MARK: - Globals
-
-static mDNS_PlatformSupport PlatformStorage;
-
-// Start off with a default cache of 32K (136 records of 240 bytes each)
-// Each time we grow the cache we add another 136 records
-// 136 * 240 = 32640 bytes.
-// This fits in eight 4kB pages, with 128 bytes spare for memory block headers and similar overhead
-#define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord))
-static CacheEntity rrcachestorage[RR_CACHE_SIZE];
-struct CompileTimeAssertionChecks_RR_CACHE_SIZE { char a[(RR_CACHE_SIZE >= 136) ? 1 : -1]; };
-#define kRRCacheGrowSize (sizeof(CacheEntity) * RR_CACHE_SIZE)
-
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void PrepareForIdle(void *m_param);
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-static mach_port_t signal_port       = MACH_PORT_NULL;
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-static dnssd_sock_t *launchd_fds = mDNSNULL;
-static size_t launchd_fds_count = 0;
-
-static mDNSBool NoMulticastAdvertisements = mDNSfalse; // By default, advertise addresses (& other records) via multicast
-
-extern mDNSBool StrictUnicastOrdering;
-extern mDNSBool AlwaysAppendSearchDomains;
-extern mDNSBool EnableAllowExpired;
-mDNSexport void INFOCallback(void);
-mDNSexport void dump_state_to_fd(int fd);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_MEM_LIMIT)
-#define kRRCacheMemoryLimit 1000000 // For now, we limit the cache to at most 1MB on iOS devices.
-#endif
-
-// We keep a list of client-supplied event sources in KQSocketEventSource records
-typedef struct KQSocketEventSource
-{
-    struct  KQSocketEventSource *next;
-    int fd;
-    KQueueEntry kqs;
-    udsEventCallback callback;
-    void *context;
-} KQSocketEventSource;
-
-static KQSocketEventSource *gEventSources;
-
-//*************************************************************************************************************
-// MARK: - General Utility Functions
-
-#if MDNS_MALLOC_DEBUGGING
-void mDNSPlatformValidateLists()
-{
-    mDNS *const m = &mDNSStorage;
-
-    KQSocketEventSource *k;
-    for (k = gEventSources; k; k=k->next)
-        if (k->next == (KQSocketEventSource *)~0 || k->fd < 0)
-            LogMemCorruption("gEventSources: %p is garbage (%d)", k, k->fd);
-
-    // Check platform-layer lists
-    NetworkInterfaceInfoOSX     *i;
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->next == (NetworkInterfaceInfoOSX *)~0 || !i->m || i->m == (mDNS *)~0)
-            LogMemCorruption("m->p->InterfaceList: %p is garbage (%p)", i, i->ifinfo.ifname);
-
-    ClientTunnel *t;
-    for (t = m->TunnelClients; t; t=t->next)
-        if (t->next == (ClientTunnel *)~0 || t->dstname.c[0] > 63)
-            LogMemCorruption("m->TunnelClients: %p is garbage (%d)", t, t->dstname.c[0]);
-}
-#endif // MDNS_MALLOC_DEBUGGING
-
-//*************************************************************************************************************
-// Registration
-
-mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay)
-{
-    mDNSStorage.p->NotifyUser = NonZeroTime(mDNSStorage.timenow + delay);
-}
-
-mDNSlocal void mDNSPreferencesSetNames(int key, domainlabel *old, domainlabel *new)
-{
-    mDNS *const m = &mDNSStorage;
-    domainlabel *prevold, *prevnew;
-    switch (key)
-    {
-    case kmDNSComputerName:
-    case kmDNSLocalHostName:
-        if (key == kmDNSComputerName)
-        {
-            prevold = &m->p->prevoldnicelabel;
-            prevnew = &m->p->prevnewnicelabel;
-        }
-        else
-        {
-            prevold = &m->p->prevoldhostlabel;
-            prevnew = &m->p->prevnewhostlabel;
-        }
-        // There are a few cases where we need to invoke the helper.
-        //
-        // 1. If the "old" label and "new" label are not same, it means there is a conflict. We need
-        //    to invoke the helper so that it pops up a dialogue to inform the user about the
-        //    conflict
-        //
-        // 2. If the "old" label and "new" label are same, it means the user has set the host/nice label
-        //    through the preferences pane. We may have to inform the helper as it may have popped up
-        //    a dialogue previously (due to a conflict) and it needs to suppress it now. We can avoid invoking
-        //    the helper in this case if the previous values (old and new) that we told helper last time
-        //    are same. If the previous old and new values are same, helper does not care.
-        //
-        // Note: "new" can be NULL when we have repeated conflicts and we are asking helper to give up. "old"
-        // is not called with NULL today, but this makes it future proof.
-        if (!old || !new || !SameDomainLabelCS(old->c, new->c) ||
-            !SameDomainLabelCS(old->c, prevold->c) ||
-            !SameDomainLabelCS(new->c, prevnew->c))
-        {
-// Work around bug radar:21397654
-#ifndef __clang_analyzer__
-            if (old)
-                *prevold = *old;
-            else
-                prevold->c[0] = 0;
-            if (new)
-                *prevnew = *new;
-            else
-                prevnew->c[0] = 0;
-#endif
-            mDNSPreferencesSetName(key, old, new);
-        }
-        else
-        {
-            LogInfo("mDNSPreferencesSetNames not invoking helper %s %#s, %s %#s, old %#s, new %#s",
-                    (key == kmDNSComputerName ? "prevoldnicelabel" : "prevoldhostlabel"), prevold->c,
-                    (key == kmDNSComputerName ? "prevnewnicelabel" : "prevnewhostlabel"), prevnew->c,
-                    old->c, new->c);
-        }
-        break;
-    default:
-        LogMsg("mDNSPreferencesSetNames: unrecognized key: %d", key);
-        return;
-    }
-}
-
-mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
-{
-    if (result == mStatus_NoError)
-    {
-        if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
-            LogInfo("Local Hostname changed from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
-        // One second pause in case we get a Computer Name update too -- don't want to alert the user twice
-        RecordUpdatedNiceLabel(mDNSPlatformOneSecond);
-    }
-    else if (result == mStatus_NameConflict)
-    {
-        LogInfo("Local Hostname conflict for \"%#s.local\"", m->hostlabel.c);
-        if (!m->p->HostNameConflict) m->p->HostNameConflict = NonZeroTime(m->timenow);
-        else if (m->timenow - m->p->HostNameConflict > 60 * mDNSPlatformOneSecond)
-        {
-            // Tell the helper we've given up
-            mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, NULL);
-        }
-    }
-    else if (result == mStatus_GrowCache)
-    {
-        // Allocate another chunk of cache storage
-        static unsigned int allocated = 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_MEM_LIMIT)
-        if (allocated >= kRRCacheMemoryLimit) return;	// For now we limit the cache to at most 1MB on iOS devices
-#endif
-        allocated += kRRCacheGrowSize;
-        // LogMsg("GrowCache %d * %d = %d; total so far %6u", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE, allocated);
-        CacheEntity *storage = mallocL("mStatus_GrowCache", sizeof(CacheEntity) * RR_CACHE_SIZE);
-        //LogInfo("GrowCache %d * %d = %d", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE);
-        if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
-    }
-    else if (result == mStatus_ConfigChanged)
-    {
-        // Tell the helper we've seen a change in the labels.  It will dismiss the name conflict alert if needed.
-        mDNSPreferencesSetNames(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
-        mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
-
-        // Then we call into the UDS daemon code, to let it do the same
-        udsserver_handle_configchange(m);
-    }
-}
-
-
-//*************************************************************************************************************
-// MARK: - Startup, shutdown, and supporting code
-
-mDNSlocal void ExitCallback(int sig)
-{
-    (void)sig; // Unused
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, PUB_S " stopping", mDNSResponderVersionString);
-
-    if (udsserver_exit() < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "ExitCallback: udsserver_exit failed");
-    }
-
-    debugf("ExitCallback: mDNS_StartExit");
-    mDNS_StartExit(&mDNSStorage);
-}
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-// Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
-mDNSlocal void HandleSIG(int sig)
-{
-    kern_return_t status;
-    mach_msg_header_t header;
-
-    // WARNING: can't call syslog or fprintf from signal handler
-    header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
-    header.msgh_remote_port = signal_port;
-    header.msgh_local_port = MACH_PORT_NULL;
-    header.msgh_size = sizeof(header);
-    header.msgh_id = sig;
-
-    status = mach_msg(&header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, header.msgh_size,
-                      0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
-
-    if (status != MACH_MSG_SUCCESS)
-    {
-        if (status == MACH_SEND_TIMED_OUT) mach_msg_destroy(&header);
-        if (sig == SIGTERM || sig == SIGINT) exit(-1);
-    }
-}
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSexport void dump_state_to_fd(int fd)
-{
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNS *const m = &mDNSStorage;
-#endif
-    char buffer[1024];
-    buffer[0] = '\0';
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    const mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
-    NetworkInterfaceInfoOSX     *i;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    DNSServer *s;
-#endif
-    McastResolver *mr;
-    char timestamp[MIN_TIMESTAMP_STRING_LENGTH];
-
-    LogToFD(fd, "---- BEGIN STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
-    getLocalTimestampNow(timestamp, sizeof(timestamp));
-    LogToFD(fd, "Date: %s", timestamp);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "---- BEGIN STATE LOG ---- (" PUB_S ")", timestamp);
-
-    udsserver_info_dump_to_fd(fd);
-
-    LogToFD(fd, "----- Platform Timers -----");
-    LogTimerToFD(fd, "m->NextCacheCheck       ", mDNSStorage.NextCacheCheck);
-    LogTimerToFD(fd, "m->NetworkChanged       ", mDNSStorage.NetworkChanged);
-    LogTimerToFD(fd, "m->p->NotifyUser        ", mDNSStorage.p->NotifyUser);
-    LogTimerToFD(fd, "m->p->HostNameConflict  ", mDNSStorage.p->HostNameConflict);
-    LogTimerToFD(fd, "m->p->KeyChainTimer     ", mDNSStorage.p->KeyChainTimer);
-
-    LogToFD(fd, "----- KQSocketEventSources -----");
-    if (!gEventSources) LogToFD(fd, "<None>");
-    else
-    {
-        KQSocketEventSource *k;
-        for (k = gEventSources; k; k=k->next)
-            LogToFD(fd, "%3d %s %s", k->fd, k->kqs.KQtask, k->fd == mDNSStorage.uds_listener_skt ? "Listener for incoming UDS clients" : " ");
-    }
-
-    LogToFD(fd, "------ Network Interfaces ------");
-    if (!mDNSStorage.p->InterfaceList) LogToFD(fd, "<None>");
-    else
-    {
-        LogToFD(fd, "  Struct addr           Registered                MAC               BSSID                                Interface Address");
-        for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-        {
-            // Allow six characters for interface name, for names like "vmnet8"
-            if (!i->Exists)
-                LogToFD(fd, "%p %2ld, %p,  %s %-6s %.6a %.6a %#-14a dormant for %d seconds",
-                          i, i->ifinfo.InterfaceID, i->Registered,
-                          i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, &i->ifinfo.MAC, &i->BSSID,
-                          &i->ifinfo.ip, utc - i->LastSeen);
-            else
-            {
-                const CacheRecord *sps[3];
-                FindSPSInCache(&mDNSStorage, &i->ifinfo.NetWakeBrowse, sps);
-                LogToFD(fd, "%p %2ld, %p,  %s %-6s %.6a %.6a %s %s %s %s %s %s %#a",
-                          i, i->ifinfo.InterfaceID, i->Registered,
-                          i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, &i->ifinfo.MAC, &i->BSSID,
-                          i->ifinfo.InterfaceActive ? "Active" : "      ",
-                          i->ifinfo.IPv4Available ? "v4" : "  ",
-                          i->ifinfo.IPv6Available ? "v6" : "  ",
-                          i->ifinfo.Advertise ? "A" : " ",
-                          i->ifinfo.McastTxRx ? "M" : " ",
-                          !(i->ifinfo.InterfaceActive && i->ifinfo.NetWake) ? " " : !sps[0] ? "p" : "P",
-                          &i->ifinfo.ip);
-
-                // Only print the discovered sleep proxies once for the lead/active interface of an interface set.
-                if (i == i->Registered && (sps[0] || sps[1] || sps[2]))
-                {
-                    LogToFD(fd, "         Sleep Proxy Metric   Name");
-                    if (sps[0]) LogToFD(fd, "  %13d %#s", SPSMetric(sps[0]->resrec.rdata->u.name.c), sps[0]->resrec.rdata->u.name.c);
-                    if (sps[1]) LogToFD(fd, "  %13d %#s", SPSMetric(sps[1]->resrec.rdata->u.name.c), sps[1]->resrec.rdata->u.name.c);
-                    if (sps[2]) LogToFD(fd, "  %13d %#s", SPSMetric(sps[2]->resrec.rdata->u.name.c), sps[2]->resrec.rdata->u.name.c);
-                }
-            }
-        }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    LogToFD(fd, "----------- DNS Services -----------");
-    {
-        const mdns_dns_service_manager_t manager = Querier_GetDNSServiceManager();
-        if (manager)
-        {
-            mdns_dns_service_manager_enumerate(manager,
-            ^ bool (const mdns_dns_service_t service)
-            {
-                char *desc = mdns_copy_description(service);
-                LogToFD(fd, "%s", desc ? desc : "<missing description>");
-                mdns_free(desc);
-                return true;
-            });
-        }
-    }
-#else
-    LogToFD(fd, "--------- DNS Servers(%d) ----------", CountOfUnicastDNSServers(&mDNSStorage));
-    if (!mDNSStorage.DNSServers) LogToFD(fd, "<None>");
-    else
-    {
-        for (s = mDNSStorage.DNSServers; s; s = s->next)
-        {
-            NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(s->interface);
-            LogToFD(fd, "DNS Server %##s %s%s%#a:%d %d %s %d %d %sv4 %sv6 %scell %sexp %sconstrained %sCLAT46",
-                    s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
-                    s->penaltyTime ? (s->penaltyTime - mDNS_TimeNow(&mDNSStorage)) : 0, DNSScopeToString(s->scopeType),
-                    s->timeout, s->resGroupID,
-                    s->usableA       ? "" : "!",
-                    s->usableAAAA    ? "" : "!",
-                    s->isCell        ? "" : "!",
-                    s->isExpensive   ? "" : "!",
-                    s->isConstrained ? "" : "!",
-                    s->isCLAT46      ? "" : "!");
-        }
-    }
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-    LogToFD(fd, "v4answers %d", mDNSStorage.p->v4answers);
-    LogToFD(fd, "v6answers %d", mDNSStorage.p->v6answers);
-    LogToFD(fd, "Last DNS Trigger: %d ms ago", (now - mDNSStorage.p->DNSTrigger));
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    LogToFD(fd, "-------- Interface Monitors --------");
-    const CFIndex n = m->p->InterfaceMonitors ? CFArrayGetCount(m->p->InterfaceMonitors) : 0;
-    if (n > 0)
-    {
-        for (CFIndex j = 0; j < n; j++)
-        {
-            mdns_interface_monitor_t monitor = (mdns_interface_monitor_t) CFArrayGetValueAtIndex(m->p->InterfaceMonitors, j);
-            char *description = mdns_copy_description(monitor);
-            if (description)
-            {
-                LogToFD(fd, "%s", description);
-                mdns_free(description);
-            }
-            else
-            {
-                LogToFD(fd, "monitor %p (no description)", monitor);
-            }
-        }
-    }
-    else
-    {
-        LogToFD(fd, "No interface monitors");
-    }
-#endif
-
-    LogToFD(fd, "--------- Mcast Resolvers ----------");
-    if (!mDNSStorage.McastResolvers) LogToFD(fd, "<None>");
-    else
-    {
-        for (mr = mDNSStorage.McastResolvers; mr; mr = mr->next)
-            LogToFD(fd, "Mcast Resolver %##s timeout %u", mr->domain.c, mr->timeout);
-    }
-
-    LogToFD(fd, "------------ Hostnames -------------");
-    if (!mDNSStorage.Hostnames) LogToFD(fd, "<None>");
-    else
-    {
-        HostnameInfo *hi;
-        for (hi = mDNSStorage.Hostnames; hi; hi = hi->next)
-        {
-            LogToFD(fd, "%##s v4 %d %s", hi->fqdn.c, hi->arv4.state, ARDisplayString(&mDNSStorage, &hi->arv4));
-            LogToFD(fd, "%##s v6 %d %s", hi->fqdn.c, hi->arv6.state, ARDisplayString(&mDNSStorage, &hi->arv6));
-        }
-    }
-
-    LogToFD(fd, "--------------- FQDN ---------------");
-    if (!mDNSStorage.FQDN.c[0]) LogToFD(fd, "<None>");
-    else
-    {
-        LogToFD(fd, "%##s", mDNSStorage.FQDN.c);
-    }
-
-    #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-        dnssd_analytics_log(fd);
-    #endif
-
-    LogToFD(fd, "Date: %s", timestamp);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "---- END STATE LOG ---- (" PUB_S ")", timestamp);
-    LogToFD(fd, "----  END STATE LOG  ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
-}
-
-mDNSexport void INFOCallback(void)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Sending SIGINFO to mDNSResponder daemon is deprecated. To trigger state dump, please use 'dns-sd -O', "
-        "enter 'dns-sd -h' for more information");
-}
-
-// Writes the state out to the dynamic store and also affects the ASL filter level
-mDNSexport void UpdateDebugState()
-{
-    mDNSu32 one  = 1;
-    mDNSu32 zero = 0;
-
-    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    if (!dict)
-    {
-        LogMsg("UpdateDebugState: Could not create dict");
-        return;
-    }
-
-    CFNumberRef numOne = CFNumberCreate(NULL, kCFNumberSInt32Type, &one);
-    if (numOne == NULL)
-    {
-        LogMsg("UpdateDebugState: Could not create CFNumber one");
-        return;
-    }
-    CFNumberRef numZero = CFNumberCreate(NULL, kCFNumberSInt32Type, &zero);
-    if (numZero == NULL)
-    {
-        LogMsg("UpdateDebugState: Could not create CFNumber zero");
-        MDNS_DISPOSE_CF_OBJECT(numOne);
-        return;
-    }
-
-    if (mDNS_LoggingEnabled)
-        CFDictionarySetValue(dict, CFSTR("VerboseLogging"), numOne);
-    else
-        CFDictionarySetValue(dict, CFSTR("VerboseLogging"), numZero);
-
-    if (mDNS_PacketLoggingEnabled)
-        CFDictionarySetValue(dict, CFSTR("PacketLogging"), numOne);
-    else
-        CFDictionarySetValue(dict, CFSTR("PacketLogging"), numZero);
-
-    if (mDNS_McastLoggingEnabled)
-        CFDictionarySetValue(dict, CFSTR("McastLogging"), numOne);
-    else
-        CFDictionarySetValue(dict, CFSTR("McastLogging"), numZero);
-
-    if (mDNS_McastTracingEnabled)
-        CFDictionarySetValue(dict, CFSTR("McastTracing"), numOne);
-    else 
-        CFDictionarySetValue(dict, CFSTR("McastTracing"), numZero);
-
-    MDNS_DISPOSE_CF_OBJECT(numOne);
-    MDNS_DISPOSE_CF_OBJECT(numZero);
-    mDNSDynamicStoreSetConfig(kmDNSDebugState, mDNSNULL, dict);
-    MDNS_DISPOSE_CF_OBJECT(dict);
-
-}
-
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
-{
-    (void)port;     // Unused
-    (void)size;     // Unused
-    (void)info;     // Unused
-    mach_msg_header_t *msg_header = (mach_msg_header_t *)msg;
-    mDNS *const m = &mDNSStorage;
-
-    // We're running on the CFRunLoop (Mach port) thread, not the kqueue thread, so we need to grab the KQueueLock before proceeding
-    KQueueLock();
-    switch(msg_header->msgh_id)
-    {
-    case SIGHUP:    {
-        mDNSu32 slot;
-        CacheGroup *cg;
-        CacheRecord *rr;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGHUP: Purge cache");
-        mDNS_Lock(m);
-        FORALL_CACHERECORDS(slot, cg, rr)
-        {
-            mDNS_PurgeCacheResourceRecord(m, rr);
-        }
-        // Restart unicast and multicast queries
-        mDNSCoreRestartQueries(m);
-        mDNS_Unlock(m);
-    } break;
-    case SIGINT:
-    case SIGTERM:   ExitCallback(msg_header->msgh_id); break;
-    case SIGINFO:   INFOCallback(); break;
-    case SIGUSR1:
-        mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGUSR1: Logging " PUB_S, mDNS_LoggingEnabled ? "Enabled" : "Disabled");
-        WatchDogReportingThreshold = mDNS_LoggingEnabled ? 50 : 250;
-        UpdateDebugState();
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "USR1 Logging Enabled");
-        break;
-    case SIGUSR2:
-        mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGUSR2: Packet Logging " PUB_S, mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
-        mDNS_McastTracingEnabled = (mDNS_PacketLoggingEnabled && mDNS_McastLoggingEnabled) ? mDNStrue : mDNSfalse;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGUSR2: Multicast Tracing is " PUB_S, mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
-        UpdateDebugState();
-        break;
-    case SIGPROF:  mDNS_McastLoggingEnabled = mDNS_McastLoggingEnabled ? mDNSfalse : mDNStrue;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGPROF: Multicast Logging " PUB_S, mDNS_McastLoggingEnabled ? "Enabled" : "Disabled");
-        LogMcastStateInfo(mDNSfalse, mDNStrue, mDNStrue);
-        mDNS_McastTracingEnabled = (mDNS_PacketLoggingEnabled && mDNS_McastLoggingEnabled) ? mDNStrue : mDNSfalse;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SIGPROF: Multicast Tracing is " PUB_S, mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
-        UpdateDebugState();
-        break;
-    case SIGTSTP:  mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = mDNS_McastLoggingEnabled = mDNS_McastTracingEnabled = mDNSfalse;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "All mDNSResponder Debug Logging/Tracing Disabled (USR1/USR2/PROF)");
-        UpdateDebugState();
-        break;
-
-    default: LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SignalCallback: Unknown signal %d", msg_header->msgh_id); break;
-    }
-    KQueueUnlock("Unix Signal");
-}
-
-// MachServerName is com.apple.mDNSResponder (Supported only till 10.9.x)
-mDNSlocal kern_return_t mDNSDaemonInitialize(void)
-{
-    mStatus err;
-
-    err = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                    rrcachestorage, RR_CACHE_SIZE,
-                    !NoMulticastAdvertisements,
-                    mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
-
-    if (err)
-    {
-        LogMsg("Daemon start: mDNS_Init failed %d", err);
-        return(err);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_MEM_LIMIT)
-    if (os_feature_enabled(mDNSResponder, preallocated_cache))
-    {
-        const int growCount = (kRRCacheMemoryLimit + kRRCacheGrowSize - 1) / kRRCacheGrowSize;
-        int i;
-
-        for (i = 0; i < growCount; ++i)
-        {
-            mDNS_StatusCallback(&mDNSStorage, mStatus_GrowCache);
-        }
-    }
-#endif
-
-    CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
-    CFRunLoopSourceRef i_rls  = CFMachPortCreateRunLoopSource(NULL, i_port, 0);
-    signal_port       = CFMachPortGetPort(i_port);
-    CFRunLoopAddSource(CFRunLoopGetMain(), i_rls, kCFRunLoopDefaultMode);
-    MDNS_DISPOSE_CF_OBJECT(i_rls);
-    
-    return(err);
-}
-
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-// SignalDispatch is mostly just a copy/paste of entire code block from SignalCallback above.
-// The common code should be a subroutine, or we end up having to fix bugs in two places all the time.
-// The same applies to mDNSDaemonInitialize, much of which is just a copy/paste of chunks
-// of code from above. Alternatively we could remove the duplicated source code by having
-// single routines, with the few differing parts bracketed with "#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM"
-
-mDNSlocal void SignalDispatch(dispatch_source_t source)
-{
-    int sig = (int)dispatch_source_get_handle(source);
-    mDNS *const m = &mDNSStorage;
-    KQueueLock();
-    switch(sig)
-    {
-    case SIGHUP:    {
-        mDNSu32 slot;
-        CacheGroup *cg;
-        CacheRecord *rr;
-        LogMsg("SIGHUP: Purge cache");
-        mDNS_Lock(m);
-        FORALL_CACHERECORDS(slot, cg, rr)
-        {
-           mDNS_PurgeCacheResourceRecord(m, rr);
-        }
-        // Restart unicast and multicast queries
-        mDNSCoreRestartQueries(m);
-        mDNS_Unlock(m);
-    } break;
-    case SIGINT:
-    case SIGTERM:   ExitCallback(sig); break;
-    case SIGINFO:   INFOCallback(); break;
-    case SIGUSR1:   mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
-        LogMsg("SIGUSR1: Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
-        WatchDogReportingThreshold = mDNS_LoggingEnabled ? 50 : 250;
-        UpdateDebugState();
-        break;
-    case SIGUSR2:   mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
-        LogMsg("SIGUSR2: Packet Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
-        UpdateDebugState();
-        break;
-    default: LogMsg("SignalCallback: Unknown signal %d", sig); break;
-    }
-    KQueueUnlock("Unix Signal");
-}
-
-mDNSlocal void mDNSSetupSignal(dispatch_queue_t queue, int sig)
-{
-    signal(sig, SIG_IGN);
-    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, sig, 0, queue);
-
-    if (source)
-    {
-        dispatch_source_set_event_handler(source, ^{SignalDispatch(source);});
-        // Start processing signals
-        dispatch_resume(source);
-    }
-    else
-    {
-        LogMsg("mDNSSetupSignal: Cannot setup signal %d", sig);
-    }
-}
-
-mDNSlocal kern_return_t mDNSDaemonInitialize(void)
-{
-    mStatus err;
-    dispatch_queue_t queue = dispatch_get_main_queue();
-
-    err = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                    rrcachestorage, RR_CACHE_SIZE,
-                    !NoMulticastAdvertisements,
-                    mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
-
-    if (err)
-    {
-        LogMsg("Daemon start: mDNS_Init failed %d", err);
-        return(err);
-    }
-
-    mDNSSetupSignal(queue, SIGHUP);
-    mDNSSetupSignal(queue, SIGINT);
-    mDNSSetupSignal(queue, SIGTERM);
-    mDNSSetupSignal(queue, SIGINFO);
-    mDNSSetupSignal(queue, SIGUSR1);
-    mDNSSetupSignal(queue, SIGUSR2);
-
-    // Create a custom handler for doing the housekeeping work. This is either triggered
-    // by the timer or an event source
-    PlatformStorage.custom = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
-    if (PlatformStorage.custom == mDNSNULL) {LogMsg("mDNSDaemonInitialize: Error creating custom source"); return -1;}
-    dispatch_source_set_event_handler(PlatformStorage.custom, ^{PrepareForIdle(&mDNSStorage);});
-    dispatch_resume(PlatformStorage.custom);
-
-    // Create a timer source to trigger housekeeping work. The houskeeping work itself
-    // is done in the custom handler that we set below.
-
-    PlatformStorage.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
-    if (PlatformStorage.timer == mDNSNULL) {LogMsg("mDNSDaemonInitialize: Error creating timer source"); return -1;}
-
-    // As the API does not support one shot timers, we pass zero for the interval. In the custom handler, we
-    // always reset the time to the new time computed. In effect, we ignore the interval
-    dispatch_source_set_timer(PlatformStorage.timer, DISPATCH_TIME_NOW, 1000ull * 1000000000, 0);
-    dispatch_source_set_event_handler(PlatformStorage.timer, ^{
-                                          dispatch_source_merge_data(PlatformStorage.custom, 1);
-                                      });
-    dispatch_resume(PlatformStorage.timer);
-
-    LogMsg("DaemonIntialize done successfully");
-
-    return(err);
-}
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
-{
-    mDNSs32 now = mDNS_TimeNow(m);
-
-    // 1. If we need to set domain secrets, do so before handling the network change
-    // Detailed reason:
-    // BTMM domains listed in DynStore Setup:/Network/BackToMyMac are added to the registration domains list,
-    // and we need to setup the associated AutoTunnel DomainAuthInfo entries before that happens.
-    if (m->p->KeyChainTimer && now - m->p->KeyChainTimer >= 0)
-    {
-        m->p->KeyChainTimer = 0;
-        mDNS_Lock(m);
-        SetDomainSecrets(m);
-        mDNS_Unlock(m);
-    }
-
-    // 2. If we have network change events to handle, do them before calling mDNS_Execute()
-    // Detailed reason:
-    // mDNSMacOSXNetworkChanged() currently closes and re-opens its sockets. If there are received packets waiting, they are lost.
-    // mDNS_Execute() generates packets, including multicasts that are looped back to ourself.
-    // If we call mDNS_Execute() first, and generate packets, and then call mDNSMacOSXNetworkChanged() immediately afterwards
-    // we then systematically lose our own looped-back packets.
-    if (m->NetworkChanged && now - m->NetworkChanged >= 0) mDNSMacOSXNetworkChanged();
-
-    if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0)
-    {
-        m->p->RequestReSleep = 0;
-        mdns_power_cancel_all_events(kMDNSResponderID);
-        mDNSPowerSleepSystem();
-    }
-
-    // 3. Call mDNS_Execute() to let mDNSCore do what it needs to do
-    mDNSs32 nextevent = mDNS_Execute(m);
-
-    if (m->NetworkChanged)
-        if (nextevent - m->NetworkChanged > 0)
-            nextevent = m->NetworkChanged;
-
-    if (m->p->KeyChainTimer)
-        if (nextevent - m->p->KeyChainTimer > 0)
-            nextevent = m->p->KeyChainTimer;
-
-    if (m->p->RequestReSleep)
-        if (nextevent - m->p->RequestReSleep > 0)
-            nextevent = m->p->RequestReSleep;
-
-    
-    if (m->p->NotifyUser)
-    {
-        if (m->p->NotifyUser - now < 0)
-        {
-            if (!SameDomainLabelCS(m->p->usernicelabel.c, m->nicelabel.c))
-            {
-                LogMsg("Name Conflict: Updated Computer Name from \"%#s\" to \"%#s\"", m->p->usernicelabel.c, m->nicelabel.c);
-                mDNSPreferencesSetNames(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
-                m->p->usernicelabel = m->nicelabel;
-            }
-            if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
-            {
-                LogMsg("Name Conflict: Updated Local Hostname from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
-                mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
-                m->p->HostNameConflict = 0; // Clear our indicator, now name change has been successful
-                m->p->userhostlabel = m->hostlabel;
-            }
-            m->p->NotifyUser = 0;
-        }
-        else
-        if (nextevent - m->p->NotifyUser > 0)
-            nextevent = m->p->NotifyUser;
-    }
-
-    return(nextevent);
-}
-
-
-#define MDNSU32_MAX_DBL 4294967295.0
-check_compile_time(((mDNSu32)MDNSU32_MAX_DBL) == ((mDNSu32)-1));
-
-// Right now we consider *ALL* of our DHCP leases
-// It might make sense to be a bit more selective and only consider the leases on interfaces
-// (a) that are capable and enabled for wake-on-LAN, and
-// (b) where we have found (and successfully registered with) a Sleep Proxy
-// If we can't be woken for traffic on a given interface, then why keep waking to renew its lease?
-mDNSlocal mDNSu32 DHCPWakeTime(void)
-{
-    mDNSu32 e = 24 * 3600;      // Maximum maintenance wake interval is 24 hours
-    CFIndex ic, j;
-
-    const void *pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetDHCP);
-    if (!pattern)
-    {
-        LogMsg("DHCPWakeTime: SCDynamicStoreKeyCreateNetworkServiceEntity failed\n");
-        return e;
-    }
-    CFArrayRef dhcpinfo = CFArrayCreate(NULL, (const void **)&pattern, 1, &kCFTypeArrayCallBacks);
-    MDNS_DISPOSE_CF_OBJECT(pattern);
-    if (dhcpinfo)
-    {
-        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("DHCP-LEASES"), NULL, NULL);
-        if (store)
-        {
-            CFDictionaryRef dict = SCDynamicStoreCopyMultiple(store, NULL, dhcpinfo);
-            if (dict)
-            {
-                ic = CFDictionaryGetCount(dict);
-                CFDictionaryRef *vals = NULL;
-                if (ic > 0)
-                {
-                    vals = (CFDictionaryRef *)mdns_calloc((size_t)ic, sizeof(*vals));
-                }
-                if (vals)
-                {
-                    CFDictionaryGetKeysAndValues(dict, NULL, (const void **)vals);
-
-                    for (j = 0; j < ic; j++)
-                    {
-                        const CFDictionaryRef dhcp = vals[j];
-                        if (dhcp)
-                        {
-                            const CFDateRef start = DHCPInfoGetLeaseStartTime(dhcp);
-                            const CFDataRef lease = DHCPInfoGetOptionData(dhcp, 51);    // Option 51 = IP Address Lease Time
-                            if (!start || !lease || CFDataGetLength(lease) < 4)
-                                LogMsg("DHCPWakeTime: SCDynamicStoreCopyDHCPInfo index %d failed "
-                                       "CFDateRef start %p CFDataRef lease %p CFDataGetLength(lease) %d",
-                                       j, start, lease, lease ? CFDataGetLength(lease) : 0);
-                            else
-                            {
-                                const UInt8 *d = CFDataGetBytePtr(lease);
-                                if (!d) LogMsg("DHCPWakeTime: CFDataGetBytePtr %ld failed", (long)j);
-                                else
-                                {
-                                    mDNSu32 elapsed;
-                                    const CFAbsoluteTime now  = CFAbsoluteTimeGetCurrent();
-                                    const CFAbsoluteTime diff = now - CFDateGetAbsoluteTime(start);
-                                    if (isgreaterequal(diff, 0.0))
-                                    {
-                                        const mDNSu32 elapsedMax = (mDNSu32)-1;
-                                        elapsed = (islessequal(diff, MDNSU32_MAX_DBL)) ? ((mDNSu32)diff) : elapsedMax;
-                                    }
-                                    else
-                                    {
-                                        elapsed = 0;
-                                    }
-                                    const mDNSu32 lifetime  = (((mDNSu32)d[0]) << 24) | (((mDNSu32)d[1]) << 16) | (((mDNSu32)d[2]) << 8) | ((mDNSu32)d[3]);
-                                    const mDNSu32 remaining = (elapsed <= lifetime) ? (lifetime - elapsed) : 0;
-                                    const mDNSu32 wake      = remaining > 60 ? remaining - remaining/10 : 54;   // Wake at 90% of the lease time
-                                    LogSPS("DHCP Address Lease Elapsed %6u Lifetime %6u Remaining %6u Wake %6u", elapsed, lifetime, remaining, wake);
-                                    if (e > wake) e = wake;
-                                }
-                            }
-                        }
-                    }
-                    mdns_free(vals);
-                }
-                MDNS_DISPOSE_CF_OBJECT(dict);
-            }
-            MDNS_DISPOSE_CF_OBJECT(store);
-        }
-        MDNS_DISPOSE_CF_OBJECT(dhcpinfo);
-    }
-    return(e);
-}
-
-// We deliberately schedule our wakeup for halfway between when we'd *like* it and when we *need* it.
-// For example, if our DHCP lease expires in two hours, we'll typically renew it at the halfway point, after one hour.
-// If we scheduled our wakeup for the one-hour renewal time, that might be just seconds from now, and sleeping
-// for a few seconds and then waking again is silly and annoying.
-// If we scheduled our wakeup for the two-hour expiry time, and we were slow to wake, we might lose our lease.
-// Scheduling our wakeup for halfway in between -- 90 minutes -- avoids short wakeups while still
-// allowing us an adequate safety margin to renew our lease before we lose it.
-
-mDNSlocal mDNSBool AllowSleepNow(mDNSs32 now)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSBool ready = mDNSCoreReadyForSleep(m, now);
-    if (m->SleepState && !ready && now - m->SleepLimit < 0) return(mDNSfalse);
-
-    m->p->WakeAtUTC = 0;
-    int result = kIOReturnSuccess;
-    CFDictionaryRef opts = NULL;
-
-    // If the sleep request was cancelled, and we're no longer planning to sleep, don't need to
-    // do the stuff below, but we *DO* still need to acknowledge the sleep message we received.
-    if (!m->SleepState)
-        LogMsg("AllowSleepNow: Sleep request was canceled with %d ticks remaining", m->SleepLimit - now);
-    else
-    {
-        if (!m->SystemWakeOnLANEnabled || !mDNSCoreHaveAdvertisedMulticastServices(m))
-            LogSPS("AllowSleepNow: Not scheduling wakeup: SystemWakeOnLAN %s enabled; %s advertised services",
-                   m->SystemWakeOnLANEnabled                  ? "is" : "not",
-                   mDNSCoreHaveAdvertisedMulticastServices(m) ? "have" : "no");
-        else
-        {
-            const mDNSu32 dhcp = DHCPWakeTime();
-            LogSPS("ComputeWakeTime: DHCP Wake %d", dhcp);
-            mDNSNextWakeReason reason = mDNSNextWakeReason_Null;
-            mDNSs32 interval = mDNSCoreIntervalToNextWake(m, now, &reason) / mDNSPlatformOneSecond;
-            if ((interval >= 0) && (((mDNSu32)interval) > dhcp))
-            {
-                interval = (mDNSs32)dhcp;
-                reason = mDNSNextWakeReason_DHCPLeaseRenewal;
-            }
-            // If we're not ready to sleep (failed to register with Sleep Proxy, maybe because of
-            // transient network problem) then schedule a wakeup in one hour to try again. Otherwise,
-            // a single SPS failure could result in a remote machine falling permanently asleep, requiring
-            // someone to go to the machine in person to wake it up again, which would be unacceptable.
-            if (!ready && interval > 3600)
-            {
-                interval = 3600;
-                reason = mDNSNextWakeReason_SleepProxyRegistrationRetry;
-            }
-            //interval = 48; // For testing
-
-#if TARGET_OS_OSX && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
-            if (m->p->IOPMConnection)   // If lightweight-wake capability is available, use that
-            {
-                CFStringRef reasonStr;
-                switch (reason)
-                {
-                case mDNSNextWakeReason_NATPortMappingRenewal:
-                    reasonStr = CFSTR("NAT port mapping renewal");
-                    break;
-
-                case mDNSNextWakeReason_RecordRegistrationRenewal:
-                    reasonStr = CFSTR("record registration renewal");
-                    break;
-
-                case mDNSNextWakeReason_UpkeepWake:
-                    reasonStr = CFSTR("upkeep wake");
-                    break;
-
-                case mDNSNextWakeReason_DHCPLeaseRenewal:
-                    reasonStr = CFSTR("DHCP lease renewal");
-                    break;
-
-                case mDNSNextWakeReason_SleepProxyRegistrationRetry:
-                    reasonStr = CFSTR("sleep proxy registration retry");
-                    break;
-
-                case mDNSNextWakeReason_Null:
-                    reasonStr = CFSTR("unspecified");
-                    break;
-                }
-                CFDateRef WakeDate = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent() + interval);
-                if (!WakeDate) LogMsg("ScheduleNextWake: CFDateCreate failed");
-                else
-                {
-                    const mDNSs32 reqs         = kIOPMSystemPowerStateCapabilityNetwork;
-                    CFNumberRef Requirements = CFNumberCreate(NULL, kCFNumberSInt32Type, &reqs);
-                    if (Requirements == NULL) LogMsg("ScheduleNextWake: CFNumberCreate failed");
-                    else
-                    {
-                        const void *OptionKeys[3] = { kIOPMAckDHCPRenewWakeDate, kIOPMAckSystemCapabilityRequirements, kIOPMAckClientInfoKey };
-                        const void *OptionVals[3] = { WakeDate, Requirements, reasonStr };
-                        opts = CFDictionaryCreate(NULL, OptionKeys, OptionVals, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                        if (!opts) LogMsg("ScheduleNextWake: CFDictionaryCreate failed");
-                        MDNS_DISPOSE_CF_OBJECT(Requirements);
-                    }
-                    MDNS_DISPOSE_CF_OBJECT(WakeDate);
-                }
-                LogSPS("AllowSleepNow: Will request lightweight wakeup in %d seconds", interval);
-            }
-            else                        // else schedule the wakeup using the old API instead to
-#endif
-            {
-                // If we wake within +/- 30 seconds of our requested time we'll assume the system woke for us,
-                // so we should put it back to sleep. To avoid frustrating the user, we always request at least
-                // 60 seconds sleep, so if they immediately re-wake the system within seconds of it going to sleep,
-                // we then shouldn't hit our 30-second window, and we won't attempt to re-sleep the machine.
-                if (interval < 60)
-                    interval = 60;
-
-                mdns_power_cancel_all_events(kMDNSResponderID);
-                result = mdns_power_schedule_wake(kMDNSResponderID, interval, 0);
-                if (result == kIOReturnNotReady)
-                {
-                    int r;
-                    LogMsg("AllowSleepNow: Requested wakeup in %d seconds unsuccessful; retrying with longer intervals", interval);
-                    // IOPMSchedulePowerEvent fails with kIOReturnNotReady (-536870184/0xe00002d8) if the
-                    // requested wake time is "too soon", but there's no API to find out what constitutes
-                    // "too soon" on any given OS/hardware combination, so if we get kIOReturnNotReady
-                    // we just have to iterate with successively longer intervals until it doesn't fail.
-                    // We preserve the value of "result" because if our original power request was deemed "too soon"
-                    // for the machine to get to sleep and wake back up again, we attempt to cancel the sleep request,
-                    // since the implication is that the system won't manage to be awake again at the time we need it.
-                    do
-                    {
-                        interval += (interval < 20) ? 1 : ((interval+3) / 4);
-                        r = mdns_power_schedule_wake(kMDNSResponderID, interval, 0);
-                    }
-                    while (r == kIOReturnNotReady);
-                    if (r) LogMsg("AllowSleepNow: Requested wakeup in %d seconds unsuccessful: %d %X", interval, r, r);
-                    else LogSPS("AllowSleepNow: Requested later wakeup in %d seconds; will also attempt IOCancelPowerChange", interval);
-                }
-                else
-                {
-                    if (result) LogMsg("AllowSleepNow: Requested wakeup in %d seconds unsuccessful: %d %X", interval, result, result);
-                    else LogSPS("AllowSleepNow: Requested wakeup in %d seconds", interval);
-                }
-                m->p->WakeAtUTC = mDNSPlatformUTC() + interval;
-            }
-        }
-
-        m->SleepState = SleepState_Sleeping;
-		// Clear our interface list to empty state, ready to go to sleep
-		// As a side effect of doing this, we'll also cancel any outstanding SPS Resolve calls that didn't complete
-        mDNSMacOSXNetworkChanged();
-    }
-
-#if TARGET_OS_OSX && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
-    LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
-           (m->p->IOPMConnection) ? "IOPMConnectionAcknowledgeEventWithOptions" :
-           (result == kIOReturnSuccess) ? "IOAllowPowerChange" : "IOCancelPowerChange",
-           m->p->SleepCookie, ready ? "ready for sleep" : "giving up", now, m->SleepLimit - now);
-#else
-    LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
-           (result == kIOReturnSuccess) ? "IOAllowPowerChange" : "IOCancelPowerChange",
-           m->p->SleepCookie, ready ? "ready for sleep" : "giving up", now, m->SleepLimit - now);
-#endif
-    m->SleepLimit = 0;  // Don't clear m->SleepLimit until after we've logged it above
-    m->TimeSlept = mDNSPlatformUTC();
-
-#if TARGET_OS_OSX && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
-    if (m->p->IOPMConnection) IOPMConnectionAcknowledgeEventWithOptions(m->p->IOPMConnection, (IOPMConnectionMessageToken)m->p->SleepCookie, opts);
-    else
-#endif
-    if (result == kIOReturnSuccess) IOAllowPowerChange (m->p->PowerConnection, m->p->SleepCookie);
-    else IOCancelPowerChange(m->p->PowerConnection, m->p->SleepCookie);
-
-    MDNS_DISPOSE_CF_OBJECT(opts);
-    return(mDNStrue);
-}
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSexport void TriggerEventCompletion()
-{
-    debugf("TriggerEventCompletion: Merge data");
-    dispatch_source_merge_data(PlatformStorage.custom, 1);
-}
-
-mDNSlocal void PrepareForIdle(void *m_param)
-{
-    mDNS            *m = m_param;
-    int64_t time_offset;
-    dispatch_time_t dtime;
-
-    const int multiplier = 1000000000 / mDNSPlatformOneSecond;
-
-    // This is the main work loop:
-    // (1) First we give mDNSCore a chance to finish off any of its deferred work and calculate the next sleep time
-    // (2) Then we make sure we've delivered all waiting browse messages to our clients
-    // (3) Then we sleep for the time requested by mDNSCore, or until the next event, whichever is sooner
-
-    debugf("PrepareForIdle: called");
-    // Run mDNS_Execute to find out the time we next need to wake up
-    mDNSs32 start          = mDNSPlatformRawTime();
-    mDNSs32 nextTimerEvent = udsserver_idle(mDNSDaemonIdle(m));
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    if (m->DNSPushServers != mDNSNULL)
-    {
-        nextTimerEvent = dso_idle(m, nextTimerEvent);
-    }
-#endif
-    mDNSs32 end            = mDNSPlatformRawTime();
-    if (end - start >= WatchDogReportingThreshold)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "CustomSourceHandler: WARNING: Idle task took %d ms to complete", end - start);
-    }
-
-    mDNSs32 now = mDNS_TimeNow(m);
-
-    if (m->ShutdownTime)
-    {
-        if (mDNSStorage.ResourceRecords)
-        {
-            LogInfo("Cannot exit yet; Resource Record still exists: %s", ARDisplayString(m, mDNSStorage.ResourceRecords));
-            if (mDNS_LoggingEnabled) usleep(10000);     // Sleep 10ms so that we don't flood syslog with too many messages
-        }
-        if (mDNS_ExitNow(m, now))
-        {
-            LogInfo("IdleLoop: mDNS_FinalExit");
-            mDNS_FinalExit(&mDNSStorage);
-            usleep(1000);       // Little 1ms pause before exiting, so we don't lose our final syslog messages
-            exit(0);
-        }
-        if (nextTimerEvent - m->ShutdownTime >= 0)
-            nextTimerEvent = m->ShutdownTime;
-    }
-
-    if (m->SleepLimit)
-        if (!AllowSleepNow(now))
-            if (nextTimerEvent - m->SleepLimit >= 0)
-                nextTimerEvent = m->SleepLimit;
-
-    // Convert absolute wakeup time to a relative time from now
-    mDNSs32 ticks = nextTimerEvent - now;
-    if (ticks < 1) ticks = 1;
-
-    static mDNSs32 RepeatedBusy = 0;    // Debugging sanity check, to guard against CPU spins
-    if (ticks > 1)
-        RepeatedBusy = 0;
-    else
-    {
-        ticks = 1;
-        if (++RepeatedBusy >= mDNSPlatformOneSecond) { ShowTaskSchedulingError(&mDNSStorage); RepeatedBusy = 0; }
-    }
-
-    time_offset = ((mDNSu32)ticks / mDNSPlatformOneSecond) * 1000000000 + (ticks % mDNSPlatformOneSecond) * multiplier;
-    dtime = dispatch_time(DISPATCH_TIME_NOW, time_offset);
-    dispatch_source_set_timer(PlatformStorage.timer, dtime, 1000ull*1000000000, 0);
-    debugf("PrepareForIdle: scheduling timer with ticks %d", ticks);
-    return;
-}
-
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context, __unused mDNSBool encounteredEOF)
-{
-    // Read all of the bytes so we won't wake again.
-    char buffer[100];
-    while (recv(fd, buffer, sizeof(buffer), MSG_DONTWAIT) > 0) continue;
-}
-
-mDNSlocal void SetLowWater(const KQSocketSet *const k, const int r)
-{
-    if (k->sktv4 >=0 && setsockopt(k->sktv4, SOL_SOCKET, SO_RCVLOWAT, &r, sizeof(r)) < 0)
-        LogMsg("SO_RCVLOWAT IPv4 %d error %d errno %d (%s)", k->sktv4, r, errno, strerror(errno));
-    if (k->sktv6 >=0 && setsockopt(k->sktv6, SOL_SOCKET, SO_RCVLOWAT, &r, sizeof(r)) < 0)
-        LogMsg("SO_RCVLOWAT IPv6 %d error %d errno %d (%s)", k->sktv6, r, errno, strerror(errno));
-}
-
-mDNSlocal void * KQueueLoop(void *m_param)
-{
-    mDNS            *m = m_param;
-    int numevents = 0;
-
-#if USE_SELECT_WITH_KQUEUEFD
-    fd_set readfds;
-    FD_ZERO(&readfds);
-    const int multiplier = 1000000    / mDNSPlatformOneSecond;
-#else
-    const int multiplier = 1000000000 / mDNSPlatformOneSecond;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
-    dnssd_server_init();
-#endif
-    mrcs_server_init(&kMRCSServerHandlers);
-    pthread_mutex_lock(&PlatformStorage.BigMutex);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Starting time value 0x%08X (%d)", (mDNSu32)mDNSStorage.timenow_last, mDNSStorage.timenow_last);
-
-    // This is the main work loop:
-    // (1) First we give mDNSCore a chance to finish off any of its deferred work and calculate the next sleep time
-    // (2) Then we make sure we've delivered all waiting browse messages to our clients
-    // (3) Then we sleep for the time requested by mDNSCore, or until the next event, whichever is sooner
-    // (4) On wakeup we first process *all* events
-    // (5) then when no more events remain, we go back to (1) to finish off any deferred work and do it all again
-    for ( ; ; )
-    {
-        #define kEventsToReadAtOnce 1
-        struct kevent new_events[kEventsToReadAtOnce];
-
-        // Run mDNS_Execute to find out the time we next need to wake up
-        mDNSs32 start          = mDNSPlatformRawTime();
-        mDNSs32 nextTimerEvent = udsserver_idle(mDNSDaemonIdle(m));
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
-        dnssd_server_idle();
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-        resolved_cache_idle();
-#endif
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-        mDNS_Lock(m);
-        nextTimerEvent = dso_idle(m, m->timenow, nextTimerEvent);
-        mDNS_Unlock(m);
-#endif
-        mDNSs32 end            = mDNSPlatformRawTime();
-        if (end - start >= WatchDogReportingThreshold)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "WARNING: Idle task took %d ms to complete", end - start);
-        }
-
-#if MDNS_MALLOC_DEBUGGING >= 1
-        mDNSPlatformValidateLists();
-#endif
-
-        mDNSs32 now = mDNS_TimeNow(m);
-
-        if (m->ShutdownTime)
-        {
-            if (mDNSStorage.ResourceRecords)
-            {
-                AuthRecord *rr;
-                for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Cannot exit yet; Resource Record still exists: " PRI_S, ARDisplayString(m, rr));
-                    if (mDNS_LoggingEnabled) usleep(10000);     // Sleep 10ms so that we don't flood syslog with too many messages
-                }
-            }
-            if (mDNS_ExitNow(m, now))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_FinalExit");
-                mDNS_FinalExit(&mDNSStorage);
-                usleep(1000);       // Little 1ms pause before exiting, so we don't lose our final syslog messages
-                exit(0);
-            }
-            if (nextTimerEvent - m->ShutdownTime >= 0)
-                nextTimerEvent = m->ShutdownTime;
-        }
-
-        if (m->SleepLimit)
-            if (!AllowSleepNow(now))
-                if (nextTimerEvent - m->SleepLimit >= 0)
-                    nextTimerEvent = m->SleepLimit;
-
-        // Convert absolute wakeup time to a relative time from now
-        mDNSs32 ticks = nextTimerEvent - now;
-        if (ticks < 1) ticks = 1;
-
-        static mDNSs32 RepeatedBusy = 0;    // Debugging sanity check, to guard against CPU spins
-        if (ticks > 1)
-            RepeatedBusy = 0;
-        else
-        {
-            ticks = 1;
-            if (++RepeatedBusy >= mDNSPlatformOneSecond) { ShowTaskSchedulingError(&mDNSStorage); RepeatedBusy = 0; }
-        }
-
-        verbosedebugf("KQueueLoop: Handled %d events; now sleeping for %d ticks", numevents, ticks);
-        numevents = 0;
-
-        // Release the lock, and sleep until:
-        // 1. Something interesting happens like a packet arriving, or
-        // 2. The other thread writes a byte to WakeKQueueLoopFD to poke us and make us wake up, or
-        // 3. The timeout expires
-        pthread_mutex_unlock(&PlatformStorage.BigMutex);
-
-        // If we woke up to receive a multicast, set low-water mark to dampen excessive wakeup rate
-        if (m->p->num_mcasts)
-        {
-            SetLowWater(&m->p->permanentsockets, 0x10000);
-            if (ticks > mDNSPlatformOneSecond / 8) ticks = mDNSPlatformOneSecond / 8;
-        }
-
-#if USE_SELECT_WITH_KQUEUEFD
-        struct timeval timeout;
-        timeout.tv_sec = ticks / mDNSPlatformOneSecond;
-        timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * multiplier;
-        FD_SET(KQueueFD, &readfds);
-        if (select(KQueueFD+1, &readfds, NULL, NULL, &timeout) < 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "select(%d) failed errno %d (" PUB_S ")", KQueueFD, errno, strerror(errno));
-            sleep(1);
-        }
-#else
-        struct timespec timeout;
-        timeout.tv_sec = ticks / mDNSPlatformOneSecond;
-        timeout.tv_nsec = (ticks % mDNSPlatformOneSecond) * multiplier;
-        // In my opinion, you ought to be able to call kevent() with nevents set to zero,
-        // and have it work similarly to the way it does with nevents non-zero --
-        // i.e. it waits until either an event happens or the timeout expires, and then wakes up.
-        // In fact, what happens if you do this is that it just returns immediately. So, we have
-        // to pass nevents set to one, and then we just ignore the event it gives back to us. -- SC
-        if (kevent(KQueueFD, NULL, 0, new_events, 1, &timeout) < 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "kevent(%d) failed errno %d (" PUB_S ")", KQueueFD, errno, strerror(errno));
-            sleep(1);
-        }
-#endif
-
-        pthread_mutex_lock(&PlatformStorage.BigMutex);
-        // We have to ignore the event we may have been told about above, because that
-        // was done without holding the lock, and between the time we woke up and the
-        // time we reclaimed the lock the other thread could have done something that
-        // makes the event no longer valid. Now we have the lock, we call kevent again
-        // and this time we can safely process the events it tells us about.
-
-        // If we changed UDP socket low-water mark, restore it, so we will be told about every packet
-        if (m->p->num_mcasts)
-        {
-            SetLowWater(&m->p->permanentsockets, 1);
-            m->p->num_mcasts = 0;
-        }
-
-        static const struct timespec zero_timeout = { 0, 0 };
-        int events_found;
-        while ((events_found = kevent(KQueueFD, NULL, 0, new_events, kEventsToReadAtOnce, &zero_timeout)) != 0)
-        {
-            if (events_found > kEventsToReadAtOnce || (events_found < 0 && errno != EINTR))
-            {
-                const int kevent_errno = errno;
-                // Not sure what to do here, our kqueue has failed us - this isn't ideal
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "ERROR: KQueueLoop - kevent failed errno %d (" PUB_S ")", kevent_errno,
-                    strerror(kevent_errno));
-                exit(kevent_errno);
-            }
-
-            numevents += events_found;
-
-            int i;
-            for (i = 0; i < events_found; i++)
-            {
-                const KQueueEntry *const kqentry = new_events[i].udata;
-                mDNSs32 stime = mDNSPlatformRawTime();
-                const char *const KQtask = kqentry->KQtask; // Grab a copy in case KQcallback deletes the task
-                kqentry->KQcallback((int)new_events[i].ident, new_events[i].filter, kqentry->KQcontext, (new_events[i].flags & EV_EOF) != 0);
-                mDNSs32 etime = mDNSPlatformRawTime();
-                if (etime - stime >= WatchDogReportingThreshold)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "WARNING: " PUB_S " took %d ms to complete", KQtask, etime - stime);
-                }
-            }
-        }
-    }
-
-    return NULL;
-}
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal size_t LaunchdCheckin(void)
-{
-    // Ask launchd for our socket
-    int result = launch_activate_socket("Listeners", &launchd_fds, &launchd_fds_count);
-    if (result != 0) { LogMsg("launch_activate_socket() failed error %d (%s)", result, strerror(result)); }
-    return launchd_fds_count;
-}
-
-
-extern int sandbox_init(const char *profile, uint64_t flags, char **errorbuf) __attribute__((weak_import));
-
-
-mDNSlocal void SandboxProcess(void)
-{
-    // Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb
-#if defined(MDNS_NO_SANDBOX) && MDNS_NO_SANDBOX
-    LogMsg("Note: Compiled without Apple Sandbox support");
-#else // MDNS_NO_SANDBOX
-    if (!sandbox_init)
-        LogMsg("Note: Running without Apple Sandbox support (not available on this OS)");
-    else
-    {
-        char *sandbox_msg;
-        uint64_t sandbox_flags = SANDBOX_NAMED;
-
-        (void)confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0);
-
-        int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg);
-        if (sandbox_err)
-        {
-            LogMsg("WARNING: sandbox_init error %s", sandbox_msg);
-            // If we have errors in the sandbox during development, to prevent
-            // exiting, uncomment the following line.
-            //sandbox_free_error(sandbox_msg);
-            
-            errx(EX_OSERR, "sandbox_init() failed: %s", sandbox_msg);
-        }
-        else LogInfo("Now running under Apple Sandbox restrictions");
-    }
-#endif // MDNS_NO_SANDBOX
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-#define MDNS_OS_LOG_CATEGORY_INIT(NAME) \
-    do\
-    { \
-        mDNSLogCategory_ ## NAME = os_log_create(kMDNSResponderIDStr, # NAME ); \
-        mDNSLogCategory_ ## NAME ## _redacted = os_log_create(kMDNSResponderIDStr, # NAME "_redacted" ); \
-        if (!mDNSLogCategory_ ## NAME || !mDNSLogCategory_ ## NAME ## _redacted) \
-        { \
-            os_log_error(OS_LOG_DEFAULT, "Could NOT create the " # NAME " log handle in mDNSResponder"); \
-            mDNSLogCategory_ ## NAME = OS_LOG_DEFAULT; \
-        } \
-    } \
-    while (0)
-
-#define MDNS_OS_LOG_CATEGORY_DECLARE(NAME)                  \
-    os_log_t mDNSLogCategory_ ## NAME               = NULL; \
-    os_log_t mDNSLogCategory_ ## NAME ## _redacted  = NULL
-
-MDNS_OS_LOG_CATEGORY_DECLARE(Default);
-MDNS_OS_LOG_CATEGORY_DECLARE(mDNS);
-MDNS_OS_LOG_CATEGORY_DECLARE(uDNS);
-MDNS_OS_LOG_CATEGORY_DECLARE(SPS);
-MDNS_OS_LOG_CATEGORY_DECLARE(NAT);
-MDNS_OS_LOG_CATEGORY_DECLARE(D2D);
-MDNS_OS_LOG_CATEGORY_DECLARE(XPC);
-MDNS_OS_LOG_CATEGORY_DECLARE(Analytics);
-MDNS_OS_LOG_CATEGORY_DECLARE(DNSSEC);
-
-mDNSlocal void init_logging(void)
-{
-    MDNS_OS_LOG_CATEGORY_INIT(Default);
-    MDNS_OS_LOG_CATEGORY_INIT(mDNS);
-    MDNS_OS_LOG_CATEGORY_INIT(uDNS);
-    MDNS_OS_LOG_CATEGORY_INIT(SPS);
-    MDNS_OS_LOG_CATEGORY_INIT(NAT);
-    MDNS_OS_LOG_CATEGORY_INIT(D2D);
-    MDNS_OS_LOG_CATEGORY_INIT(XPC);
-    MDNS_OS_LOG_CATEGORY_INIT(Analytics);
-    MDNS_OS_LOG_CATEGORY_INIT(DNSSEC);
-}
-#endif
-
-#ifdef FUZZING
-#define main daemon_main
-#endif
-
-mDNSexport int main(int argc, char **argv)
-{
-    int i;
-    kern_return_t status;
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    mDNSBool bigMutexLocked = mDNSfalse;
-#endif
-
-#if DEBUG
-    bool useDebugSocket = mDNSfalse;
-    bool useSandbox = mDNStrue;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-    init_logging();
-#endif
-
-    mDNSMacOSXSystemBuildNumber(NULL);
-    LogMsg("%s starting %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
-
-#if 0
-    LogMsg("CacheRecord         %5d", sizeof(CacheRecord));
-    LogMsg("CacheGroup          %5d", sizeof(CacheGroup));
-    LogMsg("ResourceRecord      %5d", sizeof(ResourceRecord));
-    LogMsg("RData_small         %5d", sizeof(RData_small));
-
-    LogMsg("sizeof(CacheEntity) %5d", sizeof(CacheEntity));
-    LogMsg("RR_CACHE_SIZE       %5d", RR_CACHE_SIZE);
-    LogMsg("block bytes used    %5d",           sizeof(CacheEntity) * RR_CACHE_SIZE);
-    LogMsg("block bytes wasted  %5d", 32*1024 - sizeof(CacheEntity) * RR_CACHE_SIZE);
-#endif
-
-#if !DEBUG
-    if (0 == geteuid())
-    {
-        LogMsg("mDNSResponder cannot be run as root !! Exiting..");
-        return -1;
-    }
-#endif // !DEBUG
-
-    for (i=1; i<argc; i++)
-    {
-        if (!strcasecmp(argv[i], "-d"                        )) mDNS_DebugMode            = mDNStrue;
-        if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) NoMulticastAdvertisements = mDNStrue;
-        if (!strcasecmp(argv[i], "-DisableSleepProxyClient"  )) DisableSleepProxyClient   = mDNStrue;
-        if (!strcasecmp(argv[i], "-DebugLogging"             )) mDNS_LoggingEnabled       = mDNStrue;
-        if (!strcasecmp(argv[i], "-UnicastPacketLogging"     )) mDNS_PacketLoggingEnabled = mDNStrue;
-        if (!strcasecmp(argv[i], "-OfferSleepProxyService"   ))
-            OfferSleepProxyService = (i+1 < argc && mDNSIsDigit(argv[i+1][0]) && mDNSIsDigit(argv[i+1][1]) && argv[i+1][2]==0) ? atoi(argv[++i]) : 100;
-        if (!strcasecmp(argv[i], "-UseInternalSleepProxy"    ))
-            UseInternalSleepProxy = (i+1<argc && mDNSIsDigit(argv[i+1][0]) && argv[i+1][1]==0) ? atoi(argv[++i]) : 1;
-        if (!strcasecmp(argv[i], "-StrictUnicastOrdering"    )) StrictUnicastOrdering     = mDNStrue;
-        if (!strcasecmp(argv[i], "-AlwaysAppendSearchDomains")) AlwaysAppendSearchDomains = mDNStrue;
-        if (!strcasecmp(argv[i], "-DisableAllowExpired"      )) EnableAllowExpired        = mDNSfalse;
-#if DEBUG
-        if (!strcasecmp(argv[i], "-UseDebugSocket"))            useDebugSocket = mDNStrue;
-        if (!strcasecmp(argv[i], "-NoSandbox"))                 useSandbox = mDNSfalse;
-#endif    
-    }
-
-
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    PQWorkaroundThreshold     = PreferencesGetValueInt(kPreferencesKey_PQWorkaroundThreshold,      PQWorkaroundThreshold);
-    CFDictionaryRef managedDefaults = mdns_managed_defaults_create(kMDNSResponderIDStr, NULL);
-    if (managedDefaults)
-    {
-        PQWorkaroundThreshold = mdns_managed_defaults_get_int_clamped(managedDefaults,
-            kPreferencesKey_PQWorkaroundThreshold, PQWorkaroundThreshold, NULL);
-        MDNS_DISPOSE_CF_OBJECT(managedDefaults);
-    }
-#endif
-
-    // Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure
-    if (NoMulticastAdvertisements)
-        LogMsg("-NoMulticastAdvertisements is set: Administratively prohibiting multicast advertisements");
-    if (AlwaysAppendSearchDomains)
-        LogMsg("-AlwaysAppendSearchDomains is set");    
-    if (StrictUnicastOrdering)
-        LogMsg("-StrictUnicastOrdering is set");
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-    signal(SIGHUP,  HandleSIG);     // (Debugging) Purge the cache to check for cache handling bugs
-    signal(SIGINT,  HandleSIG);     // Ctrl-C: Detach from Mach BootstrapService and exit cleanly
-    signal(SIGPIPE,   SIG_IGN);     // Don't want SIGPIPE signals -- we'll handle EPIPE errors directly
-    signal(SIGTERM, HandleSIG);     // Machine shutting down: Detach from and exit cleanly like Ctrl-C
-    signal(SIGINFO, HandleSIG);     // (Debugging) Write state snapshot to syslog
-    signal(SIGUSR1, HandleSIG);     // (Debugging) Enable Logging
-    signal(SIGUSR2, HandleSIG);     // (Debugging) Enable Packet Logging
-    signal(SIGPROF, HandleSIG);     // (Debugging) Toggle Multicast Logging
-    signal(SIGTSTP, HandleSIG);     // (Debugging) Disable all Debug Logging (USR1/USR2/PROF)
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-    mDNSStorage.p = &PlatformStorage;   // Make sure mDNSStorage.p is set up, because validatelists uses it
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-    // Create the kqueue, mutex and thread to support KQSockets
-    KQueueFD = kqueue();
-    if (KQueueFD == -1)
-    {
-        const int kqueue_errno = errno;
-        LogMsg("kqueue() failed errno %d (%s)", kqueue_errno, strerror(kqueue_errno));
-        status = kqueue_errno;
-        goto exit;
-    }
-
-    i = pthread_mutex_init(&PlatformStorage.BigMutex, NULL);
-    if (i != 0) { LogMsg("pthread_mutex_init() failed error %d (%s)", i, strerror(i)); status = i; goto exit; }
-
-    pthread_mutex_lock(&PlatformStorage.BigMutex);
-    bigMutexLocked = mDNStrue;
-
-    int fdpair[2] = {0, 0};
-    i = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-    if (i == -1)
-    {
-        const int socketpair_errno = errno;
-        LogMsg("socketpair() failed errno %d (%s)", socketpair_errno, strerror(socketpair_errno));
-        status = socketpair_errno;
-        goto exit;
-    }
-
-    // Socket pair returned us two identical sockets connected to each other
-    // We will use the first socket to send the second socket. The second socket
-    // will be added to the kqueue so it will wake when data is sent.
-    static KQueueEntry wakeKQEntry = { KQWokenFlushBytes, NULL, "kqueue wakeup after CFRunLoop event" };
-
-    PlatformStorage.WakeKQueueLoopFD = fdpair[0];
-    KQueueSet(fdpair[1], EV_ADD, EVFILT_READ, &wakeKQEntry);
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-#if DEBUG
-    if (useSandbox)
-#endif
-    SandboxProcess();
-
-    status = mDNSDaemonInitialize();
-    if (status) { LogMsg("Daemon start: mDNSDaemonInitialize failed"); goto exit; }
-
-    // Need to Start XPC Server Before LaunchdCheckin() (Reason: radar:11023750)
-    xpc_server_init();
-#if DEBUG
-    if (!useDebugSocket) {
-        if (LaunchdCheckin() == 0)
-            useDebugSocket = mDNStrue;
-    }
-    if (useDebugSocket)
-        SetDebugBoundPath();
-#else
-    LaunchdCheckin();
-#endif
-
-    status = udsserver_init(launchd_fds, (mDNSu32)launchd_fds_count);
-    if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; }
-
-    mDNSMacOSXNetworkChanged();
-    UpdateDebugState();
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    LogInfo("Daemon Start: Using LibDispatch");
-#else
-      // Start the kqueue thread
-    pthread_t KQueueThread;
-    i = pthread_create(&KQueueThread, NULL, KQueueLoop, &mDNSStorage);
-    if (i != 0) { LogMsg("pthread_create() failed error %d (%s)", i, strerror(i)); status = i; goto exit; }
-#endif
-
-exit:
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    if (bigMutexLocked)
-    {
-        pthread_mutex_unlock(&PlatformStorage.BigMutex);
-    }
-#endif
-
-    if (status == 0)
-    {
-        CFRunLoopRun();
-        // This should never happen.
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "ERROR: CFRunLoopRun Exiting.");
-        mDNS_Close(&mDNSStorage);
-    }
-
-    LogMsg("%s exiting", mDNSResponderVersionString);
-    return(status);
-}
-
-// uds_daemon.c support routines /////////////////////////////////////////////
-
-mDNSlocal void kqUDSEventCallback(int fd, short filter, void *context, mDNSBool encounteredEOF)
-{
-    const KQSocketEventSource *const source = context;
-    (void)filter; // unused
-    (void)encounteredEOF; // unused
-    
-    source->callback(fd, source->context);
-}
-
-// Arrange things so that when data appears on fd, callback is called with context
-mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
-{
-    KQSocketEventSource **p = &gEventSources;
-    (void) platform_data;
-    while (*p && (*p)->fd != fd) p = &(*p)->next;
-    if (*p)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "udsSupportAddFDToEventLoop: ERROR fd %d already has EventLoop source entry", fd);
-        return mStatus_AlreadyRegistered;
-    }
-
-    KQSocketEventSource *newSource = (KQSocketEventSource*) callocL("KQSocketEventSource", sizeof(*newSource));
-    if (!newSource) return mStatus_NoMemoryErr;
-
-    newSource->next           = mDNSNULL;
-    newSource->fd             = fd;
-    newSource->callback       = callback;
-    newSource->context        = context;
-    newSource->kqs.KQcallback = kqUDSEventCallback;
-    newSource->kqs.KQcontext  = newSource;
-    newSource->kqs.KQtask     = "UDS client";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    newSource->kqs.readSource  = mDNSNULL;
-    newSource->kqs.writeSource = mDNSNULL;
-    newSource->kqs.fdClosed    = mDNSfalse;
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-    if (KQueueSet(fd, EV_ADD, EVFILT_READ, &newSource->kqs) == 0)
-    {
-        *p = newSource;
-        return mStatus_NoError;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "KQueueSet failed for fd %d errno %d (" PUB_S ")", fd, errno, strerror(errno));
-    freeL("KQSocketEventSource", newSource);
-    return mStatus_BadParamErr;
-}
-
-ssize_t udsSupportReadFD(dnssd_sock_t fd, char *buf, mDNSu32 len, int flags, void *platform_data)
-{
-    (void) platform_data;
-    return recv(fd, buf, len, flags);
-}
-
-mDNSexport mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data)     // Note: This also CLOSES the file descriptor
-{
-    KQSocketEventSource **p = &gEventSources;
-    (void) platform_data;
-    while (*p && (*p)->fd != fd) p = &(*p)->next;
-    if (*p)
-    {
-        KQSocketEventSource *s = *p;
-        *p = (*p)->next;
-        // We don't have to explicitly do a kqueue EV_DELETE here because closing the fd
-        // causes the kernel to automatically remove any associated kevents
-        mDNSPlatformCloseFD(&s->kqs, s->fd);
-        freeL("KQSocketEventSource", s);
-        return mStatus_NoError;
-    }
-    LogMsg("udsSupportRemoveFDFromEventLoop: ERROR fd %d not found in EventLoop source list", fd);
-    return mStatus_NoSuchNameErr;
-}
-
-#ifdef UNIT_TEST
-#include "../unittests/daemon_ut.c"
-#endif // UNIT_TEST
-
-#if _BUILDING_XCODE_PROJECT_
-// If mDNSResponder crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = mDNSResponderVersionString;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
-asm (".desc ___crashreporter_info__, 0x10");
-#pragma GCC diagnostic pop
-#endif
-
-// For convenience when using the "strings" command, this is the last thing in the file
-// The "@(#) " pattern is a special prefix the "what" command looks for
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdate-time"
-mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-#pragma GCC diagnostic pop
diff --git a/mDNSMacOSX/dnsproxy.c b/mDNSMacOSX/dnsproxy.c
deleted file mode 100644
index d4601ec..0000000
--- a/mDNSMacOSX/dnsproxy.c
+++ /dev/null
@@ -1,1097 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2011-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "dnsproxy.h"
-#include "mrcs_dns_proxy.h"
-#include "mrcs_server.h"
-#include "mdns_strict.h"
-#include "mDNSMacOSX.h"
-#include <AssertMacros.h>
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-#include <nw/private.h>
-#endif
-
-#ifndef UNICAST_DISABLED
-
-extern mDNS mDNSStorage;
-
-// Implementation Notes
-//
-// DNS Proxy listens on port 53 (UDPv4v6 & TCPv4v6) for DNS queries. It handles only
-// the "Query" opcode of the DNS protocol described in RFC 1035. For all other opcodes, it returns
-// "Not Implemented" error. The platform interface mDNSPlatformInitDNSProxySkts
-// sets up the sockets and whenever it receives a packet, it calls ProxyTCPCallback or ProxyUDPCallback
-// defined here. For TCP socket, the platform does the "accept" and only sends the received packets
-// on the newly accepted socket. A single UDP socket (per address family) is used to send/recv
-// requests/responses from all clients. For TCP, there is one socket per request. Hence, there is some
-// extra state that needs to be disposed at the end.
-//
-// When a DNS request is received, ProxyCallbackCommon checks for malformed packet etc. and also checks
-// for duplicates, before creating DNSProxyClient state and starting a question with the "core"
-// (mDNS_StartQuery). When the callback for the question happens, it gathers all the necessary
-// resource records, constructs a response and sends it back to the client.
-//
-//   - Question callback is called with only one resource record at a time. We need all the resource
-//     records to construct the response. Hence, we lookup all the records ourselves. 
-//
-//   - The response may not fit the client's buffer size. In that case, we need to set the truncate bit
-//     and the client would retry using TCP.
-//
-//   - The client may have set the DNSSEC OK bit in the EDNS0 option and that means we also have to
-//     return the RRSIGs or the NSEC records with the RRSIGs in the Additional section. We need to
-//     ask the "core" to fetch the DNSSEC records and do the validation if the CD bit is not set.
-//
-// Once the response is sent to the client, the client state is disposed. When there is no response
-// from the "core", it eventually times out and we will not find any answers in the cache and we send a
-// "NXDomain" response back. Thus, we don't need any special timers to reap the client state in the case
-// of errors. 
-
-typedef struct DNSProxyClient_struct DNSProxyClient;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-typedef enum
-{
-    kDNSProxyDNS64State_Initial                 = 0,    // Initial state.
-    kDNSProxyDNS64State_AAAASynthesis           = 1,    // Querying for A record for AAAA record synthesis.
-    kDNSProxyDNS64State_PTRSynthesisTrying      = 2,    // Querying for in-addr.arpa PTR record to map from ip6.arpa PTR.
-    kDNSProxyDNS64State_PTRSynthesisSuccess     = 3,    // in-addr.arpa PTR query got non-negative non-CNAME answer.
-    kDNSProxyDNS64State_PTRSynthesisNXDomain    = 4     // in-addr.arpa PTR query produced no useful result.
-
-}   DNSProxyDNS64State;
-#endif
-
-// Note: This needs to maintain compatibility with struct DNSMessage defined in mDNSEmbeddedAPI.h
-typedef struct
-{
-    DNSMessageHeader h;             // Note: Size 12 bytes
-    mDNSu8 data[];                  // Flexible storage. Start at NormalUDPDNSMessageData,
-                                    // then try rcvBufSize if present or AbsoluteMaxDNSMessageData if tcp
-} _DNSMessage;
-
-struct DNSProxyClient_struct
-{
-    DNSProxyClient *next; 
-    mDNSAddr    addr;               // Client's IP address 
-    mDNSIPPort  port;               // Client's port number
-    mDNSOpaque16 msgid;             // DNS msg id
-    mDNSInterfaceID interfaceID;    // Interface on which we received the request
-    void *socket;                   // Return socket
-    mDNSBool tcp;                   // TCP or UDP ?
-    mDNSOpaque16 requestFlags;      // second 16 bit word in the DNSMessageHeader of the request
-    mDNSu8 *optRR;                  // EDNS0 option
-    mDNSu32 optLen;                 // Total Length of the EDNS0 option
-    mDNSu16 rcvBufSize;             // How much can the client receive ?
-    void *context;                  // Platform context to be disposed if non-NULL
-    domainname qname;               // q->qname can't be used for duplicate check
-    DNSQuestion q;                  // as it can change underneath us for CNAMEs
-    mDNSu16 qtype;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-    DNSProxyDNS64State dns64state;
-#endif
-    mDNSu8 *omsg_ptr;               // Where we are in the omsg->data
-    mDNSu16 omsg_size;              // The current size of omsg->data
-    _DNSMessage *omsg;              // Outgoing message we're building
-    mrcs_dns_proxy_t proxy;         // A reference to the DNS proxy that this client request belongs to.
-};
-
-typedef struct
-{
-    DNSMessageHeader h;
-    size_t omsg_offset;
-} _MsgResourceState;
-
-// 12 (DNS message header) + 500 (DNS message body) = 512 total
-#define NormalUDPDNSMessageData 500
-
-// OPT pseudo-resource record fixed-length fields without RDATA
-// See <https://tools.ietf.org/html/rfc6891#section-6.1.2>
-typedef struct
-{
-    mDNSu8 name[1];
-    mDNSu8 type[2];
-    mDNSu8 udpPayloadSize[2];
-    mDNSu8 extendedRCode[1];
-    mDNSu8 version[1];
-    mDNSu8 extendedFlags[2];
-    mDNSu8 rdLen[2];
-} OPTRecordFixedFields;
-
-extern int sizecheck_OPTRecordFixedFields[(sizeof(OPTRecordFixedFields) == 11) ? 1 : -1];
-
-static DNSProxyClient *DNSProxyClients;
-
-mDNSlocal void FreeDNSProxyClient(DNSProxyClient *pc)
-{
-    if (pc->optRR)
-        mDNSPlatformMemFree(pc->optRR);
-    if (pc->omsg)
-        mDNSPlatformMemFree(pc->omsg);
-    mrcs_forget(&pc->proxy);
-    mDNSPlatformMemFree(pc);
-}
-
-mDNSlocal mDNSBool DNSProxyPrepareOmsg(const mDNSu16 size, DNSProxyClient *const pc)
-{
-    mDNSu32 allocation_size = sizeof(_DNSMessage) + size; // Handle values up to UINT16_MAX + sizeof(_DNSMessage)
-    size_t offset = 0;
-    if (!pc->omsg)
-    {
-        pc->omsg = mDNSPlatformMemAllocateClear(allocation_size);
-        if (!pc->omsg)
-        {
-            return mDNSfalse;
-        }
-    }
-    else
-    {
-        void * new_ptr = mDNSPlatformMemAllocateClear(allocation_size);
-        if (!new_ptr)
-        {
-            return mDNSfalse;
-        }
-        offset = pc->omsg_ptr - pc->omsg->data;
-        LogInfo("DNSProxyPrepareOmsg: Preserving offset %ld in size %d", offset, pc->omsg_size);
-        memcpy(new_ptr, pc->omsg, MIN(sizeof(_DNSMessage) + pc->omsg_size, allocation_size));
-        mDNSPlatformMemFree(pc->omsg);
-        pc->omsg = new_ptr;
-    }
-    pc->omsg_size = size;
-    pc->omsg_ptr = pc->omsg->data + offset;
-    return mDNStrue;
-}
-
-mDNSlocal mDNSBool DNSProxyMsgCanGrow(const DNSProxyClient *const pc, mDNSu16 *out_size)
-{
-    mDNSu16 max_size;
-    if (!pc->tcp)
-    {
-        if (!pc->rcvBufSize)
-        {
-            max_size = NormalUDPDNSMessageData;
-        }
-        else
-        {
-            mDNSu16 bufSize = (pc->rcvBufSize > sizeof(_DNSMessage)) ? (pc->rcvBufSize - sizeof(_DNSMessage)) : NormalUDPDNSMessageData;
-            max_size = (bufSize > AbsoluteMaxDNSMessageData ? AbsoluteMaxDNSMessageData : bufSize);
-        }
-    }
-    else
-    {
-        // For TCP, max_size is not determined by EDNS0 but by 16 bit rdlength field and
-        // AbsoluteMaxDNSMessageData is smaller than 64k.
-        max_size = AbsoluteMaxDNSMessageData;
-    }
-    if (out_size)
-    {
-        *out_size = max_size;
-    }
-    return (pc->omsg_size < max_size);
-}
-
-mDNSlocal void DNSMsgStateSave(const DNSProxyClient *const pc, _MsgResourceState *const state)
-{
-    mDNSPlatformMemCopy(&state->h, &pc->omsg->h, sizeof(DNSMessageHeader));
-    state->omsg_offset = pc->omsg_ptr - pc->omsg->data;
-}
-
-mDNSlocal void DNSMsgStateRestore(DNSProxyClient *const pc, const _MsgResourceState *const state)
-{
-    mDNSPlatformMemCopy(&pc->omsg->h, &state->h, sizeof(DNSMessageHeader));
-    pc->omsg_ptr = pc->omsg->data + state->omsg_offset;
-}
-
-mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-    DNSProxyClient *pc = (DNSProxyClient *)q->QuestionContext;
-
-    (void) msg;
-
-    h->flags = pc->requestFlags;
-    if (pc->optRR)
-    {
-        if (ptr + pc->optLen > limit)
-        {
-            LogInfo("DNSProxySetAttributes: Cannot set EDNS0 option start %p, OptLen %d, end %p", ptr, pc->optLen, limit);
-            return ptr;
-        }
-        h->numAdditionals++;
-        mDNSPlatformMemCopy(ptr, pc->optRR, pc->optLen);
-        ptr += pc->optLen;
-    }
-    return ptr;
-}
-
-mDNSlocal mDNSu8 *AddEDNS0Option(_DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-    int len = 4096;
-
-    if (ptr + 11 > limit)
-    {
-        LogInfo("AddEDNS0Option: not enough space");
-        return mDNSNULL;
-    }
-    msg->h.numAdditionals++;
-    ptr[0] = 0;
-    ptr[1] = (mDNSu8) (kDNSType_OPT >> 8);
-    ptr[2] = (mDNSu8) (kDNSType_OPT & 0xFF);
-    ptr[3] = (mDNSu8) (len >> 8);
-    ptr[4] = (mDNSu8) (len & 0xFF);
-    ptr[5] = 0;     // rcode
-    ptr[6] = 0;     // version
-    ptr[7] = 0;
-    ptr[8] = 0;     // flags
-    ptr[9] = 0;     // rdlength
-    ptr[10] = 0;    // rdlength
-
-    LogInfo("AddEDNS0 option added to response");
-
-    return (ptr + 11);
-}
-
-// Currently RD and CD bit should be copied if present in the request or cleared if
-// not present in the request. RD bit is normally set in the response and hence the
-// cache reflects the right value. CD bit behaves differently. If the CD bit is set
-// the first time, the cache retains it, if it is present in response (assuming the
-// upstream server does it right). Next time through we should not use the cached
-// value of the CD bit blindly. It depends on whether it was in the request or not.
-mDNSlocal mDNSOpaque16 SetResponseFlags(DNSProxyClient *pc, const mDNSOpaque16 responseFlags)
-{
-    mDNSOpaque16 rFlags = responseFlags;
-
-    if (pc->requestFlags.b[0] & kDNSFlag0_RD)
-        rFlags.b[0] |= kDNSFlag0_RD;
-    else
-        rFlags.b[0] &= ~kDNSFlag0_RD;
-
-    if (pc->requestFlags.b[1] & kDNSFlag1_CD)
-        rFlags.b[1] |= kDNSFlag1_CD;
-    else
-        rFlags.b[1] &= ~kDNSFlag1_CD;
-
-    return rFlags;
-}
-
-mDNSlocal mDNSu8 *AddResourceRecord(DNSProxyClient *pc, mDNSu8 **prevptr, mStatus *error, mDNSBool final_answer)
-{
-    mDNS *const m = &mDNSStorage;
-    CacheGroup *cg;
-    CacheRecord *cr;
-    int len = sizeof(DNSMessageHeader);
-    mDNSu8 *ptr = mDNSNULL;
-    mDNSs32 now;
-    mDNSs32 ttl;
-    const CacheRecord *soa = mDNSNULL;
-    mDNSu8 *limit;
-
-    *error = mStatus_NoError;
-    *prevptr = mDNSNULL;
-
-    mDNS_Lock(m);
-    now = m->timenow;
-    mDNS_Unlock(m);
-    
-    if (pc->tcp || !pc->rcvBufSize || pc->rcvBufSize > pc->omsg_size)
-    {
-        limit = pc->omsg->data + pc->omsg_size;
-    }
-    else
-    {
-        limit = pc->omsg->data + pc->rcvBufSize;
-    }
-    LogInfo("AddResourceRecord: Limit is %d", limit - pc->omsg_ptr);
-
-    cg = CacheGroupForName(m, pc->q.qnamehash, &pc->q.qname);
-    if (!cg)
-    {
-        LogInfo("AddResourceRecord: CacheGroup not found for %##s", pc->q.qname.c);
-        *error = mStatus_NoSuchRecord;
-        return mDNSNULL;
-    }
-    for (cr = cg->members; cr; cr = cr->next)
-    {
-        if (SameNameCacheRecordAnswersQuestion(cr, &pc->q))
-        {
-            if (pc->omsg->h.numQuestions == 0)
-            {
-                // If this is the first time, initialize the header and the question.
-                // This code needs to be here so that we can use the responseFlags from the
-                // cache record
-                mDNSOpaque16 responseFlags = SetResponseFlags(pc, cr->responseFlags);
-                InitializeDNSMessage(&pc->omsg->h, pc->msgid, responseFlags);
-                ptr = putQuestion((DNSMessage*)pc->omsg, pc->omsg->data, limit, &pc->qname, pc->qtype, pc->q.qclass);
-                if (!ptr)
-                {
-                    LogInfo("AddResourceRecord: putQuestion NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-                    return mDNSNULL;
-                }
-                len += (ptr - pc->omsg_ptr);
-                pc->omsg_ptr = ptr;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-                if (pc->dns64state == kDNSProxyDNS64State_PTRSynthesisSuccess)
-                {
-                    // For the first answer record, synthesize a CNAME record to map the originally requested ip6.arpa
-                    // domain name to the in-addr.arpa domain name.
-                    // See <https://tools.ietf.org/html/rfc6147#section-5.3.1>.
-                    RData rdata;
-                    ResourceRecord newRR;
-                    mDNSPlatformMemZero(&newRR, (mDNSu32)sizeof(newRR));
-                    newRR.RecordType    = kDNSRecordTypePacketAns;
-                    newRR.rrtype        = kDNSType_CNAME;
-                    newRR.rrclass       = kDNSClass_IN;
-                    newRR.name          = &pc->qname;
-                    AssignDomainName(&rdata.u.name, &pc->q.qname);
-                    rdata.MaxRDLength   = (mDNSu32)sizeof(rdata.u);
-                    newRR.rdata         = &rdata;
-                    ptr = PutResourceRecordTTLWithLimit((DNSMessage*)pc->omsg, ptr, &pc->omsg->h.numAnswers, &newRR, 0, limit);
-                    if (!ptr)
-                    {
-                        *prevptr = pc->omsg_ptr;
-                        return mDNSNULL;
-                    }
-                    len += (ptr - pc->omsg_ptr);
-                    pc->omsg_ptr = ptr;
-                }
-#endif
-            }
-            else if (!ptr)
-            {
-                ptr = pc->omsg_ptr;
-            }
-            // - For NegativeAnswers there is nothing to add
-            // - If DNSSECOK is set, we also automatically lookup the RRSIGs which
-            //   will also be returned. If the client is explicitly looking up
-            //   a DNSSEC record (e.g., DNSKEY, DS) we should return the response.
-            //   DNSSECOK bit only influences whether we add the RRSIG or not.
-            if (cr->resrec.RecordType != kDNSRecordTypePacketNegative)
-            {
-                const ResourceRecord *rr;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-                RData rdata;
-                ResourceRecord newRR;
-                const nw_nat64_prefix_t *const nat64_prefix = mrcs_dns_proxy_get_nat64_prefix(pc->proxy);
-                if (nat64_prefix && (pc->dns64state == kDNSProxyDNS64State_AAAASynthesis) && (cr->resrec.rrtype == kDNSType_A))
-                {
-                    struct in_addr  addrV4;
-                    struct in6_addr addrV6;
-
-                    newRR               = cr->resrec;
-                    newRR.rrtype        = kDNSType_AAAA;
-                    newRR.rdlength      = 16;
-                    rdata.MaxRDLength   = newRR.rdlength;
-                    newRR.rdata         = &rdata;
-
-                    memcpy(&addrV4.s_addr, cr->resrec.rdata->u.ipv4.b, 4);
-                    if (nw_nat64_synthesize_v6(nat64_prefix, &addrV4, &addrV6))
-                    {
-                        memcpy(rdata.u.ipv6.b, addrV6.s6_addr, 16);
-                        rr = &newRR;
-                    }
-                    else
-                    {
-                        continue;
-                    }
-                }
-                else
-#endif
-                {
-                    rr = &cr->resrec;
-                }
-                LogInfo("AddResourceRecord: Answering question with %s", RRDisplayString(m, rr));
-                ttl = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
-                ptr = PutResourceRecordTTLWithLimit((DNSMessage*)pc->omsg, ptr, &pc->omsg->h.numAnswers, rr, ttl, limit);
-                if (!ptr)
-                {
-                    *prevptr = pc->omsg_ptr;
-                    return mDNSNULL;
-                }
-                len += (ptr - pc->omsg_ptr);
-                pc->omsg_ptr = ptr;
-            }
-            if (cr->soa)
-            {
-                LogInfo("AddResourceRecord: soa set for %s", CRDisplayString(m ,cr));
-                soa = cr->soa;
-            }
-            // If we are using CNAME to answer a question and CNAME is not the type we
-            // are looking for, note down the CNAME record so that we can follow them
-            // later. Before we follow the CNAME, print the RRSIGs and any nsec (wildcard
-            // expanded) if any.
-            if ((pc->q.qtype != cr->resrec.rrtype) && cr->resrec.rrtype == kDNSType_CNAME)
-            {
-                LogInfo("AddResourceRecord: cname set for %s", CRDisplayString(m ,cr));
-            }
-        }
-    }
-    // Along with the nsec records, we also cache the SOA record. For non-DNSSEC question, we need
-    // to send the SOA back. Normally we either cache the SOA record (non-DNSSEC question) pointed
-    // to by "cr->soa" or the NSEC/SOA records along with their RRSIGs (DNSSEC question) pointed to
-    // by "cr->nsec". Two cases:
-    //
-    // - if we issue a DNSSEC question followed by non-DNSSEC question for the same name,
-    //   we only have the nsec records and we need to filter the SOA record alone for the
-    //   non-DNSSEC questions.
-    //
-    // - if we issue a non-DNSSEC question followed by DNSSEC question for the same name,
-    //   the "core" flushes the cache entry and re-issue the question with EDNS0/DOK bit and
-    //   in this case we return all the DNSSEC records we have.
-    if (soa)
-    {
-        LogInfo("AddResourceRecord: SOA Answering question with %s", CRDisplayString(m, soa));
-        ptr = PutResourceRecordTTLWithLimit((DNSMessage*)pc->omsg, ptr, &pc->omsg->h.numAuthorities, &soa->resrec, soa->resrec.rroriginalttl, limit);
-        if (!ptr)
-        {
-            *prevptr = pc->omsg_ptr;
-            return mDNSNULL;
-        }
-        len += (ptr - pc->omsg_ptr);
-        pc->omsg_ptr = ptr;
-    }
-    if (!ptr)
-    {
-        LogInfo("AddResourceRecord: Did not find any valid ResourceRecords");
-        *error = mStatus_NoSuchRecord;
-        return mDNSNULL;
-    }
-    if (final_answer && pc->rcvBufSize)
-    {
-        ptr = AddEDNS0Option(pc->omsg, ptr, limit);
-        if (!ptr)
-        {
-            *prevptr = pc->omsg_ptr;
-            return mDNSNULL;
-        }
-        len += (ptr - pc->omsg_ptr);
-        pc->omsg_ptr = ptr;
-    }
-    LogInfo("AddResourceRecord: Added %d bytes to the packet", len);
-    return ptr;
-}
-
-mDNSlocal void ProxyClientCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    DNSProxyClient *pc = question->QuestionContext;
-    DNSProxyClient **ppc = &DNSProxyClients;
-    mDNSu8 *ptr;
-    mDNSu8 *prevptr = mDNSNULL;
-    mStatus error;
-    mDNSBool final_answer = ((answer->RecordType == kDNSRecordTypePacketNegative) || (answer->rrtype == question->qtype));
-
-    if (!AddRecord)
-        return;
-
-    LogInfo("ProxyClientCallback: %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-    if (mrcs_dns_proxy_get_nat64_prefix(pc->proxy))
-    {
-        if (pc->dns64state == kDNSProxyDNS64State_Initial)
-        {
-            // If we get a negative AAAA answer, then retry the query as an A record query.
-            // See <https://tools.ietf.org/html/rfc6147#section-5.1.6>.
-            if ((answer->RecordType == kDNSRecordTypePacketNegative) && (question->qtype == kDNSType_AAAA) &&
-                (answer->rrtype == kDNSType_AAAA) && (answer->rrclass == kDNSClass_IN))
-            {
-                mDNS_StopQuery(m, question);
-                pc->dns64state = kDNSProxyDNS64State_AAAASynthesis;
-                question->qtype = kDNSType_A;
-                mDNS_StartQuery(m, question);
-                return;
-            }
-        }
-        else if (pc->dns64state == kDNSProxyDNS64State_PTRSynthesisTrying)
-        {
-            // If we get a non-negative non-CNAME answer, then this is the answer we give to the client.
-            // Otherwise, just respond with NXDOMAIN.
-            // See <https://tools.ietf.org/html/rfc6147#section-5.3.1>.
-            if ((answer->RecordType != kDNSRecordTypePacketNegative) && (question->qtype == kDNSType_PTR) &&
-                (answer->rrtype == kDNSType_PTR) && (answer->rrclass == kDNSClass_IN))
-            {
-                pc->dns64state = kDNSProxyDNS64State_PTRSynthesisSuccess;
-            }
-            else
-            {
-                pc->dns64state = kDNSProxyDNS64State_PTRSynthesisNXDomain;
-            }
-        }
-    }
-    if (pc->dns64state == kDNSProxyDNS64State_PTRSynthesisNXDomain)
-    {
-        const mDNSOpaque16 flags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery, kDNSFlag1_RC_NXDomain } };
-        InitializeDNSMessage(&pc->omsg->h, pc->msgid, flags);
-        ptr = putQuestion((DNSMessage*)pc->omsg, pc->omsg->data, pc->omsg->data + pc->omsg_size, &pc->qname, pc->qtype,
-            pc->q.qclass);
-        if (!ptr)
-        {
-            LogInfo("ProxyClientCallback: putQuestion NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-        }
-    }
-    else
-#endif
-    {
-        for(;;)
-        {
-            _MsgResourceState save;
-            DNSMsgStateSave(pc, &save);
-            ptr = AddResourceRecord(pc, &prevptr, &error, final_answer);
-            if (!ptr)
-            {
-                mDNSu16 max_size;
-                if (DNSProxyMsgCanGrow(pc, &max_size))
-                {
-                    LogInfo("ProxyClientCallback: Increase omsg buffer size to %d for %##s (%s)", max_size, &pc->qname.c, DNSTypeName(pc->qtype));
-                    if (!DNSProxyPrepareOmsg(max_size, pc))
-                    {
-                        LogMsg("ProxyClientCallback: AbsoluteMaxDNSMessageData memory failure for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-                    }
-                    else
-                    {
-                        DNSMsgStateRestore(pc, &save);
-                        continue;   // try again
-                    }
-                }
-            }
-            break;
-        }
-        if (!ptr)
-        {
-            LogInfo("ProxyClientCallback: AddResourceRecord NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-            if (error == mStatus_NoError && prevptr)
-            {
-                // No space to add the record. Set the Truncate bit for UDP.
-                //
-                // TBD: For TCP, we need to send the rest of the data. But finding out what is left
-                // is harder. We should allocate enough buffer in the first place to send all
-                // of the data.
-                if (!pc->tcp)
-                {
-                    pc->omsg->h.flags.b[0] |= kDNSFlag0_TC;
-                    ptr = prevptr;
-                }
-                else
-                {
-                    LogInfo("ProxyClientCallback: ERROR!! Not enough space to return in TCP for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-                    ptr = prevptr;
-                }
-            }
-            else
-            {
-                mDNSOpaque16 flags   = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery, kDNSFlag1_RC_ServFail } };
-                // We could not find the record for some reason. Return a response, so that the client
-                // is not waiting forever.
-                LogInfo("ProxyClientCallback: No response");
-                if (!mDNSOpaque16IsZero(pc->q.responseFlags))
-                    flags = pc->q.responseFlags;
-                InitializeDNSMessage(&pc->omsg->h, pc->msgid, flags);
-                ptr = putQuestion((DNSMessage*)pc->omsg, pc->omsg->data, pc->omsg->data + pc->omsg_size, &pc->qname, pc->qtype, pc->q.qclass);
-                if (!ptr)
-                {
-                    LogInfo("ProxyClientCallback: putQuestion NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->qtype));
-                    goto done;
-                }
-            }
-        }
-        if (!final_answer)
-        {
-            // Wait till we get called for the real response
-            LogInfo("ProxyClientCallback: Received %s, not answering yet", RRDisplayString(m, answer));
-            return;
-        }
-    }
-    debugf("ProxyClientCallback: InterfaceID is %p for response to client", pc->interfaceID);
-
-    if (!pc->tcp)
-    {
-        mDNSSendDNSMessage(m, (DNSMessage*)pc->omsg, ptr, pc->interfaceID, mDNSNULL, (UDPSocket *)pc->socket, &pc->addr, pc->port, mDNSNULL, mDNSfalse);
-    }
-    else
-    {
-        mDNSSendDNSMessage(m, (DNSMessage*)pc->omsg, ptr, pc->interfaceID, (TCPSocket *)pc->socket, mDNSNULL, &pc->addr, pc->port, mDNSNULL, mDNSfalse);
-    }
-
-done:
-    mDNS_StopQuery(m, question);
-
-    while (*ppc && *ppc != pc)
-        ppc=&(*ppc)->next;
-    if (!*ppc)
-    {
-        LogMsg("ProxyClientCallback: question %##s (%s) not found", question->qname.c, DNSTypeName(question->qtype));
-        return;
-    }
-    *ppc = pc->next;
-    mDNSPlatformDisposeProxyContext(pc->context);
-    FreeDNSProxyClient(pc);
-}
-
-mDNSlocal void SendError(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *dstaddr,
-    const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context, mDNSu8 rcode)
-{
-    mDNS *const m = &mDNSStorage;
-    int pktlen = (int)(end - (mDNSu8 *)msg);
-
-    // RFC 1035 requires that we copy the question back and RFC 2136 is okay with sending nothing
-    // in the body or send back whatever we get for updates. It is easy to return whatever we get
-    // in the question back to the responder. We return as much as we can fit in our standard
-    // output packet.
-    if (pktlen > AbsoluteMaxDNSMessageData)
-        pktlen = AbsoluteMaxDNSMessageData;
-
-    mDNSPlatformMemCopy(&m->omsg.h, &msg->h, sizeof(DNSMessageHeader));
-    m->omsg.h.flags.b[0] |= kDNSFlag0_QR_Response;
-    m->omsg.h.flags.b[1] = rcode;
-    mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->data, (pktlen - sizeof(DNSMessageHeader)));
-    
-    if (!tcp)
-    {
-        mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, mDNSNULL, socket, dstaddr, dstport, mDNSNULL, mDNSfalse);
-    }
-    else
-    {
-        mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, (TCPSocket *)socket, mDNSNULL, dstaddr, dstport, mDNSNULL, mDNSfalse);
-    }
-    mDNSPlatformDisposeProxyContext(context);
-}
-
-mDNSlocal DNSQuestion *IsDuplicateClient(const mDNSAddr *const addr, const mDNSIPPort port, const mDNSOpaque16 id,
-    const DNSQuestion *const question)
-{
-    DNSProxyClient *pc;
-
-    for (pc = DNSProxyClients; pc; pc = pc->next)
-    {
-        if (mDNSSameAddress(&pc->addr, addr)   &&
-            mDNSSameIPPort(pc->port, port)  &&
-            mDNSSameOpaque16(pc->msgid, id) &&
-            pc->qtype == question->qtype  &&
-            pc->q.qclass  == question->qclass &&
-            SameDomainName(&pc->qname, &question->qname))
-        {
-            LogInfo("IsDuplicateClient: Found a duplicate client in the list");
-            return(&pc->q);
-        }
-    }
-    return(mDNSNULL);
-}
-
-static mrcs_dns_proxy_manager_t gProxyManager = mDNSNULL;
-
-mDNSlocal mrcs_dns_proxy_t DNSProxyGetDNSProxyInstance(mDNSInterfaceID InterfaceID)
-{
-    const mDNSu32 index = (mDNSu32)(uintptr_t)InterfaceID;
-    return (gProxyManager ? mrcs_dns_proxy_manager_get_proxy_by_input_interface(gProxyManager, index) : mDNSNULL);
-}
-
-mDNSlocal void ProxyCallbackCommon(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-    const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSu8 QR_OP;
-    const mDNSu8 *ptr;
-    DNSQuestion q, *qptr;
-    DNSProxyClient *pc;
-    const mDNSu8 *optRR = mDNSNULL;
-    mDNSu32 optLen = 0;
-    DNSProxyClient **ppc = &DNSProxyClients;
-
-    (void) dstaddr;
-    (void) dstport;
-
-    debugf("ProxyCallbackCommon: DNS Query coming from InterfaceID %p", InterfaceID);
-    // Ignore if the DNS Query is not from a Valid Input InterfaceID
-    const mrcs_dns_proxy_t proxy = DNSProxyGetDNSProxyInstance(InterfaceID);
-    if (!proxy)
-    {
-        LogMsg("ProxyCallbackCommon: Rejecting DNS Query coming from InterfaceID %p", InterfaceID);
-        return;
-    }
-    
-    if ((unsigned)(end - (mDNSu8 *)msg) < sizeof(DNSMessageHeader))
-    {
-        debugf("ProxyCallbackCommon: DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
-        return;
-    }
-
-    // Read the integer parts which are in IETF byte-order (MSB first, LSB second)
-    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]);
-
-    QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
-    if (QR_OP != kDNSFlag0_QR_Query)
-    {
-        LogInfo("ProxyCallbackCommon: Not a query(%d) for pkt from %#a:%d", QR_OP, srcaddr, mDNSVal16(srcport));
-        SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_NotImpl);
-        return;
-    }
-    
-    if (msg->h.numQuestions != 1 || msg->h.numAnswers || msg->h.numAuthorities)
-    {
-        LogInfo("ProxyCallbackCommon: Malformed pkt from %#a:%d, Q:%d, An:%d, Au:%d", srcaddr, mDNSVal16(srcport),
-            msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities);
-        SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
-        return;
-    }
-    ptr = msg->data;
-    ptr = getQuestion(msg, ptr, end, InterfaceID, &q);
-    if (!ptr)
-    {
-        LogInfo("ProxyCallbackCommon: Question cannot be parsed for pkt from %#a:%d", srcaddr, mDNSVal16(srcport));
-        SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
-        return;
-    }
-    else
-    {
-        LogInfo("ProxyCallbackCommon: Question %##s (%s)", q.qname.c, DNSTypeName(q.qtype));
-    }
-    ptr = LocateOptRR(msg, end, 0);
-    if (ptr)
-    {
-        optRR = ptr;
-        ptr = skipResourceRecord(msg, ptr, end);
-        // Be liberal and ignore the EDNS0 option if we can't parse it properly
-        if (!ptr)
-        {
-            LogInfo("ProxyCallbackCommon: EDNS0 cannot be parsed for pkt from %#a:%d, ignoring", srcaddr, mDNSVal16(srcport));
-        }
-        else
-        {
-            optLen = (mDNSu32)(ptr - optRR);
-            LogInfo("ProxyCallbackCommon: EDNS0 opt length %u present in Question %##s (%s)", optLen, q.qname.c, DNSTypeName(q.qtype));
-        }
-    }
-    else
-    {
-        LogInfo("ProxyCallbackCommon: EDNS0 opt not present in Question %##s (%s), ptr %p", q.qname.c, DNSTypeName(q.qtype), ptr);
-    }
-        
-    qptr = IsDuplicateClient(srcaddr, srcport, msg->h.id, &q);
-    if (qptr)
-    {
-        LogInfo("ProxyCallbackCommon: Found a duplicate for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
-        return;
-    }
-    pc = (DNSProxyClient *) mDNSPlatformMemAllocateClear(sizeof(*pc));
-    if (!pc)
-    {
-        LogMsg("ProxyCallbackCommon: Memory failure for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
-        return;
-    }
-    if (!DNSProxyPrepareOmsg(NormalUDPDNSMessageData, pc))
-    {
-        LogMsg("ProxyCallbackCommon: NormalUDPDNSMessageData memory failure for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
-        FreeDNSProxyClient(pc);
-        return;
-    }
-    pc->proxy = proxy;
-    mrcs_retain(pc->proxy);
-    pc->addr = *srcaddr;
-    pc->port = srcport;
-    pc->msgid = msg->h.id;
-    pc->interfaceID = InterfaceID; // input interface 
-    pc->socket = socket;
-    pc->tcp = tcp;
-    pc->requestFlags = msg->h.flags;
-    pc->context = context;
-    AssignDomainName(&pc->qname, &q.qname);
-    if (optRR)
-    {
-        if (optLen < sizeof(OPTRecordFixedFields))
-        {
-            LogInfo("ProxyCallbackCommon: Invalid EDNS0 option for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
-        }
-        else
-        {
-            const OPTRecordFixedFields *const fields = (const OPTRecordFixedFields *)optRR;
-            pc->rcvBufSize = (mDNSu16)((fields->udpPayloadSize[0] << 8) | fields->udpPayloadSize[1]);
-            pc->optRR = (mDNSu8 *) mDNSPlatformMemAllocate(optLen);
-            if (!pc->optRR)
-            {
-                LogMsg("ProxyCallbackCommon: Memory failure for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
-                FreeDNSProxyClient(pc);
-                return;
-            }
-            mDNSPlatformMemCopy(pc->optRR, optRR, optLen);
-            pc->optLen = optLen;
-        }
-    }
-
-    const mDNSu32 outputIndex = mrcs_dns_proxy_get_output_interface(pc->proxy);
-    debugf("ProxyCallbackCommon: DNS Query forwarding to interface index %u", outputIndex);
-    mDNS_SetupQuestion(&pc->q, (mDNSInterfaceID)(unsigned long)outputIndex, &q.qname, q.qtype, ProxyClientCallback, pc);
-    pc->q.TimeoutQuestion = 1;
-    // Set ReturnIntermed so that we get the negative responses
-    pc->q.ReturnIntermed  = mDNStrue;
-    pc->q.ProxyQuestion   = mDNStrue;
-    pc->q.responseFlags   = zeroID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-    pc->qtype = pc->q.qtype;
-    const nw_nat64_prefix_t * const nat64_prefix = mrcs_dns_proxy_get_nat64_prefix(pc->proxy);
-    if (nat64_prefix)
-    {
-        if (pc->qtype == kDNSType_PTR)
-        {
-            struct in6_addr v6Addr;
-            struct in_addr v4Addr;
-            if (GetReverseIPv6Addr(&pc->qname, v6Addr.s6_addr) && nw_nat64_extract_v4(nat64_prefix, &v6Addr, &v4Addr))
-            {
-                const mDNSu8 *const a = (const mDNSu8 *)&v4Addr.s_addr;
-                char qnameStr[MAX_REVERSE_MAPPING_NAME_V4];
-                mDNS_snprintf(qnameStr, (mDNSu32)sizeof(qnameStr), "%u.%u.%u.%u.in-addr.arpa.", a[3], a[2], a[1], a[0]);
-                MakeDomainNameFromDNSNameString(&pc->q.qname, qnameStr);
-                pc->q.qnamehash = DomainNameHashValue(&pc->q.qname);
-                pc->dns64state = kDNSProxyDNS64State_PTRSynthesisTrying;
-            }
-        }
-        else if ((pc->qtype == kDNSType_AAAA) && mrcs_dns_proxy_forces_aaaa_synthesis(pc->proxy))
-        {
-            pc->dns64state = kDNSProxyDNS64State_AAAASynthesis;
-            pc->q.qtype    = kDNSType_A;
-        }
-    }
-#endif
-
-    while (*ppc)
-        ppc = &((*ppc)->next);
-    *ppc = pc;
-
-    mDNS_StartQuery(m, &pc->q);
-}
-
-mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-    const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
-{
-    LogInfo("ProxyUDPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
-    ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNSfalse, context);
-}
-
-mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-    const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
-{
-    LogInfo("ProxyTCPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
-    
-    // If the connection was closed from the other side or incoming packet does not match stored input interface list, locate the client
-    // state and free it.
-    if (((end - (mDNSu8 *)msg) == 0) || (!DNSProxyGetDNSProxyInstance(InterfaceID)))
-    {
-        DNSProxyClient **ppc = &DNSProxyClients;
-        DNSProxyClient **prevpc;
-
-        prevpc = ppc;
-        while (*ppc && (*ppc)->socket != socket)
-        {
-            prevpc = ppc;
-            ppc=&(*ppc)->next;
-        }
-        if (!*ppc)
-        {
-            mDNSPlatformDisposeProxyContext(socket);
-            LogMsg("ProxyTCPCallback: socket cannot be found");
-            return;
-        }
-        *prevpc = (*ppc)->next;
-        LogInfo("ProxyTCPCallback: free");
-        mDNSPlatformDisposeProxyContext(socket);
-        FreeDNSProxyClient(*ppc);
-        return;
-    }
-    ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNStrue, context);
-}
-
-mDNSlocal OSStatus DNSProxyStart(const mrcs_dns_proxy_t proxy)
-{
-    OSStatus err;
-    if (!gProxyManager)
-    {
-        gProxyManager = mrcs_dns_proxy_manager_create(&err);
-        require_noerr_quiet(err, exit);
-    }
-    const size_t previousCount = mrcs_dns_proxy_manager_get_count(gProxyManager);
-    err = mrcs_dns_proxy_manager_add_proxy(gProxyManager, proxy);
-    if (previousCount == 0)
-    {
-        if (mrcs_dns_proxy_manager_get_count(gProxyManager) > 0)
-        {
-            mDNSPlatformInitDNSProxySkts(ProxyUDPCallback, ProxyTCPCallback);
-        }
-    }
-
-exit:
-    return err;
-}
-
-mDNSlocal OSStatus DNSProxyStop(const mrcs_dns_proxy_t proxy)
-{
-    OSStatus err;
-    require_action_quiet(gProxyManager, exit, err = mStatus_BadStateErr);
-
-    const size_t previousCount = mrcs_dns_proxy_manager_get_count(gProxyManager);
-    err = mrcs_dns_proxy_manager_remove_proxy(gProxyManager, proxy);
-    require_noerr_quiet(err, exit);
-
-    if (previousCount > 0)
-    {
-        if (mrcs_dns_proxy_manager_get_count(gProxyManager) == 0)
-        {
-            mDNSPlatformCloseDNSProxySkts(&mDNSStorage);
-        }
-    }
-
-exit:
-    return err;
-}
-
-static mrcs_dns_proxy_t gLegacyProxy = mDNSNULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf, const mDNSu8 IPv6Prefix[16], int IPv6PrefixBitLen,
-                             mDNSBool forceAAAASynthesis)
-#else
-mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
-#endif
-{
-    if (gLegacyProxy)
-    {
-        return;
-    }
-    gLegacyProxy = mrcs_dns_proxy_create(NULL);
-    if (!gLegacyProxy)
-    {
-        return;
-    }
-    for (int i = 0; i < MaxIp; ++i)
-    {
-        mrcs_dns_proxy_add_input_interface(gLegacyProxy, IpIfArr[i]);
-    }
-    mrcs_dns_proxy_set_output_interface(gLegacyProxy, OpIf);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-    if (IPv6Prefix)
-    {
-        const OSStatus err = mrcs_dns_proxy_set_nat64_prefix(gLegacyProxy, IPv6Prefix, IPv6PrefixBitLen);
-        if (!err)
-        {
-            mrcs_dns_proxy_enable_force_aaaa_synthesis(gLegacyProxy, forceAAAASynthesis ? true : false);
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "DNSProxy using DNS64 IPv6 prefix: " PRI_IPv6_ADDR "/%d" PUB_S,
-                IPv6Prefix, IPv6PrefixBitLen, forceAAAASynthesis ? "" : " (force AAAA synthesis)");
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "DNSProxy not using invalid DNS64 IPv6 prefix: " PRI_IPv6_ADDR "/%d", IPv6Prefix, IPv6PrefixBitLen);
-        }
-    }
-#endif
-    DNSProxyStart(gLegacyProxy);
-}
-
-mDNSexport void DNSProxyTerminate(void)
-{
-    if (gLegacyProxy)
-    {
-        DNSProxyStop(gLegacyProxy);
-        mrcs_forget(&gLegacyProxy);
-    }
-}
-
-mDNSlocal OSStatus DNSProxyStartHandler(const mrcs_dns_proxy_t proxy)
-{
-    KQueueLock();
-    const OSStatus err = DNSProxyStart(proxy);
-    KQueueUnlock("DNSProxyStartHandler");
-    return err;
-}
-
-mDNSlocal OSStatus DNSProxyStopHandler(const mrcs_dns_proxy_t proxy)
-{
-    KQueueLock();
-    const OSStatus err = DNSProxyStop(proxy);
-    KQueueUnlock("DNSProxyStopHandler");
-    return err;
-}
-
-mDNSlocal char *DNSProxyGetState(void)
-{
-    char *state;
-    if (gProxyManager && (mrcs_dns_proxy_manager_get_count(gProxyManager) > 0))
-    {
-        state = mrcs_copy_description(gProxyManager);
-    }
-    else
-    {
-        state = mdns_strdup("‹No DNS Proxies›");
-    }
-    return state;
-}
-
-mDNSlocal char *DNSProxyGetStateHandler(void)
-{
-    KQueueLock();
-    char *state = DNSProxyGetState();
-    KQueueUnlock("DNSProxyGetStateHandler");
-    return state;
-}
-
-const struct mrcs_server_handlers_s kMRCSServerHandlers =
-{
-    .dns_proxy_start = DNSProxyStartHandler,
-    .dns_proxy_stop = DNSProxyStopHandler,
-    .dns_proxy_get_state = DNSProxyGetStateHandler
-};
-
-#else // UNICAST_DISABLED
-
-mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
-{
-    (void) socket;
-    (void) msg;
-    (void) end;
-    (void) srcaddr;
-    (void) srcport;
-    (void) dstaddr;
-    (void) dstport;
-    (void) InterfaceID;
-    (void) context;
-}
-
-mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
-{
-    (void) socket;
-    (void) msg;
-    (void) end;
-    (void) srcaddr;
-    (void) srcport;
-    (void) dstaddr;
-    (void) dstport;
-    (void) InterfaceID;
-    (void) context;
-}
-
-mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
-{
-    (void) IpIfArr;
-    (void) OpIf;
-}
-extern void DNSProxyTerminate(void)
-{
-}
-
-
-#endif // UNICAST_DISABLED
diff --git a/mDNSMacOSX/dnsproxy.h b/mDNSMacOSX/dnsproxy.h
deleted file mode 100644
index abecc4d..0000000
--- a/mDNSMacOSX/dnsproxy.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2011-2021 Apple 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.
- */
-
-#ifndef __DNS_PROXY_H
-#define __DNS_PROXY_H
-
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-
-extern void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-                             const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
-extern void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
-                             const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);                          
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PROXY_DNS64)
-extern void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf, const mDNSu8 IPv6Prefix[16], int IPv6PrefixLen,
-                         mDNSBool alwaysSynthesize);
-#else
-extern void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf);
-#endif
-extern void DNSProxyTerminate(void);
-
-extern const struct mrcs_server_handlers_s kMRCSServerHandlers;
-
-#endif // __DNS_PROXY_H
diff --git a/mDNSMacOSX/dnssd.c b/mDNSMacOSX/dnssd.c
deleted file mode 100644
index c5f2c23..0000000
--- a/mDNSMacOSX/dnssd.c
+++ /dev/null
@@ -1,2111 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "dnssd_private.h"
-
-#include "dnssd_object.h"
-#include "dnssd_xpc.h"
-#include "dnssd_svcb.h"
-
-#include <CoreUtils/CoreUtils.h>
-#include <os/object_private.h>
-#include <xpc/private.h>
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Kind Declarations
-
-#define DNSSD_STRUCT(NAME)	struct dnssd_ ## NAME ## _s
-#define DNSSD_TYPE(NAME)	dnssd_ ## NAME ## _t
-
-#define DNSSD_KIND_DECLARE(NAME)																\
-	static DNSSD_TYPE(NAME)																		\
-	_dnssd_ ## NAME ## _alloc(void);															\
-																								\
-	static char *																				\
-	_dnssd_ ## NAME ## _copy_description(DNSSD_TYPE(NAME) object, bool debug, bool privacy);	\
-																								\
-	static void																					\
-	_dnssd_ ## NAME ## _finalize(DNSSD_TYPE(NAME) object)
-
-// Note: The last check checks if the base's type is equal to that of the superkind. If it's not, then the pointer
-// comparison used as the argument to sizeof will cause a "comparison of distinct pointer types" warning, so long as
-// the warning hasn't been disabled.
-
-#define DNSSD_BASE_CHECK(NAME, SUPER)																	\
-	check_compile_time(offsetof(DNSSD_STRUCT(NAME), base) == 0);										\
-	check_compile_time(sizeof_field(DNSSD_STRUCT(NAME), base) == sizeof(DNSSD_STRUCT(SUPER)));			\
-	extern int _dnssd_base_type_check[sizeof(&(((DNSSD_TYPE(NAME))0)->base) == ((DNSSD_TYPE(SUPER))0))]
-
-#define DNSSD_KIND_DEFINE(NAME, SUPER) 											\
-	static const struct dnssd_kind_s _dnssd_ ## NAME ## _kind = {				\
-		&_dnssd_ ## SUPER ## _kind,												\
-		# NAME,																	\
-		_dnssd_ ## NAME ## _copy_description,									\
-		_dnssd_ ## NAME ## _finalize,											\
-	};																			\
-																				\
-	static DNSSD_TYPE(NAME)														\
-	_dnssd_ ## NAME ## _alloc(void)												\
-	{																			\
-		DNSSD_TYPE(NAME) obj = dnssd_object_ ## NAME ## _alloc(sizeof(*obj));	\
-		require_quiet(obj, exit);												\
-																				\
-		const dnssd_object_t base = (dnssd_object_t)obj;						\
-		base->kind = &_dnssd_ ## NAME ## _kind;									\
-																				\
-	exit:																		\
-		return obj;																\
-	}																			\
-	DNSSD_BASE_CHECK(NAME, SUPER)
-
-DNSSD_KIND_DECLARE(getaddrinfo);
-DNSSD_KIND_DECLARE(getaddrinfo_result);
-DNSSD_KIND_DECLARE(cname_array);
-
-typedef char *	(*dnssd_copy_description_f)(dnssd_any_t object, bool debug, bool privacy);
-typedef void	(*dnssd_finalize_f)(dnssd_any_t object);
-
-typedef const struct dnssd_kind_s *	dnssd_kind_t;
-struct dnssd_kind_s {
-	dnssd_kind_t				superkind;			// This kind's superkind.
-	const char *				name;				// Name of this kind.
-	dnssd_copy_description_f	copy_description;	// Creates a textual description of object.
-	dnssd_finalize_f			finalize;			// Releases object's resources right before the object is freed.
-};
-
-//======================================================================================================================
-// MARK: - Object Kind Definition
-
-struct dnssd_object_s {
-	_OS_OBJECT_HEADER(const void * __ptrauth_objc_isa_pointer _os_obj_isa, _os_obj_refcnt, _os_obj_xref_cnt);
-	dnssd_kind_t	kind;	// Pointer to an object's kind.
-};
-
-static const struct dnssd_kind_s _dnssd_object_kind = {
-	NULL,		// No superkind.
-	"object",
-	NULL,		// No copy_description method.
-	NULL,		// No finalize method.
-};
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Kind Definition
-
-typedef enum {
-	dnssd_getaddrinfo_state_nascent		= 0,
-	dnssd_getaddrinfo_state_starting	= 1,
-	dnssd_getaddrinfo_state_started		= 2,
-	dnssd_getaddrinfo_state_failed		= 3,
-	dnssd_getaddrinfo_state_invalidated	= 4,
-} dnssd_getaddrinfo_state_t;
-
-struct dnssd_getaddrinfo_s {
-	struct dnssd_object_s				base;				// Object base.
-	dnssd_getaddrinfo_t					next;				// Next getaddrinfo object in list.
-	uint64_t							command_id;			// Command ID.
-	dispatch_queue_t					user_queue;			// User's dispatch queue for result and event handlers.
-	dispatch_queue_t					mutex_queue;		// Mutex for accessing result_list from different queues.
-	xpc_object_t						params;				// Parameters dictionary for getaddrinfo command.
-	xpc_object_t						hostname;			// Reference to hostname from parameters dictionary.
-	dnssd_cname_array_t					cnames_a;			// Array of hostname's canonical names for A results.
-	dnssd_cname_array_t					cnames_aaaa;		// Array of hostname's canonical names for AAAA results.
-	dispatch_source_t					event_source;		// Data source for triggering result and event handlers.
-	dnssd_getaddrinfo_result_t			result_list;		// List of getaddrinfo results.
-	dnssd_getaddrinfo_result_handler_t	result_handler;		// User's result handler.
-	dnssd_event_handler_t				event_handler;		// User's event handler.
-	mdns_xpc_string_t					tracker_hostname;	// The last result's tracker hostname. Used for deduping.
-	mdns_xpc_string_t					tracker_owner;		// The last result's tracker owner. Used for deduping.
-	dnssd_getaddrinfo_state_t			state;				// Internal state.
-	OSStatus							error;				// Pending error.
-	bool								user_activated;		// True if the object has been activated by user.
-};
-
-DNSSD_KIND_DEFINE(getaddrinfo, object);
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Result Kind Definition
-
-struct dnssd_getaddrinfo_result_s {
-	struct dnssd_object_s				base;				// Object base.
-	dnssd_getaddrinfo_result_t			next;				// Next getaddrinfo result in list.
-	sockaddr_ip							addr;				// IPv4 or IPv6 address of hostname.
-	xpc_object_t						hostname;			// Requested hostname to resolve.
-	xpc_object_t						actual_hostname;	// The actual/canonical hostname of the requested hostname.
-	dnssd_cname_array_t					cnames;				// Array of hostname's canonical names.
-	xpc_object_t						auth_tag;			// Authentication tag.
-	xpc_object_t						provider_name;		// Provider name.
-	xpc_object_t						ech_config;			// SVCB ECH config.
-	xpc_object_t						address_hints;		// SVCB address hints.
-	xpc_object_t						doh_uri;			// SVCB DoH URI.
-	xpc_object_t						doh_path;			// SVCB DoH Path.
-	xpc_object_t						odoh_config;		// SVCB Oblivious DoH config.
-	xpc_object_t						alpn_values;		// SVCB ALPN values.
-	xpc_object_t						service_name;		// SVCB name.
-	mdns_xpc_string_t					tracker_hostname;	// Tracker hostname [1].
-	mdns_xpc_string_t					tracker_owner;		// Tracker owner [2].
-	xpc_object_t						validation_data;	// Validation data.
-	uint16_t							port;				// SVCB port.
-	uint16_t							priority;			// SVCB priority.
-	uint32_t							if_index;			// Interface index to which the result pertains.
-	dnssd_getaddrinfo_result_type_t		type;				// Type of getaddrinfo result.
-	dnssd_getaddrinfo_result_protocol_t	protocol;			// Protocol used for getaddrinfo result.
-	dnssd_negative_reason_t				negative_reason;	// The reason code for a negative result.
-	bool								is_from_cache;		// True if the result was an answer from the cache.
-	bool								valid_svcb;			// True if SVCB info is valid.
-	bool								tracker_approved;	// True if the tracker is an approved domain for the app.
-};
-
-// Notes:
-// 1. If non-NULL, identifies the known tracker domain name, if any, that appears earliest in the requested hostname's
-//    CNAME chain.
-// 2. If non-NULL, identifies the entity (usually a company) that owns the tracker hostname.
-
-DNSSD_KIND_DEFINE(getaddrinfo_result, object);
-
-//======================================================================================================================
-// MARK: - CName Array Kind Definition
-
-struct dnssd_cname_array_s {
-	struct dnssd_object_s	base;		// Object base.
-	xpc_object_t			xpc_array;	// Underlying array of cnames as strings. Important: Must not be modified.
-};
-
-DNSSD_KIND_DEFINE(cname_array, object);
-
-//======================================================================================================================
-// MARK: - Constants
-
-#define DNSSD_EVENT_HAVE_RESULTS	(1U << 0)	// Results are available.
-#define DNSSD_EVENT_REMOVE_ALL		(1U << 1)	// Previously delivered results are no longer valid.
-#define DNSSD_EVENT_ERROR			(1U << 2)	// An error was encountered.
-
-// Strings for redacted description items.
-
-#define DNSSD_REDACTED_HOSTNAME_STR		"<redacted hostname>"
-#define DNSSD_REDACTED_IPv4_ADDRESS_STR	"<redacted IPv4 address>"
-#define DNSSD_REDACTED_IPv6_ADDRESS_STR	"<redacted IPv6 address>"
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static dispatch_queue_t
-_dnssd_client_queue(void);
-
-static xpc_connection_t
-_dnssd_client_connection(void);
-
-static uint64_t
-_dnssd_client_get_new_id(void);
-
-static void
-_dnssd_client_activate_getaddrinfo_async(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_client_register_getaddrinfo(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_client_deregister_getaddrinfo(dnssd_getaddrinfo_t gai);
-
-static OSStatus
-_dnssd_client_send_getaddrinfo_command(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_client_fail_getaddrinfo(dnssd_getaddrinfo_t gai, OSStatus error);
-
-static void
-_dnssd_getaddrinfo_append_results(dnssd_getaddrinfo_t gai, dnssd_getaddrinfo_result_t result_list);
-
-static void
-_dnssd_getaddrinfo_remove_all_results(dnssd_getaddrinfo_t gai);
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_take_results(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_getaddrinfo_post_error_event(dnssd_getaddrinfo_t gai, OSStatus error);
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_create_result_from_dictionary(dnssd_getaddrinfo_t gai, xpc_object_t result_dict,
-	OSStatus *out_error);
-
-static dnssd_cname_array_t
-_dnssd_cname_array_create(xpc_object_t xpc_array, OSStatus *out_error);
-
-static dnssd_cname_array_t
-_dnssd_get_empty_cname_array(void);
-
-static DNSServiceErrorType
-_dnssd_osstatus_to_dns_service_error(OSStatus status);
-
-static int
-_dnssd_snprintf(char **dst, const char *end, const char *format, ...);
-
-#if !defined(dnssd_release_null_safe)
-	#define dnssd_release_null_safe(X)	\
-		do {							\
-			if (X) {					\
-				dnssd_release(X);		\
-			}							\
-		} while(0)
-#endif
-
-#if !defined(dnssd_forget)
-	#define dnssd_forget(X)	ForgetCustom(X, dnssd_release)
-#endif
-
-//======================================================================================================================
-// MARK: - Object Public Methods
-
-void
-dnssd_retain(const dnssd_any_t any)
-{
-	os_retain(any.object);
-}
-
-//======================================================================================================================
-
-void
-dnssd_release(const dnssd_any_t any)
-{
-	os_release(any.object);
-}
-
-//======================================================================================================================
-
-char *
-dnssd_copy_description(dnssd_any_t object)
-{
-	return dnssd_object_copy_description(object, false, false);
-}
-
-//======================================================================================================================
-// MARK: - Object Private Methods
-
-char *
-dnssd_object_copy_description(const dnssd_any_t any, const bool debug, const bool privacy)
-{
-	const dnssd_object_t me = any.object;
-	for (dnssd_kind_t kind = me->kind; kind; kind = kind->superkind) {
-		if (kind->copy_description) {
-			char *desc = kind->copy_description(me, debug, privacy);
-			return desc;
-		}
-	}
-	return NULL;
-}
-
-//======================================================================================================================
-
-void
-dnssd_object_finalize(const dnssd_any_t any)
-{
-	const dnssd_object_t me = any.object;
-	for (dnssd_kind_t kind = me->kind; kind; kind = kind->superkind) {
-		if (kind->finalize) {
-			kind->finalize(me);
-		}
-	}
-}
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Public Methods
-
-dnssd_getaddrinfo_t
-dnssd_getaddrinfo_create(void)
-{
-	dnssd_getaddrinfo_t	gai = NULL;
-	dnssd_getaddrinfo_t	obj = _dnssd_getaddrinfo_alloc();
-	require_quiet(obj, exit);
-
-	obj->params = xpc_dictionary_create(NULL, NULL, 0);
-	require_quiet(obj->params, exit);
-
-	obj->mutex_queue = dispatch_queue_create("com.apple.dnssd.getaddrinfo.mutex", DISPATCH_QUEUE_SERIAL);
-	require_quiet(obj->mutex_queue, exit);
-
-	gai = obj;
-	obj = NULL;
-
-exit:
-	dnssd_release_null_safe(obj);
-	return gai;
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_queue(dnssd_getaddrinfo_t me, dispatch_queue_t queue)
-{
-	if (!me->user_activated) {
-		dispatch_retain(queue);
-		dispatch_release_null_safe(me->user_queue);
-		me->user_queue = queue;
-	} else if (!me->user_queue) {
-		me->user_queue = queue;
-		dispatch_retain(me->user_queue);
-		_dnssd_client_activate_getaddrinfo_async(me);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_flags(dnssd_getaddrinfo_t me, DNSServiceFlags flags)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_flags(me->params, flags);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_account_id(dnssd_getaddrinfo_t me, const char * account_id)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_account_id(me->params, account_id);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_hostname(dnssd_getaddrinfo_t me, const char *hostname)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_hostname(me->params, hostname);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_interface_index(dnssd_getaddrinfo_t me, uint32_t interface_index)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_interface_index(me->params, interface_index);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_protocols(dnssd_getaddrinfo_t me, DNSServiceProtocol protocols)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_protocols(me->params, protocols);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_service_scheme(dnssd_getaddrinfo_t me, const char *service_scheme)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_service_scheme(me->params, service_scheme);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_delegate_pid(dnssd_getaddrinfo_t me, pid_t pid)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_delegate_pid(me->params, pid);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_delegate_uuid(dnssd_getaddrinfo_t me, uuid_t uuid)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_delegate_uuid(me->params, uuid);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_delegate_audit_token(dnssd_getaddrinfo_t me, audit_token_t audit_token)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_delegate_audit_token(me->params, &audit_token);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_result_handler(dnssd_getaddrinfo_t me, dnssd_getaddrinfo_result_handler_t handler)
-{
-	dnssd_getaddrinfo_result_handler_t const new_handler = handler ? Block_copy(handler) : NULL;
-	BlockForget(&me->result_handler);
-	me->result_handler = new_handler;
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_event_handler(dnssd_getaddrinfo_t me, dnssd_event_handler_t handler)
-{
-	dnssd_event_handler_t const new_handler = handler ? Block_copy(handler) : NULL;
-	BlockForget(&me->event_handler);
-	me->event_handler = new_handler;
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_need_authenticated_results(dnssd_getaddrinfo_t me, bool need)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_need_authentication_tags(me->params, need);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_need_encrypted_query(dnssd_getaddrinfo_t me, bool need, _Nullable xpc_object_t fallback_config)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_set_need_encrypted_query(me->params, need, fallback_config);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_use_failover(const dnssd_getaddrinfo_t me, const bool use_failover)
-{
-	require_return(!me->user_activated);
-	dnssd_xpc_parameters_set_use_failover(me->params, use_failover);
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_log_privacy_level(const dnssd_getaddrinfo_t me, const dnssd_log_privacy_level_t level)
-{
-	require_return(!me->user_activated);
-	dnssd_xpc_parameters_set_log_privacy_level(me->params, level);
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_add_resolver_uuid(dnssd_getaddrinfo_t me, uuid_t _Nonnull uuid)
-{
-	if (!me->user_activated) {
-		dnssd_xpc_parameters_add_resolver_uuid(me->params, uuid);
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_set_validation_data(const dnssd_getaddrinfo_t me, const uint8_t * const data_ptr,
-	const size_t data_len)
-{
-	require_return(!me->user_activated);
-	dnssd_xpc_parameters_set_validation_data(me->params, data_ptr, data_len);
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_activate(dnssd_getaddrinfo_t me)
-{
-	if (!me->user_activated) {
-		if (me->user_queue) {
-			_dnssd_client_activate_getaddrinfo_async(me);
-		}
-		me->user_activated = true;
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_invalidate_getaddrinfo(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_getaddrinfo_invalidate(dnssd_getaddrinfo_t me);
-
-void
-dnssd_getaddrinfo_invalidate(dnssd_getaddrinfo_t me)
-{
-	dnssd_retain(me);
-	dispatch_async(_dnssd_client_queue(),
-	^{
-		_dnssd_client_invalidate_getaddrinfo(me);
-		dnssd_release(me);
-	});
-}
-
-static void
-_dnssd_client_invalidate_getaddrinfo(dnssd_getaddrinfo_t gai)
-{
-	require_quiet(gai->state != dnssd_getaddrinfo_state_invalidated, exit);
-
-	_dnssd_client_deregister_getaddrinfo(gai);
-	if ((gai->state == dnssd_getaddrinfo_state_starting) || (gai->state == dnssd_getaddrinfo_state_started)) {
-		xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
-		if (msg) {
-			dnssd_xpc_message_set_id(msg, gai->command_id);
-			dnssd_xpc_message_set_command(msg, DNSSD_COMMAND_STOP);
-			xpc_connection_send_message_with_reply(_dnssd_client_connection(), msg, _dnssd_client_queue(),
-			^(xpc_object_t reply)
-			{
-				(void)reply;
-			});
-			xpc_forget(&msg);
-		}
-	}
-	_dnssd_getaddrinfo_invalidate(gai);
-	gai->state = dnssd_getaddrinfo_state_invalidated;
-
-exit:
-	return;
-}
-
-static void
-_dnssd_getaddrinfo_invalidate(dnssd_getaddrinfo_t me)
-{
-	dispatch_source_forget(&me->event_source);
-	_dnssd_getaddrinfo_remove_all_results(me);
-
-	if (me->user_queue) {
-		dnssd_retain(me);
-		dispatch_async(me->user_queue,
-		^{
-			if (me->event_handler) {
-				me->event_handler(dnssd_event_invalidated, kDNSServiceErr_NoError);
-			}
-			dnssd_release(me);
-		});
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_prohibit_encrypted_dns(const dnssd_getaddrinfo_t me, const bool prohibit)
-{
-	require_return(!me->user_activated);
-	dnssd_xpc_parameters_set_prohibit_encrypted_dns(me->params, prohibit);
-}
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Private Methods
-
-static char *
-_dnssd_getaddrinfo_copy_description(dnssd_getaddrinfo_t me, const bool debug, const bool privacy)
-{
-	const char *hostname_str;
-	if (me->hostname) {
-		hostname_str = xpc_string_get_string_ptr(me->hostname);
-		if (privacy && hostname_str) {
-			hostname_str = DNSSD_REDACTED_HOSTNAME_STR;
-		}
-	} else {
-		hostname_str = NULL;
-	}
-	char *desc = NULL;
-	char *buf_ptr = NULL;
-	size_t buf_len = 0;
-	for (;;)
-	{
-		int n;
-		char * dst = buf_ptr;
-		char * const end = &buf_ptr[buf_len];
-		size_t desc_len = 0;
-		if (debug) {
-			n = _dnssd_snprintf(&dst, end, "dnssd_%s (%p): ", me->base.kind->name, (void *)me);
-			require_quiet(n >= 0, exit);
-			desc_len += (size_t)n;
-		}
-		n = _dnssd_snprintf(&dst, end, "hostname: %s", hostname_str ? hostname_str : "<NO HOSTNAME>");
-		require_quiet(n >= 0, exit);
-		desc_len += (size_t)n;
-
-		if (!buf_ptr) {
-			buf_len = desc_len + 1;
-			buf_ptr = (char *)mdns_malloc(buf_len);
-			require_quiet(buf_ptr, exit);
-			buf_ptr[0] = '\0';
-		} else {
-			break;
-		}
-	}
-	desc = buf_ptr;
-	buf_ptr = NULL;
-
-exit:
-	FreeNullSafe(buf_ptr);
-	return desc;
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_getaddrinfo_finalize(dnssd_getaddrinfo_t me)
-{
-	dispatch_forget(&me->user_queue);
-	dispatch_forget(&me->mutex_queue);
-	xpc_forget(&me->params);
-	xpc_forget(&me->hostname);
-	dnssd_forget(&me->cnames_a);
-	dnssd_forget(&me->cnames_aaaa);
-	BlockForget(&me->result_handler);
-	BlockForget(&me->event_handler);
-	mdns_xpc_string_forget(&me->tracker_hostname);
-	mdns_xpc_string_forget(&me->tracker_owner);
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_getaddrinfo_append_results(dnssd_getaddrinfo_t me, dnssd_getaddrinfo_result_t result_list)
-{
-	dispatch_sync(me->mutex_queue,
-	^{
-		dnssd_getaddrinfo_result_t *ptr = &me->result_list;
-		while (*ptr) {
-			ptr = &(*ptr)->next;
-		}
-		*ptr = result_list;
-	});
-	dispatch_source_merge_data(me->event_source, DNSSD_EVENT_HAVE_RESULTS);
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_getaddrinfo_remove_all_results(dnssd_getaddrinfo_t me)
-{
-	dnssd_forget(&me->cnames_a);
-	dnssd_forget(&me->cnames_aaaa);
-	dnssd_getaddrinfo_result_t result_list = _dnssd_getaddrinfo_take_results(me);
-	if (me->event_source) {
-		dispatch_source_merge_data(me->event_source, DNSSD_EVENT_REMOVE_ALL);
-	}
-
-	dnssd_getaddrinfo_result_t result;
-	while ((result = result_list) != NULL) {
-		result_list = result->next;
-		dnssd_release(result);
-	}
-}
-
-//======================================================================================================================
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_take_results(dnssd_getaddrinfo_t me)
-{
-	__block dnssd_getaddrinfo_result_t list;
-	dispatch_sync(me->mutex_queue,
-	^{
-		list = me->result_list;
-		me->result_list = NULL;
-	});
-	return list;
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_getaddrinfo_post_error_event(dnssd_getaddrinfo_t me, OSStatus error)
-{
-	dispatch_sync(me->mutex_queue,
-	^{
-		me->error = error;
-	});
-	dispatch_source_merge_data(me->event_source, DNSSD_EVENT_ERROR);
-}
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Result Public Methods
-
-dnssd_getaddrinfo_result_type_t
-dnssd_getaddrinfo_result_get_type(dnssd_getaddrinfo_result_t me)
-{
-	return me->type;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_actual_hostname(dnssd_getaddrinfo_result_t me)
-{
-	const char * const tmp = xpc_string_get_string_ptr(me->actual_hostname);
-	return tmp;
-}
-
-//======================================================================================================================
-
-const struct sockaddr *
-dnssd_getaddrinfo_result_get_address(dnssd_getaddrinfo_result_t me)
-{
-	return &me->addr.sa;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_hostname(dnssd_getaddrinfo_result_t me)
-{
-	const char * const tmp = xpc_string_get_string_ptr(me->hostname);
-	return tmp;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_doh_uri(dnssd_getaddrinfo_result_t me)
-{
-	return xpc_string_get_string_ptr(me->doh_uri);
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_doh_path(dnssd_getaddrinfo_result_t me)
-{
-	return xpc_string_get_string_ptr(me->doh_path);
-}
-
-//======================================================================================================================
-
-uint16_t
-dnssd_getaddrinfo_result_get_service_port(dnssd_getaddrinfo_result_t me)
-{
-	return me->port;
-}
-
-//======================================================================================================================
-
-uint16_t
-dnssd_getaddrinfo_result_get_service_priority(dnssd_getaddrinfo_result_t me)
-{
-	return me->priority;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_service_name(dnssd_getaddrinfo_result_t me)
-{
-	return xpc_string_get_string_ptr(me->service_name);
-}
-
-//======================================================================================================================
-
-bool
-dnssd_getaddrinfo_result_service_is_valid(dnssd_getaddrinfo_result_t me)
-{
-	return me->valid_svcb;
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_result_enumerate_alpn_values(dnssd_getaddrinfo_result_t me,
-											   DNSSD_NOESCAPE dnssd_getaddrinfo_enumerate_alpn_values_block_t enumerator)
-{
-	if (me->alpn_values != NULL) {
-		xpc_array_apply(me->alpn_values, ^bool(__unused size_t index, xpc_object_t _Nonnull value) {
-			const char *string = xpc_string_get_string_ptr(value);
-			return enumerator(string);
-		});
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_getaddrinfo_result_enumerate_service_address_hints(dnssd_getaddrinfo_result_t me,
-														 DNSSD_NOESCAPE dnssd_getaddrinfo_enumerate_addresses_block_t enumerator)
-{
-	if (me->address_hints != NULL) {
-		xpc_array_apply(me->address_hints, ^bool(__unused size_t index, xpc_object_t _Nonnull value) {
-			const void *bytes = xpc_data_get_bytes_ptr(value);
-			return enumerator((const struct sockaddr *)bytes);
-		});
-	}
-}
-
-//======================================================================================================================
-
-const void *
-dnssd_getaddrinfo_result_get_ech_config(dnssd_getaddrinfo_result_t me, size_t *out_length)
-{
-	const void *	ech_ptr;
-	size_t			ech_len;
-
-	if (me->ech_config) {
-		ech_ptr = xpc_data_get_bytes_ptr(me->ech_config);
-		ech_len = xpc_data_get_length(me->ech_config);
-	} else {
-		ech_ptr = NULL;
-		ech_len = 0;
-	}
-	if (out_length) {
-		*out_length = ech_len;
-	}
-	return ech_ptr;
-}
-
-//======================================================================================================================
-
-const void *
-dnssd_getaddrinfo_result_get_odoh_config(dnssd_getaddrinfo_result_t me, size_t *out_length)
-{
-	const void *	odoh_ptr;
-	size_t			odoh_len;
-
-	if (me->odoh_config) {
-		odoh_ptr = xpc_data_get_bytes_ptr(me->odoh_config);
-		odoh_len = xpc_data_get_length(me->odoh_config);
-	} else {
-		odoh_ptr = NULL;
-		odoh_len = 0;
-	}
-	if (out_length) {
-		*out_length = odoh_len;
-	}
-	return odoh_ptr;
-}
-
-//======================================================================================================================
-
-uint32_t
-dnssd_getaddrinfo_result_get_interface_index(dnssd_getaddrinfo_result_t me)
-{
-	return me->if_index;
-}
-
-//======================================================================================================================
-
-const void *
-dnssd_getaddrinfo_result_get_authentication_tag(dnssd_getaddrinfo_result_t me, size_t *out_length)
-{
-	const void *	auth_tag_ptr;
-	size_t			auth_tag_len;
-
-	if (me->auth_tag) {
-		auth_tag_ptr = xpc_data_get_bytes_ptr(me->auth_tag);
-		auth_tag_len = xpc_data_get_length(me->auth_tag);
-	} else {
-		auth_tag_ptr = NULL;
-		auth_tag_len = 0;
-	}
-	if (out_length) {
-		*out_length = auth_tag_len;
-	}
-	return auth_tag_ptr;
-}
-
-//======================================================================================================================
-
-dnssd_getaddrinfo_result_protocol_t
-dnssd_getaddrinfo_result_get_protocol(dnssd_getaddrinfo_result_t me)
-{
-	return me->protocol;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_provider_name(dnssd_getaddrinfo_result_t me)
-{
-	return xpc_string_get_string_ptr(me->provider_name);
-}
-
-//======================================================================================================================
-
-dnssd_cname_array_t
-dnssd_getaddrinfo_result_get_cnames(const dnssd_getaddrinfo_result_t me)
-{
-	return (me->cnames ? me->cnames : _dnssd_get_empty_cname_array());
-}
-
-//======================================================================================================================
-
-bool
-dnssd_getaddrinfo_result_is_from_cache(const dnssd_getaddrinfo_result_t me)
-{
-	return me->is_from_cache;
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_tracker_hostname(const dnssd_getaddrinfo_result_t me)
-{
-	return mdns_xpc_string_get_string_ptr(me->tracker_hostname);
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_getaddrinfo_result_get_tracker_owner(const dnssd_getaddrinfo_result_t me)
-{
-	return mdns_xpc_string_get_string_ptr(me->tracker_owner);
-}
-
-//======================================================================================================================
-
-bool
-dnssd_getaddrinfo_result_get_tracker_is_approved(const dnssd_getaddrinfo_result_t me)
-{
-	return me->tracker_approved;
-}
-
-//======================================================================================================================
-
-dnssd_negative_reason_t
-dnssd_getaddrinfo_result_get_negative_reason(const dnssd_getaddrinfo_result_t me)
-{
-	return me->negative_reason;
-}
-
-//======================================================================================================================
-
-const uint8_t *
-dnssd_getaddrinfo_result_get_validation_data(const dnssd_getaddrinfo_result_t me, size_t * const out_length)
-{
-	const uint8_t *data_ptr;
-	size_t data_len;
-	if (me->validation_data) {
-		data_ptr = xpc_data_get_bytes_ptr(me->validation_data);
-		data_len = xpc_data_get_length(me->validation_data);
-	} else {
-		data_ptr = NULL;
-		data_len = 0;
-	}
-	if (out_length) {
-		*out_length = data_len;
-	}
-	return data_ptr;
-}
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Result Private Methods
-
-static char *
-_dnssd_getaddrinfo_result_copy_description(dnssd_getaddrinfo_result_t me, const bool debug, const bool privacy)
-{
-	const char *hostname;
-	if (me->hostname) {
-		hostname = xpc_string_get_string_ptr(me->hostname);
-		if (privacy && hostname) {
-			hostname = DNSSD_REDACTED_HOSTNAME_STR;
-		}
-	} else {
-		hostname = NULL;
-	}
-	char addr_buf[INET6_ADDRSTRLEN + 1 + Max(IF_NAMESIZE, 10) + 1];
-	const char *addr_str;
-	if (me->addr.sa.sa_family == AF_INET) {
-		if (privacy) {
-			addr_str = DNSSD_REDACTED_IPv4_ADDRESS_STR;
-		} else {
-			check_compile_time_code(sizeof(addr_buf) >= INET_ADDRSTRLEN);
-			addr_str = inet_ntop(AF_INET, &me->addr.v4.sin_addr.s_addr, addr_buf, (socklen_t)sizeof(addr_buf));
-		}
-	} else if (me->addr.sa.sa_family == AF_INET6) {
-		if (privacy) {
-			addr_str = DNSSD_REDACTED_IPv6_ADDRESS_STR;
-		} else {
-			const struct sockaddr_in6 * const sin6 = &me->addr.v6;
-			check_compile_time_code(sizeof(addr_buf) >= INET6_ADDRSTRLEN);
-			addr_str = inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, addr_buf, (socklen_t)sizeof(addr_buf));
-			if (addr_str && (sin6->sin6_scope_id > 0)) {
-				char * const		dst = &addr_buf[strlen(addr_buf)];
-				const char * const	end = &addr_buf[countof(addr_buf)];
-				char ifname[IF_NAMESIZE + 1];
-				if (if_indextoname(sin6->sin6_scope_id, ifname)) {
-					snprintf(dst, (size_t)(end - dst), "%%%s", ifname);
-				} else {
-					snprintf(dst, (size_t)(end - dst), "%%%u", sin6->sin6_scope_id);
-				}
-			}
-		}
-	} else {
-		addr_str = NULL;
-	}
-	char *desc = NULL;
-	char *buf_ptr = NULL;
-	size_t buf_len = 0;
-	for (;;)
-	{
-		char *dst = buf_ptr;
-		char * const end = &buf_ptr[buf_len];
-		size_t desc_len = 0;
-		int n;
-		if (debug) {
-			n = _dnssd_snprintf(&dst, end, "dnssd_%s (%p): ", me->base.kind->name, (void *)me);
-			require_quiet(n >= 0, exit);
-			desc_len += (size_t)n;
-		}
-		n = _dnssd_snprintf(&dst, end, "hostname: %s, address: %s, type: %s, ifindex: %lu",
-			hostname ? hostname : "<NO HOSTNAME>", addr_str ? addr_str : "<NO ADDR>",
-			dnssd_getaddrinfo_result_type_to_string(me->type), (unsigned long)me->if_index);
-		require_quiet(n >= 0, exit);
-		desc_len += (size_t)n;
-		if (!buf_ptr) {
-			buf_len = desc_len + 1;
-			buf_ptr = (char *)mdns_malloc(buf_len);
-			require_quiet(buf_ptr, exit);
-			buf_ptr[0] = '\0';
-		} else {
-			break;
-		}
-	}
-	desc = buf_ptr;
-	buf_ptr	= NULL;
-
-exit:
-	FreeNullSafe(buf_ptr);
-	return desc;
-}
-
-//======================================================================================================================
-
-void
-_dnssd_getaddrinfo_result_finalize(dnssd_getaddrinfo_result_t me)
-{
-	xpc_forget(&me->hostname);
-	xpc_forget(&me->actual_hostname);
-	dnssd_forget(&me->cnames);
-	xpc_forget(&me->auth_tag);
-	xpc_forget(&me->provider_name);
-	xpc_forget(&me->doh_uri);
-	xpc_forget(&me->doh_path);
-	xpc_forget(&me->odoh_config);
-	xpc_forget(&me->alpn_values);
-	xpc_forget(&me->service_name);
-	mdns_xpc_string_forget(&me->tracker_hostname);
-	mdns_xpc_string_forget(&me->tracker_owner);
-	xpc_forget(&me->ech_config);
-	xpc_forget(&me->address_hints);
-	xpc_forget(&me->validation_data);
-}
-
-//======================================================================================================================
-
-static OSStatus
-_dnssd_getaddrinfo_set_cnames(const dnssd_getaddrinfo_t me, const int record_type, const xpc_object_t xpc_cname_array)
-{
-	dnssd_cname_array_t *cnames_ptr;
-	switch (record_type) {
-		case kDNSServiceType_A:
-			cnames_ptr = &me->cnames_a;
-			break;
-
-		case kDNSServiceType_AAAA:
-			cnames_ptr = &me->cnames_aaaa;
-			break;
-
-		default:
-			cnames_ptr = NULL;
-			break;
-	}
-	OSStatus err;
-	if (cnames_ptr) {
-		dnssd_forget(cnames_ptr);
-		*cnames_ptr = _dnssd_cname_array_create(xpc_cname_array, &err);
-		require_noerr_quiet(err, exit);
-	}
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static xpc_object_t
-_dnssd_getaddrinfo_get_cname_array(const dnssd_getaddrinfo_t me, const int type)
-{
-	switch (type) {
-		case kDNSServiceType_A:
-			return me->cnames_a;
-
-		case kDNSServiceType_AAAA:
-			return me->cnames_aaaa;
-
-		default:
-			return NULL;
-	}
-}
-
-//======================================================================================================================
-// MARK: - dnssd_cname_array Public Methods
-
-size_t
-dnssd_cname_array_get_count(const dnssd_cname_array_t me)
-{
-	return (me->xpc_array ? xpc_array_get_count(me->xpc_array) : 0);
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_cname_array_get_cname(const dnssd_cname_array_t me, const size_t index)
-{
-	return (me->xpc_array ? xpc_array_get_string(me->xpc_array, index) : NULL);
-}
-
-//======================================================================================================================
-// MARK: - dnssd_cname_array Private Methods
-
-static dnssd_cname_array_t
-_dnssd_cname_array_create(const xpc_object_t xpc_array, OSStatus * const out_error)
-{
-	OSStatus err;
-	dnssd_cname_array_t array = NULL;
-	dnssd_cname_array_t obj = _dnssd_cname_array_alloc();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	if (xpc_array) {
-		obj->xpc_array = xpc_copy(xpc_array);
-		require_action_quiet(obj->xpc_array, exit, err = kNoResourcesErr);
-	}
-	array = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	dnssd_release_null_safe(obj);
-	return array;
-}
-
-//======================================================================================================================
-
-static char *
-_dnssd_cname_array_copy_description(const dnssd_cname_array_t me, const bool debug, const bool privacy)
-{
-	char *desc = NULL;
-	char *buf_ptr = NULL;
-	size_t buf_len = 0;
-	for (;;)
-	{
-		__block int n;
-		__block char *dst = buf_ptr;
-		const char * const end = &buf_ptr[buf_len];
-		__block size_t desc_len = 0;
-		if (debug) {
-			n = _dnssd_snprintf(&dst, end, "dnssd_%s (%p): ", me->base.kind->name, (void *)me);
-			require_quiet(n >= 0, exit);
-			desc_len += (size_t)n;
-		}
-		n = _dnssd_snprintf(&dst, end, "[");
-		require_quiet(n >= 0, exit);
-		desc_len += (size_t)n;
-
-		if (privacy) {
-			n = _dnssd_snprintf(&dst, end, "<%zu redacted cnames>",
-				me->xpc_array ? xpc_array_get_count(me->xpc_array) : 0);
-			require_quiet(n >= 0, exit);
-			desc_len += (size_t)n;
-		} else if (me->xpc_array) {
-			const bool ok = xpc_array_apply(me->xpc_array,
-			^ bool (const size_t index, const xpc_object_t _Nonnull cname)
-			{
-				const char *cname_str = xpc_string_get_string_ptr(cname);
-				if (!cname_str) {
-					cname_str = "";
-				}
-				n = _dnssd_snprintf(&dst, end, "%s%s", (index == 0) ? "" : ", ", cname_str);
-				if (likely(n >= 0)) {
-					desc_len += (size_t)n;
-					return true;
-				} else {
-					return false;
-				}
-			});
-			require_quiet(ok, exit);
-		}
-		n = _dnssd_snprintf(&dst, end, "]");
-		require_quiet(n >= 0, exit);
-		desc_len += (size_t)n;
-
-		if (!buf_ptr) {
-			buf_len = desc_len + 1;
-			buf_ptr = (char *)mdns_malloc(buf_len);
-			require_quiet(buf_ptr, exit);
-			buf_ptr[0] = '\0';
-		} else {
-			break;
-		}
-	}
-	desc = buf_ptr;
-	buf_ptr = NULL;
-
-exit:
-	FreeNullSafe(buf_ptr);
-	return desc;
-}
-
-//======================================================================================================================
-
-void
-_dnssd_cname_array_finalize(dnssd_cname_array_t me)
-{
-	xpc_forget(&me->xpc_array);
-}
-
-//======================================================================================================================
-// MARK: - dnssd Client
-
-static dnssd_getaddrinfo_t g_gai_list = NULL;
-
-static dispatch_queue_t
-_dnssd_client_queue(void)
-{
-	static dispatch_once_t	once	= 0;
-	static dispatch_queue_t	queue	= NULL;
-
-	dispatch_once(&once,
-	^{
-		queue = dispatch_queue_create("com.apple.dnssd.client", DISPATCH_QUEUE_SERIAL);
-	});
-	return queue;
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_handle_message(xpc_object_t msg);
-static void
-_dnssd_client_handle_interruption(void);
-
-static xpc_connection_t
-_dnssd_client_connection(void)
-{
-	static dispatch_once_t	once		= 0;
-	static xpc_connection_t	connection	= NULL;
-
-	dispatch_once(&once,
-	^{
-		connection = xpc_connection_create_mach_service(DNSSD_MACH_SERVICE_NAME, _dnssd_client_queue(),
-			XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
-		xpc_connection_set_event_handler(connection,
-		^(xpc_object_t event)
-		{
-			if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
-				_dnssd_client_handle_message(event);
-			} else if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
-				_dnssd_client_handle_interruption();
-			}
-		});
-		xpc_connection_activate(connection);
-	});
-	return connection;
-}
-
-static void
-_dnssd_client_handle_message(xpc_object_t msg)
-{
-	// Check if the server sent a keepalive command, which requires an immediate reply.
-	const char * const command = dnssd_xpc_message_get_command(msg);
-	if (command && (strcmp(command, DNSSD_COMMAND_KEEPALIVE) == 0)) {
-		xpc_object_t reply = xpc_dictionary_create_reply(msg);
-		if (reply) {
-			xpc_dictionary_send_reply(reply);
-			xpc_forget(&reply);
-		}
-		goto exit;
-	}
-	const uint64_t command_id = dnssd_xpc_message_get_id(msg, NULL);
-	dnssd_getaddrinfo_t gai;
-	for (gai = g_gai_list; gai; gai = gai->next) {
-		if (gai->command_id == command_id) {
-			break;
-		}
-	}
-	require_quiet(gai, exit);
-
-	const OSStatus error = dnssd_xpc_message_get_error(msg, NULL);
-	if (!error) {
-		xpc_object_t const result_array = dnssd_xpc_message_get_results(msg);
-		require_quiet(result_array, exit);
-
-		dnssd_getaddrinfo_result_t				result_list	= NULL;
-		__block dnssd_getaddrinfo_result_t *	result_ptr	= &result_list;
-		xpc_array_apply(result_array,
-		^ bool (__unused size_t index, xpc_object_t _Nonnull result_dict)
-		{
-			const dnssd_getaddrinfo_result_t result = _dnssd_getaddrinfo_create_result_from_dictionary(gai, result_dict,
-				NULL);
-			if (result) {
-				*result_ptr	= result;
-				result_ptr	= &result->next;
-			}
-			return true;
-		});
-		require_quiet(result_list, exit);
-
-		_dnssd_getaddrinfo_append_results(gai, result_list);
-		result_list = NULL;
-	} else {
-		_dnssd_client_fail_getaddrinfo(gai, error);
-	}
-
-exit:
-	return;
-}
-
-static void
-_dnssd_client_handle_interruption(void)
-{
-	dnssd_getaddrinfo_t next_gai;
-	for (dnssd_getaddrinfo_t gai = g_gai_list; gai; gai = next_gai) {
-		next_gai = gai->next;
-		gai->state = dnssd_getaddrinfo_state_starting;
-		const OSStatus err = _dnssd_client_send_getaddrinfo_command(gai);
-		if (!err) {
-			_dnssd_getaddrinfo_remove_all_results(gai);
-		} else {
-			_dnssd_client_fail_getaddrinfo(gai, err);
-		}
-	}
-}
-
-//======================================================================================================================
-
-static uint64_t
-_dnssd_client_get_new_id(void)
-{
-	static uint64_t last_id = 0;
-	return ++last_id;
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_activate_getaddrinfo(dnssd_getaddrinfo_t gai);
-
-static OSStatus
-_dnssd_getaddrinfo_activate(dnssd_getaddrinfo_t gai);
-
-static void
-_dnssd_client_activate_getaddrinfo_async(dnssd_getaddrinfo_t gai)
-{
-	dnssd_retain(gai);
-	dispatch_async(_dnssd_client_queue(),
-	^{
-		_dnssd_client_activate_getaddrinfo(gai);
-		dnssd_release(gai);
-	});
-}
-
-static void
-_dnssd_client_activate_getaddrinfo(dnssd_getaddrinfo_t gai)
-{
-	OSStatus err;
-	require_action_quiet(gai->state == dnssd_getaddrinfo_state_nascent, exit, err = kNoErr);
-
-	err = _dnssd_getaddrinfo_activate(gai);
-	if (err) {
-		gai->state = dnssd_getaddrinfo_state_failed;
-		goto exit;
-	}
-
-	gai->command_id = _dnssd_client_get_new_id();
-	gai->state = dnssd_getaddrinfo_state_starting;
-
-	_dnssd_client_register_getaddrinfo(gai);
-
-	err = _dnssd_client_send_getaddrinfo_command(gai);
-	if (err) {
-		_dnssd_client_fail_getaddrinfo(gai, err);
-	}
-
-exit:
-	return;
-}
-
-static void
-_dnssd_getaddrinfo_process_events(dnssd_getaddrinfo_t gai, unsigned long events);
-
-static OSStatus
-_dnssd_getaddrinfo_activate(dnssd_getaddrinfo_t me)
-{
-	OSStatus err;
-	xpc_object_t const hostname = dnssd_xpc_parameters_get_hostname_object(me->params);
-	require_action_quiet(hostname, exit, err = kParamErr);
-
-	me->hostname = xpc_copy(hostname);
-	require_action_quiet(me->hostname, exit, err = kNoResourcesErr);
-
-	me->event_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0, me->user_queue);
-	require_action_quiet(me->event_source, exit, err = kNoResourcesErr);
-
-	dnssd_retain(me);
-	dispatch_source_t const event_source = me->event_source;
-	dispatch_source_set_event_handler(me->event_source,
-	^{
-		_dnssd_getaddrinfo_process_events(me, dispatch_source_get_data(event_source));
-	});
-	dispatch_source_set_cancel_handler(me->event_source,
-	^{
-		dnssd_release(me);
-	});
-	dispatch_activate(me->event_source);
-	err = kNoErr;
-
-exit:
-	if (err) {
-		dnssd_retain(me);
-		dispatch_async(me->user_queue,
-		^{
-			if (me->event_handler) {
-				me->event_handler(dnssd_event_error, _dnssd_osstatus_to_dns_service_error(err));
-			}
-			dnssd_release(me);
-		});
-	}
-	return err;
-}
-
-static void
-_dnssd_getaddrinfo_process_events(dnssd_getaddrinfo_t me, unsigned long events)
-{
-	if (events & DNSSD_EVENT_REMOVE_ALL) {
-		if (me->event_handler) {
-			me->event_handler(dnssd_event_remove_all, kDNSServiceErr_NoError);
-		}
-	}
-
-	if (events & DNSSD_EVENT_HAVE_RESULTS) {
-		dnssd_getaddrinfo_result_t result;
-		dnssd_getaddrinfo_result_t result_array[32];
-		dnssd_getaddrinfo_result_t result_list = _dnssd_getaddrinfo_take_results(me);
-
-		size_t result_count = 0;
-		while ((result = result_list) != NULL) {
-			result_list		= result->next;
-			result->next	= NULL;
-			result_array[result_count++] = result;
-
-			if ((result_count == countof(result_array)) || !result_list) {
-				if (me->result_handler) {
-					me->result_handler(result_array, result_count);
-				}
-				for (size_t i = 0; i < result_count; ++i) {
-					dnssd_release(result_array[i]);
-				}
-				result_count = 0;
-			}
-		}
-	}
-
-	if (events & DNSSD_EVENT_ERROR) {
-		__block OSStatus error;
-		dispatch_sync(me->mutex_queue,
-		^{
-			error = me->error;
-			me->error = kNoErr;
-		});
-		if (me->event_handler && error) {
-			me->event_handler(dnssd_event_error, _dnssd_osstatus_to_dns_service_error(error));
-		}
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_register_getaddrinfo(dnssd_getaddrinfo_t gai)
-{
-	gai->next	= g_gai_list;
-	g_gai_list	= gai;
-	dnssd_retain(gai);
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_deregister_getaddrinfo(dnssd_getaddrinfo_t gai)
-{
-	dnssd_getaddrinfo_t *ptr;
-	for (ptr = &g_gai_list; *ptr; ptr = &(*ptr)->next)
-	{
-		if (*ptr == gai) {
-			break;
-		}
-	}
-	if (*ptr) {
-		*ptr = gai->next;
-		gai->next = NULL;
-		dnssd_release(gai);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_handle_getaddrinfo_reply(dnssd_getaddrinfo_t gai, xpc_object_t reply);
-
-static OSStatus
-_dnssd_client_send_getaddrinfo_command(dnssd_getaddrinfo_t gai)
-{
-	OSStatus err;
-	xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
-	require_action_quiet(msg, exit, err = kNoResourcesErr);
-
-	dnssd_xpc_message_set_id(msg, gai->command_id);
-	dnssd_xpc_message_set_command(msg, DNSSD_COMMAND_GETADDRINFO);
-	dnssd_xpc_message_set_parameters(msg, gai->params);
-
-	dnssd_retain(gai);
-	xpc_connection_send_message_with_reply(_dnssd_client_connection(), msg, _dnssd_client_queue(),
-	^(xpc_object_t reply)
-	{
-		_dnssd_client_handle_getaddrinfo_reply(gai, reply);
-		dnssd_release(gai);
-	});
-	xpc_forget(&msg);
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-static void
-_dnssd_client_handle_getaddrinfo_reply(dnssd_getaddrinfo_t gai, xpc_object_t reply)
-{
-	require_quiet(gai->state == dnssd_getaddrinfo_state_starting, exit);
-
-	if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
-		const OSStatus error = dnssd_xpc_message_get_error(reply, NULL);
-		if (error) {
-			_dnssd_client_fail_getaddrinfo(gai, error);
-		} else {
-			gai->state = dnssd_getaddrinfo_state_started;
-		}
-	} else if (reply != XPC_ERROR_CONNECTION_INTERRUPTED) {
-		OSStatus error;
-		if (reply == XPC_ERROR_CONNECTION_INVALID) {
-			error = kDNSServiceErr_ServiceNotRunning;
-		} else {
-			error = kDNSServiceErr_Unknown;
-		}
-		_dnssd_client_fail_getaddrinfo(gai, error);
-	}
-
-exit:
-	return;
-}
-
-//======================================================================================================================
-
-static void
-_dnssd_client_fail_getaddrinfo(dnssd_getaddrinfo_t gai, OSStatus error)
-{
-	_dnssd_client_deregister_getaddrinfo(gai);
-	gai->state = dnssd_getaddrinfo_state_failed;
-	_dnssd_getaddrinfo_post_error_event(gai, error);
-}
-
-//======================================================================================================================
-
-static bool
-_dnssd_extract_result_dict_values(xpc_object_t result, xpc_object_t *out_hostname, DNSServiceErrorType *out_error,
-	DNSServiceFlags *out_flags, uint32_t *out_interface_index, uint16_t *out_type, uint16_t *out_class,
-	xpc_object_t *out_rdata, xpc_object_t *out_auth_tag, dnssd_getaddrinfo_result_protocol_t *out_protocol,
-	xpc_object_t *out_provider_name, mdns_xpc_string_t *out_tracker_hostname, mdns_xpc_string_t *out_tracker_owner,
-	bool *out_tracker_approved, dnssd_negative_reason_t *out_negative_reason, xpc_object_t *out_validation_data);
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_result_create(dnssd_getaddrinfo_result_type_t type, xpc_object_t hostname,
-	xpc_object_t actual_hostname, dnssd_cname_array_t cname_array, int addr_family, const void *addr_data,
-	uint32_t interface_index, xpc_object_t auth_tag, dnssd_getaddrinfo_result_protocol_t protocol,
-	xpc_object_t provider_name, mdns_xpc_string_t tracker_hostname, mdns_xpc_string_t tracker_owner,
-	bool tracker_approved, dnssd_negative_reason_t negative_reason, xpc_object_t validation_data, OSStatus *out_error);
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_result_create_svcb(xpc_object_t hostname, xpc_object_t actual_hostname, const void *svcb_data,
-	size_t svcb_length, uint32_t interface_index, xpc_object_t auth_tag, dnssd_getaddrinfo_result_protocol_t protocol,
-	xpc_object_t provider_name, mdns_xpc_string_t tracker_hostname, mdns_xpc_string_t tracker_owner,
-	bool tracker_approved, dnssd_negative_reason_t negative_reason, xpc_object_t validation_data, OSStatus *out_error);
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_create_result_from_dictionary(dnssd_getaddrinfo_t me, xpc_object_t result_dict, OSStatus *out_error)
-{
-	OSStatus					err;
-	xpc_object_t				actual_hostname, rdata, auth_tag, provider_name;
-	mdns_xpc_string_t			tracker_hostname, tracker_owner;
-	DNSServiceErrorType			error;
-	DNSServiceFlags				flags;
-	uint32_t					if_index;
-	uint16_t					rtype;
-	bool						tracker_approved;
-	dnssd_getaddrinfo_result_protocol_t protocol;
-	dnssd_negative_reason_t		negative_reason;
-	xpc_object_t				validation_data;
-
-	dnssd_getaddrinfo_result_t result = NULL;
-	const bool ok = _dnssd_extract_result_dict_values(result_dict, &actual_hostname, &error, &flags, &if_index,
-		&rtype, NULL, &rdata, &auth_tag, &protocol, &provider_name, &tracker_hostname, &tracker_owner,
-		&tracker_approved, &negative_reason, &validation_data);
-	require_action_quiet(ok, exit, err = kMalformedErr);
-	require_action_quiet((error == kDNSServiceErr_NoError) || (error == kDNSServiceErr_NoSuchRecord), exit,
-		err = kUnexpectedErr);
-
-	// Dedupe the tracker hostname and owner strings, which will very likely be the same across multiple results.
-	if (tracker_hostname) {
-		mdns_xpc_string_replace_if_different(&me->tracker_hostname, tracker_hostname);
-		tracker_hostname = me->tracker_hostname;
-	}
-	if (tracker_owner) {
-		mdns_xpc_string_replace_if_different(&me->tracker_owner, tracker_owner);
-		tracker_owner = me->tracker_owner;
-	}
-	switch(rtype) {
-		case kDNSServiceType_A:
-		case kDNSServiceType_AAAA: {
-			const xpc_object_t cname_update = dnssd_xpc_result_get_cname_update(result_dict);
-			if (cname_update) {
-				_dnssd_getaddrinfo_set_cnames(me, rtype, cname_update);
-			}
-			dnssd_getaddrinfo_result_type_t result_type;
-			if (error == kDNSServiceErr_NoSuchRecord) {
-				result_type = dnssd_getaddrinfo_result_type_no_address;
-			} else {
-				if (flags & kDNSServiceFlagsAdd) {
-					if (flags & kDNSServiceFlagsExpiredAnswer) {
-						result_type = dnssd_getaddrinfo_result_type_expired;
-					} else {
-						result_type = dnssd_getaddrinfo_result_type_add;
-					}
-				} else {
-					result_type = dnssd_getaddrinfo_result_type_remove;
-				}
-				if (rtype == kDNSServiceType_A) {
-					require_action_quiet(xpc_data_get_length(rdata) == 4, exit, err = kMalformedErr);
-				} else {
-					require_action_quiet(xpc_data_get_length(rdata) == 16, exit, err = kMalformedErr);
-				}
-			}
-			const int addr_family = (rtype == kDNSServiceType_A) ? AF_INET : AF_INET6;
-			result = _dnssd_getaddrinfo_result_create(result_type, me->hostname, actual_hostname,
-				_dnssd_getaddrinfo_get_cname_array(me, rtype), addr_family, xpc_data_get_bytes_ptr(rdata), if_index,
-				auth_tag, protocol, provider_name, tracker_hostname, tracker_owner, tracker_approved, negative_reason,
-				validation_data, &err);
-			require_noerr_quiet(err, exit);
-			break;
-		}
-		case kDNSServiceType_SVCB:
-		case kDNSServiceType_HTTPS: {
-			if (error != kDNSServiceErr_NoSuchRecord) {
-				require_action_quiet(xpc_data_get_length(rdata) > 0, exit, err = kMalformedErr);
-			}
-
-			// SVCB type answer
-			result = _dnssd_getaddrinfo_result_create_svcb(me->hostname, actual_hostname,
-				xpc_data_get_bytes_ptr(rdata), xpc_data_get_length(rdata), if_index, auth_tag, protocol, provider_name,
-				tracker_hostname, tracker_owner, tracker_approved, negative_reason, validation_data, &err);
-			require_noerr_quiet(err, exit);
-			break;
-		}
-		default:
-			err = kTypeErr;
-			goto exit;
-	}
-	if ((flags & kDNSServiceFlagsAdd) && (flags & kDNSServiceFlagAnsweredFromCache)) {
-		result->is_from_cache = true;
-	}
-
-exit:
-	if (err) {
-		dnssd_forget(&result);
-	}
-	if (out_error) {
-		*out_error = err;
-	}
-	return result;
-}
-
-static bool
-_dnssd_extract_result_dict_values(xpc_object_t result, xpc_object_t *out_hostname, DNSServiceErrorType *out_error,
-	DNSServiceFlags *out_flags, uint32_t *out_interface_index, uint16_t *out_type, uint16_t *out_class,
-	xpc_object_t *out_rdata, xpc_object_t *out_auth_tag, dnssd_getaddrinfo_result_protocol_t *out_protocol,
-	xpc_object_t *out_provider_name, mdns_xpc_string_t *out_tracker_hostname, mdns_xpc_string_t *out_tracker_owner,
-	bool *out_tracker_approved, dnssd_negative_reason_t *out_negative_reason, xpc_object_t *out_validation_data)
-{
-	bool result_is_valid = false;
-	xpc_object_t const hostname = dnssd_xpc_result_get_record_name_object(result);
-	require_quiet(hostname, exit);
-
-	xpc_object_t const rdata = dnssd_xpc_result_get_record_data_object(result);
-	require_quiet(rdata, exit);
-
-	if (out_hostname) {
-		*out_hostname = hostname;
-	}
-	if (out_error) {
-		*out_error = dnssd_xpc_result_get_error(result, NULL);
-	}
-	if (out_flags) {
-		*out_flags = dnssd_xpc_result_get_flags(result, NULL);
-	}
-	if (out_interface_index) {
-		*out_interface_index = dnssd_xpc_result_get_interface_index(result, NULL);
-	}
-	if (out_type) {
-		*out_type = dnssd_xpc_result_get_record_type(result, NULL);
-	}
-	if (out_class) {
-		*out_class = dnssd_xpc_result_get_record_class(result, NULL);
-	}
-	if (out_rdata) {
-		*out_rdata = rdata;
-	}
-	if (out_auth_tag) {
-		*out_auth_tag = dnssd_xpc_result_get_authentication_tag_object(result);
-	}
-	if (out_protocol) {
-		*out_protocol = dnssd_xpc_result_get_record_protocol(result, NULL);
-	}
-	if (out_provider_name) {
-		*out_provider_name = dnssd_xpc_result_get_provider_name_object(result);
-	}
-	if (out_tracker_hostname) {
-		*out_tracker_hostname = dnssd_xpc_result_get_tracker_hostname(result);
-	}
-	if (out_tracker_owner) {
-		*out_tracker_owner = dnssd_xpc_result_get_tracker_owner(result);
-	}
-	if (out_tracker_approved) {
-		*out_tracker_approved = dnssd_xpc_result_get_tracker_is_approved(result);
-	}
-	if (out_negative_reason) {
-		*out_negative_reason = dnssd_xpc_result_get_negative_reason(result);
-	}
-	if (out_validation_data) {
-		*out_validation_data = dnssd_xpc_result_get_validation_data_object(result);
-	}
-	result_is_valid = true;
-
-exit:
-	return result_is_valid;
-}
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_result_create(const dnssd_getaddrinfo_result_type_t type, const xpc_object_t hostname,
-	const xpc_object_t actual_hostname, const dnssd_cname_array_t cnames, const int addr_family,
-	const void * const addr_data, const uint32_t if_index, const xpc_object_t auth_tag,
-	const dnssd_getaddrinfo_result_protocol_t protocol, const xpc_object_t provider_name,
-	const mdns_xpc_string_t tracker_hostname, const mdns_xpc_string_t tracker_owner, const bool tracker_approved,
-	const dnssd_negative_reason_t negative_reason, const xpc_object_t validation_data, OSStatus * const out_error)
-{
-	OSStatus err;
-	dnssd_getaddrinfo_result_t result = NULL;
-	dnssd_getaddrinfo_result_t obj = _dnssd_getaddrinfo_result_alloc();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	switch (type) {
-		case dnssd_getaddrinfo_result_type_add:
-		case dnssd_getaddrinfo_result_type_remove:
-		case dnssd_getaddrinfo_result_type_no_address:
-		case dnssd_getaddrinfo_result_type_expired:
-			break;
-
-		case dnssd_getaddrinfo_result_type_service_binding:
-		CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-		default:
-		CUClangWarningIgnoreEnd();
-			err = kTypeErr;
-			goto exit;
-	}
-	obj->type				= type;
-	obj->if_index			= if_index;
-	obj->protocol			= protocol;
-	obj->negative_reason	= negative_reason;
-
-	require_action_quiet(xpc_get_type(hostname) == XPC_TYPE_STRING, exit, err = kTypeErr);
-
-	obj->hostname = xpc_copy(hostname);
-	require_action_quiet(obj->hostname, exit, err = kNoResourcesErr);
-
-	require_action_quiet(xpc_get_type(actual_hostname) == XPC_TYPE_STRING, exit, err = kTypeErr);
-
-	obj->actual_hostname = xpc_copy(actual_hostname);
-	require_action_quiet(obj->actual_hostname, exit, err = kNoResourcesErr);
-
-	obj->cnames = cnames ? cnames : _dnssd_get_empty_cname_array();
-	dnssd_retain(obj->cnames);
-	require_action_quiet((addr_family == AF_INET) || (addr_family == AF_INET6), exit, err = kTypeErr);
-
-	if (addr_family == AF_INET) {
-		obj->addr.sa.sa_family	= AF_INET;
-		obj->addr.v4.sin_len	= sizeof(struct sockaddr_in);
-		if (obj->type != dnssd_getaddrinfo_result_type_no_address) {
-			memcpy(&obj->addr.v4.sin_addr.s_addr, addr_data, 4);
-		}
-	} else if (addr_family == AF_INET6) {
-		struct sockaddr_in6 * const sin6 = &obj->addr.v6;
-		sin6->sin6_family	= AF_INET6;
-		sin6->sin6_len		= sizeof(struct sockaddr_in6);
-		if (obj->type != dnssd_getaddrinfo_result_type_no_address) {
-			memcpy(&sin6->sin6_addr.s6_addr, addr_data, 16);
-			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
-				sin6->sin6_scope_id = obj->if_index;
-			}
-		}
-	}
-	if (auth_tag) {
-		require_action_quiet(xpc_get_type(auth_tag) == XPC_TYPE_DATA, exit, err = kTypeErr);
-
-		obj->auth_tag = xpc_copy(auth_tag);
-		require_action_quiet(obj->auth_tag, exit, err = kNoResourcesErr);
-	}
-	if (provider_name) {
-		require_action_quiet(xpc_get_type(provider_name) == XPC_TYPE_STRING, exit, err = kTypeErr);
-
-		obj->provider_name = xpc_copy(provider_name);
-		require_action_quiet(obj->provider_name, exit, err = kNoResourcesErr);
-	}
-	if (tracker_hostname) {
-		obj->tracker_hostname = mdns_xpc_string_retain(tracker_hostname);
-		if (tracker_owner) {
-			obj->tracker_owner = mdns_xpc_string_retain(tracker_owner);
-		}
-		obj->tracker_approved = tracker_approved;
-	}
-	if (validation_data) {
-		require_action_quiet(xpc_get_type(validation_data) == XPC_TYPE_DATA, exit, err = kTypeErr);
-
-		obj->validation_data = xpc_copy(validation_data);
-		require_action_quiet(obj->validation_data, exit, err = kNoResourcesErr);
-	}
-	result	= obj;
-	obj		= NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	dnssd_release_null_safe(obj);
-	return result;
-}
-
-static dnssd_getaddrinfo_result_t
-_dnssd_getaddrinfo_result_create_svcb(xpc_object_t hostname, xpc_object_t actual_hostname, const void *svcb_data,
-	size_t svcb_length, uint32_t interface_index, xpc_object_t auth_tag, dnssd_getaddrinfo_result_protocol_t protocol,
-	xpc_object_t provider_name, const mdns_xpc_string_t tracker_hostname, const mdns_xpc_string_t tracker_owner,
-	const bool tracker_approved, const dnssd_negative_reason_t negative_reason, xpc_object_t validation_data,
-	OSStatus *out_error)
-{
-	OSStatus err;
-	dnssd_getaddrinfo_result_t result = NULL;
-	dnssd_getaddrinfo_result_t obj = _dnssd_getaddrinfo_result_alloc();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->type				= dnssd_getaddrinfo_result_type_service_binding;
-	obj->if_index			= interface_index;
-	obj->protocol			= protocol;
-	obj->negative_reason	= negative_reason;
-
-	require_action_quiet(xpc_get_type(hostname) == XPC_TYPE_STRING, exit, err = kTypeErr);
-	obj->hostname = xpc_copy(hostname);
-
-	require_action_quiet(xpc_get_type(actual_hostname) == XPC_TYPE_STRING, exit, err = kTypeErr);
-
-	obj->actual_hostname = xpc_copy(actual_hostname);
-	require_action_quiet(obj->actual_hostname, exit, err = kNoResourcesErr);
-
-	if (svcb_data != NULL && svcb_length > 0) {
-		obj->valid_svcb = dnssd_svcb_is_valid(svcb_data, svcb_length);
-		obj->priority = dnssd_svcb_get_priority(svcb_data, svcb_length);
-		obj->port = dnssd_svcb_get_port(svcb_data, svcb_length);
-
-		char *service_name = dnssd_svcb_copy_service_name_string(svcb_data, svcb_length);
-		if (service_name != NULL) {
-			if (dnssd_svcb_service_name_is_empty(svcb_data, svcb_length)) {
-				// The empty name is an placeholder for the name for the record
-				obj->service_name = xpc_copy(obj->hostname);
-			} else {
-				obj->service_name = xpc_string_create(service_name);
-			}
-			ForgetMem(&service_name);
-			require_action_quiet(obj->service_name, exit, err = kNoResourcesErr);
-		}
-
-		char *doh_uri = dnssd_svcb_copy_doh_uri(svcb_data, svcb_length);
-		if (doh_uri != NULL) {
-			obj->doh_uri = xpc_string_create(doh_uri);
-			ForgetMem(&doh_uri);
-			require_action_quiet(obj->doh_uri, exit, err = kNoResourcesErr);
-		}
-
-		char *doh_path = dnssd_svcb_copy_doh_path(svcb_data, svcb_length);
-		if (doh_path != NULL) {
-			obj->doh_path = xpc_string_create(doh_path);
-			ForgetMem(&doh_path);
-			require_action_quiet(obj->doh_path, exit, err = kNoResourcesErr);
-		}
-
-		size_t ech_config_length = 0;
-		uint8_t *ech_config = dnssd_svcb_copy_ech_config(svcb_data, svcb_length, &ech_config_length);
-		if (ech_config != NULL) {
-			obj->ech_config = xpc_data_create(ech_config, ech_config_length);
-			ForgetMem(&ech_config);
-			require_action_quiet(obj->ech_config, exit, err = kNoResourcesErr);
-		}
-
-		size_t odoh_config_length = 0;
-		uint8_t *odoh_config = dnssd_svcb_copy_odoh_config(svcb_data, svcb_length, &odoh_config_length);
-		if (odoh_config != NULL) {
-			obj->odoh_config = xpc_data_create(odoh_config, odoh_config_length);
-			ForgetMem(&odoh_config);
-			require_action_quiet(obj->odoh_config, exit, err = kNoResourcesErr);
-		}
-
-		dnssd_svcb_access_alpn_values(svcb_data, svcb_length, ^bool(const char *alpn) {
-			xpc_object_t alpn_string = xpc_string_create(alpn);
-			if (obj->alpn_values == NULL) {
-				obj->alpn_values = xpc_array_create(NULL, 0);
-			}
-			xpc_array_append_value(obj->alpn_values, alpn_string);
-			xpc_forget(&alpn_string);
-			return true;
-		});
-
-		dnssd_svcb_access_address_hints(svcb_data, svcb_length, ^bool(const struct sockaddr *address) {
-			xpc_object_t address_hint = xpc_data_create(address, address->sa_len);
-			if (obj->address_hints == NULL) {
-				obj->address_hints = xpc_array_create(NULL, 0);
-			}
-			xpc_array_append_value(obj->address_hints, address_hint);
-			xpc_forget(&address_hint);
-			return true;
-		});
-	} else {
-		obj->valid_svcb = false;
-	}
-
-	if (auth_tag) {
-		require_action_quiet(xpc_get_type(auth_tag) == XPC_TYPE_DATA, exit, err = kTypeErr);
-
-		obj->auth_tag = xpc_copy(auth_tag);
-		require_action_quiet(obj->auth_tag, exit, err = kNoResourcesErr);
-	}
-
-	if (provider_name) {
-		require_action_quiet(xpc_get_type(provider_name) == XPC_TYPE_STRING, exit, err = kTypeErr);
-
-		obj->provider_name = xpc_copy(provider_name);
-		require_action_quiet(obj->provider_name, exit, err = kNoResourcesErr);
-	}
-
-	if (tracker_hostname) {
-		obj->tracker_hostname = mdns_xpc_string_retain(tracker_hostname);
-		if (tracker_owner) {
-			obj->tracker_owner = mdns_xpc_string_retain(tracker_owner);
-		}
-		obj->tracker_approved = tracker_approved;
-	}
-	if (validation_data) {
-		require_action_quiet(xpc_get_type(validation_data) == XPC_TYPE_DATA, exit, err = kTypeErr);
-
-		obj->validation_data = xpc_copy(validation_data);
-		require_action_quiet(obj->validation_data, exit, err = kNoResourcesErr);
-	}
-	result	= obj;
-	obj		= NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	dnssd_release_null_safe(obj);
-	return result;
-}
-
-//======================================================================================================================
-// MARK: - Misc. Helpers
-
-static dnssd_cname_array_t
-_dnssd_get_empty_cname_array(void)
-{
-	static dispatch_once_t		s_once = 0;
-	static dnssd_cname_array_t	s_empty_cname_array = NULL;
-	dispatch_once(&s_once,
-	^{
-		s_empty_cname_array = _dnssd_cname_array_create(NULL, NULL);
-		s_empty_cname_array->base._os_obj_refcnt	= _OS_OBJECT_GLOBAL_REFCNT;
-		s_empty_cname_array->base._os_obj_xref_cnt	= _OS_OBJECT_GLOBAL_REFCNT;
-	});
-	return s_empty_cname_array;
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dnssd_osstatus_to_dns_service_error(OSStatus error)
-{
-	switch (error) {
-		case kNoMemoryErr:
-		case kNoResourcesErr:
-			error = kDNSServiceErr_NoMemory;
-			break;
-
-		case kParamErr:
-			error = kDNSServiceErr_BadParam;
-			break;
-
-		default:
-			if ((error >= kGenericErrorBase) && (error <= kGenericErrorEnd)) {
-				error = kDNSServiceErr_Unknown;
-			}
-			break;
-	}
-	return error;
-}
-
-//======================================================================================================================
-
-static int
-_dnssd_snprintf(char ** const dst, const char * const end, const char * const format, ...)
-{
-	char * const ptr = *dst;
-	const size_t len = (size_t)(end - ptr);
-	va_list args;
-	va_start(args, format);
-	CUClangWarningIgnoreBegin(-Wformat-nonliteral);
-	const int n = vsnprintf(ptr, len, format, args);
-	CUClangWarningIgnoreEnd();
-	va_end(args);
-	if (n >= 0) {
-		*dst = ptr + Min((size_t)n, len);
-	}
-	return n;
-}
diff --git a/mDNSMacOSX/dnssd_analytics.c b/mDNSMacOSX/dnssd_analytics.c
deleted file mode 100644
index 97f715d..0000000
--- a/mDNSMacOSX/dnssd_analytics.c
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- */
-
-#include "dnssd_analytics.h"
-#include "mDNSMacOSX.h"
-#include "uds_daemon.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-
-#include <xpc/xpc.h>
-#include <CoreAnalytics/CoreAnalytics.h>
-#include <CoreUtils/DebugServices.h>
-#include "mdns_strict.h"
-
-#endif // ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-
-// MARK:  - Private Types
-
-enum : uint8_t {
-	e_index_standard_noncell		= 0,
-	e_index_standard_cell,
-	e_index_encrypted_noncell,
-	e_index_encrypted_cell,
-	e_index_count,
-	e_index_invalid = -1
-};
-
-typedef struct {
-	uint64_t			queries;
-	uint64_t			reply_pos;
-	uint64_t			reply_neg;
-} qtype_count_t;
-
-typedef struct {
-	uint64_t			latency_count;		// For calulating average
-	uint64_t			latency_total;		// For calulating average
-	uint64_t			query_bytes;
-	uint64_t			reply_bytes;
-	qtype_count_t 		v4;
-	qtype_count_t 		v6;
-	qtype_count_t 		https;
-} dns_analytic_t;
-static dns_analytic_t s_dns_analytics[e_index_count] = {};
-
-// MARK:  - Private Functions
-
-static inline const char *
-_index_to_transport_string(uint8_t index)
-{
-	switch (index) {
-		case e_index_standard_noncell:
-		case e_index_standard_cell:
-			return "standard";
-		case e_index_encrypted_noncell:
-		case e_index_encrypted_cell:
-			return "encrypted";
-	}
-	return NULL;
-}
-
-static inline const char *
-_index_to_network_string(uint8_t index)
-{
-	switch (index) {
-		case e_index_standard_noncell:
-		case e_index_encrypted_noncell:
-			return "non-cell";
-		case e_index_standard_cell:
-		case e_index_encrypted_cell:
-			return "cellular";
-	}
-	return NULL;
-}
-
-static void
-_post_dns_analytic(dns_analytic_t * const _Nonnull analytic, const char * _Nonnull network, const char * _Nonnull transport)
-{
-	bool                        posted;
-	posted = analytics_send_event_lazy("com.apple.mDNSResponder.dnsqueryinfo", ^{
-		xpc_object_t        dict;
-		dict = xpc_dictionary_create(NULL, NULL, 0);
-		xpc_dictionary_set_string(dict, "network",  		network);
-		xpc_dictionary_set_string(dict, "transport",   		transport);
-		xpc_dictionary_set_uint64(dict, "latency_ms", 		analytic->latency_total / analytic->latency_count);
-		xpc_dictionary_set_uint64(dict, "query_bytes", 		analytic->query_bytes);
-		xpc_dictionary_set_uint64(dict, "reply_bytes", 		analytic->reply_bytes);
-		xpc_dictionary_set_uint64(dict, "v4_queries", 		analytic->v4.queries);
-		xpc_dictionary_set_uint64(dict, "v4_reply_pos", 	analytic->v4.reply_pos);
-		xpc_dictionary_set_uint64(dict, "v4_reply_neg",		analytic->v4.reply_neg);
-		xpc_dictionary_set_uint64(dict, "v6_queries", 		analytic->v6.queries);
-		xpc_dictionary_set_uint64(dict, "v6_reply_pos", 	analytic->v6.reply_pos);
-		xpc_dictionary_set_uint64(dict, "v6_reply_neg",		analytic->v6.reply_neg);
-		xpc_dictionary_set_uint64(dict, "https_queries",	analytic->https.queries);
-		xpc_dictionary_set_uint64(dict, "https_reply_pos", 	analytic->https.reply_pos);
-		xpc_dictionary_set_uint64(dict, "https_reply_neg",	analytic->https.reply_neg);
-		return (dict);
-	});
-	if (!posted) {
-		LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.dnsqueryinfo: Analytic not posted");
-	}
-}
-
-static void
-_post_dns_query_info()
-{
-	for (uint8_t i = 0 ; i < e_index_count ; i++ ) {
-		if (s_dns_analytics[i].latency_count > 0) {
-			_post_dns_analytic(&s_dns_analytics[i], _index_to_network_string(i), _index_to_transport_string(i));
-		}
-	}
-	memset(&s_dns_analytics, 0, sizeof(s_dns_analytics));
-}
-
-static qtype_count_t*
-_qtype_count_for_analytic(dns_analytic_t * const _Nonnull analytic, uint16_t qtype)
-{
-	qtype_count_t *qtype_ptr = NULL;
-	switch (qtype) {
-		case kDNSType_A:
-			qtype_ptr = &analytic->v4;
-			break;
-
-		case kDNSType_AAAA:
-			qtype_ptr = &analytic->v6;
-			break;
-			
-		case kDNSType_HTTPS:
-			qtype_ptr = &analytic->https;
-			break;
-	}
-	return qtype_ptr;
-}
-
-static dns_analytic_t*
-_analytic_for_event(bool is_cellular, dns_transport_t transport)
-{
-	dns_analytic_t *analytic = NULL;
-	uint8_t			index = e_index_invalid;
-	require_quiet(transport != dns_transport_Undefined, exit);
-
-	if (is_cellular) {
-		if (transport == dns_transport_Do53) {
-			index = e_index_standard_cell;
-		} else {
-			index = e_index_encrypted_cell;
-		}
-	} else {
-		if (transport == dns_transport_Do53) {
-			index = e_index_standard_noncell;
-		} else {
-			index = e_index_encrypted_noncell;
-		}
-	}
-	require_quiet(index != e_index_invalid && index < e_index_count, exit);
-	analytic = &s_dns_analytics[index];
-exit:
-	return analytic;
-}
-
-// MARK:  - Public Functions
-
-void
-dnssd_analytics_update_dns_query_info(bool is_cellular, dns_transport_t transport, uint16_t qtype, uint32_t num_queries,
-	uint32_t latency_ms, bool is_positive_answer)
-{
-	require_quiet(num_queries > 0, exit);
-
-	dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport);
-	require_quiet(analytic, exit);
-
-	qtype_count_t *qtype_count = _qtype_count_for_analytic(analytic, qtype);
-	require_quiet(qtype_count, exit);
-
-	analytic->latency_count++;
-	analytic->latency_total += latency_ms;
-
-	qtype_count->queries += num_queries;
-	if (is_positive_answer) {
-		qtype_count->reply_pos++;
-	} else {
-		qtype_count->reply_neg++;
-	}
-
-	LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEBUG, "dnssd_analytics_update_dns_query_info cell %d qtype %d queries %u latency %d pos %d",
-			  is_cellular, qtype, num_queries, latency_ms, is_positive_answer);
-exit:
-	return;
-}
-
-void
-dnssd_analytics_update_dns_query_size(bool is_cellular, dns_transport_t transport, uint32_t send_bytes)
-{
-	dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport);
-	require_quiet(analytic, exit);
-
-	analytic->query_bytes += send_bytes;
-
-exit:
-	return;
-}
-
-void
-dnssd_analytics_update_dns_reply_size(bool is_cellular, dns_transport_t transport, uint32_t recv_bytes)
-{
-	dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport);
-	require_quiet(analytic, exit);
-
-	analytic->reply_bytes += recv_bytes;
-
-exit:
-	return;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-dns_transport_t
-dnssd_analytics_dns_transport_for_resolver_type(mdns_resolver_type_t type)
-{
-	dns_transport_t transport;
-	switch (type) {
-		case mdns_resolver_type_https:
-			transport = dns_transport_DoH;
-			break;
-
-		case mdns_resolver_type_tls:
-			transport = dns_transport_DoT;
-			break;
-
-		case mdns_resolver_type_normal:
-		case mdns_resolver_type_tcp:
-			transport = dns_transport_Do53;
-			break;
-
-		case mdns_resolver_type_null:
-			transport = dns_transport_Undefined;
-			break;
-	}
-	return transport;
-}
-
-#endif // QUERIER
-
-#endif // DNS_ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-
-// Local aggregate counters to track request counts
-
-static uint64_t sCacheUsage_UnicastHitCount = 0;
-static uint64_t sCacheUsage_UnicastMissCount = 0;
-static uint64_t sCacheUsage_MulticastHitCount = 0;
-static uint64_t sCacheUsage_MulticastMissCount = 0;
-
-static uint64_t sCacheRequest_UnicastHitCount = 0;
-static uint64_t sCacheRequest_UnicastMissCount = 0;
-static uint64_t sCacheRequest_MulticastHitCount = 0;
-static uint64_t sCacheRequest_MulticastMissCount = 0;
-
-// MARK:  - Private CacheUsage Functions
-
-static void
-_post_cache_request_count(CacheRequestType inType, CacheState inState, uint64_t inRequestCount)
-{
-    bool                        posted;
-	posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.request", ^{
-		xpc_object_t        dict;
-		dict = xpc_dictionary_create(NULL, NULL, 0);
-		xpc_dictionary_set_string(dict, "requestType",  inType  == CacheRequestType_multicast    ? "multicast"   : "unicast");
-		xpc_dictionary_set_string(dict, "cacheState",   inState == CacheState_hit                ? "hit"         : "miss");
-		xpc_dictionary_set_uint64(dict, "requestCount", inRequestCount);
-		return (dict);
-	});
-    if (!posted) {
-        LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.request: Analytic not posted");
-    }
-}
-
-static void
-_post_cache_request_counts()
-{
-    if (sCacheRequest_UnicastHitCount > 0) {
-		_post_cache_request_count(CacheRequestType_unicast, CacheState_hit, sCacheRequest_UnicastHitCount);
-        sCacheRequest_UnicastHitCount = 0;
-    }
-    if (sCacheRequest_UnicastMissCount > 0) {
-		_post_cache_request_count(CacheRequestType_unicast, CacheState_miss, sCacheRequest_UnicastMissCount);
-        sCacheRequest_UnicastMissCount = 0;
-    }
-    if (sCacheRequest_MulticastHitCount > 0) {
-		_post_cache_request_count(CacheRequestType_multicast, CacheState_hit, sCacheRequest_MulticastHitCount);
-        sCacheRequest_MulticastHitCount = 0;
-    }
-    if (sCacheRequest_MulticastMissCount > 0) {
-		_post_cache_request_count(CacheRequestType_multicast, CacheState_miss, sCacheRequest_MulticastMissCount);
-        sCacheRequest_MulticastMissCount = 0;
-    }
-}
-
-static void
-_post_cache_usage_counts_for_type(CacheRequestType inType, uint64_t inHitCount, uint64_t inMissCount)
-{
-    bool                    posted;
-	posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", ^{
-		xpc_object_t        dict;
-		dict = xpc_dictionary_create(NULL, NULL, 0);
-		xpc_dictionary_set_string(dict, "requestType",  inType == CacheRequestType_multicast ? "multicast" : "unicast");
-		xpc_dictionary_set_uint64(dict, "hitCount",     inHitCount);
-		xpc_dictionary_set_uint64(dict, "missCount",    inMissCount);
-		return (dict);
-	});
-    if (!posted) {
-        LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Analytic not posted");
-    }
-}
-
-static void
-_post_cache_usage_counts()
-{
-	if (sCacheUsage_MulticastHitCount || sCacheUsage_MulticastMissCount) {
-		_post_cache_usage_counts_for_type(CacheRequestType_multicast, sCacheUsage_MulticastHitCount, sCacheUsage_MulticastMissCount);
-		sCacheUsage_MulticastHitCount = 0;
-		sCacheUsage_MulticastMissCount = 0;
-	}
-	if (sCacheUsage_UnicastHitCount || sCacheUsage_UnicastMissCount) {
-		_post_cache_usage_counts_for_type(CacheRequestType_unicast, sCacheUsage_UnicastHitCount, sCacheUsage_UnicastMissCount);
-		sCacheUsage_UnicastHitCount = 0;
-		sCacheUsage_UnicastMissCount = 0;
-	}
-}
-
-// MARK:  - Exported CacheUsage Functions
-
-void
-dnssd_analytics_update_cache_request(CacheRequestType inType, CacheState inState)
-{
-    if (inType == CacheRequestType_unicast) {
-        if (inState == CacheState_hit) {
-            sCacheRequest_UnicastHitCount++;
-        } else if (inState == CacheState_miss) {
-            sCacheRequest_UnicastMissCount++;
-        } else {
-			LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request:  unknown CacheState %d for unicast", inState);
-        }
-    } else if (inType == CacheRequestType_multicast) {
-        if (inState == CacheState_hit) {
-            sCacheRequest_MulticastHitCount++;
-        } else if (inState == CacheState_miss) {
-            sCacheRequest_MulticastMissCount++;
-        } else {
-            LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request:  unknown CacheState %d for multicast", inState);
-        }
-    } else {
-        LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request:  unknown CacheRequestType %d", inType);
-    }
-}
-
-void
-dnssd_analytics_update_cache_usage_counts(uint32_t inHitMulticastCount, uint32_t inMissMulticastCount, uint32_t inHitUnicastCount, uint32_t inMissUnicastCount)
-{
-	sCacheUsage_MulticastHitCount += inHitMulticastCount;
-	sCacheUsage_MulticastMissCount += inMissMulticastCount;
-	sCacheUsage_UnicastHitCount += inHitUnicastCount;
-	sCacheUsage_UnicastMissCount += inMissUnicastCount;
-}
-
-#endif // CACHE_ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WAB_ANALYTICS)
-
-#define UNSET_STR	"unset"
-
-// MARK:  - Exported WABUsage Functions
-
-void
-dnssd_analytics_post_WAB_usage_event_count(WABUsageKind inKind, WABUsageType inType, WABUsageEvent inEvent, uint64_t inEventCount)
-{
-    bool                    posted;
-    char *                  kind  = UNSET_STR;
-    char *                  type  = UNSET_STR;
-    char *                  event = UNSET_STR;
-
-	if (analytics_send_event_lazy) {
-		switch (inKind) {
-			case WABUsageKind_results: {
-				kind = "results";
-				break;
-			}
-			case WABUsageKind_session: {
-				kind = "session";
-				break;
-			}
-			case WABUsageKind_operation: {
-				kind = "operation";
-				break;
-			}
-		}
-
-		switch (inType) {
-			case WABUsageType_enumeration: {
-				type = "enumeration";
-				break;
-			}
-			case WABUsageType_query: {
-				type = "query";
-				break;
-			}
-			case WABUsageType_push: {
-				type = "push";
-				break;
-			}
-			case WABUsageType_llq: {
-				type = "llq";
-				break;
-			}
-		}
-
-		switch (inEvent) {
-			case WABUsageEvent_positive: {
-				event = "positive";
-				break;
-			}
-			case WABUsageEvent_negative: {
-				event = "negative";
-				break;
-			}
-			case WABUsageEvent_null: {
-				event = "null";
-				break;
-			}
-			case WABUsageEvent_error: {
-				event = "error";
-				break;
-			}
-
-			case WABUsageEvent_connected: {
-				event = "connected";
-				break;
-			}
-			case WABUsageEvent_session: {
-				event = "session";
-				break;
-			}
-			case WABUsageEvent_reset: {
-				event = "reset";
-				break;
-			}
-			case WABUsageEvent_idledOut: {
-				event = "idledOut";
-				break;
-			}
-			case WABUsageEvent_goAway: {
-				event = "goAway";
-				break;
-			}
-			case WABUsageEvent_resumedGood: {
-				event = "resumedGood";
-				break;
-			}
-			case WABUsageEvent_resumedBad: {
-				event = "resumedBad";
-				break;
-			}
-
-			case WABUsageEvent_succeeded: {
-				event = "succeeded";
-				break;
-			}
-			case WABUsageEvent_rejected: {
-				event = "rejected";
-				break;
-			}
-			case WABUsageEvent_dsoni: {
-				event = "dsoni";
-				break;
-			}
-			case WABUsageEvent_answered: {
-				event = "answered";
-				break;
-			}
-		}
-
-		posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", ^{
-			xpc_object_t        dict;
-			dict = xpc_dictionary_create(NULL, NULL, 0);
-			xpc_dictionary_set_string(dict, "kind",         kind);
-			xpc_dictionary_set_string(dict, "type",         type);
-			xpc_dictionary_set_string(dict, "event",        event);
-			xpc_dictionary_set_uint64(dict, "eventCount",   inEventCount);
-			return (dict);
-		});
-		if (!posted) {
-			LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Analytic not posted");
-		}
-	}
-}
-
-#endif // WAB_ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-// MARK:  - Exported Analytics Functions
-
-void
-dnssd_analytics_init()
-{
-	static dispatch_once_t	sInitAnalyticsOnce = 0;
-	static dispatch_queue_t sAnalyticsQueue = NULL;
-	dispatch_once(&sInitAnalyticsOnce, ^{
-		sAnalyticsQueue = dispatch_queue_create("com.apple.mDNSResponder.analytics-reporting-queue", DISPATCH_QUEUE_SERIAL);
-		xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);
-		xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_REPEATING, true);
-		xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_ALLOW_BATTERY, true);
-		xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_DELAY, XPC_ACTIVITY_INTERVAL_1_DAY);
-		xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, XPC_ACTIVITY_INTERVAL_5_MIN);
-		xpc_dictionary_set_string(criteria, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_MAINTENANCE);
-
-		xpc_activity_register("com.apple.mDNSResponder.analytics.daily", criteria, ^(xpc_activity_t activity) {
-			if (xpc_activity_should_defer(activity)) {
-			    if (xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DEFER)) {
-					LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEFAULT, "com.apple.mDNSResponder.analytics.daily: Asked to defer");
-				} else {
-					LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Asked to defer but failed to set state");
-				}
-			} else {
-				dispatch_async(sAnalyticsQueue, ^{
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-					KQueueLock();
-					mDNS_Lock(&mDNSStorage);
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-					_post_cache_request_counts();
-					_post_cache_usage_counts();
-#endif	//	CACHE_ANALYTICS
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-					_post_dns_query_info();
-#endif	//	DNS_ANALYTICS
-					LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEFAULT, "com.apple.mDNSResponder.analytics.daily Complete");
-					mDNS_Unlock(&mDNSStorage);
-					KQueueUnlock("Analytics Update");
-#endif	//	ANALYTICS
-				});
-				if (!xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE)) {
-					LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Analytics XPC_ACTIVITY_STATE_DONE failed");
-				}
-			}
-		});
-		MDNS_DISPOSE_XPC(criteria);
-	});
-}
-
-void
-dnssd_analytics_log(int fd)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-	LogToFD(fd, "----    DNS Cache Analytics     -----");
-	LogToFD(fd, "----    Unicast Requests");
-	LogToFD(fd, "Cache Hit: %llu", sCacheRequest_UnicastHitCount);
-	LogToFD(fd, "Cache Miss: %llu", sCacheRequest_UnicastMissCount);
-	LogToFD(fd, "----    Unicast Usage");
-	LogToFD(fd, "Cache Hit: %llu", sCacheUsage_UnicastHitCount);
-	LogToFD(fd, "Cache Miss: %llu", sCacheUsage_UnicastMissCount);
-	LogToFD(fd, "----    Multicast Requests");
-	LogToFD(fd, "Cache Hit: %llu", sCacheRequest_MulticastHitCount);
-	LogToFD(fd, "Cache Miss: %llu", sCacheRequest_MulticastMissCount);
-	LogToFD(fd, "----    Multicast Usage");
-	LogToFD(fd, "Cache Hit: %llu", sCacheUsage_MulticastHitCount);
-	LogToFD(fd, "Cache Miss: %llu", sCacheUsage_MulticastMissCount);
-#endif // CACHE_ANALYTICS
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-	LogToFD(fd, "----    DNS Query Analytics     -----");
-	for (uint8_t i = 0 ; i < e_index_count ; i++ ) {
-		if (s_dns_analytics[i].latency_count > 0) {
-			LogToFD(fd, "----    Network:   %s\n        Transport: %s", _index_to_network_string(i), _index_to_transport_string(i));
-			LogToFD(fd, "Latency: %llums", s_dns_analytics[i].latency_total / s_dns_analytics[i].latency_count);
-			LogToFD(fd, "Query Bytes: %llu", s_dns_analytics[i].query_bytes);
-			LogToFD(fd, "Reply Bytes: %llu", s_dns_analytics[i].reply_bytes);
-			LogToFD(fd, "----    V4");
-			LogToFD(fd, "Queries: %llu", s_dns_analytics[i].v4.queries);
-			LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].v4.reply_pos);
-			LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].v4.reply_neg);
-			LogToFD(fd, "----    V6");
-			LogToFD(fd, "Queries: %llu", s_dns_analytics[i].v6.queries);
-			LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].v6.reply_pos);
-			LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].v6.reply_neg);
-			LogToFD(fd, "----    HTTPS");
-			LogToFD(fd, "Queries: %llu", s_dns_analytics[i].https.queries);
-			LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].https.reply_pos);
-			LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].https.reply_neg);
-		}
-	}
-#endif // DNS_ANALYTICS
-}
-
-#endif // ANALYTICS
diff --git a/mDNSMacOSX/dnssd_analytics.h b/mDNSMacOSX/dnssd_analytics.h
deleted file mode 100644
index 40321aa..0000000
--- a/mDNSMacOSX/dnssd_analytics.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2019 Apple 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.
- */
-
-#ifndef __DNSSD_ANALYTICS_H__
-#define __DNSSD_ANALYTICS_H__
-
-#include "DNSCommon.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include <mdns/resolver.h>
-#endif // QUERIER
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-
-void
-dnssd_analytics_init(void);
-
-void
-dnssd_analytics_log(int fd);
-
-#endif // ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-
-OS_CLOSED_ENUM(dns_transport, uint8_t,
-	dns_transport_Undefined  		= 0,    // Undefined
-	dns_transport_Do53  			= 1,    // DNS over port 53 (UDP or TCP)
-	dns_transport_DoH				= 2,    // DNS over HTTPS
-	dns_transport_DoT				= 3    	// DNS over TLS
-);
-
-void
-dnssd_analytics_update_dns_query_info(bool is_cellular, dns_transport_t transport, uint16_t qtype, uint32_t num_queries,
-	uint32_t latency_ms, bool is_positive_answer);
-
-void
-dnssd_analytics_update_dns_query_size(bool is_cellular, dns_transport_t transport, uint32_t send_bytes);
-
-void
-dnssd_analytics_update_dns_reply_size(bool is_cellular, dns_transport_t transport, uint32_t recv_bytes);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-
-dns_transport_t
-dnssd_analytics_dns_transport_for_resolver_type(mdns_resolver_type_t type);
-
-#endif // QUERIER
-
-#endif // DNS_ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
-
-typedef enum {
-    CacheRequestType_multicast,
-    CacheRequestType_unicast
-} CacheRequestType;
-
-typedef enum {
-    CacheState_hit,
-    CacheState_miss
-} CacheState;
-
-void
-dnssd_analytics_update_cache_request(CacheRequestType inType, CacheState inState);
-
-void
-dnssd_analytics_update_cache_usage_counts(uint32_t inHitMulticastCount, uint32_t inMissMulticastCount,
-	uint32_t inHitUnicastCount, uint32_t inMissUnicastCount);
-
-#endif // CACHE_ANALYTICS
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WAB_ANALYTICS)
-
-typedef enum {
-    WABUsageKind_results,
-    WABUsageKind_session,
-    WABUsageKind_operation
-} WABUsageKind;
-
-typedef enum {
-    WABUsageType_enumeration,
-    WABUsageType_query,
-    WABUsageType_push,
-    WABUsageType_llq
-} WABUsageType;
-
-typedef enum {
-    // Kind: results
-    // Type: enumeration, query, llq
-    WABUsageEvent_positive,
-    WABUsageEvent_negative,
-    WABUsageEvent_null,
-    WABUsageEvent_error,
-
-    // Kind: session
-    // Type: push, llq
-    WABUsageEvent_connected,
-    WABUsageEvent_session,
-    WABUsageEvent_reset,
-    WABUsageEvent_idledOut,
-    WABUsageEvent_goAway,
-    WABUsageEvent_resumedGood,
-    WABUsageEvent_resumedBad,
-
-    // Kind: operation
-    // Type: push, llq
-    WABUsageEvent_succeeded,
-    WABUsageEvent_rejected,
-    WABUsageEvent_dsoni,
-    WABUsageEvent_answered
-} WABUsageEvent;
-
-void
-dnssd_analytics_post_WAB_usage_event_count(WABUsageKind inKind, WABUsageType inType, WABUsageEvent inEvent, uint64_t inEventCount);
-
-#endif // WAB_ANALYTICS
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif // __DNSSD_ANALYTICS_H__
diff --git a/mDNSMacOSX/dnssd_object.h b/mDNSMacOSX/dnssd_object.h
deleted file mode 100644
index 816365b..0000000
--- a/mDNSMacOSX/dnssd_object.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2019-2020 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __DNSSD_OBJECT_H__
-#define __DNSSD_OBJECT_H__
-
-#include "dnssd_private.h"
-
-//======================================================================================================================
-// MARK: - Object Private Method Declarations
-
-char *
-dnssd_object_copy_description(dnssd_any_t object, bool debug, bool privacy);
-
-void
-dnssd_object_finalize(dnssd_any_t object);
-
-#define DNSSD_OBJECT_ALLOC_DECLARE(NAME)		\
-	dnssd_ ## NAME ## _t						\
-	dnssd_object_ ## NAME ## _alloc(size_t size)
-
-DNSSD_OBJECT_ALLOC_DECLARE(getaddrinfo);
-DNSSD_OBJECT_ALLOC_DECLARE(getaddrinfo_result);
-DNSSD_OBJECT_ALLOC_DECLARE(cname_array);
-
-#endif	// __DNSSD_OBJECT_H__
diff --git a/mDNSMacOSX/dnssd_server.c b/mDNSMacOSX/dnssd_server.c
deleted file mode 100644
index d3dfd5a..0000000
--- a/mDNSMacOSX/dnssd_server.c
+++ /dev/null
@@ -1,2532 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "dnssd_server.h"
-
-#include "ClientRequests.h"
-#include "DNSCommon.h"
-#include "dnssd_xpc.h"
-#include "dnssd_svcb.h"
-#include "dnssd_private.h"
-#include "gai_options.h"
-#include "mDNSMacOSX.h"
-#include "termination_reason.h"
-
-#include <bsm/libbsm.h>
-#include <CoreUtils/CommonServices.h>
-#include <CoreUtils/DebugServices.h>
-#include <mach/mach_time.h>
-#include <mdns/alloc.h>
-#include <mdns/mortality.h>
-#include <mdns/resource_record.h>
-#include <mdns/system.h>
-#include <mdns/ticks.h>
-#include <mdns/xpc.h>
-#include <net/necp.h>
-#include <os/lock.h>
-#include <stdatomic.h>
-#include <xpc/private.h>
-
-#include "helpers.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-#include "mdns_trust.h"
-#include <os/feature_private.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-#include "resolved_cache.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-#include <mdns/signed_result.h>
-#endif
-
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Kind Declarations
-
-#define DX_STRUCT(NAME)					struct dx_ ## NAME ## _s
-#define DX_KIND_DECLARE_ABSTRACT(NAME)	typedef DX_STRUCT(NAME) *	dx_ ## NAME ## _t
-#define DX_KIND_DECLARE(NAME)		\
-	DX_KIND_DECLARE_ABSTRACT(NAME)
-
-// Note: The last check checks if the base's type is equal to that of the superkind. If it's not, then the pointer
-// comparison used as the argument to sizeof will cause a "comparison of distinct pointer types" warning, so long as
-// the warning hasn't been disabled.
-
-#define DX_BASE_CHECK(NAME, SUPER)															\
-	check_compile_time(offsetof(DX_STRUCT(NAME), base) == 0);								\
-	check_compile_time(sizeof_field(DX_STRUCT(NAME), base) == sizeof(DX_STRUCT(SUPER)));	\
-	extern int _dx_base_type_check[sizeof(&(((dx_ ## NAME ## _t)0)->base) == ((dx_ ## SUPER ## _t)0))]
-
-#define DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, ...)		\
-	static const struct dx_kind_s _dx_ ## NAME ## _kind = {	\
-		.superkind = &_dx_ ## SUPER ##_kind,				\
-		__VA_ARGS__											\
-	};														\
-	DX_BASE_CHECK(NAME, SUPER)
-
-#define DX_SUBKIND_DEFINE(NAME, SUPER, ...)												\
-	DX_SUBKIND_DEFINE_ABSTRACT(NAME, SUPER, __VA_ARGS__);								\
-																						\
-	static dx_ ## NAME ## _t															\
-	_dx_ ## NAME ## _new(void)															\
-	{																					\
-		const dx_ ## NAME ## _t obj = (dx_ ## NAME ## _t)mdns_calloc(1, sizeof(*obj));	\
-		require_return_value(obj, NULL);												\
-																						\
-		_dx_object_init(obj, &_dx_ ## NAME ## _kind);									\
-		return obj;																		\
-	}																					\
-	extern int _dx_dummy_variable
-
-#define DX_OBJECT_SUBKIND_DEFINE_ABSTRACT(NAME, ...)	DX_SUBKIND_DEFINE_ABSTRACT(NAME, object, __VA_ARGS__)
-#define DX_OBJECT_SUBKIND_DEFINE(NAME, ...)				DX_SUBKIND_DEFINE(NAME, object, __VA_ARGS__)
-
-DX_KIND_DECLARE_ABSTRACT(object);
-DX_KIND_DECLARE(session);
-DX_KIND_DECLARE_ABSTRACT(request);
-DX_KIND_DECLARE(gai_request);
-DX_KIND_DECLARE(gai_result);
-
-#define DX_TRANSPARENT_UNION_MEMBER(NAME)	DX_STRUCT(NAME) *	NAME
-
-typedef union {
-	DX_TRANSPARENT_UNION_MEMBER(object);
-	DX_TRANSPARENT_UNION_MEMBER(session);
-	DX_TRANSPARENT_UNION_MEMBER(request);
-	DX_TRANSPARENT_UNION_MEMBER(gai_request);
-	DX_TRANSPARENT_UNION_MEMBER(gai_result);
-} dx_any_t __attribute__((__transparent_union__));
-
-typedef void
-(*dx_init_f)(dx_any_t object);
-
-typedef void
-(*dx_invalidate_f)(dx_any_t object);
-
-typedef void
-(*dx_finalize_f)(dx_any_t object);
-
-typedef const struct dx_kind_s *	dx_kind_t;
-struct dx_kind_s {
-	dx_kind_t		superkind;	// This kind's superkind. All kinds have a superkind, except the base kind.
-	dx_init_f		init;		// Initializes an object.
-	dx_invalidate_f	invalidate;	// Stops an object's outstanding operations, if any.
-	dx_finalize_f	finalize;	// Releases object's resources right before the object is freed.
-};
-
-//======================================================================================================================
-// MARK: - Object Kind Definition
-
-struct dx_object_s {
-	dx_kind_t			kind;		// The object's kind.
-	_Atomic(int32_t)	ref_count;	// Reference count.
-};
-
-static void
-_dx_object_init(dx_any_t object, dx_kind_t kind);
-
-static void
-_dx_retain(dx_any_t object);
-
-static void
-_dx_release(dx_any_t object);
-#define _dx_forget(X)	ForgetCustom(X, _dx_release)
-
-static void
-_dx_invalidate(dx_any_t object);
-
-static const struct dx_kind_s _dx_object_kind = {
-	.superkind	= NULL,
-	.init		= NULL,
-	.invalidate	= NULL,
-	.finalize	= NULL
-};
-
-//======================================================================================================================
-// MARK: - Session Kind Definition
-
-struct dx_session_s {
-	struct dx_object_s	base;						// Object base;
-	dx_session_t		next;						// Next session in list.
-	dx_request_t		request_list;				// List of outstanding requests.
-	xpc_connection_t	connection;					// Underlying XPC connection.
-	dispatch_source_t	idle_timer;					// Timer for detecting idleness.
-	dispatch_source_t	keepalive_reply_timer;		// Timer for enforcing a time limit on keepalive replies.
-	uint64_t			pending_send_start_ticks;	// Start time in mach ticks of the current pending send condition.
-	audit_token_t		audit_token;				// Client's audit_token.
-	uid_t				client_euid;				// Client's EUID.
-	pid_t				client_pid;					// Client's PID.
-	uint32_t			pending_send_count;			// Count of sent messages that still haven't been processed.
-	char				client_name[MAXCOMLEN];		// Client's process name.
-	bool				terminated;					// True if the session was prematurely ended due to a fatal error.
-	bool				log_pending_send_counts;	// True if pending send counts should be logged.
-};
-
-check_compile_time(sizeof(struct dx_session_s) <= 128);
-
-static void
-_dx_session_invalidate(dx_session_t session);
-
-DX_OBJECT_SUBKIND_DEFINE(session,
-	.invalidate	= _dx_session_invalidate
-);
-
-typedef union {
-	DX_TRANSPARENT_UNION_MEMBER(request);
-	DX_TRANSPARENT_UNION_MEMBER(gai_request);
-} dx_any_request_t __attribute__((__transparent_union__));
-
-//======================================================================================================================
-// MARK: - Request Kind Definition
-
-struct dx_request_s {
-	struct dx_object_s		base;				// Object base.
-	dx_request_t			next;				// Next request in list.
-	dx_session_t			session;			// Back pointer to parent session.
-	xpc_object_t			results;			// Array of pending results.
-	uint64_t				command_id;			// ID to distinquish multiple commands during a session.
-	uint32_t				request_id;			// Request ID, used for logging purposes.
-	DNSServiceErrorType		error;				// Pending error.
-	os_unfair_lock			lock;				// Lock for pending error and results array.
-	bool					sent_error;			// True if the pending error has been sent to client.
-};
-
-static void
-_dx_request_init(dx_request_t request);
-
-static void
-_dx_request_finalize(dx_request_t request);
-
-DX_OBJECT_SUBKIND_DEFINE_ABSTRACT(request,
-	.init		= _dx_request_init,
-	.finalize	= _dx_request_finalize
-);
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Request Kind Definition
-
-OS_CLOSED_OPTIONS(dx_gai_state, uint8_t,
-	dx_gai_state_null						= 0,         // Default null state.
-	dx_gai_state_gai_is_active				= (1U << 0), // Underlying GAI client request is active.
-	dx_gai_state_query_is_active			= (1U << 1), // Underlying SVCB/HTTPS query client request is active.
-	dx_gai_state_waiting_for_a				= (1U << 2), // Currently waiting for an A result. [1]
-	dx_gai_state_waiting_for_aaaa			= (1U << 3), // Currently waiting for a AAAA result. [1]
-	dx_gai_state_service_allowed_failover	= (1U << 4), // Got a result from a DNS service that allows failover.
-	dx_gai_state_failover_mode				= (1U << 5)  // Currently avoiding DNS services that allow failover.
-);
-
-#define DX_GAI_STATE_WAITING_FOR_RESULTS (dx_gai_state_waiting_for_a | dx_gai_state_waiting_for_aaaa)
-
-// Notes:
-// 1. If a client request specifies that DNS services that allow failover be avoided if they're unable to provide
-//    at least one positive response to either the A, AAAA, or HTTPS query, then we have to wait until at least one
-//    positive result is received or until all of the underlying DNSQuestions get negative results before deciding
-//    whether to start providing results to the client (former case), or discarding the current list of pending
-//    results and restarting the underlying DNSQuestions in failover mode (latter case).
-
-struct dx_gai_request_s {
-	struct dx_request_s				base;					// Request object base.
-	GetAddrInfoClientRequest		gai;					// Underlying GAI request.
-	QueryRecordClientRequest		query;					// Underlying SVCB/HTTPS query request.
-	dx_gai_result_t					results;				// List of pending results.
-	char *							hostname;				// Hostname C string to be resolved for getaddrinfo request.
-	mdns_domain_name_t				last_domain_name;		// Domain name of the most recent result.
-	mdns_xpc_string_t				last_tracker_hostname;	// Tracker hostname of the most recent result (XPC string).
-	mdns_xpc_string_t				last_tracker_owner;		// Tracker owner of the most recent result (XPC string).
-	const char *					svcb_name;				// If non-NULL, name of the SVCB/HTTPS record to query for.
-	uuid_t *						resolver_uuid;			// The resolver UUID to use for UUID-scoped requests.
-	mdns_dns_service_id_t			custom_service_id;		// ID for this request's custom DNS service.
-	xpc_object_t					cnames_a;				// Hostname's canonical names for A records (XPC array).
-	ssize_t							cnames_a_expire_idx;	// Index of the first expired canonical name in cnames_a.
-	xpc_object_t					cnames_aaaa;			// Hostname's canonical names for AAAA records (XPC array).
-	ssize_t							cnames_aaaa_expire_idx;	// Index of the first expired canonical name in cnames_aaaa.
-	audit_token_t *					delegator_audit_token;	// The delegator's audit token.
-	xpc_object_t					fallback_dns_config;	// Fallback DNS configuration.
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-	mdns_trust_t					trust;					// Trust instance if status is mdns_trust_status_pending
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_signed_resolve_result_t	signed_resolve;			// Signed resolve result with which to sign results.
-#endif
-	char *							svcb_name_memory;		// Memory that was allocated for svcb_name.
-	DNSServiceFlags					flags;					// The request's flags parameter.
-	uint32_t						ifindex;				// The interface index to use for interface-scoped requests.
-	DNSServiceProtocol				protocols;				// Used to specify IPv4, IPv6, or any IP address types.
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-	dnssd_log_privacy_level_t		log_privacy_level;		// The log privacy level of this request.
-#endif
-	pid_t							effective_pid;			// Effective client PID.
-	uuid_t							effective_uuid;			// Effective client UUID.
-	uint16_t						svcb_type;				// If svcb_name is non-NULL, the type for SVCB/HTTPS query.
-	dx_gai_state_t					state;					// Collection of state bits.
-	mdns_gai_options_t				options;				// Additional request options.
-	bool							cnames_a_changed;		// True if cnames_a has changed.
-	bool							cnames_aaaa_changed;	// True if cnames_aaaa has changed.
-};
-
-check_compile_time(sizeof(struct dx_gai_request_s) <= 1560);
-
-typedef xpc_object_t
-(*dx_request_take_results_f)(dx_any_request_t request);
-
-typedef const struct dx_request_kind_s * dx_request_kind_t;
-struct dx_request_kind_s {
-	struct dx_kind_s			base;
-	dx_request_take_results_f	take_results;
-};
-
-#define DX_REQUEST_SUBKIND_DEFINE(NAME, ...)														\
-	static void																						\
-	_dx_ ## NAME ## _request_init(dx_ ## NAME ## _request_t request);								\
-																									\
-	static void																						\
-	_dx_ ## NAME ## _request_invalidate(dx_ ## NAME ## _request_t request);							\
-																									\
-	static void																						\
-	_dx_ ## NAME ## _request_finalize(dx_ ## NAME ## _request_t request);							\
-																									\
-	static const struct dx_request_kind_s _dx_ ## NAME ## _request_kind = {							\
-		.base = {																					\
-			.superkind	= &_dx_request_kind,														\
-			.invalidate	= _dx_ ## NAME ## _request_invalidate,										\
-			.finalize	= _dx_ ## NAME ## _request_finalize											\
-		},																							\
-		__VA_ARGS__																					\
-	};																								\
-																									\
-	static dx_ ## NAME ## _request_t																\
-	_dx_ ## NAME ## _request_new(void)																\
-	{																								\
-		dx_ ## NAME ## _request_t obj = (dx_ ## NAME ## _request_t)mdns_calloc(1, sizeof(*obj));	\
-		require_return_value(obj, NULL);															\
-																									\
-		_dx_object_init(obj, &_dx_ ## NAME ## _request_kind.base);									\
-		return obj;																					\
-	}																								\
-	DX_BASE_CHECK(NAME ## _request, request)
-
-static void
-_dx_gai_request_init(dx_gai_request_t request);
-
-static xpc_object_t
-_dx_gai_request_take_results(dx_gai_request_t request);
-
-DX_REQUEST_SUBKIND_DEFINE(gai,
-	.base.init		= _dx_gai_request_init,
-	.take_results	= _dx_gai_request_take_results
-);
-
-//======================================================================================================================
-// MARK: - Result Kind Definition
-
-#define DNSSD_AUTHENTICATION_TAG_SIZE	32 // Defined here until an NECP header defines this length.
-typedef uint8_t dx_auth_tag_t[DNSSD_AUTHENTICATION_TAG_SIZE];
-
-struct dx_gai_result_s {
-	struct dx_object_s				base;				// Object base.
-	dx_gai_result_t					next;				// Next result in list.
-	mdns_resource_record_t			record;				// Result's resource record.
-	mdns_xpc_string_t				provider_name;		// The DNS service's provider name, if any.
-	xpc_object_t					cname_update;		// If non-NULL, XPC array to use for a CNAME chain update.
-	mdns_xpc_string_t				tracker_hostname;	// If non-NULL, tracker hostname as an XPC string.
-	mdns_xpc_string_t				tracker_owner;		// If non-NULL, owner of the tracker hostname as an XPC string.
-	dx_auth_tag_t *					auth_tag;			// Optional authentication tag for hostname+IP addresses.
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_signed_hostname_result_t	signed_hostname;	// Signed hostname result.
-#endif
-	DNSServiceFlags					flags;				// The result's flags.
-	dnssd_negative_reason_t			negative_reason;	// Reason code for negative results.
-	DNSServiceErrorType				error;				// Error returned by mDNS core.
-	uint32_t						ifindex;			// The interface index associated with the result.
-	mdns_resolver_type_t			protocol;			// The transport protocol used to obtain the record.
-	uint16_t						question_id;		// ID of DNSQuestion used to get result. Used for logging.
-	bool							tracker_is_approved;// True if the assoicated tracker is approved for the client.
-};
-
-static void
-_dx_gai_result_finalize(dx_gai_result_t result);
-
-DX_OBJECT_SUBKIND_DEFINE(gai_result,
-	.finalize = _dx_gai_result_finalize
-);
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static dispatch_queue_t
-_dx_server_queue(void);
-
-static void
-_dx_server_handle_new_connection(xpc_connection_t connection);
-
-static void
-_dx_server_register_session(dx_session_t session);
-
-static void
-_dx_server_deregister_session(dx_session_t session);
-
-static void
-_dx_server_check_sessions(void);
-
-static dx_session_t
-_dx_session_create(xpc_connection_t connection);
-
-static void
-_dx_session_activate(dx_session_t session);
-
-static void
-_dx_session_handle_message(dx_session_t session, xpc_object_t msg);
-
-static DNSServiceErrorType
-_dx_session_handle_getaddrinfo_command(dx_session_t session, xpc_object_t msg);
-
-static DNSServiceErrorType
-_dx_session_handle_stop_command(dx_session_t session, xpc_object_t msg);
-
-static void
-_dx_session_append_request(dx_session_t session, dx_any_request_t any);
-
-static void
-_dx_session_check(dx_session_t session, uint64_t now_ticks);
-
-static void
-_dx_session_send_message(dx_session_t session, xpc_object_t msg);
-
-static void
-_dx_session_terminate(dx_session_t session, mdns_termination_reason_t reason);
-
-static void
-_dx_session_reset_idle_timer(dx_session_t session);
-
-static void
-_dx_session_log_error(dx_session_t session, DNSServiceErrorType error);
-
-static void
-_dx_session_log_pending_send_count_increase(dx_session_t session);
-
-static void
-_dx_session_log_pending_send_count_decrease(dx_session_t session);
-
-static void
-_dx_session_log_termination(dx_session_t session, mdns_termination_reason_t reason);
-
-static xpc_object_t
-_dx_request_take_results(dx_request_t request);
-
-typedef void (^dx_block_t)(void);
-
-static void
-_dx_request_locked(dx_any_request_t request, dx_block_t block);
-
-static DNSServiceErrorType
-_dx_request_get_error(dx_any_request_t request);
-
-static bool
-_dx_request_set_error(dx_any_request_t request, DNSServiceErrorType error);
-
-static bool
-_dx_request_send_pending_error(dx_any_request_t request);
-
-static dx_gai_request_t
-_dx_gai_request_create(uint64_t command_id, dx_session_t session);
-
-static DNSServiceErrorType
-_dx_gai_request_activate(dx_gai_request_t request);
-
-static DNSServiceErrorType
-_dx_gai_request_start_client_requests(dx_gai_request_t request, bool need_lock);
-
-static DNSServiceErrorType
-_dx_gai_request_parse_params(dx_gai_request_t request, xpc_object_t params);
-
-static DNSServiceErrorType
-_dx_gai_request_start_client_requests_internal(dx_gai_request_t request, GetAddrInfoClientRequestParams *gai_params,
-	QueryRecordClientRequestParams *query_params, bool need_lock);
-
-static void
-_dx_gai_request_stop_client_requests(dx_gai_request_t request, bool need_lock);
-
-static void
-_dx_gai_request_restart_client_requests_in_failover_mode(dx_gai_request_t request);
-
-static xpc_object_t *
-_dx_gai_request_get_cnames_ptr(dx_gai_request_t request, int qtype, bool **out_changed_ptr,
-	ssize_t **out_expire_idx_ptr);
-
-static void
-_dx_gai_request_append_cname(dx_gai_request_t request, int qtype, const domainname *cname, bool expired, bool unwind);
-#define _dx_gai_request_unwind_cnames_if_necessary(R, T)	_dx_gai_request_append_cname(R, T, NULL, false, true)
-
-static xpc_object_t
-_dx_gai_request_copy_cname_update(dx_gai_request_t request, int qtype);
-
-static void
-_dx_gai_request_gai_result_handler(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result qc_result,
-	DNSServiceErrorType error, void *context);
-
-static void
-_dx_gai_request_query_result_handler(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result qc_result,
-	DNSServiceErrorType error, void *context);
-
-static void
-_dx_gai_request_enqueue_result(dx_gai_request_t request, QC_result qc_result, const ResourceRecord *answer,
-	bool answer_is_expired, const uint8_t *rdata_ptr, uint16_t rdata_len, DNSServiceErrorType error,
-	const DNSQuestion *q);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-static const uint8_t *
-_dx_gai_request_get_resolver_uuid(xpc_object_t params);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-static bool
-_dx_gai_request_is_for_in_app_browser(xpc_object_t params);
-#endif
-
-static void
-_dx_gai_request_log_start(dx_gai_request_t request, pid_t delegator_pid, const uuid_t delegator_uuid);
-
-static void
-_dx_gai_request_log_stop(dx_gai_request_t request);
-
-static void
-_dx_gai_request_log_error(dx_gai_request_t request, DNSServiceErrorType error);
-
-static bool
-_dx_gai_request_check_for_failover_restart(dx_gai_request_t request, const ResourceRecord *answer,
-	bool answer_is_expired, bool answer_is_positive);
-
-static void
-_dx_gai_result_list_forget(dx_gai_result_t *list_ptr);
-
-static xpc_object_t
-_dx_gai_result_to_dictionary(dx_gai_result_t result);
-
-static void
-_dx_gai_result_log(dx_gai_result_t result, uint32_t request_id);
-
-static bool
-_dx_authenticate_address_rdata(uuid_t effective_uuid, const char *hostname, int type, const uint8_t *rdata,
-	uint8_t out_auth_tag[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE]);
-
-static void
-_dx_kqueue_locked(const char *description, bool need_lock, dx_block_t block);
-
-static void
-_dx_replace_domain_name(mdns_domain_name_t *ptr, const domainname *name);
-
-static bool
-_dx_qc_result_is_add(QC_result qc_result);
-
-static bool
-_dx_qc_result_is_suppressed(QC_result qc_result);
-
-//======================================================================================================================
-// MARK: - Logging
-
-MDNS_LOG_CATEGORY_DEFINE(server, "dnssd_server");
-
-//======================================================================================================================
-// MARK: - Globals
-
-static dx_session_t	g_session_list = NULL;
-
-//======================================================================================================================
-// MARK: - Server Functions
-
-mDNSexport void
-dnssd_server_init(void)
-{
-	static dispatch_once_t	s_once = 0;
-	static xpc_connection_t	s_listener = NULL;
-
-	dispatch_once(&s_once,
-	^{
-		s_listener = xpc_connection_create_mach_service(DNSSD_MACH_SERVICE_NAME, _dx_server_queue(),
-			XPC_CONNECTION_MACH_SERVICE_LISTENER);
-		xpc_connection_set_event_handler(s_listener,
-		^(xpc_object_t event)
-		{
-			if (xpc_get_type(event) == XPC_TYPE_CONNECTION) {
-				_dx_server_handle_new_connection((xpc_connection_t)event);
-			}
-		});
-		xpc_connection_activate(s_listener);
-	});
-}
-
-//======================================================================================================================
-
-mDNSexport void
-dnssd_server_idle(void)
-{
-	static dispatch_once_t		s_once = 0;
-	static dispatch_source_t	s_source = NULL;
-	dispatch_once(&s_once,
-	^{
-		s_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0, _dx_server_queue());
-		dispatch_source_set_event_handler(s_source,
-		^{
-			_dx_server_check_sessions();
-		});
-		dispatch_activate(s_source);
-	});
-	dispatch_source_merge_data(s_source, 1);
-}
-
-//======================================================================================================================
-
-uint32_t
-dnssd_server_get_new_request_id(void)
-{
-	static _Atomic(uint32_t) s_next_id = 1;
-	return atomic_fetch_add(&s_next_id, 1);
-}
-
-//======================================================================================================================
-
-static dispatch_queue_t
-_dx_server_queue(void)
-{
-	static dispatch_once_t	once	= 0;
-	static dispatch_queue_t	queue	= NULL;
-
-	dispatch_once(&once,
-	^{
-		const dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
-			QOS_CLASS_USER_INITIATED, 0);
-		queue = dispatch_queue_create("com.apple.dnssd.server", attr);
-	});
-	return queue;
-}
-
-//======================================================================================================================
-
-static void
-_dx_server_handle_new_connection(const xpc_connection_t connection)
-{
-	dx_session_t session = _dx_session_create(connection);
-	if (session) {
-		_dx_session_activate(session);
-		_dx_server_register_session(session);
-		_dx_forget(&session);
-	} else {
-		xpc_connection_cancel(connection);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_server_register_session(dx_session_t session)
-{
-	dx_session_t *ptr = &g_session_list;
-	while (*ptr) {
-		ptr = &(*ptr)->next;
-	}
-	session->next = NULL;
-	*ptr = session;
-	_dx_retain(*ptr);
-}
-
-//======================================================================================================================
-
-static void
-_dx_server_deregister_session(dx_session_t session)
-{
-	dx_session_t *ptr = &g_session_list;
-	while (*ptr && (*ptr != session)) {
-		ptr = &(*ptr)->next;
-	}
-	if (*ptr) {
-		*ptr = session->next;
-		session->next = NULL;
-		_dx_forget(&session);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_server_check_sessions(void)
-{
-	if (g_session_list) {
-		const uint64_t now_ticks = mach_absolute_time();
-		for (dx_session_t session = g_session_list; session; session = session->next) {
-			_dx_session_check(session, now_ticks);
-		}
-	}
-}
-
-//======================================================================================================================
-// MARK: - Object Methods
-
-static void
-_dx_recursive_init(dx_object_t object, dx_kind_t kind);
-
-static void
-_dx_object_init(const dx_object_t me, const dx_kind_t kind)
-{
-	me->kind = kind;
-	atomic_store_explicit(&me->ref_count, 1, memory_order_relaxed);
-	_dx_recursive_init(me, me->kind);
-}
-
-static void
-_dx_recursive_init(const dx_object_t me, const dx_kind_t kind)
-{
-	if (kind->superkind) {
-		_dx_recursive_init(me, kind->superkind);
-	}
-	if (kind->init) {
-		kind->init(me);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_retain(const dx_any_t any)
-{
-	const dx_object_t me = any.object;
-	atomic_fetch_add(&me->ref_count, 1);
-}
-
-//======================================================================================================================
-
-static void
-_dx_finalize(dx_object_t object);
-
-static void
-_dx_release(const dx_any_t any)
-{
-	dx_object_t me = any.object;
-	if (atomic_fetch_sub(&me->ref_count, 1) == 1) {
-		_dx_finalize(me);
-		ForgetMem(&me);
-	}
-}
-
-static void
-_dx_finalize(const dx_object_t me)
-{
-	for (dx_kind_t kind = me->kind; kind; kind = kind->superkind) {
-		if (kind->finalize) {
-			kind->finalize(me);
-		}
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_invalidate(const dx_any_t any)
-{
-	const dx_object_t me = any.object;
-	for (dx_kind_t kind = me->kind; kind; kind = kind->superkind) {
-		if (kind->invalidate) {
-			kind->invalidate(me);
-			return;
-		}
-	}
-}
-
-//======================================================================================================================
-// MARK: - Session Methods
-
-static dx_session_t
-_dx_session_create(const xpc_connection_t connection)
-{
-	const dx_session_t obj = _dx_session_new();
-	require_quiet(obj, exit);
-
-	obj->connection = connection;
-	xpc_retain(obj->connection);
-	xpc_connection_get_audit_token(obj->connection, &obj->audit_token);
-	obj->client_pid  = xpc_connection_get_pid(obj->connection);
-	obj->client_euid = xpc_connection_get_euid(obj->connection);
-	mdns_system_pid_to_name(obj->client_pid, obj->client_name);
-
-exit:
-	return obj;
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_activate(const dx_session_t me)
-{
-	_dx_retain(me);
-	xpc_connection_set_target_queue(me->connection, _dx_server_queue());
-	xpc_connection_set_event_handler(me->connection,
-	^(const xpc_object_t event) {
-		const xpc_type_t type = xpc_get_type(event);
-		if (type == XPC_TYPE_DICTIONARY) {
-			if (me->connection) {
-				_dx_session_handle_message(me, event);
-			}
-		} else if (event == XPC_ERROR_CONNECTION_INVALID) {
-			_dx_server_deregister_session(me);
-			_dx_session_invalidate(me);
-			_dx_release(me);
-		} else {
-			xpc_connection_forget(&me->connection);
-		}
-	});
-	xpc_connection_activate(me->connection);
-	_dx_session_reset_idle_timer(me);
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_invalidate(const dx_session_t me)
-{
-	xpc_connection_forget(&me->connection);
-	dispatch_source_forget(&me->idle_timer);
-	dispatch_source_forget(&me->keepalive_reply_timer);
-	dx_request_t req;
-	while ((req = me->request_list) != NULL)
-	{
-		me->request_list = req->next;
-		_dx_invalidate(req);
-		_dx_release(req);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_handle_message(const dx_session_t me, const xpc_object_t msg)
-{
-	DNSServiceErrorType err;
-	const char * const command = dnssd_xpc_message_get_command(msg);
-	require_action_quiet(command, exit, err = kDNSServiceErr_BadParam);
-
-	if (strcmp(command, DNSSD_COMMAND_GETADDRINFO) == 0) {
-		err = _dx_session_handle_getaddrinfo_command(me, msg);
-	} else if (strcmp(command, DNSSD_COMMAND_STOP) == 0) {
-		err = _dx_session_handle_stop_command(me, msg);
-	} else {
-		err = kDNSServiceErr_BadParam;
-	}
-
-exit:
-	_dx_session_reset_idle_timer(me);
-	xpc_object_t reply = xpc_dictionary_create_reply(msg);
-	if (likely(reply)) {
-		dnssd_xpc_message_set_error(reply, err);
-		_dx_session_send_message(me, reply);
-		xpc_forget(&reply);
-	} else {
-		_dx_session_terminate(me, mdns_termination_reason_client_error);
-	}
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_session_handle_getaddrinfo_command(const dx_session_t me, const xpc_object_t msg)
-{
-	dx_gai_request_t req = NULL;
-	bool valid;
-	DNSServiceErrorType err;
-	const uint64_t command_id = dnssd_xpc_message_get_id(msg, &valid);
-	require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
-
-	const xpc_object_t params = dnssd_xpc_message_get_parameters(msg);
-	require_action_quiet(params, exit, err = kDNSServiceErr_BadParam);
-
-	req = _dx_gai_request_create(command_id, me);
-	require_action_quiet(req, exit, err = kDNSServiceErr_NoMemory);
-
-	err = _dx_gai_request_parse_params(req, params);
-	require_noerr_quiet(err, exit);
-
-	err = _dx_gai_request_activate(req);
-	require_noerr_quiet(err, exit);
-
-	_dx_session_append_request(me, req);
-
-exit:
-	if (err) {
-		if (req) {
-			_dx_gai_request_log_error(req, err);
-		} else {
-			_dx_session_log_error(me, err);
-		}
-	}
-	_dx_forget(&req);
-	return err;
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_session_handle_stop_command(const dx_session_t me, const xpc_object_t msg)
-{
-	bool valid;
-	DNSServiceErrorType err;
-	const uint64_t command_id = dnssd_xpc_message_get_id(msg, &valid);
-	require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
-
-	dx_request_t *ptr;
-	dx_request_t req;
-	for (ptr = &me->request_list; (req = *ptr) != NULL; ptr = &req->next) {
-		if (req->command_id == command_id) {
-			break;
-		}
-	}
-	require_action_quiet(req, exit, err = kDNSServiceErr_BadReference);
-
-	*ptr = req->next;
-	req->next = NULL;
-	_dx_invalidate(req);
-	_dx_forget(&req);
-	err = kDNSServiceErr_NoError;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_append_request(const dx_session_t me, const dx_any_request_t any)
-{
-	dx_request_t *ptr = &me->request_list;
-	while (*ptr) {
-		ptr = &(*ptr)->next;
-	}
-	const dx_request_t req = any.request;
-	req->next = NULL;
-	*ptr = req;
-	_dx_retain(*ptr);
-}
-
-//======================================================================================================================
-
-#define DX_SESSION_BACK_PRESSURE_TIMEOUT_SECS	5
-
-static void
-_dx_session_check(const dx_session_t me, const uint64_t now_ticks)
-{
-	require_return(me->connection);
-
-	xpc_object_t results = NULL;
-	mdns_termination_reason_t terminate_reason;
-	if (me->pending_send_count > 0) {
-		const uint64_t elapsed_secs = (now_ticks - me->pending_send_start_ticks) / mdns_mach_ticks_per_second();
-		require_action_quiet(elapsed_secs < DX_SESSION_BACK_PRESSURE_TIMEOUT_SECS, exit,
-			terminate_reason = mdns_termination_reason_back_pressure);
-	}
-	for (dx_request_t req = me->request_list; req; req = req->next) {
-		results = _dx_request_take_results(req);
-		if (results) {
-			xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
-			require_action_quiet(msg, exit, terminate_reason = mdns_termination_reason_server_error);
-
-			dnssd_xpc_message_set_id(msg, req->command_id);
-			dnssd_xpc_message_set_error(msg, kDNSServiceErr_NoError);
-			dnssd_xpc_message_set_results(msg, results);
-			xpc_forget(&results);
-			_dx_session_send_message(me, msg);
-			xpc_forget(&msg);
-		}
-		const bool ok = _dx_request_send_pending_error(req);
-		require_action_quiet(ok, exit, terminate_reason = mdns_termination_reason_server_error);
-	}
-	terminate_reason = mdns_termination_reason_none;
-
-exit:
-	if (terminate_reason != mdns_termination_reason_none) {
-		_dx_session_terminate(me, terminate_reason);
-	}
-	xpc_forget(&results);
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_send_message(const dx_session_t me, const xpc_object_t msg)
-{
-	require_return(me->connection);
-
-	xpc_connection_send_message(me->connection, msg);
-	++me->pending_send_count;
-	if (me->pending_send_count == 1) {
-		me->pending_send_start_ticks = mach_absolute_time();
-	} else {
-		if (me->pending_send_count == 2) {
-			me->log_pending_send_counts = true;
-		}
-		_dx_session_log_pending_send_count_increase(me);
-	}
-	_dx_retain(me);
-	xpc_connection_send_barrier(me->connection,
-	^{
-		--me->pending_send_count;
-		if (me->log_pending_send_counts) {
-			_dx_session_log_pending_send_count_decrease(me);
-		}
-		if (me->pending_send_count == 0) {
-			me->log_pending_send_counts = false;
-		}
-		_dx_release(me);
-	});
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_terminate(const dx_session_t me, const mdns_termination_reason_t reason)
-{
-	if (!me->terminated) {
-		_dx_session_log_termination(me, reason);
-		xpc_connection_forget(&me->connection);
-		me->terminated = true;
-	}
-}
-
-//======================================================================================================================
-
-static dispatch_source_t
-_dx_create_oneshot_timer(const uint32_t interval_ms, const unsigned int leeway_percent_numerator)
-{
-	const dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _dx_server_queue());
-	require_quiet(timer, exit);
-
-	const unsigned int numerator = Min(leeway_percent_numerator, 100);
-	const uint64_t leeway_ns = interval_ms * (numerator * (UINT64_C_safe(kNanosecondsPerMillisecond) / 100));
-	dispatch_source_set_timer(timer, dispatch_time_milliseconds(interval_ms), DISPATCH_TIME_FOREVER, leeway_ns);
-
-exit:
-	return timer;
-}
-
-//======================================================================================================================
-
-#define DX_SESSION_KEEPALIVE_TIMEOUT_MS	(5 * kMillisecondsPerSecond)
-
-static void
-_dx_session_send_keepalive_message(const dx_session_t me)
-{
-	require_return(me->connection && !me->keepalive_reply_timer);
-
-	static xpc_object_t s_keepalive_msg = NULL;
-	if (!s_keepalive_msg) {
-		s_keepalive_msg = xpc_dictionary_create_empty();
-		require_return(s_keepalive_msg);
-
-		dnssd_xpc_message_set_command(s_keepalive_msg, DNSSD_COMMAND_KEEPALIVE);
-	}
-	me->keepalive_reply_timer = _dx_create_oneshot_timer(DX_SESSION_KEEPALIVE_TIMEOUT_MS, 5);
-	require_return(me->keepalive_reply_timer);
-
-	_dx_retain(me);
-	xpc_connection_send_message_with_reply(me->connection, s_keepalive_msg, _dx_server_queue(),
-	^(xpc_object_t reply)
-	{
-		if (me->connection && (xpc_get_type(reply) == XPC_TYPE_DICTIONARY)) {
-			dispatch_source_forget(&me->keepalive_reply_timer);
-			_dx_session_reset_idle_timer(me);
-		}
-		_dx_release(me);
-	});
-	dispatch_source_set_event_handler(me->keepalive_reply_timer,
-	^{
-		dispatch_source_forget(&me->keepalive_reply_timer);
-		_dx_session_terminate(me, mdns_termination_reason_keepalive_timeout);
-	});
-	dispatch_activate(me->keepalive_reply_timer);
-}
-
-//======================================================================================================================
-
-#define DX_SESSION_IDLE_TIMEOUT_WITH_REQUESTS_MS	(1 * kSecondsPerMinute * kMillisecondsPerSecond)
-#define DX_SESSION_IDLE_TIMEOUT_WITHOUT_REQUESTS_MS	(5 * kSecondsPerMinute * kMillisecondsPerSecond)
-
-static void
-_dx_session_reset_idle_timer(const dx_session_t me)
-{
-	require_return(!me->keepalive_reply_timer);
-
-	dispatch_source_forget(&me->idle_timer);
-	uint32_t idle_interval_ms;
-	if (me->request_list) {
-		idle_interval_ms = DX_SESSION_IDLE_TIMEOUT_WITH_REQUESTS_MS;
-	} else {
-		idle_interval_ms = DX_SESSION_IDLE_TIMEOUT_WITHOUT_REQUESTS_MS;
-	}
-	me->idle_timer = _dx_create_oneshot_timer(idle_interval_ms, 5);
-	require_return(me->idle_timer);
-
-	dispatch_source_set_event_handler(me->idle_timer,
-	^{
-		dispatch_source_forget(&me->idle_timer);
-		if (me->request_list) {
-			_dx_session_send_keepalive_message(me);
-		} else {
-			_dx_session_terminate(me, mdns_termination_reason_idle);
-		}
-	});
-	dispatch_activate(me->idle_timer);
-}
-
-//======================================================================================================================
-
-static bool
-_dx_session_has_entitlement(const dx_session_t me, const char * const entitlement)
-{
-	bool entitled = false;
-	if (me->connection) {
-		entitled = mdns_xpc_connection_is_entitled(me->connection, entitlement);
-	}
-	return entitled;
-}
-
-//======================================================================================================================
-
-static bool
-_dx_session_has_delegate_entitlement(const dx_session_t me)
-{
-	return _dx_session_has_entitlement(me, "com.apple.private.network.socket-delegate");
-}
-
-//======================================================================================================================
-
-static bool
-_dx_session_has_prohibit_encrypted_dns_entitlement(const dx_session_t me)
-{
-	return _dx_session_has_entitlement(me, "com.apple.private.dnssd.prohibit-encrypted-dns");
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_log_error(const dx_session_t me, const DNSServiceErrorType error)
-{
-	os_log_error(_mdns_server_log(),
-		"XPC session error -- error: %{mdns:err}ld, client pid: %lld (%{public}s)",
-		(long)error, (long long)me->client_pid, me->client_name);
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_log_pending_send_count_increase(const dx_session_t me)
-{
-	os_log_debug(_mdns_server_log(),
-		"XPC session to client with pid %lld (%{public}s) pending send count increased to %d",
-		(long long)me->client_pid, me->client_name, me->pending_send_count);
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_log_pending_send_count_decrease(const dx_session_t me)
-{
-	os_log_debug(_mdns_server_log(),
-		"XPC session to client with pid %lld (%{public}s) pending send count decreased to %d",
-		(long long)me->client_pid, me->client_name, me->pending_send_count);
-}
-
-//======================================================================================================================
-
-static void
-_dx_session_log_termination(const dx_session_t me, const mdns_termination_reason_t reason)
-{
-	os_log_with_type(_mdns_server_log(),
-		(reason == mdns_termination_reason_idle) ? OS_LOG_TYPE_INFO : OS_LOG_TYPE_DEFAULT,
-		"Session terminated -- reason: %{mdns:termination_reason}d, pending send count: %u, client pid: %lld "
-		"(%{public}s)",
-		reason, me->pending_send_count, (long long)me->client_pid, me->client_name);
-}
-
-//======================================================================================================================
-// MARK: - Request Methods
-
-static void
-_dx_request_init(const dx_request_t me)
-{
-	me->request_id	= dnssd_server_get_new_request_id();
-	me->lock		= OS_UNFAIR_LOCK_INIT;
-}
-
-//======================================================================================================================
-
-static void
-_dx_request_finalize(const dx_request_t me)
-{
-	_dx_forget(&me->session);
-	xpc_forget(&me->results);
-}
-
-//======================================================================================================================
-
-static xpc_object_t
-_dx_request_take_results(const dx_request_t me)
-{
-	const dx_request_kind_t kind = (dx_request_kind_t)me->base.kind;
-	if (kind->take_results) {
-		return kind->take_results(me);
-	} else {
-		return NULL;
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_request_locked(const dx_any_request_t any, const dx_block_t block)
-{
-	const dx_request_t me = any.request;
-	os_unfair_lock_lock(&me->lock);
-	block();
-	os_unfair_lock_unlock(&me->lock);
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_request_get_error(const dx_any_request_t any)
-{
-	const dx_request_t me = any.request;
-	__block DNSServiceErrorType error;
-	_dx_request_locked(me,
-	^{
-		error = me->error;
-	});
-	return error;
-}
-
-//======================================================================================================================
-
-static bool
-_dx_request_set_error(const dx_any_request_t any, const DNSServiceErrorType error)
-{
-	__block bool did_set = false;
-	if (error) {
-		const dx_request_t me = any.request;
-		_dx_request_locked(me,
-		^{
-			if (!me->error) {
-				me->error = error;
-				did_set = true;
-			}
-		});
-	}
-	return did_set;
-}
-
-//======================================================================================================================
-
-static bool
-_dx_request_send_pending_error(const dx_any_request_t any)
-{
-	bool ok = false;
-	const dx_request_t me = any.request;
-	const DNSServiceErrorType error = _dx_request_get_error(me);
-	if (error && !me->sent_error) {
-		xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
-		require_quiet(msg, exit);
-
-		dnssd_xpc_message_set_id(msg, me->command_id);
-		dnssd_xpc_message_set_error(msg, error);
-		_dx_session_send_message(me->session, msg);
-		xpc_forget(&msg);
-		me->sent_error = true;
-	}
-	ok = true;
-
-exit:
-	return ok;
-}
-
-//======================================================================================================================
-// MARK: - GetAddrInfo Request Methods
-
-static dx_gai_request_t
-_dx_gai_request_create(const uint64_t command_id, const dx_session_t session)
-{
-	dx_gai_request_t obj = _dx_gai_request_new();
-	require_quiet(obj, exit);
-
-	obj->base.command_id = command_id;
-	obj->base.session    = session;
-	_dx_retain(obj->base.session);
-
-exit:
-	return obj;
-}
-
-//======================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-static DNSServiceErrorType
-_dx_gai_request_trust_check(dx_gai_request_t request, bool *out_defer_start);
-#endif
-
-static DNSServiceErrorType
-_dx_gai_request_activate(const dx_gai_request_t me)
-{
-	DNSServiceErrorType err;
-	bool defer_start = false;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-	bool privacy_check_done = false;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	privacy_check_done = (me->signed_resolve != NULL);
-#endif
-	if (!privacy_check_done && os_feature_enabled(mDNSResponder, bonjour_privacy)) {
-		err = _dx_gai_request_trust_check(me, &defer_start);
-		require_noerr_quiet(err, exit);
-	}
-#endif
-	if (!defer_start) {
-		err = _dx_gai_request_start_client_requests(me, true);
-		require_noerr_quiet(err, exit);
-	}
-	err = kDNSServiceErr_NoError;
-
-exit:
-	return err;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-static DNSServiceErrorType
-_dx_gai_request_trust_check(const dx_gai_request_t me, bool * const out_defer_start)
-{
-	DNSServiceErrorType err;
-	bool defer_start = false;
-	const dx_session_t session = me->base.session;
-	mdns_trust_flags_t flags = mdns_trust_flags_none;
-	const mdns_trust_status_t status = mdns_trust_check_getaddrinfo(session->audit_token, me->hostname, &flags);
-	switch (status) {
-		case mdns_trust_status_granted:
-			err = kDNSServiceErr_NoError;
-			break;
-
-		case mdns_trust_status_denied:
-		case mdns_trust_status_pending:
-			me->trust = mdns_trust_create(session->audit_token, NULL, flags);
-			require_action_quiet(me->trust, exit, err = kDNSServiceErr_NoMemory);
-
-			_dx_retain(me);
-			mdns_trust_set_queue(me->trust, _dx_server_queue());
-			mdns_trust_set_event_handler(me->trust,
-			^(const mdns_trust_event_t event, const mdns_trust_status_t update)
-			{
-				if (me->trust && (event == mdns_trust_event_result)) {
-					DNSServiceErrorType handler_err;
-					if (update == mdns_trust_status_granted) {
-						handler_err = _dx_gai_request_start_client_requests(me, true);
-					} else {
-						handler_err = kDNSServiceErr_PolicyDenied;
-					}
-					if (handler_err && _dx_request_set_error(me, handler_err)) {
-						_dx_gai_request_log_error(me, handler_err);
-						_dx_request_send_pending_error(me);
-					}
-				}
-				mdns_forget(&me->trust);
-				_dx_release(me);
-			});
-			mdns_trust_activate(me->trust);
-			defer_start = true;
-			err = kDNSServiceErr_NoError;
-			break;
-
-		case mdns_trust_status_no_entitlement:
-			err = kDNSServiceErr_NoAuth;
-			break;
-
-		CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-		default:
-		CUClangWarningIgnoreEnd();
-			err = kDNSServiceErr_Unknown;
-			break;
-	}
-
-exit:
-	if (out_defer_start) {
-		*out_defer_start = defer_start;
-	}
-	return err;
-}
-#endif
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_init(const dx_gai_request_t me)
-{
-	me->cnames_a_expire_idx    = -1;
-	me->cnames_aaaa_expire_idx = -1;
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_invalidate(const dx_gai_request_t me)
-{
-	_dx_gai_request_log_stop(me);
-	_dx_gai_request_stop_client_requests(me, true);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-	if (me->custom_service_id != MDNS_DNS_SERVICE_INVALID_ID) {
-		Querier_DeregisterCustomDNSService(me->custom_service_id);
-		me->custom_service_id = MDNS_DNS_SERVICE_INVALID_ID;
-	}
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-	mdns_trust_forget(&me->trust);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_forget(&me->signed_resolve);
-#endif
-	mdns_forget(&me->last_domain_name);
-	mdns_xpc_string_forget(&me->last_tracker_hostname);
-	mdns_xpc_string_forget(&me->last_tracker_owner);
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_finalize(const dx_gai_request_t me)
-{
-	_dx_gai_result_list_forget(&me->results);
-	ForgetMem(&me->hostname);
-	ForgetMem(&me->svcb_name_memory);
-	xpc_forget(&me->cnames_a);
-	xpc_forget(&me->cnames_aaaa);
-	ForgetMem(&me->delegator_audit_token);
-	xpc_forget(&me->fallback_dns_config);
-	ForgetMem(&me->resolver_uuid);
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_gai_request_parse_params(const dx_gai_request_t me, const xpc_object_t params)
-{
-	DNSServiceErrorType err;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_signed_resolve_result_t signed_resolve = NULL;
-#endif
-	const char * const hostname = dnssd_xpc_parameters_get_hostname(params);
-	require_action_quiet(hostname, exit, err = kDNSServiceErr_BadParam);
-
-	me->hostname = mdns_strdup(hostname);
-	require_action_quiet(me->hostname, exit, err = kDNSServiceErr_NoMemory);
-
-	bool valid;
-	me->flags = dnssd_xpc_parameters_get_flags(params, &valid);
-	require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
-
-	me->ifindex = dnssd_xpc_parameters_get_interface_index(params, &valid);
-	require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
-
-	me->protocols = dnssd_xpc_parameters_get_protocols(params, &valid);
-	require_action_quiet(valid, exit, err = kDNSServiceErr_BadParam);
-
-	const dx_session_t session = me->base.session;
-
-	// Get delegator IDs.
-	pid_t delegator_pid;
-	const uint8_t *delegator_uuid;
-	audit_token_t storage;
-	const audit_token_t * const delegator_audit_token = dnssd_xpc_parameters_get_delegate_audit_token(params, &storage);
-	if (delegator_audit_token) {
-		delegator_pid  = audit_token_to_pid(*delegator_audit_token);
-		delegator_uuid = NULL;
-	} else {
-		delegator_uuid = dnssd_xpc_parameters_get_delegate_uuid(params);
-		if (delegator_uuid) {
-			delegator_pid = 0;
-		} else {
-			delegator_pid = dnssd_xpc_parameters_get_delegate_pid(params, NULL);
-		}
-	}
-	if (delegator_audit_token || delegator_uuid || (delegator_pid != 0)) {
-		const bool entitled = _dx_session_has_delegate_entitlement(session);
-		require_action_quiet(entitled, exit, err = kDNSServiceErr_NoAuth);
-
-		if (delegator_audit_token) {
-			me->delegator_audit_token = (audit_token_t *)mdns_memdup(delegator_audit_token,
-				sizeof(*delegator_audit_token));
-			require_action_quiet(me->delegator_audit_token, exit, err = kDNSServiceErr_NoMemory);
-		}
-	}
-
-	// Determine effective IDs.
-	// Note: The mDNS core requires that the effective PID be set to zero if the effective UUID is the primary ID.
-	if (delegator_uuid) {
-		uuid_copy(me->effective_uuid, delegator_uuid);
-		me->effective_pid = 0;
-	} else {
-		uuid_clear(me->effective_uuid);
-		me->effective_pid = (delegator_pid != 0) ? delegator_pid : session->client_pid;
-	}
-
-	// Determine if authentication tags are needed.
-	if (dnssd_xpc_parameters_get_need_authentication_tags(params)) {
-		if (uuid_is_null(me->effective_uuid)) {
-			err = mdns_system_pid_to_uuid(me->effective_pid, me->effective_uuid);
-			require_noerr_action_quiet(err, exit, err = kDNSServiceErr_Unknown);
-		}
-		me->options |= mdns_gai_option_auth_tags;
-	}
-
-	// Determine if an SVCB or HTTPS query is necessary.
-	const char * const service_scheme = dnssd_xpc_parameters_get_service_scheme(params);
-	if (service_scheme) {
-		if (strcasecmp(service_scheme, "_443._https") == 0) {
-			me->svcb_name = me->hostname;
-			me->svcb_type = kDNSType_HTTPS;
-		} else {
-			asprintf(&me->svcb_name_memory, "%s.%s", service_scheme, me->hostname);
-			require_action_quiet(me->svcb_name_memory, exit, err = kDNSServiceErr_NoMemory);
-
-			me->svcb_name = me->svcb_name_memory;
-			me->svcb_type = kDNSType_SVCB;
-		}
-	}
-	me->fallback_dns_config = dnssd_xpc_parameters_get_fallback_config(params);
-	if (me->fallback_dns_config) {
-		xpc_retain(me->fallback_dns_config);
-	}
-	const uint8_t * const resolver_uuid = _dx_gai_request_get_resolver_uuid(params);
-	if (resolver_uuid) {
-		me->resolver_uuid = (uuid_t *)mdns_memdup(resolver_uuid, sizeof(*me->resolver_uuid));
-		require_action_quiet(me->resolver_uuid, exit, err = kDNSServiceErr_NoMemory);
-	}
-	if (dnssd_xpc_parameters_get_need_encrypted_query(params)) {
-		me->options |= mdns_gai_option_need_encryption;
-	}
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-	if (_dx_gai_request_is_for_in_app_browser(params)) {
-		me->options |= mdns_gai_option_in_app_browser;
-	}
-#endif
-	if (dnssd_xpc_parameters_get_use_failover(params)) {
-		me->options |= mdns_gai_option_use_failover;
-	}
-	if (me->options & mdns_gai_option_use_failover) {
-		if ((me->protocols & kDNSServiceProtocol_IPv4) || !(me->protocols & kDNSServiceProtocol_IPv6)) {
-			me->state |= dx_gai_state_waiting_for_a;
-		}
-		if ((me->protocols & kDNSServiceProtocol_IPv6) || !(me->protocols & kDNSServiceProtocol_IPv4)) {
-			me->state |= dx_gai_state_waiting_for_aaaa;
-		}
-	}
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-	me->log_privacy_level = dnssd_xpc_parameters_get_log_privacy_level(params);
-#endif
-	if (dnssd_xpc_parameters_get_prohibit_encrypted_dns(params)) {
-		const bool entitled = _dx_session_has_prohibit_encrypted_dns_entitlement(session);
-		require_action_quiet(entitled, exit, err = kDNSServiceErr_NoAuth);
-
-		me->options |= mdns_gai_option_prohibit_encrypted_dns;
-	}
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	size_t signed_data_len;
-	const uint8_t * const signed_data = dnssd_xpc_parameters_get_validation_data(params, &signed_data_len);
-	if (signed_data) {
-		// Get signed_result data and validate
-		OSStatus create_err;
-		signed_resolve = mdns_signed_resolve_result_create_from_data(signed_data, signed_data_len, &create_err);
-		require_action_quiet(signed_resolve, exit, err = kDNSServiceErr_Invalid; os_log_error(_mdns_server_log(),
-			"[R%u] Failed to create signed resolve result from data: %{mdns:err}ld",
-			me->base.request_id, (long)create_err));
-
-		// Use signed result to verify params otherwise don't set the signed result instance to fallback to trust
-		if (mdns_signed_resolve_result_contains(signed_resolve, me->hostname, me->ifindex)) {
-			const bool allowed = mdns_system_is_signed_result_uuid_valid(mdns_signed_result_get_uuid(signed_resolve));
-			require_action_quiet(allowed, exit, err = kDNSServiceErr_PolicyDenied; os_log_error(_mdns_server_log(),
-				"[R%u] Signed result UUID revoked.", me->base.request_id));
-
-			os_log_debug(_mdns_server_log(), "[R%u] Allowing signed result", me->base.request_id);
-			me->signed_resolve = signed_resolve;
-			signed_resolve = NULL;
-		} else {
-			os_log_error(_mdns_server_log(),
-				"[R%u] Signed resolve result does not cover request -- hostname: %{private,mask.hash}s, ifindex: %u",
-				me->base.request_id, me->hostname, me->ifindex);
-		}
-	}
-#endif
-	_dx_gai_request_log_start(me, delegator_pid, delegator_uuid);
-	err = kDNSServiceErr_NoError;
-
-exit:
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_forget(&signed_resolve);
-#endif
-	return err;
-}
-
-//======================================================================================================================
-
-static dx_gai_result_t
-_dx_gai_request_take_expired_results(dx_gai_request_t request);
-
-static xpc_object_t
-_dx_gai_request_take_results(const dx_gai_request_t me)
-{
-	DNSServiceErrorType err;
-	xpc_object_t result_array = NULL;
-	__block dx_gai_result_t result_list = NULL;
-	_dx_request_locked(me,
-	^{
-		if (me->state & DX_GAI_STATE_WAITING_FOR_RESULTS) {
-			result_list = _dx_gai_request_take_expired_results(me);
-		} else {
-			result_list = me->results;
-			me->results = NULL;
-		}
-	});
-	if (result_list) {
-		result_array = xpc_array_create(NULL, 0);
-		require_action_quiet(result_array, exit, err = kDNSServiceErr_NoMemory);
-
-		dx_gai_result_t result;
-		while ((result = result_list) != NULL) {
-			xpc_object_t result_dict = _dx_gai_result_to_dictionary(result);
-			require_action_quiet(result_dict, exit, err = kDNSServiceErr_NoMemory);
-
-			_dx_gai_result_log(result, me->base.request_id);
-			result_list = result->next;
-			_dx_forget(&result);
-
-			xpc_array_append_value(result_array, result_dict);
-			xpc_forget(&result_dict);
-		}
-	}
-	err = kDNSServiceErr_NoError;
-
-exit:
-	_dx_gai_result_list_forget(&result_list);
-	if (err) {
-		_dx_request_set_error(me, err);
-	}
-	return result_array;
-}
-
-static dx_gai_result_t
-_dx_gai_request_take_expired_results(const dx_gai_request_t me)
-{
-	dx_gai_result_t expired_results = NULL;
-	dx_gai_result_t *expired_ptr = &expired_results;
-	dx_gai_result_t result;
-	dx_gai_result_t *ptr = &me->results;
-	while ((result = *ptr) != NULL) {
-		if (result->flags & kDNSServiceFlagsExpiredAnswer) {
-			*ptr = result->next;
-			result->next = NULL;
-			*expired_ptr = result;
-			expired_ptr = &result->next;
-		} else {
-			ptr = &result->next;
-		}
-	}
-	return expired_results;
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_gai_request_start_client_requests_internal(const dx_gai_request_t me,
-	GetAddrInfoClientRequestParams * const gai_params, QueryRecordClientRequestParams * const query_params,
-	const bool need_lock)
-{
-	__block DNSServiceErrorType err = kDNSServiceErr_NoError;
-	_dx_kqueue_locked("dx_gai_request: starting client requests", need_lock,
-	^{
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-		if (me->resolver_uuid && !uuid_is_null(*me->resolver_uuid)) {
-			Querier_RegisterPathResolver(*me->resolver_uuid);
-		}
-		if ((me->custom_service_id == MDNS_DNS_SERVICE_INVALID_ID) && me->fallback_dns_config) {
-			me->custom_service_id = Querier_RegisterCustomDNSService(me->fallback_dns_config);
-		}
-		if (gai_params) {
-			gai_params->resolverUUID	= *me->resolver_uuid;
-			gai_params->customID		= me->custom_service_id;
-		}
-		if (query_params) {
-			query_params->resolverUUID	= *me->resolver_uuid;
-			query_params->customID		= me->custom_service_id;
-		}
-#endif
-		// If present, run the query for SVCB/HTTPS first, in case the ALPN and address hints come back first.
-		if (query_params && !(me->state & dx_gai_state_query_is_active)) {
-			err = QueryRecordClientRequestStart(&me->query, query_params, _dx_gai_request_query_result_handler, me);
-			require_noerr_return(err);
-			me->state |= dx_gai_state_query_is_active;
-		}
-		// Run the A/AAAA lookup.
-		if (gai_params && !(me->state & dx_gai_state_gai_is_active)) {
-			err = GetAddrInfoClientRequestStart(&me->gai, gai_params, _dx_gai_request_gai_result_handler, me);
-			require_noerr_return(err);
-			me->state |= dx_gai_state_gai_is_active;
-		}
-	});
-	if (err) {
-		_dx_gai_request_stop_client_requests(me, need_lock);
-	}
-	return err;
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_stop_client_requests(const dx_gai_request_t me, const bool need_lock)
-{
-	_dx_kqueue_locked("dx_gai_request: stopping client requests", need_lock,
-	^{
-		if (me->state & dx_gai_state_gai_is_active) {
-			GetAddrInfoClientRequestStop(&me->gai);
-			me->state &= ~dx_gai_state_gai_is_active;
-		}
-		if (me->state & dx_gai_state_query_is_active) {
-			QueryRecordClientRequestStop(&me->query);
-			me->state &= ~dx_gai_state_query_is_active;
-		}
-	});
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_restart_client_requests_in_failover_mode(const dx_gai_request_t me)
-{
-	if (!(me->state & dx_gai_state_failover_mode)) {
-		_dx_gai_request_stop_client_requests(me, false);
-		_dx_gai_result_list_forget(&me->results);
-		os_log(_mdns_server_log(), "[R%u] getaddrinfo failover restart", me->base.request_id);
-		me->state |= dx_gai_state_failover_mode;
-		_dx_gai_request_start_client_requests(me, false);
-	}
-}
-
-//======================================================================================================================
-
-static xpc_object_t *
-_dx_gai_request_get_cnames_ptr(const dx_gai_request_t me, const int qtype, bool ** const out_changed_ptr,
-	ssize_t **out_expire_idx_ptr)
-{
-	ssize_t *expire_idx_ptr;
-	xpc_object_t *cnames_ptr;
-	bool *changed_ptr;
-	switch (qtype) {
-		case kDNSServiceType_A:
-			cnames_ptr		= &me->cnames_a;
-			changed_ptr		= &me->cnames_a_changed;
-			expire_idx_ptr	= &me->cnames_a_expire_idx;
-			break;
-
-		case kDNSServiceType_AAAA:
-			cnames_ptr		= &me->cnames_aaaa;
-			changed_ptr		= &me->cnames_aaaa_changed;
-			expire_idx_ptr	= &me->cnames_aaaa_expire_idx;
-			break;
-
-		default:
-			cnames_ptr		= NULL;
-			expire_idx_ptr	= NULL;
-			changed_ptr		= NULL;
-			break;
-	}
-	if (out_expire_idx_ptr) {
-		*out_expire_idx_ptr = expire_idx_ptr;
-	}
-	if (out_changed_ptr) {
-		*out_changed_ptr = changed_ptr;
-	}
-	return cnames_ptr;
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_append_cname(const dx_gai_request_t me, const int qtype, const domainname * const cname,
-	const bool expired, const bool unwind)
-{
-	bool *changed_ptr;
-	ssize_t *expire_idx_ptr;
-	xpc_object_t * const cnames_ptr = _dx_gai_request_get_cnames_ptr(me, qtype, &changed_ptr, &expire_idx_ptr);
-	require_quiet(cnames_ptr, exit);
-
-	const char *cname_str = NULL;
-	char cname_buf[MAX_ESCAPED_DOMAIN_NAME];
-	if (cname) {
-		if (!ConvertDomainNameToCString(cname, cname_buf)) {
-			cname_buf[0] = '\0';
-		}
-		cname_str = cname_buf;
-	}
-	_dx_request_locked(me,
-	^{
-		if (unwind) {
-			const ssize_t expire_idx = *expire_idx_ptr;
-			if (*cnames_ptr && (expire_idx >= 0)) {
-				xpc_object_t new_cnames = xpc_array_create(NULL, 0);
-				if (new_cnames && (expire_idx > 0)) {
-					xpc_array_apply(*cnames_ptr,
-					^ bool (const size_t index, const xpc_object_t _Nonnull value)
-					{
-						bool proceed = false;
-						if (index < (size_t)expire_idx) {
-							xpc_array_append_value(new_cnames, value);
-							proceed = true;
-						}
-						return proceed;
-					});
-				}
-				xpc_forget(cnames_ptr);
-				*cnames_ptr		= new_cnames;
-				*changed_ptr	= true;
-			}
-			*expire_idx_ptr = -1;
-		}
-		if (cname_str) {
-			xpc_object_t cnames = *cnames_ptr;
-			if (expired && (*expire_idx_ptr < 0)) {
-				*expire_idx_ptr = cnames ? (ssize_t)xpc_array_get_count(cnames) : 0;
-			}
-			if (!cnames) {
-				cnames = xpc_array_create(NULL, 0);
-				*cnames_ptr = cnames;
-			}
-			if (cnames) {
-				xpc_array_set_string(cnames, XPC_ARRAY_APPEND, cname_str);
-				*changed_ptr = true;
-			}
-		}
-	});
-
-exit:
-	return;
-}
-
-//======================================================================================================================
-
-static xpc_object_t
-_dx_gai_request_copy_cname_update(const dx_gai_request_t me, const int qtype)
-{
-	__block xpc_object_t result = NULL;
-	bool *changed_ptr;
-	xpc_object_t * const cnames_ptr = _dx_gai_request_get_cnames_ptr(me, qtype, &changed_ptr, NULL);
-	require_quiet(cnames_ptr, exit);
-
-	_dx_request_locked(me,
-	^{
-		if (*changed_ptr) {
-			const xpc_object_t cnames = *cnames_ptr;
-			if (cnames) {
-				result = xpc_copy(cnames);
-			}
-			*changed_ptr = false;
-		}
-	});
-
-exit:
-	return result;
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_failover_check_gai_answer(dx_gai_request_t request, const ResourceRecord *answer);
-
-static void
-_dx_gai_request_gai_result_handler(mDNS * const m, DNSQuestion * const q, const ResourceRecord * const answer,
-	const QC_result qc_result, const DNSServiceErrorType error, void * const context)
-{
-	(void)m;
-	bool failover_restart = false;
-	const dx_gai_request_t me = (dx_gai_request_t)context;
-	if (!error || (error == kDNSServiceErr_NoSuchRecord)) {
-		_dx_gai_request_failover_check_gai_answer(me, answer);
-		const bool expired = (answer->mortality == Mortality_Ghost) || (q->firstExpiredQname.c[0] != 0);
-		if (answer->rrtype == kDNSServiceType_CNAME) {
-			require_quiet(!error, exit);
-
-			_dx_gai_request_append_cname(me, q->qtype, &answer->rdata->u.name, expired, q->CNAMEReferrals == 0);
-		}
-		require_quiet((answer->rrtype == kDNSServiceType_A) || (answer->rrtype == kDNSServiceType_AAAA), exit);
-
-		if (q->CNAMEReferrals == 0) {
-			_dx_gai_request_unwind_cnames_if_necessary(me, q->qtype);
-		}
-		const uint8_t *rdata_ptr;
-		uint16_t rdata_len;
-		if (!error) {
-			if (answer->rrtype == kDNSServiceType_A) {
-				rdata_ptr = answer->rdata->u.ipv4.b;
-				rdata_len = 4;
-			} else {
-				rdata_ptr = answer->rdata->u.ipv6.b;
-				rdata_len = 16;
-			}
-		} else {
-			rdata_ptr = NULL;
-			rdata_len = 0;
-		}
-		failover_restart = _dx_gai_request_check_for_failover_restart(me, answer, expired, rdata_len > 0);
-		if (!failover_restart) {
-			_dx_gai_request_enqueue_result(me, qc_result, answer, expired, rdata_ptr, rdata_len, error, q);
-		}
-	} else {
-		_dx_request_set_error(me, error);
-	}
-
-exit:
-	if (failover_restart) {
-		_dx_gai_request_restart_client_requests_in_failover_mode(me);
-	}
-}
-
-static void
-_dx_gai_request_failover_check_gai_answer(const dx_gai_request_t me, const ResourceRecord * const answer)
-{
-	if ((me->state & DX_GAI_STATE_WAITING_FOR_RESULTS) && !(me->state & dx_gai_state_service_allowed_failover)) {
-		if (answer->dnsservice && mdns_dns_service_allows_failover(answer->dnsservice)) {
-			me->state |= dx_gai_state_service_allowed_failover;
-		}
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_query_result_handler(mDNS * const m, DNSQuestion * const q, const ResourceRecord * const answer,
-	const QC_result qc_result, const DNSServiceErrorType error, void * const context)
-{
-	(void)m;
-	bool failover_restart = false;
-	const dx_gai_request_t me = (dx_gai_request_t)context;
-	if (!error || (error == kDNSServiceErr_NoSuchRecord)) {
-		require_quiet((answer->rrtype == kDNSServiceType_SVCB) || (answer->rrtype == kDNSServiceType_HTTPS), exit);
-
-		const uint8_t *rdata_ptr;
-		uint16_t rdata_len;
-		if (!error) {
-			rdata_ptr = answer->rdata->u.data;
-			rdata_len = answer->rdlength;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-			char *svcb_doh_uri = dnssd_svcb_copy_doh_uri(rdata_ptr, rdata_len);
-			// Check for a valid DoH URI.
-			if (svcb_doh_uri) {
-				// Pass the domain to map if the record is DNSSEC signed.
-				char *svcb_domain = NULL;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-				char svcb_domain_buffer[MAX_ESCAPED_DOMAIN_NAME] = "";
-				if (resource_record_get_validation_result(answer) == dnssec_secure) {
-					if (ConvertDomainNameToCString(answer->name, svcb_domain_buffer)) {
-						svcb_domain = svcb_domain_buffer;
-					}
-				}
-#endif
-				Querier_RegisterDoHURI(svcb_doh_uri, svcb_domain);
-				ForgetMem(&svcb_doh_uri);
-			}
-#endif
-		} else {
-			rdata_ptr = NULL;
-			rdata_len = 0;
-		}
-		const bool expired = (answer->mortality == Mortality_Ghost) || (q->firstExpiredQname.c[0] != 0);
-		failover_restart = _dx_gai_request_check_for_failover_restart(me, answer, expired, rdata_len > 0);
-		if (!failover_restart) {
-			_dx_gai_request_enqueue_result(me, qc_result, answer, expired, rdata_ptr, rdata_len, error, q);
-		}
-	} else {
-		_dx_request_set_error(me, error);
-	}
-
-exit:
-	if (failover_restart) {
-		_dx_gai_request_restart_client_requests_in_failover_mode(me);
-	}
-}
-
-//======================================================================================================================
-
-static dnssd_negative_reason_t
-_dx_get_negative_answer_reason(const ResourceRecord *answer, QC_result qc_result);
-
-static void
-_dx_gai_request_enqueue_result(const dx_gai_request_t me, const QC_result qc_result,
-	const ResourceRecord * const answer, const bool answer_is_expired, const uint8_t * const rdata_ptr,
-	const uint16_t rdata_len, const DNSServiceErrorType result_error, const DNSQuestion * const q)
-{
-	DNSServiceErrorType err;
-	dx_gai_result_t result = NULL;
-	require_action_quiet(!answer_is_expired || (rdata_len > 0), exit, err = kDNSServiceErr_NoError);
-
-	result = _dx_gai_result_new();
-	require_action_quiet(result, exit, err = kDNSServiceErr_NoMemory);
-
-	_dx_replace_domain_name(&me->last_domain_name, answer->name);
-	require_action_quiet(me->last_domain_name, exit, err = kDNSServiceErr_NoMemory);
-
-	result->record = mdns_resource_record_create(me->last_domain_name, answer->rrtype, answer->rrclass, 0,
-		rdata_ptr, rdata_len, NULL);
-	require_action_quiet(result->record, exit, err = kDNSServiceErr_NoMemory);
-
-	DNSServiceFlags flags = 0;
-	const bool is_add = _dx_qc_result_is_add(qc_result);
-	if (is_add) {
-		flags |= kDNSServiceFlagsAdd;
-		if (!q->InitialCacheMiss) {
-			flags |= kDNSServiceFlagAnsweredFromCache;
-		}
-		if (rdata_len <= 0) {
-			result->negative_reason = _dx_get_negative_answer_reason(answer, qc_result);
-		}
-	}
-	if (answer_is_expired) {
-		flags |= kDNSServiceFlagsExpiredAnswer;
-	}
-	extern mDNS mDNSStorage;
-	result->flags       = flags;
-	result->error       = result_error;
-	result->ifindex     = mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, answer->InterfaceID, mDNStrue);
-	result->protocol    = answer->protocol;
-	result->question_id = mDNSVal16(q->TargetQID);
-	if (answer->dnsservice) {
-		result->provider_name = mdns_dns_service_copy_provider_name(answer->dnsservice);
-	}
-	const uint16_t record_type = mdns_resource_record_get_type(result->record);
-	if (is_add && !result_error) {
-		if (me->options & mdns_gai_option_auth_tags) {
-			uint8_t auth_tag[DNSSD_AUTHENTICATION_TAG_SIZE];
-			const bool ok = _dx_authenticate_address_rdata(me->effective_uuid, me->hostname, record_type,
-				mdns_resource_record_get_rdata_bytes_ptr(result->record), auth_tag);
-			if (ok) {
-				check_compile_time(sizeof(*result->auth_tag) == sizeof(auth_tag));
-				result->auth_tag = (dx_auth_tag_t *)mdns_memdup(auth_tag, sizeof(*result->auth_tag));
-			}
-		}
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-		if (me->signed_resolve && ((record_type == kDNSType_A) || (record_type == kDNSType_AAAA))) {
-			OSStatus create_err;
-			mdns_signed_hostname_result_t signed_hostname;
-			if (record_type == kDNSType_A) {
-				signed_hostname = mdns_signed_hostname_result_create_ipv4(me->signed_resolve, rdata_ptr, &create_err);
-			} else {
-				signed_hostname = mdns_signed_hostname_result_create_ipv6(me->signed_resolve, rdata_ptr,
-					result->ifindex, &create_err);
-			}
-			result->signed_hostname = signed_hostname;
-			if (!result->signed_hostname) {
-				os_log_error(_mdns_server_log(),
-					"[R%u] Failed to create IPv%d signed hostname result: %{mdns:err}ld",
-					me->base.request_id, (record_type == kDNSType_A) ? 4 : 6, (long)create_err);
-			}
-		}
-#endif
-	}
-	result->cname_update = _dx_gai_request_copy_cname_update(me, record_type);
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-	if (resolved_cache_is_enabled() && is_add) {
-		const char *hostname = NULL;
-		const char *owner = NULL;
-		bool approved_domain = false;
-		const tracker_state_t tracker_state = resolved_cache_get_tracker_state(q, &hostname, &owner, &approved_domain);
-		if ((tracker_state == tracker_state_known_tracker) && hostname) {
-			mdns_xpc_string_recreate(&me->last_tracker_hostname, hostname);
-			require_action_quiet(me->last_tracker_hostname, exit, err = kDNSServiceErr_NoMemory);
-
-			result->tracker_hostname = me->last_tracker_hostname;
-			xpc_retain(result->tracker_hostname);
-			if (owner) {
-				mdns_xpc_string_recreate(&me->last_tracker_owner, owner);
-				require_action_quiet(me->last_tracker_owner, exit, err = kDNSServiceErr_NoMemory);
-
-				result->tracker_owner = me->last_tracker_owner;
-				mdns_xpc_string_retain(result->tracker_owner);
-			}
-			if (approved_domain) {
-				result->tracker_is_approved = true;
-			}
-		}
-	}
-#endif
-	_dx_request_locked(me,
-	^{
-		dx_gai_result_t *ptr = &me->results;
-		while (*ptr) {
-			ptr = &(*ptr)->next;
-		}
-		*ptr = result;
-	});
-	result = NULL;
-	err = kDNSServiceErr_NoError;
-
-exit:
-	static_analyzer_malloc_freed(result); // Analyzer isn't aware that result will be freed if non-NULL.
-	_dx_forget(&result);
-	if (err) {
-		_dx_request_set_error(me, err);
-	}
-}
-
-static dnssd_negative_reason_t
-_dx_get_negative_answer_reason(const ResourceRecord * const answer, const QC_result qc_result)
-{
-	if (answer->dnsservice) {
-		if (_dx_qc_result_is_suppressed(qc_result)) {
-			return dnssd_negative_reason_query_suppressed;
-		} else {
-			switch (answer->rcode) {
-				case kDNSFlag1_RC_NoErr:
-					return dnssd_negative_reason_no_data;
-
-				case kDNSFlag1_RC_NXDomain:
-					return dnssd_negative_reason_nxdomain;
-
-				default:
-					return dnssd_negative_reason_server_error;
-			}
-		}
-	} else {
-		if (answer->InterfaceID) {
-			// A non-zero InterfaceID means that an mDNS NSEC record asserted that there's no data for the record.
-			return dnssd_negative_reason_no_data;
-		} else {
-			return dnssd_negative_reason_no_dns_service;
-		}
-	}
-}
-
-//======================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-static const uint8_t *
-_dx_gai_request_get_resolver_uuid(const xpc_object_t params)
-{
-	const xpc_object_t resolver_uuids = dnssd_xpc_parameters_get_resolver_uuid_array(params);
-	if (resolver_uuids && (xpc_array_get_count(resolver_uuids) > 0)) {
-		return xpc_array_get_uuid(resolver_uuids, 0);
-	} else {
-		return NULL;
-	}
-}
-#endif
-
-//======================================================================================================================
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-static bool
-_dx_gai_request_is_for_in_app_browser(const xpc_object_t params)
-{
-	const char * const account_id = dnssd_xpc_parameters_get_account_id(params);
-	if (account_id && (strcmp(account_id, "com.apple.WebKit.InAppBrowser") == 0)) {
-		return true;
-	} else {
-		return false;
-	}
-}
-#endif
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_log_start(const dx_gai_request_t me, const pid_t delegator_pid, const uuid_t delegator_uuid)
-{
-	const dx_session_t session = me->base.session;
-	if (delegator_uuid) {
-		os_log(_mdns_server_log(),
-			"[R%u] getaddrinfo start -- flags: 0x%X, ifindex: %d, protocols: %u, hostname: %{private,mask.hash}s, "
-			"options: %{mdns:gaiopts}X, client pid: %lld (%{public}s), delegator uuid: %{public,uuid_t}.16P",
-			me->base.request_id, me->flags, (int32_t)me->ifindex, me->protocols, me->hostname, me->options,
-			(long long)session->client_pid, session->client_name, delegator_uuid);
-	} else if (delegator_pid != 0) {
-		char delegator_name[MAXCOMLEN];
-		delegator_name[0] = '\0';
-		mdns_system_pid_to_name(delegator_pid, delegator_name);
-		os_log(_mdns_server_log(),
-			"[R%u] getaddrinfo start -- flags: 0x%X, ifindex: %d, protocols: %u, hostname: %{private,mask.hash}s, "
-			"options: %{mdns:gaiopts}X, client pid: %lld (%{public}s), delegator pid: %lld (%{public}s)",
-			me->base.request_id, me->flags, (int32_t)me->ifindex, me->protocols, me->hostname, me->options,
-			(long long)session->client_pid, session->client_name, (long long)delegator_pid, delegator_name);
-	} else {
-		os_log(_mdns_server_log(),
-			"[R%u] getaddrinfo start -- flags: 0x%X, ifindex: %d, protocols: %u, hostname: %{private,mask.hash}s, "
-			"options: %{mdns:gaiopts}X, client pid: %lld (%{public}s)",
-			me->base.request_id, me->flags, (int32_t)me->ifindex, me->protocols, me->hostname, me->options,
-			(long long)session->client_pid, session->client_name);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_log_stop(const dx_gai_request_t me)
-{
-	const dx_session_t session = me->base.session;
-	if (session->terminated) {
-		os_log(_mdns_server_log(),
-			"[R%u] getaddrinfo stop (forced) -- hostname: %{private,mask.hash}s, client pid: %lld (%{public}s)",
-			me->base.request_id, me->hostname, (long long)session->client_pid, session->client_name);
-	} else {
-		os_log(_mdns_server_log(),
-			"[R%u] getaddrinfo stop -- hostname: %{private,mask.hash}s, client pid: %lld (%{public}s)",
-			me->base.request_id, me->hostname, (long long)session->client_pid, session->client_name);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_request_log_error(const dx_gai_request_t me, const DNSServiceErrorType error)
-{
-	const dx_session_t session = me->base.session;
-	os_log_error(_mdns_server_log(),
-		"[R%u] getaddrinfo error -- hostname: %{private,mask.hash}s, error: %{mdns:err}ld"", "
-		"client pid: %lld (%{public}s)",
-		me->base.request_id, me->hostname, (long)error, (long long)session->client_pid, session->client_name);
-}
-
-//======================================================================================================================
-
-static DNSServiceErrorType
-_dx_gai_request_start_client_requests(const dx_gai_request_t me, const bool need_lock)
-{
-	const dx_session_t session = me->base.session;
-
-	// Set up GetAddrInfo parameters.
-	GetAddrInfoClientRequestParams gai_params;
-	GetAddrInfoClientRequestParamsInit(&gai_params);
-	gai_params.hostnameStr				= me->hostname;
-	gai_params.requestID				= me->base.request_id;
-	gai_params.interfaceIndex			= me->ifindex;
-	gai_params.flags					= me->flags;
-	gai_params.protocols				= me->protocols;
-	gai_params.effectivePID				= me->effective_pid;
-	gai_params.effectiveUUID			= me->effective_uuid;
-	gai_params.peerUID					= session->client_euid;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-	gai_params.needEncryption			= (me->options & mdns_gai_option_need_encryption) != 0;
-	gai_params.failoverMode				= (me->state & dx_gai_state_failover_mode) != 0;
-	gai_params.prohibitEncryptedDNS		= (me->options & mdns_gai_option_prohibit_encrypted_dns) != 0;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-	gai_params.peerAuditToken			= &session->audit_token;
-	gai_params.delegatorAuditToken		= me->delegator_audit_token;
-	gai_params.isInAppBrowserRequest	= (me->options & mdns_gai_option_in_app_browser) != 0;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-	gai_params.logPrivacyLevel			= me->log_privacy_level;
-#endif
-
-	// Set up QueryRecord parameters.
-	QueryRecordClientRequestParams query_params;
-	QueryRecordClientRequestParams *query_params_ptr = NULL;
-	if (me->svcb_name) {
-		QueryRecordClientRequestParamsInit(&query_params);
-		query_params.requestID				= me->base.request_id;
-		query_params.qnameStr				= me->svcb_name;
-		query_params.interfaceIndex			= me->ifindex;
-		query_params.flags					= me->flags;
-		query_params.qtype					= me->svcb_type;
-		query_params.qclass					= kDNSServiceClass_IN;
-		query_params.effectivePID			= me->effective_pid;
-		query_params.effectiveUUID			= me->effective_uuid;
-		query_params.peerUID				= session->client_euid;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-		query_params.needEncryption			= (me->options & mdns_gai_option_need_encryption) != 0;
-		query_params.failoverMode			= (me->state & dx_gai_state_failover_mode) != 0;
-		query_params.prohibitEncryptedDNS	= (me->options & mdns_gai_option_prohibit_encrypted_dns) != 0;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-		query_params.peerAuditToken			= &session->audit_token;
-		query_params.delegatorAuditToken	= me->delegator_audit_token;
-		query_params.isInAppBrowserRequest	= (me->options & mdns_gai_option_in_app_browser) != 0;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-		query_params.logPrivacyLevel		= me->log_privacy_level;
-#endif
-		query_params_ptr = &query_params;
-	}
-	return _dx_gai_request_start_client_requests_internal(me, &gai_params, query_params_ptr, need_lock);
-}
-
-//======================================================================================================================
-
-static bool
-_dx_gai_request_check_for_failover_restart(const dx_gai_request_t me, const ResourceRecord * const answer,
-	const bool answer_is_expired, const bool answer_is_positive)
-{
-	bool restart = false;
-	if ((me->state & DX_GAI_STATE_WAITING_FOR_RESULTS) && !answer_is_expired) {
-		if (answer_is_positive) {
-			switch (answer->rrtype) {
-				case kDNSType_A:
-				case kDNSType_AAAA:
-				case kDNSType_HTTPS:
-					me->state &= ~DX_GAI_STATE_WAITING_FOR_RESULTS;
-					break;
-			}
-		} else {
-			switch (answer->rrtype) {
-				case kDNSServiceType_A:
-					me->state &= ~dx_gai_state_waiting_for_a;
-					break;
-
-				case kDNSServiceType_AAAA:
-					me->state &= ~dx_gai_state_waiting_for_aaaa;
-					break;
-			}
-			const dx_gai_state_t state = me->state;
-			if (!(state & DX_GAI_STATE_WAITING_FOR_RESULTS) && (state & dx_gai_state_service_allowed_failover)) {
-				restart = true;
-			}
-		}
-	}
-	return restart;
-}
-
-//======================================================================================================================
-// MARK: - GAI Result Methods
-
-static void
-_dx_gai_result_finalize(const dx_gai_result_t me)
-{
-	mdns_forget(&me->record);
-	mdns_xpc_string_forget(&me->provider_name);
-	xpc_forget(&me->cname_update);
-	mdns_xpc_string_forget(&me->tracker_hostname);
-	mdns_xpc_string_forget(&me->tracker_owner);
-	ForgetMem(&me->auth_tag);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	mdns_forget(&me->signed_hostname);
-#endif
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_result_list_forget(dx_gai_result_t * const list_ptr)
-{
-	dx_gai_result_t list;
-	if ((list = *list_ptr) != NULL) {
-		*list_ptr = NULL;
-		dx_gai_result_t result;
-		while ((result = list) != NULL) {
-			list = result->next;
-			_dx_forget(&result);
-		}
-	}
-}
-
-//======================================================================================================================
-
-static xpc_object_t
-_dx_gai_result_to_dictionary(const dx_gai_result_t me)
-{
-	xpc_object_t result = xpc_dictionary_create(NULL, NULL, 0);
-	require_return_value(result, NULL);
-
-	dnssd_xpc_result_set_error(result, me->error);
-	dnssd_xpc_result_set_flags(result, me->flags);
-	dnssd_xpc_result_set_interface_index(result, me->ifindex);
-	const mdns_domain_name_t name = mdns_resource_record_get_name(me->record);
-	dnssd_xpc_result_set_record_name(result, mdns_domain_name_get_presentation(name));
-	dnssd_xpc_result_set_record_type(result, mdns_resource_record_get_type(me->record));
-	dnssd_xpc_result_set_record_protocol(result, (uint16_t)me->protocol);
-	dnssd_xpc_result_set_record_class(result, mdns_resource_record_get_class(me->record));
-	dnssd_xpc_result_set_record_data(result, mdns_resource_record_get_rdata_bytes_ptr(me->record),
-		mdns_resource_record_get_rdata_length(me->record));
-	if (me->negative_reason != dnssd_negative_reason_none) {
-		dnssd_xpc_result_set_negative_reason(result, me->negative_reason);
-	}
-	if (me->provider_name) {
-		dnssd_xpc_result_set_provider_name(result, me->provider_name);
-	}
-	if (me->auth_tag) {
-		dnssd_xpc_result_set_authentication_tag(result, me->auth_tag, sizeof(*me->auth_tag));
-	}
-	if (me->cname_update) {
-		dnssd_xpc_result_set_cname_update(result, me->cname_update);
-	}
-	if (me->tracker_hostname) {
-		dnssd_xpc_result_set_tracker_hostname(result, me->tracker_hostname);
-		if (me->tracker_owner) {
-			dnssd_xpc_result_set_tracker_owner(result, me->tracker_owner);
-		}
-		dnssd_xpc_result_set_tracker_is_approved(result, me->tracker_is_approved);
-	}
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-	if (me->signed_hostname) {
-		size_t data_len;
-		const uint8_t * const data = mdns_signed_result_get_data(me->signed_hostname, &data_len);
-		if (data) {
-			dnssd_xpc_result_set_validation_data(result, data, data_len);
-		}
-	}
-#endif
-	return result;
-}
-
-//======================================================================================================================
-
-static void
-_dx_gai_result_log(const dx_gai_result_t me, const uint32_t request_id)
-{
-	const bool is_add = (me->flags & kDNSServiceFlagsAdd) ? true : false;
-	const mdns_domain_name_t name = me->record ? mdns_resource_record_get_name(me->record) : NULL;
-	const int type = me->record ? mdns_resource_record_get_type(me->record) : 0;
-	if (me->record && (mdns_resource_record_get_rdata_length(me->record) > 0)) {
-		const bool expired = (me->flags & kDNSServiceFlagsExpiredAnswer) != 0;
-		os_log(_mdns_server_log(),
-			"[R%u->Q%u] getaddrinfo result -- event: %{mdns:addrmv}d, ifindex: %d, name: %@, type: %{mdns:rrtype}d,"
-			" rdata: %@, expired: %{mdns:yesno}d",
-			request_id, me->question_id, is_add, me->ifindex, name, type, me->record, expired);
-	} else {
-		os_log(_mdns_server_log(),
-			"[R%u->Q%u] getaddrinfo result -- event: %{mdns:addrmv}d, ifindex: %d, name: %@, type: %{mdns:rrtype}d,"
-			" rdata: <none>, reason: %{mdns:nreason}d",
-			request_id, me->question_id, is_add, me->ifindex, name, type, me->negative_reason);
-	}
-}
-
-//======================================================================================================================
-// MARK: - Helper Functions
-
-typedef struct {
-	struct necp_client_resolver_answer	hdr;
-	uint8_t								hostname[MAX_ESCAPED_DOMAIN_NAME];
-} dx_necp_answer_t;
-
-check_compile_time(sizeof_field(dx_necp_answer_t, hdr) == offsetof(dx_necp_answer_t, hostname));
-
-static bool
-_dx_authenticate_address_rdata(uuid_t effective_uuid, const char * const hostname, const int type,
-	const uint8_t * const rdata, uint8_t out_auth_tag[STATIC_PARAM DNSSD_AUTHENTICATION_TAG_SIZE])
-{
-	bool ok = false;
-	require_quiet((type == kDNSServiceType_A) || (type == kDNSServiceType_AAAA), exit);
-
-	dx_necp_answer_t answer;
-	struct necp_client_resolver_answer * const hdr = &answer.hdr;
-	memset(hdr, 0, sizeof(*hdr));
-	uuid_copy(hdr->client_id, effective_uuid);
-
-	hdr->sign_type = NECP_CLIENT_SIGN_TYPE_RESOLVER_ANSWER;
-	if (type == kDNSServiceType_A) {
-		hdr->address_answer.sa.sa_family	= AF_INET;
-		hdr->address_answer.sa.sa_len		= sizeof(struct sockaddr_in);
-		memcpy(&hdr->address_answer.sin.sin_addr.s_addr, rdata, 4);
-	} else {
-		hdr->address_answer.sa.sa_family	= AF_INET6;
-		hdr->address_answer.sa.sa_len		= sizeof(struct sockaddr_in6);
-		memcpy(hdr->address_answer.sin6.sin6_addr.s6_addr, rdata, 16);
-	}
-	const size_t hostname_len = strlen(hostname);
-	require_quiet(hostname_len <= sizeof(answer.hostname), exit);
-
-	hdr->hostname_length = (uint32_t)hostname_len;
-	memcpy(answer.hostname, hostname, hdr->hostname_length);
-
-	static int necp_fd = -1;
-	if (necp_fd < 0) {
-		necp_fd = necp_open(0);
-	}
-	require_quiet(necp_fd >= 0, exit);
-
-	const int err = necp_client_action(necp_fd, NECP_CLIENT_ACTION_SIGN, (uint8_t *)&answer.hdr,
-		sizeof(answer.hdr) + hdr->hostname_length, out_auth_tag, DNSSD_AUTHENTICATION_TAG_SIZE);
-	require_noerr_quiet(err, exit);
-
-	ok = true;
-
-exit:
-	return ok;
-}
-
-//======================================================================================================================
-
-static void
-_dx_kqueue_locked(const char * const description, const bool need_lock, const dx_block_t block)
-{
-	if (need_lock) {
-		KQueueLock();
-		block();
-		KQueueUnlock(description);
-	} else {
-		block();
-	}
-}
-
-//======================================================================================================================
-
-static void
-_dx_replace_domain_name(mdns_domain_name_t * const ptr, const domainname * const name)
-{
-	const mdns_domain_name_t original = *ptr;
-	if (!original || !SameDomainNameBytes(mdns_domain_name_get_labels(original), name->c)) {
-		mdns_forget(ptr);
-		*ptr = mdns_domain_name_create_with_labels(name->c, NULL);
-	}
-}
-
-//======================================================================================================================
-
-static bool
-_dx_qc_result_is_add(const QC_result qc_result)
-{
-	// No default case to allow the compiler to catch missing enum values.
-	switch (qc_result) {
-		case QC_rmv:
-			return false;
-
-		case QC_add:
-		case QC_addnocache:
-		case QC_forceresponse:
-		case QC_suppressed:
-			break;
-	}
-	return true;
-}
-
-//======================================================================================================================
-
-static bool
-_dx_qc_result_is_suppressed(const QC_result qc_result)
-{
-	// No default case to allow the compiler to catch missing enum values.
-	switch (qc_result) {
-		case QC_suppressed:
-			return true;
-
-		case QC_rmv:
-		case QC_add:
-		case QC_addnocache:
-		case QC_forceresponse:
-			break;
-	}
-	return false;
-}
diff --git a/mDNSMacOSX/dnssd_server.h b/mDNSMacOSX/dnssd_server.h
deleted file mode 100644
index 75a4ae8..0000000
--- a/mDNSMacOSX/dnssd_server.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2018-2020 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __DNSSD_SERVER_H__
-#define __DNSSD_SERVER_H__
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void
-dnssd_server_init(void);
-
-void
-dnssd_server_idle(void);
-
-uint32_t
-dnssd_server_get_new_request_id(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	// __DNSSD_SERVER_H__
diff --git a/mDNSMacOSX/dnssd_svcb.c b/mDNSMacOSX/dnssd_svcb.c
deleted file mode 100644
index 3b13eb7..0000000
--- a/mDNSMacOSX/dnssd_svcb.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple 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.
- */
-
-#include "dnssd_svcb.h"
-
-#include <CoreUtils/CoreUtils.h>
-#include <netinet/in.h>
-#include "mdns_strict.h"
-
-typedef enum
-{
-    dnssd_svcb_key_mandatory = 0,
-    dnssd_svcb_key_alpn = 1,
-    dnssd_svcb_key_no_default_alpn = 2,
-    dnssd_svcb_key_port = 3,
-    dnssd_svcb_key_ipv4_hint = 4,
-    dnssd_svcb_key_ech_config = 5,
-    dnssd_svcb_key_ipv6_hint = 6,
-	dnssd_svcb_key_doh_path = 7,
-    dnssd_svcb_key_doh_uri = 32768,
-	dnssd_svcb_key_odoh_config = 32769,
-} dnssd_svcb_key_t;
-
-typedef bool (^_dnssd_svcb_access_value_block_t)(const void *value, size_t value_size);
-
-bool
-dnssd_svcb_is_alias(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return false;
-	}
-
-	return (dnssd_svcb_get_priority(buffer, buffer_size) == 0);
-}
-
-uint16_t
-dnssd_svcb_get_priority(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return 0;
-	}
-
-	const uint16_t *priority_p = (const uint16_t *)buffer;
-	return (uint16_t)htons(*priority_p);
-}
-
-#define DNSSD_MAX_DOMAIN_NAME 256
-#define DNSSD_MAX_DOMAIN_LABEL 63
-#define DNSSD_MAX_ESCAPED_DOMAIN_NAME 1009
-
-static bool
-_dnssd_svcb_get_service_name_length(const uint8_t *buffer, size_t buffer_size, size_t *out_name_length)
-{
-	const uint8_t *limit = buffer + buffer_size;
-	const uint8_t *cursor = buffer;
-    while (cursor != NULL && cursor < limit) {
-		if (*cursor == 0) {
-			*out_name_length = ((uint16_t)(cursor - buffer + 1));
-			if (*out_name_length > DNSSD_MAX_DOMAIN_NAME) {
-				return false;
-			}
-			return true;
-		}
-        cursor += 1 + *cursor;
-    }
-	return false;
-}
-
-static char *
-_dnssd_svcb_convert_label_to_string(const uint8_t *source, char *string_buffer)
-{
-    const uint8_t length = *source++; // Read length of this (non-null) label
-    const uint8_t *limit = source + length; // Work out where the label ends
-	if (length > DNSSD_MAX_DOMAIN_LABEL) {
-		return NULL;
-	}
-	while (source < limit) {
-        uint8_t character = *source++;
-		if (character == '.' || character == '\\') { // If character is a dot or the escape character
-			*string_buffer++ = '\\'; // Output escape character
-		} else if (character <= ' ') { // Output decimal escape sequence
-			*string_buffer++ = '\\';
-			*string_buffer++ = (char)  ('0' + (character / 100));
-			*string_buffer++ = (char)  ('0' + (character / 10) % 10);
-			character = (uint8_t)('0' + (character) % 10);
-		}
-        *string_buffer++ = (char)character; // Copy the character
-    }
-    *string_buffer = 0; // Null-terminate the string
-    return(string_buffer); // and return
-}
-
-static char *
-_dnssd_svcb_get_string_from_domain_name(const uint8_t *source, char *string_buffer)
-{
-    const uint8_t *limit = source + DNSSD_MAX_DOMAIN_NAME;
-
-	if (*source == 0) {
-		*string_buffer++ = '.'; // Special case: For root, just write a dot
-	}
-
-    while (*source) {
-		if (source + 1 + *source >= limit) {
-			return NULL;
-		}
-        string_buffer = _dnssd_svcb_convert_label_to_string(source, string_buffer);
-		if (string_buffer == NULL) {
-			return NULL;
-		}
-        source += 1 + *source;
-        *string_buffer++ = '.'; // Write the dot after the label
-    }
-
-    *string_buffer++ = 0; // Null-terminate the string
-    return string_buffer; // and return
-}
-
-char *
-dnssd_svcb_copy_service_name_string(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return NULL;
-	}
-
-	buffer += sizeof(uint16_t);
-	buffer_size -= sizeof(uint16_t);
-
-	size_t service_name_length = 0;
-	if (!_dnssd_svcb_get_service_name_length(buffer, buffer_size, &service_name_length)) {
-		return NULL;
-	}
-
-	char *name_str = (char *)mdns_calloc(1, DNSSD_MAX_ESCAPED_DOMAIN_NAME);
-	if (_dnssd_svcb_get_string_from_domain_name(buffer, name_str) == NULL) {
-		ForgetMem(&name_str);
-		return NULL;
-	}
-	return name_str;
-}
-
-bool
-dnssd_svcb_service_name_is_empty(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return false;
-	}
-
-	buffer += sizeof(uint16_t);
-	buffer_size -= sizeof(uint16_t);
-
-	size_t service_name_length = 0;
-	if (!_dnssd_svcb_get_service_name_length(buffer, buffer_size, &service_name_length)) {
-		return false;
-	}
-
-	// If the label length is 1, it's just an empty ".".
-	return (service_name_length == 1);
-}
-
-const uint8_t *
-dnssd_svcb_get_service_name_raw(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return NULL;
-	}
-
-	buffer += sizeof(uint16_t);
-	buffer_size -= sizeof(uint16_t);
-
-	size_t service_name_length = 0;
-	if (!_dnssd_svcb_get_service_name_length(buffer, buffer_size, &service_name_length)) {
-		return NULL;
-	}
-
-	return buffer;
-}
-
-static bool
-_dnssd_svcb_extract_values(const uint8_t *buffer, size_t buffer_size,
-						   dnssd_svcb_key_t match_key, _dnssd_svcb_access_value_block_t value_block)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return false;
-	}
-
-	const uint16_t *priority_p = (const uint16_t *)buffer;
-	uint16_t priority = (uint16_t)htons(*priority_p);
-	if (priority == 0) {
-		// Alias form, no value
-		return false;
-	}
-
-	buffer += sizeof(uint16_t);
-	buffer_size -= sizeof(uint16_t);
-
-	size_t service_name_length = 0;
-	if (!_dnssd_svcb_get_service_name_length(buffer, buffer_size, &service_name_length)) {
-		return false;
-	}
-
-	buffer += service_name_length;
-	buffer_size -= service_name_length;
-
-	while (buffer != NULL && buffer_size >= (sizeof(uint16_t) + sizeof(uint16_t))) {
-		const uint16_t *param_key_p = (const uint16_t *)buffer;
-		uint16_t param_key = (uint16_t)htons(*param_key_p);
-
-		buffer += sizeof(uint16_t);
-		buffer_size -= sizeof(uint16_t);
-
-		const uint16_t *param_value_length_p = (const uint16_t *)buffer;
-		uint16_t param_value_length = (uint16_t)htons(*param_value_length_p);
-
-		buffer += sizeof(uint16_t);
-		buffer_size -= sizeof(uint16_t);
-
-		if (param_value_length > buffer_size) {
-			break;
-		}
-
-		if (match_key == param_key) {
-			bool continue_looping = value_block(buffer, param_value_length);
-			if (!continue_looping) {
-				break;
-			}
-		}
-
-		buffer += param_value_length;
-		buffer_size -= param_value_length;
-	}
-
-	return true;
-}
-
-bool
-dnssd_svcb_is_valid(const uint8_t *buffer, size_t buffer_size)
-{
-	if (buffer_size < sizeof(uint16_t)) {
-		return false;
-	}
-
-	uint16_t priority = dnssd_svcb_get_priority(buffer, buffer_size);
-	if (priority == 0) {
-		// Alias forms with an empty name are treated as non-existent
-		if (dnssd_svcb_service_name_is_empty(buffer, buffer_size)) {
-			return false;
-		}
-		return true;
-	}
-
-	__block bool invalid_mandatory_value = false;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_mandatory, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size > 0) {
-			if ((value_size % sizeof(uint16_t)) != 0) {
-				// Value must be a list of keys, as 16-bit integers
-				invalid_mandatory_value = true;
-			} else {
-				const uint16_t mandatory_key_count = (uint16_t)(value_size / sizeof(uint16_t));
-				for (uint16_t i = 0; i < mandatory_key_count && !invalid_mandatory_value; i++) {
-					const uint16_t *param_key_p = ((const uint16_t *)value) + i;
-					uint16_t param_key = (uint16_t)htons(*param_key_p);
-					switch (param_key) {
-						case dnssd_svcb_key_mandatory:
-							// Mandatory key cannot be listed
-							invalid_mandatory_value = true;
-							break;
-						case dnssd_svcb_key_alpn:
-						case dnssd_svcb_key_no_default_alpn:
-						case dnssd_svcb_key_port:
-						case dnssd_svcb_key_ipv4_hint:
-						case dnssd_svcb_key_ech_config:
-						case dnssd_svcb_key_ipv6_hint:
-						case dnssd_svcb_key_doh_uri:
-						case dnssd_svcb_key_odoh_config:
-						case dnssd_svcb_key_doh_path:
-							// Known keys are fine
-							break;
-						default:
-							// Unknown mandatory key means we should ignore the record
-							invalid_mandatory_value = true;
-							break;
-					}
-				}
-			}
-		}
-		return false;
-	});
-	if (invalid_mandatory_value) {
-		return false;
-	} else {
-		return true;
-	}
-}
-
-uint16_t
-dnssd_svcb_get_port(const uint8_t *buffer, size_t buffer_size)
-{
-	__block uint16_t port = false;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_port, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size == sizeof(uint16_t)) {
-			port = (uint16_t)htons(*(const uint16_t *)value);
-		}
-		return false;
-	});
-	return port;
-}
-
-char *
-dnssd_svcb_copy_doh_uri(const uint8_t *buffer, size_t buffer_size)
-{
-	__block char *doh_uri = NULL;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_doh_uri, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size > 0) {
-			asprintf(&doh_uri, "%.*s", (int)value_size, value);
-		}
-		return false;
-	});
-	return doh_uri;
-}
-
-char *
-dnssd_svcb_copy_doh_path(const uint8_t *buffer, size_t buffer_size)
-{
-	__block char *doh_path = NULL;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_doh_path, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size > 0) {
-			asprintf(&doh_path, "%.*s", (int)value_size, value);
-		}
-		return false;
-	});
-	return doh_path;
-}
-
-uint8_t *
-dnssd_svcb_copy_ech_config(const uint8_t *buffer, size_t buffer_size, size_t *out_length)
-{
-	__block uint8_t *ech_config = NULL;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_ech_config, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size > 0) {
-			ech_config = (uint8_t *)mdns_calloc(1, value_size);
-			*out_length = value_size;
-			memcpy(ech_config, value, value_size);
-		}
-		return false;
-	});
-	return ech_config;
-}
-
-uint8_t *
-dnssd_svcb_copy_odoh_config(const uint8_t *buffer, size_t buffer_size, size_t *out_length)
-{
-	__block uint8_t *odoh_config = NULL;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_odoh_config, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && value_size > 0) {
-			odoh_config = (uint8_t *)mdns_calloc(1, value_size);
-			*out_length = value_size;
-			memcpy(odoh_config, value, value_size);
-		}
-		return false;
-	});
-	return odoh_config;
-}
-
-void
-dnssd_svcb_access_alpn_values(const uint8_t *buffer, size_t buffer_size,
-							  DNSSD_NOESCAPE _dnssd_svcb_access_alpn_t block)
-{
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_alpn, ^bool(const void *value, size_t value_size) {
-		if (value != NULL) {
-			size_t value_read = 0;
-			while (value_size > 0 && value_read < value_size) {
-				char alpn_value[UINT8_MAX] = "";
-
-				uint8_t alpn_length = *(((const uint8_t *)value) + value_read);
-				value_read++;
-
-				if (value_read + alpn_length > value_size) {
-					break;
-				}
-
-				memcpy(alpn_value, ((const uint8_t *)value) + value_read, alpn_length);
-				if (!block((const char *)alpn_value)) {
-					break;
-				}
-				value_read += alpn_length;
-			}
-		}
-		return false;
-	});
-}
-
-void
-dnssd_svcb_access_address_hints(const uint8_t *buffer, size_t buffer_size, DNSSD_NOESCAPE _dnssd_svcb_access_address_t block)
-{
-	__block bool continue_enumerating = true;
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_ipv4_hint, ^bool(const void *value, size_t value_size) {
-		if (value != NULL && (value_size % sizeof(struct in_addr)) == 0) {
-			size_t value_read = 0;
-			while (value_read < value_size) {
-				struct sockaddr_in v4addr;
-				memset(&v4addr, 0, sizeof(v4addr));
-				v4addr.sin_family = AF_INET;
-				v4addr.sin_len = sizeof(v4addr);
-				memcpy(&v4addr.sin_addr, ((const uint8_t *)value) + value_read, sizeof(struct in_addr));
-				continue_enumerating = block((const struct sockaddr *)&v4addr);
-				if (!continue_enumerating) {
-					break;
-				}
-				value_read += sizeof(struct in_addr);
-			}
-		}
-		return false;
-	});
-	if (!continue_enumerating) {
-		return;
-	}
-	(void)_dnssd_svcb_extract_values(buffer, buffer_size, dnssd_svcb_key_ipv6_hint, ^bool(const void *value, size_t value_size) {
-
-		if (value != NULL && (value_size % sizeof(struct in6_addr)) == 0) {
-			size_t value_read = 0;
-			while (value_read < value_size) {
-				struct sockaddr_in6 v6addr;
-				memset(&v6addr, 0, sizeof(v6addr));
-				v6addr.sin6_family = AF_INET6;
-				v6addr.sin6_len = sizeof(v6addr);
-				memcpy(&v6addr.sin6_addr, ((const uint8_t *)value) + value_read, sizeof(struct in6_addr));
-				continue_enumerating = block((const struct sockaddr *)&v6addr);
-				if (!continue_enumerating) {
-					break;
-				}
-				value_read += sizeof(struct in6_addr);
-			}
-		}
-		return false;
-	});
-}
diff --git a/mDNSMacOSX/dnssd_svcb.h b/mDNSMacOSX/dnssd_svcb.h
deleted file mode 100644
index 46b4361..0000000
--- a/mDNSMacOSX/dnssd_svcb.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple 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.
- */
-
-#ifndef __DNSSD_SVCB_H__
-#define __DNSSD_SVCB_H__
-
-#include "dnssd_private.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool
-dnssd_svcb_is_valid(const uint8_t *buffer, size_t buffer_size);
-
-bool
-dnssd_svcb_is_alias(const uint8_t *buffer, size_t buffer_size);
-
-uint16_t
-dnssd_svcb_get_priority(const uint8_t *buffer, size_t buffer_size);
-
-bool
-dnssd_svcb_service_name_is_empty(const uint8_t *buffer, size_t buffer_size);
-
-char *
-dnssd_svcb_copy_service_name_string(const uint8_t *buffer, size_t buffer_size);
-
-const uint8_t *
-dnssd_svcb_get_service_name_raw(const uint8_t *buffer, size_t buffer_size);
-
-uint16_t
-dnssd_svcb_get_port(const uint8_t *buffer, size_t buffer_size);
-
-char *
-dnssd_svcb_copy_doh_uri(const uint8_t *buffer, size_t buffer_size);
-
-char *
-dnssd_svcb_copy_doh_path(const uint8_t *buffer, size_t buffer_size);
-
-uint8_t *
-dnssd_svcb_copy_ech_config(const uint8_t *buffer, size_t buffer_size,
-						   size_t *out_length);
-
-uint8_t *
-dnssd_svcb_copy_odoh_config(const uint8_t *buffer, size_t buffer_size,
-							size_t *out_length);
-
-#ifdef __BLOCKS__
-
-typedef bool (^_dnssd_svcb_access_alpn_t)(const char *alpn);
-
-void
-dnssd_svcb_access_alpn_values(const uint8_t *buffer, size_t buffer_size,
-							  DNSSD_NOESCAPE _dnssd_svcb_access_alpn_t block);
-
-typedef bool (^_dnssd_svcb_access_address_t)(const struct sockaddr *address);
-
-void
-dnssd_svcb_access_address_hints(const uint8_t *buffer, size_t buffer_size,
-								DNSSD_NOESCAPE _dnssd_svcb_access_address_t block);
-
-#endif //  __BLOCKS__
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // __DNSSD_SVCB_H__
diff --git a/mDNSMacOSX/dnssd_xpc.c b/mDNSMacOSX/dnssd_xpc.c
deleted file mode 100644
index eddee56..0000000
--- a/mDNSMacOSX/dnssd_xpc.c
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "dnssd_private.h"
-#include "dnssd_xpc.h"
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - XPC Dictionary Helper Declarations
-
-static int32_t
-_dnssd_xpc_dictionary_get_int32(xpc_object_t dict, const char *key, bool *out_valid);
-
-static int64_t
-_dnssd_xpc_dictionary_get_int64(xpc_object_t dict, const char *key, bool *out_valid);
-
-static int64_t
-_dnssd_xpc_dictionary_get_int64_limited(xpc_object_t dict, const char *key, int64_t min, int64_t max, bool *out_valid);
-
-static uint16_t
-_dnssd_xpc_dictionary_get_uint16(xpc_object_t dict, const char *key, bool *out_valid);
-
-static uint32_t
-_dnssd_xpc_dictionary_get_uint32(xpc_object_t dict, const char *key, bool *out_valid);
-
-static uint64_t
-_dnssd_xpc_dictionary_get_uint64(xpc_object_t dict, const char *key, bool *out_valid);
-
-static uint64_t
-_dnssd_xpc_dictionary_get_uint64_limited(xpc_object_t dict, const char *key, uint64_t min, uint64_t max,
-	bool *out_valid);
-
-static xpc_object_t _Nullable
-_dnssd_xpc_dictionary_get_value(xpc_object_t dict, const char *key, xpc_type_t type);
-
-//======================================================================================================================
-// MARK: - Top-Level Message Dictionaries
-
-#define DNSSD_XPC_MESSAGE_KEY_COMMAND	"command"
-#define DNSSD_XPC_MESSAGE_KEY_ERROR		"error"
-#define DNSSD_XPC_MESSAGE_KEY_ID		"id"
-#define DNSSD_XPC_MESSAGE_KEY_PARAMS	"params"
-#define DNSSD_XPC_MESSAGE_KEY_RESULTS	"results"
-
-//======================================================================================================================
-
-const char * _Nullable
-dnssd_xpc_message_get_command(xpc_object_t msg)
-{
-	return xpc_dictionary_get_string(msg, DNSSD_XPC_MESSAGE_KEY_COMMAND);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_message_set_command(xpc_object_t msg, const char *command)
-{
-	xpc_dictionary_set_string(msg, DNSSD_XPC_MESSAGE_KEY_COMMAND, command);
-}
-
-//======================================================================================================================
-
-DNSServiceErrorType
-dnssd_xpc_message_get_error(xpc_object_t msg, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_int32(msg, DNSSD_XPC_MESSAGE_KEY_ERROR, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_message_set_error(xpc_object_t msg, DNSServiceErrorType error)
-{
-	xpc_dictionary_set_int64(msg, DNSSD_XPC_MESSAGE_KEY_ERROR, error);
-}
-
-//======================================================================================================================
-
-uint64_t
-dnssd_xpc_message_get_id(xpc_object_t msg, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint64(msg, DNSSD_XPC_MESSAGE_KEY_ID, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_message_set_id(xpc_object_t msg, uint64_t ident)
-{
-	xpc_dictionary_set_uint64(msg, DNSSD_XPC_MESSAGE_KEY_ID, ident);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_message_get_parameters(xpc_object_t msg)
-{
-	return xpc_dictionary_get_dictionary(msg, DNSSD_XPC_MESSAGE_KEY_PARAMS);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_message_set_parameters(xpc_object_t msg, xpc_object_t params)
-{
-	xpc_dictionary_set_value(msg, DNSSD_XPC_MESSAGE_KEY_PARAMS, params);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_message_get_results(xpc_object_t msg)
-{
-	return xpc_dictionary_get_array(msg, DNSSD_XPC_MESSAGE_KEY_RESULTS);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_message_set_results(xpc_object_t msg, xpc_object_t results)
-{
-	xpc_dictionary_set_value(msg, DNSSD_XPC_MESSAGE_KEY_RESULTS, results);
-}
-
-//======================================================================================================================
-// MARK: - Parameter Dictionaries
-
-#define DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID				"account_id"
-#define DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID			"delegate_id"
-#define DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG		"fallback_config"
-#define DNSSD_XPC_PARAMETERS_KEY_FLAGS					"flags"
-#define DNSSD_XPC_PARAMETERS_KEY_HOSTNAME				"hostname"
-#define DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX		"interface_index"
-#define DNSSD_XPC_PARAMETERS_KEY_LOG_PRIVACY_LEVEL		"log_privacy_level"
-#define DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS			"need_auth_tags"
-#define DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION		"need_encryption"
-#define DNSSD_XPC_PARAMETERS_KEY_PROHIBIT_ENCRYPTED_DNS	"prohibit_encrypted_dns"
-#define DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS				"protocols"
-#define DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS			"resolver_uuids"
-#define DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME			"service_scheme"
-#define DNSSD_XPC_PARAMETERS_KEY_USE_FAILOVER			"use_failover"
-#define DNSSD_XPC_PARAMETERS_KEY_VALIDATION_DATA		"validation_data"
-
-//======================================================================================================================
-
-pid_t
-dnssd_xpc_parameters_get_delegate_pid(xpc_object_t params, bool *out_valid)
-{
-	return (pid_t)_dnssd_xpc_dictionary_get_int64(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_delegate_pid(xpc_object_t params, pid_t pid)
-{
-	xpc_dictionary_set_int64(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, pid);
-}
-
-//======================================================================================================================
-
-const uint8_t *
-dnssd_xpc_parameters_get_delegate_uuid(xpc_object_t params)
-{
-	return xpc_dictionary_get_uuid(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_delegate_uuid(xpc_object_t params, uuid_t uuid)
-{
-	xpc_dictionary_set_uuid(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, uuid);
-}
-
-//======================================================================================================================
-
-audit_token_t * _Nullable
-dnssd_xpc_parameters_get_delegate_audit_token(const xpc_object_t params, audit_token_t * const audit_token_storage)
-{
-	size_t size;
-	const void * const data = xpc_dictionary_get_data(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, &size);
-	if (data && (size == sizeof(*audit_token_storage))) {
-		memcpy(audit_token_storage, data, size);
-		return audit_token_storage;
-	} else {
-		return NULL;
-	}
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_delegate_audit_token(const xpc_object_t params, const audit_token_t * const audit_token)
-{
-	xpc_dictionary_set_data(params, DNSSD_XPC_PARAMETERS_KEY_DELEGATE_ID, audit_token, sizeof(*audit_token));
-}
-
-//======================================================================================================================
-
-DNSServiceFlags
-dnssd_xpc_parameters_get_flags(xpc_object_t params, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_FLAGS, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_flags(xpc_object_t params, DNSServiceFlags flags)
-{
-	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_FLAGS, flags);
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_xpc_parameters_get_account_id(xpc_object_t params)
-{
-	return xpc_dictionary_get_string(params, DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_account_id(xpc_object_t params, const char *account_id)
-{
-	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_ACCOUNT_ID, account_id);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_parameters_get_hostname_object(xpc_object_t params)
-{
-	return _dnssd_xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_HOSTNAME, XPC_TYPE_STRING);
-}
-
-//======================================================================================================================
-
-const char *
-dnssd_xpc_parameters_get_hostname(xpc_object_t params)
-{
-	return xpc_dictionary_get_string(params, DNSSD_XPC_PARAMETERS_KEY_HOSTNAME);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_hostname(xpc_object_t params, const char *hostname)
-{
-	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_HOSTNAME, hostname);
-}
-
-//======================================================================================================================
-
-uint32_t
-dnssd_xpc_parameters_get_interface_index(xpc_object_t params, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_interface_index(xpc_object_t params, uint32_t interface_index)
-{
-	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_INTERFACE_INDEX, interface_index);
-}
-
-//======================================================================================================================
-
-bool
-dnssd_xpc_parameters_get_need_authentication_tags(xpc_object_t params)
-{
-	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_need_authentication_tags(xpc_object_t params, bool need_auth_tags)
-{
-	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_AUTH_TAGS, need_auth_tags);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_need_encrypted_query(xpc_object_t params, bool need, _Nullable xpc_object_t fallback_config)
-{
-	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION, need);
-	if (fallback_config != NULL) {
-		xpc_dictionary_set_value(params, DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG, fallback_config);
-	}
-}
-
-//======================================================================================================================
-
-bool
-dnssd_xpc_parameters_get_need_encrypted_query(xpc_object_t params)
-{
-	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_NEED_ENCRYPTION);
-}
-
-//======================================================================================================================
-
-xpc_object_t _Nullable
-dnssd_xpc_parameters_get_fallback_config(xpc_object_t params)
-{
-	return xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_FALLBACK_CONFIG);
-}
-
-//======================================================================================================================
-
-xpc_object_t _Nullable
-dnssd_xpc_parameters_get_resolver_uuid_array(xpc_object_t params)
-{
-	return xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_add_resolver_uuid(xpc_object_t params, uuid_t _Nonnull uuid)
-{
-	xpc_object_t resolver_uuid_array = xpc_dictionary_get_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS);
-	if (resolver_uuid_array == NULL) {
-		resolver_uuid_array = xpc_array_create(NULL, 0);
-		xpc_dictionary_set_value(params, DNSSD_XPC_PARAMETERS_KEY_RESOLVER_UUIDS, resolver_uuid_array);
-		xpc_object_t tmp = resolver_uuid_array;
-		xpc_forget(&tmp);
-	}
-	xpc_array_set_uuid(resolver_uuid_array, XPC_ARRAY_APPEND, uuid);
-}
-
-//======================================================================================================================
-
-DNSServiceProtocol
-dnssd_xpc_parameters_get_protocols(xpc_object_t params, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint32(params, DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_protocols(xpc_object_t params, DNSServiceProtocol protocols)
-{
-	xpc_dictionary_set_uint64(params, DNSSD_XPC_PARAMETERS_KEY_PROTOCOLS, protocols);
-}
-
-//======================================================================================================================
-
-const char * _Nullable
-dnssd_xpc_parameters_get_service_scheme(xpc_object_t params)
-{
-	return xpc_dictionary_get_string(params, DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_service_scheme(xpc_object_t params, const char *service_scheme)
-{
-	xpc_dictionary_set_string(params, DNSSD_XPC_PARAMETERS_KEY_SERVICE_SCHEME, service_scheme);
-}
-
-//======================================================================================================================
-
-bool
-dnssd_xpc_parameters_get_use_failover(const xpc_object_t params)
-{
-	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_USE_FAILOVER);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_use_failover(const xpc_object_t params, const bool use_failover)
-{
-	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_USE_FAILOVER, use_failover);
-}
-
-//======================================================================================================================
-
-dnssd_log_privacy_level_t
-dnssd_xpc_parameters_get_log_privacy_level(const xpc_object_t params)
-{
-	bool valid;
-	// Make sure that dnssd_log_privacy_level_t is indeed a 32-bit signed integer.
-	check_compile_time_code(sizeof(dnssd_log_privacy_level_t) == sizeof(int32_t));
-	check_compile_time_code(((dnssd_log_privacy_level_t)-1) < 0);
-	const dnssd_log_privacy_level_t level = _dnssd_xpc_dictionary_get_int32(params,
-		DNSSD_XPC_PARAMETERS_KEY_LOG_PRIVACY_LEVEL, &valid);
-	if (valid) {
-		// A default case isn't used to allow the compiler to catch missing dnssd_log_privacy_level_t enum values.
-		switch (level) {
-			case dnssd_log_privacy_level_default:
-			case dnssd_log_privacy_level_private:
-				return level;
-		}
-	}
-	return dnssd_log_privacy_level_default;
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_log_privacy_level(const xpc_object_t params, const dnssd_log_privacy_level_t level)
-{
-	xpc_dictionary_set_int64(params, DNSSD_XPC_PARAMETERS_KEY_LOG_PRIVACY_LEVEL, level);
-}
-
-//======================================================================================================================
-
-const uint8_t *
-dnssd_xpc_parameters_get_validation_data(const xpc_object_t params, size_t * const out_length)
-{
-	return (const uint8_t *)xpc_dictionary_get_data(params, DNSSD_XPC_PARAMETERS_KEY_VALIDATION_DATA, out_length);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_validation_data(const xpc_object_t params, const uint8_t * const data_ptr,
-	const size_t data_len)
-{
-	xpc_dictionary_set_data(params, DNSSD_XPC_PARAMETERS_KEY_VALIDATION_DATA, data_ptr, data_len);
-}
-
-//======================================================================================================================
-
-bool
-dnssd_xpc_parameters_get_prohibit_encrypted_dns(const xpc_object_t params)
-{
-	return xpc_dictionary_get_bool(params, DNSSD_XPC_PARAMETERS_KEY_PROHIBIT_ENCRYPTED_DNS);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_parameters_set_prohibit_encrypted_dns(const xpc_object_t params, const bool prohibit)
-{
-	xpc_dictionary_set_bool(params, DNSSD_XPC_PARAMETERS_KEY_PROHIBIT_ENCRYPTED_DNS, prohibit);
-}
-
-//======================================================================================================================
-// MARK: - Result Dictionaries
-
-#define DNSSD_XPC_RESULT_KEY_AUTH_TAG			"auth_tag"
-#define DNSSD_XPC_RESULT_KEY_CNAME_UPDATE		"cname_update"
-#define DNSSD_XPC_RESULT_KEY_ERROR				"error"
-#define DNSSD_XPC_RESULT_KEY_FLAGS				"flags"
-#define DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX	"interface_index"
-#define DNSSD_XPC_RESULT_KEY_NEGATIVE_REASON	"negative_reason"
-#define DNSSD_XPC_RESULT_KEY_PROVIDER_NAME		"provider_name"
-#define DNSSD_XPC_RESULT_KEY_RECORD_CLASS		"rclass"
-#define DNSSD_XPC_RESULT_KEY_RECORD_DATA		"rdata"
-#define DNSSD_XPC_RESULT_KEY_RECORD_NAME		"rname"
-#define DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL	"rprotocol"
-#define DNSSD_XPC_RESULT_KEY_RECORD_TYPE		"rtype"
-#define DNSSD_XPC_RESULT_KEY_TRACKER_HOSTNAME	"tracker_hostname"
-#define DNSSD_XPC_RESULT_KEY_TRACKER_OWNER		"tracker_owner"
-#define DNSSD_XPC_RESULT_KEY_TRACKER_APPROVED	"tracker_approved"
-#define DNSSD_XPC_RESULT_KEY_VALIDATION_DATA	"validation_data"
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_authentication_tag_object(xpc_object_t result)
-{
-	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_AUTH_TAG, XPC_TYPE_DATA);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_authentication_tag(xpc_object_t result, const void *auth_tag_ptr, size_t auth_tag_len)
-{
-	xpc_dictionary_set_data(result, DNSSD_XPC_RESULT_KEY_AUTH_TAG, auth_tag_ptr, auth_tag_len);
-}
-
-//======================================================================================================================
-
-DNSServiceErrorType
-dnssd_xpc_result_get_error(xpc_object_t result, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_int32(result, DNSSD_XPC_RESULT_KEY_ERROR, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_error(xpc_object_t result, DNSServiceErrorType error)
-{
-	xpc_dictionary_set_int64(result, DNSSD_XPC_RESULT_KEY_ERROR, error);
-}
-
-//======================================================================================================================
-
-DNSServiceFlags
-dnssd_xpc_result_get_flags(xpc_object_t result, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint32(result, DNSSD_XPC_RESULT_KEY_FLAGS, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_flags(xpc_object_t result, DNSServiceFlags flags)
-{
-	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_FLAGS, flags);
-}
-
-//======================================================================================================================
-
-uint32_t
-dnssd_xpc_result_get_interface_index(xpc_object_t result, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint32(result, DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_interface_index(xpc_object_t result, uint32_t interface_index)
-{
-	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_INTERFACE_INDEX, interface_index);
-}
-
-//======================================================================================================================
-
-uint16_t
-dnssd_xpc_result_get_record_class(xpc_object_t result, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_CLASS, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_record_class(xpc_object_t result, uint16_t class)
-{
-	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_CLASS, class);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_record_data_object(xpc_object_t result)
-{
-	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_RECORD_DATA, XPC_TYPE_DATA);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_record_data(xpc_object_t result, const void * const data_ptr, const size_t data_len)
-{
-	if (data_ptr || (data_len == 0)) {
-		const void * const safe_data_ptr = data_ptr ? data_ptr : "";
-		xpc_dictionary_set_data(result, DNSSD_XPC_RESULT_KEY_RECORD_DATA, safe_data_ptr, data_len);
-	}
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_record_name_object(xpc_object_t result)
-{
-	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_RECORD_NAME, XPC_TYPE_STRING);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_record_name(xpc_object_t result, const char *name)
-{
-	xpc_dictionary_set_string(result, DNSSD_XPC_RESULT_KEY_RECORD_NAME, name);
-}
-
-//======================================================================================================================
-
-uint16_t
-dnssd_xpc_result_get_record_type(xpc_object_t result, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_TYPE, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_record_type(xpc_object_t result, uint16_t type)
-{
-	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_TYPE, type);
-}
-
-//======================================================================================================================
-
-uint16_t
-dnssd_xpc_result_get_record_protocol(xpc_object_t result, bool * out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint16(result, DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL, out_valid);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_record_protocol(xpc_object_t result, uint16_t protocol)
-{
-	xpc_dictionary_set_uint64(result, DNSSD_XPC_RESULT_KEY_RECORD_PROTOCOL, protocol);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_provider_name_object(xpc_object_t result)
-{
-	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_PROVIDER_NAME, XPC_TYPE_STRING);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_provider_name(const xpc_object_t result, const mdns_xpc_string_t name)
-{
-	xpc_dictionary_set_value(result, DNSSD_XPC_RESULT_KEY_PROVIDER_NAME, mdns_xpc_string_to_xpc_object(name));
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_cname_update(xpc_object_t result)
-{
-	return xpc_dictionary_get_array(result, DNSSD_XPC_RESULT_KEY_CNAME_UPDATE);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_cname_update(xpc_object_t result, xpc_object_t cname_update)
-{
-	xpc_dictionary_set_value(result, DNSSD_XPC_RESULT_KEY_CNAME_UPDATE, cname_update);
-}
-
-//======================================================================================================================
-
-mdns_xpc_string_t
-dnssd_xpc_result_get_tracker_hostname(const xpc_object_t result)
-{
-	return mdns_xpc_dictionary_get_string(result, DNSSD_XPC_RESULT_KEY_TRACKER_HOSTNAME);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_tracker_hostname(const xpc_object_t result, const mdns_xpc_string_t hostname)
-{
-	xpc_dictionary_set_value(result, DNSSD_XPC_RESULT_KEY_TRACKER_HOSTNAME, mdns_xpc_string_to_xpc_object(hostname));
-}
-
-//======================================================================================================================
-
-mdns_xpc_string_t
-dnssd_xpc_result_get_tracker_owner(const xpc_object_t result)
-{
-	return mdns_xpc_dictionary_get_string(result, DNSSD_XPC_RESULT_KEY_TRACKER_OWNER);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_tracker_owner(const xpc_object_t result, const mdns_xpc_string_t owner)
-{
-	xpc_dictionary_set_value(result, DNSSD_XPC_RESULT_KEY_TRACKER_OWNER, mdns_xpc_string_to_xpc_object(owner));
-}
-
-//======================================================================================================================
-
-bool
-dnssd_xpc_result_get_tracker_is_approved(const xpc_object_t result)
-{
-	return xpc_dictionary_get_bool(result, DNSSD_XPC_RESULT_KEY_TRACKER_APPROVED);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_tracker_is_approved(const xpc_object_t result, const bool approved)
-{
-	xpc_dictionary_set_bool(result, DNSSD_XPC_RESULT_KEY_TRACKER_APPROVED, approved);
-}
-
-//======================================================================================================================
-
-dnssd_negative_reason_t
-dnssd_xpc_result_get_negative_reason(const xpc_object_t result)
-{
-	bool valid;
-	// Make sure that dnssd_negative_reason_t is indeed a 32-bit signed integer.
-	check_compile_time_code(sizeof(dnssd_negative_reason_t) == sizeof(int32_t));
-	check_compile_time_code(((dnssd_negative_reason_t)-1) < 0);
-	const dnssd_negative_reason_t reason = _dnssd_xpc_dictionary_get_int32(result,
-		DNSSD_XPC_RESULT_KEY_NEGATIVE_REASON, &valid);
-	if (valid) {
-		// A default case isn't used to allow the compiler to catch missing dnssd_negative_reason_t enum values.
-		switch (reason) {
-			case dnssd_negative_reason_none:
-			case dnssd_negative_reason_no_data:
-			case dnssd_negative_reason_nxdomain:
-			case dnssd_negative_reason_query_suppressed:
-			case dnssd_negative_reason_no_dns_service:
-			case dnssd_negative_reason_server_error:
-				return reason;
-		}
-	}
-	return dnssd_negative_reason_none;
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_negative_reason(const xpc_object_t result, const dnssd_negative_reason_t reason)
-{
-	xpc_dictionary_set_int64(result, DNSSD_XPC_RESULT_KEY_NEGATIVE_REASON, reason);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-dnssd_xpc_result_get_validation_data_object(const xpc_object_t result)
-{
-	return _dnssd_xpc_dictionary_get_value(result, DNSSD_XPC_RESULT_KEY_VALIDATION_DATA, XPC_TYPE_DATA);
-}
-
-//======================================================================================================================
-
-void
-dnssd_xpc_result_set_validation_data(const xpc_object_t result, const uint8_t * const data_ptr,
-	const size_t data_len)
-{
-	xpc_dictionary_set_data(result, DNSSD_XPC_RESULT_KEY_VALIDATION_DATA, data_ptr, data_len);
-}
-
-//======================================================================================================================
-// MARK: - XPC Dictionary Helpers
-
-static int32_t
-_dnssd_xpc_dictionary_get_int32(xpc_object_t dict, const char *key, bool *out_valid)
-{
-	return (int32_t)_dnssd_xpc_dictionary_get_int64_limited(dict, key, INT32_MIN, INT32_MAX, out_valid);
-}
-
-//======================================================================================================================
-
-static int64_t
-_dnssd_xpc_dictionary_get_int64(xpc_object_t dict, const char *key, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_int64_limited(dict, key, INT64_MIN, INT64_MAX, out_valid);
-}
-
-//======================================================================================================================
-
-static int64_t
-_dnssd_xpc_dictionary_get_int64_limited(xpc_object_t dict, const char *key, int64_t min, int64_t max, bool *out_valid)
-{
-	int64_t	i64;
-	bool	valid;
-
-	xpc_object_t const value = _dnssd_xpc_dictionary_get_value(dict, key, XPC_TYPE_INT64);
-	if (value) {
-		i64 = xpc_int64_get_value(value);
-		if ((i64 >= min) && (i64 <= max)) {
-			valid	= true;
-		} else {
-			i64		= 0;
-			valid	= false;
-		}
-	} else {
-		i64		= 0;
-		valid	= false;
-	}
-	if (out_valid) {
-		*out_valid = valid;
-	}
-	return i64;
-}
-
-//======================================================================================================================
-
-static uint16_t
-_dnssd_xpc_dictionary_get_uint16(xpc_object_t dict, const char *key, bool *out_valid)
-{
-	return (uint16_t)_dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT16_MAX, out_valid);
-}
-
-//======================================================================================================================
-
-static uint32_t
-_dnssd_xpc_dictionary_get_uint32(xpc_object_t dict, const char *key, bool *out_valid)
-{
-	return (uint32_t)_dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT32_MAX, out_valid);
-}
-
-//======================================================================================================================
-
-static uint64_t
-_dnssd_xpc_dictionary_get_uint64(xpc_object_t dict, const char *key, bool *out_valid)
-{
-	return _dnssd_xpc_dictionary_get_uint64_limited(dict, key, 0, UINT64_MAX, out_valid);
-}
-
-//======================================================================================================================
-
-static uint64_t
-_dnssd_xpc_dictionary_get_uint64_limited(xpc_object_t dict, const char *key, uint64_t min, uint64_t max,
-	bool *out_valid)
-{
-	uint64_t	u64;
-	bool		valid;
-
-	xpc_object_t const value = _dnssd_xpc_dictionary_get_value(dict, key, XPC_TYPE_UINT64);
-	if (value) {
-		u64 = xpc_uint64_get_value(value);
-		if ((u64 >= min) && (u64 <= max)) {
-			valid	= true;
-		} else {
-			u64		= 0;
-			valid	= false;
-		}
-	} else {
-		u64		= 0;
-		valid	= false;
-	}
-	if (out_valid) {
-		*out_valid = valid;
-	}
-	return u64;
-}
-
-//======================================================================================================================
-
-static xpc_object_t
-_dnssd_xpc_dictionary_get_value(xpc_object_t dict, const char *key, xpc_type_t type)
-{
-	xpc_object_t value = xpc_dictionary_get_value(dict, key);
-	return (value && (xpc_get_type(value) == type)) ? value : NULL;
-}
diff --git a/mDNSMacOSX/dnssd_xpc.h b/mDNSMacOSX/dnssd_xpc.h
deleted file mode 100644
index 375a5d6..0000000
--- a/mDNSMacOSX/dnssd_xpc.h
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __DNSSD_XPC_H__
-#define __DNSSD_XPC_H__
-
-#include "dnssd_private.h"
-
-#include <CoreUtils/CommonServices.h>
-#include <dns_sd.h>
-#include <mdns/xpc.h>
-#include <xpc/xpc.h>
-
-#define DNSSD_MACH_SERVICE_NAME	"com.apple.dnssd.service"
-
-#define DNSSD_COMMAND_GETADDRINFO	"getaddrinfo"
-#define DNSSD_COMMAND_KEEPALIVE		"keepalive"
-#define DNSSD_COMMAND_STOP			"stop"
-
-CU_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Gets command as a C string from XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@result
- *		Command, if present. Otherwise, NULL.
- */
-const char * _Nullable
-dnssd_xpc_message_get_command(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Gets error code from XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Error code, if present. Otherwise, 0.
- */
-DNSServiceErrorType
-dnssd_xpc_message_get_error(xpc_object_t msg, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets command instance ID from XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		ID, if present. Otherwise, 0.
- */
-uint64_t
-dnssd_xpc_message_get_id(xpc_object_t msg, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets command parameter dictionary from XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@result
- *		Command parameter dictionary, if present. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_message_get_parameters(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Gets result array from XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@result
- *		Result array, if present. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_message_get_results(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Sets command in XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param command
- *		Command as a C string.
- */
-void
-dnssd_xpc_message_set_command(xpc_object_t msg, const char *command);
-
-/*!
- *	@brief
- *		Sets error code in XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param error
- *		Error code.
- */
-void
-dnssd_xpc_message_set_error(xpc_object_t msg, DNSServiceErrorType error);
-
-/*!
- *	@brief
- *		Sets command instance ID in XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param ident
- *		Command instance ID.
- */
-void
-dnssd_xpc_message_set_id(xpc_object_t msg, uint64_t ident);
-
-/*!
- *	@brief
- *		Sets command parameters dictionary in XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param params
- *		Command parameters dictionary.
- */
-void
-dnssd_xpc_message_set_parameters(xpc_object_t msg, xpc_object_t params);
-
-/*!
- *	@brief
- *		Sets command result array in XPC message.
- *
- *	@param msg
- *		XPC message.
- *
- *	@param results
- *		Command result array.
- */
-void
-dnssd_xpc_message_set_results(xpc_object_t msg, xpc_object_t results);
-
-/*!
- *	@brief
- *		Gets delegate ID as a PID from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Delegate ID as PID, if present. Otherwise, 0.
- */
-pid_t
-dnssd_xpc_parameters_get_delegate_pid(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets delegate ID as a UUID from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		Delegate ID as UUID, if present. Otherwise, NULL.
- */
-const uint8_t * _Nullable
-dnssd_xpc_parameters_get_delegate_uuid(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets a delegate audit token from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param audit_token_storage
- *		Pointer to an audit token to overwrite with parameters dictionary's delegate audit token data.
- *
- *	@result
- *		If the parameters dictionary contains a delegate audit token, this function copies it to
- *		audit_token_storage and returns audit_token_storage. Otherwise, it returns NULL.
- */
-audit_token_t * _Nullable
-dnssd_xpc_parameters_get_delegate_audit_token(xpc_object_t params, audit_token_t *audit_token_storage);
-
-/*!
- *	@brief
- *		Gets flags from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Flags, if present. Otherwise, 0.
- */
-DNSServiceFlags
-dnssd_xpc_parameters_get_flags(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
-*	@brief
-*		Gets account id from a command parameters dictionary.
-*
-*	@param params
-*		Command parameters dictionary.
-*
-*	@result
-*		Account, if present, as a const char *. Otherwise, NULL.
-*/
-const char * _Nullable
-dnssd_xpc_parameters_get_account_id(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets hostname from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		Hostname, if present, as an XPC string object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_parameters_get_hostname_object(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets the hostname from a command parameters dictionary as a C string.
- *
- *	@param params
- *		The command parameters dictionary.
- *
- *	@result
- *		The hostname, if present, as C string. Otherwise, NULL.
- */
-const char * _Nullable
-dnssd_xpc_parameters_get_hostname(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets interface index from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Interface index, if present. Otherwise, 0.
- */
-uint32_t
-dnssd_xpc_parameters_get_interface_index(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets need_auth_tags boolean value from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		A boolean value.
- */
-bool
-dnssd_xpc_parameters_get_need_authentication_tags(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets need encryption boolean value from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		A boolean value.
- */
-bool
-dnssd_xpc_parameters_get_need_encrypted_query(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets fallback resolver configuration dictionary from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		A dictionary containing resolver configuration to use in the absence of encrypted resolvers, or NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_parameters_get_fallback_config(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets resolver UUID array from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		An array of UUIDs, or NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_parameters_get_resolver_uuid_array(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets protocols from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Protocols, if present. Otherwise, 0.
- */
-DNSServiceProtocol
-dnssd_xpc_parameters_get_protocols(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets the service scheme from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		A string containing service scheme for the query, or NULL.
- */
-const char * _Nullable
-dnssd_xpc_parameters_get_service_scheme(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets the truth value of whether DNS service failover should be used from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		True if DNS service failover should be used. Otherwise, false.
- */
-bool
-dnssd_xpc_parameters_get_use_failover(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets the enum value of whether or not the private level logs and the content of state dump should be redacted,
- *		from a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@result
- *		The log privacy level.
- */
-dnssd_log_privacy_level_t
-dnssd_xpc_parameters_get_log_privacy_level(xpc_object_t params);
-
-/*!
- *	@brief
- *		Gets the validation data from a command parameters dictionary
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param out_length
- *		Gets set to the length of the validation data.
- *
- *	@discussion
- *		The returned pointer, if non-NULL, is valid until the getaddrinfo result is released.
- */
-const uint8_t * _Nullable
-dnssd_xpc_parameters_get_validation_data(xpc_object_t params, size_t * _Nullable out_length);
-
-/*!
- *	@brief
- *		Determines whether a command parameters dictionary specifies that use of encrypted DNS protocols is
- *		prohibited for the associated command.
- *
- *	@param params
- *		The command parameters dictionary.
- *
- *	@result
- *		True if use of encrypted DNS protocols is prohibited. Otherwise, false.
- */
-bool
-dnssd_xpc_parameters_get_prohibit_encrypted_dns(xpc_object_t params);
-
-/*!
- *	@brief
- *		Sets delegate ID as a PID in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param pid
- *		PID.
- */
-void
-dnssd_xpc_parameters_set_delegate_pid(xpc_object_t params, pid_t pid);
-
-/*!
- *	@brief
- *		Sets delegate ID as a UUID in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param uuid
- *		UUID.
- */
-void
-dnssd_xpc_parameters_set_delegate_uuid(xpc_object_t params, uuid_t _Nonnull uuid);
-
-/*!
- *	@brief
- *		Sets the delegate audit token in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param audit_token
- *		The delegate audit token.
- */
-void
-dnssd_xpc_parameters_set_delegate_audit_token(xpc_object_t params, const audit_token_t *audit_token);
-
-/*!
- *	@brief
- *		Sets flags in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param flags
- *		Flags.
- */
-void
-dnssd_xpc_parameters_set_flags(xpc_object_t params, DNSServiceFlags flags);
-
-/*!
-*	@brief
-*		Sets account id in a command parameters dictionary.
-*
-*	@param params
-*		Command parameters dictionary.
-*
-*	@param account_id
-*		Account id.
-*/
-void
-dnssd_xpc_parameters_set_account_id(xpc_object_t params, const char *account_id);
-
-/*!
- *	@brief
- *		Sets hostname in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param hostname
- *		Hostname.
- */
-void
-dnssd_xpc_parameters_set_hostname(xpc_object_t params, const char *hostname);
-
-/*!
- *	@brief
- *		Sets interface index in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param interface_index
- *		Interface index.
- */
-void
-dnssd_xpc_parameters_set_interface_index(xpc_object_t params, uint32_t interface_index);
-
-/*!
- *	@brief
- *		Sets whether mDNSResponder should include an authentication tag for each hostname resolution.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param need
- *		Pass <code>true</code> to enable this behavior. Pass <code>false</code> to disable it.
- */
-void
-dnssd_xpc_parameters_set_need_authentication_tags(xpc_object_t params, bool need);
-
-/*!
- *	@brief
- *		Specifies whether or not queries must use encrypted transports to the next DNS server.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param need
- *		Pass <code>true</code> if encrypted queries are required, otherwise, pass <code>false</code>.
- *
- *	@param fallback_config
- *		If not NULL, specify a custom resolver configuration to use if no encrypted resolver configuation is otherwise
- *		available.
- */
-void
-dnssd_xpc_parameters_set_need_encrypted_query(xpc_object_t params, bool need, _Nullable xpc_object_t fallback_config);
-
-/*!
- *	@brief
- *		Add a resolver UUID that represents a resolver configuration registered with the system that should
- *		be applied to this resolution. Multiple UUIDs can be set.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param uuid
- *		UUID of a resolver configuration registered with the system.
- */
-void
-dnssd_xpc_parameters_add_resolver_uuid(xpc_object_t params, uuid_t _Nonnull uuid);
-
-/*!
- *	@brief
- *		Sets a service scheme in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param service_scheme
- *		Service scheme.
- */
-void
-dnssd_xpc_parameters_set_service_scheme(xpc_object_t params, const char *service_scheme);
-
-/*!
- *	@brief
- *		Sets protocols in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param protocols
- *		Protocols.
- */
-void
-dnssd_xpc_parameters_set_protocols(xpc_object_t params, DNSServiceProtocol protocols);
-
-/*!
- *	@brief
- *		Specifies in a command parameters dictionary whether or not DNS service failover should be used if
- *		necessary and applicable.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param use_failover
- *		Pass true if DNS service failover should be used, otherwise, pass false.
- */
-void
-dnssd_xpc_parameters_set_use_failover(xpc_object_t params, bool use_failover);
-
-/*!
- *	@brief
- *		Specifies the log privacy level in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param level
- *		The log privacy level.
- */
-void
-dnssd_xpc_parameters_set_log_privacy_level(xpc_object_t params, dnssd_log_privacy_level_t level);
-
-/*!
- *	@brief
- *		Sets the validation data in a command parameters dictionary.
- *
- *	@param params
- *		Command parameters dictionary.
- *
- *	@param data_ptr
- *		Pointer to the validation data.
- *
- *	@param data_len
- *		Length of the validation data.
- */
-void
-dnssd_xpc_parameters_set_validation_data(xpc_object_t params, const uint8_t *data_ptr, size_t data_len);
-
-/*!
- *	@brief
- *		Specifies in a command parameters dictionary whether use of encrypted DNS protocols is prohibited for
- *		the associated command.
- *
- *	@param params
- *		The command parameters dictionary.
- *
- *	@param prohibit
- *		If use of encrypted DNS protocols is prohibited, pass true. Otherwise, pass false.
- *
- *	@discussion
- *		By default, use of encrypted DNS protocols is not prohibited.
- */
-void
-dnssd_xpc_parameters_set_prohibit_encrypted_dns(xpc_object_t params, bool prohibit);
-
-/*!
- *	@brief
- *		Gets authentication tag from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		Authentication tag, if present, as an XPC data object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_authentication_tag_object(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets error code from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Error code, if present. Otherwise, 0.
- */
-DNSServiceErrorType
-dnssd_xpc_result_get_error(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets flags from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Flags, if present. Otherwise, 0.
- */
-DNSServiceFlags
-dnssd_xpc_result_get_flags(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets interface index from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Interface index, if present. Otherwise, 0.
- */
-uint32_t
-dnssd_xpc_result_get_interface_index(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets record class from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Record class, if present. Otherwise, 0.
- */
-uint16_t
-dnssd_xpc_result_get_record_class(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets record data from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		Record data, if present, as an XPC data object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_record_data_object(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets record name from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		Record name, if present, as an XPC string object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_record_name_object(xpc_object_t result);
-
-/*!
-* @brief
-*      Gets record canonical name from a command result dictionary.
-*
-*  @param result
-*      The command result dictionary.
-*
-*  @result
-*      Record canonical name, if present, as an XPC string object. Otherwise, NULL.
-*/
-xpc_object_t _Nullable
-dnssd_xpc_result_get_record_cname_object(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets record type from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Record type, if present. Otherwise, 0.
- */
-uint16_t
-dnssd_xpc_result_get_record_type(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets used record protocol from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param out_valid
- *		If non-NULL, set to true if value is present and of correct type, otherwise, set to false.
- *
- *	@result
- *		Used record protocol, if present. Otherwise, 0.
- */
-uint16_t
-dnssd_xpc_result_get_record_protocol(xpc_object_t result, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets provider name from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		Provider name, if present, as an XPC string object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_provider_name_object(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets canonical name updates from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		The canonical name update, if present, as an XPC array object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_cname_update(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets the verified tracker hostname in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		The tracker hostname, if present, as an XPC string. Otherwise, NULL.
- *
- * @discussion
- *		No tracker hostname means that the result is not associated with a known tracker.
- */
-mdns_xpc_string_t _Nullable
-dnssd_xpc_result_get_tracker_hostname(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets the tracker owner in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		The tracker owner, if present, as an XPC string. Otherwise, NULL.
- */
-mdns_xpc_string_t _Nullable
-dnssd_xpc_result_get_tracker_owner(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets whether or not the tracker is an approved app domain.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		A boolean indiciating if the domain is approved for the app.
- */
-bool
-dnssd_xpc_result_get_tracker_is_approved(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets the reason why a result is negative from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		The negative reason, if present. Otherwise, dnssd_negative_reason_none.
- */
-dnssd_negative_reason_t
-dnssd_xpc_result_get_negative_reason(xpc_object_t result);
-
-/*!
- *	@brief
- *		Gets validation data from a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@result
- *		Validation data, if present, as an XPC data object. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-dnssd_xpc_result_get_validation_data_object(xpc_object_t result);
-
-/*!
- *	@brief
- *		Sets the authentication tag in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param auth_tag_ptr
- *		Pointer to the authentication tag.
- *
- *	@param auth_tag_len
- *		Length of the authentication tag.
- */
-void
-dnssd_xpc_result_set_authentication_tag(xpc_object_t result, const void *auth_tag_ptr, size_t auth_tag_len);
-
-/*!
- *	@brief
- *		Sets the error code in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param error
- *		Error code.
- */
-void
-dnssd_xpc_result_set_error(xpc_object_t result, DNSServiceErrorType error);
-
-/*!
- *	@brief
- *		Sets flags in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param flags
- *		Flags.
- */
-void
-dnssd_xpc_result_set_flags(xpc_object_t result, DNSServiceFlags flags);
-
-/*!
- *	@brief
- *		Sets interface index in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param interface_index
- *		Interface index.
- */
-void
-dnssd_xpc_result_set_interface_index(xpc_object_t result, uint32_t interface_index);
-
-/*!
- *	@brief
- *		Sets record class in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param class
- *		Record class.
- */
-void
-dnssd_xpc_result_set_record_class(xpc_object_t result, uint16_t class);
-
-/*!
- *	@brief
- *		Sets the record data in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param data_ptr
- *		Pointer to the record data.
- *
- *	@param data_len
- *		Length of the record data.
- */
-void
-dnssd_xpc_result_set_record_data(xpc_object_t result, const void * _Nullable data_ptr, size_t data_len);
-
-/*!
- *	@brief
- *		Sets record name in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param name
- *		Record name.
- */
-void
-dnssd_xpc_result_set_record_name(xpc_object_t result, const char *name);
-
-/*!
-* @brief
-*      Sets record canonical name in a command result dictionary.
-*
-*  @param result
-*      The command result dictionary.
-*
-*  @param cname
-*      Record canonical name.
-*/
-void
-dnssd_xpc_result_set_record_cname(xpc_object_t result, const char *cname);
-
-/*!
- *	@brief
- *		Sets record type in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param type
- *		Record type.
- */
-void
-dnssd_xpc_result_set_record_type(xpc_object_t result, uint16_t type);
-
-/*!
- *	@brief
- *		Sets record protocol in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param protocol
- *		Record protocol.
- */
-void
-dnssd_xpc_result_set_record_protocol(xpc_object_t result, uint16_t protocol);
-
-/*!
- *	@brief
- *		Sets the DNS provider name in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param provider_name
- *		DNS provider name.
- */
-void
-dnssd_xpc_result_set_provider_name(xpc_object_t result, mdns_xpc_string_t provider_name);
-
-/*!
- *	@brief
- *		Sets a canonical name update in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param cname_update
- *		The canonical name update as an array of canonical names as strings.
- */
-void
-dnssd_xpc_result_set_cname_update(xpc_object_t result, xpc_object_t cname_update);
-
-/*!
- *	@brief
- *		Sets the tracker hostname in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param hostname
- *		The hostname that was verified.
- */
-void
-dnssd_xpc_result_set_tracker_hostname(xpc_object_t result, mdns_xpc_string_t hostname);
-
-/*!
- *	@brief
- *		Sets the tracker owner in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param owner
- *		The tracker owner.
- */
-void
-dnssd_xpc_result_set_tracker_owner(xpc_object_t result, mdns_xpc_string_t owner);
-
-/*!
- *	@brief
- *		Sets whether or not the tracker is an approved app domain.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param approved
- *		A boolean indiciating if the domain is approved for the app.
- */
-void
-dnssd_xpc_result_set_tracker_is_approved(xpc_object_t result, bool approved);
-
-/*!
- *	@brief
- *		Sets the reason why a result is negative in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param reason
- *		The negative reason.
- */
-void
-dnssd_xpc_result_set_negative_reason(xpc_object_t result, dnssd_negative_reason_t reason);
-
-/*!
- *	@brief
- *		Sets the validation data in a command result dictionary.
- *
- *	@param result
- *		The command result dictionary.
- *
- *	@param data_ptr
- *		Pointer to the validation data.
- *
- *	@param data_len
- *		Length of the validation data.
- */
-void
-dnssd_xpc_result_set_validation_data(xpc_object_t result, const uint8_t *data_ptr, size_t data_len);
-
-__END_DECLS
-
-CU_ASSUME_NONNULL_END
-
-#endif	// __DNSSD_XPC_H__
diff --git a/mDNSMacOSX/helper-main.c b/mDNSMacOSX/helper-main.c
deleted file mode 100644
index 547547f..0000000
--- a/mDNSMacOSX/helper-main.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * Copyright (c) 2007-2021 Apple 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.
- */
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <sys/cdefs.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <servers/bootstrap.h>
-#include <launch.h>
-#include <pwd.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#include "helper.h"
-#include "helper-server.h"
-#include "helper/server.h"
-#include <xpc/private.h>
-
-#if TARGET_OS_IPHONE
-#define NO_SECURITYFRAMEWORK 1
-#endif
-
-#ifndef LAUNCH_JOBKEY_MACHSERVICES
-#define LAUNCH_JOBKEY_MACHSERVICES "MachServices"
-#define LAUNCH_DATA_MACHPORT 10
-#define launch_data_get_machport launch_data_get_fd
-#endif
-
-os_log_t  log_handle = NULL;
-
-static dispatch_queue_t xpc_queue = NULL;
-static int opt_debug;
-static pthread_t idletimer_thread;
-
-unsigned long maxidle = 15;
-unsigned long actualidle = 3600;
-
-CFRunLoopRef gRunLoop = NULL;
-CFRunLoopTimerRef gTimer = NULL;
-
-
-static void handle_sigterm(int sig)
-{
-    // os_log_debug(log_handle,"entry sig=%d", sig);	Can't use syslog from within a signal handler
-    assert(sig == SIGTERM);
-    helper_exit();
-}
-
-static void initialize_logging(void)
-{
-    log_handle   = os_log_create("com.apple.mDNSResponderHelper", "INFO");
-    
-    if (!log_handle)
-    {
-        // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category
-        os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponderHelper");
-    }
-    
-}
-
-static void initialize_id(void)
-{
-    static char login[] = "_mdnsresponder";
-    struct passwd hardcode;
-    struct passwd *pwd = &hardcode; // getpwnam(login);
-    hardcode.pw_uid = 65;
-    hardcode.pw_gid = 65;
-
-    if (!pwd)
-    {
-        os_log(log_handle, "Could not find account name `%s'.  I will only help root.", login);
-        return;
-    }
-    mDNSResponderUID = pwd->pw_uid;
-    mDNSResponderGID = pwd->pw_gid;
-}
-
-static void diediedie(CFRunLoopTimerRef timer, void *context)
-{
-    os_log_info(log_handle, "entry %p %p %lu", timer, context, actualidle);
-    
-    assert(gTimer == timer);
-    os_log_info(log_handle, "mDNSResponderHelper exiting after [%lu] seconds", actualidle);
-    
-    if (actualidle)
-        helper_exit();
-}
-
-void pause_idle_timer(void)
-{
-    os_log_debug(log_handle,"entry");
-    assert(gTimer);
-    assert(gRunLoop);
-    CFRunLoopRemoveTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
-}
-
-void unpause_idle_timer(void)
-{
-    os_log_debug(log_handle,"entry");
-    assert(gRunLoop);
-    assert(gTimer);
-    CFRunLoopAddTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
-}
-
-void update_idle_timer(void)
-{
-    os_log_debug(log_handle,"entry");
-    assert(gTimer);
-    CFRunLoopTimerSetNextFireDate(gTimer, CFAbsoluteTimeGetCurrent() + actualidle);
-}
-
-static void *idletimer(void *context)
-{
-    os_log_debug(log_handle,"entry context=%p", context);
-    gRunLoop = CFRunLoopGetMain();
-
-    unpause_idle_timer();
-
-    for (;;)
-    {
-        // os_log_debug(log_handle,"Running CFRunLoop");
-        CFRunLoopRun();
-        sleep(1);
-    }
-
-    return NULL;
-}
-
-static int initialize_timer()
-{
-    gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL);
-    int err = 0;
-    os_log_info(log_handle, "mDNSResponderHelper initialize_timer() started");
-
-    if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL)))
-        os_log(log_handle, "Could not start idletimer thread: %s", strerror(err));
-
-    return err;
-}
-
-// Verify Client's Entitlement
-static mDNSBool check_entitlement(xpc_connection_t conn, const char *password)
-{
-    mDNSBool entitled = mDNSfalse;
-    xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password);
-    
-    if (ent)
-    {
-        if (xpc_get_type(ent) == XPC_TYPE_BOOL && xpc_bool_get_value(ent))
-        {
-            entitled = mDNStrue;
-        }
-        xpc_release(ent);
-    }
-    else
-    {
-        os_log(log_handle, "client entitlement is NULL");
-    }
-    
-    if (!entitled)
-        os_log(log_handle, "entitlement check failed -> client is missing entitlement!");
-    
-    return entitled;
-}
-
-
-static void handle_request(xpc_object_t req)
-{
-    mDNSu32 helper_mode = 0;
-    int error_code = 0;
-    
-    xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req);
-    xpc_object_t response = xpc_dictionary_create_reply(req);
-    
-    // switch here based on dictionary to handle different requests from mDNSResponder
-    if ((xpc_dictionary_get_uint64(req, kHelperMode)))
-    {
-        os_log_info(log_handle, "Getting mDNSResponder request mode");
-        helper_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kHelperMode));
-    }
-   
-    switch (helper_mode)
-    {
-        case set_name:
-        {
-#if MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-            const char *old_name;
-            const char *new_name;
-            int pref_key = 0;
-            
-            pref_key = (int)(xpc_dictionary_get_uint64(req, kPrefsNameKey));
-            old_name = xpc_dictionary_get_string(req, kPrefsOldName);
-            new_name = xpc_dictionary_get_string(req, kPrefsNewName);
-            
-            os_log_info(log_handle, "Calling new SetName() oldname: %s newname: %s key:%d", old_name, new_name, pref_key);
-            PreferencesSetName(pref_key, old_name, new_name);
-#else
-            os_log_error(log_handle, "mDNSResponderHelper does not notify users of name changes on this OS");
-            error_code = kHelperErr_UndefinedMode;
-#endif
-            break;
-        }
-            
-        case power_req:
-        {
-            os_log_info(log_handle,"Calling new PowerSleepSystem()");
-            error_code = PowerSleepSystem();
-            break;
-        }
-            
-        case send_wakepkt:
-        {
-            const char *ether_addr;
-            const char *ip_addr;
-            int iteration;
-            unsigned int if_id;
-            
-            if_id = (unsigned int)xpc_dictionary_get_uint64(req, "interface_index");
-            ether_addr = xpc_dictionary_get_string(req, "ethernet_address");
-            ip_addr = xpc_dictionary_get_string(req, "ip_address");
-            iteration = (int)xpc_dictionary_get_uint64(req, "swp_iteration");
-            
-            os_log_info(log_handle, "Calling new SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]",
-                           ether_addr, ip_addr, if_id, iteration);
-            SendWakeupPacket(if_id, ether_addr, ip_addr, iteration);
-            break;
-        }
-            
-        case set_localaddr_cacheentry:
-        {
-            uint32_t if_index;
-            int family;
-            size_t ip_len, eth_len;
-
-            if_index = (uint32_t)xpc_dictionary_get_uint64(req, "slace_ifindex");
-            family   = (int)xpc_dictionary_get_uint64(req, "slace_family");
-
-            const uint8_t * const ip = (const uint8_t *)xpc_dictionary_get_data(req, "slace_ip", &ip_len);
-            if (ip_len != sizeof(v6addr_t))
-            {
-                error_code = kHelperErr_ParamErr;
-                break;
-            }
-
-            const uint8_t * const eth = (const uint8_t *)xpc_dictionary_get_data(req, "slace_eth", &eth_len);
-            if (eth_len != sizeof(ethaddr_t))
-            {
-                error_code = kHelperErr_ParamErr;
-                break;
-            }
-
-            os_log_info(log_handle, "Calling new SetLocalAddressCacheEntry() if_index[%d] family[%d] ", if_index, family);
-
-            SetLocalAddressCacheEntry(if_index, family, ip, eth, &error_code);
-            break;
-        }
-            
-        case send_keepalive:
-        {
-            uint16_t lport, rport, win;
-            uint32_t seq, ack;
-            size_t sadd6_len, dadd6_len;
-            
-            lport = (uint16_t)xpc_dictionary_get_uint64(req, "send_keepalive_lport");
-            rport = (uint16_t)xpc_dictionary_get_uint64(req, "send_keepalive_rport");
-            seq   = (uint32_t)xpc_dictionary_get_uint64(req, "send_keepalive_seq");
-            ack   = (uint32_t)xpc_dictionary_get_uint64(req, "send_keepalive_ack");
-            win   = (uint16_t)xpc_dictionary_get_uint64(req, "send_keepalive_win");
-            
-            const uint8_t * const sadd6 = (const uint8_t *)xpc_dictionary_get_data(req, "send_keepalive_sadd", &sadd6_len);
-            const uint8_t * const dadd6 = (const uint8_t *)xpc_dictionary_get_data(req, "send_keepalive_dadd", &dadd6_len);
-            if ((sadd6_len != sizeof(v6addr_t)) || (dadd6_len != sizeof(v6addr_t)))
-            {
-                error_code = kHelperErr_ParamErr;
-                break;
-            }
-
-            os_log_info(log_handle, "helper-main: handle_request: send_keepalive: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
-                           lport, rport, seq, ack, win);
-            
-            SendKeepalive(sadd6, dadd6, lport, rport, seq, ack, win);
-            break;
-        }
-    
-        case keychain_getsecrets:
-        {
-            unsigned int num_sec  = 0;
-            unsigned long secrets = 0;
-            unsigned int sec_cnt  = 0;
-            
-            os_log_info(log_handle,"Calling new KeyChainGetSecrets()");
-            
-            KeychainGetSecrets(&num_sec, &secrets, &sec_cnt, &error_code);
-            
-            if (response)
-            {
-                xpc_dictionary_set_uint64(response, "keychain_num_secrets", num_sec);
-                xpc_dictionary_set_data(response, "keychain_secrets", (void *)secrets, sec_cnt);
-            }
-            
-            os_log_info(log_handle,"helper-main: handle_request: keychain_getsecrets: num_secrets is %u, secrets is %lu, secrets_Cnt is %u",
-                        num_sec, secrets, sec_cnt);
-            
-            if (secrets)
-                vm_deallocate(mach_task_self(), secrets, sec_cnt);
-            
-            break;
-        }
-            
-        default:
-        {
-            os_log(log_handle, "handle_request: Unrecognized mode!");
-            error_code  = kHelperErr_UndefinedMode;
-            break;
-        }
-    }
-    
-    // Return Response Status back to the client (essentially ACKing the request)
-    if (response)
-    {
-        xpc_dictionary_set_uint64(response, kHelperReplyStatus, kHelperReply_ACK);
-        xpc_dictionary_set_int64(response, kHelperErrCode, error_code);
-        xpc_connection_send_message(remote_conn, response);
-        xpc_release(response);
-    }
-    else
-    {
-        os_log(log_handle, "handle_requests: Response Dictionary could not be created!");
-        return;
-    }
-    
-}
-
-static void accept_client(xpc_connection_t conn)
-{
-    int c_pid = xpc_connection_get_pid(conn);
-    
-    if (!(check_entitlement(conn, kHelperService)))
-    {
-        os_log(log_handle, "accept_client: Helper Client PID[%d] is missing Entitlement. Cancelling connection", c_pid);
-        xpc_connection_cancel(conn);
-        return;
-    }
-    
-    xpc_retain(conn);
-    xpc_connection_set_target_queue(conn, xpc_queue);
-    xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg)
-    {
-        xpc_type_t type = xpc_get_type(req_msg);
-                                         
-        if (type == XPC_TYPE_DICTIONARY)
-        {
-            os_log_info(log_handle,"accept_client:conn:[%p] client[%d](mDNSResponder) requesting service", (void *) conn, c_pid);
-            const bool handled = mhs_handle_client_message(req_msg);
-            if (!handled)
-            {
-                handle_request(req_msg);
-            }
-        }
-        else // We hit this case ONLY if Client Terminated Connection OR Crashed
-        {
-            os_log(log_handle, "accept_client:conn:[%p] client[%d](mDNSResponder) teared down the connection (OR Crashed)", (void *) conn, c_pid);
-            // handle_termination();
-            xpc_release(conn);
-        }
-    });
-    
-    xpc_connection_resume(conn);
-}
-
-
-static void init_helper_service(const char *service_name)
-{
-    
-    xpc_connection_t xpc_listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
-    if (!xpc_listener || xpc_get_type(xpc_listener) != XPC_TYPE_CONNECTION)
-    {
-        os_log(log_handle, "init_helper_service: Error Creating XPC Listener for mDNSResponderHelperService !!");
-        return;
-    }
-    
-    os_log_info(log_handle,"init_helper_service: XPC Listener for mDNSResponderHelperService Listening");
-    
-    xpc_queue = dispatch_queue_create("com.apple.mDNSHelper.service_queue", NULL);
-    
-    xpc_connection_set_event_handler(xpc_listener, ^(xpc_object_t eventmsg)
-    {
-        xpc_type_t type = xpc_get_type(eventmsg);
-                                         
-        if (type == XPC_TYPE_CONNECTION)
-        {
-            os_log_info(log_handle,"init_helper_service: new mDNSResponderHelper Client %p", eventmsg);
-            accept_client(eventmsg);
-        }
-        else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases below
-        {
-            os_log(log_handle, "init_helper_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION));
-            return;
-        }
-        else
-        {
-            os_log(log_handle, "init_helper_service: Unknown EventMsg type");
-            return;
-        }
-    });
-    
-    xpc_connection_resume(xpc_listener);
-}
-
-
-int main(int ac, char *av[])
-{
-    mhs_prologue();
-    char *p = NULL;
-    long n;
-    int ch;
-
-    while ((ch = getopt(ac, av, "dt:")) != -1)
-    {
-        switch (ch)
-        {
-            case 'd':
-                opt_debug = 1;
-                break;
-            case 't':
-                n = strtol(optarg, &p, 0);
-                if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0)
-                {
-                    fprintf(stderr, "Invalid idle timeout: %s\n", optarg);
-                    exit(EXIT_FAILURE);
-                }
-                maxidle = (unsigned long)n;
-                break;
-            case '?':
-            default:
-                fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n");
-                exit(EXIT_FAILURE);
-        }
-    }
-    ac -= optind;
-    av += optind;
-    (void)ac; // Unused
-    (void)av; // Unused
-
-    initialize_logging();
-    initialize_id();
-
-    os_log_info(log_handle,"mDNSResponderHelper Starting to run");
-
-#ifndef NO_SECURITYFRAMEWORK
-    // We should normally be running as a system daemon.  However, that might not be the case in some scenarios (e.g. debugging).
-    // Explicitly ensure that our Keychain operations utilize the system domain.
-    if (opt_debug)
-        SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
-#endif
-
-    if (maxidle)
-        actualidle = maxidle;
-
-    signal(SIGTERM, handle_sigterm);
-
-    if (initialize_timer())
-        exit(EXIT_FAILURE);
-    for (n=0; n<100000; n++)
-        if (!gRunLoop)
-            usleep(100);
-    
-    if (!gRunLoop)
-    {
-        os_log(log_handle, "gRunLoop not set after waiting");
-        exit(EXIT_FAILURE);
-    }
-
-    init_helper_service(kHelperService);
-    os_log_info(log_handle,"mDNSResponderHelper is now running");
-    dispatch_main();
-    
-}
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// For convenience when using the "strings" command, this is the last thing in the file
-// The "@(#) " pattern is a special prefix the "what" command looks for
-const char VersionString_SCCS[] = "@(#) mDNSResponderHelper " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-
-#if _BUILDING_XCODE_PROJECT_
-// If the process crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = VersionString_SCCS + 5;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wlanguage-extension-token"
-asm (".desc ___crashreporter_info__, 0x10");
-#pragma clang diagnostic pop
-#endif
diff --git a/mDNSMacOSX/helper-server.h b/mDNSMacOSX/helper-server.h
deleted file mode 100644
index 8a34274..0000000
--- a/mDNSMacOSX/helper-server.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2007-2011 Apple 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.
- */
-
-#ifndef H_HELPER_SERVER_H
-#define H_HELPER_SERVER_H
-
-extern void pause_idle_timer(void);
-extern void unpause_idle_timer(void);
-extern void update_idle_timer(void);
-extern uid_t mDNSResponderUID;
-extern uid_t mDNSResponderGID;
-extern CFRunLoopRef gRunLoop;
-
-#endif /* H_HELPER_SERVER_H */
diff --git a/mDNSMacOSX/helper-stubs.c b/mDNSMacOSX/helper-stubs.c
deleted file mode 100644
index d1fd9e8..0000000
--- a/mDNSMacOSX/helper-stubs.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (c) 2007-2021 Apple 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
- *
- *     https://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.
- */
-
-#include "helper.h"
-#include "mDNSMacOSX.h"
-#include <dispatch/dispatch.h>
-#include <arpa/inet.h>
-#include <xpc/private.h>
-#include <Block.h>
-#include <mdns/system.h>
-#include "mdns_strict.h"
-
-//
-// Implementation Notes about the HelperQueue:
-//
-// To prevent blocking the main queue, all communications with mDNSResponderHelper should happen on
-// HelperQueue. There are a few calls which are still synchronous and needs to be handled separately
-// case by case.
-//
-// When spawning off the work to the HelperQueue, any arguments that are pointers need to be copied
-// explicitly as they may cease to exist after the call returns. From within the block that is scheduled,
-// arrays defined on the stack can't be referenced and hence it is enclosed them in a struct. If the array is
-// an argument to the function, the blocks can reference them as they are passed in as pointers. But care should
-// be taken to copy them locally as they may cease to exist when the function returns.
-//
-
-
-//*************************************************************************************************************
-// Globals
-static dispatch_queue_t HelperQueue;
-
-static int64_t maxwait_secs = 5LL;
-
-#define mDNSHELPER_DEBUG LogOperation
-
-//*************************************************************************************************************
-// Utility Functions
-
-static void HelperLog(const char *prefix, xpc_object_t o)
-{
-    char *desc = xpc_copy_description(o);
-    mDNSHELPER_DEBUG("HelperLog %s: %s", prefix, desc);
-    mdns_free(desc);
-}
-
-//*************************************************************************************************************
-// XPC Funcs:
-//*************************************************************************************************************
-
-
-mDNSlocal xpc_connection_t Create_Connection(void)
-{
-    xpc_connection_t connection = xpc_connection_create_mach_service(kHelperService, HelperQueue,
-        XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
-    if (connection)
-    {
-        xpc_connection_set_event_handler(connection, ^(xpc_object_t event)
-        {
-            mDNSHELPER_DEBUG("Create_Connection xpc: [%s] \n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
-        });
-        xpc_connection_activate(connection);
-    }
-    return connection;
-}
-
-mDNSlocal int SendDict_ToServer(xpc_object_t msg, xpc_object_t *out_reply)
-{
-    xpc_connection_t connection;
-    dispatch_semaphore_t sem = NULL;
-    __block xpc_object_t reply = NULL;
-    __block int errorcode = kHelperErr_NoResponse;
-    
-    HelperLog("SendDict_ToServer Sending msg to Daemon", msg);
-    
-    connection = Create_Connection();
-    if (!connection)
-    {
-        goto exit;
-    }
-
-    sem = dispatch_semaphore_create(0);
-    if (!sem)
-    {
-        goto exit;
-    }
-    
-    dispatch_retain(sem); // for the block below
-    xpc_connection_send_message_with_reply(connection, msg, HelperQueue, ^(xpc_object_t recv_msg)
-    {
-        const xpc_type_t type = xpc_get_type(recv_msg);
-                                               
-        if (type == XPC_TYPE_DICTIONARY)
-        {
-            HelperLog("SendDict_ToServer Received reply msg from Daemon", recv_msg);
-            uint64_t reply_status = xpc_dictionary_get_uint64(recv_msg, kHelperReplyStatus);
-            errorcode = (int)xpc_dictionary_get_int64(recv_msg, kHelperErrCode);
-            
-            switch (reply_status)
-            {
-                case kHelperReply_ACK:
-                    mDNSHELPER_DEBUG("NoError: successful reply");
-                    break;
-                default:
-                    LogMsg("default: Unexpected reply from Helper");
-                    break;
-            }
-            reply = recv_msg;
-            xpc_retain(reply);
-        }
-        else
-        {
-            LogMsg("SendDict_ToServer Received unexpected reply from daemon [%s]",
-                    xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
-            HelperLog("SendDict_ToServer Unexpected Reply contents", recv_msg);
-        }
-        
-        dispatch_semaphore_signal(sem);
-        dispatch_semaphore_t tmp = sem;
-        MDNS_DISPOSE_DISPATCH(tmp);
-    });
-    
-    if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (maxwait_secs * (int64_t)NSEC_PER_SEC))) != 0)
-    {
-        LogMsg("SendDict_ToServer: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait");
-
-        // If we insist on using a semaphore timeout, then cancel the connection if the timeout is reached.
-        // This forces the reply block to be called if a reply wasn't received to keep things serialized.
-        xpc_connection_cancel(connection);
-        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-    }
-    if (out_reply)
-    {
-        *out_reply = reply;
-        reply = NULL;
-    }
-    
-    mDNSHELPER_DEBUG("SendDict_ToServer returning with errorcode[%d]", errorcode);
-    
-exit:
-    if (connection)
-    {
-        xpc_connection_cancel(connection);
-        MDNS_DISPOSE_XPC(connection);
-    }
-    MDNS_DISPOSE_DISPATCH(sem);
-    MDNS_DISPOSE_XPC(reply);
-    return errorcode;
-}
-
-//**************************************************************************************************************
-
-mDNSexport mStatus mDNSHelperInit()
-{
-    HelperQueue = dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL);
-    if (HelperQueue == NULL)
-    {
-        LogMsg("dispatch_queue_create: Helper queue NULL");
-        return mStatus_NoMemoryErr;
-    }
-    return mStatus_NoError;
-}
-
-void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
-{
-    struct
-    {
-        char oldname[MAX_DOMAIN_LABEL+1];
-        char newname[MAX_DOMAIN_LABEL+1];
-    } names;
-
-    mDNSPlatformMemZero(names.oldname, MAX_DOMAIN_LABEL + 1);
-    mDNSPlatformMemZero(names.newname, MAX_DOMAIN_LABEL + 1);
-
-    ConvertDomainLabelToCString_unescaped(old, names.oldname);
-    
-    if (new)
-        ConvertDomainLabelToCString_unescaped(new, names.newname);
-
-    if ((names.newname[0] != '\0') && (strcmp(names.oldname, names.newname) != 0))
-    {
-        if (key == kmDNSComputerName)
-        {
-            // Original comment regarding why the current encoding is used:
-            // We want to write the new Computer Name to System Preferences, without disturbing the user-selected
-            // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising.
-            // Note that this encoding is not used for the computer name, but since both are set by the same call,
-            // we need to take care to set the name without changing the character set.
-            const mdns_computer_name_opts_t options = mdns_computer_name_opt_keep_current_encoding;
-            const OSStatus err = mdns_system_set_computer_name_with_utf8_cstring(names.newname, kMDNSResponderID, options);
-            if (err)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                    "Failed to set computer name -- name: " PRI_S ", error: %ld", names.newname, (long)err);
-            }
-        }
-        else if (key == kmDNSLocalHostName)
-        {
-            const OSStatus err = mdns_system_set_local_host_name_with_utf8_cstring(names.newname, kMDNSResponderID, false);
-            if (err)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                    "Failed to set local hostname -- name: " PRI_S ", error: %ld", names.newname, (long)err);
-            }
-        }
-    }
-
-#if MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-    mDNSHELPER_DEBUG("mDNSPreferencesSetName: XPC IPC Test oldname %s newname %s", names.oldname, names.newname);
-     
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, set_name);
-    
-    xpc_dictionary_set_uint64(dict, kPrefsNameKey, (uint64_t)key);
-    xpc_dictionary_set_string(dict, kPrefsOldName, names.oldname);
-    xpc_dictionary_set_string(dict, kPrefsNewName, names.newname);
-    
-    SendDict_ToServer(dict, NULL);
-    MDNS_DISPOSE_XPC(dict);
-#endif
-}
-
-void mDNSRequestBPF(const dispatch_queue_t queue, const mhc_bpf_open_result_handler_t handler)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "Requesting BPF from helper");
-    mhc_bpf_open(O_RDWR, queue, handler);
-}
-
-int mDNSPowerSleepSystem(void)
-{
-    int err_code = kHelperErr_NotConnected;
-    
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, power_req);
-    xpc_dictionary_set_uint64(dict, "powerreq_key", 0);
-    xpc_dictionary_set_uint64(dict, "powerreq_interval", 0);
-    
-    err_code = SendDict_ToServer(dict, NULL);
-    MDNS_DISPOSE_XPC(dict);
-
-    mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC returning error_code %d", err_code);
-    return err_code;
-}
-
-int mDNSSetLocalAddressCacheEntry(mDNSu32 ifindex, int family, const v6addr_t ip, const ethaddr_t eth)
-{
-    int err_code = kHelperErr_NotConnected;
-    
-    mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC calling out to Helper: ifindex is [%d] family is [%d]", ifindex, family);
-    
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, set_localaddr_cacheentry);
-    
-    xpc_dictionary_set_uint64(dict, "slace_ifindex", ifindex);
-    xpc_dictionary_set_uint64(dict, "slace_family", (uint64_t)family);
-    
-    xpc_dictionary_set_data(dict, "slace_ip", (const uint8_t*)ip, sizeof(v6addr_t));
-    xpc_dictionary_set_data(dict, "slace_eth", (const uint8_t*)eth, sizeof(ethaddr_t));
-    
-    err_code = SendDict_ToServer(dict, NULL);
-    MDNS_DISPOSE_XPC(dict);
-
-    mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC returning error_code %d", err_code);
-    return err_code;
-}
-
-
-void mDNSNotify(const char *title, const char *msg) // Both strings are UTF-8 text
-{
-    mhc_display_notification(title, msg);
-}
-
-
-int mDNSKeychainGetSecrets(CFArrayRef *result)
-{
-    
-    CFPropertyListRef plist = NULL;
-    CFDataRef bytes = NULL;
-    uint64_t numsecrets = 0;
-    size_t secretsCnt = 0;
-    int error_code = kHelperErr_NotConnected;
-    xpc_object_t reply_dict = NULL;
-    const void *sec = NULL;
-    
-    mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper");
-    
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, keychain_getsecrets);
-
-    SendDict_ToServer(dict, &reply_dict);
- 
-    if (reply_dict != NULL)
-    {
-        numsecrets = xpc_dictionary_get_uint64(reply_dict, "keychain_num_secrets");
-        sec = xpc_dictionary_get_data(reply_dict, "keychain_secrets", &secretsCnt);
-        error_code = (int)xpc_dictionary_get_int64(reply_dict,   kHelperErrCode);
-    }
- 
-    mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper: numsecrets is %u, secretsCnt is %u error_code is %d",
-                     (unsigned int)numsecrets, (unsigned int)secretsCnt, error_code);
-     
-    if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const void*)sec, (CFIndex)secretsCnt, kCFAllocatorNull)))
-    {
-        error_code = kHelperErr_ApiErr;
-        LogMsg("mDNSKeychainGetSecrets: CFDataCreateWithBytesNoCopy failed");
-        goto fin;
-    }
-    
-    if (NULL == (plist = CFPropertyListCreateWithData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL, NULL)))
-    {
-        error_code = kHelperErr_ApiErr;
-        LogMsg("mDNSKeychainGetSecrets: CFPropertyListCreateFromXMLData failed");
-        goto fin;
-    }
-    
-    if (CFArrayGetTypeID() != CFGetTypeID(plist))
-    {
-        error_code = kHelperErr_ApiErr;
-        LogMsg("mDNSKeychainGetSecrets: Unexpected result type");
-        MDNS_DISPOSE_CF_OBJECT(plist);
-        goto fin;
-    }
-    
-    *result = (CFArrayRef)plist;
-    
-    
-fin:
-    MDNS_DISPOSE_CF_OBJECT(bytes);
-    MDNS_DISPOSE_XPC(dict);
-    MDNS_DISPOSE_XPC(reply_dict);
-
-    return error_code;
-}
-
-void mDNSSendWakeupPacket(unsigned int ifid, char *eth_addr, char *ip_addr, int iteration)
-{
-    // (void) ip_addr; // unused
-    // (void) iteration; // unused
-
-    mDNSHELPER_DEBUG("mDNSSendWakeupPacket: Entered ethernet address[%s],ip_address[%s], interface_id[%d], iteration[%d]",
-           eth_addr, ip_addr, ifid, iteration);
-    
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, send_wakepkt);
-    
-    xpc_dictionary_set_uint64(dict, "interface_index", ifid);
-    xpc_dictionary_set_string(dict, "ethernet_address", eth_addr);
-    xpc_dictionary_set_string(dict, "ip_address", ip_addr);
-    xpc_dictionary_set_uint64(dict, "swp_iteration", (uint64_t)iteration);
-    
-    SendDict_ToServer(dict, NULL);
-    MDNS_DISPOSE_XPC(dict);
-
-}
-
-void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win)
-{
-
-    mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
-           lport, rport, seq, ack, win);
-    
-    char buf1[INET6_ADDRSTRLEN];
-    char buf2[INET6_ADDRSTRLEN];
-    
-    buf1[0] = 0;
-    buf2[0] = 0;
-    
-    inet_ntop(AF_INET6, sadd, buf1, sizeof(buf1));
-    inet_ntop(AF_INET6, dadd, buf2, sizeof(buf2));
-    mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: sadd is %s, dadd is %s", buf1, buf2);
-    
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(dict, kHelperMode, send_keepalive);
-    
-    xpc_dictionary_set_data(dict, "send_keepalive_sadd", (const uint8_t*)sadd, sizeof(v6addr_t));
-    xpc_dictionary_set_data(dict, "send_keepalive_dadd", (const uint8_t*)dadd, sizeof(v6addr_t));
-    
-    xpc_dictionary_set_uint64(dict, "send_keepalive_lport", lport);
-    xpc_dictionary_set_uint64(dict, "send_keepalive_rport", rport);
-    xpc_dictionary_set_uint64(dict, "send_keepalive_seq", seq);
-    xpc_dictionary_set_uint64(dict, "send_keepalive_ack", ack);
-    xpc_dictionary_set_uint64(dict, "send_keepalive_win", win);
-    
-    SendDict_ToServer(dict, NULL);
-    MDNS_DISPOSE_XPC(dict);
-
-}
diff --git a/mDNSMacOSX/helper.c b/mDNSMacOSX/helper.c
deleted file mode 100644
index f76d49d..0000000
--- a/mDNSMacOSX/helper.c
+++ /dev/null
@@ -1,1184 +0,0 @@
-/*
- * Copyright (c) 2007-2021 Apple 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
- *
- *     https://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.
- */
-
-#include <sys/cdefs.h>
-#include <arpa/inet.h>
-#include <bsm/libbsm.h>
-#include <mdns/bpf.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/nd6.h>
-#include <netinet6/ipsec.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <TargetConditionals.h>
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <net/bpf.h>
-
-#include "mDNSEmbeddedAPI.h"
-#include "dns_sd.h"
-#include "dnssd_ipc.h"
-#include "helper.h"
-#include "helper-server.h"
-#include "setup_assistant_helper.h"
-#include <stdatomic.h>
-
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-
-#ifndef RTF_IFSCOPE
-#define RTF_IFSCOPE 0x1000000
-#endif
-
-#if TARGET_OS_IPHONE
-#define NO_SECURITYFRAMEWORK 1
-#endif
-
-uid_t mDNSResponderUID;
-gid_t mDNSResponderGID;
-
-void helper_exit()
-{
-    os_log_info(log_handle,"mDNSResponderHelper exiting");
-    exit(0);
-}
-
-int PowerSleepSystem(void)
-{
-    IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL));
-    if (r)
-    {
-        usleep(100000);
-        os_log_info(log_handle, "IOPMSleepSystem %d", r);
-    }
-    update_idle_timer();
-    return r;
-}
-
-void SetLocalAddressCacheEntry(uint32_t ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err)
-{
-    
-#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
-#define IPv6FMTARGS  ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
-    
-    if (family == 4)
-    {
-        os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
-                       ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
-    }
-    else
-    {
-        os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
-                       ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
-    }
-    
-    *err = kHelperErr_DefaultErr;
-    
-    static int s = -1, seq = 0;
-    if (s < 0)
-    {
-        s = socket(PF_ROUTE, SOCK_RAW, 0);
-        if (s < 0)
-            os_log(log_handle, "SetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
-    }
-
-    if (s >= 0)
-    {
-        struct timeval tv;
-        gettimeofday(&tv, 0);
-        if (family == 4)
-        {
-            struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg;
-            memset(&rtmsg, 0, sizeof(rtmsg));
-            
-            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
-            rtmsg.hdr.rtm_version        = RTM_VERSION;
-            rtmsg.hdr.rtm_type           = RTM_ADD;
-            rtmsg.hdr.rtm_index          = (u_short)ifindex;
-            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
-            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
-            rtmsg.hdr.rtm_pid            = 0;
-            rtmsg.hdr.rtm_seq            = seq++;
-            rtmsg.hdr.rtm_errno          = 0;
-            rtmsg.hdr.rtm_use            = 0;
-            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
-            rtmsg.hdr.rtm_rmx.rmx_expire = (int32_t)(tv.tv_sec + 30);
-            
-            rtmsg.dst.sin_len            = sizeof(rtmsg.dst);
-            rtmsg.dst.sin_family         = AF_INET;
-            rtmsg.dst.sin_port           = 0;
-            rtmsg.dst.sin_addr.s_addr    = *(in_addr_t*)ip;
-            rtmsg.dst.sin_srcaddr.s_addr = 0;
-            rtmsg.dst.sin_tos            = 0;
-            rtmsg.dst.sin_other          = 0;
-            
-            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
-            rtmsg.sdl.sdl_family         = AF_LINK;
-            rtmsg.sdl.sdl_index          = (u_short)ifindex;
-            rtmsg.sdl.sdl_type           = IFT_ETHER;
-            rtmsg.sdl.sdl_nlen           = 0;
-            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
-            rtmsg.sdl.sdl_slen           = 0;
-            
-            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
-            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-            
-            ssize_t len = write(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0)
-                os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address %d.%d.%d.%d seq %d result %zd errno %d (%s)",
-                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
-            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0 || rtmsg.hdr.rtm_errno)
-                os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address %d.%d.%d.%d seq %d result %zd errno %d (%s) %d",
-                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-            
-            *err = kHelperErr_NoErr;
-        }
-        else
-        {
-            struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg;
-            memset(&rtmsg, 0, sizeof(rtmsg));
-            
-            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
-            rtmsg.hdr.rtm_version        = RTM_VERSION;
-            rtmsg.hdr.rtm_type           = RTM_ADD;
-            rtmsg.hdr.rtm_index          = (u_short)ifindex;
-            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
-            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
-            rtmsg.hdr.rtm_pid            = 0;
-            rtmsg.hdr.rtm_seq            = seq++;
-            rtmsg.hdr.rtm_errno          = 0;
-            rtmsg.hdr.rtm_use            = 0;
-            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
-            rtmsg.hdr.rtm_rmx.rmx_expire = (int32_t)(tv.tv_sec + 30);
-            
-            rtmsg.dst.sin6_len           = sizeof(rtmsg.dst);
-            rtmsg.dst.sin6_family        = AF_INET6;
-            rtmsg.dst.sin6_port          = 0;
-            rtmsg.dst.sin6_flowinfo      = 0;
-            rtmsg.dst.sin6_addr          = *(struct in6_addr*)ip;
-            rtmsg.dst.sin6_scope_id      = ifindex;
-            
-            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
-            rtmsg.sdl.sdl_family         = AF_LINK;
-            rtmsg.sdl.sdl_index          = (u_short)ifindex;
-            rtmsg.sdl.sdl_type           = IFT_ETHER;
-            rtmsg.sdl.sdl_nlen           = 0;
-            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
-            rtmsg.sdl.sdl_slen           = 0;
-            
-            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
-            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-            
-            ssize_t len = write(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0)
-                os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address " IPv6FMTSTRING " seq %d result %zd errno %d (%s)",
-                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
-            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0 || rtmsg.hdr.rtm_errno)
-                os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address " IPv6FMTSTRING " seq %d result %zd errno %d (%s) %d",
-                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-            
-            *err = kHelperErr_NoErr;
-        }
-    }
-    
-    update_idle_timer();
-}
-
-
-char usercompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name the user saw
-char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the user saw
-char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
-char lasthostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name saved to preferences
-
-#if MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-static CFStringRef CFS_OQ = NULL;
-static CFStringRef CFS_CQ = NULL;
-static CFStringRef CFS_Format = NULL;
-static CFStringRef CFS_ComputerName = NULL;
-static CFStringRef CFS_ComputerNameMsg = NULL;
-static CFStringRef CFS_LocalHostName = NULL;
-static CFStringRef CFS_LocalHostNameMsg = NULL;
-static CFStringRef CFS_Problem = NULL;
-
-static CFUserNotificationRef gNotification    = NULL;
-static CFRunLoopSourceRef gNotificationRLS = NULL;
-
-static void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
-{
-    os_log_debug(log_handle,"entry");
-    (void)responseFlags;    // Unused
-    if (userNotification != gNotification) os_log(log_handle, "NotificationCallBackDismissed: Wrong CFUserNotificationRef");
-    if (gNotificationRLS)
-    {
-        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
-        // We need to explicitly specify the desired CFRunLoop from which we want to remove this event source.
-        CFRunLoopRemoveSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
-        CFRelease(gNotificationRLS);
-        gNotificationRLS = NULL;
-        CFRelease(gNotification);
-        gNotification = NULL;
-    }
-    // By dismissing the alert, the user has conceptually acknowleged the rename.
-    // (e.g. the machine's name is now officially "computer-2.local", not "computer.local".)
-    // If we get *another* conflict, the new alert should refer to the 'old' name
-    // as now being "computer-2.local", not "computer.local"
-    usercompname[0] = 0;
-    userhostname[0] = 0;
-    lastcompname[0] = 0;
-    lasthostname[0] = 0;
-    update_idle_timer();
-    unpause_idle_timer();
-}
-
-static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef subtext)
-{
-    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    if (!dictionary) return;
-
-    os_log_debug(log_handle,"entry");
-
-    CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header);
-    CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext);
-
-    CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/CoreServices/mDNSResponder.bundle"), kCFURLPOSIXPathStyle, true);
-    if (urlRef) { CFDictionarySetValue(dictionary, kCFUserNotificationLocalizationURLKey, urlRef); CFRelease(urlRef); }
-
-    if (gNotification)  // If notification already on-screen, update it in place
-        CFUserNotificationUpdate(gNotification, 0, kCFUserNotificationCautionAlertLevel, dictionary);
-    else                // else, we need to create it
-    {
-        SInt32 error;
-        gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary);
-        if (!gNotification || error) { os_log(log_handle, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; }
-        gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0);
-        if (!gNotificationRLS) { os_log(log_handle, "ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
-        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
-        // We need to explicitly specify the desired CFRunLoop to which we want to add this event source.
-        CFRunLoopAddSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
-        os_log_debug(log_handle,"gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS);
-        pause_idle_timer();
-    }
-
-    CFRelease(dictionary);
-}
-
-static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newname, const CFStringRef msg, const char* suffix)
-{
-    CFMutableArrayRef alertHeader = NULL;
-
-    const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname,  kCFStringEncodingUTF8);
-    // NULL newname means we've given up trying to construct a name that doesn't conflict
-    const CFStringRef cfnewname = newname ? CFStringCreateWithCString(NULL, newname,  kCFStringEncodingUTF8) : NULL;
-    // We tag a zero-width non-breaking space at the end of the literal text to guarantee that, no matter what
-    // arbitrary computer name the user may choose, this exact text (with zero-width non-breaking space added)
-    // can never be one that occurs in the Localizable.strings translation file.
-    if (!cfoldname)
-    {
-        os_log(log_handle, "Could not construct CFStrings for old=%s", newname);
-    }
-    else if (newname && !cfnewname)
-    {
-        os_log(log_handle, "Could not construct CFStrings for new=%s", newname);
-    }
-    else
-    {
-        const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfoldname, suffix);
-        const CFStringRef s2 = cfnewname ? CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfnewname, suffix) : NULL;
-
-        alertHeader = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-        if (!s1)
-        {
-            os_log(log_handle, "Could not construct secondary CFString for old=%s", oldname);
-        }
-        else if (cfnewname && !s2)
-        {
-            os_log(log_handle, "Could not construct secondary CFString for new=%s", newname);
-        }
-        else if (!alertHeader)
-        {
-            os_log(log_handle, "Could not construct CFArray for notification");
-        }
-        else
-        {
-            // Make sure someone is logged in.  We don't want this popping up over the login window
-            uid_t uid;
-            gid_t gid;
-            CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);
-            if (userName)
-            {
-                if (!CFEqual(userName, CFSTR("_mbsetupuser")))
-                {
-                    CFArrayAppendValue(alertHeader, msg); // Opening phrase of message, provided by caller
-                    CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s1); CFArrayAppendValue(alertHeader, CFS_CQ);
-                    CFArrayAppendValue(alertHeader, CFSTR(" is already in use on this network. "));
-                    if (s2)
-                    {
-                        CFArrayAppendValue(alertHeader, CFSTR("The name has been changed to "));
-                        CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s2); CFArrayAppendValue(alertHeader, CFS_CQ);
-                        CFArrayAppendValue(alertHeader, CFSTR("."));
-                    }
-                    else
-                    {
-                        CFArrayAppendValue(alertHeader, CFSTR("All attempts to find an available name by adding a number to the name were also unsuccessful."));
-                    }
-                }
-                CFRelease(userName);
-            }
-        }
-        if (s1) CFRelease(s1);
-        if (s2) CFRelease(s2);
-    }
-    if (cfoldname) CFRelease(cfoldname);
-    if (cfnewname) CFRelease(cfnewname);
-
-    return alertHeader;
-}
-#endif // MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-
-static void update_notification(void)
-{
-#if MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-    os_log_debug(log_handle,"entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
-    buddy_state_t buddy_state = assistant_helper_get_buddy_state();
-    if (buddy_state != buddy_state_done)
-    {
-        static _Atomic uint32_t notify_count = 0;
-        os_log_info(log_handle, "update_notification: buddy is %{public}s so skipping notification (%u)", buddy_state_to_string(buddy_state), atomic_load(&notify_count));
-        if (buddy_state == buddy_state_in_process &&
-            atomic_load(&notify_count) == 0)
-        {
-            assistant_helper_notify_when_buddy_done(^{
-                os_log_info(log_handle, "update_notification: buddy done notification (%u)", atomic_load(&notify_count));
-                update_notification();
-                atomic_store(&notify_count, 0);
-            });
-        }
-        atomic_fetch_add(&notify_count, 1);
-        return;
-    }
-    if (!CFS_OQ)
-    {
-        // Note: The "\xEF\xBB\xBF" byte sequence (U+FEFF) in the CFS_Format string is the UTF-8 encoding of the zero-width non-breaking space character.
-        // By appending this invisible character on the end of literal names, we ensure the these strings cannot inadvertently match any string
-        // in the localization file -- since we know for sure that none of our strings in the localization file contain the ZWNBS character.
-        CFS_Format           = CFStringCreateWithCString(NULL, "%@%s\xEF\xBB\xBF", kCFStringEncodingUTF8);
-
-        // The strings CFS_OQ, CFS_CQ and the others below are the localization keys for the “Localizable.strings” files,
-        // and MUST NOT BE CHANGED, or localization substitution will be broken.
-        // To change the text displayed to the user, edit the values in the appropriate “Localizable.strings” file, not the keys here.
-        // This includes making changes for adding appropriate directionality overrides like LRM, LRE, RLE, PDF, etc. These need to go in the values
-        // in the appropriate “Localizable.strings” entries, not in the keys here (which then won’t match *any* entry in the localization files).
-        // These localization keys here were broken in <rdar://problem/8629082> and then subsequently repaired in
-        // <rdar://problem/21071535> [mDNSResponder]: TA: Gala15A185: Incorrect punctuation marks when Change the host name to an exist one
-        CFS_OQ               = CFStringCreateWithCString(NULL, "“",  kCFStringEncodingUTF8);	// DO NOT CHANGE THIS STRING
-        CFS_CQ               = CFStringCreateWithCString(NULL, "”",  kCFStringEncodingUTF8);	// DO NOT CHANGE THIS STRING
-        CFS_ComputerName     = CFStringCreateWithCString(NULL, "The name of your computer ",  kCFStringEncodingUTF8);
-        CFS_ComputerNameMsg  = CFStringCreateWithCString(NULL, "To change the name of your computer, "
-                                                         "open System Preferences and click Sharing, then type the name in the Computer Name field.",  kCFStringEncodingUTF8);
-        CFS_LocalHostName    = CFStringCreateWithCString(NULL, "This computer’s local hostname ",  kCFStringEncodingUTF8);
-        CFS_LocalHostNameMsg = CFStringCreateWithCString(NULL, "To change the local hostname, "
-                                                         "open System Preferences and click Sharing, then click “Edit” and type the name in the Local Hostname field.",  kCFStringEncodingUTF8);
-        CFS_Problem          = CFStringCreateWithCString(NULL, "This may indicate a problem with the local network. "
-                                                         "Please inform your network administrator.",  kCFStringEncodingUTF8);
-    }
-
-    if (!usercompname[0] && !userhostname[0])
-    {
-        if (gNotificationRLS)
-        {
-            os_log_debug(log_handle,"canceling notification %p", gNotification);
-            CFUserNotificationCancel(gNotification);
-            unpause_idle_timer();
-        }
-    }
-    else
-    {
-        CFMutableArrayRef header = NULL;
-        CFStringRef* subtext = NULL;
-        if (userhostname[0] && !lasthostname[0]) // we've given up trying to construct a name that doesn't conflict
-        {
-            header = CreateAlertHeader(userhostname, NULL, CFS_LocalHostName, ".local");
-            subtext = &CFS_Problem;
-        }
-        else if (usercompname[0])
-        {
-            header = CreateAlertHeader(usercompname, lastcompname, CFS_ComputerName, "");
-            subtext = &CFS_ComputerNameMsg;
-        }
-        else
-        {
-            header = CreateAlertHeader(userhostname, lasthostname, CFS_LocalHostName, ".local");
-            subtext = &CFS_LocalHostNameMsg;
-        }
-        ShowNameConflictNotification(header, *subtext);
-        CFRelease(header);
-    }
-#endif // MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES
-}
-
-void PreferencesSetName(int key, const char* old, const char* new)
-{
-    char* user = NULL;
-    char* last = NULL;
-    Boolean needUpdate = FALSE;
-    
-    os_log_info(log_handle,"PreferencesSetName: entry %s old=%s new=%s",
-                   key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
-    
-    switch ((enum mDNSPreferencesSetNameKey)key)
-    {
-        case kmDNSComputerName:
-            user = usercompname;
-            last = lastcompname;
-            break;
-        case kmDNSLocalHostName:
-            user = userhostname;
-            last = lasthostname;
-            break;
-        default:
-            os_log(log_handle, "PreferencesSetName: unrecognized key: %d", key);
-            goto fin;
-    }
-    
-    if (!last)
-    {
-        os_log(log_handle, "PreferencesSetName: no last ptr");
-        goto fin;
-    }
-    
-    if (!user)
-    {
-        os_log(log_handle, "PreferencesSetName:: no user ptr");
-        goto fin;
-    }
-    
-    if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1))
-    {
-        // old and new are same means the config changed i.e, the user has set something in the preferences pane.
-        // This means the conflict has been resolved. We need to dismiss the dialogue.
-        if (last[0] && 0 != strncmp(last, new, MAX_DOMAIN_LABEL+1))
-        {
-            last[0] = 0;
-            user[0] = 0;
-            needUpdate = TRUE;
-        }
-        goto fin;
-    }
-    else
-    {
-        // old and new are not same, this means there is a conflict. For the first conflict, we show
-        // the old value and the new value. For all subsequent conflicts, while the dialogue is still
-        // up, we do a real time update of the "new" value in the dialogue. That's why we update just
-        // "last" here and not "user".
-        if (strncmp(last, new, MAX_DOMAIN_LABEL+1))
-        {
-            strncpy(last, new, MAX_DOMAIN_LABEL);
-            needUpdate = TRUE;
-        }
-    }
-    
-    // If we are not showing the dialogue, we need to remember the first "old" value so that
-    // we maintain the same through the lifetime of the dialogue. Subsequent conflicts don't
-    // update the "old" value.
-    if (!user[0])
-    {
-        strncpy(user, old, MAX_DOMAIN_LABEL);
-        needUpdate = TRUE;
-    }
-    
-fin:
-    update_idle_timer();
-    if (needUpdate)
-        update_notification();
-    
-}
-
-
-enum DNSKeyFormat
-{
-    formatNotDNSKey,
-    formatDdnsTypeItem,
-    formatDnsPrefixedServiceItem,
-};
-
-// On Mac OS X on Intel, the four-character string seems to be stored backwards, at least sometimes.
-// I suspect some overenthusiastic inexperienced engineer said, "On Intel everything's backwards,
-// therefore I need to add some byte swapping in this API to make this four-character string backwards too."
-// To cope with this we allow *both* "ddns" and "sndd" as valid item types.
-
-
-#ifndef NO_SECURITYFRAMEWORK
-static const char dnsprefix[] = "dns:";
-static const char ddns[] = "ddns";
-static const char ddnsrev[] = "sndd";
-
-static enum DNSKeyFormat getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
-{
-    static UInt32 tags[4] =
-    {
-        kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr, kSecLabelItemAttr
-    };
-    static SecKeychainAttributeInfo attributeInfo =
-    {
-        sizeof(tags)/sizeof(tags[0]), tags, NULL
-    };
-    SecKeychainAttributeList *attributes = NULL;
-    enum DNSKeyFormat format;
-    Boolean malformed = FALSE;
-    OSStatus status = noErr;
-    int i = 0;
-    
-    *attributesp = NULL;
-    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, &attributeInfo, NULL, &attributes, NULL, NULL)))
-    {
-        os_log_info(log_handle,"getDNSKeyFormat: SecKeychainItemCopyAttributesAndData %d - skipping", status);
-        goto skip;
-    }
-    if (attributeInfo.count != attributes->count)
-        malformed = TRUE;
-    for (i = 0; !malformed && i < (int)attributeInfo.count; ++i)
-        if (attributeInfo.tag[i] != attributes->attr[i].tag)
-            malformed = TRUE;
-    if (malformed)
-    {
-        os_log(log_handle, "getDNSKeyFormat: malformed result from SecKeychainItemCopyAttributesAndData - skipping");
-        goto skip;
-    }
-    
-    os_log_info(log_handle,"getDNSKeyFormat: entry (\"%.*s\", \"%.*s\", \"%.*s\")",
-                   (int)attributes->attr[0].length, attributes->attr[0].data,
-                   (int)attributes->attr[1].length, attributes->attr[1].data,
-                   (int)attributes->attr[2].length, attributes->attr[2].data);
-
-    if (attributes->attr[1].length >= MAX_ESCAPED_DOMAIN_NAME +
-        sizeof(dnsprefix)-1)
-    {
-        os_log(log_handle, "getDNSKeyFormat: kSecServiceItemAttr too long (%u) - skipping",
-              (unsigned int)attributes->attr[1].length);
-        goto skip;
-    }
-    if (attributes->attr[2].length >= MAX_ESCAPED_DOMAIN_NAME)
-    {
-        os_log(log_handle, "getDNSKeyFormat: kSecAccountItemAttr too long (%u) - skipping",
-              (unsigned int)attributes->attr[2].length);
-        goto skip;
-    }
-    if (attributes->attr[1].length >= sizeof(dnsprefix)-1 && 0 == strncasecmp(attributes->attr[1].data, dnsprefix, sizeof(dnsprefix)-1))
-        format = formatDnsPrefixedServiceItem;
-    else if (attributes->attr[0].length == sizeof(ddns)-1 && 0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1))
-        format = formatDdnsTypeItem;
-    else if (attributes->attr[0].length == sizeof(ddnsrev)-1 && 0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1))
-        format = formatDdnsTypeItem;
-    else
-    {
-        os_log_info(log_handle,"getDNSKeyFormat: uninterested in this entry");
-        goto skip;
-    }
-    
-    *attributesp = attributes;
-    os_log_info(log_handle,"getDNSKeyFormat: accepting this entry");
-    return format;
-    
-skip:
-    SecKeychainItemFreeAttributesAndData(attributes, NULL);
-    return formatNotDNSKey;
-}
-
-// Insert the attributes as defined by mDNSKeyChainAttributes
-static CFPropertyListRef copyKeychainItemInfo(SecKeychainItemRef item, SecKeychainAttributeList *attributes, enum DNSKeyFormat format)
-{
-    CFMutableArrayRef entry = NULL;
-    CFDataRef data = NULL;
-    OSStatus status = noErr;
-    UInt32 keylen = 0;
-    void *keyp = 0;
-    
-    if (NULL == (entry = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)))
-    {
-        os_log(log_handle, "copyKeychainItemInfo: CFArrayCreateMutable failed");
-        goto error;
-    }
-    
-    // Insert the Account attribute (kmDNSKcWhere)
-    switch ((enum DNSKeyFormat)format)
-    {
-        case formatDdnsTypeItem:
-            data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length);
-            break;
-        case formatDnsPrefixedServiceItem:
-            data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length);
-            break;
-        default:
-            os_log(log_handle, "copyKeychainItemInfo: unknown DNSKeyFormat value");
-            break;
-    }
-    if (NULL == data)
-    {
-        os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[1] failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-    
-    // Insert the Where attribute (kmDNSKcAccount)
-    if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[2].data, attributes->attr[2].length)))
-    {
-        os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[2] failed");
-        goto error;
-    }
-    
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-    
-    // Insert the Key attribute (kmDNSKcKey)
-    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL, NULL, NULL, &keylen, &keyp)))
-    {
-        os_log(log_handle, "copyKeychainItemInfo: could not retrieve key for \"%.*s\": %d",
-              (int)attributes->attr[1].length, attributes->attr[1].data, status);
-        goto error;
-    }
-    
-    data = CFDataCreate(kCFAllocatorDefault, keyp, keylen);
-    SecKeychainItemFreeAttributesAndData(NULL, keyp);
-    if (NULL == data)
-    {
-        os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for keyp failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-    
-    // Insert the Name attribute (kmDNSKcName)
-    if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[3].data, attributes->attr[3].length)))
-    {
-        os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[3] failed");
-        goto error;
-    }
-    
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-    return entry;
-    
-error:
-    if (NULL != entry)
-        CFRelease(entry);
-    return NULL;
-}
-#endif
-
-void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err)
-{
-#ifndef NO_SECURITYFRAMEWORK
-    CFWriteStreamRef stream = NULL;
-    CFDataRef result = NULL;
-    CFPropertyListRef entry = NULL;
-    CFMutableArrayRef keys = NULL;
-    SecKeychainRef skc = NULL;
-    SecKeychainItemRef item = NULL;
-    SecKeychainSearchRef search = NULL;
-    SecKeychainAttributeList *attributes = NULL;
-    enum DNSKeyFormat format;
-    OSStatus status = 0;
-   
-    os_log_info(log_handle,"KeychainGetSecrets: entry");
-    *err = kHelperErr_NoErr;
-    *numsecrets = 0;
-    *secrets = (vm_offset_t)NULL;
-
-    if (NULL == (keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)))
-    {
-        os_log(log_handle, "KeychainGetSecrets: CFArrayCreateMutable failed");
-        *err = kHelperErr_ApiErr;
-        goto fin;
-    }
-    if (noErr != SecKeychainCopyDefault(&skc))
-    {
-        *err = kHelperErr_ApiErr;
-        goto fin;
-    }
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    if (noErr != SecKeychainSearchCreateFromAttributes(skc, kSecGenericPasswordItemClass, NULL, &search))
-    {
-        *err = kHelperErr_ApiErr;
-        goto fin;
-    }
-    for (status = SecKeychainSearchCopyNext(search, &item); noErr == status; status = SecKeychainSearchCopyNext(search, &item))
-    {
-        if (formatNotDNSKey != (format = getDNSKeyFormat(item, &attributes)) &&
-            NULL != (entry = copyKeychainItemInfo(item, attributes, format)))
-        {
-            CFArrayAppendValue(keys, entry);
-            CFRelease(entry);
-        }
-        SecKeychainItemFreeAttributesAndData(attributes, NULL);
-        CFRelease(item);
-    }
-#pragma clang diagnostic pop
-    if (errSecItemNotFound != status)
-         os_log(log_handle, "KeychainGetSecrets: SecKeychainSearchCopyNext failed: %d", status);
-    
-    if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, kCFAllocatorDefault)))
-    {
-        *err = kHelperErr_ApiErr;
-        os_log(log_handle, "KeychainGetSecrets:CFWriteStreamCreateWithAllocatedBuffers failed");
-        goto fin;
-    }
-    
-    CFWriteStreamOpen(stream);
-    if (0 == CFPropertyListWrite(keys, stream, kCFPropertyListBinaryFormat_v1_0, 0, NULL))
-    {
-        *err = kHelperErr_ApiErr;
-        os_log(log_handle, "KeychainGetSecrets:CFPropertyListWriteToStream failed");
-        goto fin;
-    }
-    result = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten);
-    
-    if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets, (vm_size_t)CFDataGetLength(result), VM_FLAGS_ANYWHERE))
-    {
-        *err = kHelperErr_ApiErr;
-        os_log(log_handle, "KeychainGetSecrets: vm_allocate failed");
-        goto fin;
-    }
-    
-    CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)), (void *)*secrets);
-    *secretsCnt = (unsigned int)CFDataGetLength(result);
-    *numsecrets = (unsigned int)CFArrayGetCount(keys);
-    
-    os_log_info(log_handle,"KeychainGetSecrets: succeeded");
-    
-fin:
-    os_log_info(log_handle,"KeychainGetSecrets: returning numsecrets[%u] secrets[%lu] secrets addr[%p] secretscount[%u]",
-                   *numsecrets, *secrets, secrets, *secretsCnt);
-    
-    if (NULL != stream)
-    {
-        CFWriteStreamClose(stream);
-        CFRelease(stream);
-    }
-    if (NULL != result)
-        CFRelease(result);
-    if (NULL != keys)
-        CFRelease(keys);
-    if (NULL != search)
-        CFRelease(search);
-    if (NULL != skc)
-        CFRelease(skc);
-    update_idle_timer();
-    
-    *err = KERN_SUCCESS;
-    
-#else
-    
-    *err = KERN_FAILURE;
-    
-#endif
-    
-}
-
-
-CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
-CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
-
-
-void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration)
-{
-    int bpf_fd = -1;
-    int i, j;
-    struct ifreq ifr;
-    char ifname[IFNAMSIZ];
-    uint8_t packet[512];
-    uint8_t *ptr = packet;
-    struct ether_addr *ea;
-    
-    os_log_info(log_handle,"SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]",
-                   eth_addr, ip_addr, ifid, iteration);
-    
-    if (if_indextoname(ifid, ifname) == NULL)
-    {
-        os_log(log_handle, "SendWakeupPacket: invalid interface index %u", ifid);
-        goto exit;
-    }
-    
-    ea = ether_aton(eth_addr);
-    if (ea == NULL)
-    {
-        os_log(log_handle, "SendWakeupPacket: invalid ethernet address %s", eth_addr);
-        goto exit;
-    }
-    
-    bpf_fd = mdns_bpf_open(O_RDWR, NULL);
-    if (bpf_fd < 0)
-    {
-        os_log(log_handle, "SendWakeupPacket: cannot find a bpf device");
-        goto exit;
-    }
-    
-    memset(&ifr, 0, sizeof(ifr));
-    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-    
-    if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
-    {
-        os_log(log_handle, "SendWakeupPacket: BIOCSETIF failed %s", strerror(errno));
-        goto exit;
-    }
-    
-    // 0x00 Destination address
-    for (i=0; i<6; i++)
-        *ptr++ = ea->octet[i];
-    
-    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option,
-    // BPF will fill in the real interface address for us)
-    for (i=0; i<6; i++)
-        *ptr++ = 0;
-    
-    // 0x0C Ethertype (0x0842)
-    *ptr++ = 0x08;
-    *ptr++ = 0x42;
-    
-    // 0x0E Wakeup sync sequence
-    for (i=0; i<6; i++)
-        *ptr++ = 0xFF;
-    
-    // 0x14 Wakeup data
-    for (j=0; j<16; j++)
-        for (i=0; i<6; i++)
-            *ptr++ = ea->octet[i];
-    
-    // 0x74 Password
-    for (i=0; i<6; i++)
-        *ptr++ = 0;
-    
-    if (write(bpf_fd, packet, (size_t)(ptr - packet)) < 0)
-    {
-        os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno));
-        goto exit;
-    }
-    os_log(log_handle, "SendWakeupPacket: sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
-    
-    // Send a broadcast one to handle ethernet switches that don't flood forward packets with
-    // unknown mac addresses.
-    for (i=0; i<6; i++)
-        packet[i] = 0xFF;
-    
-    if (write(bpf_fd, packet, (size_t)(ptr - packet)) < 0)
-    {
-        os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno));
-        goto exit;
-    }
-    os_log(log_handle, "SendWakeupPacket: sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
-
-exit:
-    if (bpf_fd >= 0)
-    {
-        close(bpf_fd);
-    }
-}
-
-static unsigned long in_cksum(unsigned short *ptr, int nbytes)
-{
-    unsigned long sum;
-    u_short oddbyte;
-    
-    /*
-     * Our algorithm is simple, using a 32-bit accumulator (sum),
-     * we add sequential 16-bit words to it, and at the end, fold back
-     * all the carry bits from the top 16 bits into the lower 16 bits.
-     */
-    sum = 0;
-    while (nbytes > 1)
-    {
-        sum += *ptr++;
-        nbytes -= 2;
-    }
-    
-    /* mop up an odd byte, if necessary */
-    if (nbytes == 1)
-    {
-        /* make sure top half is zero */
-        oddbyte = 0;
-        
-        /* one byte only */
-        *((u_char *)&oddbyte) = *(u_char *)ptr;
-        sum += oddbyte;
-    }
-    /* Add back carry outs from top 16 bits to low 16 bits. */
-    sum = (sum >> 16) + (sum & 0xffff);
-    
-    /* add carry */
-    sum += (sum >> 16);
-    
-    return sum;
-}
-
-static unsigned short InetChecksum(unsigned short *ptr, int nbytes)
-{
-    unsigned long sum;
-    
-    sum = in_cksum(ptr, nbytes);
-    return (unsigned short)~sum;
-}
-
-static void TCPCheckSum(int af, struct tcphdr *t, int tcplen, const v6addr_t sadd6, const v6addr_t dadd6)
-{
-    unsigned long sum = 0;
-    unsigned short *ptr;
-    
-    /* TCP header checksum */
-    sum = in_cksum((unsigned short *)t, tcplen);
-    
-    if (af == AF_INET)
-    {
-        /* Pseudo header */
-        ptr = (unsigned short *)sadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        ptr = (unsigned short *)dadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-    }
-    else if (af == AF_INET6)
-    {
-        /* Pseudo header */
-        ptr = (unsigned short *)sadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        ptr = (unsigned short *)dadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-    }
-    
-    sum += htons(tcplen);
-    sum += htons(IPPROTO_TCP);
-    
-    while (sum >> 16)
-        sum = (sum >> 16) + (sum & 0xFFFF);
-    
-    t->th_sum = (unsigned short)~sum;
-    
-}
-
-void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win)
-{
-    
-#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
-#define IPv6FMTSARGS  sadd6[0], sadd6[1], sadd6[2], sadd6[3], sadd6[4], sadd6[5], sadd6[6], sadd6[7], sadd6[8], sadd6[9], sadd6[10], sadd6[11], sadd6[12], sadd6[13], sadd6[14], sadd6[15]
-#define IPv6FMTDARGS  dadd6[0], dadd6[1], dadd6[2], dadd6[3], dadd6[4], dadd6[5], dadd6[6], dadd6[7], dadd6[8], dadd6[9], dadd6[10], dadd6[11], dadd6[12], dadd6[13], dadd6[14], dadd6[15]
-
-    os_log_info(log_handle, "SendKeepalive:  "IPv6FMTSTRING" :space: "IPv6FMTSTRING"",
-                IPv6FMTSARGS, IPv6FMTDARGS);
-    
-    struct packet4
-    {
-        struct ip ip;
-        struct tcphdr tcp;
-    } packet4;
-    struct packet6
-    {
-        struct tcphdr tcp;
-    } packet6;
-    int sock, on;
-    struct tcphdr *t;
-    int af;
-    struct sockaddr_storage ss_to;
-    struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to;
-    struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to;
-    void *packet;
-    size_t packetlen;
-    char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-    struct msghdr msghdr;
-    struct iovec iov;
-    ssize_t len;
-    
-    os_log_info(log_handle,"SendKeepalive invoked: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
-                   lport, rport, seq, ack, win);
-    
-    char buf1[INET6_ADDRSTRLEN];
-    char buf2[INET6_ADDRSTRLEN];
-    
-    buf1[0] = 0;
-    buf2[0] = 0;
-    
-    inet_ntop(AF_INET6, sadd6, buf1, sizeof(buf1));
-    inet_ntop(AF_INET6, dadd6, buf2, sizeof(buf2));
-    
-    os_log_info(log_handle,"SendKeepalive invoked: sadd6 is %s, dadd6 is %s", buf1, buf2);
-    
-    // all the incoming arguments are in network order
-    if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0))
-    {
-        af = AF_INET;
-        memset(&packet4, 0, sizeof (packet4));
-        
-        /* Fill in all the IP header information - should be in host order*/
-        packet4.ip.ip_v = 4;            /* 4-bit Version */
-        packet4.ip.ip_hl = 5;       /* 4-bit Header Length */
-        packet4.ip.ip_tos = 0;      /* 8-bit Type of service */
-        packet4.ip.ip_len = 40;     /* 16-bit Total length */
-        packet4.ip.ip_id = 9864;        /* 16-bit ID field */
-        packet4.ip.ip_off = 0;      /* 13-bit Fragment offset */
-        packet4.ip.ip_ttl = 63;     /* 8-bit Time To Live */
-        packet4.ip.ip_p = IPPROTO_TCP;  /* 8-bit Protocol */
-        packet4.ip.ip_sum = 0;      /* 16-bit Header checksum (below) */
-        memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4);
-        memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4);
-        
-        /* IP header checksum */
-        packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20);
-        t = &packet4.tcp;
-        packet = &packet4;
-        packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20)
-    }
-    else
-    {
-        af = AF_INET6;
-        memset(&packet6, 0, sizeof (packet6));
-        t = &packet6.tcp;
-        packet = &packet6;
-        // We don't send IPv6 header, hence just the TCP header len (20)
-        packetlen = 20;
-    }
-    
-    /* Fill in all the TCP header information */
-    t->th_sport = lport;        /* 16-bit Source port number */
-    t->th_dport = rport;        /* 16-bit Destination port */
-    t->th_seq = seq;            /* 32-bit Sequence Number */
-    t->th_ack = ack;            /* 32-bit Acknowledgement Number */
-    t->th_off = 5;              /* Data offset */
-    t->th_flags = TH_ACK;
-    t->th_win = win;
-    t->th_sum = 0;              /* 16-bit checksum (below) */
-    t->th_urp = 0;              /* 16-bit urgent offset */
-    
-    TCPCheckSum(af, t, 20, sadd6, dadd6);
-    
-    /* Open up a RAW socket */
-    if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0)
-    {
-        os_log(log_handle, "SendKeepalive: socket %s", strerror(errno));
-        return;
-    }
-    
-    if (af == AF_INET)
-    {
-        on = 1;
-        if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)))
-        {
-            close(sock);
-            os_log(log_handle, "SendKeepalive: setsockopt %s", strerror(errno));
-            return;
-        }
-        
-        memset(sin_to, 0, sizeof(struct sockaddr_in));
-        sin_to->sin_len = sizeof(struct sockaddr_in);
-        sin_to->sin_family = AF_INET;
-        memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr));
-        sin_to->sin_port = rport;
-        
-        msghdr.msg_control = NULL;
-        msghdr.msg_controllen = 0;
-        
-    }
-    else
-    {
-        struct cmsghdr *ctl;
-        
-        memset(sin6_to, 0, sizeof(struct sockaddr_in6));
-        sin6_to->sin6_len = sizeof(struct sockaddr_in6);
-        sin6_to->sin6_family = AF_INET6;
-        memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr));
-        
-        sin6_to->sin6_port = rport;
-        sin6_to->sin6_flowinfo = 0;
-        
-        
-        msghdr.msg_control = ctlbuf;
-        msghdr.msg_controllen = sizeof(ctlbuf);
-        ctl = CMSG_FIRSTHDR(&msghdr);
-        ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
-        ctl->cmsg_level = IPPROTO_IPV6;
-        ctl->cmsg_type = IPV6_PKTINFO;
-        struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl);
-        memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr));
-        pktinfo->ipi6_ifindex = 0;
-    }
-    
-    msghdr.msg_name = (struct sockaddr *)&ss_to;
-    msghdr.msg_namelen = ss_to.ss_len;
-    iov.iov_base = packet;
-    iov.iov_len = packetlen;
-    msghdr.msg_iov = &iov;
-    msghdr.msg_iovlen = 1;
-    msghdr.msg_flags = 0;
-    
-again:
-    len = sendmsg(sock, &msghdr, 0);
-    if (len == -1)
-    {
-        if (errno == EINTR)
-            goto again;
-    }
-    
-    if ((len < 0) || (((size_t)len) != packetlen))
-    {
-        os_log(log_handle, "SendKeepalive: sendmsg failed %s", strerror(errno));
-    }
-    else
-    {
-        char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN];
-        
-        inet_ntop(af, (void *)sadd6, source, sizeof(source));
-        inet_ntop(af, (void *)dadd6, dest, sizeof(dest));
-        
-        os_log(log_handle, "SendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u",
-                source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win));
-        
-    }
-    close(sock);
-
-}
diff --git a/mDNSMacOSX/helper.h b/mDNSMacOSX/helper.h
deleted file mode 100644
index 2d6ed92..0000000
--- a/mDNSMacOSX/helper.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2007-2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef H_HELPER_H
-#define H_HELPER_H
-
-#include "helper/client.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <os/log.h>
-#include <TargetConditionals.h>
-
-#define kHelperService "com.apple.mDNSResponder_Helper"
-
-#define kHelperMode             "HelperMode"
-#define kHelperReplyStatus      "HelperReplyStatusToClient"
-#define kHelperErrCode          "HelperErrorCodefromCall"
-
-#define kPrefsNameKey  "PreferencesNameKey"
-#define kPrefsOldName  "PreferencesOldName"
-#define kPrefsNewName  "PreferencesNewName"
-
-#if TARGET_OS_OSX
-    #define MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES 1
-#else
-    #define MDNSRESPONDER_HELPER_NOTIFIES_USER_OF_NAME_CHANGES 0
-#endif
-
-extern int mDNSHelperLogEnabled;
-
-extern os_log_t  log_handle;
-
-typedef enum
-{
-    bpf_request = 1,
-    set_name = 2,
-    p2p_packetfilter = 3,
-    user_notify = 4,
-    power_req = 5,
-    send_wakepkt = 6,
-    set_localaddr_cacheentry = 7,
-    send_keepalive = 8,
-    retreive_tcpinfo = 9,
-    keychain_getsecrets = 10,
-} HelperModes;
-
-typedef enum
-{
-    kHelperReply_ACK = 0,
-} HelperReplyStatusCodes;
-
-
-typedef enum
-{
-    kHelperErr_NoErr = 0,
-    kHelperErr_DefaultErr = -1,
-    kHelperErr_NotConnected = -2,
-    kHelperErr_NoResponse = -3,
-    kHelperErr_UndefinedMode = -4,
-    kHelperErr_ApiErr = -5,
-    kHelperErr_InvalidTunnelSetKeysOperation = -6,
-    kHelperErr_InvalidNetworkAddress = -7,
-    kHelperErr_ResultTooLarge = -8,
-    kHelperErr_RacoonConfigCreationFailed = -9,
-    kHelperErr_IPsecPolicySocketCreationFailed = -10,
-    kHelperErr_IPsecPolicyCreationFailed = -11,
-    kHelperErr_IPsecPolicySetFailed = -12,
-    kHelperErr_IPsecRemoveSAFailed = -13,
-    kHelperErr_IPsecDisabled = -14,
-    kHelperErr_RoutingSocketCreationFailed = -15,
-    kHelperErr_RouteDeletionFailed = -16,
-    kHelperErr_RouteAdditionFailed = -17,
-    kHelperErr_RacoonStartFailed = -18,
-    kHelperErr_RacoonNotificationFailed = -19,
-    kHelperErr_ParamErr = -20,
-} HelperErrorCodes;
-
-
-enum mDNSPreferencesSetNameKey
-{
-    kmDNSComputerName = 1,
-    kmDNSLocalHostName
-};
-
-enum mDNSUpDown
-{
-    kmDNSUp = 1,
-    kmDNSDown
-};
-
-// helper parses the system keychain and returns the information to mDNSResponder.
-// It returns four attributes. Attributes are defined after how they show up in
-// keychain access utility (the actual attribute name to retrieve these are different).
-enum mDNSKeyChainAttributes
-{
-    kmDNSKcWhere,   // Where
-    kmDNSKcAccount, // Account
-    kmDNSKcKey,     // Key
-    kmDNSKcName     // Name
-};
-
-#include "mDNSEmbeddedAPI.h"
-#include "helpermsg-types.h"
-
-extern const char *mDNSHelperError(int errornum);
-
-extern mStatus mDNSHelperInit(void);
-
-
-extern void mDNSRequestBPF(dispatch_queue_t queue, mhc_bpf_open_result_handler_t handler);
-extern int  mDNSPowerSleepSystem(void);
-extern int  mDNSSetLocalAddressCacheEntry(mDNSu32 ifindex, int family, const v6addr_t ip, const ethaddr_t eth);
-extern void mDNSNotify(const char *title, const char *msg);     // Both strings are UTF-8 text
-extern void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new);
-extern int  mDNSKeychainGetSecrets(CFArrayRef *secrets);
-extern void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration);
-extern void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win);
-
-extern void RequestBPF(void);
-extern void PreferencesSetName(int key, const char* old, const char* new);
-extern void UserNotify(const char *title, const char *msg);     // Both strings are UTF-8 text
-extern int  PowerSleepSystem(void);
-extern void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration);
-extern void SetLocalAddressCacheEntry(uint32_t ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err);
-extern void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win);
-extern void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err);
-extern int  HelperAutoTunnelSetKeys(int replacedelete, const v6addr_t loc_inner, const v6addr_t loc_outer6, uint16_t loc_port, const v6addr_t rmt_inner,
-                            const v6addr_t rmt_outer6, uint16_t rmt_port, const char *id, int *err);
-extern void helper_exit(void);
-
-#endif /* H_HELPER_H */
diff --git a/mDNSMacOSX/helpermsg-types.h b/mDNSMacOSX/helpermsg-types.h
deleted file mode 100644
index 925c319..0000000
--- a/mDNSMacOSX/helpermsg-types.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2007-2011, 2015, 2020 Apple 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.
- */
-
-#ifndef H_HELPERMSG_TYPES_H
-#define H_HELPERMSG_TYPES_H
-
-#include <stdint.h>
-typedef uint8_t v4addr_t [ 4];
-typedef uint8_t ethaddr_t[ 6];
-typedef uint8_t v6addr_t [16];
-typedef const char *string_t;
-
-#endif /* H_HELPERMSG_TYPES_H */
diff --git a/mDNSMacOSX/libmrc/mrc/dns_proxy.h b/mDNSMacOSX/libmrc/mrc/dns_proxy.h
deleted file mode 100644
index c493f1a..0000000
--- a/mDNSMacOSX/libmrc/mrc/dns_proxy.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_DNS_PROXY_H
-#define MRC_DNS_PROXY_H
-
-#if !defined(MRC_ALLOW_HEADER_INCLUDES) || !MRC_ALLOW_HEADER_INCLUDES
-	#error "Please include <mrc/private.h> instead of this file directly."
-#endif
-
-#include <mrc/object.h>
-
-#include <dispatch/dispatch.h>
-#include <MacTypes.h>
-#include <mdns/base.h>
-
-MRC_DECL(dns_proxy);
-MRC_DECL(dns_proxy_parameters);
-MRC_DECL(dns_proxy_state_inquiry);
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Creates a DNS proxy based on the specified DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param out_error
- *		A variable to set to either kNoErr if creation succeeds, or a non-zero error code to indicate why
- *		creation failed.
- *
- *	@result
- *		A reference to the new DNS proxy object, or NULL if creation failed.
- *
- *	@discussion
- *		The parameters are copied by the DNS proxy object during its creation, so the DNS proxy will not be
- *		affected by later changes to the parameters object.
- *
- *		If not using Objective-C ARC, use mrc_retain() and mrc_release() to retain and release references to the
- *		object.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-MDNS_RETURNS_RETAINED MDNS_WARN_RESULT
-mrc_dns_proxy_t _Nullable
-mrc_dns_proxy_create(mrc_dns_proxy_parameters_t params, OSStatus * _Nullable out_error);
-
-/*!
- *	@brief
- *		Sets a DNS proxy's dispatch queue on which to invoke the DNS proxy's event handler.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param queue
- *		The dispatch queue.
- *
- *	@discussion
- *		A dispatch queue must be set in order for the event handler to be invoked.
- *
- *		This function has no effect on a DNS proxy that has been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_set_queue(mrc_dns_proxy_t proxy, dispatch_queue_t queue);
-
-OS_CLOSED_ENUM(mrc_dns_proxy_event, int,
-	mrc_dns_proxy_event_invalidation	= -1,
-	mrc_dns_proxy_event_none			=  0,
-	mrc_dns_proxy_event_started			=  1,
-	mrc_dns_proxy_event_interruption	=  2
-);
-
-static inline const char *
-mrc_dns_proxy_event_to_string(const mrc_dns_proxy_event_t event)
-{
-	switch (event) {
-		case mrc_dns_proxy_event_invalidation:	return "invalidation";
-		case mrc_dns_proxy_event_none:			return "none";
-		case mrc_dns_proxy_event_started:		return "started";
-		case mrc_dns_proxy_event_interruption:	return "interruption";
-	}
-	return "<INVALID EVENT>";
-}
-
-/*!
- *	@brief
- *		A DNS proxy event handler.
- *
- *	@param event
- *		The event.
- *
- *	@param error
- *		An error code associated with the event.
- */
-typedef void
-(^mrc_dns_proxy_event_handler_t)(mrc_dns_proxy_event_t event, OSStatus error);
-
-/*!
- *	@brief
- *		Sets a DNS proxy's event handler.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param handler
- *		The event handler.
- *
- *	@discussion
- *		The event handler will never be invoked before the first call to either mrc_dns_proxy_activate()
- *		or mrc_dns_proxy_invalidate().
- *
- *		The handler will be invoked with the mrc_dns_proxy_event_invalidation event at most once if either a
- *		fatal error occurs or if the the DNS proxy was manually invalidated with mrc_dns_proxy_invalidate().
- *		If a fatal error occurred, the event handler's error code argument will be non-zero to indicate the
- *		error that occurred. If the DNS proxy was gracefully invalidated with mrc_dns_proxy_invalidate(), then
- *		the event handler's error code will be kNoErr (0).
- *
- *		After the handler is invoked with the mrc_dns_proxy_event_invalidation event, the handler will be
- *		released by the DNS proxy, and will never be invoked by the DNS proxy ever again.
- *
- *		The handler will be invoked with the mrc_dns_proxy_event_started event each time a remote instance of
- *		the DNS proxy has successfully started.
- *
- *		The handler will be invoked with the mrc_dns_proxy_event_interruption event if the connection to the
- *		daemon was interrupted. For example, the daemon may have crashed. This event exists to inform the user
- *		that the remote instance of the DNS proxy may have suffered some downtime. The DNS proxy object will try
- *		to re-establish the connection as well as a new remote instance of the DNS proxy.
- *
- *		The mrc_dns_proxy_event_none event simply exists as a placeholder event value. The event handler will
- *		never be invoked with the mrc_dns_proxy_event_none event.
- *
- *		Currently, the event handler's error code argument is only meaningful for the
- *		mrc_dns_proxy_event_invalidation event.
- *
- *		This function has no effect on a DNS proxy that has been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_set_event_handler(mrc_dns_proxy_t proxy, mrc_dns_proxy_event_handler_t handler);
-
-/*!
- *	@brief
- *		Activates a DNS proxy.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@discussion
- *		Activating a DNS proxy object causes it to try to instantiate a remote instance of itself on the system
- *		daemon that implements DNS proxies.
- *
- *		This function has no effect on a DNS proxy that has already been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_activate(mrc_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Invalidates a DNS proxy.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@discussion
- *		Invalidating a DNS proxy object causes it to tear down the remote instance of itself on the system
- *		daemon if such an instance exists.
- *
- *		This function exists to gracefully invalidate a DNS proxy. This function can safely be called even if
- *		the DNS proxy was already forcibly invalidated due to a fatal error.
- *
- *		This function has no effect on a DNS proxy that has already been invalidated.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_invalidate(mrc_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Creates an empty modifiable set of DNS proxy parameters.
- *
- *	@param out_error
- *		A variable to set to either kNoErr if creation succeeds, or a non-zero error code to indicate why
- *		creation failed.
- *
- *	@result
- *		A reference to the new DNS proxy parameters, or NULL if creation failed.
- *
- *	@discussion
- *		If not using Objective-C ARC, use mrc_retain() and mrc_release() to retain and release references to the
- *		object.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-MDNS_RETURNS_RETAINED MDNS_WARN_RESULT
-mrc_dns_proxy_parameters_t _Nullable
-mrc_dns_proxy_parameters_create(OSStatus *out_error);
-
-/*!
- *	@brief
- *		Adds an input interface to a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param ifindex
- *		The input interface's index.
- *
- *	@discussion
- *		This function can be called more than once to specify a set of multiple input interfaces.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_parameters_add_input_interface(mrc_dns_proxy_parameters_t params, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Sets the output interface in a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param ifindex
- *		The output interface's index.
- *
- *	@discussion
- *		By default, the output interface index is 0, which means that the remote DNS proxy instance will use the
- *		most suitable interface for its DNS network traffic.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_parameters_set_output_interface(mrc_dns_proxy_parameters_t params, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Sets the NAT64 IPv6 prefix in a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param prefix
- *		A pointer to the prefix.
- *
- *	@param prefix_bit_length
- *		The bit length of the prefix. Values greater than 128 will be treated as 128.
- *
- *	@discussion
- *		If a NAT64 prefix is set, then the remote instance of the DNS proxy will carry out DNS64 functionality
- *		using the specified NAT64 prefix. If it's not set, then no DNS64 functionality will be performed.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_parameters_set_nat64_prefix(mrc_dns_proxy_parameters_t params, const uint8_t *prefix,
-	size_t prefix_bit_length);
-
-/*!
- *	@brief
- *		Sets whether or not AAAA synthesis should be forced in a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param value
- *		The truth value.
- *
- *	@discussion
- *		Forcing AAAA synthesis only applies if the remote instance of the DNS proxy has DNS64 functionality
- *		enabled by specifying a NAT64 prefix with mrc_dns_proxy_parameters_set_nat64_prefix().
- *
- *		By default, AAAA synthesis is not forced.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_dns_proxy_parameters_set_force_aaaa_synthesis(mrc_dns_proxy_parameters_t params, bool value);
-
-/*!
- *	@brief
- *		A block used for enumerating interface indexes.
- *
- *	@param ifindex
- *		An enumerated interface index.
- *
- *	@result
- *		True if enumeration should continue onto the next interface index, if any. False if enumeration should
- *		not continue.
- */
-typedef bool
-(^mrc_dns_proxy_parameters_interface_applier_t)(uint32_t ifindex);
-
-/*!
- *	@brief
- *		Enumerates the input interface indexes in a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@param applier
- *		An applier to synchronously invoke once for each input interface index until either no interface indexes
- *		remains or the applier returns false. Note that if there are no input interface indexes, then the
- *		applier will not be invoked.
- *
- *	@result
- *		True if the applier never returned false during enumeration. Otherwise, false.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-bool
-mrc_dns_proxy_parameters_enumerate_input_interfaces(mrc_dns_proxy_parameters_t params,
-	mrc_dns_proxy_parameters_interface_applier_t applier);
-
-/*!
- *	@brief
- *		Gets the output interface index from a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@result
- *		The output interface index.
- *
- *	@discussion
- *		By default, the output interface index is 0, which means that the remote DNS proxy instance will use the
- *		most suitable interface for its DNS network traffic.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-uint32_t
-mrc_dns_proxy_parameters_get_output_interface(mrc_dns_proxy_parameters_t params);
-
-/*!
- *	@brief
- *		Gets the truth value of whether or not AAAA synthesis should be forced in a set of DNS proxy parameters.
- *
- *	@param params
- *		The parameters.
- *
- *	@result
- *		The truth value.
- *
- *	@discussion
- *		By default, AAAA synthesis is not forced.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-bool
-mrc_dns_proxy_parameters_get_force_aaaa_synthesis(mrc_dns_proxy_parameters_t params);
-
-/*!
- *	@brief
- *		Creates a DNS proxy state inquiry object, whose purpose is to inquire about the current state of all of
- *		the system's DNS proxies.
- *
- *	@result
- *		A reference to the new inquiry, or NULL if creation failed.
- *
- *	@discussion
- *		The state that is obtained by this object is human-readable text meant for diagnostic purposes.
- *
- *		If not using Objective-C ARC, use mrc_retain() and mrc_release() to retain and release references to the
- *		object.
- */
-MDNS_SPI_AVAILABLE_MIDFALL_2022
-MDNS_RETURNS_RETAINED MDNS_WARN_RESULT
-mrc_dns_proxy_state_inquiry_t
-mrc_dns_proxy_state_inquiry_create(void);
-
-/*!
- *	@brief
- *		Sets a DNS proxy state inquiry's queue on which to invoke its response handler.
- *
- *	@param inquiry
- *		The DNS proxy state inquiry.
- *
- *	@param queue
- *		The dispatch queue.
- *
- *	@discussion
- *		A dispatch queue must be set in order for an inquiry's response handler to be invoked.
- *
- *		This function should be called before the inquiry is activated. This function has no effect on an
- *		inquiry that has been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_MIDFALL_2022
-void
-mrc_dns_proxy_state_inquiry_set_queue(mrc_dns_proxy_state_inquiry_t inquiry, dispatch_queue_t queue);
-
-/*!
- *	@brief
- *		A DNS proxy state inquiry response handler.
- *
- *	@param state
- *		The state as a human-readable C string.
- *
- *	@param error
- *		An error code, which will be non-zero if a fatal error occurred, or zero, otherwise.
- *
- *	@discussion
- *		The lifetime of the state C string is not guaranteed beyond the invocation of this handler. If it is
- *		needed beyond the invocation of this handler, then it should be duplicated.
- */
-typedef void
-(^mrc_dns_proxy_state_inquiry_response_handler_t)(const char * _Nullable state, OSStatus error);
-
-/*!
- *	@brief
- *		Sets a DNS proxy state inquiry's response handler.
- *
- *	@param inquiry
- *		The DNS proxy state inquiry.
- *
- *	@param handler
- *		The response handler.
- *
- *	@discussion
- *		The response handler will never be invoked before the first call to either
- *		mrc_dns_proxy_state_inquiry_activate() or mrc_dns_proxy_state_inquiry_invalidate().
- *
- *		The response handler will be submitted to the inquiry's queue no more than once for one of the following
- *		events, whichever occurs first:
- *
- *		1. The system daemon that implements DNS proxies responds with the current state of the DNS proxies. In
- *		   this case, the handler will be invoked with a non-NULL state string and a kNoErr error code.
- *
- *		2. A fatal error occurs that halts the inquiry's progress. In this case, the handler will be invoked
- *		   with a NULL state string and a non-zero error code that indicates the type of error that occurred.
- *
- *		3. The inquiry is invalidated with mrc_dns_proxy_state_inquiry_invalidate(). In this case, the handler
- *		   will be invoked with a NULL state string and a kNoErr error code.
- *
- *		This function should be called before the inquiry is activated. This function has no effect on an
- *		inquiry that has been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_MIDFALL_2022
-void
-mrc_dns_proxy_state_inquiry_set_handler(mrc_dns_proxy_state_inquiry_t inquiry,
-	mrc_dns_proxy_state_inquiry_response_handler_t handler);
-
-/*!
- *	@brief
- *		Activates a DNS proxy state inquiry.
- *
- *	@param inquiry
- *		The DNS proxy state inquiry.
- *
- *	@discussion
- *		Activating an inquiry causes it to ask the system daemon that implements DNS proxies about the current
- *		state of those proxies.
- *
- *		This function has no effect on an inquiry that has already been activated or invalidated.
- */
-MDNS_SPI_AVAILABLE_MIDFALL_2022
-void
-mrc_dns_proxy_state_inquiry_activate(mrc_dns_proxy_state_inquiry_t inquiry);
-
-/*!
- *	@brief
- *		Invalidates a DNS proxy state inquiry.
- *
- *	@param inquiry
- *		The DNS proxy state inquiry.
- *
- *	@discussion
- *		This function exists to gracefully invalidate an inquiry.
- *
- *		If the inquiry's response handler hasn't already been invoked and isn't on its way to be invoked, then
- *		this function will force it to be invoked (asynchronously, of course) with a NULL state string. If the
- *		response handler has already been called, then calling this function is unnecessary, but harmless.
- *
- *		This function has no effect on an inquiry that has already been invalidated.
- */
-MDNS_SPI_AVAILABLE_MIDFALL_2022
-void
-mrc_dns_proxy_state_inquiry_invalidate(mrc_dns_proxy_state_inquiry_t inquiry);
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#endif	// MRC_DNS_PROXY_H
diff --git a/mDNSMacOSX/libmrc/mrc/object.h b/mDNSMacOSX/libmrc/mrc/object.h
deleted file mode 100644
index 0e4b524..0000000
--- a/mDNSMacOSX/libmrc/mrc/object.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_OBJECT_H
-#define MRC_OBJECT_H
-
-#if !defined(MRC_ALLOW_HEADER_INCLUDES) || !MRC_ALLOW_HEADER_INCLUDES
-	#error "Please include <mrc/private.h> instead of this file directly."
-#endif
-
-#include <mrc/object_members.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <mdns/base.h>
-
-#define MRC_BASE_DECL(NAME)				MDNS_COMMON_BASE_DECL(mrc_ ## NAME)
-#define MRC_DECL_SUBKIND(NAME, SUPER)	MDNS_COMMON_DECL_SUBKIND(mrc_ ## NAME, mrc_ ## SUPER)
-#define MRC_DECL(NAME)					MRC_DECL_SUBKIND(NAME, object)
-
-MRC_BASE_DECL(object);
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-/*!
- *	@typedef mrc_any_t
- *	@brief
- *		A pointer to an mrc object.
- */
-#if OS_OBJECT_USE_OBJC
-	typedef mrc_object_t mrc_any_t;
-#else
-	#if defined(__cplusplus)
-		typedef void *mrc_any_t;
-	#else
-		typedef union {
-			MRC_OBJECT_MEMBERS
-		} mrc_any_t __attribute__((__transparent_union__));
-	#endif
-#endif
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Increments the reference count of an mrc object.
- *
- *	@param object
- *		The mrc object.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_retain(mrc_any_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-	#undef mrc_retain
-	#define mrc_retain(object)	(void)[(object) retain]
-#endif
-
-/*!
- *	@brief
- *		Decrements the reference count of an mrc object.
- *
- *	@param object
- *		The mrc object.
- */
-MDNS_SPI_AVAILABLE_FALL_2022
-void
-mrc_release(mrc_any_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-	#undef mrc_release
-	#define mrc_release(object)	[(object) release]
-#endif
-
-/*!
- *	@brief
- *		Explicitly retains an mrc object if ARC is disabled. Does nothing if ARC is enabled.
- *
- *	@param object
- *		The mrc object.
- *
- *	@discussion
- *		This is a convenience function that allows writing portable Objective-C code regardless of whether ARC
- *		is enabled or disabled.
- */
-static inline void
-mrc_retain_arc_safe(const mrc_any_t object)
-{
-#if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
-	(void)object;
-#else
-	mrc_retain(object);
-#endif
-}
-
-/*!
- *	@brief
- *		Explicitly releases an mrc object if ARC is disabled. Does nothing if ARC is enabled.
- *
- *	@param object
- *		The mrc object.
- *
- *	@discussion
- *		This is a convenience function that allows writing portable Objective-C code regardless of whether ARC
- *		is enabled or disabled.
- */
-static inline void
-mrc_release_arc_safe(const mrc_any_t object)
-{
-#if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
-	(void)object;
-#else
-	mrc_release(object);
-#endif
-}
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#define mrc_forget(PTR)						\
-	do {									\
-		if (*(PTR)) {						\
-			mrc_release_arc_safe(*(PTR));	\
-			*(PTR) = NULL;					\
-		}									\
-	} while(0)
-
-#endif	// MRC_OBJECT_H
diff --git a/mDNSMacOSX/libmrc/mrc/object_members.h b/mDNSMacOSX/libmrc/mrc/object_members.h
deleted file mode 100644
index bf2073f..0000000
--- a/mDNSMacOSX/libmrc/mrc/object_members.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_OBJECT_MEMBERS_H
-#define MRC_OBJECT_MEMBERS_H
-
-#if !defined(MRC_ALLOW_HEADER_INCLUDES) || !MRC_ALLOW_HEADER_INCLUDES
-	#error "Please include <mrc/private.h> instead of this file directly."
-#endif
-
-#define MRC_UNION_MEMBER(NAME)	struct mrc_ ## NAME ## _s *	_mrc_ ## NAME
-
-#define MRC_OBJECT_MEMBERS					\
-	MRC_UNION_MEMBER(object);				\
-	MRC_UNION_MEMBER(dns_proxy);			\
-	MRC_UNION_MEMBER(dns_proxy_parameters);	\
-	MRC_UNION_MEMBER(dns_proxy_state_inquiry);
-
-#endif	// MRC_OBJECT_MEMBERS_H
diff --git a/mDNSMacOSX/libmrc/mrc/private.h b/mDNSMacOSX/libmrc/mrc/private.h
deleted file mode 100644
index c4e01f9..0000000
--- a/mDNSMacOSX/libmrc/mrc/private.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_PRIVATE_H
-#define MRC_PRIVATE_H
-
-#undef MRC_ALLOW_HEADER_INCLUDES
-#define MRC_ALLOW_HEADER_INCLUDES 1
-
-#include <mrc/dns_proxy.h>
-
-#undef MRC_ALLOW_HEADER_INCLUDES
-
-#endif	// MRC_PRIVATE_H
diff --git a/mDNSMacOSX/libmrc/src/mrc.c b/mDNSMacOSX/libmrc/src/mrc.c
deleted file mode 100644
index 55e51dd..0000000
--- a/mDNSMacOSX/libmrc/src/mrc.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#include <mrc/dns_proxy.h>
-
-#include "helpers.h"
-#include "mdns_memcpy_bits.h"
-#include "mrc_objects.h"
-#include "mrc_xpc.h"
-
-#include <arpa/inet.h>
-#include <CoreUtils/CoreUtils.h>
-#include <mdns/xpc.h>
-#include <os/log.h>
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - DNS Proxy Kind Definition
-
-OS_CLOSED_ENUM(mrc_dns_proxy_state, int8_t,
-	mrc_dns_proxy_state_failed		= -2,
-	mrc_dns_proxy_state_invalidated	= -1,
-	mrc_dns_proxy_state_nascent		=  0,
-	mrc_dns_proxy_state_starting	=  1,
-	mrc_dns_proxy_state_started		=  2
-);
-
-struct mrc_dns_proxy_s {
-	struct mdns_obj_s				base;			// Object base.
-	mrc_dns_proxy_t					next;			// Next DNS proxy object in list.
-	dispatch_queue_t				queue;			// User's dispatch queue.
-	xpc_object_t					params;			// DNS proxy parameters.
-	mrc_dns_proxy_event_handler_t	event_handler;	// Event handler.
-	uint64_t						cmd_id;			// Command ID.
-	mrc_dns_proxy_state_t			state;			// Current state.
-	bool							immutable;		// True if the DNS proxy is no longer externally mutable.
-};
-
-MRC_OBJECT_SUBKIND_DEFINE(dns_proxy);
-
-//======================================================================================================================
-
-struct mrc_dns_proxy_parameters_s {
-	struct mdns_obj_s	base;	// Object base.
-	xpc_object_t		dict;	// DNS proxy parameters.
-};
-
-MRC_OBJECT_SUBKIND_DEFINE(dns_proxy_parameters);
-
-//======================================================================================================================
-// MARK: - DNS Proxy State Inquiry Kind Definition
-
-OS_CLOSED_ENUM(mrc_dns_proxy_state_inquiry_state, int8_t,
-	mrc_dns_proxy_state_inquiry_state_nascent		= 0,
-	mrc_dns_proxy_state_inquiry_state_registered	= 1,
-	mrc_dns_proxy_state_inquiry_state_in_progress	= 2,
-	mrc_dns_proxy_state_inquiry_state_done			= 3
-);
-
-struct mrc_dns_proxy_state_inquiry_s {
-	struct mdns_obj_s								base;		// Object base.
-	mrc_dns_proxy_state_inquiry_t					next;		// Next inquiry in list.
-	dispatch_queue_t								queue;		// User's dispatch queue.
-	mrc_dns_proxy_state_inquiry_response_handler_t	handler;	// Response handler.
-	uint64_t										cmd_id;		// Command ID.
-	mrc_dns_proxy_state_inquiry_state_t				state;		// Current inquiry state.
-	bool											immutable;	// True if this object is no longer externally mutable.
-};
-
-MRC_OBJECT_SUBKIND_DEFINE(dns_proxy_state_inquiry);
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static void
-_mrc_dns_proxy_activate(mrc_dns_proxy_t proxy);
-
-static void
-_mrc_dns_proxy_terminate_async(mrc_dns_proxy_t proxy, OSStatus error);
-
-static void
-_mrc_dns_proxy_register(mrc_dns_proxy_t proxy);
-
-static void
-_mrc_dns_proxy_deregister(mrc_dns_proxy_t proxy);
-
-static void
-_mrc_dns_proxy_start(mrc_dns_proxy_t proxy);
-
-static void
-_mrc_dns_proxy_stop(mrc_dns_proxy_t proxy);
-
-static void
-_mrc_dns_proxy_state_inquiry_register(mrc_dns_proxy_state_inquiry_t inquiry);
-
-static void
-_mrc_dns_proxy_state_inquiry_deregister(mrc_dns_proxy_state_inquiry_t inquiry);
-
-static void
-_mrc_dns_proxy_state_inquiry_send_command(mrc_dns_proxy_state_inquiry_t inquiry);
-
-static void
-_mrc_dns_proxy_state_inquiry_terminate_with_error(mrc_dns_proxy_state_inquiry_t inquiry, OSStatus error);
-
-static void
-_mrc_dns_proxy_state_inquiry_terminate_with_state_description(mrc_dns_proxy_state_inquiry_t inquiry,
-	mdns_xpc_string_t description);
-
-static os_log_t
-_mrc_client_log(void);
-
-static dispatch_queue_t
-_mrc_client_queue(void);
-
-static xpc_connection_t
-_mrc_client_connection(void);
-
-static OSStatus
-_mrc_xpc_dns_proxy_params_print_description(xpc_object_t params, bool debug, bool privacy, char *buf, size_t buf_len,
-	size_t *out_len, size_t *out_full_len);
-
-//======================================================================================================================
-// MARK: - Globals
-
-static mrc_dns_proxy_t g_dns_proxy_list = NULL;
-static mrc_dns_proxy_state_inquiry_t g_dns_proxy_state_inquiry_list = NULL;
-
-//======================================================================================================================
-// MARK: - DNS Proxy Public Methods
-
-mrc_dns_proxy_t
-mrc_dns_proxy_create(const mrc_dns_proxy_parameters_t params, OSStatus * const out_error)
-{
-	OSStatus err;
-	mrc_dns_proxy_t proxy = NULL;
-	mrc_dns_proxy_t obj = _mrc_dns_proxy_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->params = xpc_copy(params->dict);
-	require_action_quiet(obj->params, exit, err = kNoResourcesErr);
-
-	proxy = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrc_forget(&obj);
-	return proxy;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_set_queue(const mrc_dns_proxy_t me, const dispatch_queue_t queue)
-{
-	require_return(!me->immutable);
-	if (queue) {
-		dispatch_retain(queue);
-	}
-	dispatch_forget(&me->queue);
-	me->queue = queue;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_set_event_handler(const mrc_dns_proxy_t me, const mrc_dns_proxy_event_handler_t handler)
-{
-	require_return(!me->immutable);
-	const mrc_dns_proxy_event_handler_t new_handler = handler ? Block_copy(handler) : NULL;
-	BlockForget(&me->event_handler);
-	me->event_handler = new_handler;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_activate(const mrc_dns_proxy_t me)
-{
-	me->immutable = true;
-	mrc_retain(me);
-	dispatch_async(_mrc_client_queue(),
-	^{
-		_mrc_dns_proxy_activate(me);
-		mrc_release(me);
-	});
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_invalidate(const mrc_dns_proxy_t me)
-{
-	me->immutable = true;
-	_mrc_dns_proxy_terminate_async(me, kNoErr);
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Private Methods
-
-static OSStatus
-_mrc_dns_proxy_print_description(const mrc_dns_proxy_t me, const bool debug, const bool privacy, char * const buf,
-	const size_t buf_len, size_t * const out_len, size_t * const out_full_len)
-{
-	OSStatus err;
-	char *dst = buf;
-	const char * const lim = &buf[buf_len];
-	size_t full_len = 0;
-
-#define _do_appendf(...)											\
-	do {															\
-		const int _n = mdns_snprintf_add(&dst, lim, __VA_ARGS__);	\
-		require_action_quiet(_n >= 0, exit, err = kUnknownErr);		\
-		full_len += (size_t)_n;										\
-	} while(0)
-
-	if (debug) {
-		_do_appendf("<%s: %p>: ", me->base.kind->name, me);
-	}
-#undef _do_appendf
-	size_t wrote_len, desc_full_len;
-	err = _mrc_xpc_dns_proxy_params_print_description(me->params, debug, privacy, dst, (size_t)(lim - dst), &wrote_len,
-		&desc_full_len);
-	require_noerr_quiet(err, exit);
-
-	dst += wrote_len;
-	full_len += desc_full_len;
-
-	if (out_len) {
-		*out_len = (size_t)(dst - buf);
-	}
-	if (out_full_len) {
-		*out_full_len = full_len;
-	}
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static char *
-_mrc_dns_proxy_copy_description(const mrc_dns_proxy_t me, const bool debug, const bool privacy)
-{
-	char *description = NULL;
-	char buf[128];
-	size_t full_len;
-	OSStatus err = _mrc_dns_proxy_print_description(me, debug, privacy, buf, sizeof(buf), NULL, &full_len);
-	require_noerr_quiet(err, exit);
-
-	if (full_len < sizeof(buf)) {
-		description = mdns_strdup(buf);
-	} else {
-		const size_t buf_len = full_len + 1;
-		char *buf_ptr = (char *)mdns_malloc(buf_len);
-		require_quiet(buf_ptr, exit);
-
-		err = _mrc_dns_proxy_print_description(me, debug, privacy, buf_ptr, buf_len, NULL, NULL);
-		require_noerr_action_quiet(err, exit, ForgetMem(&buf_ptr));
-
-		description = buf_ptr;
-	}
-
-exit:
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_finalize(const mrc_dns_proxy_t me)
-{
-	dispatch_forget(&me->queue);
-	xpc_forget(&me->params);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_activate(const mrc_dns_proxy_t me)
-{
-	require_return(me->state == mrc_dns_proxy_state_nascent);
-
-	_mrc_dns_proxy_register(me);
-	_mrc_dns_proxy_start(me);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_generate_event_with_error(const mrc_dns_proxy_t me, const mrc_dns_proxy_event_t event,
-	const OSStatus error)
-{
-	require_return(me->queue && me->event_handler);
-
-	const mrc_dns_proxy_event_handler_t event_handler = Block_copy(me->event_handler);
-	dispatch_async(me->queue,
-	^{
-		event_handler(event, error);
-		mrc_dns_proxy_event_handler_t tmp = event_handler;
-		BlockForget(&tmp);
-	});
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_generate_event(const mrc_dns_proxy_t me, const mrc_dns_proxy_event_t event)
-{
-	_mrc_dns_proxy_generate_event_with_error(me, event, kNoErr);
-}
-
-//======================================================================================================================
-
-static uint64_t
-_mrc_client_get_new_command_id(void)
-{
-	static uint64_t last_command_id = 0;
-	return ++last_command_id;
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_register(const mrc_dns_proxy_t me)
-{
-	require_return(me->cmd_id == 0);
-
-	me->cmd_id = _mrc_client_get_new_command_id();
-	mrc_dns_proxy_t *ptr = &g_dns_proxy_list;
-	while (*ptr) {
-		ptr = &(*ptr)->next;
-	}
-	*ptr = me;
-	mrc_retain(*ptr);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_deregister(const mrc_dns_proxy_t me)
-{
-	mrc_dns_proxy_t *ptr = &g_dns_proxy_list;
-	while (*ptr && (*ptr != me)) {
-		ptr = &(*ptr)->next;
-	}
-	if (*ptr) {
-		mrc_release(*ptr);
-		*ptr = me->next;
-		me->next = NULL;
-	}
-}
-
-static void
-_mrcs_dns_proxy_handle_dns_proxy_start_reply(const mrc_dns_proxy_t me, const uint64_t cmd_id, const xpc_object_t reply)
-{
-	require_return(me->cmd_id == cmd_id);
-	require_return(me->state == mrc_dns_proxy_state_starting);
-
-	if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
-		bool valid;
-		OSStatus err = mrc_xpc_message_get_error(reply, &valid);
-		if (!valid) {
-			err = kResponseErr;
-		}
-		os_log_with_type(_mrc_client_log(), err ? OS_LOG_TYPE_ERROR : OS_LOG_TYPE_INFO,
-			"[DP%llu] DNS proxy start reply -- error: %{mdns:err}ld", (unsigned long long)me->cmd_id, (long)err);
-		if (!err) {
-			me->state = mrc_dns_proxy_state_started;
-			_mrc_dns_proxy_generate_event(me, mrc_dns_proxy_event_started);
-		} else {
-			me->state = mrc_dns_proxy_state_failed;
-			_mrc_dns_proxy_terminate_async(me, err);
-		}
-	} else {
-		char *description = xpc_copy_description(reply);
-		os_log_error(_mrc_client_log(),
-			"[DP%llu] Abnormal DNS proxy start reply: %{public}s", (unsigned long long)me->cmd_id, description);
-		ForgetMem(&description);
-		if (reply != XPC_ERROR_CONNECTION_INTERRUPTED) {
-			const OSStatus err = (reply == XPC_ERROR_CONNECTION_INVALID) ? kConnectionErr : kResponseErr;
-			me->state = mrc_dns_proxy_state_failed;
-			_mrc_dns_proxy_terminate_async(me, err);
-		}
-	}
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_start(const mrc_dns_proxy_t me)
-{
-	me->state = mrc_dns_proxy_state_starting;
-	xpc_object_t msg = mrc_xpc_create_dns_proxy_start_command_message(me->cmd_id, me->params);
-	mrc_retain(me);
-	const uint64_t cmd_id = me->cmd_id;
-	xpc_connection_send_message_with_reply(_mrc_client_connection(), msg, _mrc_client_queue(),
-	^(const xpc_object_t reply)
-	{
-		_mrcs_dns_proxy_handle_dns_proxy_start_reply(me, cmd_id, reply);
-		mrc_release(me);
-	});
-	xpc_forget(&msg);
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_dns_proxy_handle_dns_proxy_stop_reply(const mrc_dns_proxy_t me, const xpc_object_t reply)
-{
-	if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
-		bool valid;
-		OSStatus err = mrc_xpc_message_get_error(reply, &valid);
-		if (!valid) {
-			err = kResponseErr;
-		}
-		os_log_with_type(_mrc_client_log(), err ? OS_LOG_TYPE_ERROR : OS_LOG_TYPE_INFO,
-			"[DP%llu] DNS proxy stop reply -- error: %{mdns:err}ld", (unsigned long long)me->cmd_id, (long)err);
-	} else {
-		char *description = xpc_copy_description(reply);
-		os_log_error(_mrc_client_log(),
-			"[DP%llu] Abnormal DNS proxy stop reply: %{public}s", (unsigned long long)me->cmd_id, description);
-		ForgetMem(&description);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_stop(const mrc_dns_proxy_t me)
-{
-	xpc_object_t msg = mrc_xpc_create_dns_proxy_stop_command_message(me->cmd_id);
-	mrc_retain(me);
-	xpc_connection_send_message_with_reply(_mrc_client_connection(), msg, _mrc_client_queue(),
-	^(const xpc_object_t reply)
-	{
-		_mrcs_dns_proxy_handle_dns_proxy_stop_reply(me, reply);
-		mrc_release(me);
-	});
-	xpc_forget(&msg);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_terminate_direct(const mrc_dns_proxy_t me, const OSStatus error)
-{
-	require_return(me->state != mrc_dns_proxy_state_invalidated);
-
-	_mrc_dns_proxy_deregister(me);
-	switch (me->state) {
-		case mrc_dns_proxy_state_starting:
-		case mrc_dns_proxy_state_started:
-			_mrc_dns_proxy_stop(me);
-			break;
-
-		case mrc_dns_proxy_state_failed:
-		case mrc_dns_proxy_state_invalidated:
-		case mrc_dns_proxy_state_nascent:
-			break;
-	}
-	me->state = mrc_dns_proxy_state_invalidated;
-	_mrc_dns_proxy_generate_event_with_error(me, mrc_dns_proxy_event_invalidation, error);
-	BlockForget(&me->event_handler);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_terminate_async(const mrc_dns_proxy_t me, const OSStatus error)
-{
-	mrc_retain(me);
-	dispatch_async(_mrc_client_queue(),
-	^{
-		_mrc_dns_proxy_terminate_direct(me, error);
-		mrc_release(me);
-	});
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Parameters Public Methods
-
-mrc_dns_proxy_parameters_t
-mrc_dns_proxy_parameters_create(OSStatus * const out_error)
-{
-	OSStatus err;
-	mrc_dns_proxy_parameters_t params = NULL;
-	mrc_dns_proxy_parameters_t obj = _mrc_dns_proxy_parameters_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->dict = xpc_dictionary_create(NULL, NULL, 0);
-	require_action_quiet(obj->dict, exit, err = kNoResourcesErr);
-
-	params = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrc_forget(&obj);
-	return params;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_parameters_add_input_interface(const mrc_dns_proxy_parameters_t me, const uint32_t ifindex)
-{
-	mrc_xpc_dns_proxy_params_add_input_interface(me->dict, ifindex);
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_parameters_set_output_interface(const mrc_dns_proxy_parameters_t me, const uint32_t ifindex)
-{
-	mrc_xpc_dns_proxy_params_set_output_interface(me->dict, ifindex);
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_parameters_set_nat64_prefix(const mrc_dns_proxy_parameters_t me, const uint8_t * const prefix,
-	const size_t prefix_bitlen)
-{
-	mrc_xpc_dns_proxy_params_set_nat64_prefix(me->dict, prefix, prefix_bitlen);
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_parameters_set_force_aaaa_synthesis(const mrc_dns_proxy_parameters_t me, bool value)
-{
-	mrc_xpc_dns_proxy_params_set_force_aaaa_synthesis(me->dict, value);
-}
-
-//======================================================================================================================
-
-bool
-mrc_dns_proxy_parameters_enumerate_input_interfaces(const mrc_dns_proxy_parameters_t me,
-	const mrc_dns_proxy_parameters_interface_applier_t applier)
-{
-	bool completed = false;
-	const xpc_object_t interfaces = mrc_xpc_dns_proxy_params_get_input_interfaces(me->dict);
-	const size_t n = interfaces ? xpc_array_get_count(interfaces) : 0;
-	for (size_t i = 0; i < n; ++i) {
-		const uint32_t ifindex = mdns_xpc_array_get_uint32(interfaces, i, NULL);
-		const bool proceed = applier(ifindex);
-		if (!proceed) {
-			goto exit;
-		}
-	}
-	completed = true;
-
-exit:
-	return completed;
-}
-
-//======================================================================================================================
-
-uint32_t
-mrc_dns_proxy_parameters_get_output_interface(const mrc_dns_proxy_parameters_t me)
-{
-	return mrc_xpc_dns_proxy_params_get_output_interface(me->dict, NULL);
-}
-
-//======================================================================================================================
-
-bool
-mrc_dns_proxy_parameters_get_force_aaaa_synthesis(const mrc_dns_proxy_parameters_t me)
-{
-	return mrc_xpc_dns_proxy_params_get_force_aaaa_synthesis(me->dict, NULL);
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Parameters Private Methods
-
-static OSStatus
-_mrc_dns_proxy_parameters_print_description(const mrc_dns_proxy_parameters_t me, const bool debug,
-	const bool privacy, char * const buf, const size_t buf_len, size_t * const out_len, size_t * const out_full_len)
-{
-	OSStatus err;
-	char *dst = buf;
-	const char * const lim = &buf[buf_len];
-	size_t full_len = 0;
-
-#define _do_appendf(...)											\
-	do {															\
-		const int _n = mdns_snprintf_add(&dst, lim, __VA_ARGS__);	\
-		require_action_quiet(_n >= 0, exit, err = kUnknownErr);		\
-		full_len += (size_t)_n;										\
-	} while(0)
-
-	if (debug) {
-		_do_appendf("<%s: %p>: ", me->base.kind->name, me);
-	}
-#undef _do_appendf
-	size_t wrote_len, desc_full_len;
-	err = _mrc_xpc_dns_proxy_params_print_description(me->dict, debug, privacy, dst, (size_t)(lim - dst), &wrote_len,
-		&desc_full_len);
-	require_noerr_quiet(err, exit);
-
-	dst += wrote_len;
-	full_len += desc_full_len;
-
-	if (out_len) {
-		*out_len = (size_t)(dst - buf);
-	}
-	if (out_full_len) {
-		*out_full_len = full_len;
-	}
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static char *
-_mrc_dns_proxy_parameters_copy_description(const mrc_dns_proxy_parameters_t me, const bool debug, const bool privacy)
-{
-	char *description = NULL;
-	char buf[128];
-	size_t full_len;
-	OSStatus err = _mrc_dns_proxy_parameters_print_description(me, debug, privacy, buf, sizeof(buf), NULL, &full_len);
-	require_noerr_quiet(err, exit);
-
-	if (full_len < sizeof(buf)) {
-		description = mdns_strdup(buf);
-	} else {
-		const size_t buf_len = full_len + 1;
-		char *buf_ptr = (char *)mdns_malloc(buf_len);
-		require_quiet(buf_ptr, exit);
-
-		err = _mrc_dns_proxy_parameters_print_description(me, debug, privacy, buf_ptr, buf_len, NULL, NULL);
-		require_noerr_action_quiet(err, exit, ForgetMem(&buf_ptr));
-
-		description = buf_ptr;
-	}
-
-exit:
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_parameters_finalize(const mrc_dns_proxy_parameters_t me)
-{
-	xpc_forget(&me->dict);
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy State Inquiry Public Methods
-
-mrc_dns_proxy_state_inquiry_t
-mrc_dns_proxy_state_inquiry_create()
-{
-	return _mrc_dns_proxy_state_inquiry_new();
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_state_inquiry_set_queue(const mrc_dns_proxy_state_inquiry_t me, const dispatch_queue_t queue)
-{
-	require_return(!me->immutable);
-	if (queue) {
-		dispatch_retain(queue);
-	}
-	dispatch_forget(&me->queue);
-	me->queue = queue;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_state_inquiry_set_handler(const mrc_dns_proxy_state_inquiry_t me,
-	const mrc_dns_proxy_state_inquiry_response_handler_t handler)
-{
-	require_return(!me->immutable);
-	const mrc_dns_proxy_state_inquiry_response_handler_t new_handler = handler ? Block_copy(handler) : NULL;
-	BlockForget(&me->handler);
-	me->handler = new_handler;
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_state_inquiry_activate(const mrc_dns_proxy_state_inquiry_t me)
-{
-	me->immutable = true;
-	mrc_retain(me);
-	dispatch_async(_mrc_client_queue(),
-	^{
-		_mrc_dns_proxy_state_inquiry_register(me);
-		_mrc_dns_proxy_state_inquiry_send_command(me);
-		mrc_release(me);
-	});
-}
-
-//======================================================================================================================
-
-void
-mrc_dns_proxy_state_inquiry_invalidate(const mrc_dns_proxy_state_inquiry_t me)
-{
-	me->immutable = true;
-	mrc_retain(me);
-	dispatch_async(_mrc_client_queue(),
-	^{
-		_mrc_dns_proxy_state_inquiry_terminate_with_state_description(me, NULL);
-		mrc_release(me);
-	});
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy State Inquiry Private Methods
-
-static char *
-_mrc_dns_proxy_state_inquiry_copy_description(const mrc_dns_proxy_state_inquiry_t me, __unused const bool debug,
-	__unused const bool privacy)
-{
-	char *description = NULL;
-	asprintf(&description, "<%s: %p>: ", me->base.kind->name, (void *)me);
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_finalize(const mrc_dns_proxy_state_inquiry_t me)
-{
-	dispatch_forget(&me->queue);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_register(const mrc_dns_proxy_state_inquiry_t me)
-{
-	require_return(me->state == mrc_dns_proxy_state_inquiry_state_nascent);
-
-	me->state = mrc_dns_proxy_state_inquiry_state_registered;
-	mrc_dns_proxy_state_inquiry_t *ptr = &g_dns_proxy_state_inquiry_list;
-	while (*ptr) {
-		ptr = &(*ptr)->next;
-	}
-	*ptr = me;
-	mrc_retain(*ptr);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_deregister(const mrc_dns_proxy_state_inquiry_t me)
-{
-	mrc_dns_proxy_state_inquiry_t *ptr = &g_dns_proxy_state_inquiry_list;
-	while (*ptr && (*ptr != me)) {
-		ptr = &(*ptr)->next;
-	}
-	if (*ptr) {
-		mrc_release(*ptr);
-		*ptr = me->next;
-		me->next = NULL;
-	}
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_handle_reply(const mrc_dns_proxy_state_inquiry_t me, const uint64_t cmd_id,
-	const xpc_object_t reply)
-{
-	require_return(me->cmd_id == cmd_id);
-	require_return(me->state == mrc_dns_proxy_state_inquiry_state_in_progress);
-
-	if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
-		bool valid;
-		OSStatus err = mrc_xpc_message_get_error(reply, &valid);
-		if (!valid) {
-			err = kResponseErr;
-		}
-		mdns_xpc_string_t state = NULL;
-		if (!err) {
-			mdns_xpc_dictionary_t result = mrc_xpc_message_get_result(reply);
-			if (result) {
-				state = mrc_xpc_dns_proxy_state_result_get_description(result);
-			}
-			if (!state) {
-				err = kResponseErr;
-			}
-		}
-		os_log_with_type(_mrc_client_log(), err ? OS_LOG_TYPE_ERROR : OS_LOG_TYPE_INFO,
-			"[DP%llu] DNS proxy state reply -- error: %{mdns:err}ld", (unsigned long long)me->cmd_id, (long)err);
-		if (err) {
-			_mrc_dns_proxy_state_inquiry_terminate_with_error(me, err);
-		} else {
-			_mrc_dns_proxy_state_inquiry_terminate_with_state_description(me, state);
-		}
-	} else {
-		char *description = xpc_copy_description(reply);
-		os_log_error(_mrc_client_log(),
-			"[DP%llu] Abnormal DNS proxy state reply: %{public}s", (unsigned long long)me->cmd_id, description);
-		ForgetMem(&description);
-		if (reply != XPC_ERROR_CONNECTION_INTERRUPTED) {
-			const OSStatus err = (reply == XPC_ERROR_CONNECTION_INVALID) ? kConnectionErr : kResponseErr;
-			_mrc_dns_proxy_state_inquiry_terminate_with_error(me, err);
-		}
-	}
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_send_command(const mrc_dns_proxy_state_inquiry_t me)
-{
-	require_return(
-		(me->state == mrc_dns_proxy_state_inquiry_state_registered) ||
-		(me->state == mrc_dns_proxy_state_inquiry_state_in_progress)
-	);
-	me->state = mrc_dns_proxy_state_inquiry_state_in_progress;
-	me->cmd_id = _mrc_client_get_new_command_id();
-	const uint64_t cmd_id = me->cmd_id;
-	xpc_object_t msg = mrc_xpc_create_dns_proxy_get_state_command_message(cmd_id);
-	mrc_retain(me);
-	xpc_connection_send_message_with_reply(_mrc_client_connection(), msg, _mrc_client_queue(),
-	^(const xpc_object_t reply)
-	{
-		_mrc_dns_proxy_state_inquiry_handle_reply(me, cmd_id, reply);
-		mrc_release(me);
-	});
-	xpc_forget(&msg);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_terminate_imp(const mrc_dns_proxy_state_inquiry_t me,
-	const mdns_xpc_string_t state_description, const OSStatus error)
-{
-	require_return(me->state != mrc_dns_proxy_state_inquiry_state_done);
-
-	_mrc_dns_proxy_state_inquiry_deregister(me);
-	me->state = mrc_dns_proxy_state_inquiry_state_done;
-	if (me->queue && me->handler) {
-		const mrc_dns_proxy_state_inquiry_response_handler_t handler = me->handler;
-		me->handler = NULL;
-		if (state_description) {
-			mdns_xpc_string_retain(state_description);
-		}
-		dispatch_async(me->queue,
-		^{
-			const char * const cstr = state_description ? mdns_xpc_string_get_string_ptr(state_description) : NULL;
-			handler(cstr, error);
-			mrc_dns_proxy_state_inquiry_response_handler_t tmp_handler = handler;
-			BlockForget(&tmp_handler);
-			mdns_xpc_string_t tmp = state_description;
-			mdns_xpc_string_forget(&tmp);
-		});
-	}
-	BlockForget(&me->handler);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_terminate_with_error(const mrc_dns_proxy_state_inquiry_t me, const OSStatus error)
-{
-	_mrc_dns_proxy_state_inquiry_terminate_imp(me, NULL, error);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_dns_proxy_state_inquiry_terminate_with_state_description(const mrc_dns_proxy_state_inquiry_t me,
-	const mdns_xpc_string_t description)
-{
-	_mrc_dns_proxy_state_inquiry_terminate_imp(me, description, kNoErr);
-}
-
-//======================================================================================================================
-// MARK: - Internal Functions
-
-static os_log_t
-_mrc_client_log(void)
-{
-	static dispatch_once_t s_once = 0;
-	static os_log_t s_log = NULL;
-	dispatch_once(&s_once,
-	^{
-		s_log = os_log_create("com.apple.mdns", "mrc");
-	});
-	return s_log;
-}
-
-//======================================================================================================================
-
-static dispatch_queue_t
-_mrc_client_queue(void)
-{
-	static dispatch_once_t s_once = 0;
-	static dispatch_queue_t s_queue = NULL;
-	dispatch_once(&s_once,
-	^{
-		s_queue = dispatch_queue_create("com.apple.mdns.mrc", DISPATCH_QUEUE_SERIAL);
-	});
-	return s_queue;	
-}
-
-//======================================================================================================================
-
-static void
-_mrc_client_handle_connection_interruption(void)
-{
-	for (mrc_dns_proxy_t proxy = g_dns_proxy_list; proxy; proxy = proxy->next) {
-		switch (proxy->state) {
-			case mrc_dns_proxy_state_starting:
-			case mrc_dns_proxy_state_started:
-				if (proxy->state == mrc_dns_proxy_state_started) {
-					_mrc_dns_proxy_generate_event(proxy, mrc_dns_proxy_event_interruption);
-				}
-				proxy->cmd_id = _mrc_client_get_new_command_id();
-				_mrc_dns_proxy_start(proxy);
-				break;
-
-			case mrc_dns_proxy_state_failed:
-			case mrc_dns_proxy_state_invalidated:
-			case mrc_dns_proxy_state_nascent:
-				break;
-		}
-	}
-	for (mrc_dns_proxy_state_inquiry_t inquiry = g_dns_proxy_state_inquiry_list; inquiry; inquiry = inquiry->next) {
-		switch (inquiry->state) {
-			case mrc_dns_proxy_state_inquiry_state_in_progress:
-				_mrc_dns_proxy_state_inquiry_send_command(inquiry);
-				break;
-
-			case mrc_dns_proxy_state_inquiry_state_nascent:
-			case mrc_dns_proxy_state_inquiry_state_registered:
-			case mrc_dns_proxy_state_inquiry_state_done:
-				break;
-		}
-	}
-}
-
-//======================================================================================================================
-
-static xpc_connection_t
-_mrc_client_connection(void)
-{
-	static xpc_connection_t s_connection = NULL;
-	require_quiet(!s_connection, exit);
-
-	const uint64_t flags = XPC_CONNECTION_MACH_SERVICE_PRIVILEGED;
-	s_connection = xpc_connection_create_mach_service(g_mrc_mach_service_name, _mrc_client_queue(), flags);
-	xpc_connection_set_event_handler(s_connection,
-	^(const xpc_object_t event)
-	{
-		const xpc_type_t type = xpc_get_type(event);
-		if (type == XPC_TYPE_ERROR) {
-			os_log_error(_mrc_client_log(),
-				"Connection error: %{public}s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
-		} else {
-			char *description = xpc_copy_description(event);
-			os_log(_mrc_client_log(),
-				"Unexpected connection event: %s", description);
-			ForgetMem(&description);
-		}
-		if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
-			_mrc_client_handle_connection_interruption();
-		}
-	});
-	xpc_connection_activate(s_connection);
-
-exit:
-	return s_connection;
-}
-
-//======================================================================================================================
-
-static OSStatus
-_mrc_xpc_dns_proxy_params_print_description(const xpc_object_t params, __unused const bool debug,
-	__unused const bool privacy, char * const buf, const size_t buf_len, size_t * const out_len,
-	size_t * const out_full_len)
-{
-	OSStatus err;
-	char *dst = buf;
-	const char * const lim = &buf[buf_len];
-	size_t full_len = 0;
-
-#define _do_appendf(...)											\
-	do {															\
-		const int _n = mdns_snprintf_add(&dst, lim, __VA_ARGS__);	\
-		require_action_quiet(_n >= 0, exit, err = kUnknownErr);		\
-		full_len += (size_t)_n;										\
-	} while(0)
-	_do_appendf("input interface indexes: {");
-	const xpc_object_t input_interfaces = mrc_xpc_dns_proxy_params_get_input_interfaces(params);
-	const size_t n = input_interfaces ? xpc_array_get_count(input_interfaces) : 0;
-	for (size_t i = 0; i < n; ++i) {
-		_do_appendf("%s%u", (i == 0) ? "" : ", ", mdns_xpc_array_get_uint32(input_interfaces, i, NULL));
-	}
-	_do_appendf("}, output interface index: %u", mrc_xpc_dns_proxy_params_get_output_interface(params, NULL));
-	size_t bitlen;
-	const uint8_t * const prefix = mrc_xpc_dns_proxy_params_get_nat64_prefix(params, &bitlen);
-	if (prefix) {
-		uint8_t ipv6_addr[16] = {0};
-		mdns_memcpy_bits(ipv6_addr, prefix, Min(bitlen, sizeof(ipv6_addr) * 8));
-
-		char addr_buf[INET6_ADDRSTRLEN];
-		const char * const addr_str = inet_ntop(AF_INET6, ipv6_addr, addr_buf, (socklen_t)sizeof(addr_buf));
-		err = map_global_value_errno(addr_str, addr_str);
-		require_noerr_quiet(err, exit);
-
-		_do_appendf(", nat64 prefix: %s/%zu", addr_str, bitlen);
-	}
-	const bool force_aaaa_synthesis = mrc_xpc_dns_proxy_params_get_force_aaaa_synthesis(params, NULL);
-	_do_appendf(", forces AAAA synthesis: %s", YesNoStr(force_aaaa_synthesis));
-#undef _do_appendf
-	if (out_len) {
-		*out_len = (size_t)(dst - buf);
-	}
-	if (out_full_len) {
-		*out_full_len = full_len;
-	}
-	err = kNoErr;
-
-exit:
-	return err;
-}
diff --git a/mDNSMacOSX/libmrc/src/mrc_object.c b/mDNSMacOSX/libmrc/src/mrc_object.c
deleted file mode 100644
index ea9f24a..0000000
--- a/mDNSMacOSX/libmrc/src/mrc_object.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include <mrc/object.h>
-
-#include "mdns_obj.h"
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Object Public Methods
-
-void
-mrc_retain(const mrc_object_t me)
-{
-	mdns_obj_retain(me);
-}
-
-//======================================================================================================================
-
-void
-mrc_release(const mrc_object_t me)
-{
-	mdns_obj_release(me);
-}
diff --git a/mDNSMacOSX/libmrc/src/mrc_objects.h b/mDNSMacOSX/libmrc/src/mrc_objects.h
deleted file mode 100644
index 921b989..0000000
--- a/mDNSMacOSX/libmrc/src/mrc_objects.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_OBJECTS_H
-#define MRC_OBJECTS_H
-
-#include "mdns_objects.h"
-
-#define MRC_OBJECT_SUBKIND_DEFINE_ABSTRACT(NAME)	MDNS_OBJ_SUBKIND_DEFINE_ABSTRACT(mrc_ ## NAME)
-#define MRC_OBJECT_SUBKIND_DEFINE(NAME)				MDNS_OBJ_SUBKIND_DEFINE(mrc_ ## NAME)
-#define MRC_OBJECT_SUBKIND_DEFINE_FULL(NAME)		MDNS_OBJ_SUBKIND_DEFINE_FULL(mrc_ ## NAME)
-
-#define MRC_BASE_CHECK(NAME, SUPER)	MDNS_OBJ_BASE_CHECK(mrc_ ## NAME, mrc_ ## SUPER)
-
-#define MRC_CLASS(NAME)			MDNS_OBJ_CLASS(mrc_ ## NAME)
-#define MRC_CLASS_DECL(NAME)	MDNS_OBJ_CLASS_DECL(mrc_ ## NAME)
-
-#endif	// MRC_OBJECTS_H
diff --git a/mDNSMacOSX/libmrc/src/mrc_xpc.c b/mDNSMacOSX/libmrc/src/mrc_xpc.c
deleted file mode 100644
index 6f5d35a..0000000
--- a/mDNSMacOSX/libmrc/src/mrc_xpc.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "mrc_xpc.h"
-
-#include <mdns/xpc.h>
-#include "mdns_memcpy_bits.h"
-
-#include <CoreUtils/CoreUtils.h>
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static xpc_object_t
-_mrc_xpc_create_command_message(uint64_t ident, const char *command, xpc_object_t params);
-
-static void
-_mrc_xpc_message_set_id(xpc_object_t msg, uint64_t ident);
-
-static void
-_mrc_xpc_message_set_command(const xpc_object_t msg, const char * const command);
-
-static void
-_mrc_xpc_message_set_parameters(xpc_object_t msg, xpc_object_t params);
-
-static void
-_mrc_xpc_message_set_error(xpc_object_t msg, OSStatus error);
-
-static void
-_mrc_xpc_message_set_result(xpc_object_t msg, mdns_xpc_dictionary_t result);
-
-//======================================================================================================================
-// MARK: - Mach Service Name
-
-const char * const g_mrc_mach_service_name = "com.apple.mDNSResponder.control";
-
-//======================================================================================================================
-// MARK: - Commands
-
-const char * const g_mrc_command_dns_proxy_start		= "dns_proxy.start";
-const char * const g_mrc_command_dns_proxy_stop			= "dns_proxy.stop";
-const char * const g_mrc_command_dns_proxy_get_state	= "dns_proxy.get_state";
-
-//======================================================================================================================
-// MARK: - Top-Level Dictionary Keys
-
-static const char * const g_mrc_message_key_command	= "command";
-static const char * const g_mrc_message_key_error	= "error";
-static const char * const g_mrc_message_key_id		= "id";
-static const char * const g_mrc_message_key_params	= "params";
-static const char * const g_mrc_message_key_result	= "result";
-
-//======================================================================================================================
-// MARK: - DNS Proxy Keys
-
-static const char * const g_mrc_dns_proxy_key_input_interfaces		= "input_interfaces";
-static const char * const g_mrc_dns_proxy_key_nat64_prefix_bit_len	= "nat64_prefix.bit_len";
-static const char * const g_mrc_dns_proxy_key_nat64_prefix_bits		= "nat64_prefix.bits";
-static const char * const g_mrc_dns_proxy_key_output_interface		= "output_interface";
-static const char * const g_mrc_dns_proxy_key_force_aaaa_synthesis	= "force_aaaa_synth";
-
-//======================================================================================================================
-// MARK: - Result Keys
-
-static const char * const g_mrc_result_key_description = "description";
-
-//======================================================================================================================
-// MARK: - External Message Functions
-
-uint64_t
-mrc_xpc_message_get_id(const xpc_object_t msg)
-{
-	return xpc_dictionary_get_uint64(msg, g_mrc_message_key_id);
-}
-
-//======================================================================================================================
-
-const char *
-mrc_xpc_message_get_command(const xpc_object_t msg)
-{
-	return xpc_dictionary_get_string(msg, g_mrc_message_key_command);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-mrc_xpc_message_get_params(const xpc_object_t msg)
-{
-	return mdns_xpc_dictionary_get_dictionary(msg, g_mrc_message_key_params);
-}
-
-//======================================================================================================================
-
-check_compile_time(((OSStatus)-1) < 0); // Make sure OSStatus is indeed signed.
-
-OSStatus
-mrc_xpc_message_get_error(const xpc_object_t msg, bool * const out_valid)
-{
-	return (OSStatus)mdns_xpc_dictionary_get_int32(msg, g_mrc_message_key_error, out_valid);
-}
-
-//======================================================================================================================
-
-mdns_xpc_dictionary_t
-mrc_xpc_message_get_result(const xpc_object_t msg)
-{
-	return mdns_xpc_dictionary_get_dictionary(msg, g_mrc_message_key_result);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-mrc_xpc_create_reply(const xpc_object_t msg, const OSStatus error, const mdns_xpc_dictionary_t result)
-{
-	xpc_object_t reply = xpc_dictionary_create_reply(msg);
-	require_quiet(reply, exit);
-
-	const uint64_t ident = mrc_xpc_message_get_id(msg);
-	_mrc_xpc_message_set_id(reply, ident);
-	_mrc_xpc_message_set_error(reply, error);
-	if (result) {
-		_mrc_xpc_message_set_result(reply, result);
-	}
-
-exit:
-	return reply;
-}
-
-//======================================================================================================================
-// MARK: - External DNS Proxy Functions
-
-xpc_object_t
-mrc_xpc_create_dns_proxy_start_command_message(const uint64_t ident, const xpc_object_t params)
-{
-	return _mrc_xpc_create_command_message(ident, g_mrc_command_dns_proxy_start, params);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-mrc_xpc_create_dns_proxy_stop_command_message(const uint64_t ident)
-{
-	return _mrc_xpc_create_command_message(ident, g_mrc_command_dns_proxy_stop, NULL);
-}
-
-//======================================================================================================================
-
-xpc_object_t
-mrc_xpc_create_dns_proxy_get_state_command_message(const uint64_t ident)
-{
-	return _mrc_xpc_create_command_message(ident, g_mrc_command_dns_proxy_get_state, NULL);
-}
-
-//======================================================================================================================
-
-void
-mrc_xpc_dns_proxy_params_add_input_interface(const xpc_object_t params, const uint32_t ifindex)
-{
-	bool already_present = false;
-	xpc_object_t interfaces = mrc_xpc_dns_proxy_params_get_input_interfaces(params);
-	if (interfaces) {
-		const size_t n = xpc_array_get_count(interfaces);
-		for (size_t i = 0; i < n; ++i) {
-			bool valid;
-			const uint32_t current_ifindex = mdns_xpc_array_get_uint32(interfaces, i, &valid);
-			if (valid && (current_ifindex == ifindex)) {
-				already_present = true;
-				break;
-			}
-		}
-	} else {
-		xpc_object_t new_interfaces = xpc_array_create(NULL, 0);
-		xpc_dictionary_set_value(params, g_mrc_dns_proxy_key_input_interfaces, new_interfaces);
-		interfaces = new_interfaces;
-		xpc_forget(&new_interfaces);
-	}
-	if (!already_present) {
-		mdns_xpc_array_append_uint32(interfaces, ifindex);
-	}
-}
-
-//======================================================================================================================
-
-xpc_object_t
-mrc_xpc_dns_proxy_params_get_input_interfaces(const xpc_object_t params)
-{
-	return mdns_xpc_dictionary_get_array(params, g_mrc_dns_proxy_key_input_interfaces);
-}
-
-//======================================================================================================================
-
-void
-mrc_xpc_dns_proxy_params_set_output_interface(const xpc_object_t params, const uint32_t ifindex)
-{
-	mdns_xpc_dictionary_set_uint32(params, g_mrc_dns_proxy_key_output_interface, ifindex);
-}
-
-//======================================================================================================================
-
-uint32_t
-mrc_xpc_dns_proxy_params_get_output_interface(const xpc_object_t params, bool * const out_valid)
-{
-	bool valid;
-	const char * const key = g_mrc_dns_proxy_key_output_interface;
-	const uint32_t ifindex = mdns_xpc_dictionary_get_uint32(params, key, &valid);
-	if (out_valid) {
-		if (!valid && !xpc_dictionary_get_value(params, key)) {
-			valid = true;
-		}
-		*out_valid = valid;
-	}
-	return ifindex;
-}
-
-//======================================================================================================================
-
-// Simply limit the bit length to the bit length of an IPv6 address. This code makes no assumptions about acceptable
-// NAT64 prefix bit lengths, which is something that should be enforced by the server side.
-#define MRC_NAT64_BIT_LEN_MAX	128
-#define MRC_ROUND_BIT_LEN_UP_TO_BYTE_LEN(BITLEN)	(RoundUp(BITLEN, 8) / 8)
-
-void
-mrc_xpc_dns_proxy_params_set_nat64_prefix(const xpc_object_t params, const uint8_t * const prefix,
-	const size_t prefix_bit_len)
-{
-	uint8_t buffer[16] = {0};
-	check_compile_time(sizeof(buffer) == MRC_ROUND_BIT_LEN_UP_TO_BYTE_LEN(MRC_NAT64_BIT_LEN_MAX));
-	const size_t bit_len = Min(prefix_bit_len, MRC_NAT64_BIT_LEN_MAX);
-	mdns_memcpy_bits(buffer, prefix, bit_len);
-	const size_t byte_len = MRC_ROUND_BIT_LEN_UP_TO_BYTE_LEN(bit_len);
-	xpc_dictionary_set_data(params, g_mrc_dns_proxy_key_nat64_prefix_bits, buffer, byte_len);
-	xpc_dictionary_set_uint64(params, g_mrc_dns_proxy_key_nat64_prefix_bit_len, bit_len);
-}
-
-//======================================================================================================================
-
-const uint8_t *
-mrc_xpc_dns_proxy_params_get_nat64_prefix(const xpc_object_t params, size_t * const out_bit_len)
-{
-	const uint8_t *result_bits = NULL;
-	bool valid;
-	const uint64_t bit_len = mdns_xpc_dictionary_get_uint64(params, g_mrc_dns_proxy_key_nat64_prefix_bit_len, &valid);
-	require_quiet(valid, exit);
-	require_quiet(bit_len <= MRC_NAT64_BIT_LEN_MAX, exit);
-
-	const uint8_t *bits;
-	if (bit_len > 0) {
-		size_t byte_len = 0;
-		bits = xpc_dictionary_get_data(params, g_mrc_dns_proxy_key_nat64_prefix_bits, &byte_len);
-		require_quiet(bits, exit);
-		require_quiet(byte_len >= MRC_ROUND_BIT_LEN_UP_TO_BYTE_LEN(bit_len), exit);
-	} else {
-		bits = (const uint8_t *)"";
-	}
-	result_bits = bits;
-	if (out_bit_len) {
-		*out_bit_len = (size_t)bit_len;
-	}
-
-exit:
-	return result_bits;
-}
-
-//======================================================================================================================
-
-void
-mrc_xpc_dns_proxy_params_set_force_aaaa_synthesis(const xpc_object_t params, const bool value)
-{
-	xpc_dictionary_set_bool(params, g_mrc_dns_proxy_key_force_aaaa_synthesis, value);
-}
-
-//======================================================================================================================
-
-bool
-mrc_xpc_dns_proxy_params_get_force_aaaa_synthesis(const xpc_object_t params, bool * const out_valid)
-{
-	bool valid;
-	const char * const key = g_mrc_dns_proxy_key_force_aaaa_synthesis;
-	const bool force_aaaa_synthesis = mdns_xpc_dictionary_get_bool(params, key, &valid);
-	if (out_valid) {
-		if (!valid && !xpc_dictionary_get_value(params, key)) {
-			valid = true;
-		}
-		*out_valid = valid;
-	}
-	return force_aaaa_synthesis;
-}
-
-//======================================================================================================================
-
-void
-mrc_xpc_dns_proxy_state_result_set_description(const mdns_xpc_dictionary_t result, const char * const description)
-{
-	xpc_dictionary_set_string(result, g_mrc_result_key_description, description);
-}
-
-//======================================================================================================================
-
-mdns_xpc_string_t
-mrc_xpc_dns_proxy_state_result_get_description(const mdns_xpc_dictionary_t result)
-{
-	return mdns_xpc_dictionary_get_string(result, g_mrc_result_key_description);
-}
-
-//======================================================================================================================
-// MARK: - Internal Message Functions
-
-static xpc_object_t
-_mrc_xpc_create_command_message(const uint64_t ident, const char * const command, const xpc_object_t params)
-{
-	xpc_object_t _Nonnull msg = xpc_dictionary_create(NULL, NULL, 0);
-	_mrc_xpc_message_set_id(msg, ident);
-	_mrc_xpc_message_set_command(msg, command);
-	if (params) {
-		_mrc_xpc_message_set_parameters(msg, params);
-	}
-	return msg;
-}
-
-//======================================================================================================================
-
-static void
-_mrc_xpc_message_set_id(const xpc_object_t msg, const uint64_t ident)
-{
-	xpc_dictionary_set_uint64(msg, g_mrc_message_key_id, ident);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_xpc_message_set_command(const xpc_object_t msg, const char * const command)
-{
-	xpc_dictionary_set_string(msg, g_mrc_message_key_command, command);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_xpc_message_set_parameters(const xpc_object_t msg, const xpc_object_t params)
-{
-	xpc_dictionary_set_value(msg, g_mrc_message_key_params, params);
-}
-
-//======================================================================================================================
-
-void
-_mrc_xpc_message_set_error(const xpc_object_t msg, const OSStatus error)
-{
-	mdns_xpc_dictionary_set_int32(msg, g_mrc_message_key_error, error);
-}
-
-//======================================================================================================================
-
-static void
-_mrc_xpc_message_set_result(const xpc_object_t msg, const mdns_xpc_dictionary_t result)
-{
-	xpc_dictionary_set_value(msg, g_mrc_message_key_result, result);
-}
diff --git a/mDNSMacOSX/libmrc/src/mrc_xpc.h b/mDNSMacOSX/libmrc/src/mrc_xpc.h
deleted file mode 100644
index c2542f3..0000000
--- a/mDNSMacOSX/libmrc/src/mrc_xpc.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRC_XPC_H
-#define MRC_XPC_H
-
-#include <mdns/base.h>
-
-#include <MacTypes.h>
-#include <mdns/xpc.h>
-#include <xpc/xpc.h>
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-/*!
- *	@brief
- *		mDNSResponder control Mach service name.
- */
-extern const char * const g_mrc_mach_service_name;
-
-/*!
- *	@brief
- *		DNS proxy start command string.
- */
-extern const char * const g_mrc_command_dns_proxy_start;
-
-/*!
- *	@brief
- *		DNS proxy stop command string.
- */
-extern const char * const g_mrc_command_dns_proxy_stop;
-
-/*!
- *	@brief
- *		DNS proxy get state command string.
- */
-extern const char * const g_mrc_command_dns_proxy_get_state;
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Gets the ID number from an XPC message.
- *
- *	@param msg
- *		The message.
- *
- *	@result
- *		The ID number, if present. Otherwise, 0.
- */
-uint64_t
-mrc_xpc_message_get_id(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Gets the command name from an XPC message as a C string.
- *
- *	@param msg
- *		The message.
- *
- *	@result
- *		The command, if present. Otherwise, NULL.
- */
-const char * _Nullable
-mrc_xpc_message_get_command(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Gets the parameters dictionary from an XPC message.
- *
- *	@param msg
- *		The message.
- *
- *	@result
- *		The parameters, if present. Otherwise, NULL.
- */
-xpc_object_t _Nullable
-mrc_xpc_message_get_params(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Gets the error code from an XPC message.
- *
- *	@param msg
- *		The message.
- *
- *	@param out_valid
- *		Variable to set to true if the error code value was properly set in the message. Otherwise, the variable
- *		is set to false.
- *
- *	@result
- *		The error code, if properly set. Otherwise, 0.
- */
-OSStatus
-mrc_xpc_message_get_error(xpc_object_t msg, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Gets the result dictionary from an XPC message.
- *
- *	@param msg
- *		The message.
- *
- *	@result
- *		The result dictionary, if present. Otherwise, NULL.
- */
-mdns_xpc_dictionary_t _Nullable
-mrc_xpc_message_get_result(xpc_object_t msg);
-
-/*!
- *	@brief
- *		Creates an XPC reply message from a received XPC command message.
- *
- *	@param error
- *		The error code to set in the reply message.
- *
- *	@param result
- *		The command-specific result dictionary to set in the reply message.
- *
- *	@result
- *		A reference to the reply message.
- */
-XPC_RETURNS_RETAINED
-xpc_object_t _Nullable
-mrc_xpc_create_reply(xpc_object_t msg, OSStatus error, mdns_xpc_dictionary_t _Nullable result);
-
-/*!
- *	@brief
- *		Creates an XPC message for the DNS proxy start command.
- *
- *	@param ident
- *		An ID number that uniquely identifies the new DNS proxy to start.
- *
- *	@param params
- *		The DNS proxy start command's parameters dictionary.
- *
- *	@result
- *		A reference to the message.
- */
-XPC_RETURNS_RETAINED
-xpc_object_t
-mrc_xpc_create_dns_proxy_start_command_message(uint64_t ident, xpc_object_t params);
-
-/*!
- *	@brief
- *		Creates an XPC message for the DNS proxy stop command.
- *
- *	@param ident
- *		An ID number that identifies the DNS proxy to stop.
- *
- *	@result
- *		A reference to the message.
- *
- *	@discussion
- *		The ID number should match the ID number used in the DNS proxy start command message.
- */
-XPC_RETURNS_RETAINED
-xpc_object_t
-mrc_xpc_create_dns_proxy_stop_command_message(uint64_t ident);
-
-/*!
- *	@brief
- *		Creates an XPC message for the DNS proxy get state command.
- *
- *	@param ident
- *		An ID number that uniquely identifies the command.
- *
- *	@result
- *		A reference to the message.
- */
-XPC_RETURNS_RETAINED
-xpc_object_t
-mrc_xpc_create_dns_proxy_get_state_command_message(uint64_t ident);
-
-/*!
- *	@brief
- *		Adds an input interface index to a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- */
-void
-mrc_xpc_dns_proxy_params_add_input_interface(xpc_object_t params, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Gets the internal array containing the input interface indexes from a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@result
- *		The array if present. Otherwise, NULL.
- *
- *	@discussion
- *		This function exists for the convenience of code that implements the client or server side of the XPC
- *		communication. Unfortunately, there is currently no such thing as an immutable XPC array reference. The
- *		array returned by this function must not be directly modified. Also, references to the array must never
- *		be shared beyond such implementation code since that risks the possibility of modification by external
- *		code.
- */
-xpc_object_t
-mrc_xpc_dns_proxy_params_get_input_interfaces(xpc_object_t params);
-
-/*!
- *	@brief
- *		Sets the output interface index in a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@param ifindex
- *		The output interface index.
- */
-void
-mrc_xpc_dns_proxy_params_set_output_interface(xpc_object_t params, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Gets the output interface index from a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@param out_valid
- *		Variable to set to true if the output interface index was properly set or is missing. Otherwise, the
- *		variable is set to false.
- *
- *	@result
- *		The output interface index if properly set. Otherwise, 0.
- *
- *	@discussion
- *		The default output interface index is 0.
- */
-uint32_t
-mrc_xpc_dns_proxy_params_get_output_interface(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Sets the NAT64 IPv6 prefix in a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@param prefix
- *		A pointer to the prefix.
- *
- *	@param prefix_bit_length
- *		The bit length of the prefix. Values greater than 128 will be treated as 128.
- */
-void
-mrc_xpc_dns_proxy_params_set_nat64_prefix(xpc_object_t params, const uint8_t *prefix, size_t prefix_bit_length);
-
-/*!
- *	@brief
- *		Gets the NAT64 IPv6 prefix from a DNS proxy parameters dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@param out_bitlen
- *		A variable to set to the prefix's bit length if the prefix is present.
- *
- *	@result
- *		The prefix if present. Otherwise, NULL.
- */
-const uint8_t * _Nullable
-mrc_xpc_dns_proxy_params_get_nat64_prefix(xpc_object_t params, size_t * _Nullable out_bitlen);
-
-/*!
- *	@brief
- *		Sets the truth value of whether or not AAAA synthesis should be forced in a DNS proxy parameters
- *		dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@param value
- *		The truth value.
- */
-void
-mrc_xpc_dns_proxy_params_set_force_aaaa_synthesis(xpc_object_t params, bool value);
-
-/*!
- *	@brief
- *		Gets the truth value of whether or not AAAA synthesis should be forced from a DNS proxy parameters
- *		dictionary.
- *
- *	@param params
- *		The parameters dictionary.
- *
- *	@result
- *		The truth value.
- *
- *	@discussion
- *		The default value is false.
- */
-bool
-mrc_xpc_dns_proxy_params_get_force_aaaa_synthesis(xpc_object_t params, bool * _Nullable out_valid);
-
-/*!
- *	@brief
- *		Sets the description in a DNS proxy state result dictionary.
- *
- *	@param result
- *		The result dictionary.
- *
- *	@param description
- *		A C string that contains the human-readable description of the DNS proxy state.
- */
-void
-mrc_xpc_dns_proxy_state_result_set_description(mdns_xpc_dictionary_t result, const char *description);
-
-/*!
- *	@brief
- *		Gets the description from a DNS proxy state result dictionary.
- *
- *	@param result
- *		The result dictionary.
- *
- *	@result
- *		The description if present. Otherwise, NULL.
- */
-mdns_xpc_string_t _Nullable
-mrc_xpc_dns_proxy_state_result_get_description(mdns_xpc_dictionary_t result);
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#endif	// MRC_XPC_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_cf_support.c b/mDNSMacOSX/libmrc/src/mrcs_cf_support.c
deleted file mode 100644
index 36b6b75..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_cf_support.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "mrcs_cf_support.h"
-
-#include "mdns_obj.h"
-#include "mrcs_object.h"
-
-#include <CoreUtils/CoreUtils.h>
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static const void *
-_mrcs_cf_callback_retain(CFAllocatorRef allocator, const void *value);
-
-static void
-_mrcs_cf_callback_release(CFAllocatorRef allocator, const void *value);
-
-static CFStringRef
-_mrcs_cf_callback_copy_description(const void *value);
-
-static mrcs_object_t
-_mrcs_cf_const_void_pointer_to_object(const void *value);
-
-//======================================================================================================================
-// MARK: - CF Callback Structures
-
-const CFArrayCallBacks mrcs_cfarray_callbacks = {
-	.version			= 0,
-	.retain				= _mrcs_cf_callback_retain,
-	.release			= _mrcs_cf_callback_release,
-	.copyDescription	= _mrcs_cf_callback_copy_description,
-};
-
-//======================================================================================================================
-// MARK: - External Functions
-
-bool
-mrcs_cfarray_enumerate(const CFArrayRef array, const mrcs_any_applier_t applier)
-{
-	bool completed = false;
-	const CFIndex n = CFArrayGetCount(array);
-	for (CFIndex i = 0; i < n; ++i) {
-		const mrcs_object_t object = _mrcs_cf_const_void_pointer_to_object(CFArrayGetValueAtIndex(array, i));
-		const bool proceed = applier(object);
-		if (!proceed) {
-			goto exit;
-		}
-	}
-	completed = true;
-
-exit:
-	return completed;
-}
-
-//======================================================================================================================
-// MARK: - Internal Functions
-
-static const void *
-_mrcs_cf_callback_retain(__unused const CFAllocatorRef allocator, const void * const value)
-{
-	const mrcs_object_t object = _mrcs_cf_const_void_pointer_to_object(value);
-	mrcs_retain(object);
-	return object;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_cf_callback_release(__unused const CFAllocatorRef allocator, const void * const value)
-{
-	const mrcs_object_t object = _mrcs_cf_const_void_pointer_to_object(value);
-	mrcs_release(object);
-}
-
-//======================================================================================================================
-
-static CFStringRef
-_mrcs_cf_callback_copy_description(const void * const value)
-{
-	const mrcs_object_t object = _mrcs_cf_const_void_pointer_to_object(value);
-	return mdns_obj_copy_description_as_cfstring(object);
-}
-
-//======================================================================================================================
-
-mrcs_object_t
-_mrcs_cf_const_void_pointer_to_object(const void * const value)
-{
-	// CF callbacks are broken in that they use 'const void *' for the values contained in collections, so they
-	// have to be unconstified when they're cast to mrcs_object_t, which is an opaque pointer type. This is a
-	// necessary evil in order for callbacks that modify a value, such as the retain and release callbacks, to
-	// work. Most retain and release operate by modifying an object's internal reference count, which is only
-	// possible with a non-const pointer.
-	CUClangWarningIgnoreBegin(-Wcast-qual);
-	const mrcs_object_t object = (mrcs_object_t)value;
-	CUClangWarningIgnoreEnd();
-	return object;
-}
diff --git a/mDNSMacOSX/libmrc/src/mrcs_cf_support.h b/mDNSMacOSX/libmrc/src/mrcs_cf_support.h
deleted file mode 100644
index 1fe3f57..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_cf_support.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_CF_SUPPORT_H
-#define MRCS_CF_SUPPORT_H
-
-#include "mrcs_object.h"
-
-#include <mdns/base.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-/*!
- *	@brief
- *		CFArray callbacks for mrcs objects.
- */
-extern const CFArrayCallBacks mrcs_cfarray_callbacks;
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		The type of block that handles any kind of mrcs_object during enumeration.
- *
- *	@param object
- *		The object.
- *
- *	@result
- *		True if enumeration should continue onto the next object, if any. False if enumeration should end.
- */
-typedef bool
-(^mrcs_any_applier_t)(mrcs_any_t object);
-
-/*!
- *	@brief
- *		Enumerates the mrcs_objects in a CFArray in sequential order starting with the object at index 0.
- *
- *	@param array
- *		The array.
- *
- *	@param applier
- *		Block to synchronously invoke once for each object in the array until either no objects remain or the
- *		applier returns false. Note that if the array is empty, then the applier will not be invoked.
- *
- *	@result
- *		True if the applier never returned false during enumeration. Otherwise, false.
- *
- *	@discussion
- *		This function should only be used on a CFArray that can only contain mrcs_objects. The mrcs_objects can
- *		be of any derived kind.
- */
-bool
-mrcs_cfarray_enumerate(CFArrayRef array, mrcs_any_applier_t applier);
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#endif	// MDNS_CF_SUPPORT_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.c b/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.c
deleted file mode 100644
index 18c22a7..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "mrcs_dns_proxy.h"
-
-#include "helpers.h"
-#include "mdns_memcpy_bits.h"
-#include "mrcs_cf_support.h"
-#include "mrcs_objects.h"
-
-#include <arpa/inet.h>
-#include <CoreUtils/CoreUtils.h>
-#include <mdns/system.h>
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - DNS Proxy Kind Definition
-
-typedef struct {
-	char *		name;	// Network interface's name.
-	uint32_t	index;	// Network interface's index.
-} mrcs_interface_t;
-
-struct mrcs_dns_proxy_s {
-	struct mdns_obj_s	base;					// Object base.
-	nw_nat64_prefix_t	nat64_prefix;			// NAT64 prefix.
-	mrcs_interface_t *	input_interfaces;		// Array of input interfaces.
-	size_t				input_interface_count;	// Current number of input interface indexes.
-	mrcs_interface_t	output_interface;		// Output interface.
-	bool				nat64_prefix_valid;		// True if the NAT64 prefix is currently valid.
-	bool				force_aaaa_synthesis;	// True if the DNS proxy policy is to force AAAA synthesis.
-};
-
-MRCS_OBJECT_SUBKIND_DEFINE(dns_proxy);
-
-//======================================================================================================================
-// MARK: - DNS Proxy Kind Definition
-
-struct mrcs_dns_proxy_manager_s {
-	struct mdns_obj_s	base;		// Object base.
-	CFMutableArrayRef	proxies;	// DNS proxy collection.
-};
-
-MRCS_OBJECT_SUBKIND_DEFINE(dns_proxy_manager);
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static bool
-_mrcs_dns_proxy_manager_conflicts_with_proxy(mrcs_dns_proxy_manager_t me, mrcs_dns_proxy_t proxy);
-
-static bool
-_mrcs_nat64_prefix_equal_null_safe(const nw_nat64_prefix_t *p1, const nw_nat64_prefix_t *p2);
-
-static int
-_mrcs_nat64_prefix_to_byte_length(const nw_nat64_prefix_t *prefix);
-
-static const char *
-_mrcs_string_or_empty(const char *string);
-
-//======================================================================================================================
-// MARK: - DNS Proxy Public Methods
-
-mrcs_dns_proxy_t
-mrcs_dns_proxy_create(OSStatus * const out_error)
-{
-	OSStatus err;
-	mrcs_dns_proxy_t proxy = NULL;
-	mrcs_dns_proxy_t obj = _mrcs_dns_proxy_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	proxy = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrcs_forget(&obj);
-	return proxy;
-}
-
-//======================================================================================================================
-
-OSStatus
-mrcs_dns_proxy_add_input_interface(const mrcs_dns_proxy_t me, const uint32_t ifindex)
-{
-	OSStatus err;
-	if (!mrcs_dns_proxy_contains_input_interface(me, ifindex)) {
-		require_action_quiet(me->input_interface_count <= (SIZE_MAX - 1), exit, err = kCountErr);
-		const size_t new_count = me->input_interface_count + 1;
-		mrcs_interface_t *new_interfaces = (mrcs_interface_t *)mdns_calloc(new_count, sizeof(*new_interfaces));
-		require_action_quiet(new_interfaces, exit, err = kNoMemoryErr);
-
-		// Shallow copy the new interface array, but remember to NULL out the old allocated interface name pointer.
-		for (size_t i = 0; i < me->input_interface_count; ++i) {
-			new_interfaces[i] = me->input_interfaces[i];
-			me->input_interfaces[i].name = NULL;
-		}
-		// Set the newest input interface.
-		mrcs_interface_t * const interface = &new_interfaces[me->input_interface_count];
-		interface->index = ifindex;
-		interface->name = mdns_system_interface_index_to_name(interface->index, NULL);
-
-		// Free the old input interface array and take ownership of the new one.
-		ForgetMem(&me->input_interfaces);
-		me->input_interfaces = new_interfaces;
-		new_interfaces = NULL;
-		me->input_interface_count = new_count;
-	}
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-void
-mrcs_dns_proxy_set_output_interface(const mrcs_dns_proxy_t me, const uint32_t ifindex)
-{
-	mrcs_interface_t * const interface = &me->output_interface;
-	interface->index = ifindex;
-	ForgetMem(&interface->name);
-	interface->name = mdns_system_interface_index_to_name(interface->index, NULL);
-}
-
-//======================================================================================================================
-
-OSStatus
-mrcs_dns_proxy_set_nat64_prefix(const mrcs_dns_proxy_t me, const uint8_t * const prefix, const size_t prefix_bitlen)
-{
-	OSStatus err;
-	nw_nat64_prefix_length_t length;
-	switch (prefix_bitlen) {
-#define _nat64_prefix_bitlen_case(BITLEN)				\
-		case BITLEN:									\
-			length = nw_nat64_prefix_length_ ## BITLEN;	\
-			break;
-		_nat64_prefix_bitlen_case(32)
-		_nat64_prefix_bitlen_case(40)
-		_nat64_prefix_bitlen_case(48)
-		_nat64_prefix_bitlen_case(56)
-		_nat64_prefix_bitlen_case(64)
-		_nat64_prefix_bitlen_case(96)
-#undef _nat64_prefix_bitlen_case
-		default:
-			err = kSizeErr;
-			goto exit;
-	}
-	memset(me->nat64_prefix.data, 0, sizeof(me->nat64_prefix.data));
-	mdns_memcpy_bits(me->nat64_prefix.data, prefix, prefix_bitlen);
-	me->nat64_prefix.length = length;
-	me->nat64_prefix_valid = true;
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-void
-mrcs_dns_proxy_enable_force_aaaa_synthesis(const mrcs_dns_proxy_t me, const bool enable)
-{
-	me->force_aaaa_synthesis = enable;
-}
-
-//======================================================================================================================
-
-bool
-mrcs_dns_proxy_contains_input_interface(const mrcs_dns_proxy_t me, const uint32_t ifindex)
-{
-	for (size_t i = 0; i < me->input_interface_count; ++i) {
-		if (me->input_interfaces[i].index == ifindex) {
-			return true;
-		}
-	}
-	return false;
-}
-
-//======================================================================================================================
-
-uint32_t
-mrcs_dns_proxy_get_output_interface(const mrcs_dns_proxy_t me)
-{
-	return me->output_interface.index;
-}
-
-//======================================================================================================================
-
-const nw_nat64_prefix_t *
-mrcs_dns_proxy_get_nat64_prefix(const mrcs_dns_proxy_t me)
-{
-	return (me->nat64_prefix_valid ? &me->nat64_prefix : NULL);
-}
-
-//======================================================================================================================
-
-bool
-mrcs_dns_proxy_forces_aaaa_synthesis(const mrcs_dns_proxy_t me)
-{
-	return me->force_aaaa_synthesis;
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Private Methods
-
-static OSStatus
-_mrcs_dns_proxy_print_description(const mrcs_dns_proxy_t me, const bool debug, __unused const bool privacy,
-	char * const buf, const size_t buf_len, size_t * const out_len, size_t * const out_full_len)
-{
-	OSStatus err;
-	char *dst = buf;
-	const char * const lim = &buf[buf_len];
-	size_t full_len = 0;
-
-#define _do_appendf(...)											\
-	do {															\
-		const int _n = mdns_snprintf_add(&dst, lim, __VA_ARGS__);	\
-		require_action_quiet(_n >= 0, exit, err = kUnknownErr);		\
-		full_len += (size_t)_n;										\
-	} while(0)
-
-	if (debug) {
-		_do_appendf("<%s: %p>: ", me->base.kind->name, me);
-	}
-	_do_appendf("input interfaces: {");
-	const mrcs_interface_t *interface;
-	const char *separator = "";
-	for (size_t i = 0; i < me->input_interface_count; ++i) {
-		interface = &me->input_interfaces[i];
-		_do_appendf("%s%s/%u", separator, _mrcs_string_or_empty(interface->name), interface->index);
-		separator = ", ";
-	}
-	interface = &me->output_interface;
-	_do_appendf("}, output interface: %s/%u", _mrcs_string_or_empty(interface->name), interface->index);
-
-	const nw_nat64_prefix_t * const prefix = mrcs_dns_proxy_get_nat64_prefix(me);
-	if (prefix) {
-		uint8_t ipv6_addr[16] = {0};
-		check_compile_time_code(sizeof(prefix->data) <= sizeof(ipv6_addr));
-		memcpy(ipv6_addr, prefix->data, sizeof(prefix->data));
-
-		char addr_buf[INET6_ADDRSTRLEN];
-		const char * const addr_str = inet_ntop(AF_INET6, ipv6_addr, addr_buf, (socklen_t)sizeof(addr_buf));
-		err = map_global_value_errno(addr_str, addr_str);
-		require_noerr_quiet(err, exit);
-
-		const int byte_len = _mrcs_nat64_prefix_to_byte_length(prefix);
-		const int bitlen = (byte_len >= 0) ? (byte_len * 8) : -1;
-		_do_appendf(", nat64 prefix: %s/%d", addr_str, bitlen);
-	}
-	_do_appendf(", forces AAAA synthesis: %s", mrcs_dns_proxy_forces_aaaa_synthesis(me) ? "yes" : "no");
-#undef _do_appendf
-	if (out_len) {
-		*out_len = (size_t)(dst - buf);
-	}
-	if (out_full_len) {
-		*out_full_len = full_len;
-	}
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static char *
-_mrcs_dns_proxy_copy_description(const mrcs_dns_proxy_t me, const bool debug, const bool privacy)
-{
-	char *description = NULL;
-	char buf[128];
-	size_t full_len;
-	OSStatus err = _mrcs_dns_proxy_print_description(me, debug, privacy, buf, sizeof(buf), NULL, &full_len);
-	require_noerr_quiet(err, exit);
-
-	if (full_len < sizeof(buf)) {
-		description = mdns_strdup(buf);
-	} else {
-		const size_t buf_len = full_len + 1;
-		char *buf_ptr = (char *)mdns_malloc(buf_len);
-		require_quiet(buf_ptr, exit);
-
-		err = _mrcs_dns_proxy_print_description(me, debug, privacy, buf_ptr, buf_len, NULL, NULL);
-		require_noerr_action_quiet(err, exit, ForgetMem(&buf_ptr));
-
-		description = buf_ptr;
-	}
-
-exit:
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_dns_proxy_finalize(const mrcs_dns_proxy_t me)
-{
-	for (size_t i = 0; i < me->input_interface_count; ++i) {
-		ForgetMem(&me->input_interfaces[i].name);
-	}
-	ForgetMem(&me->input_interfaces);
-	ForgetMem(&me->output_interface.name);
-}
-
-//======================================================================================================================
-
-static bool
-_mrcs_dns_proxy_has_common_input_interface(const mrcs_dns_proxy_t me, const mrcs_dns_proxy_t other)
-{
-	for (size_t i = 0; i < me->input_interface_count; ++i) {
-		if (mrcs_dns_proxy_contains_input_interface(other, me->input_interfaces[i].index)) {
-			return true;
-		}
-	}
-	return false;
-}
-
-//======================================================================================================================
-
-static bool
-_mrcs_dns_proxy_conflicts_with_other_proxy(const mrcs_dns_proxy_t me, const mrcs_dns_proxy_t other)
-{
-	if (_mrcs_dns_proxy_has_common_input_interface(me, other)) {
-		if (me->output_interface.index != other->output_interface.index) {
-			return true;
-		}
-		const nw_nat64_prefix_t * const prefix = mrcs_dns_proxy_get_nat64_prefix(me);
-		const nw_nat64_prefix_t * const other_prefix = mrcs_dns_proxy_get_nat64_prefix(other);
-		if (!_mrcs_nat64_prefix_equal_null_safe(prefix, other_prefix)) {
-			return true;
-		}
-		if (prefix && other_prefix) {
-			if (!!me->force_aaaa_synthesis != !!other->force_aaaa_synthesis) {
-				return true;
-			}
-		}
-	}
-	return false;
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Manager Public Methods
-
-mrcs_dns_proxy_manager_t
-mrcs_dns_proxy_manager_create(OSStatus * const out_error)
-{
-	OSStatus err;
-	mrcs_dns_proxy_manager_t manager = NULL;
-	mrcs_dns_proxy_manager_t obj = _mrcs_dns_proxy_manager_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->proxies = CFArrayCreateMutable(kCFAllocatorDefault, 0, &mrcs_cfarray_callbacks);
-	require_action_quiet(obj->proxies, exit, err = kNoResourcesErr);
-
-	manager = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrcs_forget(&obj);
-	return manager;
-}
-
-//======================================================================================================================
-
-OSStatus
-mrcs_dns_proxy_manager_add_proxy(const mrcs_dns_proxy_manager_t me, const mrcs_dns_proxy_t proxy)
-{
-	OSStatus err;
-	const bool conflicts = _mrcs_dns_proxy_manager_conflicts_with_proxy(me, proxy);
-	require_action_quiet(!conflicts, exit, err = kCollisionErr);
-
-	CFArrayAppendValue(me->proxies, proxy);
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-OSStatus
-mrcs_dns_proxy_manager_remove_proxy(const mrcs_dns_proxy_manager_t me, const mrcs_dns_proxy_t proxy)
-{
-	CFIndex i;
-	const CFIndex n = CFArrayGetCount(me->proxies);
-	for (i = 0; i < n; ++i) {
-		if (CFArrayGetValueAtIndex(me->proxies, i) == proxy) {
-			break;
-		}
-	}
-	OSStatus err;
-	require_action_quiet(i < n, exit, err = kNotFoundErr);
-
-	CFArrayRemoveValueAtIndex(me->proxies, i);
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-size_t
-mrcs_dns_proxy_manager_get_count(const mrcs_dns_proxy_manager_t me)
-{
-	return (size_t)CFArrayGetCount(me->proxies);
-}
-
-//======================================================================================================================
-
-mrcs_dns_proxy_t
-mrcs_dns_proxy_manager_get_proxy_by_input_interface(const mrcs_dns_proxy_manager_t me, const uint32_t ifindex)
-{
-	__block mrcs_dns_proxy_t result = NULL;
-	mrcs_cfarray_enumerate(me->proxies,
-	^ bool (const mrcs_dns_proxy_t proxy)
-	{
-		if (mrcs_dns_proxy_contains_input_interface(proxy, ifindex)) {
-			result = proxy;
-		}
-		const bool proceed = (result == NULL);
-		return proceed;
-	});
-	return result;
-}
-
-//======================================================================================================================
-// MARK: - DNS Proxy Manager Private Methods
-
-static OSStatus
-_mrcs_dns_proxy_manager_print_description(const mrcs_dns_proxy_manager_t me, const bool debug, const bool privacy,
-	char * const buf, const size_t buf_len, size_t * const out_len, size_t * const out_full_len)
-{
-	OSStatus err;
-	char *dst = buf;
-	const char * const lim = &buf[buf_len];
-	size_t full_len = 0;
-
-#define _do_appendf(...)											\
-	do {															\
-		const int _n = mdns_snprintf_add(&dst, lim, __VA_ARGS__);	\
-		require_action_quiet(_n >= 0, exit, err = kUnknownErr);		\
-		full_len += (size_t)_n;										\
-	} while(0)
-
-	if (debug) {
-		_do_appendf("<%s: %p>: ", me->base.kind->name, me);
-	}
-	_do_appendf("{");
-	const CFIndex n = CFArrayGetCount(me->proxies);
-	for (CFIndex i = 0; i < n; ++i) {
-		_do_appendf("%s\n\t", (i == 0) ? "" : ",");
-		size_t wrote_len, desc_len;
-		const mrcs_dns_proxy_t proxy = (mrcs_dns_proxy_t)CFArrayGetValueAtIndex(me->proxies, i);
-		err = _mrcs_dns_proxy_print_description(proxy, false, privacy, dst, (size_t)(lim - dst), &wrote_len, &desc_len);
-		require_noerr_quiet(err, exit);
-
-		dst += wrote_len;
-		full_len += desc_len;
-	}
-	_do_appendf("\n}");
-#undef _do_appendf
-	if (out_len) {
-		*out_len = (size_t)(dst - buf);
-	}
-	if (out_full_len) {
-		*out_full_len = full_len;
-	}
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static char *
-_mrcs_dns_proxy_manager_copy_description(const mrcs_dns_proxy_manager_t me, const bool debug, const bool privacy)
-{
-	char *description = NULL;
-	char buf[512];
-	size_t full_len;
-	OSStatus err = _mrcs_dns_proxy_manager_print_description(me, debug, privacy, buf, sizeof(buf), NULL, &full_len);
-	require_noerr_quiet(err, exit);
-
-	if (full_len < sizeof(buf)) {
-		description = mdns_strdup(buf);
-	} else {
-		const size_t buf_len = full_len + 1;
-		char *buf_ptr = (char *)mdns_malloc(buf_len);
-		require_quiet(buf_ptr, exit);
-
-		err = _mrcs_dns_proxy_manager_print_description(me, debug, privacy, buf_ptr, buf_len, NULL, NULL);
-		require_noerr_action_quiet(err, exit, ForgetMem(&buf_ptr));
-
-		description = buf_ptr;
-	}
-
-exit:
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_dns_proxy_manager_finalize(const mrcs_dns_proxy_manager_t me)
-{
-	CFForget(&me->proxies);
-}
-
-//======================================================================================================================
-
-static bool
-_mrcs_dns_proxy_manager_conflicts_with_proxy(const mrcs_dns_proxy_manager_t me, const mrcs_dns_proxy_t other)
-{
-	const bool conflict_free = mrcs_cfarray_enumerate(me->proxies,
-	^ bool (const mrcs_dns_proxy_t proxy)
-	{
-		const bool proceed = !_mrcs_dns_proxy_conflicts_with_other_proxy(proxy, other);
-		return proceed;
-	});
-	return !conflict_free;
-}
-
-//======================================================================================================================
-// MARK: - Helpers
-
-static bool
-_mrcs_nat64_prefix_equal_null_safe(const nw_nat64_prefix_t * const p1, const nw_nat64_prefix_t * const p2)
-{
-	if (p1 == p2) {
-		return true;
-	}
-	if (!p1 || !p2) {
-		return false;
-	}
-	if (p1->length != p2->length) {
-		return false;
-	}
-	const int byte_len = _mrcs_nat64_prefix_to_byte_length(p1);
-	if (byte_len < 0) {
-		return false;
-	}
-	return (memcmp(p1->data, p2->data, (size_t)byte_len) == 0);
-}
-
-//======================================================================================================================
-
-static int
-_mrcs_nat64_prefix_to_byte_length(const nw_nat64_prefix_t * const prefix)
-{
-	int len;
-	switch (prefix->length) {
-#define _nat64_prefix_length_case(BITLEN)					\
-		case nw_nat64_prefix_length_ ## BITLEN: {			\
-			check_compile_time_code(((BITLEN) % 8) == 0);	\
-			len = (BITLEN) / 8;								\
-			break;											\
-		}
-		_nat64_prefix_length_case(32)
-		_nat64_prefix_length_case(40)
-		_nat64_prefix_length_case(48)
-		_nat64_prefix_length_case(56)
-		_nat64_prefix_length_case(64)
-		_nat64_prefix_length_case(96)
-#undef _nat64_prefix_length_case
-		CUClangWarningIgnoreBegin(-Wcovered-switch-default);
-		default:
-		CUClangWarningIgnoreEnd();
-			len = -1;
-			break;
-	}
-	return len;
-}
-
-//======================================================================================================================
-
-static const char *
-_mrcs_string_or_empty(const char * const string)
-{
-	return (string ? string : "");
-}
diff --git a/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.h b/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.h
deleted file mode 100644
index 451ca39..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_dns_proxy.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_DNS_PROXY_H
-#define MRCS_DNS_PROXY_H
-
-#include "mrcs_object.h"
-
-#include <MacTypes.h>
-#include <mdns/base.h>
-#include <nw/private.h>
-
-MRCS_DECL(dns_proxy);
-MRCS_DECL(dns_proxy_manager);
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Creates a DNS proxy object to represent an instance of a DNS proxy.
- *
- *	@param out_error
- *		A variable to set to either kNoErr if creation succeeds, or a non-zero error code if creation fails.
- *
- *	@result
- *		A reference to the new DNS proxy object, or NULL if creation failed.
- *
- *	@discussion
- *		If not using Objective-C ARC, use mrcs_retain() and mrcs_release() to retain and release references to
- *		the object.
- */
-MDNS_RETURNS_RETAINED MDNS_WARN_RESULT
-mrcs_dns_proxy_t _Nullable
-mrcs_dns_proxy_create(OSStatus * _Nullable out_error);
-
-/*!
- *	@brief
- *		Adds an input interface to a DNS proxy.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param ifindex
- *		The input interface's index.
- *
- *	@discussion
- *		This function can be called more than once to specify a set of multiple input interfaces.
- */
-OSStatus
-mrcs_dns_proxy_add_input_interface(mrcs_dns_proxy_t proxy, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Sets a DNS proxy's output interface.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param ifindex
- *		The output interface's index.
- *
- *	@discussion
- *		By default, the output interface index is 0, which means that the remote DNS proxy instance will use the
- *		most suitable interface for its DNS network traffic.
- */
-void
-mrcs_dns_proxy_set_output_interface(mrcs_dns_proxy_t proxy, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Sets a DNS proxy's NAT64 IPv6 prefix.
- *
- *	@param proxy
- *		The parameters.
- *
- *	@param prefix
- *		A pointer to the prefix.
- *
- *	@param prefix_bit_length
- *		The bit length of the prefix.
- *
- *	@result
- *		kNoErr if the NAT64 prefix was successfully set. Otherwise, a non-zero error code indicating why it
- *		wasn't set.
- *
- *	@discussion
- *		If a NAT64 prefix is set, then the DNS proxy instance will carry out DNS64 functionality using the
- *		specified NAT64 prefix. If not set, then no DNS64 functionality will be performed.
- */
-OSStatus
-mrcs_dns_proxy_set_nat64_prefix(mrcs_dns_proxy_t proxy, const uint8_t *prefix, size_t prefix_bit_length);
-
-/*!
- *	@brief
- *		Enables a DNS proxy's option to force AAAA synthesis when performing DNS64 functionality.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param enable
- *		Pass true to enable the option. Pass false to disable the option.
- *
- *	@discussion
- *		This option is disabled by default and only applies when the DNS proxy's DNS64 functionality is enabled
- *		by specifying a NAT64 prefix.
- */
-void
-mrcs_dns_proxy_enable_force_aaaa_synthesis(mrcs_dns_proxy_t proxy, bool enable);
-
-/*!
- *	@brief
- *		Determines whether a DNS proxy contains an input interface.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@param ifindex
- *		The intput interface's index.
- *
- *	@result
- *		The truth value.
- */
-bool
-mrcs_dns_proxy_contains_input_interface(mrcs_dns_proxy_t proxy, uint32_t ifindex);
-
-/*!
- *	@brief
- *		Gets a DNS proxy's output interface index.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@result
- *		The output interface index.
- *
- *	@discussion
- *		By default, the output interface index is 0, which means that the DNS proxy instance will use the most
- *		suitable interface for its DNS network traffic.
- */
-uint32_t
-mrcs_dns_proxy_get_output_interface(mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Gets a DNS proxy's NAT64 prefix.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@result
- *		The NAT64 prefix if the DNS proxy has one. Otherwise, NULL.
- *
- *	@discussion
- *		The NAT64 prefix returned by this function is valid for the lifetime of the DNS proxy object and is
- *		guaranteed to not change until the next successful call to mrcs_dns_proxy_set_nat64_prefix().
- */
-const nw_nat64_prefix_t * _Nullable
-mrcs_dns_proxy_get_nat64_prefix(mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Determines whether a DNS proxy forces AAAA synthesis when performing DNS64 functionality.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@result
- *		The truth value.
- */
-bool
-mrcs_dns_proxy_forces_aaaa_synthesis(mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Creates a DNS proxy manager which can be uses to contain DNS proxy objects.
- *
- *	@param out_error
- *		A variable to set to either kNoErr if creation succeeds, or a non-zero error code if creation fails.
- *
- *	@result
- *		A reference to the new DNS proxy manager, or NULL if creation failed.
- *
- *	@discussion
- *		If not using Objective-C ARC, use mrcs_retain() and mrcs_release() to retain and release references to
- *		the object.
- */
-MDNS_RETURNS_RETAINED MDNS_WARN_RESULT
-mrcs_dns_proxy_manager_t _Nullable
-mrcs_dns_proxy_manager_create(OSStatus * _Nullable out_error);
-
-/*!
- *	@brief
- *		Adds a DNS proxy to a DNS proxy manager if it doesn't conflict with its current set of DNS proxies.
- *
- *	@param manager
- *		The DNS proxy manager.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@result
- *		kNoErr if the DNS proxy was added. Otherwise, a non-zero error code if there was a conflict.
- *
- *	@discussion
- *		The DNS proxy manager will retain a reference to each DNS proxy that it successfully adds.
- *
- *		A DNS proxy is considered to conflict with another DNS proxy if they have at least one input interface
- *		in common and either their output interfaces don't match or their output interfaces do match, but their
- *		DNS64 settings do not.
- */
-OSStatus
-mrcs_dns_proxy_manager_add_proxy(mrcs_dns_proxy_manager_t manager, mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Removes a DNS proxy from a DNS proxy manager.
- *
- *	@param manager
- *		The DNS proxy manager.
- *
- *	@param proxy
- *		The DNS proxy.
- *
- *	@result
- *		kNoErr if the DNS proxy was successfully removed. Otherwise, a non-zero error code if the DNS proxy was
- *		not contained by the DNS proxy manager.
- *
- *	@discussion
- *		The DNS proxy manager will release its reference to each DNS proxy that gets removed.
- */
-OSStatus
-mrcs_dns_proxy_manager_remove_proxy(mrcs_dns_proxy_manager_t manager, mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		Gets the number of DNS proxies contained by a DNS proxy manager.
- *
- *	@param manager
- *		The DNS proxy manager.
- *
- *	@result
- *		The number or DNS proxies.
- */
-size_t
-mrcs_dns_proxy_manager_get_count(mrcs_dns_proxy_manager_t manager);
-
-/*!
- *	@brief
- *		Gets a DNS proxy that contains the specified input interface from a DNS proxy manager if such a DNS
- *		proxy exists.
- *
- *	@param manager
- *		The DNS proxy manager.
- *
- *	@param ifindex
- *		The input interface's index.
- *
- *	@result
- *		The DNS proxy if such a DNS proxy exists. Otherwise, NULL.
- */
-mrcs_dns_proxy_t _Nullable
-mrcs_dns_proxy_manager_get_proxy_by_input_interface(mrcs_dns_proxy_manager_t manager, uint32_t ifindex);
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#endif	// MRCS_DNS_PROXY_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_object.c b/mDNSMacOSX/libmrc/src/mrcs_object.c
deleted file mode 100644
index 120887a..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_object.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "mrcs_object.h"
-
-#include "mdns_obj.h"
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Object Public Methods
-
-void
-mrcs_retain(const mrcs_object_t me)
-{
-	mdns_obj_retain(me);
-}
-
-//======================================================================================================================
-
-void
-mrcs_release(const mrcs_object_t me)
-{
-	mdns_obj_release(me);
-}
-
-//======================================================================================================================
-
-char *
-mrcs_copy_description(const mrcs_object_t me)
-{
-	return mdns_obj_copy_description(me, false, false);
-}
diff --git a/mDNSMacOSX/libmrc/src/mrcs_object.h b/mDNSMacOSX/libmrc/src/mrcs_object.h
deleted file mode 100644
index 9828c73..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_object.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_OBJECT_H
-#define MRCS_OBJECT_H
-
-#include "mrcs_object_members.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <mdns/base.h>
-
-#define MRCS_BASE_DECL(NAME)			MDNS_COMMON_BASE_DECL(mrcs_ ## NAME)
-#define MRCS_DECL_SUBKIND(NAME, SUPER)	MDNS_COMMON_DECL_SUBKIND(mrcs_ ## NAME, mrcs_ ## SUPER)
-#define MRCS_DECL(NAME)					MRCS_DECL_SUBKIND(NAME, object)
-
-MRCS_BASE_DECL(object);
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-/*!
- *	@typedef mrcs_any_t
- *	@brief
- *		A pointer to an mrcs object.
- */
-#if OS_OBJECT_USE_OBJC
-	typedef mrcs_object_t	mrcs_any_t;
-#else
-	#if defined(__cplusplus)
-		typedef void *	mrcs_any_t;
-	#else
-		typedef union {
-			MRCS_OBJECT_MEMBERS
-		} mrcs_any_t __attribute__((__transparent_union__));
-	#endif
-#endif
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		Increments the reference count of an mrcs object.
- *
- *	@param object
- *		The mrcs object.
- */
-void
-mrcs_retain(mrcs_any_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-	#undef mrcs_retain
-	#define mrcs_retain(object)	(void)[(object) retain]
-#endif
-
-/*!
- *	@brief
- *		Decrements the reference count of an mrcs object.
- *
- *	@param object
- *		The mrcs object.
- */
-void
-mrcs_release(mrcs_any_t object);
-#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
-	#undef mrcs_release
-	#define mrcs_release(object)	[(object) release]
-#endif
-
-/*!
- *	@brief
- *		Creates a human-readable description of an mrcs object as a C string encoded in UTF-8.
- *
- *	@param object
- *		The mrcs object.
- *
- *	@result
- *		A C string that must be freed with free(3), or NULL if memory allocation failed.
- */
-MDNS_WARN_RESULT
-char * _Nullable
-mrcs_copy_description(mrcs_any_t object);
-
-/*!
- *	@brief
- *		Explicitly retains an mrcs object if ARC is disabled. Does nothing if ARC is enabled.
- *
- *	@param object
- *		The mrcs object.
- *
- *	@discussion
- *		This is a convenience function that allows writing portable Objective-C code regardless of whether ARC
- *		is enabled or disabled.
- */
-static inline void
-mrcs_retain_arc_safe(const mrcs_any_t object)
-{
-#if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
-	(void)object;
-#else
-	mrcs_retain(object);
-#endif
-}
-
-/*!
- *	@brief
- *		Explicitly releases an mrcs object if ARC is disabled. Does nothing if ARC is enabled.
- *
- *	@param object
- *		The mrcs object.
- *
- *	@discussion
- *		This is a convenience function that allows writing portable Objective-C code regardless of whether ARC
- *		is enabled or disabled.
- */
-static inline void
-mrcs_release_arc_safe(const mrcs_any_t object)
-{
-#if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
-	(void)object;
-#else
-	mrcs_release(object);
-#endif
-}
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#define mrcs_forget(PTR)					\
-	do {									\
-		if (*(PTR)) {						\
-			mrcs_release_arc_safe(*(PTR));	\
-			*(PTR) = NULL;					\
-		}									\
-	} while(0)
-
-#endif	// MRCS_OBJECT_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_object_members.h b/mDNSMacOSX/libmrc/src/mrcs_object_members.h
deleted file mode 100644
index 5790703..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_object_members.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_OBJECT_MEMBERS_H
-#define MRCS_OBJECT_MEMBERS_H
-
-#include <mdns/base.h>
-
-#define MRCS_UNION_MEMBER(NAME)	struct mrcs_ ## NAME ## _s *	_mrcs_ ## NAME
-
-#define MRCS_OBJECT_MEMBERS					\
-	MRCS_UNION_MEMBER(object);				\
-	MRCS_UNION_MEMBER(dns_proxy);			\
-	MRCS_UNION_MEMBER(dns_proxy_manager);	\
-	MRCS_UNION_MEMBER(dns_proxy_request);	\
-	MRCS_UNION_MEMBER(session);
-
-#endif	// MRCS_OBJECT_MEMBERS_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_objects.h b/mDNSMacOSX/libmrc/src/mrcs_objects.h
deleted file mode 100644
index 47755dc..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_objects.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_OBJECTS_H
-#define MRCS_OBJECTS_H
-
-#include "mdns_objects.h"
-
-#define MRCS_OBJECT_SUBKIND_DEFINE_ABSTRACT(NAME)	MDNS_OBJ_SUBKIND_DEFINE_ABSTRACT(mrcs_ ## NAME)
-#define MRCS_OBJECT_SUBKIND_DEFINE(NAME)			MDNS_OBJ_SUBKIND_DEFINE(mrcs_ ## NAME)
-#define MRCS_OBJECT_SUBKIND_DEFINE_FULL(NAME)		MDNS_OBJ_SUBKIND_DEFINE_FULL(mrcs_ ## NAME)
-
-#define MRCS_BASE_CHECK(NAME, SUPER)	MDNS_OBJ_BASE_CHECK(mrcs_ ## NAME, mrcs_ ## SUPER)
-
-#define MRCS_CLASS(NAME)		MDNS_OBJ_CLASS(mrcs_ ## NAME)
-#define MRCS_CLASS_DECL(NAME)	MDNS_OBJ_CLASS_DECL(mrcs_ ## NAME)
-
-#endif	// MRCS_OBJECTS_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_server.c b/mDNSMacOSX/libmrc/src/mrcs_server.c
deleted file mode 100644
index 59ecffc..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_server.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "mrcs_server_internal.h"
-
-#include "mrc_xpc.h"
-#include "mrcs_objects.h"
-
-#include <CoreUtils/CoreUtils.h>
-#include <mdns/xpc.h>
-#include <xpc/xpc.h>
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Session Kind
-
-struct mrcs_session_s {
-	struct mdns_obj_s			base;			// Object base.
-	mrcs_session_t				next;			// Next session in list.
-	xpc_connection_t			connection;		// Underlying XPC connection.
-	mrcs_dns_proxy_request_t	request_list;	// List of client requests.
-};
-
-MRCS_OBJECT_SUBKIND_DEFINE(session);
-
-//======================================================================================================================
-// MARK: - Session Kind
-
-struct mrcs_dns_proxy_request_s {
-	struct mdns_obj_s			base;		// Object base.
-	mrcs_dns_proxy_request_t	next;		// Next request in list.
-	mrcs_dns_proxy_t			proxy;		// DNS proxy.
-	uint64_t					command_id;	// Command ID.
-};
-
-MRCS_OBJECT_SUBKIND_DEFINE(dns_proxy_request);
-
-//======================================================================================================================
-// MARK: - Local Prototypes
-
-static dispatch_queue_t
-_mrcs_server_queue(void);
-
-static void
-_mrcs_server_handle_new_connection(xpc_connection_t connection);
-
-static mrcs_session_t
-_mrcs_session_create(xpc_connection_t connection, OSStatus *out_error);
-
-static void
-_mrcs_session_activate(mrcs_session_t session);
-
-static void
-_mrcs_session_invalidate(mrcs_session_t session);
-
-static void
-_mrcs_session_register(mrcs_session_t session);
-
-static void
-_mrcs_session_deregister(mrcs_session_t session);
-
-static void
-_mrcs_session_handle_message(mrcs_session_t session, xpc_object_t msg);
-
-static mrcs_dns_proxy_request_t
-_mrcs_dns_proxy_request_create(mrcs_dns_proxy_t proxy, uint64_t command_id, OSStatus *out_error);
-
-static mrcs_dns_proxy_t
-_mrcs_create_dns_proxy_from_params_dictionary(xpc_object_t params, OSStatus *out_error);
-
-//======================================================================================================================
-// MARK: - Globals
-
-static mrcs_server_handlers_t	g_handlers		= NULL;
-static mrcs_session_t			g_session_list	= NULL;
-
-//======================================================================================================================
-// MARK: - Public Server Functions
-
-OSStatus
-mrcs_server_init(const mrcs_server_handlers_t handlers)
-{
-	OSStatus err;
-	static xpc_connection_t s_listener = NULL;
-	require_action_quiet(!s_listener, exit, err = kNoErr);
-
-	const uint64_t flags = XPC_CONNECTION_MACH_SERVICE_LISTENER;
-	s_listener = xpc_connection_create_mach_service(g_mrc_mach_service_name, _mrcs_server_queue(), flags);
-	require_action_quiet(s_listener, exit, err = kNoResourcesErr);
-
-	xpc_connection_set_event_handler(s_listener,
-	^(const xpc_object_t event)
-	{
-		if (xpc_get_type(event) == XPC_TYPE_CONNECTION) {
-			_mrcs_server_handle_new_connection((xpc_connection_t)event);
-		}
-	});
-	g_handlers = handlers;
-	xpc_connection_activate(s_listener);
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-// MARK: - Private Server Functions
-
-static dispatch_queue_t
-_mrcs_server_queue(void)
-{
-	static dispatch_once_t s_once = 0;
-	static dispatch_queue_t s_queue = NULL;
-	dispatch_once(&s_once,
-	^{
-		s_queue = dispatch_queue_create("com.apple.mDNSResponder.control.server", DISPATCH_QUEUE_SERIAL);
-	});
-	return s_queue;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_server_handle_new_connection(const xpc_connection_t connection)
-{
-	mrcs_session_t session = _mrcs_session_create(connection, NULL);
-	if (session) {
-		_mrcs_session_register(session);
-		_mrcs_session_activate(session);
-		mrcs_forget(&session);
-	} else {
-		xpc_connection_cancel(connection);
-	}
-}
-
-//======================================================================================================================
-
-static OSStatus
-_mrcs_server_dns_proxy_start(const mrcs_dns_proxy_t proxy)
-{
-	OSStatus err;
-	if (g_handlers->dns_proxy_start) {
-		err = g_handlers->dns_proxy_start(proxy);
-	} else {
-		err = kNotHandledErr;
-	}
-	return err;
-}
-
-//======================================================================================================================
-
-static OSStatus
-_mrcs_server_dns_proxy_stop(const mrcs_dns_proxy_t proxy)
-{
-	OSStatus err;
-	if (g_handlers->dns_proxy_stop) {
-		err = g_handlers->dns_proxy_stop(proxy);
-	} else {
-		err = kNotHandledErr;
-	}
-	return err;
-}
-
-//======================================================================================================================
-
-static char *
-_mrcs_server_dns_proxy_state(OSStatus * const out_error)
-{
-	char *state;
-	OSStatus err;
-	const mrcs_server_dns_proxy_get_state_handler_f dns_proxy_get_state = g_handlers->dns_proxy_get_state;
-	if (dns_proxy_get_state) {
-		state = dns_proxy_get_state();
-		err = state ? kNoErr : kNoMemoryErr;
-	} else {
-		state = NULL;
-		err = kNotHandledErr;
-	}
-	if (out_error) {
-		*out_error = err;
-	}
-	return state;
-}
-
-//======================================================================================================================
-// MARK: - Session Methods
-
-static mrcs_session_t
-_mrcs_session_create(const xpc_connection_t connection, OSStatus * const out_error)
-{
-	OSStatus err;
-	mrcs_session_t session = NULL;
-	mrcs_session_t obj = _mrcs_session_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->connection = connection;
-	xpc_retain(obj->connection);
-	session = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrcs_forget(&obj);
-	return session;
-}
-
-//======================================================================================================================
-
-static char *
-_mrcs_session_copy_description(const mrcs_session_t me, __unused const bool debug, __unused const bool privacy)
-{
-	char *description = NULL;
-	asprintf(&description, "<%s: %p>", me->base.kind->name, (void *)me);
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_finalize(const mrcs_session_t me)
-{
-	xpc_forget(&me->connection);
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_activate(const mrcs_session_t me)
-{
-	mrcs_retain(me);
-	xpc_connection_set_target_queue(me->connection, _mrcs_server_queue());
-	xpc_connection_set_event_handler(me->connection,
-	^(const xpc_object_t event)
-	{
-		const xpc_type_t type = xpc_get_type(event);
-		if (type == XPC_TYPE_DICTIONARY) {
-			if (me->connection) {
-				_mrcs_session_handle_message(me, event);
-			}
-		} else if (event == XPC_ERROR_CONNECTION_INVALID) {
-			_mrcs_session_deregister(me);
-			_mrcs_session_invalidate(me);
-			mrcs_release(me);
-		} else {
-			xpc_connection_forget(&me->connection);
-		}
-	});
-	xpc_connection_activate(me->connection);
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_invalidate(const mrcs_session_t me)
-{
-	xpc_connection_forget(&me->connection);
-	mrcs_dns_proxy_request_t request;
-	while ((request = me->request_list) != NULL) {
-		me->request_list = request->next;
-		_mrcs_server_dns_proxy_stop(request->proxy);
-		mrcs_forget(&request);
-	}
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_register(const mrcs_session_t me)
-{
-	mrcs_session_t *ptr = &g_session_list;
-	while (*ptr) {
-		ptr = &(*ptr)->next;
-	}
-	me->next = NULL;
-	*ptr = me;
-	mrcs_retain(me);
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_deregister(const mrcs_session_t me)
-{
-	mrcs_session_t *ptr = &g_session_list;
-	while (*ptr && (*ptr != me)) {
-		ptr = &(*ptr)->next;
-	}
-	if (*ptr) {
-		*ptr = me->next;
-		me->next = NULL;
-		mrcs_release(me);
-	}
-}
-
-//======================================================================================================================
-
-static OSStatus
-_mrcs_session_handle_dns_proxy_start(const mrcs_session_t me, const xpc_object_t msg)
-{
-	OSStatus err;
-	mrcs_dns_proxy_t proxy = NULL;
-	const uint64_t command_id = mrc_xpc_message_get_id(msg);
-	mrcs_dns_proxy_request_t *ptr = &me->request_list;
-	while (*ptr && ((*ptr)->command_id != command_id)) {
-		ptr = &(*ptr)->next;
-	}
-	require_action_quiet(!*ptr, exit, err = kStateErr);
-
-	const xpc_object_t params = mrc_xpc_message_get_params(msg);
-	require_action_quiet(params, exit, err = kParamErr);
-
-	proxy = _mrcs_create_dns_proxy_from_params_dictionary(params, &err);
-	require_noerr_quiet(err, exit);
-
-	err = _mrcs_server_dns_proxy_start(proxy);
-	require_noerr_quiet(err, exit);
-
-	mrcs_dns_proxy_request_t request = _mrcs_dns_proxy_request_create(proxy, command_id, &err);
-	require_noerr_quiet(err, exit);
-
-	*ptr = request;
-	request = NULL;
-
-exit:
-	mrcs_forget(&proxy);
-	return err;
-}
-
-//======================================================================================================================
-
-static OSStatus
-_mrcs_session_handle_dns_proxy_stop(const mrcs_session_t me, const xpc_object_t msg)
-{
-	OSStatus err;
-	const uint64_t command_id = mrc_xpc_message_get_id(msg);
-	mrcs_dns_proxy_request_t *ptr = &me->request_list;
-	while (*ptr && ((*ptr)->command_id != command_id)) {
-		ptr = &(*ptr)->next;
-	}
-	mrcs_dns_proxy_request_t request = *ptr;
-	require_action_quiet(request, exit, err = kIDErr);
-
-	*ptr = request->next;
-	request->next = NULL;
-	_mrcs_server_dns_proxy_stop(request->proxy);
-	mrcs_forget(&request);
-	err = kNoErr;
-
-exit:
-	return err;
-}
-
-//======================================================================================================================
-
-static mdns_xpc_dictionary_t
-_mrcs_session_handle_dns_proxy_get_state(OSStatus * const out_error)
-{
-	OSStatus err;
-	mdns_xpc_dictionary_t result = mdns_xpc_dictionary_create_empty();
-	require_action_quiet(result, exit, err = kNoResourcesErr);
-
-	char *state = _mrcs_server_dns_proxy_state(&err);
-	if (state) {
-		mrc_xpc_dns_proxy_state_result_set_description(result, state);
-	}
-	ForgetMem(&state);
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	return result;
-}
-
-//======================================================================================================================
-
-static mdns_xpc_dictionary_t
-_mrcs_session_handle_command(const mrcs_session_t me, const char * const command, const xpc_object_t msg,
-	OSStatus * const out_error)
-{
-	OSStatus err;
-	mdns_xpc_dictionary_t result;
-	if (strcmp(command, g_mrc_command_dns_proxy_start) == 0) {
-		err = _mrcs_session_handle_dns_proxy_start(me, msg);
-		result = NULL;
-	} else if (strcmp(command, g_mrc_command_dns_proxy_stop) == 0) {
-		err = _mrcs_session_handle_dns_proxy_stop(me, msg);
-		result = NULL;
-	} else if (strcmp(command, g_mrc_command_dns_proxy_get_state) == 0) {
-		result = _mrcs_session_handle_dns_proxy_get_state(&err);
-	} else {
-		err = kCommandErr;
-		result = NULL;
-	}
-	if (out_error) {
-		*out_error = err;
-	}
-	return result;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_session_handle_message(const mrcs_session_t me, const xpc_object_t msg)
-{
-	OSStatus err;
-	mdns_xpc_dictionary_t result = NULL;
-	const bool entitled = mdns_xpc_connection_is_entitled(me->connection, "com.apple.mDNSResponder.dnsproxy");
-	require_action_quiet(entitled, exit, err = kMissingEntitlementErr);
-
-	const char * const command = mrc_xpc_message_get_command(msg);
-	require_action_quiet(command, exit, err = kCommandErr);
-
-	result = _mrcs_session_handle_command(me, command, msg, &err);
-	require_noerr_quiet(err, exit);
-
-exit:;
-	xpc_object_t reply = mrc_xpc_create_reply(msg, err, result);
-	xpc_forget(&result);
-	if (reply) {
-		xpc_connection_send_message(me->connection, reply);
-		xpc_forget(&reply);
-	}
-	if (!entitled) {
-		xpc_connection_cancel(me->connection);
-	}
-}
-
-//======================================================================================================================
-// MARK: - Session Methods
-
-static mrcs_dns_proxy_request_t
-_mrcs_dns_proxy_request_create(const mrcs_dns_proxy_t proxy, const uint64_t command_id, OSStatus * const out_error)
-{
-	OSStatus err;
-	mrcs_dns_proxy_request_t request = NULL;
-	mrcs_dns_proxy_request_t obj = _mrcs_dns_proxy_request_new();
-	require_action_quiet(obj, exit, err = kNoMemoryErr);
-
-	obj->proxy = proxy;
-	mrcs_retain(obj->proxy);
-	obj->command_id = command_id;
-	request = obj;
-	obj = NULL;
-	err = kNoErr;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrcs_forget(&obj);
-	return request;
-}
-
-//======================================================================================================================
-
-static char *
-_mrcs_dns_proxy_request_copy_description(const mrcs_dns_proxy_request_t me, __unused const bool debug,
-	__unused const bool privacy)
-{
-	char *description = NULL;
-	asprintf(&description, "<%s: %p>", me->base.kind->name, (void *)me);
-	return description;
-}
-
-//======================================================================================================================
-
-static void
-_mrcs_dns_proxy_request_finalize(const mrcs_dns_proxy_request_t me)
-{
-	mrcs_forget(&me->proxy);
-}
-
-//======================================================================================================================
-// MARK: - Helpers
-
-static mrcs_dns_proxy_t
-_mrcs_create_dns_proxy_from_params_dictionary(const xpc_object_t params, OSStatus * const out_error)
-{
-	OSStatus err;
-	mrcs_dns_proxy_t result = NULL;
-	mrcs_dns_proxy_t proxy = mrcs_dns_proxy_create(&err);
-	require_noerr_quiet(err, exit);
-
-	// Set input interfaces.
-	const xpc_object_t input_interfaces = mrc_xpc_dns_proxy_params_get_input_interfaces(params);
-	require_action_quiet(input_interfaces, exit, err = kParamErr);
-
-	const size_t input_interface_count = xpc_array_get_count(input_interfaces);
-	require_action_quiet(input_interface_count > 0, exit, err = kParamErr);
-
-	bool valid;
-	for (size_t i = 0; i < input_interface_count; ++i) {
-		const uint32_t ifindex = mdns_xpc_array_get_uint32(input_interfaces, i, &valid);
-		require_action_quiet(valid, exit, err = kParamErr);
-
-		mrcs_dns_proxy_add_input_interface(proxy, ifindex);
-	}
-	// Set output interface.
-	const uint32_t output_ifindex = mrc_xpc_dns_proxy_params_get_output_interface(params, &valid);
-	require_action_quiet(valid, exit, err = kParamErr);
-
-	mrcs_dns_proxy_set_output_interface(proxy, output_ifindex);
-
-	// Set optional NAT64 prefix.
-	size_t nat64_prefix_bitlen;
-	const uint8_t * const nat64_prefix = mrc_xpc_dns_proxy_params_get_nat64_prefix(params, &nat64_prefix_bitlen);
-	if (nat64_prefix) {
-		err = mrcs_dns_proxy_set_nat64_prefix(proxy, nat64_prefix, nat64_prefix_bitlen);
-		require_noerr_quiet(err, exit);
-	}
-	const bool force_aaaa_synthesis = mrc_xpc_dns_proxy_params_get_force_aaaa_synthesis(params, &valid);
-	require_action_quiet(valid, exit, err = kParamErr);
-
-	mrcs_dns_proxy_enable_force_aaaa_synthesis(proxy, force_aaaa_synthesis);
-	result = proxy;
-	proxy = NULL;
-
-exit:
-	if (out_error) {
-		*out_error = err;
-	}
-	mrcs_forget(&proxy);
-	return result;
-}
diff --git a/mDNSMacOSX/libmrc/src/mrcs_server.h b/mDNSMacOSX/libmrc/src/mrcs_server.h
deleted file mode 100644
index d02a93b..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_server.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_SERVER_H
-#define MRCS_SERVER_H
-
-#include "mrcs_dns_proxy.h"
-
-#include <MacTypes.h>
-#include <mdns/base.h>
-
-MDNS_ASSUME_NONNULL_BEGIN
-
-__BEGIN_DECLS
-
-/*!
- *	@brief
- *		A handler that starts a specified DNS proxy.
- *
- *	@param proxy
- *		An object that describes the DNS proxy to start.
- *
- *	@result
- *		kNoErr if the DNS proxy was successfully started. Otherwise, a non-zero error code to indicate why the
- *		DNS proxy was not started.
- */
-typedef OSStatus
-(*mrcs_server_dns_proxy_start_handler_f)(mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		A handler that stops a specified DNS proxy.
- *
- *	@param proxy
- *		A reference to the DNS proxy to stop.
- *
- *	@result
- *		kNoErr if the DNS proxy was successfully stopped. Otherwise, a non-zero error code to indicate why the
- *		DNS proxy was not stopped.
- */
-typedef OSStatus
-(*mrcs_server_dns_proxy_stop_handler_f)(mrcs_dns_proxy_t proxy);
-
-/*!
- *	@brief
- *		A handler that gets the state of all active DNS proxies in human-readable text.
- *
- *	@result
- *		The text as an allocated C string.
- */
-typedef char * _Nullable
-(*mrcs_server_dns_proxy_get_state_handler_f)(void);
-
-/*!
- *	@brief
- *		A structure containing handlers to be invoked an mDNSResponder control server.
- */
-struct mrcs_server_handlers_s {
-	mrcs_server_dns_proxy_start_handler_f		dns_proxy_start;
-	mrcs_server_dns_proxy_stop_handler_f		dns_proxy_stop;
-	mrcs_server_dns_proxy_get_state_handler_f	dns_proxy_get_state;
-};
-
-typedef const struct mrcs_server_handlers_s *mrcs_server_handlers_t;
-
-/*!
- *	@brief
- *		Initializes mDNSResponder's control server.
- *
- *	@param handlers
- *		The handlers to be used by the control server.
- *
- *	@result
- *		kNoErr if the control server was successfully initialized. Otherwise, a non-zero error code to indicate
- *		why initialization failed.
- */
-OSStatus
-mrcs_server_init(mrcs_server_handlers_t handlers);
-
-__END_DECLS
-
-MDNS_ASSUME_NONNULL_END
-
-#endif	// MRCS_SERVER_H
diff --git a/mDNSMacOSX/libmrc/src/mrcs_server_internal.h b/mDNSMacOSX/libmrc/src/mrcs_server_internal.h
deleted file mode 100644
index bc1b7ab..0000000
--- a/mDNSMacOSX/libmrc/src/mrcs_server_internal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MRCS_SERVER_INTERNAL_H
-#define MRCS_SERVER_INTERNAL_H
-
-#include "mrcs_server.h"
-
-#include "mrcs_object.h"
-
-MRCS_DECL(session);
-MRCS_DECL(dns_proxy_request);
-
-#endif	// MRCS_SERVER_INTERNAL_H
diff --git a/mDNSMacOSX/log/pseudo-OSLogCopyFormattedString.h b/mDNSMacOSX/log/pseudo-OSLogCopyFormattedString.h
deleted file mode 100644
index e6b8afd..0000000
--- a/mDNSMacOSX/log/pseudo-OSLogCopyFormattedString.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2020 Apple 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
- *
- *     https://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.
- *
- * This file is a pseudo header file for OSLogCopyFormattedString, which
- * is defined in <os/log_private.h>. this header is used for customized
- * log formatters to declare the symbol, so InstallAPI will not complain
- * about the missing header symbol when it finds the defined
- * OSLogCopyFormattedString in the source code.
- *
- * Set -extra-public-header $(SRCROOT)/pseudo_OSLogCopyFormattedString.h
- * in "Other Text-Based InstallAPI Flags" in Xcode Build Settings to use
- * this header file.
- */
-
-#ifndef __PSEUDO_OS_LOG_COPY_FORMATTED_STRING_H__
-#define __PSEUDO_OS_LOG_COPY_FORMATTED_STRING_H__
-
-#include <Foundation/Foundation.h>
-#include <os/log_private.h>
-
-NSAttributedString *
-OSLogCopyFormattedString(const char *type, id value, os_log_type_info_t info);
-
-#endif // __PSEUDO_OS_LOG_COPY_FORMATTED_STRING_H__
diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c
deleted file mode 100644
index 8d7dea6..0000000
--- a/mDNSMacOSX/mDNSMacOSX.c
+++ /dev/null
@@ -1,7091 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-// ***************************************************************************
-// mDNSMacOSX.c:
-// Supporting routines to run mDNS on a CFRunLoop platform
-// ***************************************************************************
-
-// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
-// including ones that mDNSResponder chooses not to use.
-#define LIST_ALL_INTERFACES 0
-
-#include "mDNSEmbeddedAPI.h"        // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "uDNS.h"
-#include "mDNSMacOSX.h"             // Defines the specific types needed to run mDNS on this platform
-#include "dns_sd.h"                 // For mDNSInterface_LocalOnly etc.
-#include "dns_sd_internal.h"
-#include "PlatformCommon.h"
-#include "uds_daemon.h"
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-#include "dnssd_analytics.h"
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-#include "mdns_trust.h"
-#include <os/feature_private.h>
-#endif
-
-#if defined(__x86_64__) && __x86_64__
-#include <smmintrin.h>
-#endif
-
-#include "mdns_strict.h"
-
-#include <mdns/power.h>
-#include <mdns/tcpinfo.h>
-#include <stdio.h>
-#include <stdarg.h>                 // For va_list support
-#include <stdlib.h>                 // For arc4random
-#include <net/if.h>
-#include <net/if_types.h>           // For IFT_ETHER
-#include <net/if_dl.h>
-#include <net/bpf.h>                // For BIOCSETIF etc.
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/event.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <time.h>                   // platform support for UTC time
-#include <arpa/inet.h>              // for inet_aton
-#include <pthread.h>
-#include <netdb.h>                  // for getaddrinfo
-#include <sys/sockio.h>             // for SIOCGIFEFLAGS
-#include <notify.h>
-#include <netinet/in.h>             // For IP_RECVTTL
-#ifndef IP_RECVTTL
-#define IP_RECVTTL 24               // bool; receive reception TTL w/dgram
-#endif
-
-#include <netinet/in_systm.h>       // For n_long, required by <netinet/ip.h> below
-#include <netinet/ip.h>             // For IPTOS_LOWDELAY etc.
-#include <netinet6/in6_var.h>       // For IN6_IFF_TENTATIVE etc.
-
-#include <netinet/tcp.h>
-
-#include "DebugServices.h"
-#include "dnsinfo.h"
-
-#include <ifaddrs.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOMessage.h>
-
-#include <IOKit/ps/IOPowerSources.h>
-#include <IOKit/ps/IOPowerSourcesPrivate.h>
-#include <IOKit/ps/IOPSKeys.h>
-
-#include <mach/mach_error.h>
-#include <mach/mach_port.h>
-#include <mach/mach_time.h>
-#include "helper.h"
-
-#include <SystemConfiguration/SCPrivate.h>
-
-
-#include "system_utilities.h"
-
-// Include definition of opaque_presence_indication for KEV_DL_NODE_PRESENCE handling logic.
-#include <Kernel/IOKit/apple80211/apple80211_var.h>
-
-
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#ifdef UNIT_TEST
-#include "unittest.h"
-#endif
-
-#define mDNS_IOREG_KEY               "mDNS_KEY"
-#define mDNS_IOREG_VALUE             "2009-07-30"
-#if !TARGET_OS_WATCH
-#define mDNS_IOREG_KA_KEY            "mDNS_Keepalive"
-#endif
-#define mDNS_USER_CLIENT_CREATE_TYPE 'mDNS'
-
-#define DARK_WAKE_TIME 16 // Time we hold an idle sleep assertion for maintenance after a wake notification
-
-// cache the InterfaceID of the AWDL interface
-mDNSInterfaceID AWDLInterfaceID;
-mDNSInterfaceID WiFiAwareInterfaceID;
-
-// ***************************************************************************
-// Globals
-
-// MARK: - Globals
-
-// By default we don't offer sleep proxy service
-// If OfferSleepProxyService is set non-zero (typically via command-line switch),
-// then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
-// We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
-mDNSexport int OfferSleepProxyService = 0;
-mDNSexport int DisableSleepProxyClient = 0;
-mDNSexport int UseInternalSleepProxy = 1;       // Set to non-zero to use internal (in-NIC) Sleep Proxy
-
-mDNSexport int OSXVers, iOSVers;
-mDNSexport int KQueueFD;
-
-#ifndef NO_SECURITYFRAMEWORK
-static CFArrayRef ServerCerts;
-OSStatus SSLSetAllowAnonymousCiphers(SSLContextRef context, Boolean enable);
-#endif /* NO_SECURITYFRAMEWORK */
-
-static CFStringRef NetworkChangedKey_IPv4;
-static CFStringRef NetworkChangedKey_IPv6;
-static CFStringRef NetworkChangedKey_Hostnames;
-static CFStringRef NetworkChangedKey_Computername;
-static CFStringRef NetworkChangedKey_DNS;
-static CFStringRef NetworkChangedKey_StateInterfacePrefix;
-static CFStringRef NetworkChangedKey_DynamicDNS       = CFSTR("Setup:/Network/DynamicDNS");
-static CFStringRef NetworkChangedKey_PowerSettings    = CFSTR("State:/IOKit/PowerManagement/CurrentSettings");
-
-static char HINFO_HWstring_buffer[32];
-static char *HINFO_HWstring = "Device";
-static int HINFO_HWstring_prefixlen = 6;
-
-mDNSexport int WatchDogReportingThreshold = 250;
-
-dispatch_queue_t SSLqueue;
-
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-domainname ActiveDirectoryPrimaryDomain;
-static int ActiveDirectoryPrimaryDomainLabelCount;
-static mDNSAddr ActiveDirectoryPrimaryDomainServer;
-#endif
-
-// Don't send triggers too often. We arbitrarily limit it to three minutes.
-#define DNS_TRIGGER_INTERVAL (180 * mDNSPlatformOneSecond)
-
-const char dnsprefix[] = "dns:";
-
-// String Array used to write list of private domains to Dynamic Store
-static CFArrayRef privateDnsArray = NULL;
-
-// ***************************************************************************
-// Functions
-
-// MARK: - Utility Functions
-
-// We only attempt to send and receive multicast packets on interfaces that are
-// (a) flagged as multicast-capable
-// (b) *not* flagged as point-to-point (e.g. modem)
-// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
-// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
-// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-#define MulticastInterface(i) ((i)->m->BonjourEnabled && ((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
-#else
-#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
-#endif
-#define SPSInterface(i)       ((i)->ifinfo.McastTxRx && !((i)->ifa_flags & IFF_LOOPBACK) && !(i)->D2DInterface)
-
-mDNSlocal void SetNetworkChanged(mDNSs32 delay);
-
-mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)  // Both strings are UTF-8 text
-{
-    // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
-    #if !ForceAlerts
-    {
-        // Determine if we're at Apple (17.*.*.*)
-        NetworkInterfaceInfoOSX *i;
-        for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-            if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
-                break;
-        if (!i)
-            return; // If not at Apple, don't show the alert
-    }
-    #endif
-
-    LogMsg("NotifyOfElusiveBug: %s", title);
-    LogMsg("NotifyOfElusiveBug: %s", msg);
-
-    // If we display our alert early in the boot process, then it vanishes once the desktop appears.
-    // To avoid this, we don't try to display alerts in the first three minutes after boot.
-    if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180))
-    {
-        LogMsg("Suppressing notification early in boot: %d", mDNSPlatformRawTime());
-        return;
-    }
-
-#ifndef NO_CFUSERNOTIFICATION
-    static int notifyCount = 0; // To guard against excessive display of warning notifications
-    if (notifyCount < 5)
-    {
-        notifyCount++;
-        mDNSNotify(title, msg);
-    }
-#endif /* NO_CFUSERNOTIFICATION */
-
-}
-
-// Write a syslog message and display an alert, then if ForceAlerts is set, generate a stack trace
-#if MDNS_MALLOC_DEBUGGING >= 1
-mDNSexport void LogMemCorruption(const char *format, ...)
-{
-    char buffer[512];
-    va_list ptr;
-    va_start(ptr,format);
-    mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr);
-    va_end(ptr);
-    LogMsg("!!!! %s !!!!", buffer);
-    NotifyOfElusiveBug("Memory Corruption", buffer);
-#if ForceAlerts
-    *(volatile long*)0 = 0;  // Trick to crash and get a stack trace right here, if that's what we want
-#endif
-}
-#endif
-
-// Like LogMemCorruption above, but only display the alert if ForceAlerts is set and we're going to generate a stack trace
-
-// Returns true if it is an AppleTV based hardware running iOS, false otherwise
-mDNSlocal mDNSBool IsAppleTV(void)
-{
-#if TARGET_OS_TV
-    return mDNStrue;
-#else
-    return mDNSfalse;
-#endif
-}
-
-mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
-{
-    static struct ifaddrs *ifa = NULL;
-
-    if (refresh && ifa)
-    {
-        freeifaddrs(ifa);
-        ifa = NULL;
-    }
-
-    if (ifa == NULL)
-        getifaddrs(&ifa);
-    return ifa;
-}
-
-mDNSlocal void DynamicStoreWrite(enum mDNSDynamicStoreSetConfigKey key, const char* subkey, uintptr_t value, signed long valueCnt)
-{
-    CFStringRef sckey       = NULL;
-    Boolean release_sckey   = FALSE;
-    CFDataRef bytes         = NULL;
-    CFPropertyListRef plist = NULL;
-
-    switch (key)
-    {
-        case kmDNSMulticastConfig:
-            sckey = CFSTR("State:/Network/" kDNSServiceCompMulticastDNS);
-            break;
-        case kmDNSDynamicConfig:
-            sckey = CFSTR("State:/Network/DynamicDNS");
-            break;
-        case kmDNSPrivateConfig:
-            sckey = CFSTR("State:/Network/" kDNSServiceCompPrivateDNS);
-            break;
-        case kmDNSBackToMyMacConfig:
-            sckey = CFSTR("State:/Network/BackToMyMac");
-            break;
-        case kmDNSSleepProxyServersState:
-        {
-            CFMutableStringRef tmp = CFStringCreateMutable(kCFAllocatorDefault, 0);
-            CFStringAppend(tmp, CFSTR("State:/Network/Interface/"));
-            CFStringAppendCString(tmp, subkey, kCFStringEncodingUTF8);
-            CFStringAppend(tmp, CFSTR("/SleepProxyServers"));
-            sckey = CFStringCreateCopy(kCFAllocatorDefault, tmp);
-            release_sckey = TRUE;
-            MDNS_DISPOSE_CF_OBJECT(tmp);
-            break;
-        }
-        case kmDNSDebugState:
-            sckey = CFSTR("State:/Network/mDNSResponder/DebugState");
-            break;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcovered-switch-default"
-        default:
-#pragma clang diagnostic pop
-            LogMsg("unrecognized key %d", key);
-            goto fin;
-    }
-    if (NULL == (bytes = CFDataCreateWithBytesNoCopy(NULL, (void *)value,
-                                                     valueCnt, kCFAllocatorNull)))
-    {
-        LogMsg("CFDataCreateWithBytesNoCopy of value failed");
-        goto fin;
-    }
-    if (NULL == (plist = CFPropertyListCreateWithData(NULL, bytes, kCFPropertyListImmutable, NULL, NULL)))
-    {
-        LogMsg("CFPropertyListCreateWithData of bytes failed");
-        goto fin;
-    }
-    MDNS_DISPOSE_CF_OBJECT(bytes);
-    SCDynamicStoreSetValue(NULL, sckey, plist);
-
-fin:
-    MDNS_DISPOSE_CF_OBJECT(bytes);
-    MDNS_DISPOSE_CF_OBJECT(plist);
-    if (release_sckey)
-        MDNS_DISPOSE_CF_OBJECT(sckey);
-}
-
-mDNSexport void mDNSDynamicStoreSetConfig(enum mDNSDynamicStoreSetConfigKey key, const char *subkey, CFPropertyListRef value)
-{
-    CFPropertyListRef valueCopy;
-    char *subkeyCopy  = NULL;
-    if (!value)
-        return;
-
-    // We need to copy the key and value before we dispatch off the block below as the
-    // caller will free the memory once we return from this function.
-    valueCopy = CFPropertyListCreateDeepCopy(NULL, value, kCFPropertyListImmutable);
-    if (!valueCopy)
-    {
-        LogMsg("mDNSDynamicStoreSetConfig: ERROR valueCopy NULL");
-        return;
-    }
-    if (subkey)
-    {
-        const mDNSu32 len = (mDNSu32)strlen(subkey);
-        subkeyCopy = mDNSPlatformMemAllocate(len + 1);
-        if (!subkeyCopy)
-        {
-            LogMsg("mDNSDynamicStoreSetConfig: ERROR subkeyCopy NULL");
-            MDNS_DISPOSE_CF_OBJECT(valueCopy);
-            return;
-        }
-        mDNSPlatformMemCopy(subkeyCopy, subkey, len);
-        subkeyCopy[len] = 0;
-    }
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        CFWriteStreamRef stream = NULL;
-        CFDataRef bytes = NULL;
-        CFIndex ret;
-        KQueueLock();
-
-        if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCreateWithAllocatedBuffers failed (Object creation failed)");
-            goto END;
-        }
-        CFWriteStreamOpen(stream);
-        ret = CFPropertyListWrite(valueCopy, stream, kCFPropertyListBinaryFormat_v1_0, 0, NULL);
-        if (ret == 0)
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFPropertyListWriteToStream failed (Could not write property list to stream)");
-            goto END;
-        }
-        if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCopyProperty failed (Object creation failed) ");
-            goto END;
-        }
-        CFWriteStreamClose(stream);
-        MDNS_DISPOSE_CF_OBJECT(stream);
-        const UInt8 * bytes_ptr = CFDataGetBytePtr(bytes);
-        DynamicStoreWrite(key, subkeyCopy ? subkeyCopy : "", (uintptr_t)bytes_ptr, CFDataGetLength(bytes));
-
-    END:;
-        CFPropertyListRef tmp = valueCopy;
-        MDNS_DISPOSE_CF_OBJECT(tmp);
-        if (NULL != stream)
-        {
-            CFWriteStreamClose(stream);
-            MDNS_DISPOSE_CF_OBJECT(stream);
-        }
-        MDNS_DISPOSE_CF_OBJECT(bytes);
-        if (subkeyCopy)
-            mDNSPlatformMemFree(subkeyCopy);
-
-        KQueueUnlock("mDNSDynamicStoreSetConfig");
-    });
-}
-
-// To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
-mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(const char *ifname, int type)
-{
-    NetworkInterfaceInfoOSX *i;
-    for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-        if (i->Exists && !strcmp(i->ifinfo.ifname, ifname) &&
-            ((type == AF_UNSPEC                                         ) ||
-             (type == AF_INET  && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
-             (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
-    return(NULL);
-}
-
-mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
-{
-    struct ifaddrs *ifa;
-    for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
-        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
-            if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
-            { mdns_strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
-    return -1;
-}
-
-mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
-    NetworkInterfaceInfoOSX *i;
-
-    // Don't get tricked by inactive interfaces
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->Registered && i->scope_id == scope_id) return(i);
-
-    return mDNSNULL;
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSexport mdns_interface_monitor_t GetInterfaceMonitorForIndex(uint32_t ifIndex)
-{
-    mDNS *const m = &mDNSStorage;
-
-    // We assume that interface should always be real interface, and should never be 0.
-    if (ifIndex == 0) return NULL;
-
-    if (!m->p->InterfaceMonitors)
-    {
-        m->p->InterfaceMonitors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &mdns_cfarray_callbacks);
-        if (!m->p->InterfaceMonitors)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Failed to create InterfaceMonitors array");
-            return NULL;
-        }
-    }
-
-    // Search for interface monitor given the interface index.
-    mdns_interface_monitor_t monitor;
-    for (CFIndex i = 0, n = CFArrayGetCount(m->p->InterfaceMonitors); i < n; i++)
-    {
-        monitor = (mdns_interface_monitor_t) CFArrayGetValueAtIndex(m->p->InterfaceMonitors, i);
-        if (mdns_interface_monitor_get_interface_index(monitor) == ifIndex) return monitor;
-    }
-
-    // If we come here, it means the interface is a new interface that needs to be monitored.
-    monitor = mdns_interface_monitor_create(ifIndex);
-    if (!monitor)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Failed to create an interface monitor for index %u", ifIndex);
-        return NULL;
-    }
-    CFArrayAppendValue(m->p->InterfaceMonitors, monitor);
-
-    // Put the monitor into serial queue.
-    mdns_interface_monitor_set_queue(monitor, dispatch_get_main_queue());
-
-    // When the interface configuration is changed, this block will be called.
-    mdns_interface_monitor_set_update_handler(monitor,
-    ^(mdns_interface_flags_t changeFlags)
-    {
-        const mdns_interface_flags_t relevantFlags =
-            mdns_interface_flag_expensive   |
-            mdns_interface_flag_constrained |
-            mdns_interface_flag_clat46;
-        if ((changeFlags & relevantFlags) == 0) return;
-
-        KQueueLock();
-        const CFRange range = CFRangeMake(0, CFArrayGetCount(m->p->InterfaceMonitors));
-        if (CFArrayContainsValue(m->p->InterfaceMonitors, range, monitor))
-        {
-            m->p->if_interface_changed = mDNStrue;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Monitored interface changed: %@", monitor);
-#endif
-            // Let mDNSResponder update its network configuration.
-            mDNS_Lock(m);
-            SetNetworkChanged((mDNSPlatformOneSecond + 39) / 40);   // 25 ms delay
-            mDNS_Unlock(m);
-        }
-        KQueueUnlock("interface monitor update handler");
-    });
-
-    mdns_interface_monitor_set_event_handler(monitor,
-    ^(mdns_event_t event, OSStatus error)
-    {
-        switch (event)
-        {
-            case mdns_event_invalidated:
-                mdns_release(monitor);
-                break;
-
-            case mdns_event_error:
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Interface monitor for index %u error: %ld",
-                    mdns_interface_monitor_get_interface_index(monitor), (long) error);
-                KQueueLock();
-                if (m->p->InterfaceMonitors)
-                {
-                    const CFRange range = CFRangeMake(0, CFArrayGetCount(m->p->InterfaceMonitors));
-                    const CFIndex i = CFArrayGetFirstIndexOfValue(m->p->InterfaceMonitors, range, monitor);
-                    if (i >= 0) CFArrayRemoveValueAtIndex(m->p->InterfaceMonitors, i);
-                }
-                KQueueUnlock("interface monitor event handler");
-                mdns_interface_monitor_invalidate(monitor);
-                break;
-
-            default:
-                break;
-        }
-    });
-    mdns_interface_monitor_activate(monitor);
-
-    return monitor;
-}
-#endif
-
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
-{
-    (void) m;
-    if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
-    if (ifindex == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
-    if (ifindex == kDNSServiceInterfaceIndexBLE      ) return(mDNSInterface_BLE);
-    if (ifindex == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
-
-    NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX((mDNSInterfaceID)(uintptr_t)ifindex);
-    if (!ifi)
-    {
-        // Not found. Make sure our interface list is up to date, then try again.
-        LogInfo("mDNSPlatformInterfaceIDfromInterfaceIndex: InterfaceID for interface index %d not found; Updating interface list", ifindex);
-        mDNSMacOSXNetworkChanged();
-        ifi = IfindexToInterfaceInfoOSX((mDNSInterfaceID)(uintptr_t)ifindex);
-    }
-
-    if (!ifi) return(mDNSNULL);
-
-    return(ifi->ifinfo.InterfaceID);
-}
-
-
-mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
-{
-    NetworkInterfaceInfoOSX *i;
-    if (id == mDNSInterface_Any      ) return(0);
-    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
-    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
-    if (id == mDNSInterface_BLE      ) return(kDNSServiceInterfaceIndexBLE);
-
-    mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
-
-    // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->scope_id == scope_id) return(i->scope_id);
-
-    // If we are supposed to suppress network change, return "id" back
-    if (suppressNetworkChange) return scope_id;
-
-    // Not found. Make sure our interface list is up to date, then try again.
-    LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
-    mDNSMacOSXNetworkChanged();
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->scope_id == scope_id) return(i->scope_id);
-
-    return(0);
-}
-
-mDNSlocal mDNSBool GetInterfaceSupportsWakeOnLANPacket(mDNSInterfaceID id)
-{
-    NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(id);
-    if (info == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "GetInterfaceSupportsWakeOnLANPacket: Invalid interface id %p", id);
-        return mDNSfalse;
-    }
-    else
-    {
-        return (info->ift_family == IFRTYPE_FAMILY_ETHERNET) ? mDNStrue : mDNSfalse;
-    }
-}
-
-mDNSlocal uint32_t GetIFTFamily(const char * _Nonnull if_name, uint32_t *out_sub_family)
-{
-    uint32_t ift_family = IFRTYPE_FAMILY_ANY;
-    if (out_sub_family)
-    {
-        *out_sub_family = IFRTYPE_SUBFAMILY_ANY;
-    }
-    int s = socket(AF_INET, SOCK_DGRAM, 0);
-    if (s == -1)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "GetIFTFamily: socket() failed: " PUB_S, strerror(errno));
-        return ift_family;
-    }
-    struct ifreq ifr;
-    memset(&ifr, 0, sizeof(ifr));
-    mdns_strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-    if (ioctl(s, SIOCGIFTYPE, (caddr_t)&ifr) == -1)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "GetIFTFamily: SIOCGIFTYPE failed: " PUB_S, strerror(errno));
-    }
-    else
-    {
-        ift_family = ifr.ifr_type.ift_family;
-        if (out_sub_family)
-        {
-            *out_sub_family = ifr.ifr_type.ift_subfamily;
-        }
-    }
-    close(s);
-    return ift_family;
-}
-
-// MARK: - UDP & TCP send & receive
-
-
-// Set traffic class for socket
-mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
-{
-    int traffic_class;
-
-    if (useBackgroundTrafficClass)
-        traffic_class = SO_TC_BK_SYS;
-    else
-        traffic_class = SO_TC_CTL;
-
-    (void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
-}
-
-#ifdef UNIT_TEST
-UNITTEST_SETSOCKOPT
-#else
-mDNSlocal int mDNSPlatformGetSocktFd(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType)
-{
-    if (transType == mDNSTransport_UDP)
-    {
-        UDPSocket* sock = (UDPSocket*) sockCxt;
-        return (addrType == mDNSAddrType_IPv4) ? sock->ss.sktv4 : sock->ss.sktv6;
-    }
-    else if (transType == mDNSTransport_TCP)
-    {
-        TCPSocket* sock = (TCPSocket*) sockCxt;
-        return sock->fd;
-    }
-    else
-    {
-        LogInfo("mDNSPlatformGetSocktFd: invalid transport %d", transType);
-        return kInvalidSocketRef;
-    }
-}
-
-mDNSexport void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q)
-{
-    int sockfd;
-    char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
-
-    // verify passed-in arguments exist and that sockfd is valid
-    if (q == mDNSNULL || sockCxt == mDNSNULL || (sockfd = mDNSPlatformGetSocktFd(sockCxt, transType, addrType)) < 0)
-        return;
-
-    if (q->pid)
-    {
-        if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
-            LogMsg("mDNSPlatformSetSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
-    }
-    else
-    {
-        if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
-            LogMsg("mDNSPlatformSetSocktOpt: Delegate UUID failed %s", strerror(errno));
-    }
-
-    // set the domain on the socket
-    ConvertDomainNameToCString(&q->qname, unenc_name);
-    if (!(ne_session_set_socket_attributes(sockfd, unenc_name, NULL)))
-        LogInfo("mDNSPlatformSetSocktOpt: ne_session_set_socket_attributes()-> setting domain failed for %s", unenc_name);
-
-    int nowake = 1;
-    if (setsockopt(sockfd, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
-        LogInfo("mDNSPlatformSetSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
-}
-#endif // UNIT_TEST
-
-// Note: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
-// Note: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
-// OR send via our primary v4 unicast socket
-// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
-mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
-                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
-                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
-{
-    NetworkInterfaceInfoOSX *info = mDNSNULL;
-    struct sockaddr_storage to;
-    int s = -1;
-    mStatus result = mStatus_NoError;
-    ssize_t sentlen;
-    int sendto_errno;
-    const DNSMessage *const dns_msg = msg;
-
-    if (InterfaceID)
-    {
-        info = IfindexToInterfaceInfoOSX(InterfaceID);
-        if (info == NULL)
-        {
-            // We may not have registered interfaces with the "core" as we may not have
-            // seen any interface notifications yet. This typically happens during wakeup
-            // where we might try to send DNS requests (non-SuppressUnusable questions internal
-            // to mDNSResponder) before we receive network notifications.
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
-            return mStatus_BadParamErr;
-        }
-    }
-
-    char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
-
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
-        sin_to->sin_len            = sizeof(*sin_to);
-        sin_to->sin_family         = AF_INET;
-        sin_to->sin_port           = dstPort.NotAnInteger;
-        sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
-        s = (src ? src->ss : m->p->permanentsockets).sktv4;
-
-        if (!mDNSAddrIsDNSMulticast(dst))
-        {
-        #ifdef IP_BOUND_IF
-            const mDNSu32 ifindex = info ? info->scope_id : IFSCOPE_NONE;
-            setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
-        #else
-            static int displayed = 0;
-            if (displayed < 1000)
-            {
-                displayed++;
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "[Q%u] IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets",
-                    mDNSVal16(dns_msg->h.id));
-            }
-        #endif
-        }
-        else if (info)
-        {
-            int err;
-        #ifdef IP_MULTICAST_IFINDEX
-            err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IFINDEX, &info->scope_id, sizeof(info->scope_id));
-            // We get an error when we compile on a machine that supports this option and run the binary on
-            // a different machine that does not support it
-            if (err < 0)
-            {
-                if (errno != ENOPROTOOPT)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] mDNSPlatformSendUDP: setsockopt: IP_MUTLTICAST_IFINDEX returned %d (" PUB_S ")",
-                        mDNSVal16(dns_msg->h.id), errno, strerror(errno));
-                }
-                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
-                if (err < 0 && !m->NetworkChanged)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] setsockopt - IP_MULTICAST_IF error " PRI_IPv4_ADDR " %d errno %d (" PUB_S ")",
-                        mDNSVal16(dns_msg->h.id), &info->ifa_v4addr, err, errno, strerror(errno));
-                }
-            }
-        #else
-            err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
-            if (err < 0 && !m->NetworkChanged)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] setsockopt - IP_MULTICAST_IF error " PRI_IPv4_ADDR " %d errno %d (" PUB_S ")",
-                    mDNSVal16(dns_msg->h.id), &info->ifa_v4addr, err, errno, strerror(errno));
-            }
-        #endif
-        }
-    }
-    else if (dst->type == mDNSAddrType_IPv6)
-    {
-        struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
-        sin6_to->sin6_len            = sizeof(*sin6_to);
-        sin6_to->sin6_family         = AF_INET6;
-        sin6_to->sin6_port           = dstPort.NotAnInteger;
-        sin6_to->sin6_flowinfo       = 0;
-        memcpy(sin6_to->sin6_addr.s6_addr, dst->ip.v6.b, sizeof(sin6_to->sin6_addr.s6_addr));
-        sin6_to->sin6_scope_id       = info ? info->scope_id : 0;
-        s = (src ? src->ss : m->p->permanentsockets).sktv6;
-        if (info && mDNSAddrIsDNSMulticast(dst))    // Specify outgoing interface
-        {
-            const int err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
-            if (err < 0)
-            {
-                const int setsockopt_errno = errno;
-                char name[IFNAMSIZ];
-                if (if_indextoname(info->scope_id, name) != NULL)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] setsockopt - IPV6_MULTICAST_IF error %d errno %d (" PUB_S ")",
-                        mDNSVal16(dns_msg->h.id), err, setsockopt_errno, strerror(setsockopt_errno));
-                }
-                else
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] setsockopt - IPV6_MUTLICAST_IF scopeid %d, not a valid interface",
-                        mDNSVal16(dns_msg->h.id), info->scope_id);
-                }
-            }
-        }
-#ifdef IPV6_BOUND_IF
-        if (info)   // Specify outgoing interface for non-multicast destination
-        {
-            if (!mDNSAddrIsDNSMulticast(dst))
-            {
-                if (info->scope_id == 0)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "[Q%u] IPV6_BOUND_IF socket option not set -- info %p (" PUB_S ") scope_id is zero",
-                        mDNSVal16(dns_msg->h.id), info, ifa_name);
-                }
-                else
-                {
-                    setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-                }
-            }
-        }
-#endif
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_FAULT, "[Q%u] mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!", mDNSVal16(dns_msg->h.id));
-        return mStatus_BadParamErr;
-    }
-
-    if (s >= 0)
-    {
-        verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
-                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
-    }
-    else
-    {
-        verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
-                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
-    }
-
-    // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
-    // If we don't have the corresponding type of socket available, then return mStatus_Invalid
-    if (s < 0) return(mStatus_Invalid);
-
-    // switch to background traffic class for this message if requested
-    if (useBackgroundTrafficClass)
-        setTrafficClass(s, useBackgroundTrafficClass);
-
-    sentlen = sendto(s, msg, end - (const UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
-    sendto_errno = (sentlen < 0) ? errno : 0;
-
-    // set traffic class back to default value
-    if (useBackgroundTrafficClass)
-        setTrafficClass(s, mDNSfalse);
-
-    if (sentlen < 0)
-    {
-        static int MessageCount = 0;
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] mDNSPlatformSendUDP -> sendto(%d) failed to send packet on InterfaceID %p "
-            PUB_S "/%d to " PRI_IP_ADDR ":%d skt %d error %ld errno %d (" PUB_S ") %u",
-            mDNSVal16(dns_msg->h.id), s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, (long)sentlen,
-            sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow));
-        if (!mDNSAddressIsAllDNSLinkGroup(dst))
-        {
-            if ((sendto_errno == EHOSTUNREACH) || (sendto_errno == ENETUNREACH)) return(mStatus_HostUnreachErr);
-            if ((sendto_errno == EHOSTDOWN)    || (sendto_errno == ENETDOWN))    return(mStatus_TransientErr);
-        }
-        // Don't report EHOSTUNREACH in the first three minutes after boot
-        // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
-        // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
-        if (sendto_errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
-        // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
-        if (sendto_errno == EADDRNOTAVAIL && m->NetworkChanged) return(mStatus_TransientErr);
-        if (sendto_errno == EHOSTUNREACH || sendto_errno == EADDRNOTAVAIL || sendto_errno == ENETDOWN)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_ERROR, "[Q%u] mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p "
-                PUB_S "/%d to " PRI_IP_ADDR ":%d skt %d error %ld errno %d (" PUB_S ") %u",
-                mDNSVal16(dns_msg->h.id), s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s,
-                (long)sentlen, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow));
-        }
-        else
-        {
-            MessageCount++;
-            if (MessageCount < 50) // Cap and ensure NO spamming of LogMsgs
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                    "[Q%u] mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p " PUB_S "/%d to " PRI_IP_ADDR ":%d skt %d error %ld errno %d (" PUB_S ") %u MessageCount is %d",
-                    mDNSVal16(dns_msg->h.id), s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, (long)sentlen, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow), MessageCount);
-            }
-            else // If logging is enabled, remove the cap and log aggressively
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "[Q%u] mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p " PUB_S "/%d to " PRI_IP_ADDR ":%d skt %d error %ld errno %d (" PUB_S ") %u MessageCount is %d",
-                    mDNSVal16(dns_msg->h.id), s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, (long)sentlen, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow), MessageCount);
-            }
-        }
-
-        result = mStatus_UnknownErr;
-    }
-
-    return(result);
-}
-
-mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
-                             struct sockaddr *const from, socklen_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
-{
-    static unsigned int numLogMessages = 0;
-    struct iovec databuffers = { (char *)buffer, max };
-    struct msghdr msg;
-    ssize_t n;
-    struct cmsghdr *cmPtr;
-    char ancillary[1024];
-
-    *ttl = 255;  // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
-
-    // Set up the message
-    msg.msg_name       = (caddr_t)from;
-    msg.msg_namelen    = *fromlen;
-    msg.msg_iov        = &databuffers;
-    msg.msg_iovlen     = 1;
-    msg.msg_control    = (caddr_t)&ancillary;
-    msg.msg_controllen = sizeof(ancillary);
-    msg.msg_flags      = 0;
-
-    // Receive the data
-    n = recvmsg(s, &msg, 0);
-    if (n<0)
-    {
-        if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
-        return(-1);
-    }
-    if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
-    {
-        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu, errno %d",
-                                           s, n, msg.msg_controllen, sizeof(struct cmsghdr), errno);
-        return(-1);
-    }
-    // Note: MSG_TRUNC means the datagram was truncated, while MSG_CTRUNC means that the control data was truncated.
-    // The mDNS core is capable of handling truncated DNS messages, so MSG_TRUNC isn't checked.
-    if (msg.msg_flags & MSG_CTRUNC)
-    {
-        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
-        return(-1);
-    }
-
-    *fromlen = msg.msg_namelen;
-
-    // Parse each option out of the ancillary data.
-    for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
-    {
-        // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
-        {
-            dstaddr->type = mDNSAddrType_IPv4;
-            dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
-            //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
-        {
-            struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
-            if (sdl->sdl_nlen < IF_NAMESIZE)
-            {
-                mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
-                ifname[sdl->sdl_nlen] = 0;
-                // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
-            }
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
-            *ttl = *(u_char*)CMSG_DATA(cmPtr);
-        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
-        {
-            struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
-            dstaddr->type = mDNSAddrType_IPv6;
-            dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
-            myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
-            *ttl = *(int*)CMSG_DATA(cmPtr);
-    }
-
-    return(n);
-}
-
-// What is this for, and why does it use xor instead of a simple equality check? -- SC
-mDNSlocal mDNSInterfaceID FindMyInterface(const mDNSAddr *addr)
-{
-    NetworkInterfaceInfo *intf;
-
-    if (addr->type == mDNSAddrType_IPv4)
-    {
-        for (intf = mDNSStorage.HostInterfaces; intf; intf = intf->next)
-        {
-            if (intf->ip.type == addr->type && intf->McastTxRx)
-            {
-                if ((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) == 0)
-                {
-                    return(intf->InterfaceID);
-                }
-            }
-        }
-    }
-
-    if (addr->type == mDNSAddrType_IPv6)
-    {
-        for (intf = mDNSStorage.HostInterfaces; intf; intf = intf->next)
-        {
-            if (intf->ip.type == addr->type && intf->McastTxRx)
-            {
-                if (((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) == 0) &&
-                    ((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) == 0) &&
-                    ((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) == 0) &&
-                    (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) == 0)))
-                    {
-                        return(intf->InterfaceID);
-                    }
-            }
-        }
-    }
-    return(mDNSInterface_Any);
-}
-
-mDNSexport void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF)
-{
-    KQSocketSet *const ss = (KQSocketSet *)context;
-    mDNS *const m = ss->m;
-    ssize_t recvlen = -1;
-    int count = 0, closed = 0, recvfrom_errno = 0;
-
-    if (filter != EVFILT_READ)
-        LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
-
-    if (s1 != ss->sktv4 && s1 != ss->sktv6)
-    {
-        LogMsg("myKQSocketCallBack: native socket %d", s1);
-        LogMsg("myKQSocketCallBack: sktv4 %d sktv6 %d", ss->sktv4, ss->sktv6);
-    }
-
-    if (encounteredEOF)
-    {
-        LogMsg("myKQSocketCallBack: socket %d is no longer readable (EOF)", s1);
-        if (s1 == ss->sktv4)
-        {
-            ss->sktv4EOF = mDNStrue;
-            KQueueSet(ss->sktv4, EV_DELETE, EVFILT_READ, &ss->kqsv4);
-        }
-        else if (s1 == ss->sktv6)
-        {
-            ss->sktv6EOF = mDNStrue;
-            KQueueSet(ss->sktv6, EV_DELETE, EVFILT_READ, &ss->kqsv6);
-        }
-        return;
-    }
-
-    while (!closed)
-    {
-        mDNSAddr senderAddr, destAddr = zeroAddr;
-        mDNSIPPort senderPort;
-        struct sockaddr_storage from;
-        socklen_t fromlen = sizeof(from);
-        char packetifname[IF_NAMESIZE] = "";
-        mDNSu8 ttl;
-        recvlen = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
-        if (recvlen < 0)
-        {
-            recvfrom_errno = errno;
-            break;
-        }
-
-        if ((destAddr.type == mDNSAddrType_IPv4 && (destAddr.ip.v4.b[0] & 0xF0) == 0xE0) ||
-            (destAddr.type == mDNSAddrType_IPv6 && (destAddr.ip.v6.b[0]         == 0xFF))) m->p->num_mcasts++;
-
-        count++;
-        if (from.ss_family == AF_INET)
-        {
-            struct sockaddr_in *s = (struct sockaddr_in*)&from;
-            senderAddr.type = mDNSAddrType_IPv4;
-            senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
-            senderPort.NotAnInteger = s->sin_port;
-            //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
-        }
-        else if (from.ss_family == AF_INET6)
-        {
-            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
-            senderAddr.type = mDNSAddrType_IPv6;
-            senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
-            senderPort.NotAnInteger = sin6->sin6_port;
-            //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
-        }
-        else
-        {
-            LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
-            return;
-        }
-
-        // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
-        mDNSInterfaceID InterfaceID = mDNSNULL;
-        NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
-        while (intf)
-        {
-            if (intf->Exists && !strcmp(intf->ifinfo.ifname, packetifname))
-                break;
-            intf = intf->next;
-        }
-
-        // When going to sleep we deregister all our interfaces, but if the machine
-        // takes a few seconds to sleep we may continue to receive multicasts
-        // during that time, which would confuse mDNSCoreReceive, because as far
-        // as it's concerned, we should have no active interfaces any more.
-        // Hence we ignore multicasts for which we can find no matching InterfaceID.
-        if (intf)
-            InterfaceID = intf->ifinfo.InterfaceID;
-        else if (mDNSAddrIsDNSMulticast(&destAddr))
-            continue;
-
-        if (!InterfaceID)
-        {
-            InterfaceID = FindMyInterface(&destAddr);
-        }
-
-//      LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
-//          &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
-
-        // mDNSCoreReceive may close the socket we're reading from.  We must break out of our
-        // loop when that happens, or we may try to read from an invalid FD.  We do this by
-        // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
-        // if it closes the socketset.
-        ss->closeFlag = &closed;
-
-        if (ss->proxy)
-        {
-            m->p->UDPProxyCallback(&m->p->UDPProxy, &m->imsg.m, (unsigned char*)&m->imsg + recvlen, &senderAddr,
-                senderPort, &destAddr, ss->port, InterfaceID, NULL);
-        }
-        else
-        {
-            mDNSCoreReceive(m, &m->imsg.m, (unsigned char*)&m->imsg + recvlen, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
-        }
-
-        // if we didn't close, we can safely dereference the socketset, and should to
-        // reset the closeFlag, since it points to something on the stack
-        if (!closed) ss->closeFlag = mDNSNULL;
-    }
-
-    // If a client application's sockets are marked as defunct
-    // sockets we have delegated to it with SO_DELEGATED will also go defunct.
-    // We get an ENOTCONN error for defunct sockets and should just close the socket in that case.
-    if (recvlen < 0 && recvfrom_errno == ENOTCONN)
-    {
-        LogInfo("myKQSocketCallBack: ENOTCONN, closing socket");
-        close(s1);
-        return;
-    }
-
-    if (recvlen < 0 && (recvfrom_errno != EWOULDBLOCK || count == 0))
-    {
-        // Something is busted here.
-        // kqueue says there is a packet, but myrecvfrom says there is not.
-        // Try calling select() to get another opinion.
-        // Find out about other socket parameter that can help understand why select() says the socket is ready for read
-        // All of this is racy, as data may have arrived after the call to select()
-        static unsigned int numLogMessages = 0;
-        int so_error = -1;
-        int so_nread = -1;
-        int fionread = -1;
-        socklen_t solen;
-        fd_set readfds;
-        struct timeval timeout;
-        int selectresult;
-        FD_ZERO(&readfds);
-        FD_SET(s1, &readfds);
-        timeout.tv_sec  = 0;
-        timeout.tv_usec = 0;
-        selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
-        solen = (socklen_t)sizeof(so_error);
-        if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
-            LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
-        solen = (socklen_t)sizeof(so_nread);
-        if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
-            LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
-        if (ioctl(s1, FIONREAD, &fionread) == -1)
-            LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
-        if (numLogMessages++ < 100)
-            LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
-                   s1, (int)recvlen, recvfrom_errno, strerror(recvfrom_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
-        if (numLogMessages > 5)
-            NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
-                               "Congratulations, you've reproduced an elusive bug.\r"
-                               "Please send email to radar-3387020@group.apple.com.)\r"
-                               "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
-
-        sleep(1);       // After logging this error, rate limit so we don't flood syslog
-    }
-}
-
-mDNSlocal void doTcpSocketCallback(TCPSocket *sock)
-{
-    mDNSBool c = !sock->connected;
-    if (!sock->connected && sock->err == mStatus_NoError)
-    {
-        sock->connected = mDNStrue;
-    }
-    sock->callback(sock, sock->context, c, sock->err);
-    // Note: the callback may call CloseConnection here, which frees the context structure!
-}
-
-#ifndef NO_SECURITYFRAMEWORK
-
-mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, size_t *dataLength)
-{
-    const ssize_t ret = send(((const TCPSocket *)connection)->fd, data, *dataLength, 0);
-    if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = (size_t)ret; return(errSSLWouldBlock); }
-    if (ret >= 0)                              { *dataLength = (size_t)ret; return(noErr); }
-    *dataLength = 0;
-    if (errno == EAGAIN                      ) return(errSSLWouldBlock);
-    if (errno == ENOENT                      ) return(errSSLClosedGraceful);
-    if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
-    LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((const TCPSocket *)connection)->fd, errno, strerror(errno));
-    return(errSSLClosedAbort);
-}
-
-mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
-{
-    const ssize_t ret = recv(((const TCPSocket *)connection)->fd, data, *dataLength, 0);
-    if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = (size_t)ret; return(errSSLWouldBlock); }
-    if (ret > 0)                              { *dataLength = (size_t)ret; return(noErr); }
-    *dataLength = 0;
-    if (ret == 0 || errno == ENOENT    ) return(errSSLClosedGraceful);
-    if (            errno == EAGAIN    ) return(errSSLWouldBlock);
-    if (            errno == ECONNRESET) return(errSSLClosedAbort);
-    LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
-    return(errSSLClosedAbort);
-}
-
-mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, SSLProtocolSide pside, SSLConnectionType ctype)
-{
-    char domname_cstr[MAX_ESCAPED_DOMAIN_NAME];
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    sock->tlsContext = SSLCreateContext(kCFAllocatorDefault, pside, ctype);
-    if (!sock->tlsContext)
-    {
-        LogMsg("ERROR: tlsSetupSock: SSLCreateContext failed");
-        return(mStatus_UnknownErr);
-    }
-
-    mStatus err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
-    if (err)
-    {
-        LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err);
-        goto fail;
-    }
-
-    err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
-    if (err)
-    {
-        LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err);
-        goto fail;
-    }
-
-    // Set the default ciphersuite configuration
-    err = SSLSetSessionConfig(sock->tlsContext, CFSTR("default"));
-    if (err)
-    {
-        LogMsg("ERROR: tlsSetupSock: SSLSetSessionConfig failed with error code: %d", err);
-        goto fail;
-    }
-
-    // We already checked for NULL in hostname and this should never happen. Hence, returning -1
-    // (error not in OSStatus space) is okay.
-    if (!sock->hostname || !sock->hostname->c[0])
-    {
-        LogMsg("ERROR: tlsSetupSock: hostname NULL");
-        err = -1;
-        goto fail;
-    }
-
-    ConvertDomainNameToCString(sock->hostname, domname_cstr);
-    err = SSLSetPeerDomainName(sock->tlsContext, domname_cstr, strlen(domname_cstr));
-    if (err)
-    {
-        LogMsg("ERROR: tlsSetupSock: SSLSetPeerDomainname: %s failed with error code: %d", domname_cstr, err);
-        goto fail;
-    }
-#pragma clang diagnostic pop
-    return(err);
-
-fail:
-    MDNS_DISPOSE_CF_OBJECT(sock->tlsContext);
-    return(err);
-}
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void doSSLHandshake(TCPSocket *sock)
-{
-    mStatus err = SSLHandshake(sock->tlsContext);
-
-    //Can't have multiple threads in mDNS core. When MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM is
-    //defined, KQueueLock is a noop. Hence we need to serialize here
-    //
-    //NOTE: We just can't serialize doTcpSocketCallback alone on the main queue.
-    //We need the rest of the logic also. Otherwise, we can enable the READ
-    //events below, dispatch a doTcpSocketCallback on the main queue. Assume it is
-    //ConnFailed which means we are going to free the tcpInfo. While it
-    //is waiting to be dispatched, another read event can come into tcpKQSocketCallback
-    //and potentially call doTCPCallback with error which can close the fd and free the
-    //tcpInfo. Later when the thread gets dispatched it will crash because the tcpInfo
-    //is already freed.
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-
-                       LogInfo("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-
-                       if (sock->handshake == handshake_to_be_closed)
-                       {
-                           LogInfo("SSLHandshake completed after close");
-                           mDNSPlatformTCPCloseConnection(sock);
-                       }
-                       else
-                       {
-                           if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
-                           else LogMsg("doSSLHandshake: sock->fd is -1");
-
-                           if (err == errSSLWouldBlock)
-                               sock->handshake = handshake_required;
-                           else
-                           {
-                               if (err)
-                               {
-                                   LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
-                                   MDNS_DISPOSE_CF_OBJECT(sock->tlsContext);
-                               }
-
-                               sock->err = err ? mStatus_ConnFailed : 0;
-                               sock->handshake = handshake_completed;
-
-                               LogInfo("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
-                               doTcpSocketCallback(sock);
-                           }
-                       }
-
-                       LogInfo("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
-                       return;
-                   });
-}
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void *doSSLHandshake(TCPSocket *sock)
-{
-    // Warning: Touching sock without the kqueue lock!
-    // We're protected because sock->handshake == handshake_in_progress
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    mStatus err = SSLHandshake(sock->tlsContext);
-#pragma clang diagnostic pop
-    KQueueLock();
-    debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-
-    if (sock->handshake == handshake_to_be_closed)
-    {
-        LogInfo("SSLHandshake completed after close");
-        mDNSPlatformTCPCloseConnection(sock);
-    }
-    else
-    {
-        if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry);
-        else LogMsg("doSSLHandshake: sock->fd is -1");
-
-        if (err == errSSLWouldBlock)
-            sock->handshake = handshake_required;
-        else
-        {
-            if (err)
-            {
-                LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
-                MDNS_DISPOSE_CF_OBJECT(sock->tlsContext);
-            }
-
-            sock->err = err ? mStatus_ConnFailed : 0;
-            sock->handshake = handshake_completed;
-
-            debugf("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
-            doTcpSocketCallback(sock);
-        }
-    }
-
-    debugf("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
-    KQueueUnlock("doSSLHandshake");
-    return NULL;
-}
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void spawnSSLHandshake(TCPSocket* sock)
-{
-    debugf("spawnSSLHandshake %p: entry", sock);
-
-    if (sock->handshake != handshake_required) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock->handshake);
-    sock->handshake = handshake_in_progress;
-    KQueueSet(sock->fd, EV_DELETE, EVFILT_READ, &sock->kqEntry);
-
-    // Dispatch it on a separate queue to help avoid blocking other threads/queues, and
-    // to limit the number of threads used for SSLHandshake
-    dispatch_async(SSLqueue, ^{doSSLHandshake(sock);});
-
-    debugf("spawnSSLHandshake %p: done for %d", sock, sock->fd);
-}
-
-#endif /* NO_SECURITYFRAMEWORK */
-
-mDNSlocal void tcpKQSocketCallback(int fd, short filter, void *context, __unused mDNSBool encounteredEOF)
-{
-    TCPSocket *sock = context;
-    sock->err = mStatus_NoError;
-
-    //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
-    //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
-    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
-    if (filter == EVFILT_WRITE)
-    {
-        // sock->connected gets set by doTcpSocketCallback(), which may be called from here, or may be called
-        // from the TLS connect code.   If we asked for a writability test, we are connecting
-        // (sock->connected == mDNSFalse).
-        if (sock->connected)
-        {
-            LogInfo("ERROR: TCPConnectCallback called with write event when socket is connected.");
-        }
-        else
-        {
-            int result = 0;
-            socklen_t len = (socklen_t)sizeof(result);
-            if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &len) < 0)
-            {
-                LogInfo("ERROR: TCPConnectCallback - unable to get connect error: socket %d: Error %d (%s)",
-                        sock->fd, errno, strerror(errno));
-                sock->err = mStatus_ConnFailed;
-            }
-            else
-            {
-                if (result != 0)
-                {
-                    sock->err = mStatus_ConnFailed;
-                    if (result == EHOSTUNREACH || result == EADDRNOTAVAIL || result == ENETDOWN)
-                    {
-                        LogInfo("ERROR: TCPConnectCallback - connect failed: socket %d: Error %d (%s)",
-                                sock->fd, result, strerror(result));
-                    }
-                    else
-                    {
-                        LogMsg("ERROR: TCPConnectCallback - connect failed: socket %d: Error %d (%s)",
-                               sock->fd, result, strerror(result));
-                    }
-                }
-            }
-        }
-        KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, &sock->kqEntry);
-
-        // If we set the EVFILT_READ event in mDNSPlatformTCPConnect, it's possible to get a read event
-        // before the write event--apparently the socket is both readable and writable once that happens,
-        // even if the connect fails.   If we set it here, after we've gotten a successful connection, then
-        // we shouldn't run into that problem.
-        if (sock->err == mStatus_NoError &&
-            KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry))
-        {
-            // And of course if that fails, we can't use the connection even though we have it.
-            LogMsg("ERROR: tcpKQSocketCallback - KQueueSet failed");
-            sock->err = mStatus_TransientErr;
-        }
-    }
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        // Don't try to set up TLS if the connect failed.
-        if (sock->err == mStatus_NoError) {
-            if (!sock->setup)
-            {
-                sock->setup = mDNStrue;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-                sock->err = tlsSetupSock(sock, kSSLClientSide, kSSLStreamType);
-                if (sock->err)
-                {
-                    LogMsg("ERROR: tcpKQSocketCallback: tlsSetupSock failed with error code: %d", sock->err);
-                    return;
-                }
-#pragma clang diagnostic pop
-            }
-            if (sock->handshake == handshake_required)
-            {
-                spawnSSLHandshake(sock);
-                return;
-            }
-            else if (sock->handshake == handshake_in_progress || sock->handshake == handshake_to_be_closed)
-            {
-                return;
-            }
-            else if (sock->handshake != handshake_completed)
-            {
-                if (!sock->err)
-                    sock->err = mStatus_UnknownErr;
-                LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
-            }
-        }
-#else  /* NO_SECURITYFRAMEWORK */
-        sock->err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-
-    doTcpSocketCallback(sock);
-}
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef)
-{
-    dispatch_queue_t queue = dispatch_get_main_queue();
-    dispatch_source_t source;
-    if (flags == EV_DELETE)
-    {
-        if (filter == EVFILT_READ)
-        {
-            dispatch_source_cancel(entryRef->readSource);
-            MDNS_DISPOSE_DISPATCH(entryRef->readSource);
-            debugf("KQueueSet: source cancel for read %p, %p", entryRef->readSource, entryRef->writeSource);
-        }
-        else if (filter == EVFILT_WRITE)
-        {
-            dispatch_source_cancel(entryRef->writeSource);
-            MDNS_DISPOSE_DISPATCH(entryRef->writeSource);
-            debugf("KQueueSet: source cancel for write %p, %p", entryRef->readSource, entryRef->writeSource);
-        }
-        else
-            LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_DELETE", filter);
-        return 0;
-    }
-    if (flags != EV_ADD) LogMsg("KQueueSet: Invalid flags %d", flags);
-
-    if (filter == EVFILT_READ)
-    {
-        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue);
-    }
-    else if (filter == EVFILT_WRITE)
-    {
-        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, queue);
-    }
-    else
-    {
-        LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_ADD", filter);
-        return -1;
-    }
-    if (!source) return -1;
-    dispatch_source_set_event_handler(source, ^{
-
-                                          mDNSs32 stime = mDNSPlatformRawTime();
-                                          entryRef->KQcallback(fd, filter, entryRef->KQcontext);
-                                          mDNSs32 etime = mDNSPlatformRawTime();
-                                          if (etime - stime >= WatchDogReportingThreshold)
-                                              LogInfo("KQEntryCallback Block: WARNING: took %dms to complete", etime - stime);
-
-                                          // Trigger the event delivery to the application. Even though we trigger the
-                                          // event completion after handling every event source, these all will hopefully
-                                          // get merged
-                                          TriggerEventCompletion();
-
-                                      });
-    dispatch_source_set_cancel_handler(source, ^{
-                                           if (entryRef->fdClosed)
-                                           {
-                                               //LogMsg("CancelHandler: closing fd %d", fd);
-                                               close(fd);
-                                           }
-                                       });
-    dispatch_resume(source);
-    if (filter == EVFILT_READ)
-        entryRef->readSource = source;
-    else
-        entryRef->writeSource = source;
-
-    return 0;
-}
-
-mDNSexport void KQueueLock()
-{
-}
-mDNSexport void KQueueUnlock(const char const *task)
-{
-    (void)task; //unused
-}
-#else
-
-mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef)
-{
-    struct kevent new_event;
-    EV_SET(&new_event, fd, filter, flags, 0, 0, entryRef);
-    return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
-}
-
-mDNSexport void KQueueLock()
-{
-    mDNS *const m = &mDNSStorage;
-    pthread_mutex_lock(&m->p->BigMutex);
-    m->p->BigMutexStartTime = mDNSPlatformRawTime();
-}
-
-mDNSexport void KQueueUnlock(const char* task)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSs32 end = mDNSPlatformRawTime();
-    (void)task;
-    if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING,
-            "WARNING: " PUB_S " took %d ms to complete", task, end - m->p->BigMutexStartTime);
-    }
-
-    pthread_mutex_unlock(&m->p->BigMutex);
-
-    char wake = 1;
-    if (send(m->p->WakeKQueueLoopFD, &wake, sizeof(wake), 0) == -1)
-        LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
-}
-#endif
-
-mDNSexport void mDNSPlatformCloseFD(KQueueEntry *kq, int fd)
-{
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        (void) fd; //unused
-    if (kq->readSource)
-    {
-        dispatch_source_cancel(kq->readSource);
-        kq->readSource = mDNSNULL;
-    }
-    if (kq->writeSource)
-    {
-        dispatch_source_cancel(kq->writeSource);
-        kq->writeSource = mDNSNULL;
-    }
-    // Close happens in the cancellation handler
-    debugf("mDNSPlatformCloseFD: resetting sources for %d", fd);
-    kq->fdClosed = mDNStrue;
-#else
-    (void)kq; //unused
-    close(fd);
-#endif
-}
-
-mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass)
-{
-    int skt;
-
-    skt = -1;
-    if (!mDNSPosixTCPSocketSetup(&skt, addrtype, port, &sock->port))
-    {
-        if (skt != -1) close(skt);
-        return mStatus_UnknownErr;
-    }
-
-    // for TCP sockets, the traffic class is set once and not changed
-    setTrafficClass(skt, useBackgroundTrafficClass);
-
-    sock->fd = skt;
-    sock->kqEntry.KQcallback = tcpKQSocketCallback;
-    sock->kqEntry.KQcontext  = sock;
-    sock->kqEntry.KQtask     = "mDNSPlatformTCPSocket";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    sock->kqEntry.readSource = mDNSNULL;
-    sock->kqEntry.writeSource = mDNSNULL;
-    sock->kqEntry.fdClosed = mDNSfalse;
-#endif
-    return mStatus_NoError;
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSAddr_Type addrtype, mDNSIPPort *port, domainname *hostname, mDNSBool useBackgroundTrafficClass)
-{
-    mStatus err;
-    mDNSu32 lowWater = 16384;
-    size_t len = sizeof (TCPSocket);
-    if (hostname) {
-        len += sizeof (domainname);
-    }
-
-    TCPSocket *sock = (TCPSocket *) callocL("TCPSocket/mDNSPlatformTCPSocket", len);
-    if (!sock)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPSocket: memory allocation failure");
-        return(mDNSNULL);
-    }
-
-    if (hostname)
-    {
-        sock->hostname = (domainname *)(sock + 1); // Allocated together so can be freed together
-        debugf("mDNSPlatformTCPSocket: hostname %##s", hostname->c);
-        AssignDomainName(sock->hostname, hostname);
-    }
-
-    err = SetupTCPSocket(sock, addrtype, port, useBackgroundTrafficClass);
-
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPSocket: socket error %d errno %d (" PUB_S ")", sock->fd, errno, strerror(errno));
-        freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
-        return(mDNSNULL);
-    }
-
-    if (setsockopt(sock->fd, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &lowWater, sizeof lowWater) < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPSocket: TCP_NOTSENT_LOWAT returned %d", errno);
-               mDNSPlatformTCPCloseConnection(sock);
-        return mDNSNULL;
-    }
-
-    sock->callback          = mDNSNULL;
-    sock->flags             = flags;
-    sock->context           = mDNSNULL;
-    sock->setup             = mDNSfalse;
-    sock->connected         = mDNSfalse;
-    sock->handshake         = handshake_required;
-    sock->m                 =  &mDNSStorage;
-    sock->err               = mStatus_NoError;
-
-    return sock;
-}
-
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context)
-{
-    mStatus err = mStatus_NoError;
-    struct sockaddr_storage ss;
-
-    sock->callback          = callback;
-    sock->context           = context;
-    sock->setup             = mDNSfalse;
-    sock->connected         = mDNSfalse;
-    sock->handshake         = handshake_required;
-    sock->err               = mStatus_NoError;
-
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *saddr = (struct sockaddr_in *)&ss;
-        mDNSPlatformMemZero(saddr, sizeof(*saddr));
-        saddr->sin_family      = AF_INET;
-        saddr->sin_port        = dstport.NotAnInteger;
-        saddr->sin_len         = sizeof(*saddr);
-        saddr->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
-    }
-    else
-    {
-        struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&ss;
-        mDNSPlatformMemZero(saddr6, sizeof(*saddr6));
-        saddr6->sin6_family      = AF_INET6;
-        saddr6->sin6_port        = dstport.NotAnInteger;
-        saddr6->sin6_len         = sizeof(*saddr6);
-        saddr6->sin6_addr        = *(const struct in6_addr *)&dst->ip.v6;
-    }
-
-    // Watch for connect complete (write is ready)
-    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
-    if (KQueueSet(sock->fd, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, &sock->kqEntry))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
-        return errno;
-    }
-
-    if (fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ERROR: setsockopt O_NONBLOCK - " PUB_S, strerror(errno));
-        return mStatus_UnknownErr;
-    }
-
-    // We bind to the interface and all subsequent packets including the SYN will be sent out
-    // on this interface
-    //
-    // Note: If we are in Active Directory domain, we may try TCP (if the response can't fit in
-    // UDP).
-    if (InterfaceID)
-    {
-        NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(InterfaceID);
-        if (dst->type == mDNSAddrType_IPv4)
-        {
-        #ifdef IP_BOUND_IF
-            if (info) setsockopt(sock->fd, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID);
-                return mStatus_BadParamErr;
-            }
-        #else
-            (void)InterfaceID; // Unused
-            (void)info; // Unused
-        #endif
-        }
-        else
-        {
-        #ifdef IPV6_BOUND_IF
-            if (info) setsockopt(sock->fd, IPPROTO_IPV6, IPV6_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID);
-                return mStatus_BadParamErr;
-            }
-        #else
-            (void)InterfaceID; // Unused
-            (void)info; // Unused
-        #endif
-        }
-    }
-
-    // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
-    // from which we can infer the destination address family. Hence we need to remember that here.
-    // Instead of remembering the address family, we remember the right fd.
-    sock->fd = sock->fd;
-    // initiate connection wth peer
-    if (connect(sock->fd, (struct sockaddr *)&ss, ss.ss_len) < 0)
-    {
-        if (errno == EINPROGRESS) return mStatus_ConnPending;
-        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (" PUB_S ")",
-                sock->fd, errno, strerror(errno));
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (" PUB_S ") length %d",
-                sock->fd, errno, strerror(errno), ss.ss_len);
-        }
-        return mStatus_ConnFailed;
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "NOTE: mDNSPlatformTCPConnect completed synchronously");
-    // kQueue should notify us, but this LogMsg is to help track down if it doesn't
-    // Experimentation shows that even a connection to a local listener returns EINPROGRESS, so this
-    // will likely never happen.
-
-    return err;
-}
-
-// Replace the existing socket callback with a new one, or establish a callback where none was present.
-mDNSexport mStatus mDNSPlatformTCPSocketSetCallback(TCPSocket *sock, TCPConnectionCallback callback, void *context)
-{
-    sock->callback = callback;
-    sock->context = context;
-
-    // dnsextd currently reaches into the TCPSocket structure layer to do its own thing; this won't work for
-    // any code (e.g., the Discovery Proxy or Discovery Relay) that actually uses the mDNSPlatform layer as
-    // an opaque layer.   So for that code, we have this.   dnsextd should probably be platformized if it's
-    // still relevant.
-    if (!sock->callback) {
-        // Watch for incoming data
-        if (KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry))
-        {
-            LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
-            return mStatus_UnknownErr;
-        }
-    }
-
-    sock->kqEntry.KQcallback = tcpKQSocketCallback;
-    sock->kqEntry.KQcontext  = sock;
-    sock->kqEntry.KQtask     = "mDNSPlatformTCPSocket";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    sock->kqEntry.readSource = mDNSNULL;
-    sock->kqEntry.writeSource = mDNSNULL;
-    sock->kqEntry.fdClosed = mDNSfalse;
-#endif
-    return mStatus_NoError;
-}
-
-// Why doesn't mDNSPlatformTCPAccept actually call accept() ?
-// mDNSPlatformTCPAccept is only called by dnsextd.c.   It's called _after_ accept has returned
-// a connected socket.   The purpose appears to be to allocate and initialize the TCPSocket structure
-// and set up TLS, if required for this connection.   dnsextd appears to be the only thing in mDNSResponder
-// that accepts incoming TLS connections.
-mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
-{
-    mStatus err = mStatus_NoError;
-
-    TCPSocket *sock = (TCPSocket *) callocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(*sock));
-    if (!sock) return(mDNSNULL);
-
-    sock->fd = fd;
-    sock->flags = flags;
-
-    if (flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
-        if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
-
-        err = tlsSetupSock(sock, kSSLServerSide, kSSLStreamType);
-        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
-
-        err = SSLSetCertificate(sock->tlsContext, ServerCerts);
-        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
-#pragma clang diagnostic pop
-#else
-        err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-#ifndef NO_SECURITYFRAMEWORK
-exit:
-#endif
-
-    if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
-    return(sock);
-}
-
-mDNSlocal void tcpListenCallback(int fd, __unused short filter, void *context, __unused mDNSBool encounteredEOF)
-{
-    TCPListener *listener = context;
-    TCPSocket *sock;
-
-    sock = mDNSPosixDoTCPListenCallback(fd, listener->addressType, listener->socketFlags,
-                                 listener->callback, listener->context);
-
-    if (sock != mDNSNULL)
-    {
-        KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry);
-
-        sock->kqEntry.KQcallback = tcpKQSocketCallback;
-        sock->kqEntry.KQcontext  = sock;
-        sock->kqEntry.KQtask     = "mDNSPlatformTCPListen";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        sock->kqEntry.readSource = mDNSNULL;
-        sock->kqEntry.writeSource = mDNSNULL;
-        sock->kqEntry.fdClosed = mDNSfalse;
-#endif
-    }
-}
-
-mDNSexport TCPListener *mDNSPlatformTCPListen(mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
-                                              TCPSocketFlags socketFlags, mDNSBool reuseAddr, int queueLength,
-                                              TCPAcceptedCallback callback, void *context)
-{
-    TCPListener *ret;
-    int fd = -1;
-
-    if (!mDNSPosixTCPListen(&fd, addrtype, port, addr, reuseAddr, queueLength)) {
-        if (fd != -1) {
-            close(fd);
-        }
-        return mDNSNULL;
-    }
-
-    // Allocate a listener structure
-    ret = (TCPListener *) mDNSPlatformMemAllocateClear(sizeof *ret);
-    if (ret == mDNSNULL)
-    {
-        LogMsg("mDNSPlatformTCPListen: no memory for TCPListener struct.");
-        close(fd);
-        return mDNSNULL;
-    }
-    ret->fd = fd;
-    ret->callback = callback;
-    ret->context = context;
-    ret->socketFlags = socketFlags;
-
-    // Watch for incoming data
-    KQueueSet(ret->fd, EV_ADD, EVFILT_READ, &ret->kqEntry);
-    ret->kqEntry.KQcallback = tcpListenCallback;
-    ret->kqEntry.KQcontext  = ret;
-    ret->kqEntry.KQtask     = "mDNSPlatformTCPListen";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    ret->kqEntry.readSource = mDNSNULL;
-    ret->kqEntry.writeSource = mDNSNULL;
-    ret->kqEntry.fdClosed = mDNSfalse;
-#endif
-    return ret;
-}
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-    mDNSu16 port;
-
-    port = -1;
-    if (sock)
-    {
-        port = sock->ss.port.NotAnInteger;
-    }
-    return port;
-}
-
-mDNSlocal void CloseSocketSet(KQSocketSet *ss)
-{
-    if (ss->sktv4 != -1)
-    {
-        mDNSPlatformCloseFD(&ss->kqsv4,  ss->sktv4);
-        ss->sktv4 = -1;
-    }
-    if (ss->sktv6 != -1)
-    {
-        mDNSPlatformCloseFD(&ss->kqsv6,  ss->sktv6);
-        ss->sktv6 = -1;
-    }
-    if (ss->closeFlag) *ss->closeFlag = 1;
-}
-
-mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
-{
-    if (sock)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (sock->tlsContext)
-        {
-            if (sock->handshake == handshake_in_progress) // SSLHandshake thread using this sock (esp. tlsContext)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformTCPCloseConnection: called while handshake in progress");
-                // When we come back from SSLHandshake, we will notice that a close was here and
-                // call this function again which will do the cleanup then.
-                sock->handshake = handshake_to_be_closed;
-                return;
-            }
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-            SSLClose(sock->tlsContext);
-            MDNS_DISPOSE_CF_OBJECT(sock->tlsContext);
-        }
-#pragma clang diagnostic pop
-#endif /* NO_SECURITYFRAMEWORK */
-        if (sock->fd != -1) {
-            shutdown(sock->fd, 2);
-            mDNSPlatformCloseFD(&sock->kqEntry, sock->fd);
-            sock->fd = -1;
-        }
-
-        freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
-    }
-}
-
-mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
-{
-    ssize_t nread = 0;
-    *closed = mDNSfalse;
-
-    // We can get here if the caller set up a TCP connection but didn't check the status when it got the
-    // callback.
-    if (!sock->connected) {
-        return mStatus_DefunctConnection;
-    }
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
-        else if (sock->handshake == handshake_in_progress) return 0;
-        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-
-        //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        mStatus err = SSLRead(sock->tlsContext, buf, buflen, (size_t *)&nread);
-#pragma clang diagnostic pop
-        //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
-        if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
-        else if (err && err != errSSLWouldBlock)
-        { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
-#else
-        nread = -1;
-        *closed = mDNStrue;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-    else
-    {
-        nread = mDNSPosixReadTCP(sock->fd, buf, buflen, closed);
-    }
-
-    return nread;
-}
-
-mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
-{
-    long nsent;
-
-    if (!sock->connected) {
-        return mStatus_DefunctConnection;
-    }
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        size_t processed;
-        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
-        if (sock->handshake == handshake_in_progress) return 0;
-        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
-#pragma clang diagnostic pop
-
-        if (!err) nsent = (long)processed;
-        else if (err == errSSLWouldBlock) nsent = 0;
-        else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
-#else
-        nsent = -1;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-    else
-    {
-        nsent = mDNSPosixWriteTCP(sock->fd, msg, len);
-    }
-    return nsent;
-}
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
-{
-    return sock->fd;
-}
-
-// This function checks to see if the socket is writable.   It will be writable if the kernel TCP output
-// buffer is less full than TCP_NOTSENT_LOWAT.   This should be half or less of the actual kernel buffer
-// size.   This check is done in cases where data should be written if there's space, for example in the
-// Discovery Relay code, where we may be receiving mDNS messages at arbitrary times, and generally there
-// should be buffer space to relay them, but in exceptional cases there might not be.   In this case it's
-
-mDNSexport mDNSBool mDNSPlatformTCPWritable(TCPSocket *sock)
-{
-    int kfd = kqueue();
-    struct kevent kin, kout;
-    int count;
-    struct timespec ts;
-
-    if (kfd < 0)
-    {
-        LogMsg("ERROR: kqueue failed: %m");
-        return mDNSfalse;
-    }
-    ts.tv_sec = 0;
-    ts.tv_nsec = 0;
-    EV_SET(&kin, sock->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
-    count = kevent(kfd, &kin, 1, &kout, 1, &ts);
-    close(kfd);
-    if (count == 1 && (int)kout.ident == sock->fd && kout.filter == EVFILT_WRITE)
-    {
-        return mDNStrue;
-    }
-    return mDNSfalse;
-}
-
-// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
-// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
-{
-    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
-    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
-    const int on = 1;
-    const int twofivefive = 255;
-    mStatus err = mStatus_NoError;
-    char *errstr = mDNSNULL;
-    const int mtu = 0;
-    int saved_errno;
-
-    cp->closeFlag = mDNSNULL;
-
-    int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
-    if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno));return(skt); }
-
-    // set default traffic class
-    setTrafficClass(skt, mDNSfalse);
-
-#ifdef SO_RECV_ANYIF
-    // Enable inbound packets on IFEF_AWDL interface.
-    // Only done for multicast sockets, since we don't expect unicast socket operations
-    // on the IFEF_AWDL interface. Operation is a no-op for other interface types.
-    if (mDNSSameIPPort(port, MulticastDNSPort))
-    {
-        err = setsockopt(skt, SOL_SOCKET, SO_RECV_ANYIF, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - SO_RECV_ANYIF"; goto fail; }
-    }
-#endif // SO_RECV_ANYIF
-
-    // ... with a shared UDP port, if it's for multicast receiving
-    if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort))
-    {
-        err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
-    }
-
-    // Don't want to wake from sleep for inbound packets on the mDNS sockets
-    if (mDNSSameIPPort(port, MulticastDNSPort))
-    {
-        int nowake = 1;
-        if (setsockopt(skt, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
-            LogInfo("SetupSocket: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
-    }
-
-    if (sa_family == AF_INET)
-    {
-        // We want to receive destination addresses
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
-
-        // We want to receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
-
-        // We want to receive packet TTL value so we can check it
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IP_RECVTTL"; goto fail; }
-
-        // Send unicast packets with TTL 255
-        err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
-
-        // And multicast packets with TTL 255 too
-        err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
-
-        // And start listening for packets
-        struct sockaddr_in listening_sockaddr;
-        listening_sockaddr.sin_family      = AF_INET;
-        listening_sockaddr.sin_port        = port.NotAnInteger;     // Pass in opaque ID without any byte swapping
-        listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllHosts_v4.NotAnInteger : 0;
-        err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
-        if (err) { errstr = "bind"; goto fail; }
-        if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
-    }
-    else if (sa_family == AF_INET6)
-    {
-        // NAT-PMP Announcements make no sense on IPv6, and we don't support IPv6 for PCP, so bail early w/o error
-        if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort; close(skt); return mStatus_NoError; }
-
-        // We want to receive destination addresses and receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_RECVPKTINFO"; goto fail; }
-
-        // We want to receive packet hop count value so we can check it
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_RECVHOPLIMIT"; goto fail; }
-
-        // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
-        // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
-
-        // Send unicast packets with TTL 255
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
-
-        // And multicast packets with TTL 255 too
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
-
-        // Want to receive our own packets
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
-
-        // Disable default option to send mDNSv6 packets at min IPv6 MTU: RFC 3542, Sec 11
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &mtu, sizeof(mtu));
-        if (err < 0) // Since it is an optimization if we fail just log the err, no need to close the skt
-            LogMsg("SetupSocket: setsockopt - IPV6_USE_MIN_MTU: IP6PO_MINMTU_DISABLE socket %d err %d errno %d (%s)",
-                    skt, err, errno, strerror(errno));
-
-        // And start listening for packets
-        struct sockaddr_in6 listening_sockaddr6;
-        mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
-        listening_sockaddr6.sin6_len         = sizeof(listening_sockaddr6);
-        listening_sockaddr6.sin6_family      = AF_INET6;
-        listening_sockaddr6.sin6_port        = port.NotAnInteger;       // Pass in opaque ID without any byte swapping
-        listening_sockaddr6.sin6_flowinfo    = 0;
-        listening_sockaddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
-        listening_sockaddr6.sin6_scope_id    = 0;
-        err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
-        if (err) { errstr = "bind"; goto fail; }
-        if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
-    }
-
-    fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
-    fcntl(skt, F_SETFD, 1); // set close-on-exec
-    *s = skt;
-    k->KQcallback = myKQSocketCallBack;
-    k->KQcontext  = cp;
-    k->KQtask     = "UDP packet reception";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    k->readSource = mDNSNULL;
-    k->writeSource = mDNSNULL;
-    k->fdClosed = mDNSfalse;
-#endif
-    KQueueSet(*s, EV_ADD, EVFILT_READ, k);
-
-    return(mStatus_NoError);
-
-fail:
-    saved_errno = errno;
-    // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
-    if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
-        LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, saved_errno, strerror(saved_errno));
-
-    // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
-    if (!strcmp(errstr, "bind") && saved_errno == EADDRINUSE)
-    {
-        err = EADDRINUSE;
-        if (mDNSSameIPPort(port, MulticastDNSPort))
-            NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
-                               "Congratulations, you've reproduced an elusive bug.\r"
-                               "Please contact the current assignee of <rdar://problem/3814904>.\r"
-                               "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
-                               "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
-    }
-
-    mDNSPlatformCloseFD(k, skt);
-    return(err);
-}
-
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport)
-{
-    mStatus err;
-    mDNSIPPort port = requestedport;
-    mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
-    int i = 10000; // Try at most 10000 times to get a unique random port
-    UDPSocket *p = (UDPSocket *) callocL("UDPSocket", sizeof(*p));
-    if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
-    p->ss.port  = zeroIPPort;
-    p->ss.m     = &mDNSStorage;
-    p->ss.sktv4 = -1;
-    p->ss.sktv6 = -1;
-    p->ss.proxy = mDNSfalse;
-
-    do
-    {
-        // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
-        if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
-        err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
-        if (!err)
-        {
-            err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
-            if (err) { mDNSPlatformCloseFD(&p->ss.kqsv4, p->ss.sktv4); p->ss.sktv4 = -1; }
-        }
-        i--;
-    } while (err == EADDRINUSE && randomizePort && i);
-
-    if (err)
-    {
-        // In customer builds we don't want to log failures with port 5351, because this is a known issue
-        // of failing to bind to this port when Internet Sharing has already bound to it
-        // We also don't want to log about port 5350, due to a known bug when some other
-        // process is bound to it.
-        if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
-            LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
-        else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
-        freeL("UDPSocket", p);
-        return(mDNSNULL);
-    }
-    return(p);
-}
-
-#ifdef UNIT_TEST
-UNITTEST_UDPCLOSE
-#else
-mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
-{
-    CloseSocketSet(&sock->ss);
-    freeL("UDPSocket", sock);
-}
-#endif
-
-mDNSexport mDNSBool mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock)
-{
-    return (sock->ss.sktv4EOF || sock->ss.sktv6EOF);
-}
-
-// MARK: - BPF Raw packet sending/receiving
-
-
-// MARK: - Key Management
-
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal CFArrayRef CopyCertChain(SecIdentityRef identity)
-{
-    CFMutableArrayRef certChain = NULL;
-    if (!identity) { LogMsg("CopyCertChain: identity is NULL"); return(NULL); }
-    SecCertificateRef cert;
-    OSStatus err = SecIdentityCopyCertificate(identity, &cert);
-    if (err || !cert) LogMsg("CopyCertChain: SecIdentityCopyCertificate() returned %d", (int) err);
-    else
-    {
-        SecPolicySearchRef searchRef;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
-#pragma clang diagnostic pop
-       if (err || !searchRef) LogMsg("CopyCertChain: SecPolicySearchCreate() returned %d", (int) err);
-        else
-        {
-            SecPolicyRef policy;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-            err = SecPolicySearchCopyNext(searchRef, &policy);
-#pragma clang diagnostic pop
-            if (err || !policy) LogMsg("CopyCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
-            else
-            {
-                CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
-                if (!wrappedCert) LogMsg("CopyCertChain: wrappedCert is NULL");
-                else
-                {
-                    SecTrustRef trust;
-                    err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
-                    if (err || !trust) LogMsg("CopyCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
-                    else
-                    {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#pragma clang diagnostic ignored "-Wnonnull"
-                        err = SecTrustEvaluate(trust, NULL);
-#pragma clang diagnostic pop
-                        if (err) LogMsg("CopyCertChain: SecTrustEvaluate() returned %d", (int) err);
-                        else
-                        {
-                            CFArrayRef rawCertChain;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-                            CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-                            err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
-#pragma clang diagnostic pop
-                            if (err || !rawCertChain || !statusChain) LogMsg("CopyCertChain: SecTrustGetResult() returned %d", (int) err);
-                            else
-                            {
-                                certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
-                                if (!certChain) LogMsg("CopyCertChain: certChain is NULL");
-                                else
-                                {
-                                    // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
-                                    // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
-                                    CFArraySetValueAtIndex(certChain, 0, identity);
-                                    // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
-                                    if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
-                                }
-                                MDNS_DISPOSE_CF_OBJECT(rawCertChain);
-                                // Do not free statusChain:
-                                // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
-                                // certChain: Call the CFRelease function to release this object when you are finished with it.
-                                // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
-                            }
-                        }
-                        MDNS_DISPOSE_CF_OBJECT(trust);
-                    }
-                    MDNS_DISPOSE_CF_OBJECT(wrappedCert);
-                }
-                MDNS_DISPOSE_CF_OBJECT(policy);
-            }
-            MDNS_DISPOSE_CF_OBJECT(searchRef);
-        }
-        MDNS_DISPOSE_CF_OBJECT(cert);
-    }
-    return certChain;
-}
-#endif /* NO_SECURITYFRAMEWORK */
-
-mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
-{
-#ifdef NO_SECURITYFRAMEWORK
-    return mStatus_UnsupportedErr;
-#else
-    SecIdentityRef identity = nil;
-    SecIdentitySearchRef srchRef = nil;
-    OSStatus err;
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    // search for "any" identity matching specified key use
-    // In this app, we expect there to be exactly one
-    err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
-    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
-
-    err = SecIdentitySearchCopyNext(srchRef, &identity);
-    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
-#pragma clang diagnostic pop
-
-    if (CFGetTypeID(identity) != SecIdentityGetTypeID())
-    { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
-
-    // Found one. Call CopyCertChain to create the correct certificate chain.
-    ServerCerts = CopyCertChain(identity);
-    if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: CopyCertChain error"); return mStatus_UnknownErr; }
-
-    return mStatus_NoError;
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-mDNSexport void  mDNSPlatformTLSTearDownCerts(void)
-{
-#ifndef NO_SECURITYFRAMEWORK
-    MDNS_DISPOSE_CF_OBJECT(ServerCerts);
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-
-mDNSlocal void mDNSDomainLabelFromCFString(CFStringRef cfs, domainlabel *const namelabel);
-
-// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
-mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
-{
-    CFStringEncoding encoding = kCFStringEncodingUTF8;
-    CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
-
-    if (cfs == mDNSNULL) {
-        return;
-    }
-
-    mDNSDomainLabelFromCFString(cfs, namelabel);
-
-    MDNS_DISPOSE_CF_OBJECT(cfs);
-}
-
-mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
-{
-    CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
-
-    if (cfs == mDNSNULL) {
-        return;
-    }
-
-    mDNSDomainLabelFromCFString(cfs, namelabel);
-
-    MDNS_DISPOSE_CF_OBJECT(cfs);
-}
-
-mDNSlocal void mDNSDomainLabelFromCFString(CFStringRef cfs, domainlabel *const namelabel)
-{
-    CFIndex num_of_bytes_write = 0;
-    CFStringGetBytes(cfs, CFRangeMake(0, CFStringGetLength(cfs)), kCFStringEncodingUTF8, 0, FALSE, namelabel->c + 1, sizeof(*namelabel) - 1, &num_of_bytes_write);
-    namelabel->c[0] = num_of_bytes_write;
-}
-
-mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
-{
-    mDNSs32 val;
-    CFNumberRef state = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("Enabled"));
-    if (state == NULL) return mDNSfalse;
-    if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
-    { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
-    return val ? mDNStrue : mDNSfalse;
-}
-
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
-{
-    if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
-
-    if (sa->sa_family == AF_INET)
-    {
-        const struct sockaddr_in *const ifa_addr = (const struct sockaddr_in *)sa;
-        ip->type = mDNSAddrType_IPv4;
-        ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
-        return(mStatus_NoError);
-    }
-
-    if (sa->sa_family == AF_INET6)
-    {
-        const struct sockaddr_in6 *const ifa_addr = (const struct sockaddr_in6 *)sa;
-        ip->type = mDNSAddrType_IPv6;
-        memcpy(ip->ip.v6.b, ifa_addr->sin6_addr.s6_addr, sizeof(ip->ip.v6.b));
-        // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
-        // value into the second word of the IPv6 link-local address, so they can just
-        // pass around IPv6 address structures instead of full sockaddr_in6 structures.
-        // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
-        // To work around this we always whack the second word of any IPv6 link-local address back to zero.
-        if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr))
-        {
-            ip->ip.v6.w[1] = 0;
-        }
-        return(mStatus_NoError);
-    }
-
-    LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
-    return(mStatus_Invalid);
-}
-
-mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
-{
-    mDNSEthAddr eth = zeroEthAddr;
-
-    CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
-    if (entityname)
-    {
-        CFDictionaryRef dict = SCDynamicStoreCopyValue(NULL, entityname);
-        if (dict)
-        {
-            CFRange range = { 0, 6 };       // Offset, length
-            CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
-            if (data && CFDataGetLength(data) == 6)
-                CFDataGetBytes(data, range, eth.b);
-            MDNS_DISPOSE_CF_OBJECT(dict);
-        }
-        MDNS_DISPOSE_CF_OBJECT(entityname);
-    }
-
-    return(eth);
-}
-
-mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
-{
-    struct ifaddrs *ifa;
-    for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
-        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
-        {
-            const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
-            if (sdl->sdl_index == ifindex)
-            { mDNSPlatformMemCopy(eth->b, sdl->sdl_data + sdl->sdl_nlen, 6); return 0; }
-        }
-    *eth = zeroEthAddr;
-    return -1;
-}
-
-#ifndef SIOCGIFWAKEFLAGS
-#define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
-#endif
-
-#ifndef IF_WAKE_ON_MAGIC_PACKET
-#define IF_WAKE_ON_MAGIC_PACKET 0x01
-#endif
-
-#ifndef ifr_wake_flags
-#define ifr_wake_flags ifr_ifru.ifru_intval
-#endif
-
-mDNSlocal
-kern_return_t
-RegistryEntrySearchCFPropertyAndIOObject( io_registry_entry_t     entry,
-                                          const io_name_t         plane,
-                                          CFStringRef             keystr,
-                                          CFTypeRef *             outProperty,
-                                          io_registry_entry_t *   outEntry)
-{
-    kern_return_t       kr;
-
-    IOObjectRetain(entry);
-    while (entry)
-    {
-        CFTypeRef ref = IORegistryEntryCreateCFProperty(entry, keystr, kCFAllocatorDefault, mDNSNULL);
-        if (ref)
-        {
-            if (outProperty) *outProperty = ref;
-            else             MDNS_DISPOSE_CF_OBJECT(ref);
-            break;
-        }
-        io_registry_entry_t parent;
-        kr = IORegistryEntryGetParentEntry(entry, plane, &parent);
-        if (kr != KERN_SUCCESS) parent = mDNSNULL;
-        IOObjectRelease(entry);
-        entry = parent;
-    }
-    if (!entry)          kr = kIOReturnNoDevice;
-    else
-    {
-        if (outEntry)   *outEntry = entry;
-        else            IOObjectRelease(entry);
-        kr = KERN_SUCCESS;
-    }
-    return(kr);
-}
-
-mDNSlocal mDNSBool  CheckInterfaceSupport(NetworkInterfaceInfo *const intf, const char *key)
-{
-    io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOBSDNameMatching(kIOMainPortDefault, 0, intf->ifname));
-    if (!service)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, "CheckInterfaceSupport: No service for interface " PUB_S , intf->ifname);
-        return mDNSfalse;
-    }
-    mDNSBool    ret    = mDNSfalse;
-
-    CFStringRef keystr =  CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
-    kern_return_t kr = RegistryEntrySearchCFPropertyAndIOObject(service, kIOServicePlane, keystr, mDNSNULL, mDNSNULL);
-    MDNS_DISPOSE_CF_OBJECT(keystr);
-    if (kr == KERN_SUCCESS) ret = mDNStrue;
-    else
-    {
-        io_name_t n1;
-        IOObjectGetClass(service, n1);
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT, "CheckInterfaceSupport: No " PUB_S " for interface " PUB_S "/" PUB_S " kr 0x%X",
-            key, intf->ifname, n1, kr);
-        ret = mDNSfalse;
-    }
-
-    IOObjectRelease(service);
-    return ret;
-}
-
-
-#if !TARGET_OS_WATCH
-mDNSlocal  mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf)
-{
-    return CheckInterfaceSupport(intf, mDNS_IOREG_KA_KEY);
-}
-#endif
-
-mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
-{
-#if TARGET_OS_WATCH
-    (void) i;   // unused
-    return(mDNSfalse);
-#else
-    // We only use Sleep Proxy Service on multicast-capable interfaces, except loopback and D2D.
-    if (!MulticastInterface(i) || (i->ifa_flags & IFF_LOOPBACK) || i->D2DInterface)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEBUG,
-            "NetWakeInterface: returning false for " PUB_S, i->ifinfo.ifname);
-        return(mDNSfalse);
-    }
-
-    // If the interface supports TCPKeepalive, it is capable of waking up for a magic packet
-    // This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability
-    // when the power source is not AC Power.
-    if (InterfaceSupportsKeepAlive(&i->ifinfo))
-    {
-        LogSPS("NetWakeInterface: %s supports TCP Keepalive returning true", i->ifinfo.ifname);
-        return mDNStrue;
-    }
-
-    int s = socket(AF_INET, SOCK_DGRAM, 0);
-    if (s < 0) { LogMsg("NetWakeInterface socket failed %s error %d errno %d (%s)", i->ifinfo.ifname, s, errno, strerror(errno)); return(mDNSfalse); }
-
-    struct ifreq ifr;
-    mdns_strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
-    if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
-    {
-        const int ioctl_errno = errno;
-        // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
-        // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
-        // error code is being returned from the kernel, we need to use the kernel version.
-        #define KERNEL_EOPNOTSUPP 102
-        if (ioctl_errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
-            LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, ioctl_errno, strerror(ioctl_errno));
-        // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
-        // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
-        ifr.ifr_wake_flags = (ioctl_errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
-    }
-
-    close(s);
-
-    // ifr.ifr_wake_flags = IF_WAKE_ON_MAGIC_PACKET;    // For testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
-
-    LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT,
-        "NetWakeInterface: " PUB_S " " PRI_IP_ADDR " " PUB_S " WOMP",
-        i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
-
-    return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
-#endif  // TARGET_OS_WATCH
-}
-
-mDNSlocal u_int64_t getExtendedFlags(const char *ifa_name)
-{
-    int sockFD;
-    struct ifreq ifr;
-
-    sockFD = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sockFD < 0)
-    {
-        LogMsg("getExtendedFlags: socket() call failed, errno = %d (%s)", errno, strerror(errno));
-        return 0;
-    }
-
-    ifr.ifr_addr.sa_family = AF_INET;
-    mdns_strlcpy(ifr.ifr_name, ifa_name, sizeof(ifr.ifr_name));
-
-    if (ioctl(sockFD, SIOCGIFEFLAGS, (caddr_t)&ifr) == -1)
-    {
-        LogMsg("getExtendedFlags: SIOCGIFEFLAGS failed for %s, errno = %d (%s)", ifa_name, errno, strerror(errno));
-        ifr.ifr_eflags = 0;
-    }
-
-    close(sockFD);
-    return ifr.ifr_eflags;
-}
-
-mDNSlocal mDNSBool isExcludedInterface(int sockFD, char * ifa_name)
-{
-    struct ifreq ifr;
-
-    // llw0 interface is excluded from Bonjour discovery.
-    // There currently is no interface attributed based way to identify these interfaces
-    // until rdar://problem/47933782 is addressed.
-    if (strncmp(ifa_name, "llw", 3) == 0)
-    {
-        LogMsg("isExcludedInterface: excluding %s", ifa_name);
-        return mDNStrue;
-    }
-
-    // Coprocessor interfaces are also excluded.
-    if (sockFD < 0)
-    {
-        LogMsg("isExcludedInterface: invalid socket FD passed: %d", sockFD);
-        return mDNSfalse;
-    }
-
-    memset(&ifr, 0, sizeof(struct ifreq));
-    mdns_strlcpy(ifr.ifr_name, ifa_name, sizeof(ifr.ifr_name));
-
-    if (ioctl(sockFD, SIOCGIFFUNCTIONALTYPE, (caddr_t)&ifr) == -1)
-    {
-        LogMsg("isExcludedInterface: SIOCGIFFUNCTIONALTYPE failed, errno = %d (%s)", errno, strerror(errno));
-        return mDNSfalse;
-    }
-
-    if (ifr.ifr_functional_type == IFRTYPE_FUNCTIONAL_INTCOPROC)
-    {
-        LogMsg("isExcludedInterface: excluding coprocessor interface %s", ifa_name);
-        return mDNStrue;
-    }
-    else
-        return mDNSfalse;
-}
-
-
-// Returns pointer to newly created NetworkInterfaceInfoOSX object, or
-// pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
-// may return NULL if out of memory (unlikely) or parameters are invalid for some reason
-// (e.g. sa_family not AF_INET or AF_INET6)
-
-mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(const struct ifaddrs *ifa, const mDNSs32 utc)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSu32 scope_id  = if_nametoindex(ifa->ifa_name);
-    mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
-    u_int64_t   eflags = getExtendedFlags(ifa->ifa_name);
-
-    mDNSAddr ip, mask;
-    if (SetupAddr(&ip,   ifa->ifa_addr   ) != mStatus_NoError) return(NULL);
-    if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
-
-    NetworkInterfaceInfoOSX **p;
-    for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
-    {
-        if (scope_id == (*p)->scope_id &&
-            mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
-            mDNSSameEthAddress(&bssid, &(*p)->BSSID))
-        {
-            debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p, ifname before %s, after %s", scope_id, &bssid, &ip, *p, (*p)->ifinfo.ifname, ifa->ifa_name);
-            if ((*p)->Exists)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                    "Ignoring attempt to re-add interface (" PUB_S ", " PRI_IP_ADDR ") already marked as existing",
-                    ifa->ifa_name, &ip);
-                return(*p);
-            }
-            // The name should be updated to the new name so that we don't report a wrong name in our SIGINFO output.
-            // When interfaces are created with same MAC address, kernel resurrects the old interface.
-            // Even though the interface index is the same (which should be sufficient), when we receive a UDP packet
-            // we get the corresponding name for the interface index on which the packet was received and check against
-            // the InterfaceList for a matching name. So, keep the name in sync.
-            mdns_strlcpy((*p)->ifinfo.ifname, ifa->ifa_name, sizeof((*p)->ifinfo.ifname));
-
-            // Determine if multicast state has changed.
-            const mDNSBool txrx = MulticastInterface(*p);
-            if ((*p)->ifinfo.McastTxRx != txrx)
-            {
-                (*p)->ifinfo.McastTxRx = txrx;
-                (*p)->Exists = MulticastStateChanged; // State change; need to deregister and reregister this interface
-            }
-            else
-                 (*p)->Exists = mDNStrue;
-
-            // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
-            if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc;
-
-            // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
-            // we may need to start or stop or sleep proxy browse operation
-            const mDNSBool NetWake = NetWakeInterface(*p);
-            if ((*p)->ifinfo.NetWake != NetWake)
-            {
-                (*p)->ifinfo.NetWake = NetWake;
-                // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
-                // If this interface is not already registered (i.e. it's a dormant interface we had in our list
-                // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
-                // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
-                if ((*p)->Registered)
-                {
-                    mDNS_Lock(m);
-                    if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
-                    else         mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
-                    mDNS_Unlock(m);
-                }
-            }
-            // Reset the flag if it has changed this time.
-            (*p)->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
-
-            return(*p);
-        }
-    }
-    NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *) callocL("NetworkInterfaceInfoOSX", sizeof(*i));
-    debugf("AddInterfaceToList: Making   new   interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
-    if (!i) return(mDNSNULL);
-    i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
-    i->ifinfo.ip          = ip;
-    i->ifinfo.mask        = mask;
-    mdns_strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
-    i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
-    // We can be configured to disable multicast advertisement, but we want to to support
-    // local-only services, which need a loopback address record.
-    i->ifinfo.Advertise   = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
-    i->ifinfo.Loopback    = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse;
-    i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
-
-    // Setting DirectLink indicates we can do the optimization of skipping the probe phase
-    // for the interface address records since they should be unique.
-    // Unfortunately, the legacy p2p* interfaces do not set the IFEF_LOCALNET_PRIVATE
-    // or IFEF_DIRECTLINK flags, so we have to match against the name.
-    i->ifinfo.DirectLink = mDNSFalse;
-
-    if (i->ifinfo.DirectLink)
-        LogInfo("AddInterfaceToList: DirectLink set for %s", ifa->ifa_name);
-
-    i->next            = mDNSNULL;
-    i->m               = m;
-    i->Exists          = mDNStrue;
-    i->Flashing        = mDNSfalse;
-    i->Occulting       = mDNSfalse;
-
-    i->D2DInterface    = ((eflags & IFEF_LOCALNET_PRIVATE) || (strncmp(i->ifinfo.ifname, "p2p", 3) == 0)) ? mDNStrue: mDNSfalse;
-    if (i->D2DInterface)
-        LogInfo("AddInterfaceToList: D2DInterface set for %s", ifa->ifa_name);
-    i->isAWDL          = (eflags & IFEF_AWDL)      ? mDNStrue: mDNSfalse;
-
-    if (eflags & IFEF_AWDL)
-    {
-        // Set SupportsUnicastMDNSResponse false for the AWDL interface since unicast reserves
-        // limited AWDL resources so we don't set the kDNSQClass_UnicastResponse bit in
-        // Bonjour requests over the AWDL interface.
-        i->ifinfo.SupportsUnicastMDNSResponse = mDNSfalse;
-    }
-    else
-    {
-        i->ifinfo.SupportsUnicastMDNSResponse = mDNStrue;
-    }
-    i->AppearanceTime  = utc;       // Brand new interface; AppearanceTime is now
-    i->LastSeen        = utc;
-    i->ifa_flags       = ifa->ifa_flags;
-    i->scope_id        = scope_id;
-    i->BSSID           = bssid;
-    i->sa_family       = ifa->ifa_addr->sa_family;
-    i->BPF_fd          = -1;
-    i->BPF_mcfd        = -1;
-    i->BPF_len         = 0;
-    i->Registered      = mDNSNULL;
-
-    // MulticastInterface() depends on the "m" and "ifa_flags" values being initialized above.
-    i->ifinfo.McastTxRx   = MulticastInterface(i);
-    // Do this AFTER i->BSSID has been set up
-    i->ifinfo.NetWake  = (eflags & IFEF_EXPENSIVE)? mDNSfalse :  NetWakeInterface(i);
-    GetMAC(&i->ifinfo.MAC, scope_id);
-    if (i->ifinfo.NetWake && !i->ifinfo.MAC.l[0])
-        LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i->ifinfo.MAC, scope_id, i->ifinfo.ifname, &ip);
-    i->ift_family = GetIFTFamily(i->ifinfo.ifname, &i->ift_subfamily);
-    // Workaround: For tvOS, never prevent sleep for USB Ethernet interfaces. tvOS instantiates USB Ethernet interfaces
-    // with actual IP addresses even though there aren't always physical network interfaces backing them up. This is a
-    // problem because when an Apple TV wants to sleep, but has outstanding Bonjour services, the mDNS core will typically
-    // not allow sleep in the absence of an in-NIC sleep proxy or remote sleep proxy. Bogus USB Ethernet interfaces
-    // obviously don't have an in-NIC sleep proxy nor connectivity to a remote sleep proxy, so they shouldn't prevent sleep.
-    // Since tvOS devices don't have USB ports to allow customers to plug in USB Ethernet adapters, the best we can
-    // currently do to detect these problematic interfaces is check if they're USB Ethernet interfaces. Also, these bogus
-    // USB Ethernet interfaces are placeholders for when a debug cable is connected, so they're used for special-case
-    // Mac-to-device networks, not ordinary everyday networks that a customer device would use.
-    if (IsAppleTV() && (i->ift_family == IFRTYPE_FAMILY_ETHERNET) && (i->ift_subfamily == IFRTYPE_SUBFAMILY_USB))
-    {
-        i->ifinfo.MustNotPreventSleep = mDNStrue;
-    }
-
-    *p = i;
-    return(i);
-}
-
-// MARK: - Power State & Configuration Change Management
-
-mDNSlocal mStatus ReorderInterfaceList()
-{
-    // Disable Reorder lists till <rdar://problem/30071012> is fixed to prevent spurious name conflicts
-#ifdef PR_30071012_FIXED
-    mDNS *const m = &mDNSStorage;
-    nwi_state_t state = nwi_state_copy();
-
-    if (state == mDNSNULL)
-    {
-        LogMsg("NWI State is NULL!");
-        return (mStatus_Invalid);
-    }
-
-    // Get the count of interfaces
-    mDNSu32 count =  nwi_state_get_interface_names(state, mDNSNULL, 0);
-    if (count == 0)
-    {
-        LogMsg("Unable to get the ordered list of interface names");
-        nwi_state_release(state);
-        return (mStatus_Invalid);
-    }
-
-    // Get the ordered interface list
-    int i;
-    const char *names[count];
-    count = nwi_state_get_interface_names(state, names, count);
-
-    NetworkInterfaceInfo *newList = mDNSNULL;
-    for (i = count-1; i >= 0; i--)
-    {   // Build a new ordered interface list
-        NetworkInterfaceInfo **ptr = &m->HostInterfaces;
-        while (*ptr != mDNSNULL )
-        {
-            if (strcmp((*ptr)->ifname, names[i]) == 0)
-            {
-                NetworkInterfaceInfo *node = *ptr;
-                *ptr = (*ptr)->next;
-                node->next = newList;
-                newList = node;
-            }
-            else
-                ptr = &((*ptr)->next);
-        }
-    }
-
-    // Get to the end of the list
-    NetworkInterfaceInfo *newListEnd = newList;
-    while (newListEnd != mDNSNULL && newListEnd->next != mDNSNULL)
-        newListEnd = newListEnd->next;
-
-    // Add any remaing interfaces to the end of the sorted list
-    if (newListEnd != mDNSNULL)
-        newListEnd->next  = m->HostInterfaces;
-
-    // If we have a valid new list, point to that now
-    if (newList != mDNSNULL)
-        m->HostInterfaces = newList;
-
-    nwi_state_release(state);
-#endif // PR_30071012_FIXED
-    return (mStatus_NoError);
-}
-
-mDNSlocal mStatus UpdateInterfaceList(mDNSs32 utc)
-{
-    mDNS *const m = &mDNSStorage;
-    struct ifaddrs *ifa = myGetIfAddrs(0);
-    char defaultname[64];
-    int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0);
-    if (InfoSocket < 3 && errno != EAFNOSUPPORT)
-        LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
-
-    if (m->SleepState == SleepState_Sleeping) ifa = NULL;
-
-    for (; ifa; ifa = ifa->ifa_next)
-    {
-#if LIST_ALL_INTERFACES
-        if (ifa->ifa_addr)
-        {
-            if (ifa->ifa_addr->sa_family == AF_APPLETALK)
-                LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
-                       ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
-            else if (ifa->ifa_addr->sa_family == AF_LINK)
-                LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
-                       ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
-            else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
-                LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
-                       ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
-        }
-        else
-            LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X ifa_addr is NOT set",
-                   ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags);
-
-        if (!(ifa->ifa_flags & IFF_UP))
-            LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
-                   ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
-                   ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
-        if (!(ifa->ifa_flags & IFF_MULTICAST))
-            LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
-                   ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
-                   ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
-        if (ifa->ifa_flags & IFF_POINTOPOINT)
-            LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
-                   ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
-                   ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
-        if (ifa->ifa_flags & IFF_LOOPBACK)
-            LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
-                   ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
-                   ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
-#endif
-
-        if (!ifa->ifa_addr || isExcludedInterface(InfoSocket, ifa->ifa_name))
-        {
-            continue;
-        }
-
-        if (ifa->ifa_addr->sa_family == AF_LINK)
-        {
-            const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
-            if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == sizeof(m->PrimaryMAC) && mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr))
-            {
-                mDNSPlatformMemCopy(m->PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
-            }
-            const uint64_t eflags = getExtendedFlags(ifa->ifa_name);
-            if ((eflags & IFEF_AWDL) && (!AWDLInterfaceID || !WiFiAwareInterfaceID))
-            {
-                CFStringRef keys[] = { CFSTR(APPLE80211_REGKEY_INTERFACE_NAME) };
-                CFStringRef values[] = { CFStringCreateWithCString(kCFAllocatorDefault, ifa->ifa_name, kCFStringEncodingUTF8) };
-                CFDictionaryRef propertyDictionary[] = { CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
-                keys[0] = CFSTR(kIOPropertyMatchKey);
-                CFDictionaryRef matchingService = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)propertyDictionary, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, matchingService);
-                MDNS_DISPOSE_CF_OBJECT(values[0]);
-                MDNS_DISPOSE_CF_OBJECT(propertyDictionary[0]);
-                if (service != MACH_PORT_NULL)
-                {
-                    CFStringRef role = IORegistryEntryCreateCFProperty(service, CFSTR(APPLE80211_REGKEY_VIRTUAL_IF_ROLE), kCFAllocatorDefault, 0);
-                    if (role && CFGetTypeID(role) == CFStringGetTypeID())
-                    {
-                        if (!AWDLInterfaceID && CFStringCompare(role, CFSTR(APPLE80211_IF_ROLE_STR_AWDL), 0) == kCFCompareEqualTo)
-                        {
-                            AWDLInterfaceID = (mDNSInterfaceID)((uintptr_t)sdl->sdl_index);
-                            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                                      "UpdateInterfaceList: AWDLInterfaceID = %lu", (unsigned long) AWDLInterfaceID);
-                        }
-                        if (!WiFiAwareInterfaceID && CFStringCompare(role, CFSTR(APPLE80211_IF_ROLE_STR_NAN_DISCOVERY_DATA), 0) == kCFCompareEqualTo)
-                        {
-                            WiFiAwareInterfaceID = (mDNSInterfaceID)((uintptr_t)sdl->sdl_index);
-                            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                                      "UpdateInterfaceList: WiFiAwareInstanceID = %lu", (unsigned long) WiFiAwareInterfaceID);
-                        }
-                    }
-                    MDNS_DISPOSE_CF_OBJECT(role);
-                    IOObjectRelease(service);
-                }
-            }
-        }
-
-        if (ifa->ifa_flags & IFF_UP)
-        {
-            if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
-            {
-                if (!ifa->ifa_netmask)
-                {
-                    mDNSAddr ip;
-                    SetupAddr(&ip, ifa->ifa_addr);
-                    LogMsg("UpdateInterfaceList: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
-                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
-                }
-                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
-                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0)
-                {
-                    mDNSAddr ip;
-                    SetupAddr(&ip, ifa->ifa_addr);
-                    LogMsg("UpdateInterfaceList: ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
-                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
-                }
-                // Currently we use a few internal ones like mDNSInterfaceID_LocalOnly etc. that are negative values (0, -1, -2).
-                else if ((int)if_nametoindex(ifa->ifa_name) <= 0)
-                {
-                    LogMsg("UpdateInterfaceList: if_nametoindex returned zero/negative value for %5s(%d)", ifa->ifa_name, if_nametoindex(ifa->ifa_name));
-                }
-                else
-                {
-                    // Make sure ifa_netmask->sa_family is set correctly
-                    // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                    ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
-                    int ifru_flags6 = 0;
-
-                    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
-                    if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
-                    {
-                        struct in6_ifreq ifr6;
-                        mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
-                        mdns_strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
-                        ifr6.ifr_addr = *sin6;
-                        if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
-                            ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
-                        verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
-                    }
-
-                    if (!(ifru_flags6 & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
-                    {
-                        AddInterfaceToList(ifa, utc);
-                    }
-                }
-            }
-        }
-    }
-
-    if (InfoSocket >= 0)
-        close(InfoSocket);
-
-    mDNS_snprintf(defaultname, sizeof(defaultname), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen, HINFO_HWstring,
-                  m->PrimaryMAC.b[0], m->PrimaryMAC.b[1], m->PrimaryMAC.b[2], m->PrimaryMAC.b[3], m->PrimaryMAC.b[4], m->PrimaryMAC.b[5]);
-
-    // Set up the nice label
-    domainlabel nicelabel;
-    nicelabel.c[0] = 0;
-    GetUserSpecifiedFriendlyComputerName(&nicelabel);
-    if (nicelabel.c[0] == 0)
-    {
-        debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
-        MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
-    }
-
-    // Set up the RFC 1034-compliant label
-    domainlabel hostlabel;
-    hostlabel.c[0] = 0;
-    GetUserSpecifiedLocalHostName(&hostlabel);
-    if (hostlabel.c[0] == 0)
-    {
-        debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
-        MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
-    }
-
-    // We use a case-sensitive comparison here because even though changing the capitalization
-    // of the name alone is not significant to DNS, it's still a change from the user's point of view
-    if (SameDomainLabelCS(m->p->usernicelabel.c, nicelabel.c))
-        debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
-    else
-    {
-        if (m->p->usernicelabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
-            LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
-        m->p->usernicelabel = m->nicelabel = nicelabel;
-    }
-
-    if (SameDomainLabelCS(m->p->userhostlabel.c, hostlabel.c))
-        debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
-    else
-    {
-        if (m->p->userhostlabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
-            LogMsg("User updated Local Hostname from “%#s” to “%#s”", m->p->userhostlabel.c, hostlabel.c);
-        m->p->userhostlabel = m->hostlabel = hostlabel;
-        mDNS_SetFQDN(m);
-    }
-
-    return(mStatus_NoError);
-}
-
-// Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
-// Returns -1 if all the one-bits are not contiguous
-mDNSlocal int CountMaskBits(mDNSAddr *mask)
-{
-    int i = 0, bits = 0;
-    int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
-    while (i < bytes)
-    {
-        mDNSu8 b = mask->ip.v6.b[i++];
-        while (b & 0x80) { bits++; b <<= 1; }
-        if (b) return(-1);
-    }
-    while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
-    return(bits);
-}
-
-mDNSlocal void mDNSGroupJoinOrLeave(const int sock, const NetworkInterfaceInfoOSX *const i, const mDNSBool join)
-{
-    int level;
-    struct group_req gr;
-    mDNSPlatformMemZero(&gr, sizeof(gr));
-    gr.gr_interface = i->scope_id;
-    switch (i->sa_family)
-    {
-        case AF_INET: {
-            struct sockaddr_in *const sin = (struct sockaddr_in *)&gr.gr_group;
-            sin->sin_len         = sizeof(*sin);
-            sin->sin_family      = AF_INET;
-            sin->sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-            level = IPPROTO_IP;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, PUB_S "ing mcast group " PUB_IPv4_ADDR " on " PUB_S " (%u)",
-                join ? "Join" : "Leav", &sin->sin_addr.s_addr, i->ifinfo.ifname, i->scope_id);
-            break;
-        }
-        case AF_INET6: {
-            struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)&gr.gr_group;
-            sin6->sin6_len    = sizeof(*sin6);
-            sin6->sin6_family = AF_INET6;
-            memcpy(sin6->sin6_addr.s6_addr, AllDNSLinkGroup_v6.ip.v6.b, sizeof(sin6->sin6_addr.s6_addr));
-            level = IPPROTO_IPV6;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, PUB_S "ing mcast group " PUB_IPv6_ADDR " on " PUB_S " (%u)",
-                join ? "Join" : "Leav", sin6->sin6_addr.s6_addr, i->ifinfo.ifname, i->scope_id);
-            break;
-        }
-        default:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "Cannot " PUB_S " mcast group on " PUB_S " (%u) for unrecognized address family %d",
-                join ? "join" : "leave", i->ifinfo.ifname, i->scope_id, i->sa_family);
-            goto exit;
-    }
-    const int err = setsockopt(sock, level, join ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, &gr, sizeof(gr));
-    if (err)
-    {
-        // When joining a group, ignore EADDRINUSE errors, which can ocur when the same group is joined twice.
-        // When leaving a group, ignore EADDRNOTAVAIL errors, which can occur when an interface is no longer present.
-        const int opterrno = errno;
-        if ((join && (opterrno != EADDRINUSE)) || (!join && (opterrno != EADDRNOTAVAIL)))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "setsockopt - IPPROTO_IP" PUB_S "/MCAST_" PUB_S "_GROUP error %d errno %d (%s) on " PUB_S " (%u)",
-                (level == IPPROTO_IPV6) ? "V6" : "", join ? "JOIN" : "LEAVE", err, opterrno, strerror(opterrno),
-                i->ifinfo.ifname, i->scope_id);
-        }
-    }
-
-exit:
-    return;
-}
-#define mDNSGroupJoin(SOCK, INTERFACE)  mDNSGroupJoinOrLeave(SOCK, INTERFACE, mDNStrue)
-#define mDNSGroupLeave(SOCK, INTERFACE) mDNSGroupJoinOrLeave(SOCK, INTERFACE, mDNSfalse)
-
-// Returns count of non-link local V4 addresses registered (why? -- SC)
-mDNSlocal int SetupActiveInterfaces(mDNSs32 utc)
-{
-    mDNS *const m = &mDNSStorage;
-    NetworkInterfaceInfoOSX *i;
-    int count = 0;
-
-    // Recalculate SuppressProbes time based on the current set of active interfaces.
-    m->SuppressProbes = 0;
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->Exists)
-        {
-            NetworkInterfaceInfo *const n = &i->ifinfo;
-            NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(i->ifinfo.ifname, AF_UNSPEC);
-
-            if (i->Registered && i->Registered != primary)  // Sanity check
-            {
-                LogMsg("SetupActiveInterfaces ERROR! n->Registered %p != primary %p", i->Registered, primary);
-                i->Registered = mDNSNULL;
-            }
-
-            if (!i->Registered)
-            {
-                InterfaceActivationSpeed activationSpeed;
-
-                // Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
-                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
-                // If i->Registered is NOT set, then we haven't registered it and we should not try to deregister it.
-                i->Registered = primary;
-
-                // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
-                // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
-                // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
-                i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
-
-                // The "p2p*" interfaces used for legacy AirDrop reuse the scope-id, MAC address and the IP address
-                // every time a new interface is created. We think it is a duplicate and hence consider it
-                // as flashing and occulting, that is, flapping. If an interface is marked as flapping,
-                // mDNS_RegisterInterface() changes the probe delay from 1/2 second to 5 seconds and
-                // logs a warning message to system.log noting frequent interface transitions.
-                // The same logic applies when the IFEF_DIRECTLINK flag is set on the interface.
-                if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
-                {
-                    activationSpeed = FastActivation;
-                    LogInfo("SetupActiveInterfaces: %s DirectLink interface registering", i->ifinfo.ifname);
-                }
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-                else if (i->Flashing && i->Occulting)
-                {
-                    activationSpeed = SlowActivation;
-                }
-#endif
-                else
-                {
-                    activationSpeed = NormalActivation;
-                }
-
-                mDNS_RegisterInterface(m, n, activationSpeed);
-
-                if (!mDNSAddressIsLinkLocal(&n->ip)) count++;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "SetupActiveInterfaces: Registered " PUB_S " (%u) BSSID " PRI_MAC_ADDR " Struct addr %p, primary %p,"
-                        " " PRI_IP_ADDR "/%d" PUB_S PUB_S PUB_S,
-                        i->ifinfo.ifname, i->scope_id, &i->BSSID, i, primary, &n->ip, CountMaskBits(&n->mask),
-                        i->Flashing        ? " (Flashing)"  : "",
-                        i->Occulting       ? " (Occulting)" : "",
-                        n->InterfaceActive ? " (Primary)"   : "");
-
-                if (!n->McastTxRx)
-                {
-                    debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip);
-                }
-                else
-                {
-                    if ((i->sa_family == AF_INET) || (i->sa_family == AF_INET6))
-                    {
-                        // If this is our *first* address family instance for this interface name, we need to do a leave first,
-                        // before trying to join the group, to clear out stale kernel state which may be lingering.
-                        // In particular, this happens with removable network interfaces like USB Ethernet adapters -- the kernel has stale state
-                        // from the last time the USB Ethernet adapter was connected, and part of the kernel thinks we've already joined the group
-                        // on that interface (so we get EADDRINUSE when we try to join again) but a different part of the kernel thinks we haven't
-                        // joined the group (so we receive no multicasts). Doing a leave before joining seems to flush the stale state.
-                        // Also, trying to make the code leave the group when the adapter is removed doesn't work either,
-                        // because by the time we get the configuration change notification, the interface is already gone,
-                        // so attempts to unsubscribe fail with EADDRNOTAVAIL (errno 49 "Can't assign requested address").
-                        // <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
-                        const int sock = (i->sa_family == AF_INET) ? m->p->permanentsockets.sktv4 : m->p->permanentsockets.sktv6;
-                        if (SearchForInterfaceByName(i->ifinfo.ifname, i->sa_family) == i)
-                        {
-                            mDNSGroupLeave(sock, i);
-                        }
-                        mDNSGroupJoin(sock, i);
-                    }
-                }
-            }
-        }
-
-    return count;
-}
-
-mDNSlocal void MarkAllInterfacesInactive(mDNSs32 utc)
-{
-    NetworkInterfaceInfoOSX *i;
-    for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-    {
-        if (i->Exists) i->LastSeen = utc;
-        i->Exists = mDNSfalse;
-    }
-}
-
-// Returns count of non-link local V4 addresses deregistered (why? -- SC)
-mDNSlocal int ClearInactiveInterfaces(mDNSs32 utc)
-{
-    mDNS *const m = &mDNSStorage;
-    // First pass:
-    // If an interface is going away, then deregister this from the mDNSCore.
-    // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
-    // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
-    // it refers to has gone away we'll crash.
-    NetworkInterfaceInfoOSX *i;
-    int count = 0;
-    for (i = m->p->InterfaceList; i; i = i->next)
-    {
-        // If this interface is no longer active, or its InterfaceID is changing, deregister it
-        NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(i->ifinfo.ifname, AF_UNSPEC);
-        if (i->Registered)
-        {
-            if (i->Exists == 0 || i->Exists == MulticastStateChanged || i->Registered != primary)
-            {
-                InterfaceActivationSpeed activationSpeed;
-
-                i->Flashing = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->AppearanceTime < 60);
-                LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ClearInactiveInterfaces: Deregistering " PUB_S "(%u) " PRI_MAC_ADDR
-                    " InterfaceID %p(%p), primary %p, " PRI_IP_ADDR "/%d" PUB_S PUB_S PUB_S,
-                    i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i, primary,
-                    &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask),
-                    i->Flashing               ? " (Flashing)"  : "",
-                    i->Occulting              ? " (Occulting)" : "",
-                    i->ifinfo.InterfaceActive ? " (Primary)"   : "");
-
-                // "p2p*" interfaces used for legacy AirDrop reuse the scope-id, MAC address and the IP address
-                // every time it creates a new interface. We think it is a duplicate and hence consider it
-                // as flashing and occulting. The "core" does not flush the cache for this case. This leads to
-                // stale data returned to the application even after the interface is removed. The application
-                // then starts to send data but the new interface is not yet created.
-                // The same logic applies when the IFEF_DIRECTLINK flag is set on the interface.
-                if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
-                {
-                    activationSpeed = FastActivation;
-                    LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ClearInactiveInterfaces: " PUB_S " DirectLink interface deregistering", i->ifinfo.ifname);
-                }
-#if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
-                else if (i->Flashing && i->Occulting)
-                {
-                    activationSpeed = SlowActivation;
-                }
-#endif
-                else
-                {
-                    activationSpeed = NormalActivation;
-                }
-                mDNS_DeregisterInterface(m, &i->ifinfo, activationSpeed);
-
-                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
-                i->Registered = mDNSNULL;
-                // Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
-                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
-                // If i->Registered is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
-
-                // Caution: If we ever decide to add code here to leave the multicast group, we need to make sure that this
-                // is the LAST representative of this physical interface, or we'll unsubscribe from the group prematurely.
-            }
-        }
-    }
-
-    // Second pass:
-    // Now that everything that's going to deregister has done so, we can clean up and free the memory
-    NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
-    while (*p)
-    {
-        i = *p;
-        // If no longer active, delete interface from list and free memory
-        if (!i->Exists)
-        {
-            if (i->LastSeen == utc) i->LastSeen = utc - 1;
-            const mDNSBool delete = ((utc - i->LastSeen) >= 60) ? mDNStrue : mDNSfalse;
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "ClearInactiveInterfaces: " PUB_S " " PUB_S "(%u) " PRI_MAC_ADDR " InterfaceID %p(%p) " PRI_IP_ADDR
-                "/%d Age %d" PUB_S,
-                delete ? "Deleting" : "Holding", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i,
-                &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), utc - i->LastSeen,
-                i->ifinfo.InterfaceActive ? " (Primary)" : "");
-            if (delete)
-            {
-                *p = i->next;
-                freeL("NetworkInterfaceInfoOSX", i);
-                continue;   // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
-            }
-        }
-        p = &i->next;
-    }
-    return count;
-}
-
-mDNSlocal void AppendDNameListElem(DNameListElem ***List, mDNSu32 uid, domainname *name)
-{
-    DNameListElem *dnle = (DNameListElem*) callocL("DNameListElem/AppendDNameListElem", sizeof(*dnle));
-    if (!dnle) LogMsg("ERROR: AppendDNameListElem: memory exhausted");
-    else
-    {
-        dnle->next = mDNSNULL;
-        dnle->uid  = uid;
-        AssignDomainName(&dnle->name, name);
-        **List = dnle;
-        *List = &dnle->next;
-    }
-}
-
-mDNSlocal int compare_dns_configs(const void *aa, const void *bb)
-{
-    const dns_resolver_t *const a = *(const dns_resolver_t *const *)aa;
-    const dns_resolver_t *const b = *(const dns_resolver_t *const *)bb;
-
-    return (a->search_order < b->search_order) ? -1 : (a->search_order == b->search_order) ? 0 : 1;
-}
-
-mDNSlocal void UpdateSearchDomainHash(MD5_CTX *sdc, char *domain, mDNSInterfaceID InterfaceID)
-{
-    mDNS *const m = &mDNSStorage;
-    char *buf = ".";
-    mDNSu32 scopeid = 0;
-    char ifid_buf[16];
-
-    if (domain)
-        buf = domain;
-    //
-    // Hash the search domain name followed by the InterfaceID.
-    // As we have scoped search domains, we also included InterfaceID. If either of them change,
-    // we will detect it. Even if the order of them change, we will detect it.
-    //
-    // Note: We have to handle a few of these tricky cases.
-    //
-    // 1) Current: com, apple.com Changing to: comapple.com
-    // 2) Current: a.com,b.com Changing to a.comb.com
-    // 3) Current: a.com,b.com (ifid 8), Changing to a.com8b.com (ifid 8)
-    // 4) Current: a.com (ifid 12), Changing to a.com1 (ifid: 2)
-    //
-    // There are more variants of the above. The key thing is if we include the null in each case
-    // at the end of name and the InterfaceID, it will prevent a new name (which can't include
-    // NULL as part of the name) to be mistakenly thought of as a old name.
-
-    scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
-    // mDNS_snprintf always null terminates
-    if (mDNS_snprintf(ifid_buf, sizeof(ifid_buf), "%u", scopeid) >= sizeof(ifid_buf))
-        LogMsg("UpdateSearchDomainHash: mDNS_snprintf failed for scopeid %u", scopeid);
-
-    LogInfo("UpdateSearchDomainHash: buf %s, ifid_buf %s", buf, ifid_buf);
-    MD5_Update(sdc, buf, strlen(buf) + 1);
-    MD5_Update(sdc, ifid_buf, strlen(ifid_buf) + 1);
-}
-
-mDNSlocal void FinalizeSearchDomainHash(MD5_CTX *sdc)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSu8 md5_hash[MD5_LEN];
-
-    MD5_Final(md5_hash, sdc);
-
-    if (memcmp(md5_hash, m->SearchDomainsHash, MD5_LEN))
-    {
-        // If the hash is different, either the search domains have changed or
-        // the ordering between them has changed. Restart the questions that
-        // would be affected by this.
-        LogInfo("FinalizeSearchDomains: The hash is different");
-        memcpy(m->SearchDomainsHash, md5_hash, MD5_LEN);
-        RetrySearchDomainQuestions(m);
-    }
-    else { LogInfo("FinalizeSearchDomains: The hash is same"); }
-}
-
-mDNSlocal void ConfigSearchDomains(dns_resolver_t *resolver, mDNSInterfaceID interfaceId, mDNSu32 scope,  MD5_CTX *sdc, uint64_t generation)
-{
-    const char *scopeString = DNSScopeToString(scope);
-    int j;
-    domainname d;
-
-    if (scope == kScopeNone)
-        interfaceId = mDNSInterface_Any;
-
-    if (scope == kScopeNone || scope == kScopeInterfaceID)
-    {
-        for (j = 0; j < resolver->n_search; j++)
-        {
-            if (MakeDomainNameFromDNSNameString(&d, resolver->search[j]) != NULL)
-            {
-                char interface_buf[32];
-                mDNS_snprintf(interface_buf, sizeof(interface_buf), "for interface %s", InterfaceNameForID(&mDNSStorage,  interfaceId));
-                LogInfo("ConfigSearchDomains: (%s) configuring search domain %s %s (generation= %llu)", scopeString,
-                        resolver->search[j], (interfaceId == mDNSInterface_Any) ? "" : interface_buf, generation);
-                UpdateSearchDomainHash(sdc, resolver->search[j], interfaceId);
-                mDNS_AddSearchDomain_CString(resolver->search[j], interfaceId);
-            }
-            else
-            {
-                LogInfo("ConfigSearchDomains: An invalid search domain was detected for %s domain %s n_nameserver %d, (generation= %llu)",
-                        DNSScopeToString(scope), resolver->domain, resolver->n_nameserver, generation);
-            }
-        }
-    }
-    else
-    {
-        LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for interface %s", scopeString, InterfaceNameForID(&mDNSStorage, interfaceId));
-    }
-}
-
-mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNSu32 ifindex)
-{
-    NetworkInterfaceInfoOSX *ni;
-    mDNSInterfaceID interface;
-
-    for (ni = mDNSStorage.p->InterfaceList; ni; ni = ni->next)
-    {
-        if (ni->ifinfo.InterfaceID && ni->scope_id == ifindex)
-            break;
-    }
-    if (ni != NULL)
-    {
-        interface = ni->ifinfo.InterfaceID;
-    }
-    else
-    {
-        // In rare circumstances, we could potentially hit this case where we cannot parse the InterfaceID
-        // (see <rdar://problem/13214785>). At this point, we still accept the DNS Config from configd
-        // Note: We currently ack the whole dns configuration and not individual resolvers or DNS servers.
-        // As the caller is going to ack the configuration always, we have to add all the DNS servers
-        // in the configuration. Otherwise, we won't have any DNS servers up until the network change.
-
-        LogMsg("ConfigParseInterfaceID: interface specific index %d not found (interface may not be UP)",ifindex);
-
-        // Set the correct interface from configd before passing this to mDNS_AddDNSServer() below
-        interface = (mDNSInterfaceID)(unsigned long)ifindex;
-    }
-    return interface;
-}
-
-mDNSlocal void ConfigNonUnicastResolver(dns_resolver_t *r)
-{
-    char *opt = r->options;
-    domainname d;
-
-    if (opt && !strncmp(opt, "mdns", strlen(opt)))
-    {
-        if (!MakeDomainNameFromDNSNameString(&d, r->domain))
-        {
-            LogMsg("ConfigNonUnicastResolver: config->resolver bad domain %s", r->domain);
-            return;
-        }
-        mDNS_AddMcastResolver(&mDNSStorage, &d, mDNSInterface_Any, r->timeout);
-    }
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-mDNSlocal void ConfigDNSServers(dns_resolver_t *r, mDNSInterfaceID interfaceID, mDNSu32 scope, mDNSu32 resGroupID)
-{
-    domainname domain;
-    if (!r->domain || (*r->domain == '\0'))
-    {
-        domain.c[0] = 0;
-    }
-    else if (!MakeDomainNameFromDNSNameString(&domain, r->domain))
-    {
-        LogMsg("ConfigDNSServers: bad domain %s", r->domain);
-        return;
-    }
-    // Parse the resolver specific attributes that affects all the DNS servers.
-    const int32_t serviceID = (scope == kScopeServiceID) ? r->service_identifier : 0;
-
-    const mdns_interface_monitor_t monitor = GetInterfaceMonitorForIndex((uint32_t)((uintptr_t)interfaceID));
-    const mDNSBool isExpensive   = (monitor && mdns_interface_monitor_is_expensive(monitor))   ? mDNStrue : mDNSfalse;
-    const mDNSBool isConstrained = (monitor && mdns_interface_monitor_is_constrained(monitor)) ? mDNStrue : mDNSfalse;
-    const mDNSBool isCLAT46      = (monitor && mdns_interface_monitor_is_clat46(monitor))      ? mDNStrue : mDNSfalse;
-    const mDNSBool usableA       = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS)           ? mDNStrue : mDNSfalse;
-    const mDNSBool usableAAAA    = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS)        ? mDNStrue : mDNSfalse;
-    const mDNSBool isCell        = mDNSfalse;
-
-    const mDNSIPPort port = (r->port != 0) ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort;
-    for (int32_t i = 0; i < r->n_nameserver; i++)
-    {
-        const int family = r->nameserver[i]->sa_family;
-        if ((family != AF_INET) && (family != AF_INET6)) continue;
-
-        mDNSAddr saddr;
-        if (SetupAddr(&saddr, r->nameserver[i]))
-        {
-            LogMsg("ConfigDNSServers: Bad address");
-            continue;
-        }
-
-        // The timeout value is for all the DNS servers in a given resolver, hence we pass
-        // the timeout value only for the first DNSServer. If we don't have a value in the
-        // resolver, then use the core's default value
-        //
-        // Note: this assumes that when the core picks a list of DNSServers for a question,
-        // it takes the sum of all the timeout values for all DNS servers. By doing this, it
-        // tries all the DNS servers in a specified timeout
-        DNSServer *s = mDNS_AddDNSServer(&mDNSStorage, &domain, interfaceID, serviceID, &saddr, port, scope,
-            (i == 0) ? (r->timeout ? r->timeout : DEFAULT_UDNS_TIMEOUT) : 0, isCell, isExpensive, isConstrained, isCLAT46,
-            resGroupID, usableA, usableAAAA, mDNStrue);
-        if (s)
-        {
-            LogInfo("ConfigDNSServers(%s): DNS server %#a:%d for domain %##s",
-                DNSScopeToString(scope), &s->addr, mDNSVal16(s->port), domain.c);
-        }
-    }
-}
-#endif
-
-// ConfigResolvers is called for different types of resolvers: Unscoped resolver, Interface scope resolver and
-// Service scope resolvers. This is indicated by the scope argument.
-//
-// "resolver" has entries that should only be used for unscoped questions.
-//
-// "scoped_resolver" has entries that should only be used for Interface scoped question i.e., questions that specify an
-// interface index (q->InterfaceID)
-//
-// "service_specific_resolver" has entries that should be used for Service scoped question i.e., questions that specify
-// a service identifier (q->ServiceID)
-//
-mDNSlocal void ConfigResolvers(dns_config_t *config, mDNSu32 scope, mDNSBool setsearch, mDNSBool setservers, MD5_CTX *sdc)
-{
-    int i;
-    dns_resolver_t **resolver;
-    int nresolvers;
-    const char *scopeString = DNSScopeToString(scope);
-    mDNSInterfaceID interface;
-
-    switch (scope)
-    {
-        case kScopeNone:
-            resolver = config->resolver;
-            nresolvers = config->n_resolver;
-            break;
-        case kScopeInterfaceID:
-            resolver = config->scoped_resolver;
-            nresolvers = config->n_scoped_resolver;
-            break;
-        case kScopeServiceID:
-            resolver = config->service_specific_resolver;
-            nresolvers = config->n_service_specific_resolver;
-            break;
-        default:
-            return;
-    }
-    qsort(resolver, nresolvers, sizeof(dns_resolver_t*), compare_dns_configs);
-
-    for (i = 0; i < nresolvers; i++)
-    {
-        dns_resolver_t *r = resolver[i];
-
-        LogInfo("ConfigResolvers: %s resolver[%d] domain %s n_nameserver %d", scopeString, i, r->domain, r->n_nameserver);
-
-        interface = mDNSInterface_Any;
-
-        // Parse the interface index
-        if (r->if_index != 0)
-        {
-            interface = ConfigParseInterfaceID(r->if_index);
-        }
-
-        if (setsearch)
-        {
-            ConfigSearchDomains(resolver[i], interface, scope, sdc, config->generation);
-
-            // Parse other scoped resolvers for search lists
-            if (!setservers)
-                continue;
-        }
-
-        if (r->port == 5353 || r->n_nameserver == 0)
-        {
-            ConfigNonUnicastResolver(r);
-        }
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        else
-        {
-            ConfigDNSServers(r, interface, scope, mDNS_GetNextResolverGroupID());
-        }
-#endif
-    }
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-mDNSlocal mDNSBool QuestionValidForDNSTrigger(const DNSQuestion *q)
-{
-    if (q->Suppressed)
-    {
-        debugf("QuestionValidForDNSTrigger: Suppressed: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    if (mDNSOpaque16IsZero(q->TargetQID))
-    {
-        debugf("QuestionValidForDNSTrigger: Multicast: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    // If we answered using LocalOnly records e.g., /etc/hosts, don't consider that a valid response
-    // for trigger.
-    if (q->LOAddressAnswers)
-    {
-        debugf("QuestionValidForDNSTrigger: LocalOnly answers: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    return mDNStrue;
-}
-
-// This function is called if we are not delivering unicast answers to "A" or "AAAA" questions.
-// We set our state appropriately so that if we start receiving answers, trigger the
-// upper layer to retry DNS questions.
-mDNSexport void mDNSPlatformUpdateDNSStatus(const DNSQuestion *q)
-{
-    mDNS *const m = &mDNSStorage;
-    if (!QuestionValidForDNSTrigger(q))
-        return;
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    // Ignore applications that start and stop queries for no reason before we ever talk
-    // to any DNS server.
-    if (!q->triedAllServersOnce)
-    {
-        LogInfo("QuestionValidForDNSTrigger: question %##s (%s) stopped too soon", q->qname.c, DNSTypeName(q->qtype));
-        return;
-    }
-#endif
-    if (q->qtype == kDNSType_A)
-        m->p->v4answers = 0;
-    if (q->qtype == kDNSType_AAAA)
-        m->p->v6answers = 0;
-    if (!m->p->v4answers || !m->p->v6answers)
-    {
-        LogInfo("mDNSPlatformUpdateDNSStatus: Trigger needed v4 %d, v6 %d, question %##s (%s)", m->p->v4answers, m->p->v6answers, q->qname.c,
-            DNSTypeName(q->qtype));
-    }
-}
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-
-mDNSlocal void AckConfigd(dns_config_t *config)
-{
-    mDNS_CheckLock(&mDNSStorage);
-
-    // Acking the configuration triggers configd to reissue the reachability queries
-    mDNSStorage.p->DNSTrigger = NonZeroTime(mDNSStorage.timenow);
-    _dns_configuration_ack(config, "com.apple.mDNSResponder");
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-// If v4q is non-NULL, it means we have received some answers for "A" type questions
-// If v6q is non-NULL, it means we have received some answers for "AAAA" type questions
-mDNSexport void mDNSPlatformTriggerDNSRetry(const DNSQuestion *v4q, const DNSQuestion *v6q)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNSBool trigger = mDNSfalse;
-    mDNSs32 timenow;
-
-    // Don't send triggers too often.
-    // If we have started delivering answers to questions, we should send a trigger
-    // if the time permits. If we are delivering answers, we should set the state
-    // of v4answers/v6answers to 1 and avoid sending a trigger.  But, we don't know
-    // whether the answers that are being delivered currently is for configd or some
-    // other application. If we set the v4answers/v6answers to 1 and not deliver a trigger,
-    // then we won't deliver the trigger later when it is okay to send one as the
-    // "answers" are already set to 1. Hence, don't affect the state of v4answers and
-    // v6answers if we are not delivering triggers.
-    mDNS_Lock(m);
-    timenow = m->timenow;
-    if (m->p->DNSTrigger && (timenow - m->p->DNSTrigger) < DNS_TRIGGER_INTERVAL)
-    {
-        if (!m->p->v4answers || !m->p->v6answers)
-        {
-            debugf("mDNSPlatformTriggerDNSRetry: not triggering, time since last trigger %d ms, v4ans %d, v6ans %d",
-                (timenow - m->p->DNSTrigger), m->p->v4answers, m->p->v6answers);
-        }
-        mDNS_Unlock(m);
-        return;
-    }
-    mDNS_Unlock(m);
-    if (v4q != NULL && QuestionValidForDNSTrigger(v4q))
-    {
-        int old = m->p->v4answers;
-
-        m->p->v4answers = 1;
-
-        // If there are IPv4 answers now and previously we did not have
-        // any answers, trigger a DNS change so that reachability
-        // can retry the queries again.
-        if (!old)
-        {
-            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv4, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
-                v4q->qname.c, DNSTypeName(v4q->qtype));
-            trigger = mDNStrue;
-        }
-    }
-    if (v6q != NULL && QuestionValidForDNSTrigger(v6q))
-    {
-        int old = m->p->v6answers;
-
-        m->p->v6answers = 1;
-        // If there are IPv6 answers now and previously we did not have
-        // any answers, trigger a DNS change so that reachability
-        // can retry the queries again.
-        if (!old)
-        {
-            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv6, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
-                v6q->qname.c, DNSTypeName(v6q->qtype));
-            trigger = mDNStrue;
-        }
-    }
-    if (trigger)
-    {
-        dns_config_t *config = dns_configuration_copy();
-        if (config)
-        {
-            mDNS_Lock(m);
-            AckConfigd(config);
-            mDNS_Unlock(m);
-            dns_configuration_free(config);
-        }
-        else
-        {
-            LogMsg("mDNSPlatformTriggerDNSRetry: ERROR!! configd did not return config");
-        }
-    }
-}
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-mDNSlocal void SetupActiveDirectoryDomain(dns_config_t *config)
-{
-    // Record the so-called "primary" domain, which we use as a hint to tell if the user is on a network set up
-    // by someone using Microsoft Active Directory using "local" as a private internal top-level domain
-    if (config->n_resolver && config->resolver[0]->domain && config->resolver[0]->n_nameserver &&
-        config->resolver[0]->nameserver[0])
-    {
-        MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, config->resolver[0]->domain);
-    }
-    else
-    {
-         ActiveDirectoryPrimaryDomain.c[0] = 0;
-    }
-
-    //MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, "test.local");
-    ActiveDirectoryPrimaryDomainLabelCount = CountLabels(&ActiveDirectoryPrimaryDomain);
-    if (config->n_resolver && config->resolver[0]->n_nameserver &&
-        SameDomainName(SkipLeadingLabels(&ActiveDirectoryPrimaryDomain, ActiveDirectoryPrimaryDomainLabelCount - 1), &localdomain))
-    {
-        SetupAddr(&ActiveDirectoryPrimaryDomainServer, config->resolver[0]->nameserver[0]);
-    }
-    else
-    {
-        AssignConstStringDomainName(&ActiveDirectoryPrimaryDomain, "");
-        ActiveDirectoryPrimaryDomainLabelCount = 0;
-        ActiveDirectoryPrimaryDomainServer = zeroAddr;
-    }
-}
-#endif
-
-mDNSlocal void SetupDDNSDomains(domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
-{
-    int i;
-    char buf[MAX_ESCAPED_DOMAIN_NAME];  // Max legal C-string name, including terminating NULL
-    domainname d;
-
-    CFDictionaryRef ddnsdict = SCDynamicStoreCopyValue(NULL, NetworkChangedKey_DynamicDNS);
-    if (ddnsdict)
-    {
-        if (fqdn)
-        {
-            CFArrayRef fqdnArray = CFDictionaryGetValue(ddnsdict, CFSTR("HostNames"));
-            if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
-            {
-                // for now, we only look at the first array element.  if we ever support multiple configurations, we will walk the list
-                CFDictionaryRef fqdnDict = CFArrayGetValueAtIndex(fqdnArray, 0);
-                if (fqdnDict && DictionaryIsEnabled(fqdnDict))
-                {
-                    CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
-                    if (name)
-                    {
-                        if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                            !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
-                            LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
-                        else
-                            debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
-                    }
-                }
-            }
-        }
-        if (RegDomains)
-        {
-            CFArrayRef regArray = CFDictionaryGetValue(ddnsdict, CFSTR("RegistrationDomains"));
-            if (regArray && CFArrayGetCount(regArray) > 0)
-            {
-                CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
-                if (regDict && DictionaryIsEnabled(regDict))
-                {
-                    CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
-                    if (name)
-                    {
-                        if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                            !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
-                            LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
-                        else
-                        {
-                            debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration domain: %s", buf);
-                            AppendDNameListElem(&RegDomains, 0, &d);
-                        }
-                    }
-                }
-            }
-        }
-        if (BrowseDomains)
-        {
-            CFArrayRef browseArray = CFDictionaryGetValue(ddnsdict, CFSTR("BrowseDomains"));
-            if (browseArray)
-            {
-                for (i = 0; i < CFArrayGetCount(browseArray); i++)
-                {
-                    CFDictionaryRef browseDict = CFArrayGetValueAtIndex(browseArray, i);
-                    if (browseDict && DictionaryIsEnabled(browseDict))
-                    {
-                        CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
-                        if (name)
-                        {
-                            if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                                !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
-                                LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS browsing domain: %s", buf[0] ? buf : "(unknown)");
-                            else
-                            {
-                                debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS browsing domain: %s", buf);
-                                AppendDNameListElem(&BrowseDomains, 0, &d);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        MDNS_DISPOSE_CF_OBJECT(ddnsdict);
-    }
-}
-
-// Returns mDNSfalse, if it does not set the configuration i.e., if the DNS configuration did not change
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn,
-                                             DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig)
-{
-    mDNS *const m = &mDNSStorage;
-    MD5_CTX sdc;    // search domain context
-
-    // Need to set these here because we need to do this even if SCDynamicStoreCreate() or SCDynamicStoreCopyValue() below don't succeed
-    if (fqdn         ) fqdn->c[0]      = 0;
-    if (RegDomains   ) *RegDomains     = NULL;
-    if (BrowseDomains) *BrowseDomains  = NULL;
-
-    LogInfo("mDNSPlatformSetDNSConfig:%s%s%s%s%s",
-            setservers    ? " setservers"    : "",
-            setsearch     ? " setsearch"     : "",
-            fqdn          ? " fqdn"          : "",
-            RegDomains    ? " RegDomains"    : "",
-            BrowseDomains ? " BrowseDomains" : "");
-
-    if (setsearch) MD5_Init(&sdc);
-
-    // Add the inferred address-based configuration discovery domains
-    // (should really be in core code I think, not platform-specific)
-    if (setsearch)
-    {
-        struct ifaddrs *ifa = mDNSNULL;
-        struct sockaddr_in saddr;
-        mDNSPlatformMemZero(&saddr, sizeof(saddr));
-        saddr.sin_len = sizeof(saddr);
-        saddr.sin_family = AF_INET;
-        saddr.sin_port = 0;
-        saddr.sin_addr.s_addr = *(in_addr_t *)&m->Router.ip.v4;
-
-        // Don't add any reverse-IP search domains if doing the WAB bootstrap queries would cause dial-on-demand connection initiation
-        if (!AddrRequiresPPPConnection((struct sockaddr *)&saddr)) ifa =  myGetIfAddrs(1);
-
-        while (ifa)
-        {
-            mDNSAddr a, n;
-            char buf[64];
-
-            if (ifa->ifa_addr->sa_family == AF_INET &&
-                ifa->ifa_netmask                    &&
-                !(ifa->ifa_flags & IFF_LOOPBACK)    &&
-                !SetupAddr(&a, ifa->ifa_addr)       &&
-                !mDNSv4AddressIsLinkLocal(&a.ip.v4)  )
-            {
-                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be incorrect, so we explicitly fix it here before calling SetupAddr
-                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;     // Make sure ifa_netmask->sa_family is set correctly
-                SetupAddr(&n, ifa->ifa_netmask);
-                // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-                mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", a.ip.v4.b[3] & n.ip.v4.b[3],
-                              a.ip.v4.b[2] & n.ip.v4.b[2],
-                              a.ip.v4.b[1] & n.ip.v4.b[1],
-                              a.ip.v4.b[0] & n.ip.v4.b[0]);
-                UpdateSearchDomainHash(&sdc, buf, NULL);
-                mDNS_AddSearchDomain_CString(buf, mDNSNULL);
-            }
-            ifa = ifa->ifa_next;
-        }
-    }
-
-#ifndef MDNS_NO_DNSINFO
-    if (setservers || setsearch)
-    {
-        dns_config_t *config = dns_configuration_copy();
-        if (!config)
-        {
-            // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
-            // Apparently this is expected behaviour -- "not a bug".
-            // Accordingly, we suppress syslog messages for the first three minutes after boot.
-            // If we are still getting failures after three minutes, then we log them.
-            if ((mDNSu32)mDNSPlatformRawTime() > (mDNSu32)(mDNSPlatformOneSecond * 180))
-                LogMsg("mDNSPlatformSetDNSConfig: Error: dns_configuration_copy returned NULL");
-        }
-        else
-        {
-            LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu, last %llu", config->n_resolver, config->generation, m->p->LastConfigGeneration);
-
-            // For every network change, mDNSPlatformSetDNSConfig is called twice. First,
-            // to update the search domain list (in which case, the setsearch bool is set);
-            // and second, to update the DNS server list (in which case, the setservers bool
-            // is set). The code assumes only one of these flags, setsearch or setserver,
-            // will be set when mDNSPlatformSetDNSConfig is called to handle a network change.
-            // The mDNSPlatformSetDNSConfig function also assumes that ackCfg will be set
-            // when setservers is set.
-
-            // The search domains update occurs on every network change to avoid sync issues
-            // that may occur if a network change happens during the processing
-            // of a network change.  The dns servers update occurs when the DNS config
-            // changes. The dns servers stay in sync by saving the config's generation number
-            // on every update; and only updating when the generation number changes.
-
-            // If this is a DNS server update and the configuration hasn't changed, then skip update
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (setservers && m->p->LastConfigGeneration == config->generation)
-#else
-            if (setservers && !m->p->if_interface_changed && m->p->LastConfigGeneration == config->generation)
-#endif
-            {
-                LogInfo("mDNSPlatformSetDNSConfig(setservers): generation number %llu same, not processing", config->generation);
-                dns_configuration_free(config);
-                SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
-                return mDNSfalse;
-            }
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (setservers) {
-                // Must check if setservers is true, because mDNSPlatformSetDNSConfig can be called for multiple times
-                // with setservers equals to false. If setservers is false, we will end up with clearing if_interface_changed
-                // without really updating the server.
-                m->p->if_interface_changed = mDNSfalse;
-            }
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-            SetupActiveDirectoryDomain(config);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (setservers) Querier_ApplyDNSConfig(config);
-#endif
-            ConfigResolvers(config, kScopeNone, setsearch, setservers, &sdc);
-            ConfigResolvers(config, kScopeInterfaceID, setsearch, setservers, &sdc);
-            ConfigResolvers(config, kScopeServiceID, setsearch, setservers, &sdc);
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            const CFIndex n = m->p->InterfaceMonitors ? CFArrayGetCount(m->p->InterfaceMonitors) : 0;
-            for (CFIndex i = n - 1; i >= 0; i--)
-            {
-                mdns_interface_monitor_t monitor;
-                monitor = (mdns_interface_monitor_t) CFArrayGetValueAtIndex(m->p->InterfaceMonitors, i);
-                const uint32_t ifIndex = mdns_interface_monitor_get_interface_index(monitor);
-                DNSServer *server;
-                for (server = m->DNSServers; server; server = server->next)
-                {
-                    if ((((uintptr_t)server->interface) == ifIndex) && !(server->flags & DNSServerFlag_Delete))
-                    {
-                        break;
-                    }
-                }
-                if (!server)
-                {
-                    mdns_retain(monitor);
-                    CFArrayRemoveValueAtIndex(m->p->InterfaceMonitors, i);
-                    mdns_interface_monitor_invalidate(monitor);
-                    mdns_release(monitor);
-                }
-            }
-#endif
-            // Acking provides a hint to other processes that the current DNS configuration has completed
-            // its update.  When configd receives the ack, it publishes a notification.
-            // Applications monitoring the notification then know when to re-issue their DNS queries
-            // after a network change occurs.
-            if (ackConfig)
-            {
-                // Note: We have to set the generation number here when we are acking.
-                // For every DNS configuration change, we do the following:
-                //
-                // 1) Copy dns configuration, handle search domains change
-                // 2) Copy dns configuration, handle dns server change
-                //
-                // If we update the generation number at step (1), we won't process the
-                // DNS servers the second time because generation number would be the same.
-                // As we ack only when we process dns servers, we set the generation number
-                // during acking.
-                m->p->LastConfigGeneration = config->generation;
-                LogInfo("mDNSPlatformSetDNSConfig: Acking configuration setservers %d, setsearch %d", setservers, setsearch);
-                AckConfigd(config);
-            }
-            dns_configuration_free(config);
-            if (setsearch) FinalizeSearchDomainHash(&sdc);
-        }
-    }
-#endif // MDNS_NO_DNSINFO
-    SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
-    return mDNStrue;
-}
-
-
-mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
-{
-    char buf[256];
-
-    CFDictionaryRef dict = SCDynamicStoreCopyValue(NULL, NetworkChangedKey_IPv4);
-    if (dict)
-    {
-        r->type  = mDNSAddrType_IPv4;
-        r->ip.v4 = zerov4Addr;
-        CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
-        if (string)
-        {
-            if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
-                LogMsg("Could not convert router to CString");
-            else
-            {
-                struct sockaddr_in saddr;
-                saddr.sin_len = sizeof(saddr);
-                saddr.sin_family = AF_INET;
-                saddr.sin_port = 0;
-                inet_aton(buf, &saddr.sin_addr);
-                *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
-            }
-        }
-        string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
-        if (string)
-        {
-            mDNSBool HavePrimaryGlobalv6 = mDNSfalse;  // does the primary interface have a global v6 address?
-            struct ifaddrs *ifa = myGetIfAddrs(1);
-            *v4 = *v6 = zeroAddr;
-
-            if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
-            {
-                LogMsg("Could not convert router to CString");
-                goto exit;
-            }
-            // find primary interface in list
-            while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
-            {
-                if (!ifa->ifa_addr)
-                {
-                    LogMsg("Skip interface, %s, since ifa_addr is not set.", (ifa->ifa_name) ? ifa->ifa_name: "name not found");
-                    ifa = ifa->ifa_next;
-                    continue;
-                }
-                mDNSAddr tmp6 = zeroAddr;
-                if (!strcmp(buf, ifa->ifa_name))
-                {
-                    if (ifa->ifa_addr->sa_family == AF_INET)
-                    {
-                        if (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4))
-                            SetupAddr(v4, ifa->ifa_addr);
-                    }
-                    else if (ifa->ifa_addr->sa_family == AF_INET6)
-                    {
-                        SetupAddr(&tmp6, ifa->ifa_addr);
-                        if (tmp6.ip.v6.b[0] >> 5 == 1)   // global prefix: 001
-                        {
-                            HavePrimaryGlobalv6 = mDNStrue;
-                            *v6 = tmp6;
-                        }
-                    }
-                }
-                else
-                {
-                    // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
-                    if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6->ip.v6.b[0])
-                    {
-                        SetupAddr(&tmp6, ifa->ifa_addr);
-                        if (tmp6.ip.v6.b[0] >> 5 == 1)
-                            *v6 = tmp6;
-                    }
-                }
-                ifa = ifa->ifa_next;
-            }
-            // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
-            // V4 to communicate w/ our DNS server
-        }
-
-exit:
-        MDNS_DISPOSE_CF_OBJECT(dict);
-    }
-    return mStatus_NoError;
-}
-
-mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-    LogInfo("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status, dname->c);
-    char uname[MAX_ESCAPED_DOMAIN_NAME];    // Max legal C-string name, including terminating NUL
-    ConvertDomainNameToCString(dname, uname);
-
-    char *p = uname;
-    while (*p)
-    {
-        *p = tolower(*p);
-        if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
-        p++;
-    }
-
-    // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
-    // That single entity is a CFDictionary with name "HostNames".
-    // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
-    // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
-    // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
-    // The CFDictionary for each FQDN holds (at present) a single name/value pair,
-    // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
-
-    const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
-    CFStringRef HostKeys  [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
-    const CFStringRef StatusKeys[1] = { CFSTR("Status") };
-    if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
-    else
-    {
-        CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
-        if (StatusVals[0] == NULL) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
-        else
-        {
-            CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
-            if (HostVals[0])
-            {
-                CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
-                if (StateVals[0])
-                {
-                    CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                    if (StateDict)
-                    {
-                        mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
-                        MDNS_DISPOSE_CF_OBJECT(StateDict);
-                    }
-                    MDNS_DISPOSE_CF_OBJECT(StateVals[0]);
-                }
-                MDNS_DISPOSE_CF_OBJECT(HostVals[0]);
-            }
-            MDNS_DISPOSE_CF_OBJECT(StatusVals[0]);
-        }
-        MDNS_DISPOSE_CF_OBJECT(HostKeys[0]);
-    }
-}
-
-// MUST be called holding the lock
-mDNSlocal void SetDomainSecrets_internal(mDNS *m)
-{
-#ifdef NO_SECURITYFRAMEWORK
-        (void) m;
-    LogMsg("Note: SetDomainSecrets: no keychain support");
-#else
-
-    LogInfo("SetDomainSecrets");
-
-    // Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
-    // In the case where the user simultaneously removes their DDNS host name and the key
-    // for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
-    // server before it loses access to the necessary key. Otherwise, we'd leave orphaned
-    // address records behind that we no longer have permission to delete.
-    DomainAuthInfo *ptr;
-    for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
-        ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
-
-    // String Array used to write list of private domains to Dynamic Store
-    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (!sa) { LogMsg("SetDomainSecrets: CFArrayCreateMutable failed"); return; }
-    CFIndex i;
-    CFDataRef data = NULL;
-    const int itemsPerEntry = 4; // domain name, key name, key value, Name value
-    CFArrayRef secrets = NULL;
-    int err = mDNSKeychainGetSecrets(&secrets);
-    if (err || !secrets)
-        LogMsg("SetDomainSecrets: mDNSKeychainGetSecrets failed error %d CFArrayRef %p", err, secrets);
-    else
-    {
-        CFIndex ArrayCount = CFArrayGetCount(secrets);
-        // Iterate through the secrets
-        for (i = 0; i < ArrayCount; ++i)
-        {
-            int j;
-            size_t offset;
-            CFArrayRef entry = CFArrayGetValueAtIndex(secrets, i);
-            if (CFArrayGetTypeID() != CFGetTypeID(entry) || itemsPerEntry != CFArrayGetCount(entry))
-            { LogMsg("SetDomainSecrets: malformed entry %d, itemsPerEntry %d", i, itemsPerEntry); continue; }
-            for (j = 0; j < CFArrayGetCount(entry); ++j)
-                if (CFDataGetTypeID() != CFGetTypeID(CFArrayGetValueAtIndex(entry, j)))
-                { LogMsg("SetDomainSecrets: malformed entry item %d", j); continue; }
-
-            // The names have already been vetted by the helper, but checking them again here helps humans and automated tools verify correctness
-
-            // Max legal domainname as C-string, including space for dnsprefix and terminating NUL
-            // Get DNS domain this key is for (kmDNSKcWhere)
-            char stringbuf[MAX_ESCAPED_DOMAIN_NAME + sizeof(dnsprefix)];
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcWhere);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            { LogMsg("SetDomainSecrets: Bad kSecServiceItemAttr length %d", CFDataGetLength(data)); continue; }
-            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';
-
-            offset = 0;
-            if (!strncmp(stringbuf, dnsprefix, strlen(dnsprefix)))
-                offset = strlen(dnsprefix);
-
-            domainname domain;
-            if (!MakeDomainNameFromDNSNameString(&domain, stringbuf + offset)) { LogMsg("SetDomainSecrets: bad key domain %s", stringbuf); continue; }
-
-            // Get key name (kmDNSKcAccount)
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcAccount);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            { LogMsg("SetDomainSecrets: Bad kSecAccountItemAttr length %d", CFDataGetLength(data)); continue; }
-            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';
-
-            domainname keyname;
-            if (!MakeDomainNameFromDNSNameString(&keyname, stringbuf)) { LogMsg("SetDomainSecrets: bad key name %s", stringbuf); continue; }
-
-            // Get key data (kmDNSKcKey)
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcKey);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            {
-                LogMsg("SetDomainSecrets: Shared secret too long: %d", CFDataGetLength(data));
-                continue;
-            }
-            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';    // mDNS_SetSecretForDomain requires NULL-terminated C string for key
-
-            // Get the Name of the keychain entry (kmDNSKcName) host or host:port
-            // The hostname also has the port number and ":". It should take a maximum of 6 bytes.
-            char hostbuf[MAX_ESCAPED_DOMAIN_NAME + 6];  // Max legal domainname as C-string, including terminating NUL
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcName);
-            if (CFDataGetLength(data) >= (int)sizeof(hostbuf))
-            {
-                LogMsg("SetDomainSecrets: host:port data too long: %d", CFDataGetLength(data));
-                continue;
-            }
-            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)hostbuf);
-            hostbuf[CFDataGetLength(data)] = '\0';
-
-            domainname hostname;
-            mDNSIPPort port;
-            char *hptr;
-            hptr = strchr(hostbuf, ':');
-
-            port.NotAnInteger = 0;
-            if (hptr)
-            {
-                mDNSu8 *p;
-                mDNSu16 val = 0;
-
-                *hptr++ = '\0';
-                while(hptr && *hptr != 0)
-                {
-                    if (*hptr < '0' || *hptr > '9')
-                    { LogMsg("SetDomainSecrets: Malformed Port number %d, val %d", *hptr, val); val = 0; break;}
-                    val = val * 10 + *hptr - '0';
-                    hptr++;
-                }
-                if (!val) continue;
-                p = (mDNSu8 *)&val;
-                port.NotAnInteger = p[0] << 8 | p[1];
-            }
-            // The hostbuf is of the format dsid@hostname:port. We don't care about the dsid.
-            hptr = strchr(hostbuf, '@');
-            if (hptr)
-                hptr++;
-            else
-                hptr = hostbuf;
-            if (!MakeDomainNameFromDNSNameString(&hostname, hptr)) { LogMsg("SetDomainSecrets: bad host name %s", hptr); continue; }
-
-            DomainAuthInfo *FoundInList;
-            for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
-                if (SameDomainName(&FoundInList->domain, &domain)) break;
-
-            // Uncomment the line below to view the keys as they're read out of the system keychain
-            // DO NOT SHIP CODE THIS WAY OR YOU'LL LEAK SECRET DATA INTO A PUBLICLY READABLE FILE!
-            //LogInfo("SetDomainSecrets: domain %##s keyname %##s key %s hostname %##s port %d", &domain.c, &keyname.c, stringbuf, hostname.c, (port.b[0] << 8 | port.b[1]));
-            LogInfo("SetDomainSecrets: domain %##s keyname %##s hostname %##s port %d", &domain.c, &keyname.c, hostname.c, (port.b[0] << 8 | port.b[1]));
-
-            // If didn't find desired domain in the list, make a new entry
-            ptr = FoundInList;
-            if (!FoundInList)
-            {
-                ptr = (DomainAuthInfo*) callocL("DomainAuthInfo", sizeof(*ptr));
-                if (!ptr) { LogMsg("SetDomainSecrets: No memory"); continue; }
-            }
-
-            if (mDNS_SetSecretForDomain(m, ptr, &domain, &keyname, stringbuf, &hostname, &port) == mStatus_BadParamErr)
-            {
-                if (!FoundInList) mDNSPlatformMemFree(ptr);     // If we made a new DomainAuthInfo here, and it turned out bad, dispose it immediately
-                continue;
-            }
-
-            ConvertDomainNameToCString(&domain, stringbuf);
-            CFStringRef cfs = CFStringCreateWithCString(NULL, stringbuf, kCFStringEncodingUTF8);
-            if (cfs) { CFArrayAppendValue(sa, cfs); MDNS_DISPOSE_CF_OBJECT(cfs); }
-        }
-        MDNS_DISPOSE_CF_OBJECT(secrets);
-    }
-
-    if (!privateDnsArray || !CFEqual(privateDnsArray, sa))
-    {
-        MDNS_DISPOSE_CF_OBJECT(privateDnsArray);
-
-        privateDnsArray = sa;
-        CFRetain(privateDnsArray);
-        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
-    }
-    MDNS_DISPOSE_CF_OBJECT(sa);
-
-    CheckSuppressUnusableQuestions(m);
-
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-mDNSexport void SetDomainSecrets(mDNS *m)
-{
-#if DEBUG
-    // Don't get secrets for BTMM if running in debug mode
-    if (!IsDebugSocketInUse())
-#endif
-    SetDomainSecrets_internal(m);
-}
-
-mDNSlocal void SetLocalDomains(void)
-{
-    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (!sa) { LogMsg("SetLocalDomains: CFArrayCreateMutable failed"); return; }
-
-    CFArrayAppendValue(sa, CFSTR("local"));
-    CFArrayAppendValue(sa, CFSTR("254.169.in-addr.arpa"));
-    CFArrayAppendValue(sa, CFSTR("8.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("9.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("a.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("b.e.f.ip6.arpa"));
-
-    mDNSDynamicStoreSetConfig(kmDNSMulticastConfig, mDNSNULL, sa);
-    MDNS_DISPOSE_CF_OBJECT(sa);
-}
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, NO_WAKE_FOR_NET_ACCESS)
-mDNSlocal void GetCurrentPMSetting(const CFStringRef name, mDNSs32 *val)
-{
-    CFDictionaryRef dict = SCDynamicStoreCopyValue(NULL, NetworkChangedKey_PowerSettings);
-    if (!dict)
-    {
-        LogSPS("GetCurrentPMSetting: Could not get IOPM CurrentSettings dict");
-    }
-    else
-    {
-        CFNumberRef number = CFDictionaryGetValue(dict, name);
-        if ((number == NULL) || CFGetTypeID(number) != CFNumberGetTypeID() || !CFNumberGetValue(number, kCFNumberSInt32Type, val))
-            *val = 0;
-        MDNS_DISPOSE_CF_OBJECT(dict);
-    }
-}
-#endif
-
-
-mDNSlocal mDNSu8 SystemWakeForNetworkAccess(void)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, NO_WAKE_FOR_NET_ACCESS)
-    LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEBUG, "SystemWakeForNetworkAccess: compile-time disabled");
-    return ((mDNSu8)mDNS_NoWake);
-#else
-    mDNSs32 val = 0;
-    mDNSu8  ret = (mDNSu8)mDNS_NoWake;
-
-    if (DisableSleepProxyClient)
-    {
-       LogSPS("SystemWakeForNetworkAccess: Sleep Proxy Client disabled by command-line option");
-       return ret;
-    }
-
-    GetCurrentPMSetting(CFSTR("Wake On LAN"), &val);
-
-    ret = (mDNSu8)(val != 0) ? mDNS_WakeOnAC : mDNS_NoWake;
-
-
-    LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", ret);
-    return ret;
-#endif
-}
-
-mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
-{
-    mDNSs32 val = 0;
-    // PrioritizeNetworkReachabilityOverSleep has been deprecated.
-    // GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val);
-    // Statically set the PrioritizeNetworkReachabilityOverSleep value to 1 for AppleTV
-    if (IsAppleTV())
-        val = 1;
-    return val != 0 ? mDNStrue : mDNSfalse;
-}
-
-mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    (void)m;
-#else
-    DNSServer *s;
-    // Determine if we're on AppleNW based on DNSServer having 17.x.y.z IPv4 addr
-    for (s = m->DNSServers; s; s = s->next)
-    {
-        if (s->addr.ip.v4.b[0] == 17)
-        {
-            LogInfo("IsAppleNetwork: Found 17.x.y.z DNSServer concluding that we are on AppleNW: %##s %#a", s->domain.c, &s->addr);
-            return mDNStrue;
-        }
-    }
-#endif
-    return mDNSfalse;
-}
-
-// Called with KQueueLock & mDNS lock
-// SetNetworkChanged is allowed to shorten (but not extend) the pause while we wait for configuration changes to settle
-mDNSlocal void SetNetworkChanged(mDNSs32 delay)
-{
-    mDNS *const m = &mDNSStorage;
-    mDNS_CheckLock(m);
-    if (!m->NetworkChanged || m->NetworkChanged - NonZeroTime(m->timenow + delay) > 0)
-    {
-        m->NetworkChanged = NonZeroTime(m->timenow + delay);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "SetNetworkChanged: Scheduling in %d ticks", delay);
-    }
-    else
-   	{
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "SetNetworkChanged: *NOT* increasing delay from %d to %d", m->NetworkChanged - m->timenow, delay);
-    }
-}
-
-// Called with KQueueLock & mDNS lock
-mDNSlocal void SetKeyChainTimer(mDNSs32 delay)
-{
-    mDNS *const m = &mDNSStorage;
-    // If it's not set or it needs to happen sooner than when it's currently set
-    if (!m->p->KeyChainTimer || m->p->KeyChainTimer - NonZeroTime(m->timenow + delay) > 0)
-    {
-        m->p->KeyChainTimer = NonZeroTime(m->timenow + delay);
-        LogInfo("SetKeyChainTimer: %d", delay);
-    }
-}
-
-mDNSexport void mDNSMacOSXNetworkChanged(void)
-{
-    mDNS *const m = &mDNSStorage;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "*** Network Configuration Change ***  %d ticks late" PUB_S,
-        m->NetworkChanged ? mDNS_TimeNow(m) - m->NetworkChanged : 0,
-        m->NetworkChanged ? "" : " (no scheduled configuration change)");
-    m->NetworkChanged = 0;       // If we received a network change event and deferred processing, we're now dealing with it
-
-    // If we have *any* TENTATIVE IPv6 addresses, wait until they've finished configuring
-    int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0);
-    if (InfoSocket > 0)
-    {
-        mDNSBool tentative = mDNSfalse;
-        struct ifaddrs *ifa = myGetIfAddrs(1);
-        while (ifa)
-        {
-            if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6)
-            {
-                struct in6_ifreq ifr6;
-                mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
-                mdns_strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
-                ifr6.ifr_addr = *(struct sockaddr_in6 *)ifa->ifa_addr;
-                // We need to check for IN6_IFF_TENTATIVE here, not IN6_IFF_NOTREADY, because
-                // IN6_IFF_NOTREADY includes both IN6_IFF_TENTATIVE and IN6_IFF_DUPLICATED addresses.
-                // We can expect that an IN6_IFF_TENTATIVE address will shortly become ready,
-                // but an IN6_IFF_DUPLICATED address may not.
-                if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
-                {
-                    if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
-                    {
-                        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                            "*** Network Configuration Change ***  IPv6 address " PRI_IPv6_ADDR " TENTATIVE, will retry",
-                            &ifr6.ifr_addr.sin6_addr);
-                        tentative = mDNStrue;
-                        // no need to check other interfaces if we already found out that one interface is TENTATIVE
-                        break;
-                    }
-                }
-            }
-            ifa = ifa->ifa_next;
-        }
-        close(InfoSocket);
-        if (tentative)
-        {
-            mDNS_Lock(m);
-            SetNetworkChanged(mDNSPlatformOneSecond / 2);
-            mDNS_Unlock(m);
-            return;
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "*** Network Configuration Change ***  No IPv6 address TENTATIVE, will continue");
-    }
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-    m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
-    MarkAllInterfacesInactive(utc);
-    UpdateInterfaceList(utc);
-    ClearInactiveInterfaces(utc);
-    SetupActiveInterfaces(utc);
-    ReorderInterfaceList();
-
-
-    uDNS_SetupDNSConfig(m);
-    mDNS_ConfigChanged(m);
-
-    if (IsAppleNetwork(m) != mDNS_McastTracingEnabled)
-    {
-        mDNS_McastTracingEnabled = mDNS_McastTracingEnabled ? mDNSfalse : mDNStrue;
-        LogInfo("mDNSMacOSXNetworkChanged: Multicast Tracing %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
-        UpdateDebugState();
-    }
-
-}
-
-// Copy the fourth slash-delimited element from either:
-//   State:/Network/Interface/<bsdname>/IPv4
-// or
-//   Setup:/Network/Service/<servicename>/Interface
-mDNSlocal CFStringRef CopyNameFromKey(CFStringRef key)
-{
-    CFArrayRef a;
-    CFStringRef name = NULL;
-
-    a = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
-    if (a && CFArrayGetCount(a) == 5) name = CFRetain(CFArrayGetValueAtIndex(a, 3));
-    if (a != NULL) MDNS_DISPOSE_CF_OBJECT(a);
-
-    return name;
-}
-
-// Whether a key from a network change notification corresponds to
-// an IP service that is explicitly configured for IPv4 Link Local
-mDNSlocal int ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
-{
-    CFDictionaryRef dict = NULL;
-    CFMutableArrayRef a;
-    const void **keys = NULL, **vals = NULL;
-    CFStringRef pattern = NULL;
-    CFIndex i, ic, j, jc;
-    int found = 0;
-
-    jc = CFArrayGetCount(inkeys);
-    if (jc <= 0) goto done;
-
-    a = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (a == NULL) goto done;
-
-    // Setup:/Network/Service/[^/]+/Interface
-    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
-    if (pattern == NULL) goto done;
-    CFArrayAppendValue(a, pattern);
-    MDNS_DISPOSE_CF_OBJECT(pattern);
-
-    // Setup:/Network/Service/[^/]+/IPv4
-    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4);
-    if (pattern == NULL) goto done;
-    CFArrayAppendValue(a, pattern);
-    MDNS_DISPOSE_CF_OBJECT(pattern);
-
-    dict = SCDynamicStoreCopyMultiple(NULL, NULL, a);
-    MDNS_DISPOSE_CF_OBJECT(a);
-
-    if (!dict)
-    {
-        LogMsg("ChangedKeysHaveIPv4LL: No dictionary");
-        goto done;
-    }
-
-    ic = CFDictionaryGetCount(dict);
-    if (ic <= 0)
-    {
-        LogMsg("ChangedKeysHaveIPv4LL: Empty dictionary");
-        goto done;
-    }
-
-    vals = (const void **) mDNSPlatformMemAllocate(sizeof(void *) * (mDNSu32)ic);
-    keys = (const void **) mDNSPlatformMemAllocate(sizeof(void *) * (mDNSu32)ic);
-    CFDictionaryGetKeysAndValues(dict, keys, vals);
-
-    // For each key we were given...
-    for (j = 0; j < jc; j++)
-    {
-        CFStringRef key = CFArrayGetValueAtIndex(inkeys, j);
-        CFStringRef ifname = NULL;
-
-        char buf[256];
-
-        // It would be nice to use a regex here
-        if (!CFStringHasPrefix(key, CFSTR("State:/Network/Interface/")) || !CFStringHasSuffix(key, kSCEntNetIPv4)) continue;
-
-        if ((ifname = CopyNameFromKey(key)) == NULL) continue;
-        if (mDNS_LoggingEnabled)
-        {
-            if (!CFStringGetCString(ifname, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-            LogInfo("ChangedKeysHaveIPv4LL: potential ifname %s", buf);
-        }
-
-        // Loop over the interfaces to find matching the ifname, and see if that one has kSCValNetIPv4ConfigMethodLinkLocal
-        for (i = 0; i < ic; i++)
-        {
-            CFDictionaryRef ipv4dict;
-            CFStringRef name;
-            CFStringRef serviceid;
-            CFStringRef configmethod;
-
-            if (!CFStringHasSuffix(keys[i], kSCEntNetInterface)) continue;
-
-            if (CFDictionaryGetTypeID() != CFGetTypeID(vals[i])) continue;
-
-            if ((name = CFDictionaryGetValue(vals[i], kSCPropNetInterfaceDeviceName)) == NULL) continue;
-
-            if (!CFEqual(ifname, name)) continue;
-
-            if ((serviceid = CopyNameFromKey(keys[i])) == NULL) continue;
-            if (mDNS_LoggingEnabled)
-            {
-                if (!CFStringGetCString(serviceid, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-                LogInfo("ChangedKeysHaveIPv4LL: found serviceid %s", buf);
-            }
-
-            pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceid, kSCEntNetIPv4);
-            MDNS_DISPOSE_CF_OBJECT(serviceid);
-            if (pattern == NULL) continue;
-
-            ipv4dict = CFDictionaryGetValue(dict, pattern);
-            MDNS_DISPOSE_CF_OBJECT(pattern);
-            if (!ipv4dict || CFDictionaryGetTypeID() != CFGetTypeID(ipv4dict)) continue;
-
-            configmethod = CFDictionaryGetValue(ipv4dict, kSCPropNetIPv4ConfigMethod);
-            if (!configmethod) continue;
-
-            if (mDNS_LoggingEnabled)
-            {
-                if (!CFStringGetCString(configmethod, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-                LogInfo("ChangedKeysHaveIPv4LL: configmethod %s", buf);
-            }
-
-            if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found++; break; }
-        }
-
-        MDNS_DISPOSE_CF_OBJECT(ifname);
-    }
-
-done:
-    if (vals != NULL) mDNSPlatformMemFree(vals);
-    if (keys != NULL) mDNSPlatformMemFree(keys);
-    MDNS_DISPOSE_CF_OBJECT(dict);
-
-    return found;
-}
-
-mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
-{
-    (void)store;        // Parameter not used
-    mDNS *const m = (mDNS *const)context;
-    KQueueLock();
-    mDNS_Lock(m);
-
-    //mDNSs32 delay = mDNSPlatformOneSecond * 2;                // Start off assuming a two-second delay
-    const mDNSs32 delay = (mDNSPlatformOneSecond + 39) / 40;    // 25 ms delay
-
-    const CFIndex c = CFArrayGetCount(changedKeys);             // Count changes
-    CFRange range = { 0, c };
-    const int c_host = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Hostnames   ) != 0);
-    const int c_comp = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
-    const int c_udns = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS         ) != 0);
-    const int c_ddns = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
-    const int c_v4ll = ChangedKeysHaveIPv4LL(changedKeys);
-    int c_fast = 0;
-
-    // Do immediate network changed processing for "p2p*" interfaces and
-    // for interfaces with the IFEF_DIRECTLINK or IFEF_AWDL flag set or association with a CarPlay
-    // hosted SSID.
-    {
-        CFArrayRef  labels;
-        CFIndex     n;
-        for (CFIndex i = 0; i < c; i++)
-        {
-            CFStringRef key = CFArrayGetValueAtIndex(changedKeys, i);
-
-            // Only look at keys with prefix "State:/Network/Interface/"
-            if (!CFStringHasPrefix(key, NetworkChangedKey_StateInterfacePrefix))
-                continue;
-
-            // And suffix "IPv6" or "IPv4".
-            if (!CFStringHasSuffix(key, kSCEntNetIPv6) && !CFStringHasSuffix(key, kSCEntNetIPv4))
-                continue;
-
-            labels = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
-            if (labels == NULL)
-                break;
-            n = CFArrayGetCount(labels);
-
-            // Interface changes will have keys of the form:
-            //     State:/Network/Interface/<interfaceName>/IPv6
-            // Thus five '/' seperated fields, the 4th one being the <interfaceName> string.
-            if (n == 5)
-            {
-                char buf[256];
-
-                // The 4th label (index = 3) should be the interface name.
-                if (CFStringGetCString(CFArrayGetValueAtIndex(labels, 3), buf, sizeof(buf), kCFStringEncodingUTF8)
-                    && (strstr(buf, "p2p") || (getExtendedFlags(buf) & (IFEF_DIRECTLINK | IFEF_AWDL)) || IsCarPlaySSID(buf)))
-                {
-                    LogInfo("NetworkChanged: interface %s qualifies for reduced change handling delay", buf);
-                    c_fast++;
-                    MDNS_DISPOSE_CF_OBJECT(labels);
-                    break;
-                }
-            }
-            MDNS_DISPOSE_CF_OBJECT(labels);
-        }
-    }
-
-    //if (c && c - c_host - c_comp - c_udns - c_ddns - c_v4ll - c_fast == 0)
-    //    delay = mDNSPlatformOneSecond/10;  // If these were the only changes, shorten delay
-
-    if (mDNS_LoggingEnabled)
-    {
-        CFIndex i;
-        for (i=0; i<c; i++)
-        {
-            char buf[256];
-            if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys, i), buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "*** Network Configuration Change *** SC key: " PUB_S, buf);
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "*** Network Configuration Change *** %ld change" PUB_S " " PUB_S PUB_S PUB_S PUB_S PUB_S PUB_S "delay %d" PUB_S,
-            (long)c, c>1 ? "s" : "",
-            c_host ? "(Local Hostname) " : "",
-            c_comp ? "(Computer Name) "  : "",
-            c_udns ? "(DNS) "            : "",
-            c_ddns ? "(DynamicDNS) "     : "",
-            c_v4ll ? "(kSCValNetIPv4ConfigMethodLinkLocal) " : "",
-            c_fast ? "(P2P/IFEF_DIRECTLINK/IFEF_AWDL/IsCarPlaySSID) "  : "",
-            delay,
-            c_ddns ? " + SetKeyChainTimer" : "");
-    }
-
-    SetNetworkChanged(delay);
-
-    // Other software might pick up these changes to register or browse in WAB or BTMM domains,
-    // so in order for secure updates to be made to the server, make sure to read the keychain and
-    // setup the DomainAuthInfo before handing the network change.
-    // If we don't, then we will first try to register services in the clear, then later setup the
-    // DomainAuthInfo, which is incorrect.
-    if (c_ddns)
-        SetKeyChainTimer(delay);
-
-    // Don't try to call mDNSMacOSXNetworkChanged() here -- we're running on the wrong thread
-
-    mDNS_Unlock(m);
-    KQueueUnlock("NetworkChanged");
-}
-
-
-mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
-{
-    mDNS *const m = (mDNS *const)info;
-    (void)store;
-
-    KQueueLock();   // serialize with KQueueLoop()
-
-    LogInfo("DynamicStoreReconnected: Reconnected");
-
-    // State:/Network/MulticastDNS
-    SetLocalDomains();
-
-    // State:/Network/DynamicDNS
-    if (m->FQDN.c[0])
-        mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
-
-    // Note: PrivateDNS and BackToMyMac are automatically populated when configd is restarted
-    // as we receive network change notifications and thus not necessary. But we leave it here
-    // so that if things are done differently in the future, this code still works.
-
-    // State:/Network/PrivateDNS
-    if (privateDnsArray)
-        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
-
-    KQueueUnlock("DynamicStoreReconnected");
-}
-
-mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
-{
-    mStatus err = -1;
-    SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL };
-    SCDynamicStoreRef store    = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged, &context);
-    CFMutableArrayRef keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
-    CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
-    CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-    if (!store) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error; }
-    if (!keys || !pattern1 || !pattern2 || !patterns) goto error;
-
-    CFArrayAppendValue(keys, NetworkChangedKey_IPv4);
-    CFArrayAppendValue(keys, NetworkChangedKey_IPv6);
-    CFArrayAppendValue(keys, NetworkChangedKey_Hostnames);
-    CFArrayAppendValue(keys, NetworkChangedKey_Computername);
-    CFArrayAppendValue(keys, NetworkChangedKey_DNS);
-    CFArrayAppendValue(keys, NetworkChangedKey_DynamicDNS);
-    CFArrayAppendValue(keys, NetworkChangedKey_PowerSettings);
-    CFArrayAppendValue(patterns, pattern1);
-    CFArrayAppendValue(patterns, pattern2);
-    CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
-    if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
-    { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error; }
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue()))
-    { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
-#else
-    m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
-    if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
-    CFRunLoopAddSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode);
-#endif
-    SCDynamicStoreSetDisconnectCallBack(store, DynamicStoreReconnected);
-    m->p->Store = store;
-    err = 0;
-    goto exit;
-
-error:
-    MDNS_DISPOSE_CF_OBJECT(store);
-
-exit:
-    MDNS_DISPOSE_CF_OBJECT(patterns);
-    MDNS_DISPOSE_CF_OBJECT(pattern2);
-    MDNS_DISPOSE_CF_OBJECT(pattern1);
-    MDNS_DISPOSE_CF_OBJECT(keys);
-
-    return(err);
-}
-
-mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context, __unused mDNSBool encounteredEOF)
-{
-    mDNS *const m = (mDNS *const)context;
-
-    mDNS_Lock(m);
-
-    struct { struct kern_event_msg k; char extra[256]; } msg;
-    ssize_t bytes = recv(s1, &msg, sizeof(msg), 0);
-    if (bytes < 0)
-        LogMsg("SysEventCallBack: recv error %ld errno %d (%s)", (long)bytes, errno, strerror(errno));
-    else
-    {
-        LogInfo("SysEventCallBack got %ld bytes size %u %X %s %X %s %X %s id %d code %d %s",
-                (long)bytes, msg.k.total_size,
-                msg.k.vendor_code, msg.k.vendor_code  == KEV_VENDOR_APPLE  ? "KEV_VENDOR_APPLE"  : "?",
-                msg.k.kev_class, msg.k.kev_class    == KEV_NETWORK_CLASS ? "KEV_NETWORK_CLASS" : "?",
-                msg.k.kev_subclass, msg.k.kev_subclass == KEV_DL_SUBCLASS   ? "KEV_DL_SUBCLASS"   : "?",
-                msg.k.id, msg.k.event_code,
-                msg.k.event_code == KEV_DL_SIFFLAGS             ? "KEV_DL_SIFFLAGS"             :
-                msg.k.event_code == KEV_DL_SIFMETRICS           ? "KEV_DL_SIFMETRICS"           :
-                msg.k.event_code == KEV_DL_SIFMTU               ? "KEV_DL_SIFMTU"               :
-                msg.k.event_code == KEV_DL_SIFPHYS              ? "KEV_DL_SIFPHYS"              :
-                msg.k.event_code == KEV_DL_SIFMEDIA             ? "KEV_DL_SIFMEDIA"             :
-                msg.k.event_code == KEV_DL_SIFGENERIC           ? "KEV_DL_SIFGENERIC"           :
-                msg.k.event_code == KEV_DL_ADDMULTI             ? "KEV_DL_ADDMULTI"             :
-                msg.k.event_code == KEV_DL_DELMULTI             ? "KEV_DL_DELMULTI"             :
-                msg.k.event_code == KEV_DL_IF_ATTACHED          ? "KEV_DL_IF_ATTACHED"          :
-                msg.k.event_code == KEV_DL_IF_DETACHING         ? "KEV_DL_IF_DETACHING"         :
-                msg.k.event_code == KEV_DL_IF_DETACHED          ? "KEV_DL_IF_DETACHED"          :
-                msg.k.event_code == KEV_DL_LINK_OFF             ? "KEV_DL_LINK_OFF"             :
-                msg.k.event_code == KEV_DL_LINK_ON              ? "KEV_DL_LINK_ON"              :
-                msg.k.event_code == KEV_DL_PROTO_ATTACHED       ? "KEV_DL_PROTO_ATTACHED"       :
-                msg.k.event_code == KEV_DL_PROTO_DETACHED       ? "KEV_DL_PROTO_DETACHED"       :
-                msg.k.event_code == KEV_DL_LINK_ADDRESS_CHANGED ? "KEV_DL_LINK_ADDRESS_CHANGED" :
-                msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED    ? "KEV_DL_WAKEFLAGS_CHANGED"    :
-                msg.k.event_code == KEV_DL_IF_IDLE_ROUTE_REFCNT ? "KEV_DL_IF_IDLE_ROUTE_REFCNT" :
-                msg.k.event_code == KEV_DL_IFCAP_CHANGED        ? "KEV_DL_IFCAP_CHANGED"        :
-                msg.k.event_code == KEV_DL_LINK_QUALITY_METRIC_CHANGED    ? "KEV_DL_LINK_QUALITY_METRIC_CHANGED"    :
-                 "?");
-
-        // We receive network change notifications both through configd and through SYSPROTO_EVENT socket.
-        // Configd may not generate network change events for manually configured interfaces (i.e., non-DHCP)
-        // always during sleep/wakeup due to some race conditions (See radar:8666757). At the same time, if
-        // "Wake on Network Access" is not turned on, the notification will not have KEV_DL_WAKEFLAGS_CHANGED.
-        // Hence, during wake up, if we see a KEV_DL_LINK_ON (i.e., link is UP), we trigger a network change.
-
-        if (msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED || msg.k.event_code == KEV_DL_LINK_ON)
-            SetNetworkChanged(mDNSPlatformOneSecond * 2);
-    }
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal mStatus WatchForSysEvents(mDNS *const m)
-{
-    m->p->SysEventNotifier = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
-    if (m->p->SysEventNotifier < 0)
-    { LogMsg("WatchForSysEvents: socket failed error %d errno %d (%s)", m->p->SysEventNotifier, errno, strerror(errno)); return(mStatus_NoMemoryErr); }
-
-    struct kev_request kev_req = { KEV_VENDOR_APPLE, KEV_NETWORK_CLASS, KEV_DL_SUBCLASS };
-    int err = ioctl(m->p->SysEventNotifier, SIOCSKEVFILT, &kev_req);
-    if (err < 0)
-    {
-        LogMsg("WatchForSysEvents: SIOCSKEVFILT failed error %d errno %d (%s)", err, errno, strerror(errno));
-        close(m->p->SysEventNotifier);
-        m->p->SysEventNotifier = -1;
-        return(mStatus_UnknownErr);
-    }
-
-    m->p->SysEventKQueue.KQcallback = SysEventCallBack;
-    m->p->SysEventKQueue.KQcontext  = m;
-    m->p->SysEventKQueue.KQtask     = "System Event Notifier";
-    KQueueSet(m->p->SysEventNotifier, EV_ADD, EVFILT_READ, &m->p->SysEventKQueue);
-
-    return(mStatus_NoError);
-}
-
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context)
-{
-    LogInfo("***   Keychain Changed   ***");
-    mDNS *const m = (mDNS *const)context;
-    SecKeychainRef skc;
-    OSStatus err = SecKeychainCopyDefault(&skc);
-    if (!err)
-    {
-        if (info->keychain == skc)
-        {
-            // For delete events, attempt to verify what item was deleted fail because the item is already gone, so we just assume they may be relevant
-            mDNSBool relevant = (keychainEvent == kSecDeleteEvent);
-            if (!relevant)
-            {
-                UInt32 tags[3] = { kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr };
-                SecKeychainAttributeInfo attrInfo = { 3, tags, NULL };  // Count, array of tags, array of formats
-                SecKeychainAttributeList *a = NULL;
-                err = SecKeychainItemCopyAttributesAndData(info->item, &attrInfo, NULL, &a, NULL, NULL);
-                if (!err)
-                {
-                    relevant = ((a->attr[0].length == 4 && (!strncasecmp(a->attr[0].data, "ddns", 4) || !strncasecmp(a->attr[0].data, "sndd", 4))) ||
-                                (a->attr[1].length >= mDNSPlatformStrLen(dnsprefix) && (!strncasecmp(a->attr[1].data, dnsprefix, mDNSPlatformStrLen(dnsprefix)))));
-                    SecKeychainItemFreeAttributesAndData(a, NULL);
-                }
-            }
-            if (relevant)
-            {
-                LogInfo("***   Keychain Changed   *** KeychainEvent=%d %s",
-                        keychainEvent,
-                        keychainEvent == kSecAddEvent    ? "kSecAddEvent"    :
-                        keychainEvent == kSecDeleteEvent ? "kSecDeleteEvent" :
-                        keychainEvent == kSecUpdateEvent ? "kSecUpdateEvent" : "<Unknown>");
-                // We're running on the CFRunLoop (Mach port) thread, not the kqueue thread, so we need to grab the KQueueLock before proceeding
-                KQueueLock();
-                mDNS_Lock(m);
-
-                // To not read the keychain twice: when BTMM is enabled, changes happen to the keychain
-                // then the BTMM DynStore dictionary, so delay reading the keychain for a second.
-                // NetworkChanged() will reset the keychain timer to fire immediately when the DynStore changes.
-                //
-                // In the "fixup" case where the BTMM DNS servers aren't accepting the key mDNSResponder has,
-                // the DynStore dictionary won't change (because the BTMM zone won't change).  In that case,
-                // a one second delay is ok, as we'll still converge to correctness, and there's no race
-                // condition between the RegistrationDomain and the DomainAuthInfo.
-                //
-                // Lastly, non-BTMM WAB cases can use the keychain but not the DynStore, so we need to set
-                // the timer here, as it will not get set by NetworkChanged().
-                SetKeyChainTimer(mDNSPlatformOneSecond);
-
-                mDNS_Unlock(m);
-                KQueueUnlock("KeychainChanged");
-            }
-        }
-        MDNS_DISPOSE_CF_OBJECT(skc);
-    }
-
-    return 0;
-}
-#endif
-
-mDNSlocal void PowerOn(mDNS *const m)
-{
-    mDNSCoreMachineSleep(m, false);     // Will set m->SleepState = SleepState_Awake;
-
-    if (m->p->WakeAtUTC)
-    {
-        long utc = mDNSPlatformUTC();
-        // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake
-        mdns_power_cancel_all_events(kMDNSResponderID);
-        if (m->p->WakeAtUTC - utc > 30)
-        {
-            LogSPS("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc);
-        }
-        else if (utc - m->p->WakeAtUTC > 30)
-        {
-            LogSPS("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC);
-        }
-        else if (IsAppleTV())
-        {
-            LogSPS("PowerChanged PowerOn %d seconds late, device is an AppleTV running iOS so not re-sleeping", utc - m->p->WakeAtUTC);
-        }
-        else
-        {
-            LogSPS("PowerChanged: Waking for network maintenance operations %d seconds early; re-sleeping in 20 seconds", m->p->WakeAtUTC - utc);
-            m->p->RequestReSleep = mDNS_TimeNow(m) + 20 * mDNSPlatformOneSecond;
-        }
-    }
-
-    // Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities.
-    // This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc.
-    // We will clear this assertion as soon as we think the mainenance activities are done.
-    mDNSPlatformPreventSleep(DARK_WAKE_TIME, "mDNSResponder:maintenance");
-
-}
-
-mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
-{
-    mDNS *const m = (mDNS *const)refcon;
-    KQueueLock();
-    (void)service;    // Parameter not used
-    debugf("PowerChanged %X %lX", messageType, messageArgument);
-
-    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-
-    switch(messageType)
-    {
-    case kIOMessageCanSystemPowerOff:       LogSPS("PowerChanged kIOMessageCanSystemPowerOff     (no action)"); break;          // E0000240
-    case kIOMessageSystemWillPowerOff:      LogSPS("PowerChanged kIOMessageSystemWillPowerOff");                                // E0000250
-        mDNSCoreMachineSleep(m, true);
-        if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged();
-        break;
-    case kIOMessageSystemWillNotPowerOff:   LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break;          // E0000260
-    case kIOMessageCanSystemSleep:          LogSPS("PowerChanged kIOMessageCanSystemSleep");                    break;          // E0000270
-    case kIOMessageSystemWillSleep:         LogSPS("PowerChanged kIOMessageSystemWillSleep");                                   // E0000280
-        mDNSCoreMachineSleep(m, true);
-        break;
-    case kIOMessageSystemWillNotSleep:      LogSPS("PowerChanged kIOMessageSystemWillNotSleep    (no action)"); break;          // E0000290
-    case kIOMessageSystemHasPoweredOn:      LogSPS("PowerChanged kIOMessageSystemHasPoweredOn");                                // E0000300
-        // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
-        if (m->SleepState)
-        {
-            LogMsg("PowerChanged kIOMessageSystemHasPoweredOn: ERROR m->SleepState %d", m->SleepState);
-            PowerOn(m);
-        }
-        // Just to be safe, schedule a mDNSMacOSXNetworkChanged(), in case we never received
-        // the System Configuration Framework "network changed" event that we expect
-        // to receive some time shortly after the kIOMessageSystemWillPowerOn message
-        mDNS_Lock(m);
-        SetNetworkChanged(mDNSPlatformOneSecond * 2);
-        mDNS_Unlock(m);
-
-        break;
-    case kIOMessageSystemWillRestart:       LogSPS("PowerChanged kIOMessageSystemWillRestart     (no action)"); break;          // E0000310
-    case kIOMessageSystemWillPowerOn:       LogSPS("PowerChanged kIOMessageSystemWillPowerOn");                                 // E0000320
-
-        // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
-        if (m->SleepState != SleepState_Sleeping)
-        {
-            LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m->SleepState);
-            m->SleepState = SleepState_Sleeping;
-            mDNSMacOSXNetworkChanged();
-        }
-        PowerOn(m);
-        break;
-    default:                                LogSPS("PowerChanged unknown message %X", messageType); break;
-    }
-
-    if (messageType == kIOMessageSystemWillSleep)
-        m->p->SleepCookie = (long)messageArgument;
-    else if (messageType == kIOMessageCanSystemSleep)
-        IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
-
-    KQueueUnlock("PowerChanged Sleep/Wake");
-}
-
-// iPhone OS doesn't currently have SnowLeopard's IO Power Management
-// but it does define kIOPMAcknowledgmentOptionSystemCapabilityRequirements
-#if defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) && TARGET_OS_OSX
-mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities eventDescriptor)
-{
-    mDNS *const m = (mDNS *const)refcon;
-    KQueueLock();
-    LogSPS("SnowLeopardPowerChanged %X %X %X%s%s%s%s%s",
-           connection, token, eventDescriptor,
-           eventDescriptor & kIOPMSystemPowerStateCapabilityCPU     ? " CPU"     : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityVideo   ? " Video"   : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityAudio   ? " Audio"   : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityNetwork ? " Network" : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityDisk    ? " Disk"    : "");
-
-    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-
-    if (eventDescriptor & kIOPMSystemPowerStateCapabilityCPU)
-    {
-        // We might be in Sleeping or Transferring state. When we go from "wakeup" to "sleep" state, we don't
-        // go directly to sleep state, but transfer in to the sleep state during which SleepState is set to
-        // SleepState_Transferring. During that time, we might get another wakeup before we transition to Sleeping
-        // state. In that case, we need to acknowledge the previous "sleep" before we acknowledge the wakeup.
-        if (m->SleepLimit)
-        {
-            LogSPS("SnowLeopardPowerChanged: Waking up, Acking old Sleep, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
-            IOPMConnectionAcknowledgeEvent(connection, (IOPMConnectionMessageToken)m->p->SleepCookie);
-            m->SleepLimit = 0;
-        }
-        LogSPS("SnowLeopardPowerChanged: Waking up, Acking Wakeup, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
-        // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
-        if (m->SleepState != SleepState_Awake)
-        {
-            PowerOn(m);
-            // If the network notifications have already come before we got the wakeup, we ignored them and
-            // in case we get no more, we need to trigger one.
-            mDNS_Lock(m);
-            SetNetworkChanged(mDNSPlatformOneSecond * 2);
-            mDNS_Unlock(m);
-        }
-        IOPMConnectionAcknowledgeEvent(connection, token);
-    }
-    else
-    {
-        // CPU sleeping. Should not get this repeatedly -- once we're told that the CPU is halting
-        // we should hear nothing more until we're told that the CPU has started executing again.
-        if (m->SleepState) LogMsg("SnowLeopardPowerChanged: Sleep Error %X m->SleepState %d", eventDescriptor, m->SleepState);
-        //sleep(5);
-        //mDNSMacOSXNetworkChanged(m);
-        mDNSCoreMachineSleep(m, true);
-        //if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
-        m->p->SleepCookie = token;
-    }
-
-    KQueueUnlock("SnowLeopardPowerChanged Sleep/Wake");
-}
-#endif
-
-// MARK: - /etc/hosts support
-
-// Implementation Notes
-//
-// As /etc/hosts file can be huge (1000s of entries - when this comment was written, the test file had about
-// 23000 entries with about 4000 duplicates), we can't use a linked list to store these entries. So, we parse
-// them into a hash table. The implementation need to be able to do the following things efficiently
-//
-// 1. Detect duplicates e.g., two entries with "1.2.3.4 foo"
-// 2. Detect whether /etc/hosts has changed and what has changed since the last read from the disk
-// 3. Ability to support multiple addresses per name e.g., "1.2.3.4 foo, 2.3.4.5 foo". To support this, we
-//    need to be able set the RRSet of a resource record to the first one in the list and also update when
-//    one of them go away. This is needed so that the core thinks that they are all part of the same RRSet and
-//    not a duplicate
-// 4. Don't maintain any local state about any records registered with the core to detect changes to /etc/hosts
-//
-// CFDictionary is not a suitable candidate because it does not support duplicates and even if we use a custom
-// "hash" function to solve this, the others are hard to solve. Hence, we share the hash (AuthHash) implementation
-// of the core layer which does all of the above very efficiently
-
-#define ETCHOSTS_BUFSIZE    1024    // Buffer size to parse a single line in /etc/hosts
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *rr, mStatus result)
-{
-    (void)m;  // unused
-    (void)rr;
-    (void)result;
-    if (result == mStatus_MemFree)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "FreeEtcHosts: " PRI_S, ARDisplayString(m, rr));
-        freeL("etchosts", rr);
-    }
-}
-
-// Returns true on success and false on failure
-mDNSlocal mDNSBool mDNSMacOSXCreateEtcHostsEntry(const domainname *domain, const struct sockaddr *sa, const domainname *cname, char *ifname, AuthHash *auth)
-{
-    AuthRecord *rr;
-    mDNSu32 namehash;
-    AuthGroup *ag;
-    mDNSInterfaceID InterfaceID = mDNSInterface_LocalOnly;
-    mDNSu16 rrtype;
-
-    if (!domain)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! name NULL");
-        return mDNSfalse;
-    }
-    if (!sa && !cname)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa and cname both NULL");
-        return mDNSfalse;
-    }
-
-    if (sa && sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa with bad family %d", sa->sa_family);
-        return mDNSfalse;
-    }
-
-
-    if (ifname)
-    {
-        mDNSu32 ifindex = if_nametoindex(ifname);
-        if (!ifindex)
-        {
-            LogMsg("mDNSMacOSXCreateEtcHostsEntry: hosts entry %##s with invalid ifname %s", domain->c, ifname);
-            return mDNSfalse;
-        }
-        InterfaceID = (mDNSInterfaceID)(uintptr_t)ifindex;
-    }
-
-    if (sa)
-        rrtype = (sa->sa_family == AF_INET ? kDNSType_A : kDNSType_AAAA);
-    else
-        rrtype = kDNSType_CNAME;
-
-    // Check for duplicates. See whether we parsed an entry before like this ?
-    namehash = DomainNameHashValue(domain);
-    ag = AuthGroupForName(auth, namehash, domain);
-    if (ag)
-    {
-        rr = ag->members;
-        while (rr)
-        {
-            if (rr->resrec.rrtype == rrtype)
-            {
-                if (rrtype == kDNSType_A)
-                {
-                    mDNSv4Addr ip;
-                    ip.NotAnInteger = ((const struct sockaddr_in*)sa)->sin_addr.s_addr;
-                    if (mDNSSameIPv4Address(rr->resrec.rdata->u.ipv4, ip) && InterfaceID == rr->resrec.InterfaceID)
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv4 address and InterfaceID for name %##s ID %d", domain->c, IIDPrintable(InterfaceID));
-                        return mDNSfalse;
-                    }
-                }
-                else if (rrtype == kDNSType_AAAA)
-                {
-                    mDNSv6Addr ip6;
-                    ip6.l[0] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
-                    ip6.l[1] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
-                    ip6.l[2] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
-                    ip6.l[3] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
-                    if (mDNSSameIPv6Address(rr->resrec.rdata->u.ipv6, ip6) && InterfaceID == rr->resrec.InterfaceID)
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv6 address and InterfaceID for name %##s ID %d", domain->c, IIDPrintable(InterfaceID));
-                        return mDNSfalse;
-                    }
-                }
-                else if (rrtype == kDNSType_CNAME)
-                {
-                    if (SameDomainName(&rr->resrec.rdata->u.name, cname))
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same cname %##s for name %##s", cname->c, domain->c);
-                        return mDNSfalse;
-                    }
-                }
-            }
-            rr = rr->next;
-        }
-    }
-    rr = (AuthRecord *) callocL("etchosts", sizeof(*rr));
-    if (rr == NULL) return mDNSfalse;
-    mDNS_SetupResourceRecord(rr, NULL, InterfaceID, rrtype, 1, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, FreeEtcHosts, NULL);
-    AssignDomainName(&rr->namestorage, domain);
-
-    if (sa)
-    {
-        rr->resrec.rdlength = sa->sa_family == AF_INET ? sizeof(mDNSv4Addr) : sizeof(mDNSv6Addr);
-        if (sa->sa_family == AF_INET)
-            rr->resrec.rdata->u.ipv4.NotAnInteger = ((const struct sockaddr_in*)sa)->sin_addr.s_addr;
-        else
-        {
-            rr->resrec.rdata->u.ipv6.l[0] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
-            rr->resrec.rdata->u.ipv6.l[1] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
-            rr->resrec.rdata->u.ipv6.l[2] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
-            rr->resrec.rdata->u.ipv6.l[3] = ((const struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
-        }
-    }
-    else
-    {
-        rr->resrec.rdlength = DomainNameLength(cname);
-        rr->resrec.rdata->u.name.c[0] = 0;
-        AssignDomainName(&rr->resrec.rdata->u.name, cname);
-    }
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-    LogInfo("mDNSMacOSXCreateEtcHostsEntry: Adding resource record %s ID %d", ARDisplayString(&mDNSStorage, rr), IIDPrintable(rr->resrec.InterfaceID));
-    InsertAuthRecord(&mDNSStorage, auth, rr);
-    return mDNStrue;
-}
-
-mDNSlocal int EtcHostsParseOneName(int start, int length, char *buffer, char **name)
-{
-    int i;
-
-    *name = NULL;
-    for (i = start; i < length; i++)
-    {
-        if (buffer[i] == '#')
-            return -1;
-        if (buffer[i] != ' ' && buffer[i] != ',' && buffer[i] != '\t')
-        {
-            *name = &buffer[i];
-
-            // Found the start of a name, find the end and null terminate
-            for (i++; i < length; i++)
-            {
-                if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
-                {
-                    buffer[i] = 0;
-                    break;
-                }
-            }
-            return i;
-        }
-    }
-    return -1;
-}
-
-mDNSlocal void mDNSMacOSXParseEtcHostsLine(char *buffer, int length, AuthHash *auth)
-{
-    int i;
-    int ifStart = 0;
-    char *ifname = NULL;
-    domainname name1d;
-    domainname name2d;
-    char *name1;
-    char *name2;
-    int aliasIndex;
-
-    //Ignore leading whitespaces and tabs
-    while (*buffer == ' ' || *buffer == '\t')
-    {
-        buffer++;
-        length--;
-    }
-
-    // Find the end of the address string
-    for (i = 0; i < length; i++)
-    {
-        if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t' || buffer[i] == '%')
-        {
-            if (buffer[i] == '%')
-                ifStart = i + 1;
-            buffer[i] = 0;
-            break;
-        }
-    }
-
-    // Convert the address string to an address
-    struct addrinfo hints;
-    bzero(&hints, sizeof(hints));
-    hints.ai_flags = AI_NUMERICHOST;
-    struct addrinfo *gairesults = NULL;
-    if (getaddrinfo(buffer, NULL, &hints, &gairesults) != 0)
-    {
-        LogInfo("mDNSMacOSXParseEtcHostsLine: getaddrinfo returning null");
-        return;
-    }
-
-    if (ifStart)
-    {
-        // Parse the interface
-        ifname = &buffer[ifStart];
-        for (i = ifStart + 1; i < length; i++)
-        {
-            if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
-            {
-                buffer[i] = 0;
-                break;
-            }
-        }
-    }
-
-    i = EtcHostsParseOneName(i + 1, length, buffer, &name1);
-    if (i == length)
-    {
-        // Common case (no aliases) : The entry is of the form "1.2.3.4 somehost" with no trailing white spaces/tabs etc.
-        if (!MakeDomainNameFromDNSNameString(&name1d, name1))
-        {
-            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
-            freeaddrinfo(gairesults);
-            return;
-        }
-        mDNSMacOSXCreateEtcHostsEntry(&name1d, gairesults->ai_addr, mDNSNULL, ifname, auth);
-    }
-    else if (i != -1)
-    {
-        domainname first;
-        // We might have some extra white spaces at the end for the common case of "1.2.3.4 somehost".
-        // When we parse again below, EtchHostsParseOneName would return -1 and we will end up
-        // doing the right thing.
-
-        if (!MakeDomainNameFromDNSNameString(&first, name1))
-        {
-            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
-            freeaddrinfo(gairesults);
-            return;
-        }
-        mDNSMacOSXCreateEtcHostsEntry(&first, gairesults->ai_addr, mDNSNULL, ifname, auth);
-
-        // /etc/hosts alias discussion:
-        //
-        // If the /etc/hosts has an entry like this
-        //
-        //  ip_address cname [aliases...]
-        //  1.2.3.4    sun    star    bright
-        //
-        // star and bright are aliases (gethostbyname h_alias should point to these) and sun is the canonical
-        // name (getaddrinfo ai_cannonname and gethostbyname h_name points to "sun")
-        //
-        // To achieve this, we need to add the entry like this:
-        //
-        // sun A 1.2.3.4
-        // star CNAME sun
-        // bright CNAME sun
-        //
-        // We store the first name we parsed in "first" and add the address (A/AAAA) record.
-        // Then we parse additional names adding CNAME records till we reach the end.
-
-        aliasIndex = 0;
-        while (i < length)
-        {
-            // Continue to parse additional aliases until we reach end of the line and
-            // for each "alias" parsed, add a CNAME record where "alias" points to the first "name".
-            // See also /etc/hosts alias discussion above
-
-            i = EtcHostsParseOneName(i + 1, length, buffer, &name2);
-
-            if (name2)
-            {
-                if ((aliasIndex) && (*buffer == *name2))
-                    break; // break out of the loop if we wrap around
-
-                if (!MakeDomainNameFromDNSNameString(&name2d, name2))
-                {
-                    LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name2);
-                    freeaddrinfo(gairesults);
-                    return;
-                }
-                // Ignore if it points to itself
-                if (!SameDomainName(&first, &name2d))
-                {
-                    if (!mDNSMacOSXCreateEtcHostsEntry(&name2d, mDNSNULL, &first, ifname, auth))
-                    {
-                        freeaddrinfo(gairesults);
-                        return;
-                    }
-                }
-                else
-                {
-                    LogInfo("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names first %##s, name2 %##s", first.c, name2d.c);
-                }
-                aliasIndex++;
-            }
-            else if (!aliasIndex)
-            {
-                // We have never parsed any aliases. This case happens if there
-                // is just one name and some extra white spaces at the end.
-                LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c);
-                break;
-            }
-        }
-    }
-    freeaddrinfo(gairesults);
-}
-
-mDNSlocal void mDNSMacOSXParseEtcHosts(int fd, AuthHash *auth)
-{
-    mDNSBool good;
-    char buf[ETCHOSTS_BUFSIZE];
-    size_t len;
-    FILE *fp;
-
-    if (fd == -1) { LogInfo("mDNSMacOSXParseEtcHosts: fd is -1"); return; }
-
-    fp = fopen("/etc/hosts", "r");
-    if (!fp) { LogInfo("mDNSMacOSXParseEtcHosts: fp is NULL"); return; }
-
-    while (1)
-    {
-        good = (fgets(buf, ETCHOSTS_BUFSIZE, fp) != NULL);
-        if (!good) break;
-
-        // skip comment and empty lines
-        if (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n')
-            continue;
-
-        len = strlen(buf);
-        if (!len) break;    // sanity check
-        //Check for end of line code(mostly only \n but pre-OS X Macs could have only \r)
-        if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
-        {
-            buf[len - 1] = '\0';
-            len = len - 1;
-        }
-        // fgets always null terminates and hence even if we have no
-        // newline at the end, it is null terminated. The callee
-        // (mDNSMacOSXParseEtcHostsLine) expects the length to be such that
-        // buf[length] is zero and hence we decrement len to reflect that.
-        if (len)
-        {
-            //Additional check when end of line code is 2 chars ie\r\n(DOS, other old OSes)
-            //here we need to check for just \r but taking extra caution.
-            if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
-            {
-                buf[len - 1] = '\0';
-                len = len - 1;
-            }
-        }
-        if (!len) //Sanity Check: len should never be zero
-        {
-            LogMsg("mDNSMacOSXParseEtcHosts: Length is zero!");
-            continue;
-        }
-        mDNSMacOSXParseEtcHostsLine(buf, (int)len, auth);
-    }
-    fclose(fp);
-}
-
-mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m);
-
-mDNSlocal int mDNSMacOSXGetEtcHostsFD(void)
-{
-    mDNS *const m = &mDNSStorage;
-#ifdef __DISPATCH_GROUP__
-    // Can't do this stuff to be notified of changes in /etc/hosts if we don't have libdispatch
-    static dispatch_queue_t etcq     = 0;
-    static dispatch_source_t etcsrc   = 0;
-    static dispatch_source_t hostssrc = 0;
-
-    // First time through? just schedule ourselves on the main queue and we'll do the work later
-    if (!etcq)
-    {
-        etcq = dispatch_get_main_queue();
-        if (etcq)
-        {
-            // Do this work on the queue, not here - solves potential synchronization issues
-            dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-        }
-        return -1;
-    }
-
-    if (hostssrc) return (int)dispatch_source_get_handle(hostssrc);
-#endif
-
-    int fd = open("/etc/hosts", O_RDONLY);
-
-#ifdef __DISPATCH_GROUP__
-    // Can't do this stuff to be notified of changes in /etc/hosts if we don't have libdispatch
-    if (fd == -1)
-    {
-        // If the open failed and we're already watching /etc, we're done
-        if (etcsrc) { LogInfo("mDNSMacOSXGetEtcHostsFD: Returning etcfd because no etchosts"); return fd; }
-
-        // we aren't watching /etc, we should be
-        fd = open("/etc", O_RDONLY);
-        if (fd == -1) { LogInfo("mDNSMacOSXGetEtcHostsFD: etc does not exist"); return -1; }
-        etcsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME, etcq);
-        if (etcsrc == NULL)
-        {
-            close(fd);
-            return -1;
-        }
-        dispatch_source_set_event_handler(etcsrc,
-                                          ^{
-                                              const unsigned long flags = dispatch_source_get_data(etcsrc);
-                                              LogMsg("mDNSMacOSXGetEtcHostsFD: /etc changed 0x%x", flags);
-                                              if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
-                                              {
-                                                  dispatch_source_cancel(etcsrc);
-                                                  MDNS_DISPOSE_DISPATCH(etcsrc);
-                                                  dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-                                                  return;
-                                              }
-                                              if ((flags & DISPATCH_VNODE_WRITE) != 0 && hostssrc == NULL)
-                                              {
-                                                  mDNSMacOSXUpdateEtcHosts(m);
-                                              }
-                                          });
-        dispatch_source_set_cancel_handler(etcsrc, ^{close(fd);});
-        dispatch_resume(etcsrc);
-
-        // Try and open /etc/hosts once more now that we're watching /etc, in case we missed the creation
-        fd = open("/etc/hosts", O_RDONLY | O_EVTONLY);
-        if (fd == -1) { LogMsg("mDNSMacOSXGetEtcHostsFD etc hosts does not exist, watching etc"); return -1; }
-    }
-
-    // create a dispatch source to watch for changes to hosts file
-    hostssrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd,
-                                      (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME |
-                                       DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_LINK | DISPATCH_VNODE_REVOKE), etcq);
-    if (hostssrc == NULL)
-    {
-        close(fd);
-        return -1;
-    }
-    dispatch_source_set_event_handler(hostssrc,
-                                      ^{
-                                          const unsigned long flags = dispatch_source_get_data(hostssrc);
-                                          LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts changed 0x%x", flags);
-                                          if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
-                                          {
-                                              dispatch_source_cancel(hostssrc);
-                                              MDNS_DISPOSE_DISPATCH(hostssrc);
-                                              // Bug in LibDispatch: wait a second before scheduling the block. If we schedule
-                                              // the block immediately, we try to open the file and the file may not exist and may
-                                              // fail to get a notification in the future. When the file does not exist and
-                                              // we start to monitor the directory, on "dispatch_resume" of that source, there
-                                              // is no guarantee that the file creation will be notified always because when
-                                              // the dispatch_resume returns, the kevent manager may not have registered the
-                                              // kevent yet but the file may have been created
-                                              usleep(1000000);
-                                              dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-                                              return;
-                                          }
-                                          if ((flags & DISPATCH_VNODE_WRITE) != 0)
-                                          {
-                                              mDNSMacOSXUpdateEtcHosts(m);
-                                          }
-                                      });
-    dispatch_source_set_cancel_handler(hostssrc, ^{LogInfo("mDNSMacOSXGetEtcHostsFD: Closing etchosts fd %d", fd); close(fd);});
-    dispatch_resume(hostssrc);
-
-    // Cleanup /etc source, no need to watch it if we already have /etc/hosts
-    if (etcsrc)
-    {
-        dispatch_source_cancel(etcsrc);
-        MDNS_DISPOSE_DISPATCH(etcsrc);
-    }
-
-    LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts being monitored, and not etc");
-    return hostssrc ? (int)dispatch_source_get_handle(hostssrc) : -1;
-#else
-    (void)m;
-    return fd;
-#endif
-}
-
-// When /etc/hosts is modified, flush all the cache records as there may be local
-// authoritative answers now
-mDNSlocal void FlushAllCacheRecords(mDNS *const m)
-{
-    CacheRecord *cr;
-    mDNSu32 slot;
-    CacheGroup *cg;
-
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        // Skip multicast.
-        if (cr->resrec.InterfaceID) continue;
-
-        // If resource records can answer A, AAAA or are RRSIGs that cover A/AAAA, they need to be flushed so that we
-        // will never used to deliver an ADD or RMV.
-
-        RRTypeAnswersQuestionTypeFlags flags = kRRTypeAnswersQuestionTypeFlagsNone;
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-        // Here we are checking if the record should be decided on whether to deliver the remove event to the callback,
-        // RRSIG that covers kDNSType_A or kDNSType_AAAA should always be checked.
-        // Note that setting REQUIRES_DNSSEC_RRS to mDNStrue will not necessarily deliver the remove event for RRSIG
-        // that covers kDNSType_A or kDNSType_AAAA records. It still needs to go through the "IsAnswer" process to
-        // determine whether to deliver the remove event.
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRToValidate;
-        flags |= kRRTypeAnswersQuestionTypeFlagsRequiresDNSSECRRValidated;
-    #endif
-        const mDNSBool typeMatches = RRTypeAnswersQuestionType(&cr->resrec, kDNSType_A, flags) ||
-                                     RRTypeAnswersQuestionType(&cr->resrec, kDNSType_AAAA, flags);
-        if (!typeMatches)
-        {
-            continue;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "FlushAllCacheRecords: Purging Resourcerecord - "
-                  "record description: " PRI_S ".", CRDisplayString(m, cr));
-
-        mDNS_PurgeCacheResourceRecord(m, cr);
-    }
-}
-
-// Add new entries to the core. If justCheck is set, this function does not add, just returns true
-mDNSlocal mDNSBool EtcHostsAddNewEntries(AuthHash *newhosts, mDNSBool justCheck)
-{
-    mDNS *const m = &mDNSStorage;
-    AuthGroup *ag;
-    mDNSu32 slot;
-    AuthRecord *rr, *primary, *rrnext;
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = newhosts->rrauth_hash[slot]; ag; ag = ag->next)
-        {
-            primary = NULL;
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                rrnext = rr->next;
-                AuthGroup *ag1;
-                AuthRecord *rr1;
-                mDNSBool found = mDNSfalse;
-                ag1 = AuthGroupForRecord(&m->rrauth, &rr->resrec);
-                if (ag1 && ag1->members)
-                {
-                    if (!primary) primary = ag1->members;
-                    rr1 = ag1->members;
-                    while (rr1)
-                    {
-                        // We are not using InterfaceID in checking for duplicates. This means,
-                        // if there are two addresses for a given name e.g., fe80::1%en0 and
-                        // fe80::1%en1, we only add the first one. It is not clear whether
-                        // this is a common case. To fix this, we also need to modify
-                        // mDNS_Register_internal in how it handles duplicates. If it becomes a
-                        // common case, we will fix it then.
-                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec) && rr1->resrec.InterfaceID == rr->resrec.InterfaceID)
-                        {
-                            LogInfo("EtcHostsAddNewEntries: Skipping, not adding %s", ARDisplayString(m, rr1));
-                            found = mDNStrue;
-                            break;
-                        }
-                        rr1 = rr1->next;
-                    }
-                }
-                if (!found)
-                {
-                    if (justCheck)
-                    {
-                        LogInfo("EtcHostsAddNewEntries: Entry %s not registered with core yet", ARDisplayString(m, rr));
-                        return mDNStrue;
-                    }
-                    RemoveAuthRecord(m, newhosts, rr);
-                    // if there is no primary, point to self
-                    rr->RRSet = (uintptr_t)(primary ? primary : rr);
-                    rr->next = NULL;
-                    LogInfo("EtcHostsAddNewEntries: Adding %s ID %d", ARDisplayString(m, rr), IIDPrintable(rr->resrec.InterfaceID));
-                    if (mDNS_Register_internal(m, rr) != mStatus_NoError)
-                        LogMsg("EtcHostsAddNewEntries: mDNS_Register failed for %s", ARDisplayString(m, rr));
-                }
-            }
-        }
-    return mDNSfalse;
-}
-
-// Delete entries from the core that are no longer needed. If justCheck is set, this function
-// does not delete, just returns true
-mDNSlocal mDNSBool EtcHostsDeleteOldEntries(AuthHash *newhosts, mDNSBool justCheck)
-{
-    mDNS *const m = &mDNSStorage;
-    AuthGroup *ag;
-    mDNSu32 slot;
-    AuthRecord *rr, *rrnext;
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                mDNSBool found = mDNSfalse;
-                AuthGroup *ag1;
-                AuthRecord *rr1;
-                rrnext = rr->next;
-                if (rr->RecordCallback != FreeEtcHosts) continue;
-                ag1 = AuthGroupForRecord(newhosts, &rr->resrec);
-                if (ag1)
-                {
-                    rr1 = ag1->members;
-                    while (rr1)
-                    {
-                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec))
-                        {
-                            LogInfo("EtcHostsDeleteOldEntries: Old record %s found in new, skipping", ARDisplayString(m, rr));
-                            found = mDNStrue;
-                            break;
-                        }
-                        rr1 = rr1->next;
-                    }
-                }
-                // there is no corresponding record in newhosts for the same name. This means
-                // we should delete this from the core.
-                if (!found)
-                {
-                    if (justCheck)
-                    {
-                        LogInfo("EtcHostsDeleteOldEntries: Record %s not found in new, deleting", ARDisplayString(m, rr));
-                        return mDNStrue;
-                    }
-                    // if primary is going away, make sure that the rest of the records
-                    // point to the new primary
-                    if (rr == ag->members)
-                    {
-                        AuthRecord *new_primary = rr->next;
-                        AuthRecord *r = new_primary;
-                        while (r)
-                        {
-                            if (r->RRSet == (uintptr_t)rr)
-                            {
-                                LogInfo("EtcHostsDeleteOldEntries: Updating Resource Record %s to primary", ARDisplayString(m, r));
-                                r->RRSet = (uintptr_t)new_primary;
-                            }
-                            else LogMsg("EtcHostsDeleteOldEntries: ERROR!! Resource Record %s not pointing to primary %##s", ARDisplayString(m, r), r->resrec.name);
-                            r = r->next;
-                        }
-                    }
-                    LogInfo("EtcHostsDeleteOldEntries: Deleting %s", ARDisplayString(m, rr));
-                    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                }
-            }
-    return mDNSfalse;
-}
-
-mDNSlocal void UpdateEtcHosts(mDNS *const m, void *context)
-{
-    AuthHash *newhosts = (AuthHash *)context;
-
-    mDNS_CheckLock(m);
-
-    //Delete old entries from the core if they are not present in the newhosts
-    EtcHostsDeleteOldEntries(newhosts, mDNSfalse);
-    // Add the new entries to the core if not already present in the core
-    EtcHostsAddNewEntries(newhosts, mDNSfalse);
-}
-
-mDNSlocal void FreeNewHosts(AuthHash *newhosts)
-{
-    mDNSu32 slot;
-    AuthGroup *ag, *agnext;
-    AuthRecord *rr, *rrnext;
-
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = newhosts->rrauth_hash[slot]; ag; ag = agnext)
-        {
-            agnext = ag->next;
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                rrnext = rr->next;
-                freeL("etchosts", rr);
-            }
-            freeL("AuthGroups", ag);
-        }
-}
-
-mDNSlocal void mDNSMacOSXUpdateEtcHosts_internal(mDNS *const m)
-{
-    AuthHash newhosts;
-
-    mDNSPlatformMemZero(&newhosts, sizeof(AuthHash));
-
-    // Get the file desecriptor (will trigger us to start watching for changes)
-    int fd = mDNSMacOSXGetEtcHostsFD();
-    if (fd != -1)
-    {
-        LogInfo("mDNSMacOSXUpdateEtcHosts: Parsing /etc/hosts fd %d", fd);
-        mDNSMacOSXParseEtcHosts(fd, &newhosts);
-    }
-    else LogInfo("mDNSMacOSXUpdateEtcHosts: /etc/hosts is not present");
-
-    // Optimization: Detect whether /etc/hosts changed or not.
-    //
-    // 1. Check to see if there are any new entries. We do this by seeing whether any entries in
-    //    newhosts is already registered with core.  If we find at least one entry that is not
-    //    registered with core, then it means we have work to do.
-    //
-    // 2. Next, we check to see if any of the entries that are registered with core is not present
-    //   in newhosts. If we find at least one entry that is not present, it means we have work to
-    //   do.
-    //
-    // Note: We may not have to hold the lock right here as KQueueLock is held which prevents any
-    // other thread from running. But mDNS_Lock is needed here as we will be traversing the core
-    // data structure in EtcHostsDeleteOldEntries/NewEntries which might expect the lock to be held
-    // in the future and this code does not have to change.
-    mDNS_Lock(m);
-    // Add the new entries to the core if not already present in the core
-    if (!EtcHostsAddNewEntries(&newhosts, mDNStrue))
-    {
-        // No new entries to add, check to see if we need to delete any old entries from the
-        // core if they are not present in the newhosts
-        if (!EtcHostsDeleteOldEntries(&newhosts, mDNStrue))
-        {
-            LogInfo("mDNSMacOSXUpdateEtcHosts: No work");
-            goto exit;
-        }
-    }
-
-    // This will flush the cache, stop and start the query so that the queries
-    // can look at the /etc/hosts again
-    //
-    // Notes:
-    //
-    // We can't delete and free the records here. We wait for the mDNSCoreRestartAddressQueries to
-    // deliver RMV events. It has to be done in a deferred way because we can't deliver RMV
-    // events for local records *before* the RMV events for cache records. mDNSCoreRestartAddressQueries
-    // delivers these events in the right order and then calls us back to delete them.
-    //
-    // Similarly, we do a deferred Registration of the record because mDNSCoreRestartAddressQueries
-    // is a common function that looks at all local auth records and delivers a RMV including
-    // the records that we might add here. If we deliver a ADD here, it will get a RMV and then when
-    // the query is restarted, it will get another ADD. To avoid this (ADD-RMV-ADD), we defer registering
-    // the record until the RMVs are delivered in mDNSCoreRestartAddressQueries after which UpdateEtcHosts
-    // is called back where we do the Registration of the record. This results in RMV followed by ADD which
-    // looks normal.
-    mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts);
-
-exit:
-    FreeNewHosts(&newhosts);
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
-{
-    KQueueLock();
-    mDNSMacOSXUpdateEtcHosts_internal(m);
-    KQueueUnlock("/etc/hosts changed");
-}
-
-// MARK: - Initialization & Teardown
-
-CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
-CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
-CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
-CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
-
-// Major version 13 is 10.9.x
-mDNSexport void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
-{
-    int major = 0, minor = 0;
-    char letter = 0, prodname[256]="<Unknown>", prodvers[256]="<Unknown>", buildver[256]="<Unknown>";
-    CFDictionaryRef vers = _CFCopySystemVersionDictionary();
-    if (vers)
-    {
-        CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey);
-        CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey);
-        CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
-        if (cfprodname)
-            CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8);
-        if (cfprodvers)
-            CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8);
-        if (cfbuildver && CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8))
-            sscanf(buildver, "%d%c%d", &major, &letter, &minor);
-        MDNS_DISPOSE_CF_OBJECT(vers);
-    }
-    if (!major)
-    {
-        major = 13;
-        LogMsg("Note: No Major Build Version number found; assuming 13");
-    }
-    if (HINFO_SWstring)
-        mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, STRINGIFY(mDNSResponderVersion));
-    //LogMsg("%s %s (%s), %d %c %d", prodname, prodvers, buildver, major, letter, minor);
-
-    // If product name starts with "M" (case insensitive), thus it the current ProductName attribute "macOS"
-    // for macOS; or it matches the old ProductName attribute "Mac OS X" for macOS, we set OSXVers, else we set iOSVers.
-    // Note that "& 0xDF" operation converts prodname[0] to uppercase alphabetic character, do not use it make the ASCII
-    // character uppercase, since "& 0xDF" will incorrectly change the ASCII characters that are not in the A~Z, a~z
-    // range. For the detail, go to https://blog.cloudflare.com/the-oldest-trick-in-the-ascii-book/
-    if ((prodname[0] & 0xDF) == 'M')
-        OSXVers = major;
-    else
-        iOSVers = major;
-}
-
-// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
-// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
-// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
-mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
-{
-    int err = -1;
-    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    if (s < 3)
-        LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s, errno, strerror(errno));
-    else
-    {
-        struct sockaddr_in s5353;
-        s5353.sin_family      = AF_INET;
-        s5353.sin_port        = MulticastDNSPort.NotAnInteger;
-        s5353.sin_addr.s_addr = 0;
-        err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
-        close(s);
-    }
-
-    if (err) LogMsg("No unicast UDP responses");
-    else debugf("Unicast UDP responses okay");
-    return(err == 0);
-}
-
-mDNSlocal void CreatePTRRecord(const domainname *domain)
-{
-    AuthRecord *rr;
-    const domainname *pname = (domainname *)"\x9" "localhost";
-
-    rr = (AuthRecord *) callocL("localhosts", sizeof(*rr));
-    if (rr == NULL) return;
-
-    mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, mDNSNULL, mDNSNULL);
-    AssignDomainName(&rr->namestorage, domain);
-
-    rr->resrec.rdlength = DomainNameLength(pname);
-    rr->resrec.rdata->u.name.c[0] = 0;
-    AssignDomainName(&rr->resrec.rdata->u.name, pname);
-
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-    mDNS_Register(&mDNSStorage, rr);
-}
-
-// Setup PTR records for 127.0.0.1 and ::1. This helps answering them locally rather than relying
-// on the external DNS server to answer this. Sometimes, the DNS servers don't respond in a timely
-// fashion and applications depending on this e.g., telnetd, times out after 30 seconds creating
-// a bad user experience. For now, we specifically create only localhosts to handle radar://9354225
-//
-// Note: We could have set this up while parsing the entries in /etc/hosts. But this is kept separate
-// intentionally to avoid adding to the complexity of code handling /etc/hosts.
-mDNSlocal void SetupLocalHostRecords(void)
-{
-    domainname name;
-
-    MakeDomainNameFromDNSNameString(&name, "1.0.0.127.in-addr.arpa.");
-    CreatePTRRecord(&name);
-
-    MakeDomainNameFromDNSNameString(&name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.");
-    CreatePTRRecord(&name);
-}
-
-
-// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
-// 1) query for b._dns-sd._udp.local on LocalOnly interface
-//    (.local manually generated via explicit callback)
-// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
-// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
-// 4) result above should generate a callback from question in (1).  result added to global list
-// 5) global list delivered to client via GetSearchDomainList()
-// 6) client calls to enumerate domains now go over LocalOnly interface
-//    (!!!KRS may add outgoing interface in addition)
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, IGNORE_HOSTS_FILE)
-mDNSlocal mStatus RegisterLocalOnlyAddressRecord(const domainname *const name, mDNSu16 type, const void *rdata, mDNSu16 rdlength)
-{
-    switch(type)
-    {
-    case kDNSType_A:
-        if (rdlength != 4) return (mStatus_BadParamErr);
-        break;
-
-    case kDNSType_AAAA:
-        if (rdlength != 16) return (mStatus_BadParamErr);
-        break;
-
-    default:
-        return (mStatus_BadParamErr);
-    }
-
-    AuthRecord *rr = (AuthRecord *) callocL("etchosts", sizeof(*rr));
-    if (!rr) return (mStatus_NoMemoryErr);
-
-    mDNS_SetupResourceRecord(rr, NULL, mDNSInterface_LocalOnly, type, 1, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, FreeEtcHosts, NULL);
-    AssignDomainName(&rr->namestorage, name);
-    mDNSPlatformMemCopy(rr->resrec.rdata->u.data, rdata, rdlength);
-
-    const mStatus err = mDNS_Register_internal(&mDNSStorage, rr);
-    if (err)
-    {
-        LogMsg("RegisterLocalOnlyAddressRecord: mDNS_Register error %d registering %s", err, ARDisplayString(&mDNSStorage, rr));
-        freeL("etchosts", rr);
-    }
-    return (err);
-}
-
-mDNSlocal void RegisterLocalOnlyARecord(const domainname *const name, const mDNSv4Addr *const addr)
-{
-    RegisterLocalOnlyAddressRecord(name, kDNSType_A, addr->b, (mDNSu16)sizeof(mDNSv4Addr));
-}
-
-mDNSlocal void RegisterLocalOnlyAAAARecord(const domainname *const name, const mDNSv6Addr *const addr)
-{
-    RegisterLocalOnlyAddressRecord(name, kDNSType_AAAA, addr->b, (mDNSu16)sizeof(mDNSv6Addr));
-}
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, IGNORE_HOSTS_FILE)
-
-mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
-{
-    mStatus err;
-
-    char HINFO_SWstring[256] = "";
-    mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
-
-
-    err = mDNSHelperInit();
-    if (err)
-        return err;
-
-    // Store mDNSResponder Platform
-    if (OSXVers)
-    {
-        m->mDNS_plat = platform_OSX;
-    }
-    else if (iOSVers)
-    {
-        if (IsAppleTV())
-            m->mDNS_plat = platform_Atv;
-        else
-            m->mDNS_plat = platform_iOS;
-    }
-    else
-    {
-        m->mDNS_plat = platform_NonApple;
-    }
-
-    // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
-    // If we can't read the user's preferences, then we sleep a bit and try again, for up to five seconds before we give up.
-    int i;
-    for (i=0; i<100; i++)
-    {
-        domainlabel testlabel;
-        testlabel.c[0] = 0;
-        GetUserSpecifiedLocalHostName(&testlabel);
-        if (testlabel.c[0]) break;
-        usleep(50000);
-    }
-
-    m->hostlabel.c[0]        = 0;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    GetRandomUUIDLocalHostname(&m->RandomizedHostname);
-#endif
-    int get_model[2] = { CTL_HW, HW_MODEL };
-    size_t len_model = sizeof(HINFO_HWstring_buffer);
-
-    // Normal Apple model names are of the form "iPhone2,1", and
-    // internal code names are strings containing no commas, e.g. "N88AP".
-    // We used to ignore internal code names, but Apple now uses these internal code names
-    // even in released shipping products, so we no longer ignore strings containing no commas.
-//  if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0 && strchr(HINFO_HWstring_buffer, ','))
-    if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
-        HINFO_HWstring = HINFO_HWstring_buffer;
-
-    // For names of the form "iPhone2,1" we use "iPhone" as the prefix for automatic name generation.
-    // For names of the form "N88AP" containg no comma, we use the entire string.
-    HINFO_HWstring_prefixlen = (int)(strchr(HINFO_HWstring_buffer, ',') ? strcspn(HINFO_HWstring, "0123456789") : strlen(HINFO_HWstring));
-
-    if (mDNSPlatformInit_CanReceiveUnicast())
-        m->CanReceiveUnicastOn5353 = mDNStrue;
-
-    mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
-    mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
-    if (hlen + slen < 254)
-    {
-        m->HIHardware.c[0] = hlen;
-        m->HISoftware.c[0] = slen;
-        mDNSPlatformMemCopy(&m->HIHardware.c[1], HINFO_HWstring, hlen);
-        mDNSPlatformMemCopy(&m->HISoftware.c[1], HINFO_SWstring, slen);
-    }
-
-    m->p->permanentsockets.port  = MulticastDNSPort;
-    m->p->permanentsockets.m     = m;
-    m->p->permanentsockets.sktv4 = -1;
-    m->p->permanentsockets.kqsv4.KQcallback = myKQSocketCallBack;
-    m->p->permanentsockets.kqsv4.KQcontext  = &m->p->permanentsockets;
-    m->p->permanentsockets.kqsv4.KQtask     = "IPv4 UDP packet reception";
-    m->p->permanentsockets.sktv6 = -1;
-    m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack;
-    m->p->permanentsockets.kqsv6.KQcontext  = &m->p->permanentsockets;
-    m->p->permanentsockets.kqsv6.KQtask     = "IPv6 UDP packet reception";
-
-    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET, mDNSNULL);
-    if (err) LogMsg("mDNSPlatformInit_setup: SetupSocket(AF_INET) failed error %d errno %d (%s)", err, errno, strerror(errno));
-    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET6, mDNSNULL);
-    if (err) LogMsg("mDNSPlatformInit_setup: SetupSocket(AF_INET6) failed error %d errno %d (%s)", err, errno, strerror(errno));
-
-    struct sockaddr_in s4;
-    socklen_t n4 = sizeof(s4);
-    if (getsockname(m->p->permanentsockets.sktv4, (struct sockaddr *)&s4, &n4) < 0)
-        LogMsg("getsockname v4 error %d (%s)", errno, strerror(errno));
-    else
-        m->UnicastPort4.NotAnInteger = s4.sin_port;
-
-    if (m->p->permanentsockets.sktv6 >= 0)
-    {
-        struct sockaddr_in6 s6;
-        socklen_t n6 = sizeof(s6);
-        if (getsockname(m->p->permanentsockets.sktv6, (struct sockaddr *)&s6, &n6) < 0) LogMsg("getsockname v6 error %d (%s)", errno, strerror(errno));
-        else m->UnicastPort6.NotAnInteger = s6.sin6_port;
-    }
-
-    m->p->InterfaceList         = mDNSNULL;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    m->p->InterfaceMonitors     = NULL;
-#endif
-    m->p->userhostlabel.c[0]    = 0;
-    m->p->usernicelabel.c[0]    = 0;
-    m->p->prevoldnicelabel.c[0] = 0;
-    m->p->prevnewnicelabel.c[0] = 0;
-    m->p->prevoldhostlabel.c[0] = 0;
-    m->p->prevnewhostlabel.c[0] = 0;
-    m->p->NotifyUser         = 0;
-    m->p->KeyChainTimer      = 0;
-    m->p->WakeAtUTC          = 0;
-    m->p->RequestReSleep     = 0;
-    // Assume that everything is good to begin with. If something is not working,
-    // we will detect that when we start sending questions.
-    m->p->v4answers          = 1;
-    m->p->v6answers          = 1;
-    m->p->DNSTrigger         = 0;
-    m->p->LastConfigGeneration = 0;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    m->p->if_interface_changed = mDNSfalse;
-#endif
-
-    NetworkChangedKey_IPv4         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
-    NetworkChangedKey_IPv6         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
-    NetworkChangedKey_Hostnames    = SCDynamicStoreKeyCreateHostNames(NULL);
-    NetworkChangedKey_Computername = SCDynamicStoreKeyCreateComputerName(NULL);
-    NetworkChangedKey_DNS          = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
-    NetworkChangedKey_StateInterfacePrefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, CFSTR(""), NULL);
-    if (!NetworkChangedKey_IPv4 || !NetworkChangedKey_IPv6 || !NetworkChangedKey_Hostnames || !NetworkChangedKey_Computername || !NetworkChangedKey_DNS || !NetworkChangedKey_StateInterfacePrefix)
-    { LogMsg("SCDynamicStore string setup failed"); return(mStatus_NoMemoryErr); }
-
-    err = WatchForNetworkChanges(m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForNetworkChanges failed %d", err); return(err); }
-
-    err = WatchForSysEvents(m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForSysEvents failed %d", err); return(err); }
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-    myGetIfAddrs(1);
-    UpdateInterfaceList(utc);
-    SetupActiveInterfaces(utc);
-    ReorderInterfaceList();
-
-    // Explicitly ensure that our Keychain operations utilize the system domain.
-#ifndef NO_SECURITYFRAMEWORK
-    SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
-#endif
-
-    mDNS_Lock(m);
-    SetDomainSecrets(m);
-    SetLocalDomains();
-    mDNS_Unlock(m);
-
-#ifndef NO_SECURITYFRAMEWORK
-    err = SecKeychainAddCallback(KeychainChanged, kSecAddEventMask|kSecDeleteEventMask|kSecUpdateEventMask, m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: SecKeychainAddCallback failed %d", err); return(err); }
-#endif
-
-#if !defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) || TARGET_OS_IPHONE
-    LogMsg("Note: Compiled without SnowLeopard Fine-Grained Power Management support");
-#else
-    IOPMConnection c;
-    IOReturn iopmerr = IOPMConnectionCreate(CFSTR("mDNSResponder"), kIOPMSystemPowerStateCapabilityCPU, &c);
-    if (iopmerr) LogMsg("IOPMConnectionCreate failed %d", iopmerr);
-    else
-    {
-        iopmerr = IOPMConnectionSetNotification(c, m, SnowLeopardPowerChanged);
-        if (iopmerr) LogMsg("IOPMConnectionSetNotification failed %d", iopmerr);
-        else
-        {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-            IOPMConnectionSetDispatchQueue(c, dispatch_get_main_queue());
-            LogInfo("IOPMConnectionSetDispatchQueue is now running");
-#else
-            iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
-            if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr);
-            LogInfo("IOPMConnectionScheduleWithRunLoop is now running");
-#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
-        }
-    }
-    m->p->IOPMConnection = iopmerr ? mDNSNULL : c;
-    if (iopmerr) // If IOPMConnectionCreate unavailable or failed, proceed with old-style power notification code below
-#endif // kIOPMAcknowledgmentOptionSystemCapabilityRequirements
-    {
-        m->p->PowerConnection = IORegisterForSystemPower(m, &m->p->PowerPortRef, PowerChanged, &m->p->PowerNotifier);
-        if (!m->p->PowerConnection) { LogMsg("mDNSPlatformInit_setup: IORegisterForSystemPower failed"); return(-1); }
-        else
-        {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-            IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue());
-#else
-            CFRunLoopAddSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
-#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
-        }
-    }
-
-
-    // Currently this is not defined. SSL code will eventually fix this. If it becomes
-    // critical, we will define this to workaround the bug in SSL.
-#ifdef __SSL_NEEDS_SERIALIZATION__
-    SSLqueue = dispatch_queue_create("com.apple.mDNSResponder.SSLQueue", NULL);
-#else
-    SSLqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-#endif
-    if (SSLqueue == mDNSNULL) LogMsg("dispatch_queue_create: SSL queue NULL");
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, IGNORE_HOSTS_FILE)
-    // On device OSes (iOS, tvOS, watchOS, etc.), ignore /etc/hosts unless the OS is an internal build. When the /etc/hosts
-    // file is ignored, LocalOnly auth records will be registered for localhost and broadcasthost addresses contained in the
-    // standard /etc/hosts file:
-    //
-    //  127.0.0.1       localhost
-    //  255.255.255.255 broadcasthost
-    //  ::1             localhost
-
-    if (!is_apple_internal_build())
-    {
-        const domainname *const localHostName     = (const domainname *) "\x9" "localhost";
-        const domainname *const broadcastHostName = (const domainname *) "\xd" "broadcasthost";
-        const mDNSv4Addr        localHostV4       = { { 127, 0, 0, 1 } };
-        mDNSv6Addr              localHostV6;
-
-        // Register localhost 127.0.0.1 A record.
-
-        RegisterLocalOnlyARecord(localHostName, &localHostV4);
-
-        // Register broadcasthost 255.255.255.255 A record.
-
-        RegisterLocalOnlyARecord(broadcastHostName, &onesIPv4Addr);
-
-        // Register localhost ::1 AAAA record.
-
-        mDNSPlatformMemZero(&localHostV6, sizeof(localHostV6));
-        localHostV6.b[15] = 1;
-        RegisterLocalOnlyAAAARecord(localHostName, &localHostV6);
-    }
-    else
-#endif
-    {
-        mDNSMacOSXUpdateEtcHosts_internal(m);
-    }
-    SetupLocalHostRecords();
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
-    dso_transport_init();
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
-    dnssd_analytics_init();
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    if (os_feature_enabled(mDNSResponder, bonjour_privacy))
-    {
-        mdns_trust_init();
-   }
-#endif
-
-    return(mStatus_NoError);
-}
-
-mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
-{
-#ifdef MDNS_NO_DNSINFO
-    LogMsg("Note: Compiled without Apple-specific Split-DNS support");
-#endif
-
-    // Adding interfaces will use this flag, so set it now.
-    m->DivertMulticastAdvertisements = !m->AdvertiseLocalAddresses;
-
-
-    mStatus result = mDNSPlatformInit_setup(m);
-
-    // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
-    // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
-    if (result == mStatus_NoError)
-    {
-        mDNSCoreInitComplete(m, mStatus_NoError);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        initializeD2DPlugins(m);
-#endif
-    }
-    return(result);
-}
-
-mDNSexport void mDNSPlatformClose(mDNS *const m)
-{
-    if (m->p->PowerConnection)
-    {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL);
-#else
-        CFRunLoopRemoveSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
-#endif
-        // According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
-        // to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
-        IODeregisterForSystemPower(&m->p->PowerNotifier);
-        IOServiceClose            ( m->p->PowerConnection);
-        IONotificationPortDestroy ( m->p->PowerPortRef);
-        m->p->PowerConnection = 0;
-    }
-
-    if (m->p->Store)
-    {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_NAT, MDNS_LOG_DEFAULT, "mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed");
-        }
-#else
-        CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode);
-        CFRunLoopSourceInvalidate(m->p->StoreRLS);
-        MDNS_DISPOSE_CF_OBJECT(m->p->StoreRLS);
-#endif
-        MDNS_DISPOSE_CF_OBJECT(m->p->Store);
-    }
-
-    if (m->p->PMRLS)
-    {
-        CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->PMRLS, kCFRunLoopDefaultMode);
-        CFRunLoopSourceInvalidate(m->p->PMRLS);
-        MDNS_DISPOSE_CF_OBJECT(m->p->PMRLS);
-    }
-
-    if (m->p->SysEventNotifier >= 0) { close(m->p->SysEventNotifier); m->p->SysEventNotifier = -1; }
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    terminateD2DPlugins();
-#endif
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    MarkAllInterfacesInactive(utc);
-    ClearInactiveInterfaces(utc);
-    CloseSocketSet(&m->p->permanentsockets);
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (m->p->InterfaceMonitors)
-    {
-        CFArrayRef monitors = m->p->InterfaceMonitors;
-        m->p->InterfaceMonitors = NULL;
-        const CFIndex n = CFArrayGetCount(monitors);
-        for (CFIndex i = 0; i < n; i++)
-        {
-            mdns_interface_monitor_invalidate((mdns_interface_monitor_t) CFArrayGetValueAtIndex(monitors, i));
-        }
-        MDNS_DISPOSE_CF_OBJECT(monitors);
-    }
-#endif
-}
-
-// MARK: - General Platform Support Layer functions
-
-mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
-{
-    return(arc4random());
-}
-
-mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
-mDNSexport mDNSu32 mDNSPlatformClockDivisor = 0;
-
-mDNSexport mStatus mDNSPlatformTimeInit(void)
-{
-    // Notes: Typical values for mach_timebase_info:
-    // tbi.numer = 1000 million
-    // tbi.denom =   33 million
-    // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
-    //          numer  / denom = nanoseconds per hardware clock tick (e.g. 30);
-    //          denom  / numer = hardware clock ticks per nanosecond (e.g. 0.033)
-    // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
-    // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
-    //
-    // Arithmetic notes:
-    // tbi.denom is at least 1, and not more than 2^32-1.
-    // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
-    // tbi.denom is at least 1, and not more than 2^32-1.
-    // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
-    // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
-    // which is unlikely on any current or future Macintosh.
-    // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
-    // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
-    struct mach_timebase_info tbi;
-    kern_return_t result = mach_timebase_info(&tbi);
-    if (result == KERN_SUCCESS) mDNSPlatformClockDivisor = (mDNSu32)(((uint64_t)tbi.denom * 1000000) / tbi.numer);
-    return(result);
-}
-
-mDNSexport mDNSs32 mDNSPlatformRawTime(void)
-{
-    if (mDNSPlatformClockDivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
-
-    static uint64_t last_mach_absolute_time = 0;
-    //static uint64_t last_mach_absolute_time = 0x8000000000000000LL;   // Use this value for testing the alert display
-    uint64_t this_mach_absolute_time = mach_absolute_time();
-    if ((int64_t)this_mach_absolute_time - (int64_t)last_mach_absolute_time < 0)
-    {
-        LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time);
-        LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
-        // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
-        last_mach_absolute_time = this_mach_absolute_time;
-        // Note: This bug happens all the time on 10.3
-        NotifyOfElusiveBug("mach_absolute_time went backwards!",
-                           "This error occurs from time to time, often on newly released hardware, "
-                           "and usually the exact cause is different in each instance.\r\r"
-                           "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
-                           "and assign it to Radar Component “Kernel” Version “X”.");
-    }
-    last_mach_absolute_time = this_mach_absolute_time;
-
-    return((mDNSs32)(this_mach_absolute_time / mDNSPlatformClockDivisor));
-}
-
-mDNSexport mDNSs32 mDNSPlatformContinuousTimeSeconds(void)
-{
-    const int clockid = CLOCK_MONOTONIC_RAW;
-    struct timespec tm;
-    clock_gettime(clockid, &tm);
-
-    // We are only accurate to the second.
-    return (mDNSs32)tm.tv_sec;
-}
-
-mDNSexport mDNSs32 mDNSPlatformUTC(void)
-{
-    return (mDNSs32)time(NULL);
-}
-
-// Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
-mDNSexport void     mDNSPlatformLock   (const mDNS *const m) { (void)m; }
-mDNSexport void     mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
-mDNSexport void     mDNSPlatformStrLCopy(     void *dst, const void *src, mDNSu32 dstlen) { mdns_strlcpy((char *)dst, (const char *)src, dstlen);}
-mDNSexport mDNSu32  mDNSPlatformStrLen (                 const void *src)              { return((mDNSu32)strlen((const char*)src)); }
-mDNSexport void     mDNSPlatformMemCopy(      void *dst, const void *src, mDNSu32 len) { memcpy(dst, src, len); }
-mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
-mDNSexport int      mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len)); }
-mDNSexport void     mDNSPlatformMemZero(      void *dst,                  mDNSu32 len) { memset(dst, 0, len); }
-mDNSexport void     mDNSPlatformQsort  (      void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-    qsort(base, nel, width, compar);
-}
-#if !MDNS_MALLOC_DEBUGGING
-mDNSexport void *mDNSPlatformMemAllocate(mDNSu32 len)      { return(mallocL("mDNSPlatformMemAllocate", len)); }
-mDNSexport void *mDNSPlatformMemAllocateClear(mDNSu32 len) { return(callocL("mDNSPlatformMemAllocateClear", len)); }
-mDNSexport void  mDNSPlatformMemFree    (void *mem)                 { freeL("mDNSPlatformMemFree", mem); }
-#endif
-
-mDNSexport void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason)
-{
-    mDNS *const m = &mDNSStorage;
-    if (allowSleep && m->p->IOPMAssertion)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT,
-            "mDNSPlatformSetAllowSleep Destroying NoIdleSleep power assertion");
-        IOPMAssertionRelease(m->p->IOPMAssertion);
-        m->p->IOPMAssertion = 0;
-    }
-    else if (!allowSleep)
-    {
-#ifdef kIOPMAssertionTypeNoIdleSleep
-        if (m->p->IOPMAssertion)
-        {
-            IOPMAssertionRelease(m->p->IOPMAssertion);
-            m->p->IOPMAssertion = 0;
-        }
-
-        CFStringRef assertionName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%d %s"), getprogname(), getpid(), reason ? reason : "");
-        IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, assertionName ? assertionName : CFSTR("mDNSResponder"), &m->p->IOPMAssertion);
-        MDNS_DISPOSE_CF_OBJECT(assertionName);
-        LogRedact(MDNS_LOG_CATEGORY_SPS, MDNS_LOG_DEFAULT,
-            "mDNSPlatformSetAllowSleep Creating NoIdleSleep power assertion");
-#endif
-    }
-}
-
-mDNSexport void mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason)
-{
-    mDNS *const m = &mDNSStorage;
-    if (m->p->IOPMAssertion)
-    {
-        LogSPS("Sleep Assertion is already being held. Will not attempt to get it again for %d seconds for %s", timeout, reason);
-        return;
-    }
-#ifdef kIOPMAssertionTypeNoIdleSleep
-
-#if TARGET_OS_IPHONE
-    if (!IsAppleTV())
-        return; // No need for maintenance wakes on non-AppleTV embedded devices.
-#endif
-
-    double timeoutVal = (double)timeout;
-    CFStringRef str = CFStringCreateWithCString(NULL, reason, kCFStringEncodingUTF8);
-    CFNumberRef Timeout_num = CFNumberCreate(NULL, kCFNumberDoubleType, &timeoutVal);
-    CFMutableDictionaryRef assertionProperties = CFDictionaryCreateMutable(NULL, 0,
-                                                                           &kCFTypeDictionaryKeyCallBacks,
-                                                                           &kCFTypeDictionaryValueCallBacks);
-    if (IsAppleTV())
-        CFDictionarySetValue(assertionProperties, kIOPMAssertionTypeKey, kIOPMAssertPreventUserIdleSystemSleep);
-    else
-        CFDictionarySetValue(assertionProperties, kIOPMAssertionTypeKey, kIOPMAssertMaintenanceActivity);
-
-    CFDictionarySetValue(assertionProperties, kIOPMAssertionTimeoutKey, Timeout_num);
-    CFDictionarySetValue(assertionProperties, kIOPMAssertionNameKey,    str);
-
-    IOPMAssertionCreateWithProperties(assertionProperties, (IOPMAssertionID *)&m->p->IOPMAssertion);
-    MDNS_DISPOSE_CF_OBJECT(str);
-    MDNS_DISPOSE_CF_OBJECT(Timeout_num);
-    MDNS_DISPOSE_CF_OBJECT(assertionProperties);
-    LogSPS("Got an idle sleep assertion for %d seconds for %s", timeout, reason);
-#endif
-}
-
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
-{
-    if (GetInterfaceSupportsWakeOnLANPacket(InterfaceID))
-    {
-        mDNSu32 ifindex;
-
-        // Sanity check
-        ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, InterfaceID, mDNStrue);
-        if (ifindex <= 0)
-        {
-            LogMsg("mDNSPlatformSendWakeupPacket: ERROR!! Invalid InterfaceID %u", ifindex);
-            return;
-        }
-        mDNSSendWakeupPacket(ifindex, EthAddr, IPAddr, iteration);
-    }
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfoOSX *info;
-
-    if (InterfaceID == mDNSInterface_P2P)
-        return mDNStrue;
-
-    // mDNSInterface_BLE not considered a D2D interface for the purpose of this
-    // routine, since it's not implemented via a D2D plugin.
-    if (InterfaceID == mDNSInterface_BLE)
-        return mDNSfalse;
-
-    if (   (InterfaceID == mDNSInterface_Any)
-        || (InterfaceID == mDNSInterfaceMark)
-        || (InterfaceID == mDNSInterface_LocalOnly))
-        return mDNSfalse;
-
-    // Compare to cached AWDL interface ID.
-    if (AWDLInterfaceID && (InterfaceID == AWDLInterfaceID))
-        return mDNStrue;
-    if (WiFiAwareInterfaceID && (InterfaceID == WiFiAwareInterfaceID))
-        return mDNStrue;
-    info = IfindexToInterfaceInfoOSX(InterfaceID);
-    if (info == NULL)
-    {
-        // this log message can print when operations are stopped on an interface that has gone away
-        LogInfo("mDNSPlatformInterfaceIsD2D: Invalid interface index %d", InterfaceID);
-        return mDNSfalse;
-    }
-
-    return (mDNSBool) info->D2DInterface;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME) || MDNSRESPONDER_SUPPORTS(APPLE, AWDL_FAST_CACHE_FLUSH)
-mDNSexport mDNSBool mDNSPlatformInterfaceIsAWDL(const mDNSInterfaceID interfaceID)
-{
-    return ((
-        (AWDLInterfaceID && (interfaceID == AWDLInterfaceID)) ||
-        (WiFiAwareInterfaceID && (interfaceID == WiFiAwareInterfaceID))
-    ) ? mDNStrue : mDNSfalse);
-}
-#endif
-
-// Filter records send over P2P (D2D) type interfaces
-// Note that the terms P2P and D2D are used synonymously in the current code and comments.
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
-{
-    // For an explicit match to a valid interface ID, return true.
-    if (rr->resrec.InterfaceID == InterfaceID)
-        return mDNStrue;
-
-    // Only filtering records for D2D type interfaces, return true for all other interface types.
-    if (!mDNSPlatformInterfaceIsD2D(InterfaceID))
-        return mDNStrue;
-
-    // If it's an AWDL interface the record must be explicitly marked to include AWDL.
-    if (InterfaceID == AWDLInterfaceID || InterfaceID == WiFiAwareInterfaceID)
-    {
-        if (rr->ARType == AuthRecordAnyIncludeAWDL || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
-            return mDNStrue;
-        else
-            return mDNSfalse;
-    }
-
-    // Send record if it is explicitly marked to include all other P2P type interfaces.
-    if (rr->ARType == AuthRecordAnyIncludeP2P || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
-        return mDNStrue;
-
-    // Don't send the record over this interface.
-    return mDNSfalse;
-}
-
-// Filter questions send over P2P (D2D) type interfaces.
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-    // For an explicit match to a valid interface ID, return true.
-    if (q->InterfaceID == intf->InterfaceID)
-        return mDNStrue;
-
-    // Only filtering questions for D2D type interfaces
-    if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
-        return mDNStrue;
-
-    // If it's an AWDL interface the question must be explicitly marked to include AWDL.
-    if (intf->InterfaceID == AWDLInterfaceID || intf->InterfaceID == WiFiAwareInterfaceID)
-    {
-        if (q->flags & kDNSServiceFlagsIncludeAWDL)
-            return mDNStrue;
-        else
-            return mDNSfalse;
-    }
-
-    // Sent question if it is explicitly marked to include all other P2P type interfaces.
-    if (q->flags & kDNSServiceFlagsIncludeP2P)
-        return mDNStrue;
-
-    // Don't send the question over this interface.
-    return mDNSfalse;
-}
-
-// Returns true unless record was received over the AWDL interface and
-// the question was not specific to the AWDL interface or did not specify kDNSServiceInterfaceIndexAny
-// with the kDNSServiceFlagsIncludeAWDL flag set.
-mDNSexport mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
-{
-    if (!rr->InterfaceID || (rr->InterfaceID == q->InterfaceID))
-        return mDNStrue;
-
-    if ((rr->InterfaceID == AWDLInterfaceID || rr->InterfaceID == WiFiAwareInterfaceID) && !(q->flags & kDNSServiceFlagsIncludeAWDL))
-        return mDNSfalse;
-
-    return mDNStrue;
-}
-
-// formating time to RFC 4034 format
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-{
-    struct tm tmTime;
-    time_t t = (time_t)te;
-    // Time since epoch : strftime takes "tm". Convert seconds to "tm" using
-    // gmtime_r first and then use strftime
-    gmtime_r(&t, &tmTime);
-    strftime((char *)buf, bufsize, "%Y%m%d%H%M%S", &tmTime);
-}
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-{
-    return getpid();
-}
-
-// Schedule a function asynchronously on the main queue
-mDNSexport void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func)
-{
-    // KQueueLock/Unlock is used for two purposes
-    //
-    // 1. We can't be running along with the KQueue thread and hence acquiring the lock
-    //    serializes the access to the "core"
-    //
-    // 2. KQueueUnlock also sends a message wake up the KQueue thread which in turn wakes
-    //    up and calls udsserver_idle which schedules the messages across the uds socket.
-    //    If "func" delivers something to the uds socket from the dispatch thread, it will
-    //    not be delivered immediately if not for the Unlock.
-    dispatch_async(dispatch_get_main_queue(), ^{
-        KQueueLock();
-        func(m, context);
-        KQueueUnlock("mDNSPlatformDispatchAsync");
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        // KQueueUnlock is a noop. Hence, we need to run kick off the idle loop
-        // to handle any message that "func" might deliver.
-        TriggerEventCompletion();
-#endif
-    });
-}
-
-// definitions for device-info record construction
-#define DEVINFO_MODEL       "model="
-#define DEVINFO_MODEL_LEN   sizeof_string(DEVINFO_MODEL)
-
-#define OSX_VER         "osxvers="
-#define OSX_VER_LEN     sizeof_string(OSX_VER)
-#define VER_NUM_LEN     2  // 2 digits of version number added to base string
-
-#define MODEL_RGB_COLOR       "ecolor="
-#define MODEL_INDEX_COLOR     "icolor="
-#define MODEL_COLOR_LEN       sizeof_string(MODEL_RGB_COLOR) // Same len as MODEL_INDEX_COLOR
-#define MODEL_COLOR_VALUE_LEN sizeof_string("255,255,255")   // 'r,g,b', 'i' MAXUINT32('4294967295')
-
-// Bytes available in TXT record for model name after subtracting space for other
-// fixed size strings and their length bytes.
-#define MAX_MODEL_NAME_LEN   (256 - (DEVINFO_MODEL_LEN + 1) - (OSX_VER_LEN + VER_NUM_LEN + 1) - (MODEL_COLOR_LEN + MODEL_COLOR_VALUE_LEN + 1))
-
-// Initialize device-info TXT record contents and return total length of record data.
-mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
-{
-    mDNSu8 *bufferStart = ptr;
-    mDNSu8 len = m->HIHardware.c[0] < MAX_MODEL_NAME_LEN ? m->HIHardware.c[0] : MAX_MODEL_NAME_LEN;
-
-    *ptr = DEVINFO_MODEL_LEN + len; // total length of DEVINFO_MODEL string plus the hardware name string
-    ptr++;
-    mDNSPlatformMemCopy(ptr, DEVINFO_MODEL, DEVINFO_MODEL_LEN);
-    ptr += DEVINFO_MODEL_LEN;
-    mDNSPlatformMemCopy(ptr, m->HIHardware.c + 1, len);
-    ptr += len;
-
-    // only include this string for OSX
-    if (OSXVers)
-    {
-        char    ver_num[VER_NUM_LEN + 1]; // version digits + null written by snprintf
-        *ptr = OSX_VER_LEN + VER_NUM_LEN; // length byte
-        ptr++;
-        mDNSPlatformMemCopy(ptr, OSX_VER, OSX_VER_LEN);
-        ptr += OSX_VER_LEN;
-        // convert version number to ASCII, add 1 for terminating null byte written by snprintf()
-        // WARNING: This code assumes that OSXVers is always exactly two digits
-        snprintf(ver_num, VER_NUM_LEN + 1, "%d", OSXVers);
-        mDNSPlatformMemCopy(ptr, ver_num, VER_NUM_LEN);
-        ptr += VER_NUM_LEN;
-
-#define MAX_COLOR_LEN (MODEL_COLOR_VALUE_LEN + 1)
-        char color[MAX_COLOR_LEN]; // Color string value + null written by snprintf
-        util_enclosure_color_t color_type = util_get_enclosure_color_str(color, MAX_COLOR_LEN, &len);
-        if (color_type != util_enclosure_color_none && len < MAX_COLOR_LEN)
-        {
-            *ptr = MODEL_COLOR_LEN + len; // length byte
-            ptr++;
-
-            if (color_type == util_enclosure_color_rgb) {
-                mDNSPlatformMemCopy(ptr, MODEL_RGB_COLOR, MODEL_COLOR_LEN);
-            } else {
-                mDNSPlatformMemCopy(ptr, MODEL_INDEX_COLOR, MODEL_COLOR_LEN);
-            }
-            ptr += MODEL_COLOR_LEN;
-
-            mDNSPlatformMemCopy(ptr, color, len);
-            ptr += len;
-        }
-    }
-
-    return (mDNSu32)(ptr - bufferStart);
-}
-
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-mDNSexport void GetRandomUUIDLabel(domainlabel *label)
-{
-    uuid_t uuid;
-    uuid_string_t uuidStr;
-    uuid_generate_random(uuid);
-    uuid_unparse_lower(uuid, uuidStr);
-    MakeDomainLabelFromLiteralString(label, uuidStr);
-}
-
-mDNSexport void GetRandomUUIDLocalHostname(domainname *hostname)
-{
-    domainlabel uuidLabel;
-    GetRandomUUIDLabel(&uuidLabel);
-    hostname->c[0] = 0;
-    AppendDomainLabel(hostname, &uuidLabel);
-    AppendLiteralLabelString(hostname, "local");
-}
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS)
-mDNSexport void uDNSMetricsClear(uDNSMetrics *const metrics)
-{
-    mDNSPlatformMemZero(metrics, (mDNSu32)sizeof(*metrics));
-}
-#endif
-
-#ifdef UNIT_TEST
-#include "../unittests/mdns_macosx_ut.c"
-#endif
diff --git a/mDNSMacOSX/mDNSMacOSX.h b/mDNSMacOSX/mDNSMacOSX.h
deleted file mode 100644
index 412af02..0000000
--- a/mDNSMacOSX/mDNSMacOSX.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __mDNSMacOSX_h
-#define __mDNSMacOSX_h
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <IOKit/pwr_mgt/IOPM.h>
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "mDNSEmbeddedAPI.h"        // for domain name structure
-#include <mdns/private.h>           // for mdns_interface_monitor_t struct
-
-#include <net/if.h>
-#include <os/log.h>
-
-//#define MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-#include <dispatch/dispatch.h>
-#include <dispatch/private.h>
-#endif
-
-#if TARGET_OS_IPHONE
-#define NO_SECURITYFRAMEWORK 1
-#define NO_CFUSERNOTIFICATION 1
-#endif
-
-#ifndef NO_SECURITYFRAMEWORK
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-#endif /* NO_SECURITYFRAMEWORK */
-
-#define kMDNSResponderIDStr "com.apple.mDNSResponder"
-#define kMDNSResponderID    CFSTR(kMDNSResponderIDStr)
-
-enum mDNSDynamicStoreSetConfigKey
-{
-    kmDNSMulticastConfig = 1,
-    kmDNSDynamicConfig,
-    kmDNSPrivateConfig,
-    kmDNSBackToMyMacConfig,
-    kmDNSSleepProxyServersState,
-    kmDNSDebugState, 
-};
-
-typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX;
-
-typedef void (*KQueueEventCallback)(int fd, short filter, void *context, mDNSBool encounteredEOF);
-typedef struct
-{
-    KQueueEventCallback KQcallback;
-    void                *KQcontext;
-    const char          *KQtask;        // For debugging messages
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    dispatch_source_t readSource;
-    dispatch_source_t writeSource;
-    mDNSBool fdClosed;
-#endif
-} KQueueEntry;
-
-typedef struct
-{
-    mDNSIPPort port; // MUST BE FIRST FIELD -- UDPSocket_struct begins with a KQSocketSet,
-    // and mDNSCore requires every UDPSocket_struct to begin with a mDNSIPPort port
-    mDNS                    *m;
-    int sktv4;
-    KQueueEntry kqsv4;
-    int sktv6;
-    KQueueEntry kqsv6;
-    int                     *closeFlag;
-    mDNSBool proxy;
-    mDNSBool sktv4EOF;
-    mDNSBool sktv6EOF;
-} KQSocketSet;
-
-struct UDPSocket_struct
-{
-    KQSocketSet ss;     // First field of KQSocketSet has to be mDNSIPPort -- mDNSCore requires every UDPSocket_struct to begin with mDNSIPPort port
-};
-
-// TCP socket support
-
-typedef enum
-{
-    handshake_required,
-    handshake_in_progress,
-    handshake_completed,
-    handshake_to_be_closed
-} handshakeStatus;
-
-struct TCPSocket_struct
-{
-    mDNSIPPort port;                // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with mDNSIPPort
-    TCPSocketFlags flags;           // MUST BE SECOND FIELD -- mDNSCore expects every TCPSocket_struct have TCPSocketFlags flags after mDNSIPPort
-    TCPConnectionCallback callback;
-    int fd;
-    KQueueEntry kqEntry;
-#ifndef NO_SECURITYFRAMEWORK
-    SSLContextRef tlsContext;
-    pthread_t handshake_thread;
-#endif /* NO_SECURITYFRAMEWORK */
-    domainname *hostname;
-    void *context;
-    mDNSBool setup;
-    mDNSBool connected;
-    handshakeStatus handshake;
-    mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
-    mStatus err;
-};
-
-struct TCPListener_struct
-{
-    TCPAcceptedCallback callback;
-    int fd;
-    KQueueEntry kqEntry;
-    void *context;
-    mDNSAddr_Type addressType;
-    TCPSocketFlags socketFlags;
-    mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
-};
-
-// Value assiged to 'Exists' to indicate the multicast state of the interface has changed.
-#define MulticastStateChanged   2
-
-struct NetworkInterfaceInfoOSX_struct
-{
-    NetworkInterfaceInfo ifinfo;                // MUST be the first element in this structure
-    NetworkInterfaceInfoOSX *next;
-    mDNS                    *m;
-    mDNSu8 Exists;                              // 1 = currently exists in getifaddrs list; 0 = doesn't
-                                                // 2 = exists, but McastTxRx state changed
-    mDNSu8 Flashing;                            // Set if interface appeared for less than 60 seconds and then vanished
-    mDNSu8 Occulting;                           // Set if interface vanished for less than 60 seconds and then came back
-    mDNSu8 D2DInterface;                        // IFEF_LOCALNET_PRIVATE flag indicates we should call
-                                                // D2D plugin for operations over this interface
-    mDNSs32 AppearanceTime;                     // Time this interface appeared most recently in getifaddrs list
-                                                // i.e. the first time an interface is seen, AppearanceTime is set.
-                                                // If an interface goes away temporarily and then comes back then
-                                                // AppearanceTime is updated to the time of the most recent appearance.
-    mDNSs32 LastSeen;                           // If Exists==0, last time this interface appeared in getifaddrs list
-    uint32_t ift_family;                        // IFRTYPE_FAMILY_XXX
-    unsigned int ifa_flags;
-    struct in_addr ifa_v4addr;
-    mDNSu32 scope_id;                           // interface index / IPv6 scope ID
-    mDNSEthAddr BSSID;                          // BSSID of 802.11 base station, if applicable
-    u_short sa_family;
-    int BPF_fd;                                 // -1 uninitialized; -2 requested BPF; -3 failed
-    int BPF_mcfd;                               // Socket for our IPv6 ND group membership
-    u_int BPF_len;
-    uint32_t ift_subfamily;                     // The interface's subfamily type from the SIOCGIFTYPE ioctl().
-    mDNSBool isAWDL;                            // True if this interface has the IFEF_AWDL flag set.
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    dispatch_source_t BPF_source;
-#else
-    CFSocketRef BPF_cfs;
-    CFRunLoopSourceRef BPF_rls;
-#endif
-    NetworkInterfaceInfoOSX *Registered;        // non-NULL means registered with mDNS Core
-};
-
-struct mDNS_PlatformSupport_struct
-{
-    NetworkInterfaceInfoOSX *InterfaceList;
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    CFMutableArrayRef InterfaceMonitors;
-#endif
-    KQSocketSet permanentsockets;
-    int num_mcasts;                             // Number of multicasts received during this CPU scheduling period (used for CPU limiting)
-    domainlabel userhostlabel;                  // The hostlabel as it was set in System Preferences the last time we looked
-    domainlabel usernicelabel;                  // The nicelabel as it was set in System Preferences the last time we looked
-    // Following four variables are used for optimization where the helper is not
-    // invoked when not needed. It records the state of what we told helper the
-    // last time we invoked mDNSPreferencesSetName
-    domainlabel prevoldhostlabel;               // Previous m->p->userhostlabel
-    domainlabel prevnewhostlabel;               // Previous m->hostlabel
-    domainlabel prevoldnicelabel;               // Previous m->p->usernicelabel
-    domainlabel prevnewnicelabel;               // Previous m->nicelabel
-    mDNSs32 NotifyUser;
-    mDNSs32 HostNameConflict;                   // Time we experienced conflict on our link-local host name
-    mDNSs32 KeyChainTimer;
-
-    SCDynamicStoreRef Store;
-    CFRunLoopSourceRef StoreRLS;
-    CFRunLoopSourceRef PMRLS;
-    int SysEventNotifier;
-    KQueueEntry SysEventKQueue;
-    IONotificationPortRef PowerPortRef;
-    io_connect_t PowerConnection;
-    io_object_t PowerNotifier;
-#ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
-    IOPMConnection IOPMConnection;
-#endif
-    IOPMAssertionID IOPMAssertion;
-    long SleepCookie;                           // Cookie we need to pass to IOAllowPowerChange()
-    long WakeAtUTC;
-    mDNSs32 RequestReSleep;
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    dispatch_source_t timer;
-    dispatch_source_t custom;
-#else
-    pthread_mutex_t BigMutex;
-#endif
-    mDNSs32 BigMutexStartTime;
-    int WakeKQueueLoopFD;
-    mDNSu8 v4answers;                  // non-zero if we are receiving answers
-    mDNSu8 v6answers;                  // for A/AAAA from external DNS servers
-    mDNSs32 DNSTrigger;                // Time the DNSTrigger was given
-    uint64_t LastConfigGeneration;     // DNS configuration generation number
-#if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSBool if_interface_changed;     // There are some changes that we do not know from LastConfigGeneration, such as
-                                       // if the interface is expensive/constrained or not. Therefore, we need an additional
-                                       // field to determine if the interface has changed.
-#endif
-    UDPSocket UDPProxy;
-    TCPSocket TCPProxyV4;
-    TCPSocket TCPProxyV6;
-    ProxyCallback *UDPProxyCallback;
-    ProxyCallback *TCPProxyCallback;
-};
-
-extern int OfferSleepProxyService;
-extern int DisableSleepProxyClient;
-extern int UseInternalSleepProxy;
-extern int OSXVers, iOSVers;
-
-extern int KQueueFD;
-
-extern void NotifyOfElusiveBug(const char *title, const char *msg); // Both strings are UTF-8 text
-extern void SetDomainSecrets(mDNS *m);
-extern void mDNSMacOSXNetworkChanged(void);
-extern void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring);
-extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex);
-extern void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF);
-extern void mDNSDynamicStoreSetConfig(enum mDNSDynamicStoreSetConfigKey key, const char *subkey, CFPropertyListRef value);
-extern void UpdateDebugState(void);
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-extern int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef);
-mDNSexport void TriggerEventCompletion(void);
-#else
-extern int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef);
-#endif
-
-// When events are processed on the non-kqueue thread (i.e. CFRunLoop notifications like Sleep/Wake,
-// Interface changes, Keychain changes, etc.) they must use KQueueLock/KQueueUnlock to lock out the kqueue thread
-extern void KQueueLock(void);
-extern void KQueueUnlock(const char* task);
-extern void mDNSPlatformCloseFD(KQueueEntry *kq, int fd);
-
-extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict);
-
-// If any event takes more than WatchDogReportingThreshold milliseconds to be processed, we log a warning message
-// General event categories are:
-//  o Mach client request initiated / terminated
-//  o UDS client request
-//  o Handling UDP packets received from the network
-//  o Environmental change events:
-//    - network interface changes
-//    - sleep/wake
-//    - keychain changes
-//  o Name conflict dialog dismissal
-//  o Reception of Unix signal (e.g. SIGINFO)
-//  o Idle task processing
-// If we find that we're getting warnings for any of these categories, and it's not evident
-// what's causing the problem, we may need to subdivide some categories into finer-grained
-// sub-categories (e.g. "Idle task processing" covers a pretty broad range of sub-tasks).
-
-extern int WatchDogReportingThreshold;
-
-struct CompileTimeAssertionChecks_mDNSMacOSX
-{
-    // 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_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <=  8704) ? 1 : -1];
-    char sizecheck_mDNS_PlatformSupport   [(sizeof(mDNS_PlatformSupport)    <=  1378) ? 1 : -1];
-};
-
-extern mDNSInterfaceID AWDLInterfaceID;
-extern mDNSInterfaceID WiFiAwareInterfaceID;
-void initializeD2DPlugins(mDNS *const m);
-void terminateD2DPlugins(void);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-extern void mDNSPlatformUpdateDNSStatus(const DNSQuestion *q);
-extern void mDNSPlatformTriggerDNSRetry(const DNSQuestion *v4q, const DNSQuestion *v6q);
-#endif
-
-extern mdns_interface_monitor_t GetInterfaceMonitorForIndex(uint32_t ifIndex);
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
diff --git a/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings b/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings
index 477d242..2d60c19 100644
--- a/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings
+++ b/mDNSMacOSX/mDNSResponder-bundle/Resources/English.lproj/Localizable.strings
@@ -1,3 +1,4 @@
+"OK" = "OK";
 "The name of your computer " = "The name of your computer ";
 "This computer’s local hostname " = "This computer’s local hostname ";
 "“" = "“";
@@ -6,8 +7,8 @@
 "The name has been changed to " = "The name has been changed to ";
 "." = ".";
 
-"To change the name of your computer, open System Preferences and click Sharing, then type the name in the Computer Name field." = "To change the name of your computer, open System Settings, go to General, Sharing, and type the name in the “Computer Name” field.";
-"To change the local hostname, open System Preferences and click Sharing, then click “Edit” and type the name in the Local Hostname field." = "To change the local hostname, open System Settings, go to General, Sharing, then click “Edit” and type the name in the “Local Hostname” field.";
+"To change the name of your computer, open System Preferences and click Sharing, then type the name in the Computer Name field." = "To change the name of your computer, open System Settings, go to General, About, and type the name in the “Name” field.";
+"To change the local hostname, open System Preferences and click Sharing, then click “Edit” and type the name in the Local Hostname field." = "To change the local hostname, open System Settings, go to General, Sharing, then click “Edit” and type the name in the “Local hostname” field.";
 
 "All attempts to find an available name by adding a number to the name were also unsuccessful." = "All attempts to find an available name by adding a number to the name were also unsuccessful.";
 "This may indicate a problem with the local network. Please inform your network administrator." = "This may indicate a problem with the local network. Please inform your network administrator.";
diff --git a/mDNSMacOSX/secure_coding/secure-coding.xcconfig b/mDNSMacOSX/secure_coding/secure-coding.xcconfig
index 9fb60f5..6a97c59 100644
--- a/mDNSMacOSX/secure_coding/secure-coding.xcconfig
+++ b/mDNSMacOSX/secure_coding/secure-coding.xcconfig
@@ -1,9 +1,9 @@
 //
 // secure-coding.xcconfig
 //
-// Copyright (c) 2019 Apple Inc.
+// Copyright (c) 2019, 2022 Apple Inc.
 // All rights reserved.
 //
 // https://confluence.sd.apple.com/display/NETWORKING/Code+Safety+Checklist
 //
-WARNING_CFLAGS = $(inherited) -Weverything -Wno-missing-variable-declarations -Wno-reserved-id-macro -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-length-array -Wno-cast-align -Wno-cstring-format-directive -Wno-nullability-extension -Wno-format-pedantic -Wno-objc-missing-property-synthesis -Wno-c++98-compat-pedantic -Wno-gnu-empty-initializer -Werror -Wno-error=deprecated-declarations -Wno-error=deprecated-implementations -Wno-error=objc-designated-initializers -Wno-error=nonnull -Wno-error=nullable-to-nonnull-conversion -Wno-error=nullability-declspec -Wno-error=#warnings
+WARNING_CFLAGS = $(inherited) -Weverything -Wno-missing-variable-declarations -Wno-reserved-id-macro -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-length-array -Wno-cast-align -Wno-cstring-format-directive -Wno-nullability-extension -Wno-format-pedantic -Wno-objc-missing-property-synthesis -Wno-c++98-compat-pedantic -Wno-gnu-empty-initializer -Werror -Wno-error=deprecated-declarations -Wno-error=deprecated-implementations -Wno-error=objc-designated-initializers -Wno-error=nonnull -Wno-error=nullable-to-nonnull-conversion -Wno-error=nullability-declspec -Wno-error=#warnings -Wno-declaration-after-statement
diff --git a/mDNSMacOSX/secure_coding/strict.h b/mDNSMacOSX/secure_coding/strict.h
deleted file mode 100644
index c12381f..0000000
--- a/mDNSMacOSX/secure_coding/strict.h
+++ /dev/null
@@ -1,631 +0,0 @@
-//
-//  strict.h
-//
-//  Copyright (c) 2017-2022 Apple Inc. All rights reserved.
-//
-// Strictly enforces checks for memory allocation failures and setting pointers to NULL after free, based on NRSafeish.h
-// from the NetworkRelay project and nw_strict.h from libnetcore. This header file is intended to help the compiler
-// enforce better coding practices. It won't prevent clever engineers from introducing bugs but it may reduce a
-// number of potentially hard to track down memory smashers.
-
-#ifndef __STRICT_H__
-#define __STRICT_H__
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <malloc/malloc.h>
-
-#ifdef __BLOCKS__
-#include <Block.h>
-#endif // __BLOCKS__
-
-#ifdef __cplusplus
-#include <new>
-#endif // __cplusplus
-
-#pragma mark - Abort
-
-// If you include CrashReporterClient.h before this file, STRICT_ABORT will set the crash reason. If you have a more
-// sophisticated way to abort, define STRICT_ABORT before including this file.
-#ifndef STRICT_ABORT
-#define DEFINED_STRICT_ABORT
-#ifdef _H_CRASH_REPORTER_CLIENT
-#define STRICT_ABORT(format, ...)                   \
-    do {                                            \
-        char *reason = NULL;                        \
-        asprintf(&reason, format, ##__VA_ARGS__);   \
-        CRSetCrashLogMessage(reason);               \
-        __builtin_trap();                           \
-    } while (0)
-#else // _H_CRASH_REPORTER_CLIENT
-#define STRICT_ABORT(format, ...)       \
-    do {                                \
-        __builtin_trap();               \
-    } while (0)
-#endif // _H_CRASH_REPORTER_CLIENT
-#endif // STRICT_ABORT
-
-#pragma mark - Unlikely Macros
-
-#ifdef __cplusplus
-#define _STRICT_LIKELY_BOOL(b)          (__builtin_expect(!!(static_cast<long>(b)), 1L))
-#define _STRICT_UNLIKELY_BOOL(b)        (__builtin_expect(!!(static_cast<long>(b)), 0L))
-#define _STRICT_UNLIKELY_IS_NULL(obj)   _STRICT_UNLIKELY_BOOL(nullptr == (obj))
-#else // __cplusplus
-#define _STRICT_LIKELY_BOOL(b)          (__builtin_expect(!!((long)(b)), 1L))
-#define _STRICT_UNLIKELY_BOOL(b)        (__builtin_expect(!!((long)(b)), 0L))
-#define _STRICT_UNLIKELY_IS_NULL(obj)   _STRICT_UNLIKELY_BOOL(NULL == (obj))
-#endif // __cplusplus
-
-#pragma mark - Alloc
-
-__BEGIN_DECLS
-
-#pragma clang assume_nonnull begin
-
-static
-__attribute__((__malloc__))
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(1)
-void *strict_malloc(size_t size)
-{
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("strict_malloc called with size 0");
-        // Not reached
-    }
-    void *buffer = malloc(size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("strict_malloc(%zu) failed", size);
-        // Not reached
-    }
-    return buffer;
-}
-
-#define STRICT_MALLOC_TYPE(type)    \
-    (type*)strict_malloc(sizeof(type))
-
-static
-__attribute__((__malloc__))
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(1,2)
-void *strict_calloc(size_t count, size_t size)
-{
-    if (_STRICT_UNLIKELY_BOOL(count == 0)) {
-        STRICT_ABORT("strict_calloc called with count 0");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("strict_calloc called with size 0");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(count > SIZE_MAX/size)) {
-        STRICT_ABORT("strict_calloc count * size would overflow");
-    }
-    void *buffer = calloc(count, size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("strict_calloc(%zu, %zu) failed", count, size);
-        // Not reached
-    }
-    return buffer;
-}
-
-#define STRICT_CALLOC_TYPE(type)    \
-    (type*)strict_calloc(1, sizeof(type))
-
-#define strict_reallocf(ptr, size)                                  \
-    _Pragma("clang diagnostic push")                                \
-    _Pragma("clang diagnostic ignored \"-Wdirect-ivar-access\"")    \
-    _strict_reallocf((void **)&(ptr), size)                         \
-    _Pragma("clang diagnostic pop")
-
-static
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(2)
-void *_strict_reallocf(void * _Nullable * _Nonnull ptr, size_t size)
-{
-    if (_STRICT_UNLIKELY_IS_NULL(ptr)) {
-        STRICT_ABORT("_strict_reallocf called with NULL ptr");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("_strict_reallocf called with size 0");
-        // Not reached
-    }
-    void *buffer = reallocf(*ptr, size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("_strict_reallocf(%zu) failed", size);
-        // Not reached
-    }
-#ifdef __cplusplus
-    *ptr = reinterpret_cast<void *>(NULL);
-#else // __cplusplus
-    *ptr = NULL;
-#endif // __cplusplus
-    return buffer;
-}
-
-#define STRICT_REALLOCF_TYPE(ptr, type)    \
-    (type*)strict_reallocf(ptr, sizeof(type))
-
-static
-__attribute__((__malloc__))
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(2)
-void *strict_memalign(size_t alignment, size_t size)
-{
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("strict_memalign called with size 0");
-        // Not reached
-    }
-
-    if (_STRICT_UNLIKELY_BOOL(alignment < sizeof(void*))) {
-        STRICT_ABORT("strict_memalign called with alignment (%zu) < sizeof(void*)", alignment);
-        // Not reached
-    }
-
-    // Ensure that alignment is a power of 2. This is likely to catch
-    // someone swapping the alignment and size parameters by mistake.
-    if (_STRICT_UNLIKELY_BOOL((alignment & (alignment - 1)) != 0)) {
-        STRICT_ABORT("strict_memalign called with alignment (%zu) that is not a power of 2", alignment);
-        // Not reached
-    }
-
-#ifdef __cplusplus
-    void *buffer = nullptr;
-#else // __cplusplus
-    void *buffer = NULL;
-#endif // __cplusplus
-    if (_STRICT_UNLIKELY_BOOL((posix_memalign(&buffer, alignment, size) != 0 || buffer == NULL))) {
-        STRICT_ABORT("posix_memalign(..., %zu, %zu) failed", alignment, size);
-        // Not reached
-    }
-    return buffer;
-}
-
-static
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-char *strict_strdup(const char *string)
-{
-    if (_STRICT_UNLIKELY_IS_NULL(string)) {
-        STRICT_ABORT("strict_strdup called with NULL string");
-        // Not reached
-    }
-
-    char *result = strdup(string);
-    if (_STRICT_UNLIKELY_BOOL(result == NULL)) {
-        STRICT_ABORT("strdup() failed");
-        // Not reached
-    }
-    return result;
-}
-
-static
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-char *strict_strndup(const char *string, size_t n)
-{
-    if (_STRICT_UNLIKELY_IS_NULL(string)) {
-        STRICT_ABORT("strict_strndup called with NULL string");
-        // Not reached
-    }
-
-    char *result = strndup(string, n);
-    if (_STRICT_UNLIKELY_BOOL(result == NULL)) {
-        STRICT_ABORT("strndup() failed");
-        // Not reached
-    }
-    return result;
-}
-
-#define strict_strlcpy(DST, SRC, DST_LEN) _strict_strlcpy((char *_Nonnull)DST, (const char *_Nonnull)SRC, DST_LEN)
-
-// An almost drop-in replacement for strlcpy that doesn't require src
-// to be NULL terminated. Unlike strlcpy, it returns void rather than
-// strlen(src).
-static
-inline __attribute__((always_inline))
-void _strict_strlcpy(char *dst, const char *src, size_t dst_len)
-{
-	if (_STRICT_UNLIKELY_IS_NULL(dst)) {
-		STRICT_ABORT("strict_strlcpy called with NULL dst");
-		// Not reached
-	}
-
-	if (_STRICT_UNLIKELY_IS_NULL(src)) {
-		STRICT_ABORT("strict_strlcpy called with NULL src");
-		// Not reached
-	}
-
-	size_t bytes_to_copy = dst_len;
-
-	// Copy as many bytes as we can while making sure
-	// we leave one byte (the last byte) of dst for
-	// the trailing \0 if necessary.
-	while (bytes_to_copy > 1) {
-		if ((*dst++ = *src++) == '\0') {
-			bytes_to_copy = 0;
-			// Although functionally unnecessary, breaking out of the while loop here
-			// is significantly more performant than going back into the while and
-			// breaking out because bytes_to_copy is no longer > 1.
-			break;
-		} else {
-			bytes_to_copy--;
-		}
-	}
-
-	if (bytes_to_copy == 1 && dst_len != 0) {
-		*dst = '\0';
-	}
-}
-
-#define strict_strlcat(DST, SRC, DST_LEN) _strict_strlcat((char *_Nonnull)DST, (const char *_Nonnull)SRC, DST_LEN)
-
-// An almost drop-in replacement for strlcat that doesn't require src
-// to be NULL terminated. Unlike strlcat, it returns void rather than
-// strlen(src) + strlen(dst).
-static
-inline __attribute__((always_inline))
-void _strict_strlcat(char *dst, const char *src, size_t dst_len)
-{
-	if (_STRICT_UNLIKELY_IS_NULL(dst)) {
-		STRICT_ABORT("strict_strlcat called with NULL dst");
-		// Not reached
-	}
-
-	if (_STRICT_UNLIKELY_IS_NULL(src)) {
-		STRICT_ABORT("strict_strlcat called with NULL src");
-		// Not reached
-	}
-
-	while (dst_len != 0 && *dst != '\0') {
-		dst_len--;
-		dst++;
-	}
-
-	_strict_strlcpy(dst, src, dst_len);
-}
-
-#define STRICT_ALLOC_ALIGN_TYPE(align, type)    \
-    (type*)strict_memalign(align, sizeof(type))
-
-static
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(2)
-void *strict_malloc_zone_malloc(malloc_zone_t *zone, size_t size)
-{
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("strict_malloc_zone_malloc called with size 0");
-        // Not reached
-    }
-	void *buffer = malloc_zone_malloc(zone, size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("strict_malloc_zone_malloc(%zu) failed", size);
-        // Not reached
-    }
-	return buffer;
-}
-
-static
-__attribute__((__malloc__))
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(2,3)
-void *strict_malloc_zone_calloc(malloc_zone_t *zone, size_t count, size_t size)
-{
-    if (_STRICT_UNLIKELY_BOOL(count == 0)) {
-        STRICT_ABORT("strict_malloc_zone_calloc called with count 0");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("strict_malloc_zone_calloc called with size 0");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(count > SIZE_MAX/size)) {
-        STRICT_ABORT("strict_malloc_zone_calloc count * size would overflow");
-    }
-    void *buffer = malloc_zone_calloc(zone, count, size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("strict_malloc_zone_calloc(%zu, %zu) failed", count, size);
-        // Not reached
-    }
-    return buffer;
-}
-
-#define STRICT_MALLOC_ZONE_CALLOC_TYPE(zone, type)    \
-	(type*)strict_malloc_zone_calloc(zone, 1, sizeof(type))
-
-static
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(3)
-void *_strict_malloc_zone_realloc(malloc_zone_t *zone, void * _Nullable * _Nonnull ptr, size_t size)
-{
-    if (_STRICT_UNLIKELY_IS_NULL(ptr)) {
-        STRICT_ABORT("_strict_malloc_zone_realloc called with NULL ptr");
-        // Not reached
-    }
-    if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-        STRICT_ABORT("_strict_malloc_zone_realloc called with size 0");
-        // Not reached
-    }
-    void *buffer = malloc_zone_realloc(zone, *ptr, size);
-    if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-        STRICT_ABORT("_strict_malloc_zone_realloc(%zu) failed", size);
-        // Not reached
-    }
-#ifdef __cplusplus
-    *ptr = reinterpret_cast<void *>(NULL);
-#else // __cplusplus
-    *ptr = NULL;
-#endif // __cplusplus
-    return buffer;
-}
-
-#define strict_malloc_zone_realloc(zone, ptr, size)                 \
-    _Pragma("clang diagnostic push")                                \
-    _Pragma("clang diagnostic ignored \"-Wdirect-ivar-access\"")    \
-    _strict_malloc_zone_realloc((void **)&(ptr), size)              \
-    _Pragma("clang diagnostic pop")
-
-static
-__attribute__((__malloc__))
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-__alloc_size(3)
-void *strict_malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
-{
-	if (_STRICT_UNLIKELY_BOOL(size == 0)) {
-		STRICT_ABORT("strict_malloc_zone_memalign called with size 0");
-		// Not reached
-	}
-
-	if (_STRICT_UNLIKELY_BOOL(alignment < sizeof(void*))) {
-		STRICT_ABORT("strict_malloc_zone_memalign called with alignment (%zu) < sizeof(void*)", alignment);
-		// Not reached
-	}
-
-	// Ensure that alignment is a power of 2. This is likely to catch
-	// someone swapping the alignment and size parameters by mistake.
-	if (_STRICT_UNLIKELY_BOOL((alignment & (alignment - 1)) != 0)) {
-		STRICT_ABORT("strict_malloc_zone_memalign called with alignment (%zu) that is not a power of 2", alignment);
-		// Not reached
-	}
-
-	void *buffer = malloc_zone_memalign(zone, alignment, size);
-	if (_STRICT_UNLIKELY_BOOL(buffer == NULL)) {
-		STRICT_ABORT("malloc_zone_memalign(..., %zu, %zu) failed", alignment, size);
-		// Not reached
-	}
-	return buffer;
-}
-
-#pragma clang assume_nonnull end
-
-__END_DECLS
-
-#if defined(__cplusplus)
-template<class T>
-__attribute__((__warn_unused_result__))
-inline __attribute__((always_inline))
-T * _Nonnull strict_new()
-{
-	// Strictly speaking, we neither need to make sure new doesn't throw,
-	// nor check if new returned nullptr because strict_calloc is supplying
-	// the memory and it is guaranteed to either return the bytes requested
-	// or abort. But we'll check for nullptr to be extra defensive.
-	T *buffer = new (strict_calloc(1, sizeof(T))) T;
-	if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-		STRICT_ABORT("strict_new(%s) failed", __PRETTY_FUNCTION__);
-		// Not reached
-	}
-	return buffer;
-}
-
-template<class T>
-inline __attribute__((always_inline))
-T * _Nonnull strict_placement_new(void * _Nonnull _buffer)
-{
-	if (_buffer == nullptr) {
-		STRICT_ABORT("strict_placement_new(%s) called with NULL buffer", __PRETTY_FUNCTION__);
-	}
-
-	// Strictly speaking, we neither need to make sure new doesn't throw,
-	// nor check if new returned nullptr because the buffer passed in was
-	// checked to be non-null. But we'll check for nullptr to be extra
-	// defensive.
-	T *buffer = new (_buffer) T;
-	if (_STRICT_UNLIKELY_IS_NULL(buffer)) {
-		STRICT_ABORT("strict_placement_new(%s) failed", __PRETTY_FUNCTION__);
-		// Not reached
-	}
-	return buffer;
-}
-
-#define STRICT_NEW_TYPE(TYPE)									\
-	strict_new<TYPE>()
-
-#define STRICT_PLACEMENT_NEW_TYPE(TYPE, MEMORY)					\
-	strict_placement_new<TYPE>(MEMORY)
-
-template<class T>
-inline __attribute__((always_inline))
-void strict_delete(T ptr)
-{
-	if (ptr != nullptr) {
-		delete ptr;
-	}
-}
-#endif // __cplusplus
-
-#pragma mark - Dispose
-
-#define _STRICT_DISPOSE_NOT_NULL_TEMPLATE(ptr, function)        \
-    do {                                                        \
-        if (_STRICT_UNLIKELY_IS_NULL(ptr)) {                     \
-            STRICT_ABORT(#ptr " is NULL");                      \
-        } else {                                                \
-            function(ptr);                                      \
-            (ptr) = NULL;                                       \
-        }                                                       \
-    } while(0)
-
-#define _STRICT_DISPOSE_TEMPLATE(ptr, function) \
-    do {                                        \
-        if ((ptr) != NULL) {                    \
-            function(ptr);                      \
-            (ptr) = NULL;                       \
-        }                                       \
-    } while(0)
-
-#define STRICT_DISPOSE_XPC_NOT_NULL(obj) \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(obj, xpc_release)
-
-#define STRICT_DISPOSE_XPC(obj) \
-    _STRICT_DISPOSE_TEMPLATE(obj, xpc_release)
-
-#define STRICT_DISPOSE_ALLOCATED_NOT_NULL(ptr)  \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(ptr, free)
-
-#define STRICT_DISPOSE_ALLOCATED(ptr)   \
-    _STRICT_DISPOSE_TEMPLATE(ptr, free)
-
-#define strict_free(ptr) STRICT_DISPOSE_ALLOCATED(ptr)
-
-#define strict_malloc_zone_free(zone, ptr)  \
-    do {                                    \
-        if ((ptr) != NULL) {                \
-            malloc_zone_free(zone, ptr);    \
-            (ptr) = NULL;                   \
-        }                                   \
-    } while (0)
-
-#define STRICT_DISPOSE_DISPATCH_NOT_NULL(obj)   \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(obj, dispatch_release)
-
-#define STRICT_DISPOSE_DISPATCH(obj)    \
-    _STRICT_DISPOSE_TEMPLATE(obj, dispatch_release)
-
-#define STRICT_DISPOSE_BLOCK_NOT_NULL(obj)  \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(obj, _Block_release)
-
-#define STRICT_DISPOSE_BLOCK(obj)   \
-    _STRICT_DISPOSE_TEMPLATE(obj, _Block_release)
-
-// Avoid resetting the block if it is equal
-// This can lead to the block getting destroyed
-#define STRICT_RESET_BLOCK(reference, new_block)                   \
-    do {                                                           \
-        if (_STRICT_LIKELY_BOOL(reference != new_block)) {         \
-            __typeof(reference) new_block_temp = new_block;        \
-            if (new_block_temp != NULL) {                          \
-                new_block_temp = Block_copy(new_block_temp);       \
-            }                                                      \
-            STRICT_DISPOSE_BLOCK(reference);                       \
-            reference = new_block_temp;                            \
-        }                                                          \
-    } while(0)
-
-#define STRICT_DISPOSE_CF_OBJECT_NOT_NULL(obj)  \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(obj, CFRelease)
-
-#define STRICT_DISPOSE_CF_OBJECT(obj)  \
-    _STRICT_DISPOSE_TEMPLATE(obj, CFRelease)
-
-#define STRICT_DISPOSE_ADDRINFO_NOT_NULL(ptr)    \
-    _STRICT_DISPOSE_NOT_NULL_TEMPLATE(ptr, freeaddrinfo)
-
-#define STRICT_DISPOSE_ADDRINFO(ptr)    \
-    _STRICT_DISPOSE_TEMPLATE(ptr, freeaddrinfo)
-
-#if defined(__cplusplus)
-#define STRICT_DELETE(ptr)					\
-	_STRICT_DISPOSE_TEMPLATE(ptr, strict_delete)
-#define STRICT_DELETE_THIS(ptr)				\
-	strict_delete(ptr)
-#endif // __cplusplus
-
-#pragma mark - Poison
-
-#if !defined(BUILD_TEXT_BASED_API) || BUILD_TEXT_BASED_API == 0
-
-#ifdef __BLOCKS__
-#include <Block.h>
-#endif // __BLOCKS__
-
-#pragma GCC poison malloc			// use STRICT_MALLOC_TYPE or strict_malloc instead
-#pragma GCC poison calloc			// use STRICT_CALLOC_TYPE or strict_calloc instead
-#pragma GCC poison realloc			// use STRICT_REALLOCF_TYPE or strict_reallocf instead
-#pragma GCC poison reallocf			// use STRICT_REALLOCF_TYPE or strict_reallocf instead
-#pragma GCC poison posix_memalign	// use STRICT_ALLOC_ALIGN_TYPE instead
-#pragma GCC poison strdup			// use strict_strdup instead
-#pragma GCC poison strndup			// use strict_strndup instead
-#pragma GCC poison free				// use strict_free or STRICT_DISPOSE_ALLOCATED instead
-#pragma GCC poison CFRelease		// use STRICT_DISPOSE_CF_OBJECT instead
-#if defined(__cplusplus)
-#pragma GCC poison new				// use STRICT_NEW_TYPE or strict_new instead
-#pragma GCC poison delete			// use STRICT_DELETE, STRICT_DELETE_THIS or strict_delete instead
-#endif // __cplusplus
-
-#pragma GCC poison malloc_zone_malloc   // use strict_malloc_zone_malloc instead
-#pragma GCC poison malloc_zone_calloc   // use strict_malloc_zone_calloc instead
-#pragma GCC poison malloc_zone_realloc  // use strict_malloc_zone_realloc instead
-#pragma GCC poison malloc_zone_memalign	// use strict_malloc_zone_memalign instead
-#pragma GCC poison malloc_zone_free     // use strict_malloc_zone_free instead
-
-#ifndef DO_NOT_POISON_UNSAFE_STRING_FUNCTIONS
-#ifdef strncat
-#undef strncat
-#endif // strncat
-#pragma GCC poison strncat			// use strict_strlcat instead
-
-#ifdef strncpy
-#undef strncpy
-#endif // strncpy
-#pragma GCC poison strncpy			// use strict_strlcpy instead
-
-#ifdef strlcpy
-#undef strlcpy
-#endif // strlcpy
-#pragma GCC poison strlcpy			// use strict_strlcpy instead
-
-#ifdef strlcat
-#undef strlcat
-#endif // strlcat
-#pragma GCC poison strlcat			// use strict_strlcat instead
-
-#ifdef sprintf
-#undef sprintf
-#endif // sprintf
-#pragma GCC poison sprintf			// use snprintf instead
-#endif // DO_NOT_POISON_UNSAFE_STRING_FUNCTIONS
-
-// The following may be defines. GCC poison doesn't work with defines,
-// so we undef them first.
-#ifdef dispatch_release
-#undef dispatch_release
-#endif // dispatch_release
-#pragma GCC poison dispatch_release	// use STRICT_DISPOSE_DISPATCH instead
-
-#ifdef xpc_release
-#undef xpc_release
-#endif // xpc_release
-#pragma GCC poison xpc_release		// use STRICT_DISPOSE_XPC instead
-
-#ifdef Block_release
-#undef Block_release
-#endif // Block_release
-#pragma GCC poison Block_release	// use STRICT_DISPOSE_BLOCK instead
-
-#endif // defined(BUILD_TEXT_BASED_API) && BUILD_TEXT_BASED_API
-
-#ifdef DEFINED_STRICT_ABORT
-#undef STRICT_ABORT
-#endif // DEFINED_STRICT_ABORT
-
-#endif // __STRICT_H__
diff --git a/mDNSMacOSX/uDNSPathEvaluation.c b/mDNSMacOSX/uDNSPathEvaluation.c
deleted file mode 100644
index b44cefa..0000000
--- a/mDNSMacOSX/uDNSPathEvaluation.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2013-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "mDNSMacOSX.h"
-#include <mdns/system.h>
-#include <nw/private.h>
-
-#include "dns_sd_internal.h"
-#include "mdns_strict.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#define _nw_forget(PTR)         \
-    do                          \
-    {                           \
-        if (*(PTR))             \
-        {                       \
-            nw_release(*(PTR)); \
-            *(PTR) = NULL;      \
-        }                       \
-    } while (0)
-
-//Gets the DNSPolicy from NW PATH EVALUATOR
-mDNSexport void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q)
-{
-    nw_endpoint_t host = NULL;
-    nw_parameters_t parameters = NULL;
-    nw_path_evaluator_t evaluator = NULL;
-    nw_path_t path = NULL;
-    mDNSBool isBlocked = mDNSfalse;
-    q->ServiceID = -1; // initialize the ServiceID to default value of -1
-
-    // Return for non-unicast DNS queries, or invalid PID.
-    if (mDNSOpaque16IsZero(q->TargetQID) || (q->pid < 0))
-    {
-        goto exit;
-    }
-
-    mDNSs32 service_id;
-    mDNSu32 client_ifindex, dnspol_ifindex;
-    mDNSBool isUUIDSet;
-
-    char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
-    ConvertDomainNameToCString(&q->qname, unenc_name);
-
-    host = nw_endpoint_create_host(unenc_name, "0");
-    if (host == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME " (" PUB_S "), PID[%d], EUID[%d], ServiceID[%d]"
-            " host is NULL",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
-        goto exit;
-    }
-    parameters = nw_parameters_create();
-    if (parameters == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME " (" PUB_S "), PID[%d], EUID[%d], ServiceID[%d]"
-            " parameters is NULL",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
-        goto exit;
-    }
-#if TARGET_OS_WATCH
-    static xpc_object_t prohibited_interface_subtypes = NULL;
-    // Companion interface on watchOS does not support DNS, so we don't want path evalution to return it to us.
-    if (prohibited_interface_subtypes == NULL)
-    {
-        prohibited_interface_subtypes = xpc_array_create(NULL, 0);
-        if (prohibited_interface_subtypes != NULL)
-        {
-            xpc_array_set_uint64(prohibited_interface_subtypes, XPC_ARRAY_APPEND, nw_interface_subtype_companion);
-        }
-    }
-    if (prohibited_interface_subtypes == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_UDNS, MDNS_LOG_ERROR,
-                  "mDNSPlatformGetDNSRoutePolicy: DNS Route Policy: prohibited_interface_subtypes returned by xpc_array_create() is NULL");
-    }
-    else
-    {
-        nw_parameters_set_prohibited_interface_subtypes(parameters, prohibited_interface_subtypes);
-    }
-#endif // TARGET_OS_WATCH
-
-    // Check for all the special (negative) internal value interface indices before initializing client_ifindex
-    if (   (q->InterfaceID == mDNSInterface_Any)
-        || (q->InterfaceID == mDNSInterface_LocalOnly)
-        || (q->InterfaceID == mDNSInterfaceMark)
-        || (q->InterfaceID == mDNSInterface_P2P)
-        || (q->InterfaceID == mDNSInterface_BLE)
-        || (q->InterfaceID == uDNSInterfaceMark))
-    {
-        client_ifindex = 0;
-    }
-    else
-    {
-        client_ifindex = (mDNSu32)(uintptr_t)q->InterfaceID;
-    }
-
-    if (client_ifindex > 0)
-    {
-        nw_interface_t client_intf = nw_interface_create_with_index(client_ifindex);
-        if (client_intf)
-        {
-            nw_parameters_require_interface(parameters, client_intf);
-            _nw_forget(&client_intf);
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] mDNSPlatformGetDNSRoutePolicy: nw_interface_create_with_index() returned NULL for index %u",
-                mDNSVal16(q->TargetQID), client_ifindex);
-        }
-    }
-
-    nw_parameters_set_uid(parameters,(uid_t)q->euid);
-
-    if (q->pid != 0)
-    {
-        nw_parameters_set_pid(parameters, q->pid);
-        uuid_t uuid;
-        const OSStatus err = mdns_system_pid_to_uuid(q->pid, uuid);
-        if (!err)
-        {
-            nw_parameters_set_e_proc_uuid(parameters, uuid);
-            isUUIDSet = mDNStrue;
-        }
-        else
-        {
-            debugf("mDNSPlatformGetDNSRoutePolicy: proc_pidinfo returned %ld", (long)err);
-            isUUIDSet = mDNSfalse;
-        }
-    }
-    else
-    {
-        nw_parameters_set_e_proc_uuid(parameters, q->uuid);
-        isUUIDSet = mDNStrue;
-    }
-
-    evaluator = nw_path_create_evaluator_for_endpoint(host, parameters);
-    if (evaluator == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME " (" PUB_S "), PID[%d], EUID[%d], ServiceID[%d]"
-            " evaluator is NULL",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
-        goto exit;
-    }
-    _nw_forget(&host);
-    _nw_forget(&parameters);
-
-    path = nw_path_evaluator_copy_path(evaluator);
-    if (path == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME " (" PUB_S "), PID[%d], EUID[%d], ServiceID[%d]"
-            " path is NULL",
-            mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
-        goto exit;
-    }
-
-    if (nw_path_get_status(path) == nw_path_status_satisfied)
-    {
-        service_id = (mDNSs32)nw_path_get_flow_divert_unit(path);
-        if (service_id != 0)
-        {
-            q->ServiceID = service_id;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                "[Q%u] mDNSPlatformGetDNSRoutePolicy: Query for " PRI_DM_NAME " service ID is set ->service_ID:[%d] ",
-                mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), service_id);
-        }
-        else
-        {
-            nw_interface_t nwpath_intf = nw_path_copy_scoped_interface(path);
-            if (nwpath_intf != NULL)
-            {
-                // Use the new scoped interface given by NW PATH EVALUATOR
-                dnspol_ifindex = nw_interface_get_index(nwpath_intf);
-                q->InterfaceID = (mDNSInterfaceID)(uintptr_t)dnspol_ifindex;
-
-                _nw_forget(&nwpath_intf);
-
-                if (dnspol_ifindex != client_ifindex)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                        "[Q%u] mDNSPlatformGetDNSRoutePolicy: DNS Route Policy has changed the scoped ifindex from [%d] to [%d]",
-                        mDNSVal16(q->TargetQID), client_ifindex, dnspol_ifindex);
-                }
-            }
-            else
-            {
-                debugf("mDNSPlatformGetDNSRoutePolicy: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] nw_interface_t nwpath_intf is NULL ", q->qname.c, DNSTypeName(q->qtype), q->pid, q->euid, q->ServiceID);
-            }
-        }
-    }
-    else if (isUUIDSet && (nw_path_get_status(path) == nw_path_status_unsatisfied) && (nw_path_get_reason(path) != nw_path_reason_no_route))
-    {
-        isBlocked = mDNStrue;
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (!isBlocked)
-    {
-        uuid_clear(q->ResolverUUID);
-        if (path != NULL)
-        {
-            __block nw_resolver_config_t best_config = NULL;
-            __block mDNSBool best_config_allows_failover = mDNSfalse;
-            __block nw_resolver_class_t best_class = nw_resolver_class_default_direct;
-            nw_path_enumerate_resolver_configs(path,
-            ^bool(nw_resolver_config_t config)
-            {
-                const mDNSBool allows_failover = nw_resolver_config_get_allow_failover(config);
-                const nw_resolver_class_t class = nw_resolver_config_get_class(config);
-                if (class != nw_resolver_class_default_direct &&
-                    (!allows_failover || !q->IsFailover) &&
-                    (best_class == nw_resolver_class_default_direct || class < best_class))
-                {
-                    best_class = class;
-                    best_config = config;
-                    best_config_allows_failover = allows_failover;
-                }
-                return true;
-            });
-            if (best_config != NULL)
-            {
-                nw_resolver_config_get_identifier(best_config, q->ResolverUUID);
-            }
-        }
-        if (!uuid_is_null(q->ResolverUUID))
-        {
-            Querier_RegisterPathResolver(q->ResolverUUID);
-        }
-    }
-#endif
-
-exit:
-    _nw_forget(&host);
-    _nw_forget(&parameters);
-    _nw_forget(&path);
-    _nw_forget(&evaluator);
-    q->BlockedByPolicy = isBlocked;
-}
diff --git a/mDNSPosix/Client.c b/mDNSPosix/Client.c
deleted file mode 100644
index e756c80..0000000
--- a/mDNSPosix/Client.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include <assert.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-
-#include "mDNSEmbeddedAPI.h" // Defines the interface to the mDNS core code
-#include "mDNSPosix.h"    // Defines the specific types needed to run mDNS on this platform
-#include "ExampleClientApp.h"
-
-// Globals
-mDNSexport mDNS mDNSStorage;       // mDNS core uses this to store its globals
-static mDNS_PlatformSupport PlatformStorage;  // Stores this platform's globals
-#define RR_CACHE_SIZE 500
-static CacheEntity gRRCache[RR_CACHE_SIZE];
-
-mDNSexport const char ProgramName[] = "mDNSClientPosix";
-
-static const char *gProgramName = ProgramName;
-
-static void BrowseCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-// A callback from the core mDNS code that indicates that we've received a
-// response to our query.  Note that this code runs on the main thread
-// (in fact, there is only one thread!), so we can safely printf the results.
-{
-    domainlabel name;
-    domainname type;
-    domainname domain;
-    char nameC  [MAX_DOMAIN_LABEL+1];           // Unescaped name: up to 63 bytes plus C-string terminating NULL.
-    char typeC  [MAX_ESCAPED_DOMAIN_NAME];
-    char domainC[MAX_ESCAPED_DOMAIN_NAME];
-    const char *state;
-
-    (void)m;        // Unused
-    (void)question; // Unused
-
-    assert(answer->rrtype == kDNSType_PTR);
-
-    DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain);
-
-    ConvertDomainLabelToCString_unescaped(&name, nameC);
-    ConvertDomainNameToCString(&type, typeC);
-    ConvertDomainNameToCString(&domain, domainC);
-
-    // If the TTL has hit 0, the service is no longer available.
-    if (!AddRecord) {
-        state = "Lost ";
-    } else {
-        state = "Found";
-    }
-    fprintf(stderr, "*** %s name = '%s', type = '%s', domain = '%s'\n", state, nameC, typeC, domainC);
-}
-
-static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool printExplanation)
-// Checks that serviceType is a reasonable service type
-// label and, if it isn't and printExplanation is true, prints
-// an explanation of why not.
-{
-    mDNSBool result;
-
-    result = mDNStrue;
-    if (result && strlen(serviceType) > 63) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Service type specified by -t is too long (must be 63 characters or less)\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    if (result && serviceType[0] == 0) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Service type specified by -t can't be empty\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    return result;
-}
-
-static const char kDefaultServiceType[] = "_afpovertcp._tcp";
-static const char kDefaultDomain[]      = "local.";
-
-static void PrintUsage()
-{
-    fprintf(stderr,
-            "Usage: %s [-v level] [-t type] [-d domain]\n",
-            gProgramName);
-    fprintf(stderr, "          -v verbose mode, level is a number from 0 to 2\n");
-    fprintf(stderr, "             0 = no debugging info (default)\n");
-    fprintf(stderr, "             1 = standard debugging info\n");
-    fprintf(stderr, "             2 = intense debugging info\n");
-    fprintf(stderr, "          -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
-    fprintf(stderr, "          -d uses 'domain' as the domain to browse (default is '%s')\n", kDefaultDomain);
-}
-
-static const char *gServiceType      = kDefaultServiceType;
-static const char *gServiceDomain    = kDefaultDomain;
-
-static void ParseArguments(int argc, char **argv)
-// Parses our command line arguments into the global variables
-// listed above.
-{
-    int ch;
-
-    // Set gProgramName to the last path component of argv[0]
-
-    gProgramName = strrchr(argv[0], '/');
-    if (gProgramName == NULL) {
-        gProgramName = argv[0];
-    } else {
-        gProgramName += 1;
-    }
-
-    // Parse command line options using getopt.
-
-    do {
-        ch = getopt(argc, argv, "v:t:d:");
-        if (ch != -1) {
-            switch (ch) {
-            case 'v':
-                gMDNSPlatformPosixVerboseLevel = atoi(optarg);
-                if (gMDNSPlatformPosixVerboseLevel < 0 || gMDNSPlatformPosixVerboseLevel > 2) {
-                    fprintf(stderr,
-                            "%s: Verbose mode must be in the range 0..2\n",
-                            gProgramName);
-                    exit(1);
-                }
-                break;
-            case 't':
-                gServiceType = optarg;
-                if ( !CheckThatServiceTypeIsUsable(gServiceType, mDNStrue) ) {
-                    exit(1);
-                }
-                break;
-            case 'd':
-                gServiceDomain = optarg;
-                break;
-            case '?':
-            default:
-                PrintUsage();
-                exit(1);
-                break;
-            }
-        }
-    } while (ch != -1);
-
-    // Check for any left over command line arguments.
-
-    if (optind != argc) {
-        fprintf(stderr, "%s: Unexpected argument '%s'\n", gProgramName, argv[optind]);
-        exit(1);
-    }
-}
-
-int main(int argc, char **argv)
-// The program's main entry point.  The program does a trivial
-// mDNS query, looking for all AFP servers in the local domain.
-{
-    int result;
-    mStatus status;
-    DNSQuestion question;
-    domainname type;
-    domainname domain;
-
-    // Parse our command line arguments.  This won't come back if there's an error.
-    ParseArguments(argc, argv);
-
-    // Initialise the mDNS core.
-    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                       gRRCache, RR_CACHE_SIZE,
-                       mDNS_Init_DontAdvertiseLocalAddresses,
-                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
-    if (status == mStatus_NoError) {
-
-        // Construct and start the query.
-
-        MakeDomainNameFromDNSNameString(&type, gServiceType);
-        MakeDomainNameFromDNSNameString(&domain, gServiceDomain);
-
-        status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse, BrowseCallback, NULL);
-
-        // Run the platform main event loop until the user types ^C.
-        // The BrowseCallback routine is responsible for printing
-        // any results that we find.
-
-        if (status == mStatus_NoError) {
-            fprintf(stderr, "Hit ^C when you're bored waiting for responses.\n");
-            ExampleClientEventLoop(&mDNSStorage);
-            mDNS_StopQuery(&mDNSStorage, &question);
-            mDNS_Close(&mDNSStorage);
-        }
-    }
-
-    if (status == mStatus_NoError) {
-        result = 0;
-    } else {
-        result = 2;
-    }
-    if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
-        fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result);
-    }
-
-    return 0;
-}
diff --git a/mDNSPosix/ExampleClientApp.c b/mDNSPosix/ExampleClientApp.c
deleted file mode 100644
index 503751d..0000000
--- a/mDNSPosix/ExampleClientApp.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include <stdio.h>          // For printf()
-#include <stdlib.h>         // For exit() etc.
-#include <string.h>         // For strlen() etc.
-#include <unistd.h>         // For select()
-#include <errno.h>          // For errno, EINTR
-#include <netinet/in.h>     // For INADDR_NONE
-#include <arpa/inet.h>      // For inet_addr()
-#include <netdb.h>          // For gethostbyname()
-#include <signal.h>         // For SIGINT, etc.
-
-#include "mDNSEmbeddedAPI.h"  // Defines the interface to the client layer above
-#include "mDNSPosix.h"      // Defines the specific types needed to run mDNS on this platform
-
-//*******************************************************************************************
-// Main
-
-static volatile mDNSBool StopNow;
-
-mDNSlocal void HandleSIG(int signal)
-{
-    (void)signal;   // Unused
-    debugf("%s","");
-    debugf("HandleSIG");
-    StopNow = mDNStrue;
-}
-
-mDNSexport void ExampleClientEventLoop(mDNS *const m)
-{
-    signal(SIGINT, HandleSIG);  // SIGINT is what you get for a Ctrl-C
-    signal(SIGTERM, HandleSIG);
-
-    while (!StopNow)
-    {
-        int nfds = 0;
-        fd_set readfds;
-        fd_set writefds;
-        struct timeval timeout;
-        int result;
-
-        // 1. Set up the fd_set as usual here.
-        // This example client has no file descriptors of its own,
-        // but a real application would call FD_SET to add them to the set here
-        FD_ZERO(&readfds);
-        FD_ZERO(&writefds);
-
-        // 2. Set up the timeout.
-        // This example client has no other work it needs to be doing,
-        // so we set an effectively infinite timeout
-        timeout.tv_sec = FutureTime;
-        timeout.tv_usec = 0;
-
-        // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout
-        mDNSPosixGetFDSet(m, &nfds, &readfds, &writefds, &timeout);
-
-        // 4. Call select as normal
-        verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec);
-        result = select(nfds, &readfds, &writefds, NULL, &timeout);
-
-        if (result < 0)
-        {
-            verbosedebugf("select() returned %d errno %d", result, errno);
-            if (errno != EINTR) StopNow = mDNStrue;
-        }
-        else
-        {
-            // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work
-            mDNSPosixProcessFDSet(m, &readfds, &writefds);
-
-            // 6. This example client has no other work it needs to be doing,
-            // but a real client would do its work here
-            // ... (do work) ...
-        }
-    }
-
-    debugf("Exiting");
-}
diff --git a/mDNSPosix/ExampleClientApp.h b/mDNSPosix/ExampleClientApp.h
deleted file mode 100644
index 53f7f17..0000000
--- a/mDNSPosix/ExampleClientApp.h
+++ /dev/null
@@ -1,18 +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.
- */
-
-extern void ExampleClientEventLoop(mDNS *const m);
diff --git a/mDNSPosix/Identify.c b/mDNSPosix/Identify.c
deleted file mode 100644
index 24c08bc..0000000
--- a/mDNSPosix/Identify.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2018 Apple 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.
- *
- */
-
-//*************************************************************************************************************
-// Incorporate mDNS.c functionality
-
-// We want to use the functionality provided by "mDNS.c",
-// except we'll sneak a peek at the packets before forwarding them to the normal mDNSCoreReceive() routine
-#define mDNSCoreReceive __MDNS__mDNSCoreReceive
-#include "mDNS.c"
-#undef mDNSCoreReceive
-
-//*************************************************************************************************************
-// Headers
-
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>       // For n_long, required by <netinet/ip.h> below
-#include <netinet/ip.h>             // For IPTOS_LOWDELAY etc.
-#include <arpa/inet.h>
-#include <signal.h>
-
-#include "mDNSEmbeddedAPI.h" // Defines the interface to the mDNS core code
-#include "mDNSPosix.h"    // Defines the specific types needed to run mDNS on this platform
-#include "ExampleClientApp.h"
-
-//*************************************************************************************************************
-// Globals
-
-mDNS mDNSStorage;       // mDNS core uses this to store its globals
-static mDNS_PlatformSupport PlatformStorage;  // Stores this platform's globals
-#define RR_CACHE_SIZE 500
-static CacheEntity gRRCache[RR_CACHE_SIZE];
-mDNSexport const char ProgramName[] = "mDNSIdentify";
-
-static volatile int StopNow;    // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C
-static volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO;
-static char hostname[MAX_ESCAPED_DOMAIN_NAME], hardware[256], software[256];
-static mDNSAddr lastsrc, hostaddr, target;
-static mDNSOpaque16 lastid, id;
-
-//*************************************************************************************************************
-// Utilities
-
-// Special version of printf that knows how to print IP addresses, DNS-format name strings, etc.
-mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-mDNSlocal mDNSu32 mprintf(const char *format, ...)
-{
-    mDNSu32 length;
-    unsigned char buffer[512];
-    va_list ptr;
-    va_start(ptr,format);
-    length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr);
-    va_end(ptr);
-    printf("%s", buffer);
-    return(length);
-}
-
-//*************************************************************************************************************
-// Main code
-
-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)
-{
-    (void)dstaddr; // Unused
-    // Snag copy of header ID, then call through
-    lastid = msg->h.id;
-    lastsrc = *srcaddr;
-
-    // We *want* to allow off-net unicast responses here.
-    // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet
-    __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID);
-}
-
-mDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    (void)m;        // Unused
-    (void)question; // Unused
-    (void)AddRecord; // Unused
-    if (!id.NotAnInteger) id = lastid;
-    if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME)
-    {
-        ConvertDomainNameToCString(&answer->rdata->u.name, hostname);
-        StopNow = 1;
-        mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
-    }
-}
-
-mDNSlocal void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    (void)m;        // Unused
-    (void)question; // Unused
-    (void)AddRecord; // Unused
-    if (answer->rrtype == kDNSType_A)
-    {
-        if (!id.NotAnInteger) id = lastid;
-        NumAnswers++;
-        NumAddr++;
-        mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4);
-        hostaddr.type = mDNSAddrType_IPv4;  // Prefer v4 target to v6 target, for now
-        hostaddr.ip.v4 = answer->rdata->u.ipv4;
-    }
-    else if (answer->rrtype == kDNSType_AAAA)
-    {
-        if (!id.NotAnInteger) id = lastid;
-        NumAnswers++;
-        NumAAAA++;
-        mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6);
-        if (!hostaddr.type) // Prefer v4 target to v6 target, for now
-        {
-            hostaddr.type = mDNSAddrType_IPv6;
-            hostaddr.ip.v6 = answer->rdata->u.ipv6;
-        }
-    }
-    else if (answer->rrtype == kDNSType_HINFO)
-    {
-        mDNSu8 *p = answer->rdata->u.data;
-        strncpy(hardware, (char*)(p+1), p[0]);
-        hardware[p[0]] = 0;
-        p += 1 + p[0];
-        strncpy(software, (char*)(p+1), p[0]);
-        software[p[0]] = 0;
-        NumAnswers++;
-        NumHINFO++;
-    }
-
-    // If we've got everything we're looking for, don't need to wait any more
-    if (/*NumHINFO && */ (NumAddr || NumAAAA)) StopNow = 1;
-}
-
-mDNSlocal void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    (void)m;        // Unused
-    (void)question; // Unused
-    (void)AddRecord; // Unused
-    // Right now the mDNSCore targeted-query code is incomplete --
-    // it issues targeted queries, but accepts answers from anywhere
-    // For now, we'll just filter responses here so we don't get confused by responses from someone else
-    if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target))
-    {
-        NumAnswers++;
-        mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
-    }
-}
-
-mDNSlocal void WaitForAnswer(mDNS *const m, int seconds)
-{
-    struct timeval end;
-    gettimeofday(&end, NULL);
-    end.tv_sec += seconds;
-    StopNow = 0;
-    NumAnswers = 0;
-    while (!StopNow)
-    {
-        int nfds = 0;
-        fd_set readfds, writefds;
-        struct timeval now, remain = end;
-        int result;
-
-        FD_ZERO(&readfds);
-        FD_ZERO(&writefds);
-        gettimeofday(&now, NULL);
-        if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; }
-        if (remain.tv_sec < now.tv_sec)
-        {
-            if (!NumAnswers) printf("No response after %d seconds\n", seconds);
-            return;
-        }
-        remain.tv_usec -= now.tv_usec;
-        remain.tv_sec  -= now.tv_sec;
-        mDNSPosixGetFDSet(m, &nfds, &readfds, &writefds, &remain);
-        result = select(nfds, &readfds, &writefds, NULL, &remain);
-        if (result >= 0) mDNSPosixProcessFDSet(m, &readfds, &writefds);
-        else if (errno != EINTR) StopNow = 2;
-    }
-}
-
-mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
-{
-    lastsrc = zeroAddr;
-    if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname);
-    q->InterfaceID      = mDNSInterface_Any;
-    q->flags            = 0;
-    q->Target           = target ? *target : zeroAddr;
-    q->TargetPort       = MulticastDNSPort;
-    q->TargetQID        = zeroID;
-    q->qtype            = qtype;
-    q->qclass           = kDNSClass_IN;
-    q->LongLived        = mDNSfalse;
-    q->ExpectUnique     = mDNSfalse;    // Don't want to stop after the first response packet
-    q->ForceMCast       = mDNStrue;     // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa.
-    q->ReturnIntermed   = mDNStrue;
-    q->SuppressUnusable = mDNSfalse;
-    q->AppendSearchDomains = 0;
-    q->TimeoutQuestion  = 0;
-    q->ValidationRequired = 0;
-    q->ValidatingResponse = 0;
-    q->WakeOnResolve    = 0;
-    q->UseBackgroundTraffic = mDNSfalse;
-    q->ProxyQuestion    = 0;
-    q->pid              = mDNSPlatformGetPID();
-    q->QuestionCallback = callback;
-    q->QuestionContext  = NULL;
-
-    //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype));
-    return(mDNS_StartQuery(&mDNSStorage, q));
-}
-
-mDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
-{
-    mStatus status = StartQuery(q, qname, qtype, target, callback);
-    if (status != mStatus_NoError)
-        StopNow = 2;
-    else
-    {
-        WaitForAnswer(&mDNSStorage, 4);
-        mDNS_StopQuery(&mDNSStorage, q);
-    }
-}
-
-mDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
-{
-    DoOneQuery(q, qname, qtype, target, callback);
-    if (StopNow == 0 && NumAnswers == 0 && target && target->type)
-    {
-        mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype));
-        DoOneQuery(q, qname, qtype, NULL, callback);
-    }
-    if (StopNow == 0 && NumAnswers == 0)
-        mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype));
-    return(StopNow);
-}
-
-mDNSlocal void HandleSIG(int signal)
-{
-    (void)signal;   // Unused
-    debugf("%s","");
-    debugf("HandleSIG");
-    StopNow = 2;
-}
-
-mDNSexport int main(int argc, char **argv)
-{
-    const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
-    int this_arg = 1;
-    mStatus status;
-    struct in_addr s4;
-#if HAVE_IPV6
-    struct in6_addr s6;
-#endif
-    char buffer[256];
-    DNSQuestion q;
-
-    if (argc < 2) goto usage;
-
-    // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog
-    mDNS_DebugMode = mDNStrue;
-
-    // Initialise the mDNS core.
-    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                       gRRCache, RR_CACHE_SIZE,
-                       mDNS_Init_DontAdvertiseLocalAddresses,
-                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
-    if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }
-
-    signal(SIGINT, HandleSIG);  // SIGINT is what you get for a Ctrl-C
-    signal(SIGTERM, HandleSIG);
-
-    while (this_arg < argc)
-    {
-        char *arg = argv[this_arg++];
-        if (this_arg > 2) printf("\n");
-
-        lastid = id = zeroID;
-        hostaddr = target = zeroAddr;
-        hostname[0] = hardware[0] = software[0] = 0;
-        NumAddr = NumAAAA = NumHINFO = 0;
-
-        if (inet_pton(AF_INET, arg, &s4) == 1)
-        {
-            mDNSu8 *p = (mDNSu8 *)&s4;
-            // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-            mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]);
-            printf("%s\n", buffer);
-            target.type = mDNSAddrType_IPv4;
-            target.ip.v4.NotAnInteger = s4.s_addr;
-            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
-            if (StopNow == 2) break;
-        }
-#if HAVE_IPV6
-        else if (inet_pton(AF_INET6, arg, &s6) == 1)
-        {
-            int i;
-            mDNSu8 *p = (mDNSu8 *)&s6;
-            for (i = 0; i < 16; i++)
-            {
-                static const char hexValues[] = "0123456789ABCDEF";
-                buffer[i * 4    ] = hexValues[p[15-i] & 0x0F];
-                buffer[i * 4 + 1] = '.';
-                buffer[i * 4 + 2] = hexValues[p[15-i] >> 4];
-                buffer[i * 4 + 3] = '.';
-            }
-            mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
-            target.type = mDNSAddrType_IPv6;
-            mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6));
-            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
-            if (StopNow == 2) break;
-        }
-#endif
-        else
-        {
-            if (strlen(arg) >= sizeof(hostname))
-            {
-                fprintf(stderr, "hostname must be < %d characters\n", (int)sizeof(hostname));
-                goto usage;
-            }
-            strcpy(hostname, arg);
-        }
-
-        // Now we have the host name; get its A, AAAA, and HINFO
-        if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback);
-        if (StopNow == 2) break;
-
-        if (hardware[0] || software[0])
-        {
-            printf("HINFO Hardware: %s\n", hardware);
-            printf("HINFO Software: %s\n", software);
-        }
-        else if (NumAnswers) printf("%s has no HINFO record\n", hostname);
-        else printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n");
-
-        if (NumAnswers)
-        {
-            // Because of the way we use lastsrc in ServicesCallback, we need to clear the cache to make sure we're getting fresh answers
-            mDNS *const m = &mDNSStorage;
-            mDNSu32 slot;
-            CacheGroup *cg;
-            CacheRecord *rr;
-            FORALL_CACHERECORDS(slot, cg, rr)
-            {
-                mDNS_PurgeCacheResourceRecord(m, rr);
-            }
-            if (target.type == 0) target = hostaddr;        // Make sure the services query is targeted
-            DoQuery(&q, "_services._dns-sd._udp.local.", kDNSType_PTR, &target, ServicesCallback);
-            if (StopNow == 2) break;
-        }
-    }
-
-    mDNS_Close(&mDNSStorage);
-    return(0);
-
-usage:
-    fprintf(stderr, "Usage: %s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname);
-    return(-1);
-}
diff --git a/mDNSPosix/NetMonitor.c b/mDNSPosix/NetMonitor.c
deleted file mode 100644
index 12fdda0..0000000
--- a/mDNSPosix/NetMonitor.c
+++ /dev/null
@@ -1,1068 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- *
- */
-
-//*************************************************************************************************************
-// Incorporate mDNS.c functionality
-
-// We want to use much of the functionality provided by "mDNS.c",
-// except we'll steal the packets that would be sent to normal mDNSCoreReceive() routine
-#define mDNSCoreReceive __NOT__mDNSCoreReceive__NOT__
-#define MDNS_NO_STRICT 1
-#include "../mDNSCore/mDNS.c"
-#undef mDNSCoreReceive
-
-//*************************************************************************************************************
-// Headers
-
-#include <stdio.h>          // For printf()
-#include <stdlib.h>         // For malloc()
-#include <string.h>         // For strrchr(), strcmp()
-#include <time.h>           // For "struct tm" etc.
-#include <signal.h>         // For SIGINT, SIGTERM
-#if defined(WIN32)
-// Both mDNS.c and mDNSWin32.h declare UDPSocket_struct type resulting in a compile-time error, so
-// trick the compiler when including mDNSWin32.h
-#   define UDPSocket_struct _UDPSocket_struct
-#   include <mDNSEmbeddedAPI.h>
-#   include <mDNSWin32.h>
-#   include <PosixCompat.h>
-#   include <Poll.h>
-#   define IFNAMSIZ 256
-static HANDLE gStopEvent = INVALID_HANDLE_VALUE;
-static mDNSBool gRunning;
-static void CALLBACK StopNotification( HANDLE event, void *context ) { gRunning = mDNSfalse; }
-static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) { SetEvent( gStopEvent ); return TRUE; }
-void setlinebuf( FILE * fp ) {}
-#else
-#   include <netdb.h>           // For gethostbyname()
-#   include <sys/socket.h>      // For AF_INET, AF_INET6, etc.
-#   include <net/if.h>          // For IF_NAMESIZE
-#   include <netinet/in.h>      // For INADDR_NONE
-#   include <arpa/inet.h>       // For inet_addr()
-#   define UDPSocket_struct _UDPSocket_struct
-#   include "mDNSPosix.h"      // Defines the specific types needed to run mDNS on this platform
-#endif
-#include "ExampleClientApp.h"
-
-//*************************************************************************************************************
-// Types and structures
-
-enum
-{
-    // Primitive operations
-    OP_probe        = 0,
-    OP_goodbye      = 1,
-
-    // These are meta-categories;
-    // Query and Answer operations are actually subdivided into two classes:
-    // Browse  query/answer and
-    // Resolve query/answer
-    OP_query        = 2,
-    OP_answer       = 3,
-
-    // The "Browse" variants of query/answer
-    OP_browsegroup  = 2,
-    OP_browseq      = 2,
-    OP_browsea      = 3,
-
-    // The "Resolve" variants of query/answer
-    OP_resolvegroup = 4,
-    OP_resolveq     = 4,
-    OP_resolvea     = 5,
-
-    OP_NumTypes = 6
-};
-
-typedef struct ActivityStat_struct ActivityStat;
-struct ActivityStat_struct
-{
-    ActivityStat *next;
-    domainname srvtype;
-    int printed;
-    int totalops;
-    int stat[OP_NumTypes];
-};
-
-typedef struct FilterList_struct FilterList;
-struct FilterList_struct
-{
-    FilterList *next;
-    mDNSAddr FilterAddr;
-};
-
-//*************************************************************************************************************
-// Constants
-
-#define kReportTopServices 15
-#define kReportTopHosts    15
-
-//*************************************************************************************************************
-// Globals
-
-mDNS mDNSStorage;                       // mDNS core uses this to store its globals
-static mDNS_PlatformSupport PlatformStorage;    // Stores this platform's globals
-mDNSexport const char ProgramName[] = "mDNSNetMonitor";
-
-struct timeval tv_start, tv_end, tv_interval;
-static int FilterInterface = 0;
-static FilterList *Filters;
-#define ExactlyOneFilter (Filters && !Filters->next)
-static mDNSBool AddressType = mDNSAddrType_IPv4;
-
-static int NumPktQ, NumPktL, NumPktR, NumPktB;  // Query/Legacy/Response/Bad
-static int NumProbes, NumGoodbyes, NumQuestions, NumLegacy, NumAnswers, NumAdditionals;
-
-static ActivityStat *stats;
-
-#define OPBanner "Total Ops   Probe   Goodbye  BrowseQ  BrowseA ResolveQ ResolveA"
-
-mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
-
-//*************************************************************************************************************
-// Utilities
-
-// Special version of printf that knows how to print IP addresses, DNS-format name strings, etc.
-mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-mDNSlocal mDNSu32 mprintf(const char *format, ...)
-{
-    mDNSu32 length;
-    unsigned char buffer[512];
-    va_list ptr;
-    va_start(ptr,format);
-    length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr);
-    va_end(ptr);
-    printf("%s", buffer);
-    return(length);
-}
-
-//*************************************************************************************************************
-// Host Address List
-//
-// Would benefit from a hash
-
-typedef enum
-{
-    HostPkt_Q        = 0,       // Query
-    HostPkt_L        = 1,       // Legacy Query
-    HostPkt_R        = 2,       // Response
-    HostPkt_B        = 3,       // Bad
-    HostPkt_NumTypes = 4
-} HostPkt_Type;
-
-typedef struct
-{
-    mDNSAddr addr;
-    unsigned long pkts[HostPkt_NumTypes];
-    unsigned long totalops;
-    unsigned long stat[OP_NumTypes];
-    domainname hostname;
-    domainname revname;
-    UTF8str255 HIHardware;
-    UTF8str255 HISoftware;
-    mDNSu32 NumQueries;
-    mDNSs32 LastQuery;
-} HostEntry;
-
-#define HostEntryTotalPackets(H) ((H)->pkts[HostPkt_Q] + (H)->pkts[HostPkt_L] + (H)->pkts[HostPkt_R] + (H)->pkts[HostPkt_B])
-
-typedef struct
-{
-    long num;
-    long max;
-    HostEntry   *hosts;
-} HostList;
-
-static HostList IPv4HostList = { 0, 0, 0 };
-static HostList IPv6HostList = { 0, 0, 0 };
-
-mDNSlocal HostEntry *FindHost(const mDNSAddr *addr, HostList *list)
-{
-    long i;
-
-    for (i = 0; i < list->num; i++)
-    {
-        HostEntry *entry = list->hosts + i;
-        if (mDNSSameAddress(addr, &entry->addr))
-            return entry;
-    }
-
-    return NULL;
-}
-
-mDNSlocal HostEntry *AddHost(const mDNSAddr *addr, HostList *list)
-{
-    int i;
-    HostEntry *entry;
-    if (list->num >= list->max)
-    {
-        long newMax = list->max + 64;
-        HostEntry *newHosts = realloc(list->hosts, newMax * sizeof(HostEntry));
-        if (newHosts == NULL)
-            return NULL;
-        list->max = newMax;
-        list->hosts = newHosts;
-    }
-
-    entry = list->hosts + list->num++;
-
-    entry->addr = *addr;
-    for (i=0; i<HostPkt_NumTypes; i++) entry->pkts[i] = 0;
-    entry->totalops = 0;
-    for (i=0; i<OP_NumTypes;      i++) entry->stat[i] = 0;
-    entry->hostname.c[0] = 0;
-    entry->revname.c[0] = 0;
-    entry->HIHardware.c[0] = 0;
-    entry->HISoftware.c[0] = 0;
-    entry->NumQueries = 0;
-
-    if (entry->addr.type == mDNSAddrType_IPv4)
-    {
-        mDNSv4Addr ip = entry->addr.ip.v4;
-        char buffer[32];
-        // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-        mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", ip.b[3], ip.b[2], ip.b[1], ip.b[0]);
-        MakeDomainNameFromDNSNameString(&entry->revname, buffer);
-    }
-
-    return(entry);
-}
-
-mDNSlocal HostEntry *GotPacketFromHost(const mDNSAddr *addr, HostPkt_Type t, mDNSOpaque16 id)
-{
-    if (ExactlyOneFilter) return(NULL);
-    else
-    {
-        HostList *list = (addr->type == mDNSAddrType_IPv4) ? &IPv4HostList : &IPv6HostList;
-        HostEntry *entry = FindHost(addr, list);
-        if (!entry) entry = AddHost(addr, list);
-        if (!entry) return(NULL);
-        // Don't count our own interrogation packets
-        if (id.NotAnInteger != 0xFFFF) entry->pkts[t]++;
-        return(entry);
-    }
-}
-
-mDNSlocal void RecordHostInfo(HostEntry *entry, const ResourceRecord *const pktrr)
-{
-    if (!entry->hostname.c[0])
-    {
-        if (pktrr->rrtype == kDNSType_A || pktrr->rrtype == kDNSType_AAAA)
-        {
-            // Should really check that the rdata in the address record matches the source address of this packet
-            entry->NumQueries = 0;
-            AssignDomainName(&entry->hostname, pktrr->name);
-        }
-
-        if (pktrr->rrtype == kDNSType_PTR)
-            if (SameDomainName(&entry->revname, pktrr->name))
-            {
-                entry->NumQueries = 0;
-                AssignDomainName(&entry->hostname, &pktrr->rdata->u.name);
-            }
-    }
-    else if (pktrr->rrtype == kDNSType_HINFO)
-    {
-        RDataBody *rd = &pktrr->rdata->u;
-        mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
-        mDNSu8 *hw = rd->txt.c;
-        mDNSu8 *sw = hw + 1 + (mDNSu32)hw[0];
-        if (sw + 1 + sw[0] <= rdend)
-        {
-            AssignDomainName(&entry->hostname, pktrr->name);
-            mDNSPlatformMemCopy(entry->HIHardware.c, hw, 1 + (mDNSu32)hw[0]);
-            mDNSPlatformMemCopy(entry->HISoftware.c, sw, 1 + (mDNSu32)sw[0]);
-        }
-    }
-}
-
-mDNSlocal void SendUnicastQuery(mDNS *const m, HostEntry *entry, domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID)
-{
-    const mDNSOpaque16 id = { { 0xFF, 0xFF } };
-    DNSMessage query;
-    mDNSu8       *qptr        = query.data;
-    const mDNSu8 *const limit = query.data + sizeof(query.data);
-    const mDNSAddr *target    = &entry->addr;
-    InitializeDNSMessage(&query.h, id, QueryFlags);
-    qptr = putQuestion(&query, qptr, limit, name, rrtype, kDNSClass_IN);
-    entry->LastQuery = m->timenow;
-    entry->NumQueries++;
-
-    // Note: When there are multiple mDNSResponder agents running on a single machine
-    // (e.g. Apple mDNSResponder plus a SliMP3 server with embedded mDNSResponder)
-    // it is possible that unicast queries may not go to the primary system responder.
-    // We try the first query using unicast, but if that doesn't work we try again via multicast.
-    if (entry->NumQueries > 2)
-    {
-        target = &AllDNSLinkGroup_v4;
-    }
-    else
-    {
-        //mprintf("%#a Q\n", target);
-        InterfaceID = mDNSInterface_Any;    // Send query from our unicast reply socket
-    }
-
-    mDNSSendDNSMessage(m, &query, qptr, InterfaceID, mDNSNULL, mDNSNULL, target, MulticastDNSPort, mDNSNULL, mDNSfalse);
-}
-
-mDNSlocal void AnalyseHost(mDNS *const m, HostEntry *entry, const mDNSInterfaceID InterfaceID)
-{
-    // If we've done four queries without answer, give up
-    if (entry->NumQueries >= 4) return;
-
-    // If we've done a query in the last second, give the host a chance to reply before trying again
-    if (entry->NumQueries && m->timenow - entry->LastQuery < mDNSPlatformOneSecond) return;
-
-    // If we don't know the host name, try to find that first
-    if (!entry->hostname.c[0])
-    {
-        if (entry->revname.c[0])
-        {
-            SendUnicastQuery(m, entry, &entry->revname, kDNSType_PTR, InterfaceID);
-            //mprintf("%##s PTR %d\n", entry->revname.c, entry->NumQueries);
-        }
-    }
-    // If we have the host name but no HINFO, now ask for that
-    else if (!entry->HIHardware.c[0])
-    {
-        SendUnicastQuery(m, entry, &entry->hostname, kDNSType_HINFO, InterfaceID);
-        //mprintf("%##s HINFO %d\n", entry->hostname.c, entry->NumQueries);
-    }
-}
-
-mDNSlocal int CompareHosts(const void *p1, const void *p2)
-{
-    return (int)(HostEntryTotalPackets((HostEntry *)p2) - HostEntryTotalPackets((HostEntry *)p1));
-}
-
-mDNSlocal void ShowSortedHostList(HostList *list, int max)
-{
-    HostEntry *e, *end = &list->hosts[(max < list->num) ? max : list->num];
-    qsort(list->hosts, list->num, sizeof(HostEntry), CompareHosts);
-    if (list->num) mprintf("\n%-25s%s%s\n", "Source Address", OPBanner, "    Pkts    Query   LegacyQ Response");
-    for (e = &list->hosts[0]; e < end; e++)
-    {
-        int len = mprintf("%#-25a", &e->addr);
-        if (len > 25) mprintf("\n%25s", "");
-        mprintf("%8lu %8lu %8lu %8lu %8lu %8lu %8lu", e->totalops,
-                e->stat[OP_probe], e->stat[OP_goodbye],
-                e->stat[OP_browseq], e->stat[OP_browsea],
-                e->stat[OP_resolveq], e->stat[OP_resolvea]);
-        mprintf(" %8lu %8lu %8lu %8lu",
-                HostEntryTotalPackets(e), e->pkts[HostPkt_Q], e->pkts[HostPkt_L], e->pkts[HostPkt_R]);
-        if (e->pkts[HostPkt_B]) mprintf("Bad: %8lu", e->pkts[HostPkt_B]);
-        mprintf("\n");
-        if (!e->HISoftware.c[0] && e->NumQueries > 2)
-            mDNSPlatformMemCopy(&e->HISoftware, "\x27*** Unknown (Jaguar, Windows, etc.) ***", 0x28);
-        if (e->hostname.c[0] || e->HIHardware.c[0] || e->HISoftware.c[0])
-            mprintf("%##-45s %#-14s %#s\n", e->hostname.c, e->HIHardware.c, e->HISoftware.c);
-    }
-}
-
-//*************************************************************************************************************
-// Receive and process packets
-
-mDNSlocal mDNSBool ExtractServiceType(const domainname *const fqdn, domainname *const srvtype)
-{
-    int i, len;
-    const mDNSu8 *src = fqdn->c;
-    mDNSu8 *dst = srvtype->c;
-
-    len = *src;
-    if (len == 0 || len >= 0x40) return(mDNSfalse);
-    if (src[1] != '_') src += 1 + len;
-
-    len = *src;
-    if (len == 0 || len >= 0x40 || src[1] != '_') return(mDNSfalse);
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    len = *src;
-    if (len == 0 || len >= 0x40 || src[1] != '_') return(mDNSfalse);
-    for (i=0; i<=len; i++) *dst++ = *src++;
-
-    *dst++ = 0;     // Put the null root label on the end of the service type
-
-    return(mDNStrue);
-}
-
-mDNSlocal void recordstat(HostEntry *entry, const domainname *fqdn, int op, mDNSu16 rrtype)
-{
-    ActivityStat **s = &stats;
-    domainname srvtype;
-
-    if (op != OP_probe)
-    {
-        if (rrtype == kDNSType_SRV || rrtype == kDNSType_TXT) op = op - OP_browsegroup + OP_resolvegroup;
-        else if (rrtype != kDNSType_PTR) return;
-    }
-
-    if (!ExtractServiceType(fqdn, &srvtype)) return;
-
-    while (*s && !SameDomainName(&(*s)->srvtype, &srvtype)) s = &(*s)->next;
-    if (!*s)
-    {
-        int i;
-        *s = malloc(sizeof(ActivityStat));
-        if (!*s) exit(-1);
-        (*s)->next     = NULL;
-        (*s)->srvtype  = srvtype;
-        (*s)->printed  = 0;
-        (*s)->totalops = 0;
-        for (i=0; i<OP_NumTypes; i++) (*s)->stat[i] = 0;
-    }
-
-    (*s)->totalops++;
-    (*s)->stat[op]++;
-    if (entry)
-    {
-        entry->totalops++;
-        entry->stat[op]++;
-    }
-}
-
-mDNSlocal void printstats(int max)
-{
-    int i;
-    if (!stats) return;
-    for (i=0; i<max; i++)
-    {
-        int max_val = 0;
-        ActivityStat *s, *m = NULL;
-        for (s = stats; s; s=s->next)
-            if (!s->printed && max_val < s->totalops)
-            { m = s; max_val = s->totalops; }
-        if (!m) return;
-        m->printed = mDNStrue;
-        if (i==0) mprintf("%-25s%s\n", "Service Type", OPBanner);
-        mprintf("%##-25s%8d %8d %8d %8d %8d %8d %8d\n", m->srvtype.c, m->totalops, m->stat[OP_probe],
-                m->stat[OP_goodbye], m->stat[OP_browseq], m->stat[OP_browsea], m->stat[OP_resolveq], m->stat[OP_resolvea]);
-    }
-}
-
-mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query, const mDNSu8 *ptr, const mDNSu8 *const end,
-                                   DNSQuestion *q, LargeCacheRecord *pkt)
-{
-    int i;
-    for (i = 0; i < query->h.numAuthorities; i++)
-    {
-        const mDNSu8 *p2 = ptr;
-        ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, pkt);
-        if (!ptr) break;
-        if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && ResourceRecordAnswersQuestion(&pkt->r.resrec, q)) return(p2);
-    }
-    return(mDNSNULL);
-}
-
-mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
-{
-    const char *const ptype = (msg->h.flags.b[0] & kDNSFlag0_QR_Response)             ? "-R- " :
-                              (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) ? "-Q- " : "-LQ-";
-    const unsigned length = end - (mDNSu8 *)msg;
-    struct timeval tv;
-    struct tm tm;
-    const mDNSu32 index = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNSfalse);
-    char if_name[IFNAMSIZ];     // Older Linux distributions don't define IF_NAMESIZE
-    if_indextoname(index, if_name);
-    gettimeofday(&tv, NULL);
-    localtime_r((time_t*)&tv.tv_sec, &tm);
-    mprintf("\n%d:%02d:%02d.%06d Interface %d/%s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, index, if_name);
-
-    mprintf("%#-16a %s             Q:%3d  Ans:%3d  Auth:%3d  Add:%3d  Size:%5d bytes",
-            srcaddr, ptype, msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, length);
-
-    if (msg->h.id.NotAnInteger) mprintf("  ID:%u", mDNSVal16(msg->h.id));
-
-    if (!mDNSAddrIsDNSMulticast(dstaddr)) mprintf("   To: %#a", dstaddr);
-
-    if (msg->h.flags.b[0] & kDNSFlag0_TC)
-    {
-        if (msg->h.flags.b[0] & kDNSFlag0_QR_Response) mprintf("   Truncated");
-        else mprintf("   Truncated (KA list continues in next packet)");
-    }
-
-    mprintf("\n");
-
-    if (length < sizeof(DNSMessageHeader) + NormalMaxDNSMessageData - 192)
-        if (msg->h.flags.b[0] & kDNSFlag0_TC)
-            mprintf("%#-16a **** WARNING: Packet suspiciously small. Payload size (excluding IP and UDP headers)\n"
-                    "%#-16a **** should usually be closer to %d bytes before truncation becomes necessary.\n",
-                    srcaddr, srcaddr, sizeof(DNSMessageHeader) + NormalMaxDNSMessageData);
-}
-
-mDNSlocal void DisplaySizeCheck(const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, int num_opts)
-{
-    const unsigned length = end - (mDNSu8 *)msg;
-    const int num_records = msg->h.numAnswers + msg->h.numAuthorities + msg->h.numAdditionals - num_opts;
-
-    if (length > sizeof(DNSMessageHeader) + NormalMaxDNSMessageData)
-        if (num_records > 1)
-            mprintf("%#-16a **** ERROR: Oversized packet with %d records.\n"
-                    "%#-16a **** Many network devices cannot receive packets larger than %d bytes.\n"
-                    "%#-16a **** To minimize interoperability failures, oversized packets MUST be limited to a single resource record.\n",
-                    srcaddr, num_records, srcaddr, 40 + 8 + sizeof(DNSMessageHeader) + NormalMaxDNSMessageData, srcaddr);
-}
-
-mDNSlocal void DisplayResourceRecord(const mDNSAddr *const srcaddr, const char *const op, const ResourceRecord *const pktrr)
-{
-    static const char hexchars[16] = "0123456789ABCDEF";
-    #define MaxWidth 132
-    char buffer[MaxWidth+8];
-    char *p = buffer;
-
-    RDataBody *rd = &pktrr->rdata->u;
-    mDNSu8 *rdend = (mDNSu8 *)rd + pktrr->rdlength;
-    int n = mprintf("%#-16a %-5s %-5s%5lu %##s -> ", srcaddr, op, DNSTypeName(pktrr->rrtype), pktrr->rroriginalttl, pktrr->name->c);
-
-    if (pktrr->RecordType == kDNSRecordTypePacketNegative) { mprintf("**** ERROR: FAILED TO READ RDATA ****\n"); return; }
-
-    // The kDNSType_OPT case below just calls GetRRDisplayString_rdb
-    // Perhaps more (or all?) of the cases should do that?
-    switch(pktrr->rrtype)
-    {
-    case kDNSType_A:    mprintf("%.4a", &rd->ipv4); break;
-    case kDNSType_PTR:  mprintf("%##.*s", MaxWidth - n, rd->name.c); break;
-    case kDNSType_HINFO:    // same as kDNSType_TXT below
-    case kDNSType_TXT:  {
-        mDNSu8 *t = rd->txt.c;
-        while (t < rdend && t[0] && p < buffer+MaxWidth)
-        {
-            int i;
-            for (i=1; i<=t[0] && p < buffer+MaxWidth; i++)
-            {
-                if (t[i] == '\\') *p++ = '\\';
-                if (t[i] >= ' ') *p++ = t[i];
-                else
-                {
-                    *p++ = '\\';
-                    *p++ = '0';
-                    *p++ = 'x';
-                    *p++ = hexchars[t[i] >> 4];
-                    *p++ = hexchars[t[i] & 0xF];
-                }
-            }
-            t += 1+t[0];
-            if (t < rdend && t[0]) { *p++ = '\\'; *p++ = ' '; }
-        }
-        *p++ = 0;
-        mprintf("%.*s", MaxWidth - n, buffer);
-    } break;
-    case kDNSType_AAAA: mprintf("%.16a", &rd->ipv6); break;
-    case kDNSType_SRV:  mprintf("%##s:%d", rd->srv.target.c, mDNSVal16(rd->srv.port)); break;
-    case kDNSType_OPT:  {
-        char b[MaxMsg];
-        // Quick hack: we don't want the prefix that GetRRDisplayString_rdb puts at the start of its
-        // string, because it duplicates the name and rrtype we already display, so we compute the
-        // length of that prefix and strip that many bytes off the beginning of the string we display.
-        mDNSu32 striplen = mDNS_snprintf(b, MaxMsg-1, "%4d %##s %s ", pktrr->rdlength, pktrr->name->c, DNSTypeName(pktrr->rrtype));
-        GetRRDisplayString_rdb(pktrr, &pktrr->rdata->u, b);
-        mprintf("%.*s", MaxWidth - n, b + striplen);
-    } break;
-    case kDNSType_NSEC: {
-        char b[MaxMsg];
-        // See the quick hack above
-        mDNSu32 striplen = mDNS_snprintf(b, MaxMsg-1, "%4d %##s %s ", pktrr->rdlength, pktrr->name->c, DNSTypeName(pktrr->rrtype));
-        GetRRDisplayString_rdb(pktrr, &pktrr->rdata->u, b);
-        mprintf("%s", b+striplen);
-    } break;
-    default:            {
-        mDNSu8 *s = rd->data;
-        while (s < rdend && p < buffer+MaxWidth)
-        {
-            if (*s == '\\') *p++ = '\\';
-            if (*s >= ' ') *p++ = *s;
-            else
-            {
-                *p++ = '\\';
-                *p++ = '0';
-                *p++ = 'x';
-                *p++ = hexchars[*s >> 4];
-                *p++ = hexchars[*s & 0xF];
-            }
-            s++;
-        }
-        *p++ = 0;
-        mprintf("%.*s", MaxWidth - n, buffer);
-    } break;
-    }
-
-    mprintf("\n");
-}
-
-mDNSlocal void HexDump(const mDNSu8 *ptr, const mDNSu8 *const end)
-{
-    while (ptr < end)
-    {
-        int i;
-        for (i=0; i<16; i++)
-            if (&ptr[i] < end) mprintf("%02X ", ptr[i]);
-            else mprintf("   ");
-        for (i=0; i<16; i++)
-            if (&ptr[i] < end) mprintf("%c", ptr[i] <= ' ' || ptr[i] >= 126 ? '.' : ptr[i]);
-        ptr += 16;
-        mprintf("\n");
-    }
-}
-
-mDNSlocal void DisplayError(const mDNSAddr *srcaddr, const mDNSu8 *ptr, const mDNSu8 *const end, char *msg)
-{
-    mprintf("%#-16a **** ERROR: FAILED TO READ %s ****\n", srcaddr, msg);
-    HexDump(ptr, end);
-}
-
-mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-                            const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
-{
-    int i;
-    int num_opts = 0;
-    const mDNSu8 *ptr = msg->data;
-    const mDNSu8 *auth = LocateAuthorities(msg, end);
-    mDNSBool MQ = (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger);
-    HostEntry *entry = GotPacketFromHost(srcaddr, MQ ? HostPkt_Q : HostPkt_L, msg->h.id);
-    LargeCacheRecord pkt;
-
-    DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
-    if (msg->h.id.NotAnInteger != 0xFFFF)
-    {
-        if (MQ) NumPktQ++; else NumPktL++;
-    }
-
-    for (i=0; i<msg->h.numQuestions; i++)
-    {
-        DNSQuestion q;
-        mDNSu8 *p2 = (mDNSu8 *)getQuestion(msg, ptr, end, InterfaceID, &q);
-        mDNSu16 ucbit = q.qclass & kDNSQClass_UnicastResponse;
-        q.qclass &= ~kDNSQClass_UnicastResponse;
-        if (!p2) { DisplayError(srcaddr, ptr, end, "QUESTION"); return; }
-        ptr = p2;
-        p2 = (mDNSu8 *)FindUpdate(m, msg, auth, end, &q, &pkt);
-        if (p2)
-        {
-            NumProbes++;
-            DisplayResourceRecord(srcaddr, ucbit ? "(PU)" : "(PM)", &pkt.r.resrec);
-            recordstat(entry, &q.qname, OP_probe, q.qtype);
-            p2 = (mDNSu8 *)skipDomainName(msg, p2, end);
-            // Having displayed this update record, clear type and class so we don't display the same one again.
-            p2[0] = p2[1] = p2[2] = p2[3] = 0;
-        }
-        else
-        {
-            const char *ptype = ucbit ? "(QU)" : "(QM)";
-            if (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) NumQuestions++;
-            else { NumLegacy++; ptype = "(LQ)"; }
-            mprintf("%#-16a %-5s %-5s      %##s\n", srcaddr, ptype, DNSTypeName(q.qtype), q.qname.c);
-            if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, &q.qname, OP_query, q.qtype);
-        }
-    }
-
-    for (i=0; i<msg->h.numAnswers; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "KNOWN ANSWER"); return; }
-        DisplayResourceRecord(srcaddr, "(KA)", &pkt.r.resrec);
-        if (pkt.r.resrec.rrtype == kDNSType_OPT)
-            { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN ANSWER SECTION ****\n", srcaddr); }
-
-        // In the case of queries with long multi-packet KA lists, we count each subsequent KA packet
-        // the same as a single query, to more accurately reflect the burden on the network
-        // (A query with a six-packet KA list is *at least* six times the burden on the network as a single-packet query.)
-        if (msg->h.numQuestions == 0 && i == 0)
-            recordstat(entry, pkt.r.resrec.name, OP_query, pkt.r.resrec.rrtype);
-    }
-
-    for (i=0; i<msg->h.numAuthorities; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
-        // After we display an Update record with its matching question (above) we zero out its type and class
-        // If any remain that haven't been zero'd out, display them here
-        if (pkt.r.resrec.rrtype || pkt.r.resrec.rrclass) DisplayResourceRecord(srcaddr, "(AU)", &pkt.r.resrec);
-        if (pkt.r.resrec.rrtype == kDNSType_OPT)
-            { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN AUTHORITY SECTION ****\n", srcaddr); }
-    }
-
-    for (i=0; i<msg->h.numAdditionals; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; }
-        DisplayResourceRecord(srcaddr, pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : "(AD)", &pkt.r.resrec);
-        if (pkt.r.resrec.rrtype == kDNSType_OPT) num_opts++;
-    }
-
-    DisplaySizeCheck(msg, end, srcaddr, num_opts);
-
-    // We don't hexdump the DNSMessageHeader here because those six fields (id, flags, numQuestions, numAnswers, numAuthorities, numAdditionals)
-    // have already been swapped to host byte order and displayed, so including them in the hexdump is confusing
-    if (num_opts > 1) { mprintf("%#-16a **** ERROR: MULTIPLE OPT RECORDS ****\n", srcaddr); HexDump(msg->data, end); }
-
-    if (entry) AnalyseHost(m, entry, InterfaceID);
-}
-
-mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end,
-                               const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID)
-{
-    int i;
-    int num_opts = 0;
-    const mDNSu8 *ptr = msg->data;
-    HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id);
-    LargeCacheRecord pkt;
-
-    DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
-    if (msg->h.id.NotAnInteger != 0xFFFF) NumPktR++;
-
-    for (i=0; i<msg->h.numQuestions; i++)
-    {
-        DNSQuestion q;
-        const mDNSu8 *ep = ptr;
-        ptr = getQuestion(msg, ptr, end, InterfaceID, &q);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "QUESTION"); return; }
-        if (mDNSAddrIsDNSMulticast(dstaddr))
-            mprintf("%#-16a (?)   **** ERROR: SHOULD NOT HAVE Q IN mDNS RESPONSE **** %-5s %##s\n", srcaddr, DNSTypeName(q.qtype), q.qname.c);
-        else
-            mprintf("%#-16a (Q)   %-5s      %##s\n", srcaddr, DNSTypeName(q.qtype), q.qname.c);
-    }
-
-    for (i=0; i<msg->h.numAnswers; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "ANSWER"); return; }
-        if (pkt.r.resrec.rroriginalttl)
-        {
-            NumAnswers++;
-            DisplayResourceRecord(srcaddr, (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AN)" : "(AN+)", &pkt.r.resrec);
-            if (msg->h.id.NotAnInteger != 0xFFFF) recordstat(entry, pkt.r.resrec.name, OP_answer, pkt.r.resrec.rrtype);
-            if (entry) RecordHostInfo(entry, &pkt.r.resrec);
-        }
-        else
-        {
-            NumGoodbyes++;
-            DisplayResourceRecord(srcaddr, "(DE)", &pkt.r.resrec);
-            recordstat(entry, pkt.r.resrec.name, OP_goodbye, pkt.r.resrec.rrtype);
-        }
-        if (pkt.r.resrec.rrtype == kDNSType_OPT)
-            { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN ANSWER SECTION ****\n", srcaddr); }
-    }
-
-    for (i=0; i<msg->h.numAuthorities; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; }
-        DisplayResourceRecord(srcaddr, "(AU)", &pkt.r.resrec);
-        if (pkt.r.resrec.rrtype == kDNSType_OPT)
-            { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN AUTHORITY SECTION ****\n", srcaddr); }
-        else if (pkt.r.resrec.rrtype != kDNSType_NSEC3)
-            mprintf("%#-16a (?)  **** ERROR: SHOULD NOT HAVE AUTHORITY IN mDNS RESPONSE **** %-5s %##s\n",
-                srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name->c);
-    }
-
-    for (i=0; i<msg->h.numAdditionals; i++)
-    {
-        const mDNSu8 *ep = ptr;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt);
-        if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; }
-        NumAdditionals++;
-        if (pkt.r.resrec.rrtype == kDNSType_OPT) num_opts++;
-        DisplayResourceRecord(srcaddr,
-                              pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AD)" : "(AD+)",
-                              &pkt.r.resrec);
-        if (entry) RecordHostInfo(entry, &pkt.r.resrec);
-    }
-
-    DisplaySizeCheck(msg, end, srcaddr, num_opts);
-
-    // We don't hexdump the DNSMessageHeader here because those six fields (id, flags, numQuestions, numAnswers, numAuthorities, numAdditionals)
-    // have already been swapped to host byte order and displayed, so including them in the hexdump is confusing
-    if (num_opts > 1) { mprintf("%#-16a **** ERROR: MULTIPLE OPT RECORDS ****\n", srcaddr); HexDump(msg->data, end); }
-
-    if (entry) AnalyseHost(m, entry, InterfaceID);
-}
-
-mDNSlocal void ProcessUnicastResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID)
-{
-    int i;
-    const mDNSu8 *ptr = LocateAnswers(msg, end);
-    HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id);
-    //mprintf("%#a R\n", srcaddr);
-
-    for (i=0; i<msg->h.numAnswers + msg->h.numAuthorities + msg->h.numAdditionals; i++)
-    {
-        LargeCacheRecord pkt;
-        ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt);
-        if (ptr && pkt.r.resrec.rroriginalttl && entry) RecordHostInfo(entry, &pkt.r.resrec);
-    }
-}
-
-mDNSlocal mDNSBool AddressMatchesFilterList(const mDNSAddr *srcaddr)
-{
-    FilterList *f;
-    if (!Filters) return(srcaddr->type == AddressType);
-    for (f=Filters; f; f=f->next) if (mDNSSameAddress(srcaddr, &f->FilterAddr)) return(mDNStrue);
-    return(mDNSfalse);
-}
-
-mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-                                const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, const mDNSInterfaceID InterfaceID)
-{
-    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);
-    mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
-    int goodinterface = (FilterInterface == 0);
-
-    (void)dstaddr;  // Unused
-    (void)dstport;  // Unused
-
-    // Read the integer parts which are in IETF byte-order (MSB first, LSB second)
-    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]);
-
-    // For now we're only interested in monitoring IPv4 traffic.
-    // All IPv6 packets should just be duplicates of the v4 packets.
-    if (!goodinterface) goodinterface = (FilterInterface == (int)mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNSfalse));
-    if (goodinterface && AddressMatchesFilterList(srcaddr))
-    {
-        mDNS_Lock(m);
-        if (!mDNSAddrIsDNSMulticast(dstaddr))
-        {
-            if      (QR_OP == StdQ) mprintf("Unicast query from %#a\n", srcaddr);
-            else if (QR_OP == StdR) ProcessUnicastResponse(m, msg, end, srcaddr,                   InterfaceID);
-        }
-        else
-        {
-            if      (QR_OP == StdQ) DisplayQuery          (m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
-            else if (QR_OP == StdR) DisplayResponse       (m, msg, end, srcaddr, srcport, dstaddr, InterfaceID);
-            else
-            {
-                debugf("Unknown DNS packet type %02X%02X (ignored)", msg->h.flags.b[0], msg->h.flags.b[1]);
-                GotPacketFromHost(srcaddr, HostPkt_B, msg->h.id);
-                NumPktB++;
-            }
-        }
-        mDNS_Unlock(m);
-    }
-}
-
-mDNSlocal mStatus mDNSNetMonitor(void)
-{
-    struct tm tm;
-    int h, m, s, mul, div, TotPkt;
-#if !defined(WIN32)
-    sigset_t signals;
-#endif
-
-    mStatus status = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                               mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
-                               mDNS_Init_DontAdvertiseLocalAddresses,
-                               mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
-    if (status) return(status);
-
-    gettimeofday(&tv_start, NULL);
-
-#if defined( WIN32 )
-    status = SetupInterfaceList(&mDNSStorage);
-    if (status) return(status);
-    gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (gStopEvent == INVALID_HANDLE_VALUE) return mStatus_UnknownErr;
-    mDNSPollRegisterEvent( gStopEvent, StopNotification, NULL );
-    if (!SetConsoleCtrlHandler(ConsoleControlHandler, TRUE)) return mStatus_UnknownErr;
-    gRunning = mDNStrue; while (gRunning) mDNSPoll( INFINITE );
-    if (!SetConsoleCtrlHandler(ConsoleControlHandler, FALSE)) return mStatus_UnknownErr;
-    CloseHandle(gStopEvent);
-#else
-    mDNSPosixListenForSignalInEventLoop(SIGINT);
-    mDNSPosixListenForSignalInEventLoop(SIGTERM);
-
-    do
-    {
-        struct timeval timeout = { FutureTime, 0 };     // wait until SIGINT or SIGTERM
-        mDNSBool gotSomething;
-        mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &gotSomething);
-    }
-    while ( !( sigismember( &signals, SIGINT) || sigismember( &signals, SIGTERM)));
-#endif
-
-    // Now display final summary
-    TotPkt = NumPktQ + NumPktL + NumPktR;
-    gettimeofday(&tv_end, NULL);
-    tv_interval = tv_end;
-    if (tv_start.tv_usec > tv_interval.tv_usec)
-    { tv_interval.tv_usec += 1000000; tv_interval.tv_sec--; }
-    tv_interval.tv_sec  -= tv_start.tv_sec;
-    tv_interval.tv_usec -= tv_start.tv_usec;
-    h = (tv_interval.tv_sec / 3600);
-    m = (tv_interval.tv_sec % 3600) / 60;
-    s = (tv_interval.tv_sec % 60);
-    if (tv_interval.tv_sec > 10)
-    {
-        mul = 60;
-        div = tv_interval.tv_sec;
-    }
-    else
-    {
-        mul = 60000;
-        div = tv_interval.tv_sec * 1000 + tv_interval.tv_usec / 1000;
-        if (div == 0) div=1;
-    }
-
-    mprintf("\n\n");
-    localtime_r((time_t*)&tv_start.tv_sec, &tm);
-    mprintf("Started      %3d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv_start.tv_usec);
-    localtime_r((time_t*)&tv_end.tv_sec, &tm);
-    mprintf("End          %3d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv_end.tv_usec);
-    mprintf("Captured for %3d:%02d:%02d.%06d\n", h, m, s, tv_interval.tv_usec);
-    if (!Filters)
-    {
-        mprintf("Unique source addresses seen on network:");
-        if (IPv4HostList.num) mprintf(" %ld (IPv4)", IPv4HostList.num);
-        if (IPv6HostList.num) mprintf(" %ld (IPv6)", IPv6HostList.num);
-        if (!IPv4HostList.num && !IPv6HostList.num) mprintf(" None");
-        mprintf("\n");
-    }
-    mprintf("\n");
-    mprintf("Modern Query        Packets:      %7d   (avg%5d/min)\n", NumPktQ,        NumPktQ        * mul / div);
-    mprintf("Legacy Query        Packets:      %7d   (avg%5d/min)\n", NumPktL,        NumPktL        * mul / div);
-    mprintf("Multicast Response  Packets:      %7d   (avg%5d/min)\n", NumPktR,        NumPktR        * mul / div);
-    mprintf("Total     Multicast Packets:      %7d   (avg%5d/min)\n", TotPkt,         TotPkt         * mul / div);
-    mprintf("\n");
-    mprintf("Total New Service Probes:         %7d   (avg%5d/min)\n", NumProbes,      NumProbes      * mul / div);
-    mprintf("Total Goodbye Announcements:      %7d   (avg%5d/min)\n", NumGoodbyes,    NumGoodbyes    * mul / div);
-    mprintf("Total Query Questions:            %7d   (avg%5d/min)\n", NumQuestions,   NumQuestions   * mul / div);
-    mprintf("Total Queries from Legacy Clients:%7d   (avg%5d/min)\n", NumLegacy,      NumLegacy      * mul / div);
-    mprintf("Total Answers/Announcements:      %7d   (avg%5d/min)\n", NumAnswers,     NumAnswers     * mul / div);
-    mprintf("Total Additional Records:         %7d   (avg%5d/min)\n", NumAdditionals, NumAdditionals * mul / div);
-    mprintf("\n");
-    printstats(kReportTopServices);
-
-    if (!ExactlyOneFilter)
-    {
-        ShowSortedHostList(&IPv4HostList, kReportTopHosts);
-        ShowSortedHostList(&IPv6HostList, kReportTopHosts);
-    }
-
-    mDNS_Close(&mDNSStorage);
-    return(0);
-}
-
-#ifdef FUZZING
-#define main main_NetMonitor
-#endif
-
-mDNSexport int main(int argc, char **argv)
-{
-    const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
-    int i;
-    mStatus status;
-
-#if defined(WIN32)
-    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
-#endif
-
-    setlinebuf(stdout);             // Want to see lines as they appear, not block buffered
-
-    for (i=1; i<argc; i++)
-    {
-		if (i+1 < argc && !strcmp(argv[i], "-i"))
-        {
-			FilterInterface = if_nametoindex(argv[i+1]);
-			if (!FilterInterface) FilterInterface = atoi(argv[i+1]);
-			if (!FilterInterface) {
-				fprintf(stderr, "Unknown interface %s\n", argv[i+1]);
-				goto usage;
-			}
-            printf("Monitoring interface %d/%s\n", FilterInterface, argv[i+1]);
-			i += 1;
-        }
-        else if (!strcmp(argv[i], "-6"))
-        {
-            AddressType = mDNSAddrType_IPv6;
-            printf("Monitoring IPv6 traffic\n");
-        }
-        else
-        {
-            struct in_addr s4;
-            struct in6_addr s6;
-            FilterList *f;
-            mDNSAddr a;
-            a.type = mDNSAddrType_IPv4;
-
-            if (inet_pton(AF_INET, argv[i], &s4) == 1)
-                a.ip.v4.NotAnInteger = s4.s_addr;
-            else if (inet_pton(AF_INET6, argv[i], &s6) == 1)
-            {
-                a.type = mDNSAddrType_IPv6;
-                mDNSPlatformMemCopy(&a.ip.v6, &s6, sizeof(a.ip.v6));
-            }
-            else
-            {
-                struct hostent *h = gethostbyname(argv[i]);
-                if (h) a.ip.v4.NotAnInteger = *(long*)h->h_addr;
-                else goto usage;
-            }
-
-            f = malloc(sizeof(*f));
-            f->FilterAddr = a;
-            f->next = Filters;
-            Filters = f;
-        }
-    }
-
-    status = mDNSNetMonitor();
-    if (status) { fprintf(stderr, "%s: mDNSNetMonitor failed %d\n", progname, (int)status); return(status); }
-    return(0);
-
-usage:
-    fprintf(stderr, "\nmDNS traffic monitor\n");
-    fprintf(stderr, "Usage: %s [-i index] [-6] [host]\n", progname);
-    fprintf(stderr, "Optional [-i index] parameter displays only packets from that interface index\n");
-	fprintf(stderr, "Optional [-6] parameter displays only ipv6 packets (defaults to only ipv4 packets)\n");
-    fprintf(stderr, "Optional [host] parameter displays only packets from that host\n");
-
-    fprintf(stderr, "\nPer-packet header output:\n");
-    fprintf(stderr, "-Q-            Multicast Query from mDNS client that accepts multicast responses\n");
-    fprintf(stderr, "-R-            Multicast Response packet containing answers/announcements\n");
-    fprintf(stderr, "-LQ-           Multicast Query from legacy client that does *not* listen for multicast responses\n");
-    fprintf(stderr, "Q/Ans/Auth/Add Number of questions, answers, authority records and additional records in packet\n");
-
-    fprintf(stderr, "\nPer-record display:\n");
-    fprintf(stderr, "(PM)           Probe Question (new service starting), requesting multicast response\n");
-    fprintf(stderr, "(PU)           Probe Question (new service starting), requesting unicast response\n");
-    fprintf(stderr, "(DE)           Deletion/Goodbye (service going away)\n");
-    fprintf(stderr, "(LQ)           Legacy Query Question\n");
-    fprintf(stderr, "(QM)           Query Question, requesting multicast response\n");
-    fprintf(stderr, "(QU)           Query Question, requesting unicast response\n");
-    fprintf(stderr, "(KA)           Known Answer (information querier already knows)\n");
-    fprintf(stderr, "(AN)           Unique Answer to question (or periodic announcment) (entire RR Set)\n");
-    fprintf(stderr, "(AN+)          Answer to question (or periodic announcment) (add to existing RR Set members)\n");
-    fprintf(stderr, "(AD)           Unique Additional Record Set (entire RR Set)\n");
-    fprintf(stderr, "(AD+)          Additional records (add to existing RR Set members)\n");
-
-    fprintf(stderr, "\nFinal summary, sorted by service type:\n");
-    fprintf(stderr, "Probe          Probes for this service type starting up\n");
-    fprintf(stderr, "Goodbye        Goodbye (deletion) packets for this service type shutting down\n");
-    fprintf(stderr, "BrowseQ        Browse questions from clients browsing to find a list of instances of this service\n");
-    fprintf(stderr, "BrowseA        Browse answers/announcments advertising instances of this service\n");
-    fprintf(stderr, "ResolveQ       Resolve questions from clients actively connecting to an instance of this service\n");
-    fprintf(stderr, "ResolveA       Resolve answers/announcments giving connection information for an instance of this service\n");
-    fprintf(stderr, "\n");
-    return(-1);
-}
diff --git a/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c
deleted file mode 100644
index 9a0f692..0000000
--- a/mDNSPosix/PosixDaemon.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2003-2020 Apple 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
- *
- *     https://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.
-
-    File:		daemon.c
-
-    Contains:	main & associated Application layer for mDNSResponder on Linux.
-
- */
-
-#if __APPLE__
-// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
-// error, which prevents compilation because we build with "-Werror".
-// Since this is supposed to be portable cross-platform code, we don't care that daemon is
-// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
-#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#if __APPLE__
-#undef daemon
-extern int daemon(int, int);
-#endif
-
-#include "mDNSEmbeddedAPI.h"
-#include "mDNSPosix.h"
-#include "mDNSUNP.h"        // For daemon()
-#include "uds_daemon.h"
-#include "PlatformCommon.h"
-
-#define CONFIG_FILE "/etc/mdnsd.conf"
-static domainname DynDNSZone;                // Default wide-area zone for service registration
-static domainname DynDNSHostname;
-
-#define RR_CACHE_SIZE 500
-static CacheEntity gRRCache[RR_CACHE_SIZE];
-static mDNS_PlatformSupport PlatformStorage;
-
-mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
-{
-    (void)m; // Unused
-    if (result == mStatus_NoError)
-    {
-        // On successful registration of dot-local mDNS host name, daemon may want to check if
-        // any name conflict and automatic renaming took place, and if so, record the newly negotiated
-        // name in persistent storage for next time. It should also inform the user of the name change.
-        // On Mac OS X we store the current dot-local mDNS host name in the SCPreferences store,
-        // and notify the user with a CFUserNotification.
-    }
-    else if (result == mStatus_ConfigChanged)
-    {
-        udsserver_handle_configchange(m);
-    }
-    else if (result == mStatus_GrowCache)
-    {
-        // Allocate another chunk of cache storage
-        CacheEntity *storage = malloc(sizeof(CacheEntity) * RR_CACHE_SIZE);
-        if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
-    }
-}
-
-// %%% Reconfigure() probably belongs in the platform support layer (mDNSPosix.c), not the daemon cde
-// -- all client layers running on top of mDNSPosix.c need to handle network configuration changes,
-// not only the Unix Domain Socket Daemon
-
-static void Reconfigure(mDNS *m)
-{
-    mDNSAddr DynDNSIP;
-    const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
-    mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
-    if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
-        LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
-    ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
-    mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
-    if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
-    if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
-    mDNS_ConfigChanged(m);
-}
-
-// Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
-mDNSlocal void ParseCmdLineArgs(int argc, char **argv)
-{
-    if (argc > 1)
-    {
-        if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
-        else printf("Usage: %s [-debug]\n", argv[0]);
-    }
-    if (!mDNS_DebugMode)
-    {
-        int result = daemon(0, 0);
-        if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
-#if __APPLE__
-        LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
-        exit(-1);
-#endif
-    }
-}
-
-mDNSlocal void DumpStateLog()
-// Dump a little log of what we've been up to.
-{
-    char timestamp[MIN_TIMESTAMP_STRING_LENGTH];
-
-    mDNSu32 major_version = _DNS_SD_H / 10000;
-    mDNSu32 minor_version1 = (_DNS_SD_H - major_version * 10000) / 100;
-    mDNSu32 minor_version2 = _DNS_SD_H % 100;
-
-    getLocalTimestampNow(timestamp, sizeof(timestamp));
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "---- BEGIN STATE LOG ---- (%s mDNSResponder Build %d.%02d.%02d)", timestamp, major_version, minor_version1, minor_version2);
-
-    udsserver_info_dump_to_fd(STDERR_FILENO);
-
-    getLocalTimestampNow(timestamp, sizeof(timestamp));
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "---- END STATE LOG ---- (%s mDNSResponder Build %d.%02d.%02d)", timestamp, major_version, minor_version1, minor_version2);
-}
-
-mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
-{
-    sigset_t signals;
-    mDNSBool gotData = mDNSfalse;
-
-    mDNSPosixListenForSignalInEventLoop(SIGINT);
-    mDNSPosixListenForSignalInEventLoop(SIGTERM);
-    mDNSPosixListenForSignalInEventLoop(SIGUSR1);
-    mDNSPosixListenForSignalInEventLoop(SIGPIPE);
-    mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
-
-    for (; ;)
-    {
-        // Work out how long we expect to sleep before the next scheduled task
-        struct timeval timeout;
-        mDNSs32 ticks;
-
-        // Only idle if we didn't find any data the last time around
-        if (!gotData)
-        {
-            mDNSs32 nextTimerEvent = mDNS_Execute(m);
-            nextTimerEvent = udsserver_idle(nextTimerEvent);
-            ticks = nextTimerEvent - mDNS_TimeNow(m);
-            if (ticks < 1) ticks = 1;
-        }
-        else    // otherwise call EventLoop again with 0 timemout
-            ticks = 0;
-
-        timeout.tv_sec = ticks / mDNSPlatformOneSecond;
-        timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
-
-        (void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
-
-        if (sigismember(&signals, SIGHUP )) Reconfigure(m);
-        if (sigismember(&signals, SIGUSR1)) DumpStateLog();
-        // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
-        if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
-        if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
-    }
-    return EINTR;
-}
-
-int main(int argc, char **argv)
-{
-    mStatus err;
-
-    ParseCmdLineArgs(argc, argv);
-
-    LogMsg("%s starting", mDNSResponderVersionString);
-
-    err = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
-                    mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
-
-    if (mStatus_NoError == err)
-        err = udsserver_init(mDNSNULL, 0);
-
-    Reconfigure(&mDNSStorage);
-
-    // Now that we're finished with anything privileged, switch over to running as "nobody"
-    if (mStatus_NoError == err)
-    {
-        const struct passwd *pw = getpwnam("nobody");
-        if (pw != NULL)
-        {
-            if (setgid(pw->pw_gid) < 0)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                          "WARNING: mdnsd continuing as group root because setgid to \"nobody\" failed with " PUB_S, strerror(errno));
-            }
-            if (setuid(pw->pw_uid) < 0)
-            {
-                LogMsg("WARNING: mdnsd continuing as root because setuid to \"nobody\" failed with %s", strerror(errno));
-            }
-        }
-        else
-        {
-            LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
-        }
-    }
-
-    if (mStatus_NoError == err)
-        err = MainLoop(&mDNSStorage);
-
-    LogMsg("%s stopping", mDNSResponderVersionString);
-
-    mDNS_Close(&mDNSStorage);
-
-    if (udsserver_exit() < 0)
-        LogMsg("ExitCallback: udsserver_exit failed");
-
- #if MDNS_DEBUGMSGS > 0
-    printf("mDNSResponder exiting normally with %d\n", err);
- #endif
-
-    return err;
-}
-
-//		uds_daemon support		////////////////////////////////////////////////////////////
-
-mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
-/* Support routine for uds_daemon.c */
-{
-    // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
-    (void) platform_data;
-    return mDNSPosixAddFDToEventLoop(fd, callback, context);
-}
-
-ssize_t udsSupportReadFD(dnssd_sock_t fd, char *buf, mDNSu32 len, int flags, void *platform_data)
-{
-    (void) platform_data;
-    return recv(fd, buf, len, flags);
-}
-
-mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data)        // Note: This also CLOSES the file descriptor
-{
-    mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
-    (void) platform_data;
-    close(fd);
-    return err;
-}
-
-mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay)
-{
-    (void)delay;
-    // No-op, for now
-}
-
-#if _BUILDING_XCODE_PROJECT_
-// If the process crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
-asm (".desc ___crashreporter_info__, 0x10");
-#endif
-
-// For convenience when using the "strings" command, this is the last thing in the file
-#if mDNSResponderVersion > 1
-mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-#elif MDNS_VERSIONSTR_NODTS
-mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)";
-#else
-mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ")";
-#endif
diff --git a/mDNSPosix/ProxyResponder.c b/mDNSPosix/ProxyResponder.c
deleted file mode 100644
index 7b2305f..0000000
--- a/mDNSPosix/ProxyResponder.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include <stdio.h>              // For printf()
-#include <stdlib.h>             // For exit() etc.
-#include <string.h>             // For strlen() etc.
-#include <unistd.h>             // For select()
-#include <signal.h>             // For SIGINT, SIGTERM
-#include <errno.h>              // For errno, EINTR
-#include <netinet/in.h>         // For INADDR_NONE
-#include <arpa/inet.h>          // For inet_addr()
-#include <netdb.h>              // For gethostbyname()
-
-#include "mDNSEmbeddedAPI.h"    // Defines the interface to the client layer above
-#include "mDNSPosix.h"          // Defines the specific types needed to run mDNS on this platform
-#include "ExampleClientApp.h"
-
-// Compatibility workaround: Solaris 2.5 has no INADDR_NONE
-#ifndef INADDR_NONE
-#define INADDR_NONE (mDNSu32)0xffffffff
-#endif
-
-//*************************************************************************************************************
-// Globals
-mDNS mDNSStorage;       // mDNS core uses this to store its globals
-static mDNS_PlatformSupport PlatformStorage;  // Stores this platform's globals
-mDNSexport const char ProgramName[] = "mDNSProxyResponderPosix";
-
-//*************************************************************************************************************
-// Proxy Host Registration
-
-typedef struct
-{
-    mDNSv4Addr ip;
-    domainlabel hostlabel;      // Conforms to standard DNS letter-digit-hyphen host name rules
-    AuthRecord RR_A;        // 'A' (address) record for our ".local" name
-    AuthRecord RR_PTR;      // PTR (reverse lookup) record
-} ProxyHost;
-
-mDNSlocal void HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    ProxyHost *f = (ProxyHost*)rr->RecordContext;
-    if (result == mStatus_NoError)
-        debugf("Host name successfully registered: %##s", rr->resrec.name->c);
-    else
-    {
-        debugf("Host name conflict for %##s", rr->resrec.name->c);
-        mDNS_Deregister(m, &f->RR_A);
-        mDNS_Deregister(m, &f->RR_PTR);
-        exit(-1);
-    }
-}
-
-mDNSlocal mStatus mDNS_RegisterProxyHost(mDNS *m, ProxyHost *p)
-{
-    char buffer[32];
-
-    mDNS_SetupResourceRecord(&p->RR_A,   mDNSNULL, mDNSInterface_Any, kDNSType_A,   60, kDNSRecordTypeUnique,      AuthRecordAny, HostNameCallback, p);
-    mDNS_SetupResourceRecord(&p->RR_PTR, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 60, kDNSRecordTypeKnownUnique, AuthRecordAny, HostNameCallback, p);
-
-    p->RR_A.namestorage.c[0] = 0;
-    AppendDomainLabel(&p->RR_A.namestorage, &p->hostlabel);
-    AppendLiteralLabelString(&p->RR_A.namestorage, "local");
-
-    // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-    mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p->ip.b[3], p->ip.b[2], p->ip.b[1], p->ip.b[0]);
-    MakeDomainNameFromDNSNameString(&p->RR_PTR.namestorage, buffer);
-    p->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server
-
-    p->RR_A.resrec.rdata->u.ipv4 = p->ip;
-    AssignDomainName(&p->RR_PTR.resrec.rdata->u.name, p->RR_A.resrec.name);
-
-    mDNS_Register(m, &p->RR_A);
-    mDNS_Register(m, &p->RR_PTR);
-
-    debugf("Made Proxy Host Records for %##s", p->RR_A.resrec.name->c);
-
-    return(mStatus_NoError);
-}
-
-//*************************************************************************************************************
-// Service Registration
-
-// This sample ServiceCallback just calls mDNS_RenameAndReregisterService to automatically pick a new
-// unique name for the service. For a device such as a printer, this may be appropriate.
-// For a device with a user interface, and a screen, and a keyboard, the appropriate
-// response may be to prompt the user and ask them to choose a new name for the service.
-mDNSlocal void ServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
-{
-    switch (result)
-    {
-    case mStatus_NoError:      debugf("Callback: %##s Name Registered",    sr->RR_SRV.resrec.name->c); break;
-    case mStatus_NameConflict: debugf("Callback: %##s Name Conflict",      sr->RR_SRV.resrec.name->c); break;
-    case mStatus_MemFree:      debugf("Callback: %##s Memory Free",        sr->RR_SRV.resrec.name->c); break;
-    default:                   debugf("Callback: %##s Unknown Result %ld", sr->RR_SRV.resrec.name->c, result); break;
-    }
-
-    if (result == mStatus_NoError)
-    {
-        char buffer[MAX_ESCAPED_DOMAIN_NAME];
-        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer);
-        printf("Service %s now registered and active\n", buffer);
-    }
-
-    if (result == mStatus_NameConflict)
-    {
-        char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
-        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer1);
-        mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
-        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer2);
-        printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
-    }
-}
-
-// RegisterService() is a simple wrapper function which takes C string
-// parameters, converts them to domainname parameters, and calls mDNS_RegisterService()
-mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset,
-                               const char name[], const char type[], const char domain[],
-                               const domainname *host, mDNSu16 PortAsNumber, int argc, char **argv)
-{
-    domainlabel n;
-    domainname t, d;
-    unsigned char txtbuffer[1024], *bptr = txtbuffer;
-    char buffer[MAX_ESCAPED_DOMAIN_NAME];
-
-    MakeDomainLabelFromLiteralString(&n, name);
-    MakeDomainNameFromDNSNameString(&t, type);
-    MakeDomainNameFromDNSNameString(&d, domain);
-    while (argc)
-    {
-        int len = strlen(argv[0]);
-        if (len > 255 || bptr + 1 + len >= txtbuffer + sizeof(txtbuffer)) break;
-        printf("STR: %s\n", argv[0]);
-        bptr[0] = len;
-        strcpy((char*)(bptr+1), argv[0]);
-        bptr += 1 + len;
-        argc--;
-        argv++;
-    }
-
-    mDNS_RegisterService(m, recordset,
-                         &n, &t, &d, // Name, type, domain
-                         host, mDNSOpaque16fromIntVal(PortAsNumber),
-                         mDNSNULL, txtbuffer, bptr-txtbuffer, // TXT data, length
-                         mDNSNULL, 0, // Subtypes
-                         mDNSInterface_Any, // Interface ID
-                         ServiceCallback, mDNSNULL, 0); // Callback, context, flags
-
-    ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
-    printf("Made Service Records for %s\n", buffer);
-}
-
-//*************************************************************************************************************
-// Service non-existence assertion
-// (claiming a service name without actually providing a service at that name, to prevent anyone else using that name)
-// This is useful to avoid confusion between similar services
-// e.g. A printer that implements IPP printing service using the name "My Printer", but doesn't implement LPR service,
-// should also claim the LPR service name "My Printer" to stop a different printer offering LPR service under the same name,
-// since it would be confusing to users to have two equivalent services with the same name.
-
-mDNSlocal void NoSuchServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    const domainname *proxyhostname = (const domainname *)rr->RecordContext;
-    switch (result)
-    {
-    case mStatus_NoError:      debugf("Callback: %##s Name Registered",    rr->resrec.name->c); break;
-    case mStatus_NameConflict: debugf("Callback: %##s Name Conflict",      rr->resrec.name->c); break;
-    case mStatus_MemFree:      debugf("Callback: %##s Memory Free",        rr->resrec.name->c); break;
-    default:                   debugf("Callback: %##s Unknown Result %ld", rr->resrec.name->c, result); break;
-    }
-
-    if (result == mStatus_NoError)
-    {
-        char buffer[MAX_ESCAPED_DOMAIN_NAME];
-        ConvertDomainNameToCString(rr->resrec.name, buffer);
-        printf("Non-existence assertion %s now registered and active\n", buffer);
-    }
-
-    if (result == mStatus_NameConflict)
-    {
-        domainlabel n;
-        domainname t, d;
-        char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
-        ConvertDomainNameToCString(rr->resrec.name, buffer1);
-        DeconstructServiceName(rr->resrec.name, &n, &t, &d);
-        IncrementLabelSuffix(&n, mDNStrue);
-        mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, mDNSNULL, 0);
-        ConvertDomainNameToCString(rr->resrec.name, buffer2);
-        printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
-    }
-}
-
-mDNSlocal void RegisterNoSuchService(mDNS *m, AuthRecord *const rr, domainname *proxyhostname,
-                                     const char name[], const char type[], const char domain[])
-{
-    domainlabel n;
-    domainname t, d;
-    char buffer[MAX_ESCAPED_DOMAIN_NAME];
-    MakeDomainLabelFromLiteralString(&n, name);
-    MakeDomainNameFromDNSNameString(&t, type);
-    MakeDomainNameFromDNSNameString(&d, domain);
-    mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, proxyhostname, 0);
-    ConvertDomainNameToCString(rr->resrec.name, buffer);
-    printf("Made Non-existence Record for %s\n", buffer);
-}
-
-//*************************************************************************************************************
-// Main
-
-mDNSexport int main(int argc, char **argv)
-{
-    mStatus status;
-    sigset_t signals;
-
-    if (argc < 3) goto usage;
-
-    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                       mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
-                       mDNS_Init_DontAdvertiseLocalAddresses,
-                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
-    if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }
-
-    mDNSPosixListenForSignalInEventLoop(SIGINT);
-    mDNSPosixListenForSignalInEventLoop(SIGTERM);
-
-    if (!strcmp(argv[1], "-"))
-    {
-        domainname proxyhostname;
-        AuthRecord proxyrecord;
-        if (argc < 5) goto usage;
-        proxyhostname.c[0] = 0;
-        AppendLiteralLabelString(&proxyhostname, argv[2]);
-        AppendLiteralLabelString(&proxyhostname, "local");
-        RegisterNoSuchService(&mDNSStorage, &proxyrecord, &proxyhostname, argv[3], argv[4], "local.");
-    }
-    else
-    {
-        ProxyHost proxyhost;
-        ServiceRecordSet proxyservice;
-
-        proxyhost.ip.NotAnInteger = inet_addr(argv[1]);
-        if (proxyhost.ip.NotAnInteger == INADDR_NONE)   // INADDR_NONE is 0xFFFFFFFF
-        {
-            struct hostent *h = gethostbyname(argv[1]);
-            if (h) proxyhost.ip.NotAnInteger = *(long*)h->h_addr;
-        }
-        if (proxyhost.ip.NotAnInteger == INADDR_NONE)   // INADDR_NONE is 0xFFFFFFFF
-        {
-            fprintf(stderr, "%s is not valid host address\n", argv[1]);
-            return(-1);
-        }
-
-        MakeDomainLabelFromLiteralString(&proxyhost.hostlabel, argv[2]);
-
-        mDNS_RegisterProxyHost(&mDNSStorage, &proxyhost);
-
-        if (argc >=6)
-            RegisterService(&mDNSStorage, &proxyservice, argv[3], argv[4], "local.",
-                            proxyhost.RR_A.resrec.name, atoi(argv[5]), argc-6, &argv[6]);
-    }
-
-    do
-    {
-        struct timeval timeout = { FutureTime, 0 };     // wait until SIGINT or SIGTERM
-        mDNSBool gotSomething;
-        mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &gotSomething);
-    }
-    while ( !( sigismember( &signals, SIGINT) || sigismember( &signals, SIGTERM)));
-
-    mDNS_Close(&mDNSStorage);
-
-    return(0);
-
-usage:
-    fprintf(stderr, "%s ip hostlabel [srvname srvtype port txt [txt ...]]\n", argv[0]);
-    fprintf(stderr, "ip        Real IP address (or valid host name) of the host where the service actually resides\n");
-    fprintf(stderr, "hostlabel First label of the dot-local host name to create for this host, e.g. \"foo\" for \"foo.local.\"\n");
-    fprintf(stderr, "srvname   Descriptive name of service, e.g. \"Stuart's Ink Jet Printer\"\n");
-    fprintf(stderr, "srvtype   IANA service type, e.g. \"_ipp._tcp\" or \"_ssh._tcp\", etc.\n");
-    fprintf(stderr, "port      Port number where the service resides (1-65535)\n");
-    fprintf(stderr, "txt       Additional name/value pairs specified in service definition, e.g. \"pdl=application/postscript\"\n");
-    fprintf(stderr, "e.g. %s 169.254.12.34 thehost                                (just create a dot-local host name)\n", argv[0]);
-    fprintf(stderr, "or   %s 169.254.12.34 thehost \"My Printer\" _printer._tcp. 515 rp=lpt1 pdl=application/postscript\n", argv[0]);
-    fprintf(stderr, "or   %s -             thehost \"My Printer\" _printer._tcp.           (assertion of non-existence)\n", argv[0]);
-    return(-1);
-}
diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c
deleted file mode 100644
index 119c498..0000000
--- a/mDNSPosix/Responder.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if __APPLE__
-// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
-// error, which prevents compilation because we build with "-Werror".
-// Since this is supposed to be portable cross-platform code, we don't care that daemon is
-// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
-#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
-#endif
-
-#include <assert.h>
-#include <stdio.h>          // For printf()
-#include <stdlib.h>         // For exit() etc.
-#include <string.h>         // For strlen() etc.
-#include <unistd.h>         // For select()
-#include <errno.h>          // For errno, EINTR
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-
-#if __APPLE__
-#undef daemon
-extern int daemon(int, int);
-#endif
-
-#include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above
-#include "mDNSPosix.h"      // Defines the specific types needed to run mDNS on this platform
-#include "mDNSUNP.h"        // For daemon()
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Globals
-#endif
-
-mDNS mDNSStorage;       // mDNS core uses this to store its globals
-static mDNS_PlatformSupport PlatformStorage;  // Stores this platform's globals
-
-mDNSexport const char ProgramName[] = "mDNSResponderPosix";
-
-static const char *gProgramName = ProgramName;
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Signals
-#endif
-
-static volatile mDNSBool gReceivedSigUsr1;
-static volatile mDNSBool gReceivedSigHup;
-static volatile mDNSBool gStopNow;
-
-// We support 4 signals.
-//
-// o SIGUSR1 toggles verbose mode on and off in debug builds
-// o SIGHUP  triggers the program to re-read its preferences.
-// o SIGINT  causes an orderly shutdown of the program.
-// o SIGQUIT causes a somewhat orderly shutdown (direct but dangerous)
-// o SIGKILL kills us dead (easy to implement :-)
-//
-// There are fatal race conditions in our signal handling, but there's not much
-// we can do about them while remaining within the Posix space.  Specifically,
-// if a signal arrives after we test the globals its sets but before we call
-// select, the signal will be dropped.  The user will have to send the signal
-// again.  Unfortunately, Posix does not have a "sigselect" to atomically
-// modify the signal mask and start a select.
-
-static void HandleSigUsr1(int sigraised)
-// If we get a SIGUSR1 we toggle the state of the
-// verbose mode.
-{
-    assert(sigraised == SIGUSR1);
-    gReceivedSigUsr1 = mDNStrue;
-}
-
-static void HandleSigHup(int sigraised)
-// A handler for SIGHUP that causes us to break out of the
-// main event loop when the user kill 1's us.  This has the
-// effect of triggered the main loop to deregister the
-// current services and re-read the preferences.
-{
-    assert(sigraised == SIGHUP);
-    gReceivedSigHup = mDNStrue;
-}
-
-static void HandleSigInt(int sigraised)
-// A handler for SIGINT that causes us to break out of the
-// main event loop when the user types ^C.  This has the
-// effect of quitting the program.
-{
-    assert(sigraised == SIGINT);
-
-    if (gMDNSPlatformPosixVerboseLevel > 0) {
-        fprintf(stderr, "\nSIGINT\n");
-    }
-    gStopNow = mDNStrue;
-}
-
-static void HandleSigQuit(int sigraised)
-// If we get a SIGQUIT the user is desperate and we
-// just call mDNS_Close directly.  This is definitely
-// not safe (because it could reenter mDNS), but
-// we presume that the user has already tried the safe
-// alternatives.
-{
-    assert(sigraised == SIGQUIT);
-
-    if (gMDNSPlatformPosixVerboseLevel > 0) {
-        fprintf(stderr, "\nSIGQUIT\n");
-    }
-    mDNS_Close(&mDNSStorage);
-    exit(0);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Parameter Checking
-#endif
-
-static mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation)
-// Checks that richTextName is reasonable
-// label and, if it isn't and printExplanation is true, prints
-// an explanation of why not.
-{
-    mDNSBool result = mDNStrue;
-    if (result && strlen(richTextName) > 63) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Service name is too long (must be 63 characters or less)\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    if (result && richTextName[0] == 0) {
-        if (printExplanation) {
-            fprintf(stderr, "%s: Service name can't be empty\n", gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    return result;
-}
-
-static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool printExplanation)
-// Checks that serviceType is a reasonable service type
-// label and, if it isn't and printExplanation is true, prints
-// an explanation of why not.
-{
-    mDNSBool result;
-
-    result = mDNStrue;
-    if (result && strlen(serviceType) > 63) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Service type is too long (must be 63 characters or less)\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    if (result && serviceType[0] == 0) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Service type can't be empty\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    return result;
-}
-
-static mDNSBool CheckThatPortNumberIsUsable(long portNumber, mDNSBool printExplanation)
-// Checks that portNumber is a reasonable port number
-// and, if it isn't and printExplanation is true, prints
-// an explanation of why not.
-{
-    mDNSBool result;
-
-    result = mDNStrue;
-    if (result && (portNumber <= 0 || portNumber > 65535)) {
-        if (printExplanation) {
-            fprintf(stderr,
-                    "%s: Port number specified by -p must be in range 1..65535\n",
-                    gProgramName);
-        }
-        result = mDNSfalse;
-    }
-    return result;
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Command Line Arguments
-#endif
-
-static const char kDefaultPIDFile[]     = "/var/run/mDNSResponder.pid";
-static const char kDefaultServiceType[] = "_afpovertcp._tcp.";
-static const char kDefaultServiceDomain[] = "local.";
-enum {
-    kDefaultPortNumber = 548
-};
-
-static void PrintUsage()
-{
-    fprintf(stderr,
-            "Usage: %s [-v level ] [-r] [-n name] [-t type] [-d domain] [-p port] [-f file] [-b] [-P pidfile] [-x name=val ...]\n",
-            gProgramName);
-    fprintf(stderr, "          -v verbose mode, level is a number from 0 to 2\n");
-    fprintf(stderr, "             0 = no debugging info (default)\n");
-    fprintf(stderr, "             1 = standard debugging info\n");
-    fprintf(stderr, "             2 = intense debugging info\n");
-    fprintf(stderr, "             can be cycled kill -USR1\n");
-    fprintf(stderr, "          -r also bind to port 53 (port 5353 is always bound)\n");
-    fprintf(stderr, "          -n uses 'name' as the service name (required)\n");
-    fprintf(stderr, "          -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
-    fprintf(stderr, "          -d uses 'domain' as the service domain (default is '%s')\n", kDefaultServiceDomain);
-    fprintf(stderr, "          -p uses 'port' as the port number (default is '%d')\n",  kDefaultPortNumber);
-    fprintf(stderr, "          -f reads a service list from 'file'\n");
-    fprintf(stderr, "          -b forces daemon (background) mode\n");
-    fprintf(stderr, "          -P uses 'pidfile' as the PID file\n");
-    fprintf(stderr, "             (default is '%s')\n",  kDefaultPIDFile);
-    fprintf(stderr, "             only meaningful if -b also specified\n");
-    fprintf(stderr, "          -x stores name=val in TXT record (default is empty).\n");
-    fprintf(stderr, "             MUST be the last command-line argument;\n");
-    fprintf(stderr, "             all subsequent arguments after -x are treated as name=val pairs.\n");
-}
-
-static mDNSBool gAvoidPort53      = mDNStrue;
-static const char *gServiceName      = "";
-static const char *gServiceType      = kDefaultServiceType;
-static const char *gServiceDomain    = kDefaultServiceDomain;
-static mDNSu8 gServiceText[sizeof(RDataBody)];
-static mDNSu16 gServiceTextLen   = 0;
-static int gPortNumber       = kDefaultPortNumber;
-static const char *gServiceFile      = "";
-static mDNSBool gDaemon           = mDNSfalse;
-static const char *gPIDFile          = kDefaultPIDFile;
-
-static void ParseArguments(int argc, char **argv)
-// Parses our command line arguments into the global variables
-// listed above.
-{
-    int ch;
-
-    // Set gProgramName to the last path component of argv[0]
-
-    gProgramName = strrchr(argv[0], '/');
-    if (gProgramName == NULL) {
-        gProgramName = argv[0];
-    } else {
-        gProgramName += 1;
-    }
-
-    // Parse command line options using getopt.
-
-    do {
-        ch = getopt(argc, argv, "v:rn:t:d:p:f:dP:bx");
-        if (ch != -1) {
-            switch (ch) {
-            case 'v':
-                gMDNSPlatformPosixVerboseLevel = atoi(optarg);
-                if (gMDNSPlatformPosixVerboseLevel < 0 || gMDNSPlatformPosixVerboseLevel > 2) {
-                    fprintf(stderr,
-                            "%s: Verbose mode must be in the range 0..2\n",
-                            gProgramName);
-                    exit(1);
-                }
-                break;
-            case 'r':
-                gAvoidPort53 = mDNSfalse;
-                break;
-            case 'n':
-                gServiceName = optarg;
-                if ( !CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) {
-                    exit(1);
-                }
-                break;
-            case 't':
-                gServiceType = optarg;
-                if ( !CheckThatServiceTypeIsUsable(gServiceType, mDNStrue) ) {
-                    exit(1);
-                }
-                break;
-            case 'd':
-                gServiceDomain = optarg;
-                break;
-            case 'p':
-                gPortNumber = atol(optarg);
-                if ( !CheckThatPortNumberIsUsable(gPortNumber, mDNStrue) ) {
-                    exit(1);
-                }
-                break;
-            case 'f':
-                gServiceFile = optarg;
-                break;
-            case 'b':
-                gDaemon = mDNStrue;
-                break;
-            case 'P':
-                gPIDFile = optarg;
-                break;
-            case 'x':
-                while (optind < argc)
-                {
-                    gServiceText[gServiceTextLen] = strlen(argv[optind]);
-                    mDNSPlatformMemCopy(gServiceText+gServiceTextLen+1, argv[optind], gServiceText[gServiceTextLen]);
-                    gServiceTextLen += 1 + gServiceText[gServiceTextLen];
-                    optind++;
-                }
-                ch = -1;
-                break;
-            case '?':
-            default:
-                PrintUsage();
-                exit(1);
-                break;
-            }
-        }
-    } while (ch != -1);
-
-    // Check for any left over command line arguments.
-
-    if (optind != argc) {
-        PrintUsage();
-        fprintf(stderr, "%s: Unexpected argument '%s'\n", gProgramName, argv[optind]);
-        exit(1);
-    }
-
-    // Check for inconsistency between the arguments.
-
-    if ( (gServiceName[0] == 0) && (gServiceFile[0] == 0) ) {
-        PrintUsage();
-        fprintf(stderr, "%s: You must specify a service name to register (-n) or a service file (-f).\n", gProgramName);
-        exit(1);
-    }
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Registration
-#endif
-
-typedef struct PosixService PosixService;
-
-struct PosixService {
-    ServiceRecordSet coreServ;
-    PosixService *next;
-    int serviceID;
-};
-
-static PosixService *gServiceList = NULL;
-
-static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegistration, mStatus status)
-// mDNS core calls this routine to tell us about the status of
-// our registration.  The appropriate action to take depends
-// entirely on the value of status.
-{
-    switch (status) {
-
-    case mStatus_NoError:
-        debugf("Callback: %##s Name Registered",   thisRegistration->RR_SRV.resrec.name->c);
-        // Do nothing; our name was successfully registered.  We may
-        // get more call backs in the future.
-        break;
-
-    case mStatus_NameConflict:
-        debugf("Callback: %##s Name Conflict",     thisRegistration->RR_SRV.resrec.name->c);
-
-        // In the event of a conflict, this sample RegistrationCallback
-        // just calls mDNS_RenameAndReregisterService to automatically
-        // pick a new unique name for the service. For a device such as a
-        // printer, this may be appropriate.  For a device with a user
-        // interface, and a screen, and a keyboard, the appropriate response
-        // may be to prompt the user and ask them to choose a new name for
-        // the service.
-        //
-        // Also, what do we do if mDNS_RenameAndReregisterService returns an
-        // error.  Right now I have no place to send that error to.
-
-        status = mDNS_RenameAndReregisterService(m, thisRegistration, mDNSNULL);
-        assert(status == mStatus_NoError);
-        break;
-
-    case mStatus_MemFree:
-        debugf("Callback: %##s Memory Free",       thisRegistration->RR_SRV.resrec.name->c);
-
-        // When debugging is enabled, make sure that thisRegistration
-        // is not on our gServiceList.
-
-            #if !defined(NDEBUG)
-        {
-            PosixService *cursor;
-
-            cursor = gServiceList;
-            while (cursor != NULL) {
-                assert(&cursor->coreServ != thisRegistration);
-                cursor = cursor->next;
-            }
-        }
-            #endif
-        free(thisRegistration);
-        break;
-
-    default:
-        debugf("Callback: %##s Unknown Status %ld", thisRegistration->RR_SRV.resrec.name->c, status);
-        break;
-    }
-}
-
-static int gServiceID = 0;
-
-static mStatus RegisterOneService(const char *  richTextName,
-                                  const char *  serviceType,
-                                  const char *  serviceDomain,
-                                  const mDNSu8 text[],
-                                  mDNSu16 textLen,
-                                  long portNumber)
-{
-    mStatus status;
-    PosixService *      thisServ;
-    domainlabel name;
-    domainname type;
-    domainname domain;
-
-    status = mStatus_NoError;
-    thisServ = (PosixService *) calloc(sizeof(*thisServ), 1);
-    if (thisServ == NULL) {
-        status = mStatus_NoMemoryErr;
-    }
-    if (status == mStatus_NoError) {
-        MakeDomainLabelFromLiteralString(&name,  richTextName);
-        MakeDomainNameFromDNSNameString(&type, serviceType);
-        MakeDomainNameFromDNSNameString(&domain, serviceDomain);
-        status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ,
-                                      &name, &type, &domain, // Name, type, domain
-                                      NULL, mDNSOpaque16fromIntVal(portNumber),
-                                      NULL, text, textLen, // TXT data, length
-                                      NULL, 0,      // Subtypes
-                                      mDNSInterface_Any, // Interface ID
-                                      RegistrationCallback, thisServ, 0); // Callback, context, flags
-    }
-    if (status == mStatus_NoError) {
-        thisServ->serviceID = gServiceID;
-        gServiceID += 1;
-
-        thisServ->next = gServiceList;
-        gServiceList = thisServ;
-
-        if (gMDNSPlatformPosixVerboseLevel > 0) {
-            fprintf(stderr,
-                    "%s: Registered service %d, name \"%s\", type \"%s\", domain \"%s\",  port %ld\n",
-                    gProgramName,
-                    thisServ->serviceID,
-                    richTextName,
-                    serviceType,
-                    serviceDomain,
-                    portNumber);
-        }
-    } else {
-        if (thisServ != NULL) {
-            free(thisServ);
-        }
-    }
-    return status;
-}
-
-static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp, mDNSBool skipBlankLines)
-{
-    size_t len;
-    mDNSBool readNextLine;
-
-    do {
-        readNextLine = mDNSfalse;
-
-        if (fgets(buf, bufSize, fp) == NULL)
-            return mDNSfalse;   // encountered EOF or an error condition
-
-        // These first characters indicate a blank line.
-        if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\r' || buf[0] == '\n') {
-            if (!skipBlankLines)
-                return mDNSfalse;
-            readNextLine = mDNStrue;
-        }
-        // always skip comment lines
-        if (buf[0] == '#')
-            readNextLine = mDNStrue;
-
-    } while (readNextLine);
-
-    len = strlen( buf);
-    if ( buf[len - 1] == '\r' || buf[len - 1] == '\n')
-        buf[len - 1] = '\0';
-
-    return mDNStrue;
-}
-
-static mStatus RegisterServicesInFile(const char *filePath)
-{
-    mStatus status = mStatus_NoError;
-    FILE *      fp = fopen(filePath, "r");
-    int rv;
-
-    if (fp == NULL) {
-        return mStatus_UnknownErr;
-    }
-
-    if (gMDNSPlatformPosixVerboseLevel > 1)
-        fprintf(stderr, "Parsing %s for services\n", filePath);
-
-    do {
-        char nameBuf[256];
-        char * name = nameBuf;
-        char type[256];
-        const char *dom = kDefaultServiceDomain;
-        char rawText[1024];
-        mDNSu8 text[sizeof(RDataBody)];
-        unsigned int textLen = 0;
-        char port[256];
-        char *p;
-
-        // Read the service name, type, port, and optional text record fields.
-        // Skip blank lines while looking for the next service name.
-        if (!ReadALine(name, sizeof(nameBuf), fp, mDNStrue))
-            break;
-
-        // Special case that allows service name to begin with a '#'
-        // character by escaping it with a '\' to distiguish it from
-        // a comment line.  Remove the leading '\' here before
-        // registering the service.
-        if (name[0] == '\\' && name[1] == '#')
-            name++;
-
-        if (gMDNSPlatformPosixVerboseLevel > 1)
-            fprintf(stderr, "Service name: \"%s\"\n", name);
-
-        // Don't skip blank lines in calls to ReadAline() after finding the
-        // service name since the next blank line indicates the end
-        // of this service record.
-        if (!ReadALine(type, sizeof(type), fp, mDNSfalse))
-            break;
-
-        // see if a domain name is specified
-        p = type;
-        while (*p && *p != ' ' && *p != '\t') p++;
-        if (*p) {
-            *p = 0; // NULL terminate the <type>.<protocol> string
-            // skip any leading whitespace before domain name
-            p++;
-            while (*p && (*p == ' ' || *p == '\t')) p++;
-            if (*p)
-                dom = p;
-        }
-        if (gMDNSPlatformPosixVerboseLevel > 1) {
-            fprintf(stderr, "Service type: \"%s\"\n", type);
-            fprintf(stderr, "Service domain: \"%s\"\n", dom);
-        }
-
-        if (!ReadALine(port, sizeof(port), fp, mDNSfalse))
-            break;
-        if (gMDNSPlatformPosixVerboseLevel > 1)
-            fprintf(stderr, "Service port: %s\n", port);
-
-        if (   !CheckThatRichTextNameIsUsable(name, mDNStrue)
-               || !CheckThatServiceTypeIsUsable(type, mDNStrue)
-               || !CheckThatPortNumberIsUsable(atol(port), mDNStrue))
-            break;
-
-        // read the TXT record fields
-        while (1) {
-            int len;
-            if (!ReadALine(rawText, sizeof(rawText), fp, mDNSfalse)) break;
-            if (gMDNSPlatformPosixVerboseLevel > 1)
-                fprintf(stderr, "Text string: \"%s\"\n", rawText);
-            len = strlen(rawText);
-            if (len <= 255)
-            {
-                unsigned int newlen = textLen + 1 + len;
-                if (len == 0 || newlen >= sizeof(text)) break;
-                text[textLen] = len;
-                mDNSPlatformMemCopy(text + textLen + 1, rawText, len);
-                textLen = newlen;
-            }
-            else
-                fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n",
-                        gProgramName, name, type, port);
-        }
-
-        status = RegisterOneService(name, type, dom, text, textLen, atol(port));
-        if (status != mStatus_NoError) {
-            // print error, but try to read and register other services in the file
-            fprintf(stderr, "%s: Failed to register service, name \"%s\", type \"%s\", domain \"%s\", port %s\n",
-                    gProgramName, name, type, dom, port);
-        }
-
-    } while (!feof(fp));
-
-    if (!feof(fp)) {
-        fprintf(stderr, "%s: Error reading service file %s\n", gProgramName, filePath);
-        status = mStatus_UnknownErr;
-    }
-
-    rv = fclose(fp);
-    assert(rv == 0);
-
-    return status;
-}
-
-static mStatus RegisterOurServices(void)
-{
-    mStatus status;
-
-    status = mStatus_NoError;
-    if (gServiceName[0] != 0) {
-        status = RegisterOneService(gServiceName,
-                                    gServiceType,
-                                    gServiceDomain,
-                                    gServiceText, gServiceTextLen,
-                                    gPortNumber);
-    }
-    if (status == mStatus_NoError && gServiceFile[0] != 0) {
-        status = RegisterServicesInFile(gServiceFile);
-    }
-    return status;
-}
-
-static void DeregisterOurServices(void)
-{
-    PosixService *thisServ;
-
-    while (gServiceList != NULL) {
-        thisServ = gServiceList;
-        gServiceList = thisServ->next;
-
-        mDNS_DeregisterService(&mDNSStorage, &thisServ->coreServ);
-
-        if (gMDNSPlatformPosixVerboseLevel > 0) {
-            fprintf(stderr,
-                    "%s: Deregistered service %d\n",
-                    gProgramName,
-                    thisServ->serviceID);
-        }
-    }
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark **** Main
-#endif
-
-int main(int argc, char **argv)
-{
-    mStatus status;
-    int result;
-
-    // Parse our command line arguments.  This won't come back if there's an error.
-
-    ParseArguments(argc, argv);
-
-    // If we're told to run as a daemon, then do that straight away.
-    // Note that we don't treat the inability to create our PID
-    // file as an error.  Also note that we assign getpid to a long
-    // because printf has no format specified for pid_t.
-
-    if (gDaemon) {
-        int result;
-        if (gMDNSPlatformPosixVerboseLevel > 0) {
-            fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName);
-        }
-        result = daemon(0,0);
-        if (result == 0) {
-            FILE *fp;
-            int junk;
-
-            fp = fopen(gPIDFile, "w");
-            if (fp != NULL) {
-                fprintf(fp, "%ld\n", (long) getpid());
-                junk = fclose(fp);
-                assert(junk == 0);
-            }
-        } else {
-            fprintf(stderr, "%s: Could not run as daemon - exiting\n", gProgramName);
-            exit(result);
-        }
-    } else {
-        if (gMDNSPlatformPosixVerboseLevel > 0) {
-            fprintf(stderr, "%s: Starting in foreground mode, PID %ld\n", gProgramName, (long) getpid());
-        }
-    }
-
-    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
-                       mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
-                       mDNS_Init_AdvertiseLocalAddresses,
-                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
-    if (status != mStatus_NoError) return(2);
-
-    status = RegisterOurServices();
-    if (status != mStatus_NoError) return(2);
-
-    signal(SIGHUP,  HandleSigHup);      // SIGHUP has to be sent by kill -HUP <pid>
-    signal(SIGINT,  HandleSigInt);      // SIGINT is what you get for a Ctrl-C
-    signal(SIGQUIT, HandleSigQuit);     // SIGQUIT is what you get for a Ctrl-\ (indeed)
-    signal(SIGUSR1, HandleSigUsr1);     // SIGUSR1 has to be sent by kill -USR1 <pid>
-
-    while (!gStopNow)
-    {
-        int nfds = 0;
-        fd_set readfds, writefds;
-        struct timeval timeout;
-        int result;
-
-        // 1. Set up the fd_set as usual here.
-        // This example client has no file descriptors of its own,
-        // but a real application would call FD_SET to add them to the set here
-        FD_ZERO(&readfds);
-        FD_ZERO(&writefds);
-
-        // 2. Set up the timeout.
-        // This example client has no other work it needs to be doing,
-        // so we set an effectively infinite timeout
-        timeout.tv_sec = FutureTime;
-        timeout.tv_usec = 0;
-
-        // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout
-        mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &writefds, &timeout);
-
-        // 4. Call select as normal
-        verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec);
-        result = select(nfds, &readfds, NULL, NULL, &timeout);
-
-        if (result < 0)
-        {
-            verbosedebugf("select() returned %d errno %d", result, errno);
-            if (errno != EINTR) gStopNow = mDNStrue;
-            else
-            {
-                if (gReceivedSigUsr1)
-                {
-                    gReceivedSigUsr1 = mDNSfalse;
-                    gMDNSPlatformPosixVerboseLevel += 1;
-                    if (gMDNSPlatformPosixVerboseLevel > 2)
-                        gMDNSPlatformPosixVerboseLevel = 0;
-                    if ( gMDNSPlatformPosixVerboseLevel > 0 )
-                        fprintf(stderr, "\nVerbose level %d\n", gMDNSPlatformPosixVerboseLevel);
-                }
-                if (gReceivedSigHup)
-                {
-                    if (gMDNSPlatformPosixVerboseLevel > 0)
-                        fprintf(stderr, "\nSIGHUP\n");
-                    gReceivedSigHup = mDNSfalse;
-                    DeregisterOurServices();
-                    status = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
-                    if (status != mStatus_NoError) break;
-                    status = RegisterOurServices();
-                    if (status != mStatus_NoError) break;
-                }
-            }
-        }
-        else
-        {
-            // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work
-            mDNSPosixProcessFDSet(&mDNSStorage, &readfds, &writefds);
-
-            // 6. This example client has no other work it needs to be doing,
-            // but a real client would do its work here
-            // ... (do work) ...
-        }
-    }
-
-    debugf("Exiting");
-
-    DeregisterOurServices();
-    mDNS_Close(&mDNSStorage);
-
-    if (status == mStatus_NoError) {
-        result = 0;
-    } else {
-        result = 2;
-    }
-    if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
-        fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result);
-    }
-
-    return result;
-}
diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c
deleted file mode 100644
index 0a7c3df..0000000
--- a/mDNSPosix/mDNSPosix.c
+++ /dev/null
@@ -1,2510 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- *
- */
-
-#include "mDNSEmbeddedAPI.h"           // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "mDNSPosix.h"               // Defines the specific types needed to run mDNS on this platform
-#include "PlatformCommon.h"
-#include "dns_sd.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/select.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>                   // platform support for UTC time
-#include <ifaddrs.h>
-
-#if USES_NETLINK
-#include <asm/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#else // USES_NETLINK
-#include <net/route.h>
-#include <net/if.h>
-#endif // USES_NETLINK
-#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
-#include <netinet/in_var.h>
-#include <net/if_dl.h>
-#endif
-#if defined(TARGET_OS_LINUX) && TARGET_OS_LINUX
-#include <net/if_arp.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#endif
-
-#include "mDNSUNP.h"
-#include "GenLinkedList.h"
-#include "mdns_strict.h"
-
-// ***************************************************************************
-// Structures
-
-// Context record for interface change callback
-struct IfChangeRec
-{
-    int NotifySD;
-    mDNS *mDNS;
-};
-typedef struct IfChangeRec IfChangeRec;
-
-// Note that static data is initialized to zero in (modern) C.
-static PosixEventSource *gEventSources;             // linked list of PosixEventSource's
-static sigset_t gEventSignalSet;                // Signals which event loop listens for
-static sigset_t gEventSignals;                  // Signals which were received while inside loop
-
-static PosixNetworkInterface *gRecentInterfaces;
-
-// ***************************************************************************
-// Globals (for debugging)
-
-static int num_registered_interfaces = 0;
-static int num_pkts_accepted = 0;
-static int num_pkts_rejected = 0;
-
-// ***************************************************************************
-// Locals
-mDNSlocal void requestReadEvents(PosixEventSource *eventSource,
-                                    const char *taskName, mDNSPosixEventCallback callback, void *context);
-mDNSlocal mStatus stopReadOrWriteEvents(int fd, mDNSBool freeSource, mDNSBool removeSource, int flags);
-mDNSlocal void requestWriteEvents(PosixEventSource *eventSource,
-                                     const char *taskName, mDNSPosixEventCallback callback, void *context);
-mDNSlocal void UDPReadCallback(int fd, void *context);
-mDNSlocal int SetupIPv4Socket(int fd);
-mDNSlocal int SetupIPv6Socket(int fd);
-
-// ***************************************************************************
-// Constants
-
-static const int kOn = 1;
-static const int kIntTwoFiveFive = 255;
-static const unsigned char kByteTwoFiveFive = 255;
-
-// ***************************************************************************
-// Functions
-
-#if MDNS_MALLOC_DEBUGGING
-mDNSexport void mDNSPlatformValidateLists(void)
-{
-    // This should validate gEventSources and any other Posix-specific stuff that gets allocated.
-}
-#endif
-
-int gMDNSPlatformPosixVerboseLevel = 0;
-
-#define PosixErrorToStatus(errNum) ((errNum) == 0 ? mStatus_NoError : mStatus_UnknownErr)
-
-mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipAddr, mDNSIPPort *ipPort)
-{
-    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;
-    }
-
-#if HAVE_IPV6
-    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:
-        verbosedebugf("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 void *const msg, const mDNSu8 *const end,
-                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
-                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
-{
-    int err = 0;
-    struct sockaddr_storage to;
-    PosixNetworkInterface * thisIntf = (PosixNetworkInterface *)(InterfaceID);
-    int sendingsocket = -1;
-    struct sockaddr *sa = (struct sockaddr *)&to;
-
-    (void) useBackgroundTrafficClass;
-
-    assert(m != NULL);
-    assert(msg != NULL);
-    assert(end != NULL);
-    assert((((char *) end) - ((char *) msg)) > 0);
-
-    if (dstPort.NotAnInteger == 0)
-    {
-        LogMsg("mDNSPlatformSendUDP: Invalid argument -dstPort is set to 0");
-        return PosixErrorToStatus(EINVAL);
-    }
-    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;
-        sendingsocket           = thisIntf ? thisIntf->multicastSocket4 : m->p->unicastSocket4;
-    }
-
-#if HAVE_IPV6
-    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;
-        sendingsocket             = thisIntf ? thisIntf->multicastSocket6 : m->p->unicastSocket6;
-    }
-#endif
-    // In case we get some other address family, return an error, since it's not supported.
-    else
-    {
-        return kDNSServiceErr_BadParam;
-    }
-
-    // We don't open the socket until we get a send, because we don't know whether it's IPv4 or IPv6.
-    if (src)
-    {
-        if (src->events.fd == -1)
-        {
-            int sock = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP);
-            struct sockaddr_storage from;
-            socklen_t fromlen;
-            int times = 0;
-            uint16_t *pport;
-
-            if (sock < 0)
-            {
-                LogMsg("Can't create UDP socket: %s", strerror(errno));
-                return PosixErrorToStatus(errno);
-            }
-
-            // Randomize the port.
-            if (src->randomizePort)
-            {
-                memset(&from, 0, sizeof from);
-                if (sa->sa_family == AF_INET)
-                {
-                    ((struct sockaddr_in *)&from)->sin_family = AF_INET;
-                    fromlen = sizeof (struct sockaddr_in);
-                    pport = &((struct sockaddr_in *)&from)->sin_port;
-                    err = SetupIPv4Socket(sock);
-                    if (err) { return err; }
-                }
-                else
-                {
-                    ((struct sockaddr_in6 *)&from)->sin6_family = AF_INET6;
-                    fromlen = sizeof (struct sockaddr_in6);
-                    pport = &((struct sockaddr_in6 *)&from)->sin6_port;
-                    err = SetupIPv6Socket(sock);
-                    if (err) { return err; }
-                }
-#ifndef NOT_HAVE_SA_LEN
-                ((struct sockaddr *)&from)->sa_len = fromlen;
-#endif
-
-                while (times++ < 1000)
-                {
-                    *pport = 0xC000 + mDNSRandom(0x3FFF);
-                    if (bind(sock, (struct sockaddr *)&from, fromlen) >= 0)
-                    {
-                        src->port.NotAnInteger = *pport;
-                        src->events.fd = sock;
-                        break;
-                    }
-                    if (errno != EADDRINUSE)
-                    {
-                        LogMsg("Can't get randomized port: %s", strerror(errno));
-                        return PosixErrorToStatus(errno);
-                    }
-                }
-                if (src->events.fd == -1)
-                {
-                    LogMsg("Unable to get random port: too many tries.");
-                    return PosixErrorToStatus(EADDRINUSE);
-                }
-                requestReadEvents(&src->events, "mDNSPosix::UDPReadCallback", UDPReadCallback, src);
-            }
-        }
-        sendingsocket = src->events.fd;
-    }
-
-    if (sendingsocket >= 0)
-        err = sendto(sendingsocket, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
-
-    if      (err > 0) err = 0;
-    else if (err < 0)
-    {
-        static int MessageCount = 0;
-        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
-        if (!mDNSAddressIsAllDNSLinkGroup(dst))
-            if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
-
-        if (MessageCount < 1000)
-        {
-            MessageCount++;
-            if (thisIntf)
-                LogMsg("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);
-            else
-                LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
-        }
-    }
-
-    return PosixErrorToStatus(err);
-}
-
-mDNSlocal void TCPReadCallback(int fd, void *context)
-{
-    TCPSocket *sock = context;
-    (void)fd;
-
-    // TLS reading is handled in mDNSPlatformTCPRead().
-        sock->callback(sock, sock->context, mDNSfalse, sock->err);
-}
-
-mDNSlocal void tcpConnectCallback(int fd, void *context)
-{
-    TCPSocket *sock = context;
-    mDNSBool c = !sock->connected;
-    int result;
-    socklen_t len = sizeof result;
-
-    sock->connected = mDNStrue;
-
-    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &len) < 0)
-    {
-        LogInfo("ERROR: TCPConnectCallback - unable to get connect error: socket %d: Error %d (%s)",
-               sock->events.fd, result, strerror(result));
-        sock->err = mStatus_ConnFailed;
-    }
-    else
-    {
-        if (result != 0)
-        {
-            sock->err = mStatus_ConnFailed;
-            if (result == EHOSTUNREACH || result == EADDRNOTAVAIL || result == ENETDOWN)
-            {
-                LogInfo("ERROR: TCPConnectCallback - connect failed: socket %d: Error %d (%s)",
-                        sock->events.fd, result, strerror(result));
-            }
-            else
-            {
-                LogMsg("ERROR: TCPConnectCallback - connect failed: socket %d: Error %d (%s)",
-                       sock->events.fd, result, strerror(result));
-            }
-        }
-        else
-        {
-            if (sock->flags & kTCPSocketFlags_UseTLS) {
-#ifdef POSIX_HAS_TLS
-                sock->tls = mDNSPosixTLSClientStateCreate(sock);
-                if (sock->tls == mDNSNULL) {
-                    LogMsg("ERROR: TCPConnectCallback: TLS context state create failed");
-                    sock->err = mStatus_NoMemoryErr;
-                } else {
-                    if (!mDNSPosixTLSStart(sock)) {
-                        LogMsg("ERROR: TCPConnectCallback: TLS start failed");
-                        sock->err = mStatus_ConnFailed;
-                    }
-                }
-#else
-                // We shouldn't ever get here, because we should have already gotten an error when we created the
-                // socket.
-                LogMsg("Error: TCPSocketConnectCallback reached on TLS socket with no TLS support.");
-                sock->err = mStatus_ConnFailed;
-#endif
-            }
-            if (sock->err == 0) {
-            // The connection succeeded.
-            sock->connected = mDNStrue;
-            // Select for read events.
-            sock->events.fd = fd;
-            requestReadEvents(&sock->events, "mDNSPosix::tcpConnectCallback", TCPReadCallback, sock);
-        }
-    }
-    }
-
-    if (sock->callback)
-    {
-        sock->callback(sock, sock->context, c, sock->err);
-        // Here sock must be assumed to be invalid, in case the callback freed it.
-        return;
-    }
-}
-
-// This routine is called when the main loop detects that data is available on a socket.
-mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt, UDPSocket *sock)
-{
-    mDNSAddr senderAddr, destAddr;
-    mDNSIPPort senderPort, destPort;
-    ssize_t packetLen;
-    DNSMessage packet;
-    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(skt  >= 0);
-
-    fromLen = sizeof(from);
-    flags   = 0;
-    packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo, &ttl);
-
-    if (packetLen >= 0)
-    {
-        SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort);
-        SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, &destPort);
-
-        // 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 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_v4.ip.v4;
-            else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroup_v6.ip.v6;
-        }
-        #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.
-
-        reject = mDNSfalse;
-        if (!intf)
-        {
-            // Ignore multicasts accidentally delivered to our unicast receiving socket
-            if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1;
-        }
-        else
-        {
-            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)
-            {
-                verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d",
-                              &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
-                              &intf->coreIntf.ip, intf->intfName, intf->index, skt);
-                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
-            {
-                verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d",
-                              &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt);
-                num_pkts_accepted++;
-            }
-        }
-    }
-
-    if (packetLen >= 0)
-        mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen,
-                        &senderAddr, senderPort, &destAddr, sock == mDNSNULL ? MulticastDNSPort : sock->port, InterfaceID);
-}
-
-mDNSlocal void UDPReadCallback(int fd, void *context)
-{
-    extern mDNS mDNSStorage;
-    SocketDataReady(&mDNSStorage, NULL, fd, (UDPSocket *)context);
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSAddr_Type addrType, mDNSIPPort * port,
-                                            domainname *hostname, mDNSBool useBackgroundTrafficClass)
-{
-    TCPSocket *sock;
-    int len = sizeof (TCPSocket);
-
-    (void)useBackgroundTrafficClass;
-
-    if (hostname)
-    {
-        len += sizeof (domainname);
-    }
-    sock = mdns_malloc(len);
-
-    if (sock == NULL)
-    {
-        LogMsg("mDNSPlatformTCPSocket: no memory for socket");
-        return NULL;
-    }
-    memset(sock, 0, sizeof *sock);
-
-    if (hostname)
-    {
-        sock->hostname = (domainname *)(sock + 1);
-        LogMsg("mDNSPlatformTCPSocket: hostname %##s", hostname->c);
-        AssignDomainName(sock->hostname, hostname);
-    }
-
-    sock->events.fd = -1;
-    if (!mDNSPosixTCPSocketSetup(&sock->events.fd, addrType, port, &sock->port))
-    {
-        if (sock->events.fd != -1) close(sock->events.fd);
-        mdns_free(sock);
-        return mDNSNULL;
-    }
-
-    // Set up the other fields in the structure.
-    sock->flags = flags;
-    sock->err = mStatus_NoError;
-    sock->setup = mDNSfalse;
-    sock->connected = mDNSfalse;
-    return sock;
-}
-
-mDNSexport mStatus mDNSPlatformTCPSocketSetCallback(TCPSocket *sock, TCPConnectionCallback callback, void *context)
-{
-    sock->callback = callback;
-    sock->context = context;
-    return mStatus_NoError;
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
-{
-    TCPSocket *sock;
-
-    // In order to receive a TLS connection, use mDNSPlatformTCPListen().
-    if (flags & kTCPSocketFlags_UseTLS)
-    {
-        return mDNSNULL;
-    }
-
-    sock = mDNSPlatformMemAllocateClear(sizeof(*sock));
-    if (!sock)
-    {
-        return mDNSNULL;
-    }
-
-    sock->events.fd = fd;
-    sock->flags = flags;
-    sock->connected = mDNStrue;
-
-    return sock;
-}
-
-
-mDNSlocal void tcpListenCallback(int fd, void *context)
-{
-    TCPListener *listener = context;
-    TCPSocket *sock;
-
-    sock = mDNSPosixDoTCPListenCallback(fd, listener->addressType, listener->socketFlags,
-                                 listener->callback, listener->context);
-    if (sock != NULL)
-    {
-        requestReadEvents(&sock->events, "mDNSPosix::tcpListenCallback", TCPReadCallback, sock);
-    }
-}
-
-mDNSexport TCPListener *mDNSPlatformTCPListen(mDNSAddr_Type addrType, mDNSIPPort *port, mDNSAddr *addr,
-                                              TCPSocketFlags socketFlags, mDNSBool reuseAddr, int queueLength,
-                                              TCPAcceptedCallback callback, void *context)
-{
-    TCPListener *ret;
-    int fd = -1;
-
-    if (!mDNSPosixTCPListen(&fd, addrType, port, addr, reuseAddr, queueLength))
-    {
-        if (fd != -1)
-        {
-            close(fd);
-        }
-        return mDNSNULL;
-    }
-
-    // Allocate a listener structure
-    ret = (TCPListener *)mDNSPlatformMemAllocateClear(sizeof *ret);
-    if (ret == NULL)
-    {
-        LogMsg("mDNSPlatformTCPListen: no memory for TCPListener struct.");
-        close(fd);
-        return mDNSNULL;
-    }
-    ret->events.fd = fd;
-    ret->callback = callback;
-    ret->context = context;
-    ret->addressType = addrType;
-    ret->socketFlags = socketFlags;
-
-    // When we get a connection, mDNSPosixListenCallback will be called, and it will invoke the
-    // callback we were passed.
-    requestReadEvents(&ret->events, "tcpListenCallback", tcpListenCallback, ret);
-    return ret;
-}
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
-{
-    return sock->events.fd;
-}
-
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport,
-                                          mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context)
-{
-    int result;
-    union {
-        struct sockaddr sa;
-        struct sockaddr_in sin;
-        struct sockaddr_in6 sin6;
-    } addr;
-    socklen_t len;
-
-    sock->callback = callback;
-    sock->context = context;
-    sock->setup = mDNSfalse;
-    sock->connected = mDNSfalse;
-    sock->err = mStatus_NoError;
-
-    result = fcntl(sock->events.fd, F_GETFL, 0);
-    if (result < 0)
-    {
-        LogMsg("mDNSPlatformTCPConnect: F_GETFL failed: %s", strerror(errno));
-        return mStatus_UnknownErr;
-    }
-
-    result = fcntl(sock->events.fd, F_SETFL, result | O_NONBLOCK);
-    if (result < 0)
-    {
-        LogMsg("mDNSPlatformTCPConnect: F_SETFL failed: %s", strerror(errno));
-        return mStatus_UnknownErr;
-    }
-
-    // If we've been asked to bind to a single interface, do it.  See comment in mDNSMacOSX.c for more info.
-    if (InterfaceID)
-    {
-        PosixNetworkInterface *iface = (PosixNetworkInterface *)InterfaceID;
-#if defined(SO_BINDTODEVICE)
-        result = setsockopt(sock->events.fd,
-                            SOL_SOCKET, SO_BINDTODEVICE, iface->intfName, strlen(iface->intfName));
-        if (result < 0)
-        {
-            LogMsg("mDNSPlatformTCPConnect: SO_BINDTODEVICE failed on %s: %s", iface->intfName, strerror(errno));
-            return mStatus_BadParamErr;
-        }
-#else
-        if (dst->type == mDNSAddrType_IPv4)
-        {
-#if defined(IP_BOUND_IF)
-            result = setsockopt(sock->events.fd, IPPROTO_IP, IP_BOUND_IF, &iface->index, sizeof iface->index);
-            if (result < 0)
-            {
-                LogMsg("mDNSPlatformTCPConnect: IP_BOUND_IF failed on %s (%d): %s",
-                       iface->intfName, iface->index, strerror(errno));
-                return mStatus_BadParamErr;
-            }
-#else
-            (void)iface;
-#endif // IP_BOUND_IF
-        }
-        else
-        { // IPv6
-#if defined(IPV6_BOUND_IF)
-            result = setsockopt(sock->events.fd, IPPROTO_IPV6, IPV6_BOUND_IF, &iface->index, sizeof iface->index);
-            if (result < 0)
-            {
-                LogMsg("mDNSPlatformTCPConnect: IP_BOUND_IF failed on %s (%d): %s",
-                       iface->intfName, iface->index, strerror(errno));
-                return mStatus_BadParamErr;
-            }
-#else
-            (void)iface;
-#endif // IPV6_BOUND_IF
-        }
-#endif // SO_BINDTODEVICE
-    }
-
-    memset(&addr, 0, sizeof addr);
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        addr.sa.sa_family = AF_INET;
-        addr.sin.sin_port = dstport.NotAnInteger;
-        len = sizeof (struct sockaddr_in);
-        addr.sin.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
-    }
-    else
-    {
-        addr.sa.sa_family = AF_INET6;
-        len = sizeof (struct sockaddr_in6);
-        addr.sin6.sin6_port = dstport.NotAnInteger;
-        memcpy(&addr.sin6.sin6_addr.s6_addr, &dst->ip.v6, sizeof addr.sin6.sin6_addr.s6_addr);
-    }
-#ifndef NOT_HAVE_SA_LEN
-    addr.sa.sa_len = len;
-#endif
-
-    result = connect(sock->events.fd, (struct sockaddr *)&addr, len);
-    if (result < 0)
-    {
-        if (errno == EINPROGRESS)
-        {
-            requestWriteEvents(&sock->events, "mDNSPlatformConnect", tcpConnectCallback, sock);
-            return mStatus_ConnPending;
-        }
-        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
-        {
-            LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)",
-                    sock->events.fd, errno, strerror(errno));
-        }
-        else
-        {
-            LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s) length %d",
-                   sock->events.fd, errno, strerror(errno), len);
-        }
-        return mStatus_ConnFailed;
-    }
-
-    LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
-    return mStatus_NoError;
-}
-
-mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
-{
-    if (sock)
-    { // can sock really be NULL when this is called?
-        shutdown(sock->events.fd, SHUT_RDWR);
-        stopReadOrWriteEvents(sock->events.fd, mDNSfalse, mDNStrue,
-                              PosixEventFlag_Read | PosixEventFlag_Write);
-        close(sock->events.fd);
-        mdns_free(sock);
-    }
-}
-
-mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
-{
-    ssize_t nread;
-
-    *closed = mDNSfalse;
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifdef POSIX_HAS_TLS
-        nread = mDNSPosixTLSRead(sock, buf, buflen, closed);
-#else
-        nread = mStatus_ConnFailed;
-        *closed = mDNStrue;
-#endif
-    } else {
-        nread = mDNSPosixReadTCP(sock->events.fd, buf, buflen, closed);
-    }
-    return nread;
-}
-
-mDNSexport mDNSBool mDNSPlatformTCPWritable(TCPSocket *sock)
-{
-    fd_set w;
-    int nfds = sock->events.fd + 1;
-    int count;
-    struct timeval tv;
-
-    if (nfds > FD_SETSIZE)
-    {
-        LogMsg("ERROR: mDNSPlatformTCPWritable called on an fd that won't fit in an fd_set.");
-        return mDNStrue; // hope for the best?
-    }
-    FD_SET(sock->events.fd, &w);
-    tv.tv_sec = tv.tv_usec = 0;
-    count = select(nfds, NULL, &w, NULL, &tv);
-    if (count > 0)
-    {
-        return mDNStrue;
-    }
-    return mDNSfalse;
-}
-
-mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
-{
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifdef POSIX_HAS_TLS
-        return mDNSPosixTLSWrite(sock, msg, len);
-#else
-        return mStatus_ConnFailed;
-#endif
-    }
-    else
-    {
-        return mDNSPosixWriteTCP(sock->events.fd, msg, len);
-    }
-}
-
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNSIPPort port)
-{
-    mDNSBool randomizePort = mDNSIPPortIsZero(port);
-    UDPSocket *p = callocL("UDPSocket", sizeof(UDPSocket));
-    if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
-    p->randomizePort = randomizePort;
-    p->port = port;
-    p->events.fd = -1;
-    return(p);
-}
-
-mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
-{
-    if (sock && sock->events.fd != -1)
-    {
-        stopReadOrWriteEvents(sock->events.fd, mDNSfalse, mDNStrue,
-                              PosixEventFlag_Read | PosixEventFlag_Write);
-        close(sock->events.fd);
-        mdns_free(sock);
-    }
-}
-
-mDNSexport void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID)
-{
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-{
-    (void)msg;          // Unused
-    (void)end;          // Unused
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
-{
-    (void)tpa;          // Unused
-    (void)tha;          // Unused
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
-{
-    return(mStatus_UnsupportedErr);
-}
-
-mDNSexport void mDNSPlatformTLSTearDownCerts(void)
-{
-}
-
-mDNSexport void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason)
-{
-    (void) allowSleep;
-    (void) reason;
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - /etc/hosts support
-#endif
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;  // unused
-    (void)rr;
-    (void)result;
-}
-
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** DDNS Config Platform Functions
-#endif
-
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
-    DNameListElem **BrowseDomains, mDNSBool ackConfig)
-{
-    (void) setservers;
-    (void) setsearch;
-    (void) ackConfig;
-
-    if (fqdn         ) fqdn->c[0]      = 0;
-    if (RegDomains   ) *RegDomains     = NULL;
-    if (BrowseDomains) *BrowseDomains  = NULL;
-
-    return mDNStrue;
-}
-
-mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
-{
-    (void) v4;
-    (void) v6;
-    (void) router;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-    (void) dname;
-    (void) status;
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Init and Term
-#endif
-
-// 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;
-}
-
-// 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)
-{
-    // On Unix we have no better name than the host name, so we just use that.
-    GetUserSpecifiedRFC1034ComputerName(namelabel);
-}
-
-mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
-{
-    char line[256];
-    char nameserver[16];
-    char keyword[11];
-    int numOfServers = 0;
-    FILE *fp = fopen(filePath, "r");
-    if (fp == NULL) return -1;
-    while (fgets(line,sizeof(line),fp))
-    {
-        struct in_addr ina;
-        line[255]='\0';     // just to be safe
-        if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue;   // it will skip whitespaces
-        if (strncasecmp(keyword,"nameserver",10)) continue;
-        if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
-        {
-            mDNSAddr DNSAddr;
-            DNSAddr.type = mDNSAddrType_IPv4;
-            DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
-            mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, mDNSfalse, mDNSfalse, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
-            numOfServers++;
-        }
-    }
-    fclose(fp);
-    return (numOfServers > 0) ? 0 : -1;
-}
-
-// Searches the interface list looking for the named interface.
-// Returns a pointer to if it found, or NULL otherwise.
-mDNSlocal 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;
-}
-
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index)
-{
-    PosixNetworkInterface *intf;
-
-    assert(m != NULL);
-
-    if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
-    if (index == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
-    if (index == kDNSServiceInterfaceIndexAny      ) return(mDNSInterface_Any);
-
-    intf = (PosixNetworkInterface*)(m->HostInterfaces);
-    while ((intf != NULL) && (mDNSu32) intf->index != index)
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    return (mDNSInterfaceID) intf;
-}
-
-mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
-{
-    PosixNetworkInterface *intf;
-    (void) suppressNetworkChange; // Unused
-
-    assert(m != NULL);
-
-    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
-    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
-    if (id == mDNSInterface_Any      ) return(kDNSServiceInterfaceIndexAny);
-
-    intf = (PosixNetworkInterface*)(m->HostInterfaces);
-    while ((intf != NULL) && (mDNSInterfaceID) intf != id)
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    if (intf) return intf->index;
-
-    // If we didn't find the interface, check the RecentInterfaces list as well
-    intf = gRecentInterfaces;
-    while ((intf != NULL) && (mDNSInterfaceID) intf != id)
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    return intf ? intf->index : 0;
-}
-
-// Frees the specified PosixNetworkInterface structure. The underlying
-// interface must have already been deregistered with the mDNS core.
-mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
-{
-    int rv;
-    assert(intf != NULL);
-    if (intf->intfName != NULL) mdns_free(intf->intfName);
-    if (intf->multicastSocket4 != -1)
-    {
-        rv = close(intf->multicastSocket4);
-        assert(rv == 0);
-    }
-#if HAVE_IPV6
-    if (intf->multicastSocket6 != -1)
-    {
-        rv = close(intf->multicastSocket6);
-        assert(rv == 0);
-    }
-#endif
-
-    // Move interface to the RecentInterfaces list for a minute
-    intf->LastSeen = mDNSPlatformUTC();
-    intf->coreIntf.next = &gRecentInterfaces->coreIntf;
-    gRecentInterfaces = intf;
-}
-
-// Grab the first interface, deregister it, free it, and repeat until done.
-mDNSlocal void ClearInterfaceList(mDNS *const m)
-{
-    assert(m != NULL);
-
-    while (m->HostInterfaces)
-    {
-        PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
-        mDNS_DeregisterInterface(m, &intf->coreIntf, NormalActivation);
-        if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName);
-        FreePosixNetworkInterface(intf);
-    }
-    num_registered_interfaces = 0;
-    num_pkts_accepted = 0;
-    num_pkts_rejected = 0;
-}
-
-mDNSlocal int SetupIPv6Socket(int fd)
-{
-    int err;
-
-    #if defined(IPV6_PKTINFO)
-    err = setsockopt(fd, IPPROTO_IPV6, IPV6_2292_PKTINFO, &kOn, sizeof(kOn));
-    if (err < 0) { err = errno; perror("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
-    return err;
-}
-
-mDNSlocal int SetupIPv4Socket(int fd)
-{
-    int err;
-
-#if defined(IP_PKTINFO)                                 // Linux
-    err = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &kOn, sizeof(kOn));
-    if (err < 0) { err = errno; perror("setsockopt - IP_PKTINFO"); }
-#elif defined(IP_RECVDSTADDR) || defined(IP_RECVIF)     // BSD and Solaris
-#if defined(IP_RECVDSTADDR)
-    err = setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &kOn, sizeof(kOn));
-    if (err < 0) { err = errno; perror("setsockopt - IP_RECVDSTADDR"); }
-#endif
-#if defined(IP_RECVIF)
-    if (err == 0)
-    {
-        err = setsockopt(fd, IPPROTO_IP, IP_RECVIF, &kOn, sizeof(kOn));
-        if (err < 0) { err = errno; perror("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
-    return err;
-}
-
-// Sets up a send/receive socket.
-// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
-// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interfaceIndex, int *sktPtr)
-{
-    int err = 0;
-    const mDNSBool JoinMulticastGroup = (port.NotAnInteger != 0);
-
-    (void) interfaceIndex;  // This parameter unused on plaforms that don't have IPv6
-    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);
-#if HAVE_IPV6
-    else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
-#endif
-    else return EINVAL;
-
-    if (*sktPtr < 0) { err = errno; perror((intfAddr->sa_family == AF_INET) ? "socket AF_INET" : "socket AF_INET6"); }
-
-    // ... with a shared UDP port, if it's for multicast receiving
-    if (err == 0 && port.NotAnInteger)
-    {
-        // <rdar://problem/20946253> Suggestions from Jonny Törnbom at Axis Communications
-        // We test for SO_REUSEADDR first, as suggested by Jonny Törnbom from Axis Communications
-        // Linux kernel versions 3.9 introduces support for socket option
-        // SO_REUSEPORT, however this is not implemented the same as on *BSD
-        // systems. Linux version implements a "port hijacking" prevention
-        // mechanism, limiting processes wanting to bind to an already existing
-        // addr:port to have the same effective UID as the first who bound it. What
-        // this meant for us was that the daemon ran as one user and when for
-        // instance mDNSClientPosix was executed by another user, it wasn't allowed
-        // to bind to the socket. Our suggestion was to switch the order in which
-        // SO_REUSEPORT and SO_REUSEADDR was tested so that SO_REUSEADDR stays on
-        // top and SO_REUSEPORT to be used only if SO_REUSEADDR doesn't exist.
-        #if defined(SO_REUSEADDR) && !defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
-        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-        #elif defined(SO_REUSEPORT)
-        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
-        #else
-            #error This platform has no way to avoid address busy errors on multicast.
-        #endif
-        if (err < 0) { err = errno; perror("setsockopt - SO_REUSExxxx"); }
-
-#if TARGET_OS_MAC
-        // Enable inbound packets on IFEF_AWDL interface.
-        // Only done for multicast sockets, since we don't expect unicast socket operations
-        // on the IFEF_AWDL interface. Operation is a no-op for other interface types.
-        #ifndef SO_RECV_ANYIF
-        #define SO_RECV_ANYIF   0x1104      /* unrestricted inbound processing */
-        #endif
-        if (setsockopt(*sktPtr, SOL_SOCKET, SO_RECV_ANYIF, &kOn, sizeof(kOn)) < 0) perror("setsockopt - SO_RECV_ANYIF");
-#endif
-    }
-
-    // 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)
-        {
-            err = SetupIPv4Socket(*sktPtr);
-        }
-    #if defined(IP_RECVTTL)                                 // Linux
-        if (err == 0)
-        {
-            setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
-            // We no longer depend on being able to get the received TTL, so don't worry if the option fails
-        }
-    #endif
-
-        // Add multicast group membership on this interface
-        if (err == 0 && JoinMulticastGroup)
-        {
-            imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.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; perror("setsockopt - IP_ADD_MEMBERSHIP"); }
-        }
-
-        // Specify outgoing interface too
-        if (err == 0 && JoinMulticastGroup)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
-            if (err < 0) { err = errno; perror("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; perror("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; perror("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; perror("bind"); fflush(stderr); }
-        }
-    }     // endif (intfAddr->sa_family == AF_INET)
-
-#if HAVE_IPV6
-    else if (intfAddr->sa_family == AF_INET6)
-    {
-        struct ipv6_mreq imr6;
-        struct sockaddr_in6 bindAddr6;
-        if (err == 0) {
-            err = SetupIPv6Socket(*sktPtr);
-        }
-    #if defined(IPV6_HOPLIMIT)
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_HOPLIMIT, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_HOPLIMIT"); }
-        }
-    #endif
-
-        // Add multicast group membership on this interface
-        if (err == 0 && JoinMulticastGroup)
-        {
-            imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
-            imr6.ipv6mr_interface       = interfaceIndex;
-            //LogMsg("Joining %.16a on %d", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
-            if (err < 0)
-            {
-                err = errno;
-                verbosedebugf("IPV6_JOIN_GROUP %.16a on %d failed.\n", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
-                perror("setsockopt - IPV6_JOIN_GROUP");
-            }
-        }
-
-        // Specify outgoing interface too
-        if (err == 0 && JoinMulticastGroup)
-        {
-            u_int multicast_if = interfaceIndex;
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_IF"); }
-        }
-
-        // 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; perror("setsockopt - IPV6_V6ONLY"); }
-        }
-
-        // 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; perror("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; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
-        }
-
-        // 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        = 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; perror("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)
-    {
-        int rv;
-        rv = close(*sktPtr);
-        assert(rv == 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.
-mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask,
-    const mDNSu8 *intfHaddr, mDNSu16 intfHlen, const char *intfName, int intfIndex)
-{
-    int err = 0;
-    PosixNetworkInterface *intf;
-    PosixNetworkInterface *alias = NULL;
-
-    assert(m != NULL);
-    assert(intfAddr != NULL);
-    assert(intfName != NULL);
-    assert(intfHaddr != NULL || intfHlen == 0);
-    assert(intfMask != NULL);
-
-    // Allocate the interface structure itself.
-    intf = (PosixNetworkInterface*)mdns_calloc(1, sizeof(*intf));
-    if (intf == NULL) { assert(0); err = ENOMEM; }
-
-    // And make a copy of the intfName.
-    if (err == 0)
-    {
-#ifdef LINUX
-        char *s;
-        int len;
-        s = strchr(intfName, ':');
-        if (s != NULL)
-        {
-            len = (s - intfName) + 1;
-        }
-        else
-        {
-            len = strlen(intfName) + 1;
-        }
-        intf->intfName = malloc(len);
-        if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
-        memcpy(intf->intfName, intfName, len - 1);
-        intfName[len - 1] = 0;
-#else
-        intf->intfName = mdns_strdup(intfName);
-        if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
-#endif
-    }
-
-    if (err == 0)
-    {
-        // Set up the fields required by the mDNS core.
-        SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
-        SockAddrTomDNSAddr(intfMask, &intf->coreIntf.mask, NULL);
-        if (intfHlen == sizeof(intf->coreIntf.MAC.b))
-        {
-            mDNSPlatformMemCopy(intf->coreIntf.MAC.b, intfHaddr, sizeof(intf->coreIntf.MAC.b));
-
-            // Configure primary MAC address.
-            // Ideally, we would pick the default route interface with the lowest metric (see mDNSWin32).
-            // For now, simply assume the first one that we find is the primary one (see mDNSMacOSX).
-            if (mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr))
-                mDNSPlatformMemCopy(&m->PrimaryMAC, &intf->coreIntf.MAC, sizeof(m->PrimaryMAC));
-        }
-
-        //LogMsg("SetupOneInterface: %#a %#a",  &intf->coreIntf.ip,  &intf->coreIntf.mask);
-        mDNSPlatformStrLCopy(intf->coreIntf.ifname, intfName, sizeof(intf->coreIntf.ifname));
-        intf->coreIntf.ifname[sizeof(intf->coreIntf.ifname)-1] = 0;
-
-        intf->coreIntf.Advertise = m->AdvertiseLocalAddresses;
-        intf->coreIntf.McastTxRx = mDNStrue;
-
-        // Set up the extra fields in PosixNetworkInterface.
-        assert(intf->intfName != NULL);         // intf->intfName already set up above
-        intf->index                = intfIndex;
-        intf->multicastSocket4     = -1;
-#if HAVE_IPV6
-        intf->multicastSocket6     = -1;
-#endif
-        alias                      = SearchForInterfaceByName(m, intf->intfName);
-        if (alias == NULL) alias   = intf;
-        intf->coreIntf.InterfaceID = (mDNSInterfaceID)alias;
-
-        if (alias != intf)
-            debugf("SetupOneInterface: %s %#a is an alias of %#a", intfName, &intf->coreIntf.ip, &alias->coreIntf.ip);
-    }
-
-    // Set up the multicast socket
-    if (err == 0)
-    {
-        if (alias->multicastSocket4 == -1 && intfAddr->sa_family == AF_INET)
-            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket4);
-#if HAVE_IPV6
-        else if (alias->multicastSocket6 == -1 && intfAddr->sa_family == AF_INET6)
-            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket6);
-#endif
-    }
-
-    // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
-    // and skip the probe phase of the probe/announce packet sequence.
-    intf->coreIntf.DirectLink = mDNSfalse;
-#ifdef DIRECTLINK_INTERFACE_NAME
-    if (strcmp(intfName, STRINGIFY(DIRECTLINK_INTERFACE_NAME)) == 0)
-        intf->coreIntf.DirectLink = mDNStrue;
-#endif
-    intf->coreIntf.SupportsUnicastMDNSResponse = mDNStrue;
-
-    // The interface is all ready to go, let's register it with the mDNS core.
-    if (err == 0)
-        err = mDNS_RegisterInterface(m, &intf->coreIntf, NormalActivation);
-
-    // Clean up.
-    if (err == 0)
-    {
-        num_registered_interfaces++;
-        debugf("SetupOneInterface: %s %#a Registered", intf->intfName, &intf->coreIntf.ip);
-        if (gMDNSPlatformPosixVerboseLevel > 0)
-            fprintf(stderr, "Registered interface %s\n", intf->intfName);
-    }
-    else
-    {
-        // Use intfName instead of intf->intfName in the next line to avoid dereferencing NULL.
-        debugf("SetupOneInterface: %s %#a failed to register %d", intfName, &intf->coreIntf.ip, err);
-        if (intf) { FreePosixNetworkInterface(intf); intf = NULL; }
-    }
-
-    assert((err == 0) == (intf != NULL));
-
-    return err;
-}
-
-// Call get_ifi_info() to obtain a list of active interfaces and call SetupOneInterface() on each one.
-mDNSlocal int SetupInterfaceList(mDNS *const m)
-{
-    mDNSBool foundav4       = mDNSfalse;
-    int err            = 0;
-    struct ifaddrs *intfList;
-    struct ifaddrs *firstLoopback = NULL;
-    int firstLoopbackIndex = 0;
-
-    assert(m != NULL);
-    debugf("SetupInterfaceList");
-
-    if (getifaddrs(&intfList) < 0)
-    {
-        err = errno;
-    }
-    if (intfList == NULL) err = ENOENT;
-
-    if (err == 0)
-    {
-        struct ifaddrs *i = intfList;
-        while (i)
-        {
-            if (     i->ifa_addr != NULL &&
-                     ((i->ifa_addr->sa_family == AF_INET)
-#if HAVE_IPV6
-                      || (i->ifa_addr->sa_family == AF_INET6)
-#endif
-                      ) &&  (i->ifa_flags & IFF_UP) && !(i->ifa_flags & IFF_POINTOPOINT))
-            {
-                int ifIndex = if_nametoindex(i->ifa_name);
-                if (ifIndex == 0)
-                {
-                    continue;
-                }
-                if (i->ifa_flags & IFF_LOOPBACK)
-                {
-                    if (firstLoopback == NULL)
-                    {
-                        firstLoopback = i;
-                        firstLoopbackIndex = ifIndex;
-                    }
-                }
-                else
-                {
-#define ethernet_addr_len 6
-                    uint8_t hwaddr[ethernet_addr_len];
-                    int hwaddr_len = 0;
-
-#if defined(TARGET_OS_LINUX) && TARGET_OS_LINUX
-                    struct ifreq ifr;
-                    int sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
-                    if (sockfd >= 0)
-                    {
-                        /* Add hardware address */
-                        memcpy(ifr.ifr_name, i->ifa_name, IFNAMSIZ);
-                        if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != -1)
-                        {
-                            if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)
-                            {
-                                memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ethernet_addr_len);
-                                hwaddr_len = ethernet_addr_len;
-                            }
-                        }
-                        close(sockfd);
-                    }
-                    else
-                    {
-                        memset(hwaddr, 0, sizeof(hwaddr));
-                    }
-#endif // TARGET_OS_LINUX
-
-#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
-                    for (struct ifaddrs *hw_scan = intfList; hw_scan != NULL; hw_scan = hw_scan->ifa_next)
-                    {
-                        if (hw_scan->ifa_addr != NULL &&
-                            hw_scan->ifa_addr->sa_family == AF_LINK && !strcmp(hw_scan->ifa_name, i->ifa_name))
-                        {
-                            struct sockaddr_dl *sdl = (struct sockaddr_dl *)hw_scan->ifa_addr;
-                            if (sdl->sdl_alen == ethernet_addr_len)
-                            {
-                                hwaddr_len = ethernet_addr_len;
-                                memcpy(hwaddr, LLADDR(sdl), hwaddr_len);
-                            }
-                            break;
-                        }
-                    }
-#endif
-                    if (SetupOneInterface(m, i->ifa_addr, i->ifa_netmask,
-                                          hwaddr, hwaddr_len, i->ifa_name, ifIndex) == 0)
-                    {
-                        if (i->ifa_addr->sa_family == AF_INET)
-                            foundav4 = mDNStrue;
-                    }
-                }
-            }
-            i = i->ifa_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->ifa_addr, firstLoopback->ifa_netmask,
-                NULL, 0, firstLoopback->ifa_name, firstLoopbackIndex);
-    }
-
-    // Clean up.
-    if (intfList != NULL) freeifaddrs(intfList);
-
-    // Clean up any interfaces that have been hanging around on the RecentInterfaces list for more than a minute
-    PosixNetworkInterface **ri = &gRecentInterfaces;
-    const mDNSs32 utc = mDNSPlatformUTC();
-    while (*ri)
-    {
-        PosixNetworkInterface *pi = *ri;
-        if (utc - pi->LastSeen < 60) ri = (PosixNetworkInterface **)&pi->coreIntf.next;
-        else { *ri = (PosixNetworkInterface *)pi->coreIntf.next; mdns_free(pi); }
-    }
-
-    return err;
-}
-
-#if USES_NETLINK
-
-// See <http://www.faqs.org/rfcs/rfc3549.html> for a description of NetLink
-
-// Open a socket that will receive interface change notifications
-mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
-{
-    mStatus err = mStatus_NoError;
-    struct sockaddr_nl snl;
-    int sock;
-    int ret;
-
-    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-    if (sock < 0)
-        return errno;
-
-    // Configure read to be non-blocking because inbound msg size is not known in advance
-    (void) fcntl(sock, F_SETFL, O_NONBLOCK);
-
-    /* Subscribe the socket to Link & IP addr notifications. */
-    mDNSPlatformMemZero(&snl, sizeof snl);
-    snl.nl_family = AF_NETLINK;
-    snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
-    ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
-    if (0 == ret)
-        *pFD = sock;
-    else
-        err = errno;
-
-    return err;
-}
-
-#if MDNS_DEBUGMSGS
-mDNSlocal void      PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
-{
-    const char *kNLMsgTypes[] = { "", "NLMSG_NOOP", "NLMSG_ERROR", "NLMSG_DONE", "NLMSG_OVERRUN" };
-    const char *kNLRtMsgTypes[] = { "RTM_NEWLINK", "RTM_DELLINK", "RTM_GETLINK", "RTM_NEWADDR", "RTM_DELADDR", "RTM_GETADDR" };
-
-    printf("nlmsghdr len=%d, type=%s, flags=0x%x\n", pNLMsg->nlmsg_len,
-           pNLMsg->nlmsg_type < RTM_BASE ? kNLMsgTypes[pNLMsg->nlmsg_type] : kNLRtMsgTypes[pNLMsg->nlmsg_type - RTM_BASE],
-           pNLMsg->nlmsg_flags);
-
-    if (RTM_NEWLINK <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETLINK)
-    {
-        struct ifinfomsg    *pIfInfo = (struct ifinfomsg*) NLMSG_DATA(pNLMsg);
-        printf("ifinfomsg family=%d, type=%d, index=%d, flags=0x%x, change=0x%x\n", pIfInfo->ifi_family,
-               pIfInfo->ifi_type, pIfInfo->ifi_index, pIfInfo->ifi_flags, pIfInfo->ifi_change);
-
-    }
-    else if (RTM_NEWADDR <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETADDR)
-    {
-        struct ifaddrmsg    *pIfAddr = (struct ifaddrmsg*) NLMSG_DATA(pNLMsg);
-        printf("ifaddrmsg family=%d, index=%d, flags=0x%x\n", pIfAddr->ifa_family,
-               pIfAddr->ifa_index, pIfAddr->ifa_flags);
-    }
-    printf("\n");
-}
-#endif
-
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
-// Read through the messages on sd and if any indicate that any interface records should
-// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
-{
-    ssize_t readCount;
-    char buff[4096];
-    struct nlmsghdr         *pNLMsg = (struct nlmsghdr*) buff;
-    mDNSu32 result = 0;
-
-    // The structure here is more complex than it really ought to be because,
-    // unfortunately, there's no good way to size a buffer in advance large
-    // enough to hold all pending data and so avoid message fragmentation.
-    // (Note that FIONREAD is not supported on AF_NETLINK.)
-
-    readCount = read(sd, buff, sizeof buff);
-    while (1)
-    {
-        // Make sure we've got an entire nlmsghdr in the buffer, and payload, too.
-        // If not, discard already-processed messages in buffer and read more data.
-        if (((char*) &pNLMsg[1] > (buff + readCount)) ||    // i.e. *pNLMsg extends off end of buffer
-            ((char*) pNLMsg + pNLMsg->nlmsg_len > (buff + readCount)))
-        {
-            if (buff < (char*) pNLMsg)      // we have space to shuffle
-            {
-                // discard processed data
-                readCount -= ((char*) pNLMsg - buff);
-                memmove(buff, pNLMsg, readCount);
-                pNLMsg = (struct nlmsghdr*) buff;
-
-                // read more data
-                readCount += read(sd, buff + readCount, sizeof buff - readCount);
-                continue;                   // spin around and revalidate with new readCount
-            }
-            else
-                break;  // Otherwise message does not fit in buffer
-        }
-
-#if MDNS_DEBUGMSGS
-        PrintNetLinkMsg(pNLMsg);
-#endif
-
-        // Process the NetLink message
-        if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
-            result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
-        else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
-            result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
-
-        // Advance pNLMsg to the next message in the buffer
-        if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
-        {
-            ssize_t len = readCount - ((char*)pNLMsg - buff);
-            pNLMsg = NLMSG_NEXT(pNLMsg, len);
-        }
-        else
-            break;  // all done!
-    }
-
-    return result;
-}
-
-#else // USES_NETLINK
-
-// Open a socket that will receive interface change notifications
-mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
-{
-    *pFD = socket(AF_ROUTE, SOCK_RAW, 0);
-
-    if (*pFD < 0)
-        return mStatus_UnknownErr;
-
-    // Configure read to be non-blocking because inbound msg size is not known in advance
-    (void) fcntl(*pFD, F_SETFL, O_NONBLOCK);
-
-    return mStatus_NoError;
-}
-
-#if MDNS_DEBUGMSGS
-mDNSlocal void      PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
-{
-    const char *kRSMsgTypes[] = { "", "RTM_ADD", "RTM_DELETE", "RTM_CHANGE", "RTM_GET", "RTM_LOSING",
-                                  "RTM_REDIRECT", "RTM_MISS", "RTM_LOCK", "RTM_OLDADD", "RTM_OLDDEL", "RTM_RESOLVE",
-                                  "RTM_NEWADDR", "RTM_DELADDR", "RTM_IFINFO", "RTM_NEWMADDR", "RTM_DELMADDR" };
-
-    int index = pRSMsg->ifam_type == RTM_IFINFO ? ((struct if_msghdr*) pRSMsg)->ifm_index : pRSMsg->ifam_index;
-
-    printf("ifa_msghdr len=%d, type=%s, index=%d\n", pRSMsg->ifam_msglen, kRSMsgTypes[pRSMsg->ifam_type], index);
-}
-#endif
-
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
-// Read through the messages on sd and if any indicate that any interface records should
-// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
-{
-    ssize_t readCount;
-    char buff[4096];
-    struct ifa_msghdr       *pRSMsg = (struct ifa_msghdr*) buff;
-    mDNSu32 result = 0;
-
-    readCount = read(sd, buff, sizeof buff);
-    if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
-        return mStatus_UnsupportedErr;      // cannot decipher message
-
-#if MDNS_DEBUGMSGS
-    PrintRoutingSocketMsg(pRSMsg);
-#endif
-
-    // Process the message
-    if (pRSMsg->ifam_type == RTM_NEWADDR || pRSMsg->ifam_type == RTM_DELADDR ||
-        pRSMsg->ifam_type == RTM_IFINFO)
-    {
-        if (pRSMsg->ifam_type == RTM_IFINFO)
-            result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
-        else
-            result |= 1 << pRSMsg->ifam_index;
-    }
-
-    return result;
-}
-
-#endif // USES_NETLINK
-
-// Called when data appears on interface change notification socket
-mDNSlocal void InterfaceChangeCallback(int fd, void *context)
-{
-    IfChangeRec     *pChgRec = (IfChangeRec*) context;
-    fd_set readFDs;
-    mDNSu32 changedInterfaces = 0;
-    struct timeval zeroTimeout = { 0, 0 };
-
-    (void)fd; // Unused
-
-    FD_ZERO(&readFDs);
-    FD_SET(pChgRec->NotifySD, &readFDs);
-
-    do
-    {
-        changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
-    }
-    while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
-
-    // Currently we rebuild the entire interface list whenever any interface change is
-    // detected. If this ever proves to be a performance issue in a multi-homed
-    // configuration, more care should be paid to changedInterfaces.
-    if (changedInterfaces)
-        mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
-}
-
-// Register with either a Routing Socket or RtNetLink to listen for interface changes.
-mDNSlocal mStatus WatchForInterfaceChange(mDNS *const m)
-{
-    mStatus err;
-    IfChangeRec *pChgRec;
-
-    pChgRec = (IfChangeRec*) mDNSPlatformMemAllocateClear(sizeof *pChgRec);
-    if (pChgRec == NULL)
-        return mStatus_NoMemoryErr;
-
-    pChgRec->mDNS = m;
-    err = OpenIfNotifySocket(&pChgRec->NotifySD);
-    if (err == 0)
-        err = mDNSPosixAddFDToEventLoop(pChgRec->NotifySD, InterfaceChangeCallback, pChgRec);
-    if (err)
-        mDNSPlatformMemFree(pChgRec);
-
-    return err;
-}
-
-// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
-// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
-// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
-mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
-{
-    int err;
-    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    struct sockaddr_in s5353;
-    s5353.sin_family      = AF_INET;
-    s5353.sin_port        = MulticastDNSPort.NotAnInteger;
-    s5353.sin_addr.s_addr = 0;
-    err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
-    close(s);
-    if (err) debugf("No unicast UDP responses");
-    else debugf("Unicast UDP responses okay");
-    return(err == 0);
-}
-
-// mDNS core calls this routine to initialise the platform-specific data.
-mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
-{
-    int err = 0;
-    struct sockaddr sa;
-    assert(m != NULL);
-
-    if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
-
-    // 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, "Computer");
-
-    // Set up the RFC 1034-compliant label
-    m->hostlabel.c[0] = 0;
-    GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
-    if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Computer");
-
-    mDNS_SetFQDN(m);
-
-    sa.sa_family = AF_INET;
-    m->p->unicastSocket4 = -1;
-    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket4);
-#if HAVE_IPV6
-    sa.sa_family = AF_INET6;
-    m->p->unicastSocket6 = -1;
-    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
-#endif
-
-    // Tell mDNS core about the network interfaces on this machine.
-    if (err == mStatus_NoError) err = SetupInterfaceList(m);
-
-    // Tell mDNS core about DNS Servers
-    mDNS_Lock(m);
-    if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE);
-    mDNS_Unlock(m);
-
-    if (err == mStatus_NoError)
-    {
-        err = WatchForInterfaceChange(m);
-        // Failure to observe interface changes is non-fatal.
-        if (err != mStatus_NoError)
-        {
-            fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", getpid(), err);
-            err = mStatus_NoError;
-        }
-    }
-
-#if POSIX_HAS_TLS
-    // Use the SRP TLS shim.
-    mDNSPosixTLSInit();
-#endif
-
-    // 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 == mStatus_NoError)
-        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)
-{
-    int rv;
-    assert(m != NULL);
-    ClearInterfaceList(m);
-    if (m->p->unicastSocket4 != -1)
-    {
-        rv = close(m->p->unicastSocket4);
-        assert(rv == 0);
-    }
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1)
-    {
-        rv = close(m->p->unicastSocket6);
-        assert(rv == 0);
-    }
-#endif
-}
-
-// This is used internally by InterfaceChangeCallback.
-// It's also exported so that the Standalone Responder (mDNSResponderPosix)
-// can call it in response to a SIGHUP (mainly for debugging purposes).
-mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
-{
-    int err;
-    // This is a pretty heavyweight way to process interface changes --
-    // destroying the entire interface list and then making fresh one from scratch.
-    // We should make it like the OS X version, which leaves unchanged interfaces alone.
-    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
-
-mDNSexport void    mDNSPlatformStrLCopy(void *dst, const void *src, mDNSu32 len)
-{
-    mdns_strlcpy((char *)dst, (const char *)src, len);
-}
-
-// 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((const 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(void *dst, const void *src, 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 *dst, const void *src, mDNSu32 len)
-{
-    return memcmp(dst, src, len) == 0;
-}
-
-// If the caller wants to know the exact return of memcmp, then use this instead
-// of mDNSPlatformMemSame
-mDNSexport int mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len)
-{
-    return (memcmp(dst, src, len));
-}
-
-mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-    return (qsort(base, nel, width, compar));
-}
-
-// Proxy stub functions
-mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-    (void) q;
-    (void) h;
-    (void) msg;
-    (void) ptr;
-    (void) limit;
-
-    return ptr;
-}
-
-// 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);
-}
-
-#if !MDNS_MALLOC_DEBUGGING
-mDNSexport void *mDNSPlatformMemAllocate(mDNSu32 len)      { return(mallocL("mDNSPlatformMemAllocate", len)); }
-mDNSexport void *mDNSPlatformMemAllocateClear(mDNSu32 len) { return(callocL("mDNSPlatformMemAllocateClear", len)); }
-mDNSexport void  mDNSPlatformMemFree    (void *mem)        {          freeL("mDNSPlatformMemFree", mem); }
-#endif
-
-#if _PLATFORM_HAS_STRONG_PRNG_
-mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
-{
-    return(arc4random());
-}
-#else
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return(tv.tv_usec);
-}
-#endif
-
-mDNSexport mDNSs32 mDNSPlatformOneSecond = 1024;
-
-mDNSexport mStatus mDNSPlatformTimeInit(void)
-{
-    // 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
-    return(mStatus_NoError);
-}
-
-mDNSexport mDNSs32 mDNSPlatformRawTime(void)
-{
-    struct timespec tm;
-    int ret = clock_gettime(CLOCK_MONOTONIC, &tm);
-    assert(ret == 0); // This call will only fail if the number of seconds does not fit in an object of type time_t.
-
-    // tm.tv_sec is seconds since some unspecified starting point (it is usually the system start up time)
-    // tm.tv_nsec is nanoseconds since the start of this second (i.e. values 0 to 999999999)
-    // We use the lower 22 bits of tm.tv_sec for the top 22 bits of our result
-    // and we multiply tm.tv_nsec by 2 / 1953125 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 (mDNSs32)(((tm.tv_sec << 10) | (tm.tv_nsec * 2 / 1953125)));
-}
-
-mDNSexport mDNSs32 mDNSPlatformUTC(void)
-{
-    return time(NULL);
-}
-
-// This should return elapsed time in seconds since boot. Posix doesn't have an API for this, so we currently assume
-// that time() doesn't get adjusted, which isn't the case.
-mDNSexport mDNSs32 mDNSPlatformContinuousTimeSeconds(void)
-{
-#ifdef CLOCK_BOOTTIME
-    // CLOCK_BOOTTIME is a Linux-specific constant that indicates a monotonic time that includes time asleep
-    const int clockid = CLOCK_BOOTTIME;
-#else
-    // On MacOS, CLOCK_MONOTONIC is a monotonic time that includes time asleep. However, this may not be the case
-    // on other Posix systems, since the POSIX specification doesn't say one way or the other. E.g. on Linux
-    // time asleep is not accounted for, which is why we prefer CLOCK_BOOTTIME on Linux.
-    const int clockid = CLOCK_MONOTONIC;
-#endif
-    struct timespec tm;
-    int ret = clock_gettime(clockid, &tm);
-    assert(ret == 0); // This call will only fail if the number of seconds does not fit in an object of type time_t.
-
-    // We are only accurate to the second.
-    return (mDNSs32)tm.tv_sec;
-}
-
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
-{
-    (void) InterfaceID;
-    (void) EthAddr;
-    (void) IPAddr;
-    (void) iteration;
-}
-
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
-{
-    (void) rr;
-    (void) InterfaceID;
-
-    return 1;
-}
-
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-    (void) q;
-    (void) intf;
-
-    return 1;
-}
-
-// Used for debugging purposes. For now, just set the buffer to zero
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-{
-    (void) te;
-    if (bufsize) buf[0] = 0;
-}
-
-mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
-{
-    (void) sadd;    // Unused
-    (void) dadd;    // Unused
-    (void) lport;   // Unused
-    (void) rport;   // Unused
-    (void) seq;     // Unused
-    (void) ack;     // Unused
-    (void) win;     // Unused
-}
-
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
-{
-    (void) laddr;   // Unused
-    (void) raddr;   // Unused
-    (void) lport;   // Unused
-    (void) rport;   // Unused
-    (void) mti;     // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr)
-{
-    (void) raddr; // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
-{
-    (void) spsaddr; // Unused
-    (void) ifname;  // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus    mDNSPlatformClearSPSData(void)
-{
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length)
-{
-    (void) ifname; // Unused
-    (void) msg;    // Unused
-    (void) length; // Unused
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-    (void) sock; // unused
-
-    return (mDNSu16)-1;
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-    (void) InterfaceID; // unused
-
-    return mDNSfalse;
-}
-
-mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q)
-{
-    (void) sock;
-    (void) transType;
-    (void) addrType;
-    (void) q;
-}
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-{
-    return 0;
-}
-
-mDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
-{
-    if (*nfds < s + 1) *nfds = s + 1;
-    FD_SET(s, readfds);
-}
-
-mDNSlocal void mDNSPosixGetFDSetForSelect(mDNS *m, int *nfds, fd_set *readfds, fd_set *writefds)
-{
-    int numFDs = *nfds;
-    PosixEventSource *iSource;
-
-    // 2. Build our list of active file descriptors
-    PosixNetworkInterface *info = (PosixNetworkInterface *)(m->HostInterfaces);
-    if (m->p->unicastSocket4 != -1) mDNSPosixAddToFDSet(&numFDs, readfds, m->p->unicastSocket4);
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1) mDNSPosixAddToFDSet(&numFDs, readfds, m->p->unicastSocket6);
-#endif
-    while (info)
-    {
-        if (info->multicastSocket4 != -1) mDNSPosixAddToFDSet(&numFDs, readfds, info->multicastSocket4);
-#if HAVE_IPV6
-        if (info->multicastSocket6 != -1) mDNSPosixAddToFDSet(&numFDs, readfds, info->multicastSocket6);
-#endif
-        info = (PosixNetworkInterface *)(info->coreIntf.next);
-    }
-
-    // Copy over the event fds.   We have to do it this way because client-provided event loops expect
-    // to initialize their FD sets first and then call mDNSPosixGetFDSet()
-    for (iSource = gEventSources; iSource; iSource = iSource->next)
-    {
-        if (iSource->readCallback != NULL)
-            FD_SET(iSource->fd, readfds);
-        if (iSource->writeCallback != NULL)
-            FD_SET(iSource->fd, writefds);
-        if (numFDs <= iSource->fd)
-            numFDs = iSource->fd + 1;
-    }
-    *nfds = numFDs;
-}
-
-mDNSexport void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, fd_set *writefds, 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);
-
-    // 3. Calculate the time remaining to the next scheduled event (in struct timeval format)
-    ticks = nextevent - mDNS_TimeNow(m);
-    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;
-
-    mDNSPosixGetFDSetForSelect(m, nfds, readfds, writefds);
-}
-
-mDNSexport void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds, fd_set *writefds)
-{
-    PosixNetworkInterface *info;
-    PosixEventSource    *iSource;
-    assert(m       != NULL);
-    assert(readfds != NULL);
-    info = (PosixNetworkInterface *)(m->HostInterfaces);
-
-    if (m->p->unicastSocket4 != -1 && FD_ISSET(m->p->unicastSocket4, readfds))
-    {
-        FD_CLR(m->p->unicastSocket4, readfds);
-        SocketDataReady(m, NULL, m->p->unicastSocket4, NULL);
-    }
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1 && FD_ISSET(m->p->unicastSocket6, readfds))
-    {
-        FD_CLR(m->p->unicastSocket6, readfds);
-        SocketDataReady(m, NULL, m->p->unicastSocket6, NULL);
-    }
-#endif
-
-    while (info)
-    {
-        if (info->multicastSocket4 != -1 && FD_ISSET(info->multicastSocket4, readfds))
-        {
-            FD_CLR(info->multicastSocket4, readfds);
-            SocketDataReady(m, info, info->multicastSocket4, NULL);
-        }
-#if HAVE_IPV6
-        if (info->multicastSocket6 != -1 && FD_ISSET(info->multicastSocket6, readfds))
-        {
-            FD_CLR(info->multicastSocket6, readfds);
-            SocketDataReady(m, info, info->multicastSocket6, NULL);
-        }
-#endif
-        info = (PosixNetworkInterface *)(info->coreIntf.next);
-    }
-
-    // Now process routing socket events, discovery relay events and anything else of that ilk.
-    for (iSource = gEventSources; iSource; iSource = iSource->next)
-    {
-        if (iSource->readCallback != NULL && FD_ISSET(iSource->fd, readfds))
-        {
-            iSource->readCallback(iSource->fd, iSource->readContext);
-            break;  // in case callback removed elements from gEventSources
-        }
-        else if (iSource->writeCallback != NULL && FD_ISSET(iSource->fd, writefds))
-        {
-            mDNSPosixEventCallback writeCallback = iSource->writeCallback;
-            // Write events are one-shot: to get another event, the consumer has to put in a new request.
-            // We reset this before calling the callback just in case the callback requests another write
-            // callback, or deletes the event context from the list.
-            iSource->writeCallback = NULL;
-            writeCallback(iSource->fd, iSource->writeContext);
-            break;  // in case callback removed elements from gEventSources
-        }
-    }
-}
-
-mDNSu32 mDNSPlatformEventContextSize = sizeof (PosixEventSource);
-
-mDNSlocal void requestIOEvents(PosixEventSource *newSource, const char *taskName,
-                                  mDNSPosixEventCallback callback, void *context, int flag)
-{
-    PosixEventSource **epp = &gEventSources;
-
-    if (newSource->fd >= (int) FD_SETSIZE || newSource->fd < 0)
-    {
-        LogMsg("requestIOEvents called with fd %d > FD_SETSIZE %d.", newSource->fd, FD_SETSIZE);
-        assert(0);
-    }
-    if (callback == NULL)
-    {
-        LogMsg("requestIOEvents called no callback.", newSource->fd, FD_SETSIZE);
-        assert(0);
-    }
-
-    // See if this event context is already on the list; if it is, no need to scan the list.
-    if (!(newSource->flags & PosixEventFlag_OnList))
-    {
-        while (*epp)
-        {
-            // This should never happen.
-            if (newSource == *epp)
-            {
-                LogMsg("Event context marked not on list but is on list.");
-                assert(0);
-            }
-            epp = &(*epp)->next;
-        }
-        if (*epp == NULL)
-        {
-            *epp = newSource;
-            newSource->next = NULL;
-            newSource->flags = PosixEventFlag_OnList;
-        }
-    }
-
-    if (flag & PosixEventFlag_Read)
-    {
-        newSource->readCallback = callback;
-        newSource->readContext = context;
-        newSource->flags |= PosixEventFlag_Read;
-        newSource->readTaskName = taskName;
-    }
-    if (flag & PosixEventFlag_Write)
-    {
-        newSource->writeCallback = callback;
-        newSource->writeContext = context;
-        newSource->flags |= PosixEventFlag_Write;
-        newSource->writeTaskName = taskName;
-    }
-}
-
-mDNSlocal void requestReadEvents(PosixEventSource *eventSource,
-                                    const char *taskName, mDNSPosixEventCallback callback, void *context)
-{
-    requestIOEvents(eventSource, taskName, callback, context, PosixEventFlag_Read);
-}
-
-mDNSlocal void requestWriteEvents(PosixEventSource *eventSource,
-                                     const char *taskName, mDNSPosixEventCallback callback, void *context)
-{
-    requestIOEvents(eventSource, taskName, callback, context, PosixEventFlag_Write);
-}
-
-// Remove a file descriptor from the set that mDNSPosixRunEventLoopOnce() listens to.
-mDNSlocal mStatus stopReadOrWriteEvents(int fd, mDNSBool freeContext, mDNSBool removeContext, int flags)
-{
-    PosixEventSource *iSource, **epp = &gEventSources;
-
-    while (*epp)
-    {
-        iSource = *epp;
-        if (fd == iSource->fd)
-        {
-            if (flags & PosixEventFlag_Read)
-            {
-                iSource->readCallback = NULL;
-                iSource->readContext = NULL;
-            }
-            if (flags & PosixEventFlag_Write)
-            {
-                iSource->writeCallback = NULL;
-                iSource->writeContext = NULL;
-            }
-            if (iSource->writeCallback == NULL && iSource->readCallback == NULL)
-            {
-                if (removeContext || freeContext)
-                    *epp = iSource->next;
-                if (freeContext)
-                    mdns_free(iSource);
-            }
-            return mStatus_NoError;
-        }
-        epp = &(*epp)->next;
-    }
-    return mStatus_NoSuchNameErr;
-}
-
-// Some of the mDNSPosix client code relies on being able to add FDs to the event loop without
-// providing storage for the event-related info.   mDNSPosixAddFDToEventLoop and
-// mDNSPosixRemoveFDFromEventLoop handle the event structure storage automatically.
-mStatus mDNSPosixAddFDToEventLoop(int fd, mDNSPosixEventCallback callback, void *context)
-{
-    PosixEventSource *newSource;
-
-    newSource = (PosixEventSource*) mdns_malloc(sizeof *newSource);
-    if (NULL == newSource)
-        return mStatus_NoMemoryErr;
-    memset(newSource, 0, sizeof *newSource);
-    newSource->fd = fd;
-
-    requestReadEvents(newSource, "mDNSPosixAddFDToEventLoop", callback, context);
-    return mStatus_NoError;
-}
-
-mStatus mDNSPosixRemoveFDFromEventLoop(int fd)
-{
-    return stopReadOrWriteEvents(fd, mDNStrue, mDNStrue, PosixEventFlag_Read | PosixEventFlag_Write);
-}
-
-// Simply note the received signal in gEventSignals.
-mDNSlocal void  NoteSignal(int signum)
-{
-    sigaddset(&gEventSignals, signum);
-}
-
-// Tell the event package to listen for signal and report it in mDNSPosixRunEventLoopOnce().
-mStatus mDNSPosixListenForSignalInEventLoop(int signum)
-{
-    struct sigaction action;
-    mStatus err;
-
-    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
-    action.sa_handler = NoteSignal;
-    err = sigaction(signum, &action, (struct sigaction*) NULL);
-
-    sigaddset(&gEventSignalSet, signum);
-
-    return err;
-}
-
-// Tell the event package to stop listening for signal in mDNSPosixRunEventLoopOnce().
-mStatus mDNSPosixIgnoreSignalInEventLoop(int signum)
-{
-    struct sigaction action;
-    mStatus err;
-
-    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
-    action.sa_handler = SIG_DFL;
-    err = sigaction(signum, &action, (struct sigaction*) NULL);
-
-    sigdelset(&gEventSignalSet, signum);
-
-    return err;
-}
-
-// Do a single pass through the attendent event sources and dispatch any found to their callbacks.
-// Return as soon as internal timeout expires, or a signal we're listening for is received.
-mStatus mDNSPosixRunEventLoopOnce(mDNS *m, const struct timeval *pTimeout,
-                                  sigset_t *pSignalsReceived, mDNSBool *pDataDispatched)
-{
-    fd_set listenFDs;
-    fd_set writeFDs;
-    int numFDs = 0, numReady;
-    struct timeval timeout = *pTimeout;
-
-    // 1. Set up the fd_set as usual here.
-    // This example client has no file descriptors of its own,
-    // but a real application would call FD_SET to add them to the set here
-    FD_ZERO(&listenFDs);
-    FD_ZERO(&writeFDs);
-
-    // 2. Set up the timeout.
-    // MainLoop has already called mDNS_Execute and udsserver_idle, so the timeout we
-    // were passed is already set up.
-
-    // Include the sockets that are listening to the wire in our select() set
-    mDNSPosixGetFDSetForSelect(m, &numFDs, &listenFDs, &writeFDs);
-    numReady = select(numFDs, &listenFDs, &writeFDs, (fd_set*) NULL, &timeout);
-
-    if (numReady > 0)
-    {
-        mDNSPosixProcessFDSet(m, &listenFDs, &writeFDs);
-        *pDataDispatched = mDNStrue;
-    }
-    else if (numReady < 0)
-    {
-	if (errno != EINTR) {
-            // This should never happen, represents a coding error, and is not recoverable, since
-            // we'll just sit here spinning and never receive another event.   The usual reason for
-            // it to happen is that an FD was closed but not removed from the event list.
-            LogMsg("select failed: %s", strerror(errno));
-            abort();
-        }
-    }
-    else
-        *pDataDispatched = mDNSfalse;
-
-    (void) sigprocmask(SIG_BLOCK, &gEventSignalSet, (sigset_t*) NULL);
-    *pSignalsReceived = gEventSignals;
-    sigemptyset(&gEventSignals);
-    (void) sigprocmask(SIG_UNBLOCK, &gEventSignalSet, (sigset_t*) NULL);
-
-    return mStatus_NoError;
-}
diff --git a/mDNSPosix/mDNSPosix.h b/mDNSPosix/mDNSPosix.h
deleted file mode 100644
index 9675591..0000000
--- a/mDNSPosix/mDNSPosix.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2002-2021 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
- *
- *     https://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.
- */
-
-#ifndef __mDNSPlatformPosix_h
-#define __mDNSPlatformPosix_h
-
-#include <signal.h>
-#include <sys/time.h>
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-// 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;      // MUST be the first element in this structure
-    mDNSs32 LastSeen;
-    char *                  intfName;
-    PosixNetworkInterface * aliasIntf;
-    int index;
-    int multicastSocket4;
-#if HAVE_IPV6
-    int multicastSocket6;
-#endif
-};
-
-// This is a global because debugf_() needs to be able to check its value
-extern int gMDNSPlatformPosixVerboseLevel;
-
-struct mDNS_PlatformSupport_struct
-{
-    int unicastSocket4;
-#if HAVE_IPV6
-    int unicastSocket6;
-#endif
-};
-
-// We keep a list of client-supplied event sources in PosixEventSource records
-// Add a file descriptor to the set that mDNSPosixRunEventLoopOnce() listens to.
-#define PosixEventFlag_OnList   1
-#define PosixEventFlag_Read     2
-#define PosixEventFlag_Write    4
-    
-typedef void (*mDNSPosixEventCallback)(int fd, void *context);
-struct PosixEventSource
-{
-    struct PosixEventSource *next;
-    mDNSPosixEventCallback readCallback;
-    mDNSPosixEventCallback writeCallback;
-    const char *readTaskName;
-    const char *writeTaskName;
-    void *readContext;
-    void *writeContext;
-    int fd;
-    unsigned flags;
-};
-typedef struct PosixEventSource PosixEventSource;
-    
-struct UDPSocket_struct
-{
-    mDNSIPPort port;
-    PosixEventSource events;
-    mDNSAddr remoteAddress;
-    mDNSIPPort remotePort;
-    mDNSBool setup;
-    mDNSBool randomizePort;
-};
-
-struct TCPSocket_struct
-{
-    mDNSIPPort port;            // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with mDNSIPPort
-    TCPSocketFlags flags;       // MUST BE SECOND FIELD -- mDNSCore expects every TCPSocket_struct have TCPSocketFlags flags after mDNSIPPort
-    TCPConnectionCallback callback;
-    PosixEventSource events;
-    TLSContext *tls;
-    domainname *hostname;
-    mDNSAddr remoteAddress;
-    mDNSIPPort remotePort;
-    void *context;
-    mDNSBool setup;
-    mDNSBool connected;
-    mStatus err;
-};
-
-struct TCPListener_struct
-{
-    TCPAcceptedCallback callback;
-    PosixEventSource events;
-    TLSServerContext *tls;
-    void *context;
-    mDNSAddr_Type addressType;
-    TCPSocketFlags socketFlags;
-};
-    
-#define uDNS_SERVERS_FILE "/etc/resolv.conf"
-extern int ParseDNSServers(mDNS *m, const char *filePath);
-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 FutureTime 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 *m, int *nfds, fd_set *readfds, fd_set *writefds, struct timeval *timeout);
-extern void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds, fd_set *writefds);
-
-extern mStatus mDNSPosixAddFDToEventLoop( int fd, mDNSPosixEventCallback callback, void *context);
-extern mStatus mDNSPosixRemoveFDFromEventLoop( int fd);
-extern mStatus mDNSPosixListenForSignalInEventLoop( int signum);
-extern mStatus mDNSPosixIgnoreSignalInEventLoop( int signum);
-extern mStatus mDNSPosixRunEventLoopOnce( mDNS *m, const struct timeval *pTimeout, sigset_t *pSignalsReceived, mDNSBool *pDataDispatched);
-
-extern mStatus mDNSPosixListenForSignalInEventLoop( int signum);
-extern mStatus mDNSPosixIgnoreSignalInEventLoop( int signum);
-extern mStatus mDNSPosixRunEventLoopOnce( mDNS *m, const struct timeval *pTimeout, sigset_t *pSignalsReceived, mDNSBool *pDataDispatched);
-
-// From the TLS shim:
-extern mDNSBool mDNSPosixTLSInit(void);
-extern void mDNSPosixTLSContextFree(TLSContext *tls);
-extern TLSContext *mDNSPosixTLSClientStateCreate(TCPSocket *sock);
-extern mDNSBool mDNSPosixTLSStart(TCPSocket *sock);
-extern TLSContext *PosixTLSAccept(TCPListener *listenContext);
-extern int mDNSPosixTLSRead(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
-extern int mDNSPosixTLSWrite(TCPSocket *sock, const void *buf, unsigned long buflen);
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c
deleted file mode 100644
index 7ad0f30..0000000
--- a/mDNSPosix/mDNSUNP.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2018 Apple 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.
- */
-
-#include "mDNSUNP.h"
-
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/uio.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-#include <unistd.h>
-#include <stdio.h>
-
-/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
-   macro, usually defined in <sys/param.h> or someplace like that, to make sure the
-   CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
-   should be set to the name of the header to include to get the ALIGN(P) macro.
- */
-#ifdef NEED_ALIGN_MACRO
-#include NEED_ALIGN_MACRO
-#endif
-
-/* sockaddr_dl is only referenced if we're using IP_RECVIF,
-   so only include the header in that case.
- */
-
-#ifdef  IP_RECVIF
-    #include <net/if_dl.h>
-#endif
-
-ssize_t
-recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
-               struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
-{
-    struct msghdr msg;
-    struct iovec iov[1];
-    ssize_t n;
-
-#ifdef CMSG_FIRSTHDR
-    struct cmsghdr  *cmptr;
-    union {
-        struct cmsghdr cm;
-        char control[1024];
-    } control_un;
-
-    *ttl = 255;         // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
-
-    msg.msg_control = control_un.control;
-    msg.msg_controllen = sizeof(control_un.control);
-    msg.msg_flags = 0;
-#else
-    memset(&msg, 0, sizeof(msg));   /* make certain msg_accrightslen = 0 */
-#endif /* CMSG_FIRSTHDR */
-
-    msg.msg_name = (char *) sa;
-    msg.msg_namelen = *salenptr;
-    iov[0].iov_base = (char *)ptr;
-    iov[0].iov_len = nbytes;
-    msg.msg_iov = iov;
-    msg.msg_iovlen = 1;
-
-    if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
-        return(n);
-
-    *salenptr = msg.msg_namelen;    /* pass back results */
-    if (pktp) {
-        /* 0.0.0.0, i/f = -1 */
-        /* We set the interface to -1 so that the caller can
-           tell whether we returned a meaningful value or
-           just some default.  Previously this code just
-           set the value to 0, but I'm concerned that 0
-           might be a valid interface value.
-         */
-        memset(pktp, 0, sizeof(struct my_in_pktinfo));
-        pktp->ipi_ifindex = -1;
-    }
-/* end recvfrom_flags1 */
-
-/* include recvfrom_flags2 */
-#ifndef CMSG_FIRSTHDR
-    #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
-    *flagsp = 0;                    /* pass back results */
-    return(n);
-#else
-
-    *flagsp = msg.msg_flags;        /* pass back results */
-    if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
-        (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
-        return(n);
-
-    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
-         cmptr = CMSG_NXTHDR(&msg, cmptr)) {
-
-#ifdef  IP_PKTINFO
-#if in_pktinfo_definition_is_missing
-        struct in_pktinfo
-        {
-            int ipi_ifindex;
-            struct in_addr ipi_spec_dst;
-            struct in_addr ipi_addr;
-        };
-#endif
-        if (cmptr->cmsg_level == IPPROTO_IP &&
-            cmptr->cmsg_type == IP_PKTINFO) {
-            struct in_pktinfo *tmp;
-            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
-
-            tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
-            sin->sin_family = AF_INET;
-            sin->sin_addr = tmp->ipi_addr;
-            sin->sin_port = 0;
-            pktp->ipi_ifindex = tmp->ipi_ifindex;
-            continue;
-        }
-#endif
-
-#ifdef  IP_RECVDSTADDR
-        if (cmptr->cmsg_level == IPPROTO_IP &&
-            cmptr->cmsg_type == IP_RECVDSTADDR) {
-            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
-
-            sin->sin_family = AF_INET;
-            sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
-            sin->sin_port = 0;
-            continue;
-        }
-#endif
-
-#ifdef  IP_RECVIF
-        if (cmptr->cmsg_level == IPPROTO_IP &&
-            cmptr->cmsg_type == IP_RECVIF) {
-            struct sockaddr_dl  *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
-#ifndef HAVE_BROKEN_RECVIF_NAME
-            int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
-            strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
-#endif
-            pktp->ipi_ifindex = sdl->sdl_index;
-#ifdef HAVE_BROKEN_RECVIF_NAME
-            if (sdl->sdl_index == 0) {
-                pktp->ipi_ifindex = *(uint_t*)sdl;
-            }
-#endif
-            assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
-            // null terminated because of memset above
-            continue;
-        }
-#endif
-
-#ifdef  IP_RECVTTL
-        if (cmptr->cmsg_level == IPPROTO_IP &&
-            cmptr->cmsg_type == IP_RECVTTL) {
-            *ttl = *(u_char*)CMSG_DATA(cmptr);
-            continue;
-        }
-        else if (cmptr->cmsg_level == IPPROTO_IP &&
-                 cmptr->cmsg_type == IP_TTL) {  // some implementations seem to send IP_TTL instead of IP_RECVTTL
-            *ttl = *(int*)CMSG_DATA(cmptr);
-            continue;
-        }
-#endif
-
-#if defined(IPV6_PKTINFO) && HAVE_IPV6
-        if (cmptr->cmsg_level == IPPROTO_IPV6 &&
-            cmptr->cmsg_type  == IPV6_2292_PKTINFO) {
-            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
-            struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
-
-            sin6->sin6_family   = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-            sin6->sin6_len      = sizeof(*sin6);
-#endif
-            sin6->sin6_addr     = ip6_info->ipi6_addr;
-            sin6->sin6_flowinfo = 0;
-            sin6->sin6_scope_id = 0;
-            sin6->sin6_port     = 0;
-            pktp->ipi_ifindex   = ip6_info->ipi6_ifindex;
-            continue;
-        }
-#endif
-
-#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
-        if (cmptr->cmsg_level == IPPROTO_IPV6 &&
-            cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
-            *ttl = *(int*)CMSG_DATA(cmptr);
-            continue;
-        }
-#endif
-        assert(0);  // unknown ancillary data
-    }
-    return(n);
-#endif /* CMSG_FIRSTHDR */
-}
-
-// **********************************************************************************************
-
-// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
-// Returns 0 on success, -1 on failure.
-
-#ifdef NOT_HAVE_DAEMON
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/signal.h>
-
-int daemon(int nochdir, int noclose)
-{
-    switch (fork())
-    {
-    case -1: return (-1);       // Fork failed
-    case 0:  break;             // Child -- continue
-    default: _exit(0);          // Parent -- exit
-    }
-
-    if (setsid() == -1) return(-1);
-
-    signal(SIGHUP, SIG_IGN);
-
-    switch (fork())             // Fork again, primarily for reasons of Unix trivia
-    {
-    case -1: return (-1);       // Fork failed
-    case 0:  break;             // Child -- continue
-    default: _exit(0);          // Parent -- exit
-    }
-
-    if (!nochdir) (void)chdir("/");
-    umask(0);
-
-    if (!noclose)
-    {
-        int fd = open("/dev/null", O_RDWR, 0);
-        if (fd != -1)
-        {
-            // Avoid unnecessarily duplicating a file descriptor to itself
-            if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
-            if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
-            if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
-            if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
-                (void)close (fd);
-        }
-    }
-    return (0);
-}
-#endif /* NOT_HAVE_DAEMON */
diff --git a/mDNSPosix/mDNSUNP.h b/mDNSPosix/mDNSUNP.h
deleted file mode 100644
index 420b038..0000000
--- a/mDNSPosix/mDNSUNP.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2018 Apple 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.
- */
-
-#ifndef __mDNSUNP_h
-#define __mDNSUNP_h
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-
-#ifdef HAVE_LINUX
-#include <linux/socket.h>
-#define IPV6_2292_PKTINFO  IPV6_2292PKTINFO
-#define IPV6_2292_HOPLIMIT IPV6_2292HOPLIMIT
-#else
-// The following are the supported non-linux posix OSes -
-// netbsd, freebsd and openbsd.
-#if HAVE_IPV6
-#define IPV6_2292_PKTINFO  19
-#define IPV6_2292_HOPLIMIT 20
-#endif
-#endif
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#ifdef NOT_HAVE_SOCKLEN_T
-typedef unsigned int socklen_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 HAVE_IPV6
-#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) (((struct sockaddr*)&(X))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr))
-#endif
-
-#define IFI_NAME    IFNAMSIZ    /* same as IFNAMSIZ in <net/if.h> */
-#define IFI_HADDR   8           /* allow for 64-bit EUI-64 in future */
-
-// Renamed from my_in_pktinfo because in_pktinfo is used by Linux.
-
-struct my_in_pktinfo {
-    struct sockaddr_storage ipi_addr;
-    int ipi_ifindex;                                /* received interface index */
-    char ipi_ifname[IFI_NAME];                      /* received interface name  */
-};
-
-/* From the text (Stevens, section 20.2): */
-/* 'As an example of recvmsg we will write a function named recvfrom_flags that */
-/* is similar to recvfrom but also returns: */
-/*	1. the returned msg_flags value, */
-/*	2. the destination addres of the received datagram (from the IP_RECVDSTADDR socket option, and */
-/*	3. the index of the interface on which the datagram was received (the IP_RECVIF socket option).' */
-extern ssize_t recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
-                              struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl);
-
-#if defined(AF_INET6) && HAVE_IPV6
-#define INET6_ADDRSTRLEN 46 /*Maximum length of IPv6 address */
-#endif
-
-#ifdef NOT_HAVE_DAEMON
-extern int daemon(int nochdir, int noclose);
-#endif
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
diff --git a/mDNSPosix/mbedtls.c b/mDNSPosix/mbedtls.c
deleted file mode 100644
index a73681b..0000000
--- a/mDNSPosix/mbedtls.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2019-2021 Apple 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
- *
- *     https://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.
- *
- * This file contains a TLS Shim that allows mDNSPosix to use mbedtls to do TLS session
- * establishment and also to accept TLS connections.
- */
-
-#include "mDNSEmbeddedAPI.h"           // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "mDNSPosix.h"               // Defines the specific types needed to run mDNS on this platform
-#include "PlatformCommon.h"
-
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <mbedtls/error.h>
-#include <mbedtls/pk.h>
-#include <mbedtls/ecp.h>
-#include <mbedtls/ecdsa.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/sha256.h>
-#include <mbedtls/base64.h>
-
-#include <mbedtls/certs.h>
-#include <mbedtls/x509.h>
-#include <mbedtls/ssl.h>
-#include <mbedtls/config.h>
-
-// Posix TLS server context
-struct TLSContext_struct {
-    mbedtls_ssl_context context;
-};
-
-struct TLSServerContext_struct {
-    mbedtls_x509_crt cert;
-    mbedtls_pk_context key;
-    mbedtls_x509_crt cacert;
-    mbedtls_ssl_config config;
-};
-
-// Context that is shared amongs all TLS connections, regardless of which server cert/key is in use.
-static mbedtls_entropy_context entropy;
-static mbedtls_ctr_drbg_context ctr_drbg;
-
-mDNSBool
-mDNSPosixTLSInit(void)
-{
-    int status;
-
-    mbedtls_entropy_init(&entropy);
-    mbedtls_ctr_drbg_init(&ctr_drbg);
-
-    status = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
-    if (status != 0) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Unable to seed RNG: %x", -status);
-        return mDNSfalse;
-    }
-    return mDNStrue;
-}
-
-void
-mDNSPosixTLSContextFree(TLSContext *tls)
-{
-    mbedtls_ssl_free(&tls->context);
-    mDNSPlatformMemFree(tls);
-}
-
-TLSContext *
-mDNSPosixTLSClientStateCreate(TCPSocket *sock)
-{
-    int status;
-    TLSContext *tls;
-    mbedtls_ssl_config config;
-
-    status = mbedtls_ssl_config_defaults(&config, MBEDTLS_SSL_IS_CLIENT,
-                                         MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
-    if (status != 0) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Unable to set ssl config defaults: %d", -status);
-        return NULL;
-    }
-    mbedtls_ssl_conf_authmode(&config, (sock->flags & kTCPSocketFlags_TLSValidationNotRequired
-                                        ? MBEDTLS_SSL_VERIFY_NONE
-                                        : MBEDTLS_SSL_VERIFY_REQUIRED));
-
-    tls = mDNSPlatformMemAllocateClear(sizeof(*tls));
-    if (tls == mDNSNULL) {
-        return tls;
-    }
-
-    status = mbedtls_ssl_setup(&tls->context, &config);
-    if (status == 0) {
-        if (sock->hostname) {
-            char serverName[MAX_ESCAPED_DOMAIN_NAME];
-            ConvertDomainNameToCString_withescape(sock->hostname, serverName, '\\');
-            status = mbedtls_ssl_set_hostname(&tls->context, serverName);
-        }
-    }
-    if (status != 0) {
-        LogInfo("Unable to set up TLS listener state: %x", -status);
-        mDNSPosixTLSContextFree(tls);
-        return NULL;
-    }
-    return tls;
-}
-
-static int
-tls_io_send(void *ctx, const unsigned char *buf, size_t len)
-{
-    ssize_t ret;
-    TCPSocket *sock = ctx;
-    ret = mDNSPosixWriteTCP(sock->events.fd, (const char *)buf, len);
-    if (ret < 0) {
-        if (errno == EAGAIN) {
-            return MBEDTLS_ERR_SSL_WANT_WRITE;
-        } else {
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-    } else {
-        return (int)ret;
-    }
-}
-
-static int
-tls_io_recv(void *ctx, unsigned char *buf, size_t max)
-{
-    ssize_t ret;
-    TCPSocket *sock = ctx;
-    mDNSBool closed = mDNSfalse;
-    ret = mDNSPosixReadTCP(sock->events.fd, buf, max, &closed);
-    if (ret < 0) {
-        if (errno == EWOULDBLOCK || errno == EAGAIN) {
-            return MBEDTLS_ERR_SSL_WANT_READ;
-        } else {
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-    } else if (closed) {
-        return MBEDTLS_ERR_SSL_CONN_EOF;
-    } else {
-        return (int)ret;
-    }
-}
-
-mDNSBool
-mDNSPosixTLSStart(TCPSocket *sock)
-{
-    int status;
-
-    // Set up the I/O functions.
-    mbedtls_ssl_set_bio(&sock->tls->context, sock, tls_io_send, tls_io_recv, NULL);
-
-    // Start the TLS handshake
-    status = mbedtls_ssl_handshake(&sock->tls->context);
-    if (status != 0 && status != MBEDTLS_ERR_SSL_WANT_READ && status != MBEDTLS_ERR_SSL_WANT_WRITE) {
-        LogInfo("TLS handshake failed: %x", -status);
-        return mDNSfalse;
-    }
-    return mDNStrue;
-}
-
-TLSContext *
-PosixTLSAccept(TCPListener *listenContext)
-{
-    int status;
-    TLSContext *tls = mDNSPlatformMemAllocateClear(sizeof(*tls));
-
-    if (tls == mDNSNULL) {
-        return tls;
-    }
-
-    status = mbedtls_ssl_setup(&tls->context, &listenContext->tls->config);
-    if (status != 0) {
-        LogInfo("Unable to set up TLS listener state: %x", -status);
-        mDNSPlatformMemFree(tls);
-        return NULL;
-    }
-    return tls;
-}
-
-int
-mDNSPosixTLSRead(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
-{
-    int ret;
-
-    // Shouldn't ever happen.
-    if (!sock->tls) {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "mDNSPosixTLSRead: called without TLS context!");
-        *closed = mDNStrue;
-        return 0;
-    }
-
-    ret = mbedtls_ssl_read(&sock->tls->context, buf, buflen);
-    if (ret < 0) {
-        switch (ret) {
-        case MBEDTLS_ERR_SSL_WANT_READ:
-            return 0;
-        case MBEDTLS_ERR_SSL_WANT_WRITE:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got SSL want write in TLS read!");
-            // This means we got EWOULDBLOCK on a write operation.
-            // Not implemented yet, but the right way to handle this is probably to
-            // deselect read events until the socket is ready to write, then write,
-            // and then re-enable read events.   What we don't want is to keep calling
-            // read, because that will spin.
-            return 0;
-        case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got async in progress in TLS read!");
-            // No idea how to handle this yet.
-            return 0;
-#ifdef MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
-        case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got crypto in progress in TLS read!");
-            // No idea how to handle this.
-            return 0;
-#endif
-        default:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Unexpected response from SSL read: %x", -ret);
-            return -1;
-        }
-    } else {
-        // mbedtls returns 0 for EOF, just like read(), but we need a different signal,
-        // so we treat 0 as an error (for now).   In principle, we should get a notification
-        // when the remote end is done writing, so a clean close should be different than
-        // an abrupt close.
-        if (ret == 0) {
-            if (closed) {
-                *closed = mDNStrue;
-            }
-            return -1;
-        }
-        return ret;
-    }
-}
-
-int
-mDNSPosixTLSWrite(TCPSocket *sock, const void *buf, unsigned long buflen)
-{
-    int ret;
-    ret = mbedtls_ssl_write(&sock->tls->context, buf, buflen);
-    if (ret < 0) {
-        switch (ret) {
-        case MBEDTLS_ERR_SSL_WANT_READ:
-            return 0;
-        case MBEDTLS_ERR_SSL_WANT_WRITE:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got SSL want write in TLS read!");
-            return 0;
-        case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got async in progress in TLS read!");
-            return 0;
-#ifdef MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
-        case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Got crypto in progress in TLS read!");
-            return 0;
-#endif
-        default:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "Unexpected response from SSL read: %x", -ret);
-            return -1;
-        }
-    }
-    return ret;
-}
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/mDNSPosix/nss_mdns.c b/mDNSPosix/nss_mdns.c
deleted file mode 100644
index afadb3c..0000000
--- a/mDNSPosix/nss_mdns.c
+++ /dev/null
@@ -1,2723 +0,0 @@
-/*
-   NICTA Public Software Licence
-   Version 1.0
-
-   Copyright © 2004 National ICT Australia Ltd
-
-   All rights reserved.
-
-   By this licence, National ICT Australia Ltd (NICTA) grants permission,
-   free of charge, to any person who obtains a copy of this software
-   and any associated documentation files ("the Software") to use and
-   deal with the Software in source code and binary forms without
-   restriction, with or without modification, and to permit persons
-   to whom the Software is furnished to do so, provided that the
-   following conditions are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimers.
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimers in
-   the documentation and/or other materials provided with the
-   distribution.
-   - The name of NICTA may not be used to endorse or promote products
-   derived from this Software without specific prior written permission.
-
-   EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
-   PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS" AND
-   NICTA MAKES NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY
-   KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
-   REPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS
-   OR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS
-   FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, THE ABSENCE OF LATENT
-   OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR
-   NOT DISCOVERABLE.
-
-   TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
-   NICTA BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
-   NEGLIGENCE) FOR ANY LOSS OR DAMAGE WHATSOEVER, INCLUDING (WITHOUT
-   LIMITATION) LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR
-   CORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS,
-   OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS;
-   OR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
-   EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE,
-   THE SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF NICTA HAS BEEN
-   ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-   If applicable legislation implies warranties or conditions, or
-   imposes obligations or liability on NICTA in respect of the Software
-   that cannot be wholly or partly excluded, restricted or modified,
-   NICTA's liability is limited, to the full extent permitted by the
-   applicable legislation, at its option, to:
-
-   a. in the case of goods, any one or more of the following:
-   i.   the replacement of the goods or the supply of equivalent goods;
-   ii.  the repair of the goods;
-   iii. the payment of the cost of replacing the goods or of acquiring
-       equivalent goods;
-   iv.  the payment of the cost of having the goods repaired; or
-   b. in the case of services:
-   i.   the supplying of the services again; or
-   ii.  the payment of the cost of having the services supplied
-       again.
- */
-
-/*
-    NSSwitch Implementation of mDNS interface.
-
-    Andrew White (Andrew.White@nicta.com.au)
-    May 2004
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <syslog.h>
-#include <pthread.h>
-#include <ctype.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-
-#include <arpa/inet.h>
-#define BIND_8_COMPAT 1
-#include <arpa/nameser.h>
-
-#include <dns_sd.h>
-
-
-//----------
-// Public functions
-
-/*
-    Count the number of dots in a name string.
- */
-int
-count_dots (const char * name);
-
-
-/*
-    Test whether a domain name is local.
-
-    Returns
-        1 if name ends with ".local" or ".local."
-        0 otherwise
- */
-int
-islocal (const char * name);
-
-
-/*
-    Format an address structure as a string appropriate for DNS reverse (PTR)
-    lookup, based on address type.
-
-    Parameters
-        prefixlen
-            Prefix length, in bits.  When formatting, this will be rounded up
-            to the nearest appropriate size.  If -1, assume maximum.
-        buf
-            Output buffer.  Must be long enough to hold largest possible
-            output.
-    Returns
-        Pointer to (first character of) output buffer,
-        or NULL on error.
- */
-char *
-format_reverse_addr (int af, const void * addr, int prefixlen, char * buf);
-
-
-/*
-    Format an address structure as a string appropriate for DNS reverse (PTR)
-    lookup for AF_INET.  Output is in .in-addr.arpa domain.
-
-    Parameters
-        prefixlen
-            Prefix length, in bits.  When formatting, this will be rounded up
-            to the nearest byte (8).  If -1, assume 32.
-        buf
-            Output buffer.  Must be long enough to hold largest possible
-            output.  For AF_INET, this is 29 characters (including null).
-    Returns
-        Pointer to (first character of) output buffer,
-        or NULL on error.
- */
-char *
-format_reverse_addr_in (
-    const struct in_addr * addr,
-    int prefixlen,
-    char * buf
-    );
-#define DNS_PTR_AF_INET_SIZE 29
-
-/*
-    Format an address structure as a string appropriate for DNS reverse (PTR)
-    lookup for AF_INET6.  Output is in .ip6.arpa domain.
-
-    Parameters
-        prefixlen
-            Prefix length, in bits.  When formatting, this will be rounded up
-            to the nearest nibble (4).  If -1, assume 128.
-        buf
-            Output buffer.  Must be long enough to hold largest possible
-            output.  For AF_INET6, this is 72 characters (including null).
-    Returns
-        Pointer to (first character of) output buffer,
-        or NULL on error.
- */
-char *
-format_reverse_addr_in6 (
-    const struct in6_addr * addr,
-    int prefixlen,
-    char * buf
-    );
-#define DNS_PTR_AF_INET6_SIZE 72
-
-
-/*
-    Compare whether the given dns name has the given domain suffix.
-    A single leading '.' on the name or leading or trailing '.' on the
-    domain is ignored for the purposes of the comparison.
-    Multiple leading or trailing '.'s are an error.  Other DNS syntax
-    errors are not checked for.  The comparison is case insensitive.
-
-    Returns
-        1 on success (match)
-        0 on failure (no match)
-        < 0 on error
- */
-int
-cmp_dns_suffix (const char * name, const char * domain);
-enum
-{
-    CMP_DNS_SUFFIX_SUCCESS = 1,
-    CMP_DNS_SUFFIX_FAILURE = 0,
-    CMP_DNS_SUFFIX_BAD_NAME = 1,
-    CMP_DNS_SUFFIX_BAD_DOMAIN = -2
-};
-
-typedef int ns_type_t;
-typedef int ns_class_t;
-
-/*
-    Convert a DNS resource record (RR) code to an address family (AF) code.
-
-    Parameters
-        rrtype
-            resource record type (from nameser.h)
-
-    Returns
-        Appropriate AF code (from socket.h), or AF_UNSPEC if an appropriate
-        mapping couldn't be determined
- */
-int
-rr_to_af (ns_type_t rrtype);
-
-
-/*
-    Convert an address family (AF) code to a DNS resource record (RR) code.
-
-    Parameters
-        int
-            address family code (from socket.h)
-    Returns
-        Appropriate RR code (from nameser.h), or ns_t_invalid if an appropriate
-        mapping couldn't be determined
- */
-ns_type_t
-af_to_rr (int af);
-
-
-/*
-    Convert a string to an address family (case insensitive).
-
-    Returns
-        Matching AF code, or AF_UNSPEC if no match found.
- */
-int
-str_to_af (const char * str);
-
-
-/*
-    Convert a string to an ns_class_t (case insensitive).
-
-    Returns
-        Matching ns_class_t, or ns_c_invalid if no match found.
- */
-ns_class_t
-str_to_ns_class (const char * str);
-
-
-/*
-    Convert a string to an ns_type_t (case insensitive).
-
-    Returns
-        Matching ns_type_t, or ns_t_invalid if no match found.
- */
-ns_type_t
-str_to_ns_type (const char * str);
-
-
-/*
-    Convert an address family code to a string.
-
-    Returns
-        String representation of AF,
-        or NULL if address family unrecognised or invalid.
- */
-const char *
-af_to_str (int in);
-
-
-/*
-    Convert an ns_class_t code to a string.
-
-    Returns
-        String representation of ns_class_t,
-        or NULL if ns_class_t unrecognised or invalid.
- */
-const char *
-ns_class_to_str (ns_class_t in);
-
-
-/*
-    Convert an ns_type_t code to a string.
-
-    Returns
-        String representation of ns_type_t,
-        or NULL if ns_type_t unrecognised or invalid.
- */
-const char *
-ns_type_to_str (ns_type_t in);
-
-
-/*
-    Convert DNS rdata in label format (RFC1034, RFC1035) to a name.
-
-    On error, partial data is written to name (as much as was successfully
-    processed) and an error code is returned.  Errors include a name too
-    long for the buffer and a pointer in the label (which cannot be
-    resolved).
-
-    Parameters
-        rdata
-            Rdata formatted as series of labels.
-        rdlen
-            Length of rdata buffer.
-        name
-            Buffer to store fully qualified result in.
-            By RFC1034 section 3.1, a 255 character buffer (256 characters
-            including null) is long enough for any legal name.
-        name_len
-            Number of characters available in name buffer, not including
-            trailing null.
-
-    Returns
-        Length of name buffer (not including trailing null).
-        < 0 on error.
-        A return of 0 implies the empty domain.
- */
-static int
-dns_rdata_to_name (const unsigned char * rdata, int rdlen, char * name, unsigned int name_len);
-enum
-{
-    DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
-    // Format is broken.  Usually because we ran out of data
-    // (according to rdata) before the labels said we should.
-    DNS_RDATA_TO_NAME_TOO_LONG = -2,
-    // The converted rdata is longer than the name buffer.
-    DNS_RDATA_TO_NAME_PTR = -3,
-    // The rdata contains a pointer.
-};
-
-#define DNS_LABEL_MAXLEN 63
-// Maximum length of a single DNS label
-#define DNS_NAME_MAXLEN 256
-// Maximum length of a DNS name
-
-//----------
-// Public types
-
-typedef int errcode_t;
-// Used for 0 = success, non-zero = error code functions
-
-
-//----------
-// Public functions
-
-/*
-    Test whether a domain name is in a domain covered by nss_mdns.
-    The name is assumed to be fully qualified (trailing dot optional);
-    unqualified names will be processed but may return unusual results
-    if the unqualified prefix happens to match a domain suffix.
-
-    Returns
-         1 success
-         0 failure
-        -1 error, check errno
- */
-int
-config_is_mdns_suffix (const char * name);
-
-
-/*
-    Loads all relevant data from configuration file.  Other code should
-    rarely need to call this function, since all other public configuration
-    functions do so implicitly.  Once loaded, configuration info doesn't
-    change.
-
-    Returns
-        0 configuration ready
-        non-zero configuration error code
- */
-errcode_t
-init_config ();
-
-#define ENTNAME  hostent
-#define DATABASE "hosts"
-
-#include <nss.h>
-// For nss_status
-#include <netdb.h>
-// For hostent
-#include <sys/types.h>
-// For size_t
-
-typedef enum nss_status nss_status;
-typedef struct hostent hostent;
-
-/*
-   gethostbyname implementation
-
-    name:
-        name to look up
-    result_buf:
-        resulting entry
-    buf:
-        auxillary buffer
-    buflen:
-        length of auxillary buffer
-    errnop:
-        pointer to errno
-    h_errnop:
-        pointer to h_errno
- */
-nss_status
-_nss_mdns_gethostbyname_r (
-    const char *name,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    );
-
-
-/*
-   gethostbyname2 implementation
-
-    name:
-        name to look up
-    af:
-        address family
-    result_buf:
-        resulting entry
-    buf:
-        auxillary buffer
-    buflen:
-        length of auxillary buffer
-    errnop:
-        pointer to errno
-    h_errnop:
-        pointer to h_errno
- */
-nss_status
-_nss_mdns_gethostbyname2_r (
-    const char *name,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    );
-
-
-/*
-   gethostbyaddr implementation
-
-    addr:
-        address structure to look up
-    len:
-        length of address structure
-    af:
-        address family
-    result_buf:
-        resulting entry
-    buf:
-        auxillary buffer
-    buflen:
-        length of auxillary buffer
-    errnop:
-        pointer to errno
-    h_errnop:
-        pointer to h_errno
- */
-nss_status
-_nss_mdns_gethostbyaddr_r (
-    const void *addr,
-    socklen_t len,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    );
-
-
-//----------
-// Types and Constants
-
-const int MDNS_VERBOSE = 0;
-// This enables verbose syslog messages
-// If zero, only "imporant" messages will appear in syslog
-
-#define k_hostname_maxlen 256
-// As per RFC1034 and RFC1035
-#define k_aliases_max 15
-#define k_addrs_max 15
-
-typedef struct buf_header
-{
-    char hostname [k_hostname_maxlen + 1];
-    char * aliases [k_aliases_max + 1];
-    char * addrs [k_addrs_max + 1];
-} buf_header_t;
-
-typedef struct result_map
-{
-    int done;
-    nss_status status;
-    hostent * hostent;
-    buf_header_t * header;
-    int aliases_count;
-    int addrs_count;
-    char * buffer;
-    int addr_idx;
-    // Index for addresses - grow from low end
-    // Index points to first empty space
-    int alias_idx;
-    // Index for aliases - grow from high end
-    // Index points to lowest entry
-    int r_errno;
-    int r_h_errno;
-} result_map_t;
-
-static const struct timeval
-k_select_time = { 0, 500000 };
-// 0 seconds, 500 milliseconds
-
-//----------
-// Local prototypes
-
-static nss_status
-mdns_gethostbyname2 (
-    const char *name,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    );
-
-
-/*
-    Lookup name using mDNS server
- */
-static nss_status
-mdns_lookup_name (
-    const char * fullname,
-    int af,
-    result_map_t * result
-    );
-
-/*
-    Lookup address using mDNS server
- */
-static nss_status
-mdns_lookup_addr (
-    const void * addr,
-    socklen_t len,
-    int af,
-    const char * addr_str,
-    result_map_t * result
-    );
-
-
-/*
-    Handle incoming MDNS events
- */
-static nss_status
-handle_events (DNSServiceRef sdref, result_map_t * result, const char * str);
-
-
-// Callback for mdns_lookup operations
-//DNSServiceQueryRecordReply mdns_lookup_callback;
-typedef void
-mdns_lookup_callback_t
-(
-    DNSServiceRef sdref,
-    DNSServiceFlags flags,
-    uint32_t interface_index,
-    DNSServiceErrorType error_code,
-    const char          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void          *rdata,
-    uint32_t ttl,
-    void                *context
-);
-
-mdns_lookup_callback_t mdns_lookup_callback;
-
-
-static int
-init_result (
-    result_map_t * result,
-    hostent * result_buf,
-    char * buf,
-    size_t buflen
-    );
-
-static int
-callback_body_ptr (
-    const char * fullname,
-    result_map_t * result,
-    int rdlen,
-    const void * rdata
-    );
-
-static void *
-add_address_to_buffer (result_map_t * result, const void * data, int len);
-static char *
-add_alias_to_buffer (result_map_t * result, const char * data, int len);
-static char *
-add_hostname_len (result_map_t * result, const char * fullname, int len);
-static char *
-add_hostname_or_alias (result_map_t * result, const char * data, int len);
-
-static void *
-contains_address (result_map_t * result, const void * data, int len);
-static char *
-contains_alias (result_map_t * result, const char * data);
-
-
-static const char *
-is_applicable_name (
-    result_map_t * result,
-    const char * name,
-    char * lookup_name
-    );
-
-static const char *
-is_applicable_addr (
-    result_map_t * result,
-    const void * addr,
-    int af,
-    char * addr_str
-    );
-
-
-// Error code functions
-
-static nss_status
-set_err (result_map_t * result, nss_status status, int err, int herr);
-
-static nss_status set_err_notfound (result_map_t * result);
-static nss_status set_err_bad_hostname (result_map_t * result);
-static nss_status set_err_buf_too_small (result_map_t * result);
-static nss_status set_err_internal_resource_full (result_map_t * result);
-static nss_status set_err_system (result_map_t * result);
-static nss_status set_err_mdns_failed (result_map_t * result);
-static nss_status set_err_success (result_map_t * result);
-
-
-//----------
-// Global variables
-
-
-//----------
-// NSS functions
-
-nss_status
-_nss_mdns_gethostbyname_r (
-    const char *name,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    )
-{
-    if (MDNS_VERBOSE)
-        syslog (LOG_DEBUG,
-                "mdns: Called nss_mdns_gethostbyname with %s",
-                name
-                );
-
-    return
-        mdns_gethostbyname2 (
-            name, AF_INET, result_buf, buf, buflen, errnop, h_errnop
-            );
-}
-
-
-nss_status
-_nss_mdns_gethostbyname2_r (
-    const char *name,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    )
-{
-    if (MDNS_VERBOSE)
-        syslog (LOG_DEBUG,
-                "mdns: Called nss_mdns_gethostbyname2 with %s",
-                name
-                );
-
-    return
-        mdns_gethostbyname2 (
-            name, af, result_buf, buf, buflen, errnop, h_errnop
-            );
-}
-
-
-nss_status
-_nss_mdns_gethostbyaddr_r (
-    const void *addr,
-    socklen_t len,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    )
-{
-    char addr_str [NI_MAXHOST + 1];
-    result_map_t result;
-    int err_status;
-
-    if (inet_ntop (af, addr, addr_str, NI_MAXHOST) == NULL)
-    {
-        const char * family = af_to_str (af);
-        if (family == NULL)
-        {
-            family = "Unknown";
-        }
-
-        syslog (LOG_WARNING,
-                "mdns: Couldn't covert address, family %d (%s) in nss_mdns_gethostbyaddr: %s",
-                af,
-                family,
-                strerror (errno)
-                );
-
-        // This address family never applicable to us, so return NOT_FOUND
-
-        *errnop = ENOENT;
-        *h_errnop = HOST_NOT_FOUND;
-        return NSS_STATUS_NOTFOUND;
-    }
-    if (MDNS_VERBOSE)
-    {
-        syslog (LOG_DEBUG,
-                "mdns: Called nss_mdns_gethostbyaddr with %s",
-                addr_str
-                );
-    }
-
-    // Initialise result
-    err_status = init_result (&result, result_buf, buf, buflen);
-    if (err_status)
-    {
-        *errnop = err_status;
-        *h_errnop = NETDB_INTERNAL;
-        return NSS_STATUS_TRYAGAIN;
-    }
-
-    if (is_applicable_addr (&result, addr, af, addr_str))
-    {
-        nss_status rv;
-
-        rv = mdns_lookup_addr (addr, len, af, addr_str, &result);
-        if (rv == NSS_STATUS_SUCCESS)
-        {
-            return rv;
-        }
-    }
-
-    // Return current error status (defaults to NOT_FOUND)
-
-    *errnop = result.r_errno;
-    *h_errnop = result.r_h_errno;
-    return result.status;
-}
-
-
-//----------
-// Local functions
-
-nss_status
-mdns_gethostbyname2 (
-    const char *name,
-    int af,
-    hostent * result_buf,
-    char *buf,
-    size_t buflen,
-    int *errnop,
-    int *h_errnop
-    )
-{
-    char lookup_name [k_hostname_maxlen + 1];
-    result_map_t result;
-    int err_status;
-
-    // Initialise result
-    err_status = init_result (&result, result_buf, buf, buflen);
-    if (err_status)
-    {
-        *errnop = err_status;
-        *h_errnop = NETDB_INTERNAL;
-        return NSS_STATUS_TRYAGAIN;
-    }
-
-    if (is_applicable_name (&result, name, lookup_name))
-    {
-        // Try using mdns
-        nss_status rv;
-
-        if (MDNS_VERBOSE)
-            syslog (LOG_DEBUG,
-                    "mdns: Local name: %s",
-                    name
-                    );
-
-        rv = mdns_lookup_name (name, af, &result);
-        if (rv == NSS_STATUS_SUCCESS)
-        {
-            return rv;
-        }
-    }
-
-    // Return current error status (defaults to NOT_FOUND)
-
-    *errnop = result.r_errno;
-    *h_errnop = result.r_h_errno;
-    return result.status;
-}
-
-
-/*
-    Lookup a fully qualified hostname using the default record type
-    for the specified address family.
-
-    Parameters
-        fullname
-            Fully qualified hostname.  If not fully qualified the code will
-            still 'work', but the lookup is unlikely to succeed.
-        af
-            Either AF_INET or AF_INET6.  Other families are not supported.
-        result
-            Initialised 'result' data structure.
- */
-static nss_status
-mdns_lookup_name (
-    const char * fullname,
-    int af,
-    result_map_t * result
-    )
-{
-    // Lookup using mDNS.
-    DNSServiceErrorType errcode;
-    DNSServiceRef sdref;
-    ns_type_t rrtype;
-    nss_status status;
-
-    if (MDNS_VERBOSE)
-        syslog (LOG_DEBUG,
-                "mdns: Attempting lookup of %s",
-                fullname
-                );
-
-    switch (af)
-    {
-    case AF_INET:
-        rrtype = kDNSServiceType_A;
-        result->hostent->h_length = 4;
-        // Length of an A record
-        break;
-
-    case AF_INET6:
-        rrtype = kDNSServiceType_AAAA;
-        result->hostent->h_length = 16;
-        // Length of an AAAA record
-        break;
-
-    default:
-        syslog (LOG_WARNING,
-                "mdns: Unsupported address family %d",
-                af
-                );
-        return set_err_bad_hostname (result);
-    }
-    result->hostent->h_addrtype = af;
-
-    errcode =
-        DNSServiceQueryRecord (
-            &sdref,
-            kDNSServiceFlagsForceMulticast,     // force multicast query
-            kDNSServiceInterfaceIndexAny,   // all interfaces
-            fullname,   // full name to query for
-            rrtype,     // resource record type
-            kDNSServiceClass_IN,    // internet class records
-            mdns_lookup_callback,   // callback
-            result      // Context - result buffer
-            );
-
-    if (errcode)
-    {
-        syslog (LOG_WARNING,
-                "mdns: Failed to initialise lookup, error %d",
-                errcode
-                );
-        return set_err_mdns_failed (result);
-    }
-
-    status = handle_events (sdref, result, fullname);
-    DNSServiceRefDeallocate (sdref);
-    return status;
-}
-
-
-/*
-    Reverse (PTR) lookup for the specified address.
-
-    Parameters
-        addr
-            Either a struct in_addr or a struct in6_addr
-        addr_len
-            size of the address
-        af
-            Either AF_INET or AF_INET6.  Other families are not supported.
-            Must match addr
-        addr_str
-            Address in format suitable for PTR lookup.
-            AF_INET: a.b.c.d -> d.c.b.a.in-addr.arpa
-            AF_INET6: reverse nibble format, x.x.x...x.ip6.arpa
-        result
-            Initialised 'result' data structure.
- */
-static nss_status
-mdns_lookup_addr (
-    const void * addr,
-    socklen_t addr_len,
-    int af,
-    const char * addr_str,
-    result_map_t * result
-    )
-{
-    DNSServiceErrorType errcode;
-    DNSServiceRef sdref;
-    nss_status status;
-
-    if (MDNS_VERBOSE)
-        syslog (LOG_DEBUG,
-                "mdns: Attempting lookup of %s",
-                addr_str
-                );
-
-    result->hostent->h_addrtype = af;
-    result->hostent->h_length = addr_len;
-
-    // Query address becomes "address" in result.
-    if (!add_address_to_buffer (result, addr, addr_len))
-    {
-        return result->status;
-    }
-
-    result->hostent->h_name [0] = 0;
-
-    errcode =
-        DNSServiceQueryRecord (
-            &sdref,
-            kDNSServiceFlagsForceMulticast,     // force multicast query
-            kDNSServiceInterfaceIndexAny,   // all interfaces
-            addr_str,   // address string to query for
-            kDNSServiceType_PTR,    // pointer RRs
-            kDNSServiceClass_IN,    // internet class records
-            mdns_lookup_callback,   // callback
-            result      // Context - result buffer
-            );
-
-    if (errcode)
-    {
-        syslog (LOG_WARNING,
-                "mdns: Failed to initialise mdns lookup, error %d",
-                errcode
-                );
-        return set_err_mdns_failed (result);
-    }
-
-    status = handle_events (sdref, result, addr_str);
-    DNSServiceRefDeallocate (sdref);
-    return status;
-}
-
-
-/*
-    Wait on result of callback, and process it when it arrives.
-
-    Parameters
-        sdref
-            dns-sd reference
-        result
-            Initialised 'result' data structure.
-        str
-            lookup string, used for status/error reporting.
- */
-static nss_status
-handle_events (DNSServiceRef sdref, result_map_t * result, const char * str)
-{
-    int dns_sd_fd = DNSServiceRefSockFD(sdref);
-    int nfds = dns_sd_fd + 1;
-    fd_set readfds;
-    struct timeval tv;
-    int select_result;
-
-    while (!result->done)
-    {
-        FD_ZERO(&readfds);
-        FD_SET(dns_sd_fd, &readfds);
-
-        tv = k_select_time;
-
-        select_result =
-            select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
-        if (select_result > 0)
-        {
-            if (FD_ISSET(dns_sd_fd, &readfds))
-            {
-                if (MDNS_VERBOSE)
-                    syslog (LOG_DEBUG,
-                            "mdns: Reply received for %s",
-                            str
-                            );
-                DNSServiceProcessResult(sdref);
-            }
-            else
-            {
-                syslog (LOG_WARNING,
-                        "mdns: Unexpected return from select on lookup of %s",
-                        str
-                        );
-            }
-        }
-        else
-        {
-            // Terminate loop due to timer expiry
-            if (MDNS_VERBOSE)
-                syslog (LOG_DEBUG,
-                        "mdns: %s not found - timer expired",
-                        str
-                        );
-            set_err_notfound (result);
-            break;
-        }
-    }
-
-    return result->status;
-}
-
-
-/*
-    Examine incoming data and add to relevant fields in result structure.
-    This routine is called from DNSServiceProcessResult where appropriate.
- */
-void
-mdns_lookup_callback
-(
-    DNSServiceRef sdref,
-    DNSServiceFlags flags,
-    uint32_t interface_index,
-    DNSServiceErrorType error_code,
-    const char          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void          *rdata,
-    uint32_t ttl,
-    void                *context
-)
-{
-    // A single record is received
-
-    result_map_t * result = (result_map_t *) context;
-
-    (void)sdref; // Unused
-    (void)interface_index; // Unused
-    (void)ttl; // Unused
-
-    if (!(flags & kDNSServiceFlagsMoreComing) )
-    {
-        result->done = 1;
-    }
-
-    if (error_code == kDNSServiceErr_NoError)
-    {
-        ns_type_t expected_rr_type =
-            af_to_rr (result->hostent->h_addrtype);
-
-        // Idiot check class
-        if (rrclass != C_IN)
-        {
-            syslog (LOG_WARNING,
-                    "mdns: Received bad RR class: expected %d (%s),"
-                    " got %d (%s), RR type %d (%s)",
-                    C_IN,
-                    ns_class_to_str (C_IN),
-                    rrclass,
-                    ns_class_to_str (rrclass),
-                    rrtype,
-                    ns_type_to_str (rrtype)
-                    );
-            return;
-        }
-
-        // If a PTR
-        if (rrtype == kDNSServiceType_PTR)
-        {
-            if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
-                return;
-        }
-        else if (rrtype == expected_rr_type)
-        {
-            if (!
-                add_hostname_or_alias (
-                    result,
-                    fullname,
-                    strlen (fullname)
-                    )
-                )
-            {
-                result->done = 1;
-                return;
-                // Abort on error
-            }
-
-            if (!add_address_to_buffer (result, rdata, rdlen) )
-            {
-                result->done = 1;
-                return;
-                // Abort on error
-            }
-        }
-        else
-        {
-            syslog (LOG_WARNING,
-                    "mdns: Received bad RR type: expected %d (%s),"
-                    " got %d (%s)",
-                    expected_rr_type,
-                    ns_type_to_str (expected_rr_type),
-                    rrtype,
-                    ns_type_to_str (rrtype)
-                    );
-            return;
-        }
-
-        if (result->status != NSS_STATUS_SUCCESS)
-            set_err_success (result);
-    }
-    else
-    {
-        // For now, dump message to syslog and continue
-        syslog (LOG_WARNING,
-                "mdns: callback returned error %d",
-                error_code
-                );
-    }
-}
-
-static int
-callback_body_ptr (
-    const char * fullname,
-    result_map_t * result,
-    int rdlen,
-    const void * rdata
-    )
-{
-    char result_name [k_hostname_maxlen + 1];
-    int rv;
-
-    // Fullname should be .in-addr.arpa or equivalent, which we're
-    // not interested in.  Ignore it.
-
-    rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
-    if (rv < 0)
-    {
-        const char * errmsg;
-
-        switch (rv)
-        {
-        case DNS_RDATA_TO_NAME_BAD_FORMAT:
-            errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
-            break;
-
-        case DNS_RDATA_TO_NAME_TOO_LONG:
-            errmsg = "mdns: PTR '%s' result too long ('%s...')";
-            break;
-
-        case DNS_RDATA_TO_NAME_PTR:
-            errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
-            break;
-
-        default:
-            errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
-        }
-
-        syslog (LOG_WARNING,
-                errmsg,
-                fullname,
-                result_name
-                );
-
-        return -1;
-    }
-
-    if (MDNS_VERBOSE)
-    {
-        syslog (LOG_DEBUG,
-                "mdns: PTR '%s' resolved to '%s'",
-                fullname,
-                result_name
-                );
-    }
-
-    // Data should be a hostname
-    if (!
-        add_hostname_or_alias (
-            result,
-            result_name,
-            rv
-            )
-        )
-    {
-        result->done = 1;
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/*
-    Add an address to the buffer.
-
-    Parameter
-        result
-            Result structure to write to
-        data
-            Incoming address data buffer
-            Must be 'int' aligned
-        len
-            Length of data buffer (in bytes)
-            Must match data alignment
-
-    Result
-        Pointer to start of newly written data,
-        or NULL on error.
-        If address already exists in buffer, returns pointer to that instead.
- */
-static void *
-add_address_to_buffer (result_map_t * result, const void * data, int len)
-{
-    int new_addr;
-    void * start;
-    void * temp;
-
-    if ((temp = contains_address (result, data, len)))
-    {
-        return temp;
-    }
-
-    if (result->addrs_count >= k_addrs_max)
-    {
-        // Not enough addr slots
-        set_err_internal_resource_full (result);
-        syslog (LOG_ERR,
-                "mdns: Internal address buffer full; increase size"
-                );
-        return NULL;
-    }
-
-    // Idiot check
-    if (len != result->hostent->h_length)
-    {
-        syslog (LOG_WARNING,
-                "mdns: Unexpected rdata length for address.  Expected %d, got %d",
-                result->hostent->h_length,
-                len
-                );
-        // XXX And continue for now.
-    }
-
-    new_addr = result->addr_idx + len;
-
-    if (new_addr > result->alias_idx)
-    {
-        // Not enough room
-        set_err_buf_too_small (result);
-        if (MDNS_VERBOSE)
-            syslog (LOG_DEBUG,
-                    "mdns: Ran out of buffer when adding address %d",
-                    result->addrs_count + 1
-                    );
-        return NULL;
-    }
-
-    start = result->buffer + result->addr_idx;
-    memcpy (start, data, len);
-    result->addr_idx = new_addr;
-    result->header->addrs [result->addrs_count] = start;
-    result->addrs_count++;
-    result->header->addrs [result->addrs_count] = NULL;
-
-    return start;
-}
-
-
-static void *
-contains_address (result_map_t * result, const void * data, int len)
-{
-    int i;
-
-    // Idiot check
-    if (len != result->hostent->h_length)
-    {
-        syslog (LOG_WARNING,
-                "mdns: Unexpected rdata length for address.  Expected %d, got %d",
-                result->hostent->h_length,
-                len
-                );
-        // XXX And continue for now.
-    }
-
-    for (i = 0; result->header->addrs [i]; i++)
-    {
-        if (memcmp (result->header->addrs [i], data, len) == 0)
-        {
-            return result->header->addrs [i];
-        }
-    }
-
-    return NULL;
-}
-
-
-/*
-    Add an alias to the buffer.
-
-    Parameter
-        result
-            Result structure to write to
-        data
-            Incoming alias (null terminated)
-        len
-            Length of data buffer (in bytes), including trailing null
-
-    Result
-        Pointer to start of newly written data,
-        or NULL on error
-        If alias already exists in buffer, returns pointer to that instead.
- */
-static char *
-add_alias_to_buffer (result_map_t * result, const char * data, int len)
-{
-    int new_alias;
-    char * start;
-    char * temp;
-
-    if ((temp = contains_alias (result, data)))
-    {
-        return temp;
-    }
-
-    if (result->aliases_count >= k_aliases_max)
-    {
-        // Not enough alias slots
-        set_err_internal_resource_full (result);
-        syslog (LOG_ERR,
-                "mdns: Internal alias buffer full; increase size"
-                );
-        return NULL;
-    }
-
-    new_alias = result->alias_idx - len;
-
-    if (new_alias < result->addr_idx)
-    {
-        // Not enough room
-        set_err_buf_too_small (result);
-        if (MDNS_VERBOSE)
-            syslog (LOG_DEBUG,
-                    "mdns: Ran out of buffer when adding alias %d",
-                    result->aliases_count + 1
-                    );
-        return NULL;
-    }
-
-    start = result->buffer + new_alias;
-    memcpy (start, data, len);
-    result->alias_idx = new_alias;
-    result->header->aliases [result->aliases_count] = start;
-    result->aliases_count++;
-    result->header->aliases [result->aliases_count] = NULL;
-
-    return start;
-}
-
-
-static char *
-contains_alias (result_map_t * result, const char * alias)
-{
-    int i;
-
-    for (i = 0; result->header->aliases [i]; i++)
-    {
-        if (strcmp (result->header->aliases [i], alias) == 0)
-        {
-            return result->header->aliases [i];
-        }
-    }
-
-    return NULL;
-}
-
-
-/*
-    Add fully qualified hostname to result.
-
-    Parameter
-        result
-            Result structure to write to
-        fullname
-            Fully qualified hostname
-
-    Result
-        Pointer to start of hostname buffer,
-        or NULL on error (usually hostname too long)
- */
-
-static char *
-add_hostname_len (result_map_t * result, const char * fullname, int len)
-{
-    if (len >= k_hostname_maxlen)
-    {
-        set_err_bad_hostname (result);
-        syslog (LOG_WARNING,
-                "mdns: Hostname too long '%.*s': len %d, max %d",
-                len,
-                fullname,
-                len,
-                k_hostname_maxlen
-                );
-        return NULL;
-    }
-
-    result->hostent->h_name =
-        strcpy (result->header->hostname, fullname);
-
-    return result->header->hostname;
-}
-
-
-/*
-    Add fully qualified name as hostname or alias.
-
-    If hostname is not fully qualified this is not an error, but the data
-    returned may be not what the application wanted.
-
-    Parameter
-        result
-            Result structure to write to
-        data
-            Incoming alias (null terminated)
-        len
-            Length of data buffer (in bytes), including trailing null
-
-    Result
-        Pointer to start of newly written data,
-        or NULL on error
-        If alias or hostname already exists, returns pointer to that instead.
- */
-static char *
-add_hostname_or_alias (result_map_t * result, const char * data, int len)
-{
-    char * hostname = result->hostent->h_name;
-
-    if (*hostname)
-    {
-        if (strcmp (hostname, data) == 0)
-        {
-            return hostname;
-        }
-        else
-        {
-            return add_alias_to_buffer (result, data, len);
-        }
-    }
-    else
-    {
-        return add_hostname_len (result, data, len);
-    }
-}
-
-
-static int
-init_result (
-    result_map_t * result,
-    hostent * result_buf,
-    char * buf,
-    size_t buflen
-    )
-{
-    if (buflen < sizeof (buf_header_t))
-    {
-        return ERANGE;
-    }
-
-    result->hostent = result_buf;
-    result->header = (buf_header_t *) buf;
-    result->header->hostname[0] = 0;
-    result->aliases_count = 0;
-    result->header->aliases[0] = NULL;
-    result->addrs_count = 0;
-    result->header->addrs[0] = NULL;
-    result->buffer = buf + sizeof (buf_header_t);
-    result->addr_idx = 0;
-    result->alias_idx = buflen - sizeof (buf_header_t);
-    result->done = 0;
-    set_err_notfound (result);
-
-    // Point hostent to the right buffers
-    result->hostent->h_name = result->header->hostname;
-    result->hostent->h_aliases = result->header->aliases;
-    result->hostent->h_addr_list = result->header->addrs;
-
-    return 0;
-}
-
-/*
-    Set the status in the result.
-
-    Parameters
-        result
-            Result structure to update
-        status
-            New nss_status value
-        err
-            New errno value
-        herr
-            New h_errno value
-
-    Returns
-        New status value
- */
-static nss_status
-set_err (result_map_t * result, nss_status status, int err, int herr)
-{
-    result->status = status;
-    result->r_errno = err;
-    result->r_h_errno = herr;
-
-    return status;
-}
-
-static nss_status
-set_err_notfound (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
-}
-
-static nss_status
-set_err_bad_hostname (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
-}
-
-static nss_status
-set_err_buf_too_small (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
-}
-
-static nss_status
-set_err_internal_resource_full (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
-}
-
-static nss_status
-set_err_system (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
-}
-
-static nss_status
-set_err_mdns_failed (result_map_t * result)
-{
-    return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
-}
-
-static nss_status
-set_err_success (result_map_t * result)
-{
-    result->status = NSS_STATUS_SUCCESS;
-    return result->status;
-}
-
-
-/*
-    Test whether name is applicable for mdns to process, and if so copy into
-    lookup_name buffer (if non-NULL).
-
-    Returns
-        Pointer to name to lookup up, if applicable, or NULL otherwise.
- */
-static const char *
-is_applicable_name (
-    result_map_t * result,
-    const char * name,
-    char * lookup_name
-    )
-{
-    int match = config_is_mdns_suffix (name);
-    if (match > 0)
-    {
-        if (lookup_name)
-        {
-            strncpy (lookup_name, name, k_hostname_maxlen + 1);
-            return lookup_name;
-        }
-        else
-        {
-            return name;
-        }
-    }
-    else
-    {
-        if (match < 0)
-        {
-            set_err_system (result);
-        }
-        return NULL;
-    }
-}
-
-/*
-    Test whether address is applicable for mdns to process, and if so copy into
-    addr_str buffer as an address suitable for ptr lookup.
-
-    Returns
-        Pointer to name to lookup up, if applicable, or NULL otherwise.
- */
-static const char *
-is_applicable_addr (
-    result_map_t * result,
-    const void * addr,
-    int af,
-    char * addr_str
-    )
-{
-    int match;
-
-    if (!format_reverse_addr (af, addr, -1, addr_str))
-    {
-        if (MDNS_VERBOSE)
-            syslog (LOG_DEBUG,
-                    "mdns: Failed to create reverse address"
-                    );
-        return NULL;
-    }
-
-    if (MDNS_VERBOSE)
-        syslog (LOG_DEBUG,
-                "mdns: Reverse address: %s",
-                addr_str
-                );
-
-    match = config_is_mdns_suffix (addr_str);
-    if (match > 0)
-    {
-        return addr_str;
-    }
-    else
-    {
-        if (match < 0)
-        {
-            set_err_system (result);
-        }
-        return NULL;
-    }
-}
-
-//----------
-// Types and Constants
-
-const char * k_conf_file = "/etc/nss_mdns.conf";
-#define CONF_LINE_SIZE 1024
-
-const char k_comment_char = '#';
-
-const char * k_keyword_domain = "domain";
-
-const char * k_default_domains [] =
-{
-    "local",
-    "254.169.in-addr.arpa",
-    "8.e.f.ip6.int",
-    "8.e.f.ip6.arpa",
-    "9.e.f.ip6.int",
-    "9.e.f.ip6.arpa",
-    "a.e.f.ip6.int",
-    "a.e.f.ip6.arpa",
-    "b.e.f.ip6.int",
-    "b.e.f.ip6.arpa",
-    NULL
-    // Always null terminated
-};
-
-// Linked list of domains
-typedef struct domain_entry
-{
-    char * domain;
-    struct domain_entry * next;
-} domain_entry_t;
-
-
-// Config
-typedef struct
-{
-    domain_entry_t * domains;
-} config_t;
-
-const config_t k_empty_config =
-{
-    NULL
-};
-
-
-// Context - tracks position in config file, used for error reporting
-typedef struct
-{
-    const char * filename;
-    int linenum;
-} config_file_context_t;
-
-
-//----------
-// Local prototypes
-
-static errcode_t
-load_config (config_t * conf);
-
-static errcode_t
-process_config_line (
-    config_t * conf,
-    char * line,
-    config_file_context_t * context
-    );
-
-static char *
-get_next_word (char * input, char **next);
-
-static errcode_t
-default_config (config_t * conf);
-
-static errcode_t
-add_domain (config_t * conf, const char * domain);
-
-static int
-contains_domain (const config_t * conf, const char * domain);
-
-static int
-contains_domain_suffix (const config_t * conf, const char * addr);
-
-
-//----------
-// Global variables
-
-static config_t * g_config = NULL;
-// Configuration info
-
-pthread_mutex_t g_config_mutex =
-#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
-    PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
-#else
-    PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-
-//----------
-// Configuration functions
-
-
-/*
-    Initialise the configuration from the config file.
-
-    Returns
-        0 success
-        non-zero error code on failure
- */
-errcode_t
-init_config ()
-{
-    if (g_config)
-    {
-        /*
-            Safe to test outside mutex.
-            If non-zero, initialisation is complete and g_config can be
-            safely used read-only.  If zero, then we do proper mutex
-            testing before initialisation.
-         */
-        return 0;
-    }
-    else
-    {
-        int errcode = -1;
-        int presult;
-        config_t * temp_config;
-
-        // Acquire mutex
-        presult = pthread_mutex_lock (&g_config_mutex);
-        if (presult)
-        {
-            syslog (LOG_ERR,
-                    "mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
-                    __FILE__, __LINE__, presult, strerror (presult)
-                    );
-            return presult;
-        }
-
-        // Test again now we have mutex, in case initialisation occurred while
-        // we were waiting
-        if (!g_config)
-        {
-            temp_config = (config_t *) malloc (sizeof (config_t));
-            if (temp_config)
-            {
-                // Note: This code will leak memory if initialisation fails
-                // repeatedly.  This should only happen in the case of a memory
-                // error, so I'm not sure if it's a meaningful problem. - AW
-                *temp_config = k_empty_config;
-                errcode = load_config (temp_config);
-
-                if (!errcode)
-                {
-                    g_config = temp_config;
-                }
-            }
-            else
-            {
-                syslog (LOG_ERR,
-                        "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
-                        __FILE__, __LINE__
-                        );
-                errcode = errno;
-            }
-        }
-
-        presult = pthread_mutex_unlock (&g_config_mutex);
-        if (presult)
-        {
-            syslog (LOG_ERR,
-                    "mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
-                    __FILE__, __LINE__, presult, strerror (presult)
-                    );
-            errcode = presult;
-        }
-
-        return errcode;
-    }
-}
-
-
-int
-config_is_mdns_suffix (const char * name)
-{
-    int errcode = init_config ();
-    if (!errcode)
-    {
-        return contains_domain_suffix (g_config, name);
-    }
-    else
-    {
-        errno = errcode;
-        return -1;
-    }
-}
-
-
-//----------
-// Local functions
-
-static errcode_t
-load_config (config_t * conf)
-{
-    FILE * cf;
-    char line [CONF_LINE_SIZE];
-    config_file_context_t context;
-
-    context.filename = k_conf_file;
-    context.linenum = 0;
-
-
-    cf = fopen (context.filename, "r");
-    if (!cf)
-    {
-        syslog (LOG_INFO,
-                "mdns: Couldn't open nss_mdns configuration file %s, using default.",
-                context.filename
-                );
-        return default_config (conf);
-    }
-
-    while (fgets (line, CONF_LINE_SIZE, cf))
-    {
-        int errcode;
-        context.linenum++;
-        errcode = process_config_line (conf, line, &context);
-        if (errcode)
-        {
-            // Critical error, give up
-            fclose(cf);
-            return errcode;
-        }
-    }
-
-    fclose (cf);
-
-    return 0;
-}
-
-
-/*
-    Parse a line of the configuration file.
-    For each keyword recognised, perform appropriate handling.
-    If the keyword is not recognised, print a message to syslog
-    and continue.
-
-    Returns
-        0 success, or recoverable config file error
-        non-zero serious system error, processing aborted
- */
-static errcode_t
-process_config_line (
-    config_t * conf,
-    char * line,
-    config_file_context_t * context
-    )
-{
-    char * curr = line;
-    char * word;
-
-    word = get_next_word (curr, &curr);
-    if (!word || word [0] == k_comment_char)
-    {
-        // Nothing interesting on this line
-        return 0;
-    }
-
-    if (strcmp (word, k_keyword_domain) == 0)
-    {
-        word = get_next_word (curr, &curr);
-        if (word)
-        {
-            int errcode = add_domain (conf, word);
-            if (errcode)
-            {
-                // something badly wrong, bail
-                return errcode;
-            }
-
-            if (get_next_word (curr, NULL))
-            {
-                syslog (LOG_WARNING,
-                        "%s, line %d: ignored extra text found after domain",
-                        context->filename,
-                        context->linenum
-                        );
-            }
-        }
-        else
-        {
-            syslog (LOG_WARNING,
-                    "%s, line %d: no domain specified",
-                    context->filename,
-                    context->linenum
-                    );
-        }
-    }
-    else
-    {
-        syslog (LOG_WARNING,
-                "%s, line %d: unknown keyword %s - skipping",
-                context->filename,
-                context->linenum,
-                word
-                );
-    }
-
-    return 0;
-}
-
-
-/*
-    Get next word (whitespace separated) from input string.
-    A null character is written into the first whitespace character following
-    the word.
-
-    Parameters
-        input
-            Input string.  This string is modified by get_next_word.
-        next
-            If non-NULL and the result is non-NULL, a pointer to the
-            character following the end of the word (after the null)
-            is written to 'next'.
-            If no word is found, the original value is unchanged.
-            If the word extended to the end of the string, 'next' points
-            to the trailling NULL.
-            It is safe to pass 'str' as 'input' and '&str' as 'next'.
-    Returns
-        Pointer to the first non-whitespace character (and thus word) found.
-        if no word is found, returns NULL.
- */
-static char *
-get_next_word (char * input, char **next)
-{
-    char * curr = input;
-    char * result;
-
-    while (isspace (*curr))
-    {
-        curr++;
-    }
-
-    if (*curr == 0)
-    {
-        return NULL;
-    }
-
-    result = curr;
-    while (*curr && !isspace (*curr))
-    {
-        curr++;
-    }
-    if (*curr)
-    {
-        *curr = 0;
-        if (next)
-        {
-            *next = curr+1;
-        }
-    }
-    else
-    {
-        if (next)
-        {
-            *next = curr;
-        }
-    }
-
-    return result;
-}
-
-
-static errcode_t
-default_config (config_t * conf)
-{
-    int i;
-    for (i = 0; k_default_domains [i]; i++)
-    {
-        int errcode =
-            add_domain (conf, k_default_domains [i]);
-        if (errcode)
-        {
-            // Something has gone (badly) wrong - let's bail
-            return errcode;
-        }
-    }
-
-    return 0;
-}
-
-
-static errcode_t
-add_domain (config_t * conf, const char * domain)
-{
-    if (!contains_domain (conf, domain))
-    {
-        domain_entry_t * d =
-            (domain_entry_t *) malloc (sizeof (domain_entry_t));
-        if (!d)
-        {
-            syslog (LOG_ERR,
-                    "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
-                    __FILE__, __LINE__
-                    );
-            return ENOMEM;
-        }
-
-        d->domain = strdup (domain);
-        if (!d->domain)
-        {
-            syslog (LOG_ERR,
-                    "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
-                    __FILE__, __LINE__
-                    );
-            free (d);
-            return ENOMEM;
-        }
-        d->next = conf->domains;
-        conf->domains = d;
-    }
-
-    return 0;
-}
-
-
-static int
-contains_domain (const config_t * conf, const char * domain)
-{
-    const domain_entry_t * curr = conf->domains;
-
-    while (curr != NULL)
-    {
-        if (strcasecmp (curr->domain, domain) == 0)
-        {
-            return 1;
-        }
-
-        curr = curr->next;
-    }
-
-    return 0;
-}
-
-
-static int
-contains_domain_suffix (const config_t * conf, const char * addr)
-{
-    const domain_entry_t * curr = conf->domains;
-
-    while (curr != NULL)
-    {
-        if (cmp_dns_suffix (addr, curr->domain) > 0)
-        {
-            return 1;
-        }
-
-        curr = curr->next;
-    }
-
-    return 0;
-}
-
-//----------
-// Types and Constants
-
-static const char * k_local_suffix = "local";
-static const char k_dns_separator = '.';
-
-static const unsigned int k_label_maxlen = DNS_LABEL_MAXLEN;
-// Label entries longer than this are actually pointers.
-
-typedef struct
-{
-    int value;
-    const char * name;
-    const char * comment;
-} table_entry_t;
-
-static const table_entry_t k_table_af [] =
-{
-    { AF_UNSPEC, NULL, NULL },
-    { AF_LOCAL, "LOCAL", NULL },
-    { AF_UNIX, "UNIX", NULL },
-    { AF_INET, "INET", NULL },
-    { AF_INET6, "INET6", NULL }
-};
-static const int k_table_af_size =
-    sizeof (k_table_af) / sizeof (*k_table_af);
-
-static const char * k_table_ns_class [] =
-{
-    NULL,
-    "IN"
-};
-static const int k_table_ns_class_size =
-    sizeof (k_table_ns_class) / sizeof (*k_table_ns_class);
-
-static const char * k_table_ns_type [] =
-{
-    NULL,
-    "A",
-    "NS",
-    "MD",
-    "MF",
-    "CNAME",
-    "SOA",
-    "MB",
-    "MG",
-    "MR",
-    "NULL",
-    "WKS",
-    "PTR",
-    "HINFO",
-    "MINFO",
-    "MX",
-    "TXT",
-    "RP",
-    "AFSDB",
-    "X25",
-    "ISDN",
-    "RT",
-    "NSAP",
-    NULL,
-    "SIG",
-    "KEY",
-    "PX",
-    "GPOS",
-    "AAAA",
-    "LOC",
-    "NXT",
-    "EID",
-    "NIMLOC",
-    "SRV",
-    "ATMA",
-    "NAPTR",
-    "KX",
-    "CERT",
-    "A6",
-    "DNAME",
-    "SINK",
-    "OPT"
-};
-static const int k_table_ns_type_size =
-    sizeof (k_table_ns_type) / sizeof (*k_table_ns_type);
-
-
-//----------
-// Local prototypes
-
-static int
-simple_table_index (const char * table [], int size, const char * str);
-
-static int
-table_index_name (const table_entry_t table [], int size, const char * str);
-
-static int
-table_index_value (const table_entry_t table [], int size, int n);
-
-
-//----------
-// Global variables
-
-
-//----------
-// Util functions
-
-int
-count_dots (const char * name)
-{
-    int count = 0;
-    int i;
-    for (i = 0; name[i]; i++)
-    {
-        if (name [i] == k_dns_separator)
-            count++;
-    }
-
-    return count;
-}
-
-
-int
-islocal (const char * name)
-{
-    return cmp_dns_suffix (name, k_local_suffix) > 0;
-}
-
-
-int
-rr_to_af (ns_type_t rrtype)
-{
-    switch (rrtype)
-    {
-    case kDNSServiceType_A:
-        return AF_INET;
-
-    case kDNSServiceType_AAAA:
-        return AF_INET6;
-
-    default:
-        return AF_UNSPEC;
-    }
-}
-
-
-ns_type_t
-af_to_rr (int af)
-{
-    switch (af)
-    {
-    case AF_INET:
-        return kDNSServiceType_A;
-
-    case AF_INET6:
-        return kDNSServiceType_AAAA;
-
-    default:
-        //return ns_t_invalid;
-        return 0;
-    }
-}
-
-
-int
-str_to_af (const char * str)
-{
-    int result =
-        table_index_name (k_table_af, k_table_af_size, str);
-    if (result < 0)
-        result = 0;
-
-    return k_table_af [result].value;
-}
-
-
-ns_class_t
-str_to_ns_class (const char * str)
-{
-    return (ns_class_t)
-           simple_table_index (k_table_ns_class, k_table_ns_class_size, str);
-}
-
-
-ns_type_t
-str_to_ns_type (const char * str)
-{
-    return (ns_type_t)
-           simple_table_index (k_table_ns_type, k_table_ns_type_size, str);
-}
-
-
-const char *
-af_to_str (int in)
-{
-    int result =
-        table_index_value (k_table_af, k_table_af_size, in);
-    if (result < 0)
-        result = 0;
-
-    return k_table_af [result].name;
-}
-
-
-const char *
-ns_class_to_str (ns_class_t in)
-{
-    if (in < k_table_ns_class_size)
-        return k_table_ns_class [in];
-    else
-        return NULL;
-}
-
-
-const char *
-ns_type_to_str (ns_type_t in)
-{
-    if (in < k_table_ns_type_size)
-        return k_table_ns_type [in];
-    else
-        return NULL;
-}
-
-
-char *
-format_reverse_addr_in (
-    const struct in_addr * addr,
-    int prefixlen,
-    char * buf
-    )
-{
-    char * curr = buf;
-    int i;
-
-    const uint8_t * in_addr_a = (uint8_t *) addr;
-
-    if (prefixlen > 32)
-        return NULL;
-    if (prefixlen < 0)
-        prefixlen = 32;
-
-    i = (prefixlen + 7) / 8;
-    // divide prefixlen into bytes, rounding up
-
-    while (i > 0)
-    {
-        i--;
-        curr += sprintf (curr, "%d.", in_addr_a [i]);
-    }
-    sprintf (curr, "in-addr.arpa");
-
-    return buf;
-}
-
-
-char *
-format_reverse_addr_in6 (
-    const struct in6_addr * addr,
-    int prefixlen,
-    char * buf
-    )
-{
-    char * curr = buf;
-    int i;
-
-    const uint8_t * in_addr_a = (uint8_t *) addr;
-
-    if (prefixlen > 128)
-        return NULL;
-    if (prefixlen < 0)
-        prefixlen = 128;
-
-    i = (prefixlen + 3) / 4;
-    // divide prefixlen into nibbles, rounding up
-
-    // Special handling for first
-    if (i % 2)
-    {
-        curr += sprintf (curr, "%d.", (in_addr_a [i/2] >> 4) & 0x0F);
-    }
-    i >>= 1;
-    // Convert i to bytes (divide by 2)
-
-    while (i > 0)
-    {
-        uint8_t val;
-
-        i--;
-        val = in_addr_a [i];
-        curr += sprintf (curr, "%x.%x.", val & 0x0F, (val >> 4) & 0x0F);
-    }
-    sprintf (curr, "ip6.arpa");
-
-    return buf;
-}
-
-
-char *
-format_reverse_addr (
-    int af,
-    const void * addr,
-    int prefixlen,
-    char * buf
-    )
-{
-    switch (af)
-    {
-    case AF_INET:
-        return
-            format_reverse_addr_in (
-                (struct in_addr *) addr, prefixlen, buf
-                );
-        break;
-
-    case AF_INET6:
-        return
-            format_reverse_addr_in6 (
-                (struct in6_addr *) addr, prefixlen, buf
-                );
-        break;
-
-    default:
-        return NULL;
-    }
-}
-
-
-int
-cmp_dns_suffix (const char * name, const char * domain)
-{
-    const char * nametail;
-    const char * domaintail;
-
-    // Idiot checks
-    if (*name == 0 || *name == k_dns_separator)
-    {
-        // Name can't be empty or start with separator
-        return CMP_DNS_SUFFIX_BAD_NAME;
-    }
-
-    if (*domain == 0)
-    {
-        return CMP_DNS_SUFFIX_SUCCESS;
-        // trivially true
-    }
-
-    if (*domain == k_dns_separator)
-    {
-        // drop leading separator from domain
-        domain++;
-        if (*domain == k_dns_separator)
-        {
-            return CMP_DNS_SUFFIX_BAD_DOMAIN;
-        }
-    }
-
-    // Find ends of strings
-    for (nametail = name; *nametail; nametail++)
-        ;
-    for (domaintail = domain; *domaintail; domaintail++)
-        ;
-
-    // Shuffle back to last real character, and drop any trailing '.'
-    // while we're at it.
-    nametail--;
-    if (*nametail == k_dns_separator)
-    {
-        nametail--;
-        if (*nametail == k_dns_separator)
-        {
-            return CMP_DNS_SUFFIX_BAD_NAME;
-        }
-    }
-    domaintail--;
-    if (*domaintail == k_dns_separator)
-    {
-        domaintail--;
-        if (*domaintail == k_dns_separator)
-        {
-            return CMP_DNS_SUFFIX_BAD_DOMAIN;
-        }
-    }
-
-    // Compare.
-    while (
-        nametail >= name
-        && domaintail >= domain
-        && tolower(*nametail) == tolower(*domaintail))
-    {
-        nametail--;
-        domaintail--;
-    }
-
-    /* A successful finish will be one of the following:
-        (leading and trailing . ignored)
-
-        name  :  domain2.domain1
-        domain:  domain2.domain1
-                ^
-
-        name  : domain3.domain2.domain1
-        domain:         domain2.domain1
-                       ^
-     */
-    if (
-        domaintail < domain
-        && (nametail < name || *nametail == k_dns_separator)
-        )
-    {
-        return CMP_DNS_SUFFIX_SUCCESS;
-    }
-    else
-    {
-        return CMP_DNS_SUFFIX_FAILURE;
-    }
-}
-
-
-static int
-dns_rdata_to_name (const unsigned char * rdata, int rdlen, char * name, unsigned int name_len)
-{
-    int i = 0;
-    // Index into 'name'
-    const unsigned char * rdata_curr = rdata;
-
-    if (rdlen == 0) return DNS_RDATA_TO_NAME_BAD_FORMAT;
-
-    /*
-        In RDATA, a DNS name is stored as a series of labels.
-        Each label consists of a length octet (max value 63)
-        followed by the data for that label.
-        The series is terminated with a length 0 octet.
-        A length octet beginning with bits 11 is a pointer to
-        somewhere else in the payload, but we don't support these
-        since we don't have access to the entire payload.
-
-        See RFC1034 section 3.1 and RFC1035 section 3.1.
-     */
-    while (1)
-    {
-        unsigned int term_len = *rdata_curr;
-        rdata_curr++;
-
-        if (term_len == 0)
-        {
-            break;
-            // 0 length record terminates label
-        }
-        else if (term_len > k_label_maxlen)
-        {
-            name [i] = 0;
-            return DNS_RDATA_TO_NAME_PTR;
-        }
-        else if (rdata_curr + term_len > rdata + rdlen)
-        {
-            name [i] = 0;
-            return DNS_RDATA_TO_NAME_BAD_FORMAT;
-        }
-
-        if (name_len < i + term_len + 1)
-        // +1 is separator
-        {
-            name [i] = 0;
-            return DNS_RDATA_TO_NAME_TOO_LONG;
-        }
-
-        memcpy (name + i, rdata_curr, term_len);
-
-        i += term_len;
-        rdata_curr += term_len;
-
-        name [i] = k_dns_separator;
-        i++;
-    }
-
-    name [i] = 0;
-    return i;
-}
-
-
-//----------
-// Local functions
-
-/*
-    Find the index of an string entry in a table.  A case insenitive match
-    is performed.  If no entry is found, 0 is returned.
-
-    Parameters
-        table
-            Lookup table
-            Table entries may be NULL.  NULL entries will never match.
-        size
-            number of entries in table
-        str
-            lookup string
-
-    Result
-        index of first matching entry, or 0 if no matches
- */
-static int
-simple_table_index (const char * table [], int size, const char * str)
-{
-    int i;
-    for (i = 0; i < size; i++)
-    {
-        if (
-            table [i]
-            && (strcasecmp (table [i], str) == 0)
-            )
-        {
-            return i;
-        }
-    }
-
-    return 0;
-}
-
-
-/*
-    Find the index of a name in a table.
-
-    Parameters
-        table
-            array of table_entry_t records.  The name field is compared
-            (ignoring case) to the input string.
-        size
-            number of entries in table
-        str
-            lookup string
-
-    Result
-        index of first matching entry, or -1 if no matches
- */
-static int
-table_index_name (const table_entry_t table [], int size, const char * str)
-{
-    int i;
-    for (i = 0; i < size; i++)
-    {
-        if (
-            table [i].name
-            && (strcasecmp (table [i].name, str) == 0)
-            )
-        {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-
-/*
-    Find the index of a value a table.
-
-    Parameters
-        table
-            array of table_entry_t records.  The value field is compared to
-            the input value
-        size
-            number of entries in table
-        n
-            lookup value
-
-    Result
-        index of first matching entry, or -1 if no matches
- */
-static int
-table_index_value (const table_entry_t table [], int size, int n)
-{
-    int i;
-    for (i = 0; i < size; i++)
-    {
-        if (table [i].value == n)
-        {
-            return i;
-        }
-    }
-
-    return -1;
-}
diff --git a/mDNSShared/ClientRequests.c b/mDNSShared/ClientRequests.c
deleted file mode 100644
index 4081106..0000000
--- a/mDNSShared/ClientRequests.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-/*
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- */
-
-#include "ClientRequests.h"
-
-#include "DNSCommon.h"
-#include "uDNS.h"
-#include "mdns_strict.h"
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-#include "D2D.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-#include "mDNSMacOSX.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-#include "resolved_cache.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
-#include <dispatch/dispatch.h>
-#include <net/if.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-#include <WebFilterDNS/WebFilterDNS.h>
-
-int WCFIsServerRunning(WCFConnection *conn) __attribute__((weak_import));
-int WCFNameResolvesToAddr(WCFConnection *conn, char* domainName, struct sockaddr* address, uid_t userid) __attribute__((weak_import));
-int WCFNameResolvesToName(WCFConnection *conn, char* fromName, char* toName, uid_t userid) __attribute__((weak_import));
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec.h"
-#endif
-
-#define RecordTypeIsAddress(TYPE)   (((TYPE) == kDNSType_A) || ((TYPE) == kDNSType_AAAA))
-
-extern mDNS mDNSStorage;
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-extern domainname ActiveDirectoryPrimaryDomain;
-#endif
-
-// Normally we append search domains only for queries with a single label that are not fully qualified. This can be
-// overridden to apply search domains for queries (that are not fully qualified) with any number of labels e.g., moon,
-// moon.cs, moon.cs.be, etc. - Mohan
-mDNSBool AlwaysAppendSearchDomains = mDNSfalse;
-
-// Control enabling optimistic DNS - Phil
-mDNSBool EnableAllowExpired = mDNStrue;
-
-typedef struct
-{
-    mDNSu32                 requestID;
-    const domainname *      qname;
-    mDNSu16                 qtype;
-    mDNSu16                 qclass;
-    mDNSInterfaceID         interfaceID;
-    mDNSs32                 serviceID;
-    mDNSu32                 flags;
-    mDNSBool                appendSearchDomains;
-    mDNSs32                 effectivePID;
-    const mDNSu8 *          effectiveUUID;
-    mDNSu32                 peerUID;
-    mDNSBool                isInAppBrowserRequest;
-    mDNSBool                useAAAAFallback;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mDNSu8 *          resolverUUID;
-	mdns_dns_service_id_t	customID;
-    mDNSBool                needEncryption;
-    mDNSBool                useFailover;
-    mDNSBool                failoverMode;
-    mDNSBool                prohibitEncryptedDNS;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    const audit_token_t *   peerAuditToken;
-    const audit_token_t *   delegatorAuditToken;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    dnssd_log_privacy_level_t logPrivacyLevel;
-#endif
-
-}   QueryRecordOpParams;
-
-mDNSlocal void QueryRecordOpParamsInit(QueryRecordOpParams *inParams)
-{
-	mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
-    inParams->serviceID = -1;
-}
-
-mDNSlocal mStatus QueryRecordOpCreate(QueryRecordOp **outOp);
-mDNSlocal void QueryRecordOpFree(QueryRecordOp *operation);
-mDNSlocal mStatus QueryRecordOpStart(QueryRecordOp *inOp, const QueryRecordOpParams *inParams,
-    QueryRecordResultHandler inResultHandler, void *inResultContext);
-mDNSlocal void QueryRecordOpStop(QueryRecordOp *op);
-mDNSlocal mDNSBool QueryRecordOpIsMulticast(const QueryRecordOp *op);
-mDNSlocal void QueryRecordOpCallback(mDNS *m, DNSQuestion *inQuestion, const ResourceRecord *inAnswer,
-    QC_result inAddRecord);
-mDNSlocal void QueryRecordOpResetHandler(DNSQuestion *inQuestion);
-mDNSlocal mStatus QueryRecordOpStartQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion);
-mDNSlocal mStatus QueryRecordOpStopQuestion(DNSQuestion *inQuestion);
-mDNSlocal mStatus QueryRecordOpRestartUnicastQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion,
-    const domainname *inSearchDomain);
-mDNSlocal mStatus InterfaceIndexToInterfaceID(mDNSu32 inInterfaceIndex, mDNSInterfaceID *outInterfaceID);
-mDNSlocal mDNSBool DomainNameIsSingleLabel(const domainname *inName);
-mDNSlocal mDNSBool StringEndsWithDot(const char *inString);
-mDNSlocal const domainname * NextSearchDomain(QueryRecordOp *inOp);
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-mDNSlocal mDNSBool DomainNameIsInSearchList(const domainname *domain, mDNSBool inExcludeLocal);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-mDNSlocal void NotifyWebContentFilter(const ResourceRecord *inAnswer, uid_t inUID);
-#endif
-
-mDNSexport void GetAddrInfoClientRequestParamsInit(GetAddrInfoClientRequestParams *inParams)
-{
-	mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
-}
-
-mDNSexport mStatus GetAddrInfoClientRequestStart(GetAddrInfoClientRequest *inRequest,
-    const GetAddrInfoClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext)
-{
-    mStatus             err;
-    domainname          hostname;
-    mDNSBool            appendSearchDomains;
-    mDNSInterfaceID     interfaceID;
-    DNSServiceFlags     flags;
-    mDNSs32             serviceID;
-    QueryRecordOpParams opParams;
-
-    if (!MakeDomainNameFromDNSNameString(&hostname, inParams->hostnameStr))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%u] ERROR: bad hostname '" PRI_S "'", inParams->requestID, inParams->hostnameStr);
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    if (inParams->protocols & ~((mDNSu32)(kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6)))
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    flags = inParams->flags;
-    if (inParams->protocols == 0)
-    {
-        flags |= kDNSServiceFlagsSuppressUnusable;
-        inRequest->protocols = kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6;
-    }
-    else
-    {
-        inRequest->protocols = inParams->protocols;
-    }
-
-    if (flags & kDNSServiceFlagsServiceIndex)
-    {
-        // NOTE: kDNSServiceFlagsServiceIndex flag can only be set for DNSServiceGetAddrInfo()
-        LogInfo("GetAddrInfoClientRequestStart: kDNSServiceFlagsServiceIndex is SET by the client");
-
-        // If kDNSServiceFlagsServiceIndex is SET, interpret the interfaceID as the serviceId and set the interfaceID to 0.
-        serviceID   = (mDNSs32)inParams->interfaceIndex;
-        interfaceID = mDNSNULL;
-    }
-    else
-    {
-        serviceID = -1;
-        err = InterfaceIndexToInterfaceID(inParams->interfaceIndex, &interfaceID);
-        if (err) goto exit;
-    }
-    inRequest->interfaceID = interfaceID;
-
-    if (!StringEndsWithDot(inParams->hostnameStr) && (AlwaysAppendSearchDomains || DomainNameIsSingleLabel(&hostname)))
-    {
-        appendSearchDomains = mDNStrue;
-    }
-    else
-    {
-        appendSearchDomains = mDNSfalse;
-    }
-    QueryRecordOpParamsInit(&opParams);
-    opParams.requestID              = inParams->requestID;
-    opParams.qname                  = &hostname;
-    opParams.qclass                 = kDNSClass_IN;
-    opParams.interfaceID            = inRequest->interfaceID;
-    opParams.serviceID              = serviceID;
-    opParams.flags                  = flags;
-    opParams.appendSearchDomains    = appendSearchDomains;
-    opParams.effectivePID           = inParams->effectivePID;
-    opParams.effectiveUUID          = inParams->effectiveUUID;
-    opParams.peerUID                = inParams->peerUID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    opParams.resolverUUID           = inParams->resolverUUID;
-    opParams.customID               = inParams->customID;
-    opParams.needEncryption         = inParams->needEncryption;
-    opParams.useFailover            = inParams->useFailover;
-    opParams.failoverMode           = inParams->failoverMode;
-    opParams.prohibitEncryptedDNS   = inParams->prohibitEncryptedDNS;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    opParams.peerAuditToken         = inParams->peerAuditToken;
-    opParams.delegatorAuditToken    = inParams->delegatorAuditToken;
-    opParams.isInAppBrowserRequest  = inParams->isInAppBrowserRequest;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    opParams.logPrivacyLevel        = inParams->logPrivacyLevel;
-#endif
-
-    if (inRequest->protocols & kDNSServiceProtocol_IPv6)
-    {
-        err = QueryRecordOpCreate(&inRequest->op6);
-        if (err) goto exit;
-
-        opParams.qtype = kDNSType_AAAA;
-        err = QueryRecordOpStart(inRequest->op6, &opParams, inResultHandler, inResultContext);
-        if (err) goto exit;
-    }
-    if (inRequest->protocols & kDNSServiceProtocol_IPv4)
-    {
-        err = QueryRecordOpCreate(&inRequest->op4);
-        if (err) goto exit;
-
-        opParams.qtype = kDNSType_A;
-        err = QueryRecordOpStart(inRequest->op4, &opParams, inResultHandler, inResultContext);
-        if (err) goto exit;
-    }
-    err = mStatus_NoError;
-
-exit:
-    if (err) GetAddrInfoClientRequestStop(inRequest);
-    return err;
-}
-
-mDNSexport void GetAddrInfoClientRequestStop(GetAddrInfoClientRequest *inRequest)
-{
-    if (inRequest->op4) QueryRecordOpStop(inRequest->op4);
-    if (inRequest->op6) QueryRecordOpStop(inRequest->op6);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-    {
-        const QueryRecordOp * const     op4 = inRequest->op4;
-        const QueryRecordOp * const     op6 = inRequest->op6;
-        const DNSQuestion *             q4  = mDNSNULL;
-        const DNSQuestion *             q6  = mDNSNULL;
-
-        if (op4)
-        {
-            if (op4->answered)
-            {
-                // If we have a v4 answer and if we timed out prematurely before, provide a trigger to the upper layer so
-                // that it can retry questions if needed. - Mohan
-                q4 = &op4->q;
-            }
-            else if (op4->q.TimeoutQuestion)
-            {
-                // If we are not delivering answers, we may be timing out prematurely. Note down the current state so that
-                // we know to retry when we see a valid response again. - Mohan
-                mDNSPlatformUpdateDNSStatus(&op4->q);
-            }
-        }
-        if (op6)
-        {
-            if (op6->answered)
-            {
-                q6 = &op6->q;
-            }
-            else if (op6->q.TimeoutQuestion)
-            {
-                mDNSPlatformUpdateDNSStatus(&op6->q);
-            }
-        }
-        mDNSPlatformTriggerDNSRetry(q4, q6);
-    }
-#endif
-
-    if (inRequest->op4)
-    {
-        QueryRecordOpFree(inRequest->op4);
-        inRequest->op4 = mDNSNULL;
-    }
-    if (inRequest->op6)
-    {
-        QueryRecordOpFree(inRequest->op6);
-        inRequest->op6 = mDNSNULL;
-    }
-}
-
-mDNSexport const domainname * GetAddrInfoClientRequestGetQName(const GetAddrInfoClientRequest *inRequest)
-{
-    if (inRequest->op4) return &inRequest->op4->q.qname;
-    if (inRequest->op6) return &inRequest->op6->q.qname;
-    return (const domainname *)"";
-}
-
-mDNSexport mDNSBool GetAddrInfoClientRequestIsMulticast(const GetAddrInfoClientRequest *inRequest)
-{
-    if ((inRequest->op4 && QueryRecordOpIsMulticast(inRequest->op4)) ||
-        (inRequest->op6 && QueryRecordOpIsMulticast(inRequest->op6)))
-    {
-        return mDNStrue;
-    }
-    return mDNSfalse;
-}
-
-mDNSexport void QueryRecordClientRequestParamsInit(QueryRecordClientRequestParams *inParams)
-{
-	mDNSPlatformMemZero(inParams, (mDNSu32)sizeof(*inParams));
-}
-
-mDNSexport mStatus QueryRecordClientRequestStart(QueryRecordClientRequest *inRequest,
-    const QueryRecordClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext)
-{
-    mStatus             err;
-    domainname          qname;
-    mDNSInterfaceID     interfaceID;
-    mDNSBool            appendSearchDomains;
-    QueryRecordOpParams opParams;
-
-    err = InterfaceIndexToInterfaceID(inParams->interfaceIndex, &interfaceID);
-    if (err) goto exit;
-
-    if (!MakeDomainNameFromDNSNameString(&qname, inParams->qnameStr))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%u] ERROR: bad domain name '" PRI_S "'", inParams->requestID, inParams->qnameStr);
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-
-    if (RecordTypeIsAddress(inParams->qtype) && !StringEndsWithDot(inParams->qnameStr) &&
-        (AlwaysAppendSearchDomains || DomainNameIsSingleLabel(&qname)))
-    {
-        appendSearchDomains = mDNStrue;
-    }
-    else
-    {
-        appendSearchDomains = mDNSfalse;
-    }
-    QueryRecordOpParamsInit(&opParams);
-    opParams.requestID              = inParams->requestID;
-    opParams.qname                  = &qname;
-    opParams.flags                  = inParams->flags;
-    opParams.qtype                  = inParams->qtype;
-    opParams.qclass                 = inParams->qclass;
-    opParams.interfaceID            = interfaceID;
-    opParams.appendSearchDomains    = appendSearchDomains;
-    opParams.effectivePID           = inParams->effectivePID;
-    opParams.effectiveUUID          = inParams->effectiveUUID;
-    opParams.peerUID                = inParams->peerUID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    opParams.resolverUUID           = inParams->resolverUUID;
-    opParams.customID               = inParams->customID;
-    opParams.needEncryption         = inParams->needEncryption;
-    opParams.useFailover            = inParams->useFailover;
-    opParams.failoverMode           = inParams->failoverMode;
-    opParams.prohibitEncryptedDNS   = inParams->prohibitEncryptedDNS;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    opParams.peerAuditToken         = inParams->peerAuditToken;
-    opParams.delegatorAuditToken    = inParams->delegatorAuditToken;
-    opParams.isInAppBrowserRequest  = inParams->isInAppBrowserRequest;
-#endif
-    opParams.useAAAAFallback        = inParams->useAAAAFallback;
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    opParams.logPrivacyLevel        = inParams->logPrivacyLevel;
-#endif
-
-    err = QueryRecordOpStart(&inRequest->op, &opParams, inResultHandler, inResultContext);
-
-exit:
-    if (err) QueryRecordClientRequestStop(inRequest);
-    return err;
-}
-
-mDNSexport void QueryRecordClientRequestStop(QueryRecordClientRequest *inRequest)
-{
-    QueryRecordOpStop(&inRequest->op);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-    if (inRequest->op.answered)
-    {
-        DNSQuestion *v4q, *v6q;
-        // If we are receiving positive answers, provide the hint to the upper layer. - Mohan
-        v4q = (inRequest->op.q.qtype == kDNSType_A)    ? &inRequest->op.q : mDNSNULL;
-        v6q = (inRequest->op.q.qtype == kDNSType_AAAA) ? &inRequest->op.q : mDNSNULL;
-        mDNSPlatformTriggerDNSRetry(v4q, v6q);
-    }
-#endif
-}
-
-mDNSexport const domainname * QueryRecordClientRequestGetQName(const QueryRecordClientRequest *inRequest)
-{
-    return &inRequest->op.q.qname;
-}
-
-mDNSexport mDNSu16 QueryRecordClientRequestGetType(const QueryRecordClientRequest *inRequest)
-{
-    return inRequest->op.q.qtype;
-}
-
-mDNSexport mDNSBool QueryRecordClientRequestIsMulticast(QueryRecordClientRequest *inRequest)
-{
-    return (QueryRecordOpIsMulticast(&inRequest->op) ? mDNStrue : mDNSfalse);
-}
-
-mDNSlocal mStatus QueryRecordOpCreate(QueryRecordOp **outOp)
-{
-    mStatus err;
-    QueryRecordOp *op;
-
-    op = (QueryRecordOp *) mDNSPlatformMemAllocateClear(sizeof(*op));
-    if (!op)
-    {
-        err = mStatus_NoMemoryErr;
-        goto exit;
-    }
-    *outOp = op;
-    err = mStatus_NoError;
-
-exit:
-    return err;
-}
-
-mDNSlocal void QueryRecordOpFree(QueryRecordOp *operation)
-{
-    mDNSPlatformMemFree(operation);
-}
-
-#define VALID_MSAD_SRV_TRANSPORT(T) \
-    (SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_tcp") || SameDomainLabel((T)->c, (const mDNSu8 *)"\x4_udp"))
-#define VALID_MSAD_SRV(Q) ((Q)->qtype == kDNSType_SRV && VALID_MSAD_SRV_TRANSPORT(SecondLabel(&(Q)->qname)))
-
-mDNSlocal mStatus QueryRecordOpStart(QueryRecordOp *inOp, const QueryRecordOpParams *inParams,
-    QueryRecordResultHandler inResultHandler, void *inResultContext)
-{
-    mStatus                 err;
-    DNSQuestion * const     q = &inOp->q;
-    mDNSu32                 len;
-
-    // Save the original qname.
-
-    len = DomainNameLength(inParams->qname);
-    inOp->qname = (domainname *) mDNSPlatformMemAllocate(len);
-    if (!inOp->qname)
-    {
-        err = mStatus_NoMemoryErr;
-        goto exit;
-    }
-    mDNSPlatformMemCopy(inOp->qname, inParams->qname, len);
-
-    inOp->interfaceID          = inParams->interfaceID;
-    inOp->reqID                = inParams->requestID;
-    inOp->resultHandler        = inResultHandler;
-    inOp->resultContext        = inResultContext;
-    inOp->useAAAAFallback      = inParams->useAAAAFallback;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    inOp->useFailover          = inParams->useFailover;
-    inOp->failoverMode         = inParams->failoverMode;
-    inOp->prohibitEncryptedDNS = inParams->prohibitEncryptedDNS;
-    inOp->qtype                = inParams->qtype;
-#endif
-
-    // Set up DNSQuestion.
-
-    if (EnableAllowExpired && (inParams->flags & kDNSServiceFlagsAllowExpiredAnswers))
-    {
-        q->allowExpired = AllowExpired_AllowExpiredAnswers;
-    }
-    else
-    {
-        q->allowExpired = AllowExpired_None;
-    }
-    q->ServiceID = inParams->serviceID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    q->inAppBrowserRequest = inParams->isInAppBrowserRequest;
-    if (inParams->peerAuditToken)
-    {
-        q->peerAuditToken = *inParams->peerAuditToken;
-    }
-    if (inParams->delegatorAuditToken)
-    {
-        q->delegateAuditToken = *inParams->delegatorAuditToken;
-    }
-#endif
-    q->InterfaceID          = inParams->interfaceID;
-    q->flags                = inParams->flags;
-    AssignDomainName(&q->qname, inParams->qname);
-    q->qtype                = inParams->qtype;
-    q->qclass               = inParams->qclass;
-    q->LongLived            = (inParams->flags & kDNSServiceFlagsLongLivedQuery)            ? mDNStrue : mDNSfalse;
-    q->ForceMCast           = (inParams->flags & kDNSServiceFlagsForceMulticast)            ? mDNStrue : mDNSfalse;
-    q->ReturnIntermed       = (inParams->flags & kDNSServiceFlagsReturnIntermediates)       ? mDNStrue : mDNSfalse;
-    q->SuppressUnusable     = (inParams->flags & kDNSServiceFlagsSuppressUnusable)          ? mDNStrue : mDNSfalse;
-    q->TimeoutQuestion      = (inParams->flags & kDNSServiceFlagsTimeout)                   ? mDNStrue : mDNSfalse;
-    q->UseBackgroundTraffic = (inParams->flags & kDNSServiceFlagsBackgroundTrafficClass)    ? mDNStrue : mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    q->enableDNSSEC         = dns_service_flags_enables_dnssec(inParams->flags);
-#endif
-    q->AppendSearchDomains  = inParams->appendSearchDomains;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    q->RequireEncryption    = inParams->needEncryption;
-    q->CustomID             = inParams->customID;
-    if (inOp->failoverMode)
-    {
-        q->IsFailover = mDNStrue;
-        // Force a path evaluation if the DNSQuestion isn't interface-scoped.
-        if (!q->InterfaceID)
-        {
-            q->ForcePathEval = mDNStrue;
-        }
-    }
-    if (inOp->prohibitEncryptedDNS)
-    {
-        q->ProhibitEncryptedDNS = mDNStrue;
-    }
-    else if (inParams->resolverUUID && !q->ProhibitEncryptedDNS)
-    {
-        mDNSPlatformMemCopy(q->ResolverUUID, inParams->resolverUUID, UUID_SIZE);
-    }
-#endif
-    q->InitialCacheMiss     = mDNSfalse;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    q->logPrivacyLevel      = inParams->logPrivacyLevel;
-#endif
-
-    q->pid              = inParams->effectivePID;
-    if (inParams->effectiveUUID)
-    {
-        mDNSPlatformMemCopy(q->uuid, inParams->effectiveUUID, UUID_SIZE);
-    }
-    q->euid             = inParams->peerUID;
-    q->request_id       = inParams->requestID;
-    q->QuestionCallback = QueryRecordOpCallback;
-    q->ResetHandler     = QueryRecordOpResetHandler;
-
-    // For single label queries that are not fully qualified, look at /etc/hosts, cache and try search domains before trying
-    // them on the wire as a single label query. - Mohan
-
-    if (q->AppendSearchDomains && DomainNameIsSingleLabel(inOp->qname)) q->InterfaceID = mDNSInterface_LocalOnly;
-    err = QueryRecordOpStartQuestion(inOp, q);
-    if (err) goto exit;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    if (callExternalHelpers(q->InterfaceID, &q->qname, q->flags))
-    {
-        external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, q->flags, q->pid);
-    }
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-    if ((RecordTypeIsAddress(q->qtype) || VALID_MSAD_SRV(&inOp->q)) && !q->ForceMCast &&
-        SameDomainLabel(LastLabel(&q->qname), (const mDNSu8 *)&localdomain))
-    {
-        DNSQuestion *       q2;
-
-        q2 = (DNSQuestion *) mDNSPlatformMemAllocate((mDNSu32)sizeof(*inOp->q2));
-        if (!q2)
-        {
-            err = mStatus_NoMemoryErr;
-            goto exit;
-        }
-        inOp->q2 = q2;
-
-        *q2 = *q;
-        q2->IsUnicastDotLocal = mDNStrue;
-
-        if ((CountLabels(&q2->qname) == 2) && !SameDomainName(&q2->qname, &ActiveDirectoryPrimaryDomain)
-            && !DomainNameIsInSearchList(&q2->qname, mDNSfalse))
-        {
-            inOp->q2Type                = q2->qtype;
-            inOp->q2LongLived           = q2->LongLived;
-            inOp->q2ReturnIntermed      = q2->ReturnIntermed;
-            inOp->q2TimeoutQuestion     = q2->TimeoutQuestion;
-            inOp->q2AppendSearchDomains = q2->AppendSearchDomains;
-
-            AssignDomainName(&q2->qname, &localdomain);
-            q2->qtype                   = kDNSType_SOA;
-            q2->LongLived               = mDNSfalse;
-            q2->ReturnIntermed          = mDNStrue;
-            q2->TimeoutQuestion         = mDNSfalse;
-            q2->AppendSearchDomains     = mDNSfalse;
-        }
-
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%u] QueryRecordOpStart: starting parallel unicast query for " PRI_DM_NAME " " PUB_S,
-               inOp->reqID, DM_NAME_PARAM(&q2->qname), DNSTypeName(q2->qtype));
-
-        err = QueryRecordOpStartQuestion(inOp, q2);
-        if (err) goto exit;
-    }
-#endif
-    err = mStatus_NoError;
-
-exit:
-    if (err) QueryRecordOpStop(inOp);
-    return err;
-}
-
-mDNSlocal void QueryRecordOpStop(QueryRecordOp *op)
-{
-    if (op->q.QuestionContext)
-    {
-        QueryRecordOpStopQuestion(&op->q);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        if (callExternalHelpers(op->q.InterfaceID, op->qname, op->q.flags))
-        {
-            external_stop_browsing_for_service(op->q.InterfaceID, &op->q.qname, op->q.qtype, op->q.flags, op->q.pid);
-        }
-#endif
-    }
-    if (op->qname)
-    {
-        mDNSPlatformMemFree(op->qname);
-        op->qname = mDNSNULL;
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-    if (op->q2)
-    {
-        if (op->q2->QuestionContext) QueryRecordOpStopQuestion(op->q2);
-        mDNSPlatformMemFree(op->q2);
-        op->q2 = mDNSNULL;
-    }
-#endif
-}
-
-mDNSlocal mDNSBool QueryRecordOpIsMulticast(const QueryRecordOp *op)
-{
-    return ((mDNSOpaque16IsZero(op->q.TargetQID) && (op->q.ThisQInterval > 0)) ? mDNStrue : mDNSfalse);
-}
-
-// GetTimeNow is a callback-safe alternative to mDNS_TimeNow(), which expects to be called with m->mDNS_busy == 0.
-mDNSlocal mDNSs32 GetTimeNow(mDNS *m)
-{
-    mDNSs32 time;
-    mDNS_Lock(m);
-    time = m->timenow;
-    mDNS_Unlock(m);
-    return time;
-}
-
-mDNSlocal void QueryRecordOpCallback(mDNS *m, DNSQuestion *inQuestion, const ResourceRecord *inAnswer, QC_result inAddRecord)
-{
-    mStatus                     resultErr;
-    QueryRecordOp *const        op = (QueryRecordOp *)inQuestion->QuestionContext;
-    const domainname *          domain;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-    if ((inQuestion == op->q2) && (inQuestion->qtype == kDNSType_SOA))
-    {
-        DNSQuestion * const     q2 = op->q2;
-
-        if (inAnswer->rrtype != kDNSType_SOA) goto exit;
-        QueryRecordOpStopQuestion(q2);
-
-        // Restore DNSQuestion variables that were modified for the SOA query.
-
-        q2->qtype               = op->q2Type;
-        q2->LongLived           = op->q2LongLived;
-        q2->ReturnIntermed      = op->q2ReturnIntermed;
-        q2->TimeoutQuestion     = op->q2TimeoutQuestion;
-        q2->AppendSearchDomains = op->q2AppendSearchDomains;
-
-        if (inAnswer->RecordType != kDNSRecordTypePacketNegative)
-        {
-            QueryRecordOpRestartUnicastQuestion(op, q2, mDNSNULL);
-        }
-        else if (q2->AppendSearchDomains)
-        {
-            domain = NextSearchDomain(op);
-            if (domain) QueryRecordOpRestartUnicastQuestion(op, q2, domain);
-        }
-        goto exit;
-    }
-#endif
-
-    if (inAddRecord == QC_suppressed)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-               "[R%u] QueryRecordOpCallback: Suppressed question " PRI_DM_NAME " (" PUB_S ")",
-               op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype));
-
-        resultErr = kDNSServiceErr_NoSuchRecord;
-    }
-    else if (inAnswer->RecordType == kDNSRecordTypePacketNegative)
-    {
-        if (inQuestion->TimeoutQuestion && ((GetTimeNow(m) - inQuestion->StopTime) >= 0))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                   "[R%u] QueryRecordOpCallback: Question " PRI_DM_NAME " (" PUB_S ") timing out, InterfaceID %p",
-                   op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype),
-                   inQuestion->InterfaceID);
-            resultErr = kDNSServiceErr_Timeout;
-        }
-        else
-        {
-            if (inQuestion->AppendSearchDomains && (op->searchListIndex >= 0) && inAddRecord)
-            {
-                domain = NextSearchDomain(op);
-                if (domain || DomainNameIsSingleLabel(op->qname))
-                {
-                    QueryRecordOpStopQuestion(inQuestion);
-                    QueryRecordOpRestartUnicastQuestion(op, inQuestion, domain);
-                    goto exit;
-                }
-            }
-            if (op->useAAAAFallback && (inQuestion->qtype == kDNSType_AAAA) && (inAnswer->rcode != kDNSFlag1_RC_NXDomain))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                    "[R%u] Restarting question for " PRI_DM_NAME " AAAA record as question for A record (RCODE %d)",
-                    op->reqID, DM_NAME_PARAM(&inQuestion->qname), inAnswer->rcode);
-                QueryRecordOpStopQuestion(inQuestion);
-                inQuestion->qtype = kDNSType_A;
-                QueryRecordOpStartQuestion(op, inQuestion);
-                goto exit;
-            }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-            if (op->useFailover && !inQuestion->IsFailover && inQuestion->dnsservice &&
-                mdns_dns_service_allows_failover(inQuestion->dnsservice))
-            {
-                QueryRecordOpStopQuestion(inQuestion);
-                inQuestion->qtype = op->qtype; // Ensure that the original QTYPE is used in case AAAA fallback was used.
-                inQuestion->IsFailover = mDNStrue;
-                // Force a path evaluation if the DNSQuestion isn't interface-scoped.
-                if (!inQuestion->InterfaceID)
-                {
-                    inQuestion->ForcePathEval = mDNStrue;
-                }
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                    "[R%u] Restarting question for " PRI_DM_NAME " (" PUB_S ") due to DNS service failover",
-                    op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype));
-                domain = mDNSNULL;
-                if (inQuestion->AppendSearchDomains)
-                {
-                    op->searchListIndex = 0; // Reset search list usage
-                    domain = NextSearchDomain(op);
-                }
-                QueryRecordOpRestartUnicastQuestion(op, inQuestion, domain);
-                goto exit;
-            }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-            if (!inAnswer->InterfaceID && IsLocalDomain(inAnswer->name))
-            {
-                if ((RecordTypeIsAddress(inQuestion->qtype) && (inAnswer->rcode == kDNSFlag1_RC_NoErr)) ||
-                    DomainNameIsInSearchList(&inQuestion->qname, mDNStrue))
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                           "[R%u] QueryRecordOpCallback: Question " PRI_DM_NAME " (" PUB_S ") answering local with negative unicast response",
-                           op->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype));
-                }
-                else
-                {
-                    goto exit;
-                }
-            }
-#endif
-            resultErr = kDNSServiceErr_NoSuchRecord;
-        }
-    }
-    else
-    {
-        resultErr = kDNSServiceErr_NoError;
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-    if ((resultErr != kDNSServiceErr_Timeout) && (inAddRecord == QC_add))
-    {
-        op->answered = mDNStrue;
-    }
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-    if (resolved_cache_is_enabled()                             &&
-        inAddRecord                                             &&
-        !mDNSOpaque16IsZero(inQuestion->TargetQID)              &&
-        !LocalOnlyOrP2PInterface(inAnswer->InterfaceID)         &&
-        inAnswer->RecordType != kDNSRecordTypePacketNegative    &&
-        ((inAnswer->rrtype == kDNSServiceType_A)        ||
-         (inAnswer->rrtype == kDNSServiceType_AAAA)))
-    {
-        const void *data_ptr;
-        if (inAnswer->rrtype == kDNSServiceType_A)
-        {
-            data_ptr = inAnswer->rdata->u.ipv4.b;
-        }
-        else if (inAnswer->rrtype == kDNSServiceType_AAAA)
-        {
-            data_ptr = inAnswer->rdata->u.ipv6.b;
-        }
-        resolved_cache_append_address(inQuestion, inAnswer->rrtype, data_ptr);
-    }
-#endif
-
-    // The result handler is allowed to stop the client request, so it's not safe to touch the DNSQuestion or
-    // the QueryRecordOp unless m->CurrentQuestion still points to this DNSQuestion.
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-    const uid_t euid = inQuestion->euid;
-#endif
-    if (op->resultHandler) op->resultHandler(m, inQuestion, inAnswer, inAddRecord, resultErr, op->resultContext);
-    if (m->CurrentQuestion == inQuestion)
-    {
-        if (resultErr == kDNSServiceErr_Timeout) QueryRecordOpStopQuestion(inQuestion);
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-    NotifyWebContentFilter(inAnswer, euid);
-#endif
-
-exit:
-    return;
-}
-
-mDNSlocal void QueryRecordOpResetHandler(DNSQuestion *inQuestion)
-{
-    QueryRecordOp *const        op = (QueryRecordOp *)inQuestion->QuestionContext;
-
-    AssignDomainName(&inQuestion->qname, op->qname);
-    if (inQuestion->AppendSearchDomains && DomainNameIsSingleLabel(op->qname))
-    {
-        inQuestion->InterfaceID = mDNSInterface_LocalOnly;
-    }
-    else
-    {
-        inQuestion->InterfaceID = op->interfaceID;
-    }
-    op->searchListIndex = 0;
-}
-
-mDNSlocal mStatus QueryRecordOpStartQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion)
-{
-    mStatus     err;
-
-    inQuestion->QuestionContext = inOp;
-    err = mDNS_StartQuery(&mDNSStorage, inQuestion);
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%u] ERROR: QueryRecordOpStartQuestion mDNS_StartQuery for " PRI_DM_NAME " " PUB_S " failed with error %d",
-               inOp->reqID, DM_NAME_PARAM(&inQuestion->qname), DNSTypeName(inQuestion->qtype), err);
-        inQuestion->QuestionContext = mDNSNULL;
-    }
-    return err;
-}
-
-mDNSlocal mStatus QueryRecordOpStopQuestion(DNSQuestion *inQuestion)
-{
-    mStatus     err;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-    resolved_cache_delete(inQuestion);
-#endif
-    err = mDNS_StopQuery(&mDNSStorage, inQuestion);
-    inQuestion->QuestionContext = mDNSNULL;
-    return err;
-}
-
-mDNSlocal mStatus QueryRecordOpRestartUnicastQuestion(QueryRecordOp *inOp, DNSQuestion *inQuestion,
-    const domainname *inSearchDomain)
-{
-    mStatus     err;
-
-    inQuestion->InterfaceID = inOp->interfaceID;
-    AssignDomainName(&inQuestion->qname, inOp->qname);
-    if (inSearchDomain) AppendDomainName(&inQuestion->qname, inSearchDomain);
-    if (SameDomainLabel(LastLabel(&inQuestion->qname), (const mDNSu8 *)&localdomain))
-    {
-        inQuestion->IsUnicastDotLocal = mDNStrue;
-    }
-    else
-    {
-        inQuestion->IsUnicastDotLocal = mDNSfalse;
-    }
-    err = QueryRecordOpStartQuestion(inOp, inQuestion);
-    return err;
-}
-
-mDNSlocal mStatus InterfaceIndexToInterfaceID(mDNSu32 inInterfaceIndex, mDNSInterfaceID *outInterfaceID)
-{
-    mStatus             err;
-    mDNSInterfaceID     interfaceID;
-
-    interfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, inInterfaceIndex);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
-    // The request is scoped to a specific interface index, but the interface is not currently in our list.
-    if ((inInterfaceIndex != kDNSServiceInterfaceIndexAny) && (interfaceID == mDNSInterface_Any))
-    {
-        static dispatch_once_t      getLoopbackIndexOnce = 0;
-        static mDNSu32              loopbackIndex = 0;
-
-        dispatch_once(&getLoopbackIndexOnce,
-        ^{
-            loopbackIndex = if_nametoindex("lo0");
-        });
-
-        // If it's one of the specially defined inteface index values, just return an error. Also, caller should return an
-        // error immediately if lo0 is not configured into the current active interfaces. See <rdar://problem/21967160>.
-        if ((inInterfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
-            (inInterfaceIndex == kDNSServiceInterfaceIndexUnicast)   ||
-            (inInterfaceIndex == kDNSServiceInterfaceIndexP2P)       ||
-            (inInterfaceIndex == kDNSServiceInterfaceIndexBLE)       ||
-            (inInterfaceIndex == loopbackIndex))
-        {
-            LogInfo("ERROR: bad interfaceIndex %d", inInterfaceIndex);
-            err = mStatus_BadParamErr;
-            goto exit;
-        }
-
-        // Otherwise, use the specified interface index value and the request will be applied to that interface when it
-        // comes up.
-        interfaceID = (mDNSInterfaceID)(uintptr_t)inInterfaceIndex;
-        LogInfo("Query pending for interface index %d", inInterfaceIndex);
-    }
-#endif
-
-    *outInterfaceID = interfaceID;
-    err = mStatus_NoError;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNREADY_INTERFACES)
-exit:
-#endif
-    return err;
-}
-
-mDNSlocal mDNSBool DomainNameIsSingleLabel(const domainname *inName)
-{
-    const mDNSu8 *const     label = inName->c;
-    return (((label[0] != 0) && (label[1 + label[0]] == 0)) ? mDNStrue : mDNSfalse);
-}
-
-mDNSlocal mDNSBool StringEndsWithDot(const char *inString)
-{
-    const char *        ptr;
-    mDNSu32             escapeCount;
-    mDNSBool            result;
-
-    // Loop invariant: escapeCount is the number of consecutive escape characters that immediately precede *ptr.
-    // - If escapeCount is even, then *ptr is immediately preceded by escapeCount / 2 consecutive literal backslash
-    //   characters, so *ptr is not escaped.
-    // - If escapeCount is odd, then *ptr is immediately preceded by (escapeCount - 1) / 2 consecutive literal backslash
-    //   characters followed by an escape character, so *ptr is escaped.
-    escapeCount = 0;
-    result = mDNSfalse;
-    for (ptr = inString; *ptr != '\0'; ptr++)
-    {
-        if (*ptr == '\\')
-        {
-            escapeCount++;
-        }
-        else
-        {
-            if ((*ptr == '.') && (ptr[1] == '\0'))
-            {
-                if ((escapeCount % 2) == 0) result = mDNStrue;
-                break;
-            }
-            escapeCount = 0;
-        }
-    }
-    return result;
-}
-
-mDNSlocal const domainname * NextSearchDomain(QueryRecordOp *inOp)
-{
-    const domainname *      domain;
-
-    while ((domain = uDNS_GetNextSearchDomain(inOp->interfaceID, &inOp->searchListIndex, mDNSfalse)) != mDNSNULL)
-    {
-        if ((DomainNameLength(inOp->qname) - 1 + DomainNameLength(domain)) <= MAX_DOMAIN_NAME) break;
-    }
-    if (!domain) inOp->searchListIndex = -1;
-    return domain;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-mDNSlocal mDNSBool DomainNameIsInSearchList(const domainname *inName, mDNSBool inExcludeLocal)
-{
-    const SearchListElem *      item;
-    int                         labelCount, domainLabelCount;
-
-    labelCount = CountLabels(inName);
-    for (item = SearchList; item; item = item->next)
-    {
-        if (inExcludeLocal && SameDomainName(&item->domain, &localdomain)) continue;
-        domainLabelCount = CountLabels(&item->domain);
-        if (labelCount >= domainLabelCount)
-        {
-            if (SameDomainName(&item->domain, SkipLeadingLabels(inName, (labelCount - domainLabelCount))))
-            {
-                return mDNStrue;
-            }
-        }
-    }
-    return mDNSfalse;
-}
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
-mDNSlocal void NotifyWebContentFilter(const ResourceRecord *inAnswer, uid_t inUID)
-{
-    if (WCFIsServerRunning)
-    {
-		const mDNS *const m = &mDNSStorage;
-
-        if (WCFIsServerRunning(m->WCF) && inAnswer->rdlength != 0)
-        {
-			struct sockaddr_storage addr;
-			addr.ss_len = 0;
-			if (inAnswer->rrtype == kDNSType_A || inAnswer->rrtype == kDNSType_AAAA)
-			{
-				if (inAnswer->rrtype == kDNSType_A)
-				{
-					struct sockaddr_in *const sin = (struct sockaddr_in *)&addr;
-					sin->sin_port = 0;
-					// Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this:
-					// sin->sin_addr.s_addr = inAnswer->rdata->u.ipv4.NotAnInteger;
-					if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(mDNSv4Addr)), inAnswer))
-						LogMsg("NotifyWebContentFilter: WCF AF_INET putRData failed");
-					else
-					{
-						addr.ss_len = sizeof (struct sockaddr_in);
-						addr.ss_family = AF_INET;
-					}
-				}
-				else if (inAnswer->rrtype == kDNSType_AAAA)
-				{
-					struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)&addr;
-					sin6->sin6_port = 0;
-					// Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this:
-					// sin6->sin6_addr.__u6_addr.__u6_addr32[0] = inAnswer->rdata->u.ipv6.l[0];
-					// sin6->sin6_addr.__u6_addr.__u6_addr32[1] = inAnswer->rdata->u.ipv6.l[1];
-					// sin6->sin6_addr.__u6_addr.__u6_addr32[2] = inAnswer->rdata->u.ipv6.l[2];
-					// sin6->sin6_addr.__u6_addr.__u6_addr32[3] = inAnswer->rdata->u.ipv6.l[3];
-					if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(mDNSv6Addr)), inAnswer))
-						LogMsg("NotifyWebContentFilter: WCF AF_INET6 putRData failed");
-					else
-					{
-						addr.ss_len = sizeof (struct sockaddr_in6);
-						addr.ss_family = AF_INET6;
-					}
-				}
-				if (addr.ss_len)
-				{
-        			char name[MAX_ESCAPED_DOMAIN_NAME];
-        			ConvertDomainNameToCString(inAnswer->name, name);
-
-					debugf("NotifyWebContentFilter: Name %s, uid %u, addr length %d", name, inUID, addr.ss_len);
-					if (WCFNameResolvesToAddr)
-					{
-						WCFNameResolvesToAddr(m->WCF, name, (struct sockaddr *)&addr, inUID);
-					}
-				}
-			}
-			else if (inAnswer->rrtype == kDNSType_CNAME)
-			{
-				domainname cname;
-        		char name[MAX_ESCAPED_DOMAIN_NAME];
-				char cname_cstr[MAX_ESCAPED_DOMAIN_NAME];
-
-				if (!putRData(mDNSNULL, cname.c, (mDNSu8 *)(cname.c + MAX_DOMAIN_NAME), inAnswer))
-					LogMsg("NotifyWebContentFilter: WCF CNAME putRData failed");
-				else
-				{
-        			ConvertDomainNameToCString(inAnswer->name, name);
-					ConvertDomainNameToCString(&cname, cname_cstr);
-					if (WCFNameResolvesToAddr)
-					{
-						WCFNameResolvesToName(m->WCF, name, cname_cstr, inUID);
-					}
-				}
-			}
-        }
-    }
-}
-#endif
diff --git a/mDNSShared/ClientRequests.h b/mDNSShared/ClientRequests.h
deleted file mode 100644
index c9adaec..0000000
--- a/mDNSShared/ClientRequests.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2018-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __ClientRequests_h
-#define __ClientRequests_h
-
-#include "mDNSEmbeddedAPI.h"
-#include "dns_sd_internal.h"
-
-typedef void (*QueryRecordResultHandler)(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord,
-    DNSServiceErrorType error, void *context);
-
-typedef struct
-{
-    DNSQuestion                 q;                      // DNSQuestion for record query.
-    domainname *                qname;                  // Name of the original record.
-    mDNSInterfaceID             interfaceID;            // Interface over which to perform query.
-    QueryRecordResultHandler    resultHandler;          // Handler for query record operation results.
-    void *                      resultContext;          // Context to pass to result handler.
-    mDNSu32                     reqID;                  // Client request ID.
-    int                         searchListIndex;        // Index that indicates the next search domain to try.
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DOTLOCAL)
-    DNSQuestion *               q2;                     // DNSQuestion for unicast version of a record with a dot-local name.
-    mDNSu16                     q2Type;                 // q2's original qtype value.
-    mDNSBool                    q2LongLived;            // q2's original LongLived value.
-    mDNSBool                    q2ReturnIntermed;       // q2's original ReturnIntermed value.
-    mDNSBool                    q2TimeoutQuestion;      // q2's original TimeoutQuestion value.
-    mDNSBool                    q2AppendSearchDomains;  // q2's original AppendSearchDomains value.
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, REACHABILITY_TRIGGER)
-    mDNSBool                    answered;               // True if the query was answered.
-#endif
-    mDNSBool                    useAAAAFallback;        // If a AAAA question gets a negative answer, it's restarted as an A.
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSu16                     qtype;                  // Original QTYPE.
-    mDNSBool                    useFailover;            // Use DNS service failover if applicable.
-    mDNSBool                    failoverMode;           // Use DNS service failover immediately.
-    mDNSBool                    prohibitEncryptedDNS;   // Prohibit use of encrypted DNS protocols.
-#endif
-
-}   QueryRecordOp;
-
-typedef struct
-{
-    mDNSInterfaceID     interfaceID;    // InterfaceID being used for query record operations.
-    mDNSu32             protocols;      // Protocols (IPv4, IPv6) specified by client.
-    QueryRecordOp *     op4;            // Query record operation object for A record.
-    QueryRecordOp *     op6;            // Query record operation object for AAAA record.
-
-}   GetAddrInfoClientRequest;
-
-typedef struct
-{
-    QueryRecordOp       op; // Query record operation object.
-
-}   QueryRecordClientRequest;
-
-typedef struct
-{
-    mDNSu32                 requestID;
-    const char *            hostnameStr;
-    mDNSu32                 interfaceIndex;
-    DNSServiceFlags         flags;
-    mDNSu32                 protocols;
-    mDNSs32                 effectivePID;
-    const mDNSu8 *          effectiveUUID;
-    mDNSu32                 peerUID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mDNSu8 *          resolverUUID;
-    mdns_dns_service_id_t   customID;
-    mDNSBool                needEncryption;
-    mDNSBool                useFailover;
-    mDNSBool                failoverMode;
-    mDNSBool                prohibitEncryptedDNS;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    const audit_token_t *   peerAuditToken;
-    const audit_token_t *   delegatorAuditToken;
-    mDNSBool                isInAppBrowserRequest;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    dnssd_log_privacy_level_t logPrivacyLevel;
-#endif
-
-}   GetAddrInfoClientRequestParams;
-
-typedef struct
-{
-    mDNSu32                 requestID;
-    const char *            qnameStr;
-    mDNSu32                 interfaceIndex;
-    DNSServiceFlags         flags;
-    mDNSu16                 qtype;
-    mDNSu16                 qclass;
-    mDNSs32                 effectivePID;
-    const mDNSu8 *          effectiveUUID;
-    mDNSu32                 peerUID;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    const mDNSu8 *          resolverUUID;
-	mdns_dns_service_id_t	customID;
-    mDNSBool                needEncryption;
-    mDNSBool                useFailover;
-    mDNSBool                failoverMode;
-    mDNSBool                prohibitEncryptedDNS;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    const audit_token_t *   peerAuditToken;
-    const audit_token_t *   delegatorAuditToken;
-    mDNSBool                isInAppBrowserRequest;
-#endif
-    mDNSBool                useAAAAFallback;
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    dnssd_log_privacy_level_t logPrivacyLevel;
-#endif
-
-}   QueryRecordClientRequestParams;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-mDNSexport void GetAddrInfoClientRequestParamsInit(GetAddrInfoClientRequestParams *inParams);
-mDNSexport mStatus GetAddrInfoClientRequestStart(GetAddrInfoClientRequest *inRequest,
-    const GetAddrInfoClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext);
-mDNSexport void GetAddrInfoClientRequestStop(GetAddrInfoClientRequest *inRequest);
-mDNSexport const domainname * GetAddrInfoClientRequestGetQName(const GetAddrInfoClientRequest *inRequest);
-mDNSexport mDNSBool GetAddrInfoClientRequestIsMulticast(const GetAddrInfoClientRequest *inRequest);
-
-mDNSexport void QueryRecordClientRequestParamsInit(QueryRecordClientRequestParams *inParams);
-mDNSexport mStatus QueryRecordClientRequestStart(QueryRecordClientRequest *inRequest,
-    const QueryRecordClientRequestParams *inParams, QueryRecordResultHandler inResultHandler, void *inResultContext);
-mDNSexport void QueryRecordClientRequestStop(QueryRecordClientRequest *inRequest);
-mDNSexport const domainname * QueryRecordClientRequestGetQName(const QueryRecordClientRequest *inRequest);
-mDNSexport mDNSu16 QueryRecordClientRequestGetType(const QueryRecordClientRequest *inRequest);
-mDNSexport mDNSBool QueryRecordClientRequestIsMulticast(QueryRecordClientRequest *inRequest);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // __ClientRequests_h
diff --git a/mDNSShared/CommonServices.h b/mDNSShared/CommonServices.h
deleted file mode 100644
index f4f41dc..0000000
--- a/mDNSShared/CommonServices.h
+++ /dev/null
@@ -1,1493 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@header		CommonServices
-
-    Common Services for Mac OS X, Linux, Palm, Windows, and Windows CE.
- */
-
-#ifndef __COMMON_SERVICES__
-#define __COMMON_SERVICES__
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#if 0
-#pragma mark == Target ==
-#endif
-
-//===========================================================================================================================
-//	 Target
-//===========================================================================================================================
-
-// Macintosh
-
-#if ( !defined( TARGET_OS_MAC ) )
-    #if ( ( macintosh || __MACH__ ) && (!defined(KERNEL) || !KERNEL) )
-// ConditionalMacros.h in CoreServices will define this TARGET_* flag.
-    #else
-        #define TARGET_OS_MAC           0
-    #endif
-#endif
-
-#if ( !defined( TARGET_API_MAC_OSX_KERNEL ) )
-    #if ( __MACH__ && defined(KERNEL) && KERNEL )
-        #define TARGET_API_MAC_OSX_KERNEL       1
-    #else
-        #define TARGET_API_MAC_OSX_KERNEL       0
-    #endif
-#endif
-
-// FreeBSD
-
-#if ( !defined( TARGET_OS_FREEBSD ) )
-    #if ( defined( __FreeBSD__ ) )
-        #define TARGET_OS_FREEBSD       1
-    #else
-        #define TARGET_OS_FREEBSD       0
-    #endif
-#endif
-
-// Linux
-
-#if ( !defined( TARGET_OS_LINUX ) )
-    #if ( defined( __linux__ ) )
-        #define TARGET_OS_LINUX         1
-    #else
-        #define TARGET_OS_LINUX         0
-    #endif
-#endif
-
-// Solaris
-
-#if ( !defined( TARGET_OS_SOLARIS ) )
-    #if ( defined(solaris) || (defined(__SVR4) && defined(sun)) )
-        #define TARGET_OS_SOLARIS       1
-    #else
-        #define TARGET_OS_SOLARIS       0
-    #endif
-#endif
-
-// Palm
-
-#if ( !defined( TARGET_OS_PALM ) )
-    #if ( defined( __PALMOS_TRAPS__ ) || defined( __PALMOS_ARMLET__ ) )
-        #define TARGET_OS_PALM          1
-    #else
-        #define TARGET_OS_PALM          0
-    #endif
-#endif
-
-// Windows
-
-#if ( !defined( TARGET_OS_WIN32 ) )
-    #if ( macintosh || __MACH__ )
-        #define TARGET_OS_WIN32         0
-    #else
-        #if ( defined( _WIN32 ) )
-            #define TARGET_OS_WIN32     1
-        #else
-            #define TARGET_OS_WIN32     0
-        #endif
-    #endif
-#endif
-
-// Windows CE
-
-#if ( !defined( TARGET_OS_WINDOWS_CE ) )
-    #if ( defined( _WIN32_WCE ) )
-        #define TARGET_OS_WINDOWS_CE    1
-    #else
-        #define TARGET_OS_WINDOWS_CE    0
-    #endif
-#endif
-
-#if 0
-#pragma mark == Includes ==
-#endif
-
-//===========================================================================================================================
-//	 Includes
-//===========================================================================================================================
-
-#if ( !defined(KERNEL) || !KERNEL )
-    #if defined(WIN32) && !defined(_WSPIAPI_COUNTOF)
-        #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-    #endif
-    #include    <stddef.h>
-#endif
-
-#if ( ( (defined(macintosh) && macintosh) || __MACH__ ) && (!defined(KERNEL) || !KERNEL) )
-
-    #if ( defined( __MWERKS__ ) )
-        #if ( __option( c9x ) )
-            #include    <stdbool.h>
-        #endif
-    #else
-        #include    <stdbool.h>
-    #endif
-
-    #include    <stdint.h>
-
-    #if ( __MACH__ )
-
-// Mac OS X
-
-        #include    <sys/types.h>
-        #include    <netinet/in.h>
-        #include    <arpa/inet.h>
-        #include    <fcntl.h>
-        #include    <pthread.h>
-        #include    <sys/ioctl.h>
-        #include    <sys/socket.h>
-        #include    <unistd.h>
-
-    #else
-
-// Classic Mac OS
-
-        #include    <ConditionalMacros.h>
-        #include    <MacTypes.h>
-
-    #endif
-
-#elif ( KERNEL )
-
-// Mac OS X Kernel
-
-    #include    <stdint.h>
-
-    #include    <libkern/OSTypes.h>
-    #include    <sys/types.h>
-
-#elif ( TARGET_OS_FREEBSD )
-
-// FreeBSD
-    #include    <stdint.h>
-    #include    <pthread.h>
-    #include    <netinet/in.h>
-    #include    <arpa/inet.h>
-    #include    <sys/socket.h>
-
-#elif ( TARGET_OS_LINUX )
-
-// Linux
-
-    #include    <stdint.h>
-    #include    <arpa/inet.h>
-
-#elif ( TARGET_OS_SOLARIS )
-
-// Solaris
-
-    #include    <stdint.h>
-
-    #include    <arpa/inet.h>
-    #include    <arpa/nameser.h>
-
-    #if ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) )
-        #define TARGET_RT_LITTLE_ENDIAN     1
-    #endif
-    #if ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) )
-        #define TARGET_RT_BIG_ENDIAN        1
-    #endif
-
-#elif ( TARGET_OS_PALM )
-
-// Palm (no special includes yet).
-
-#elif ( TARGET_OS_WIN32 )
-
-// Windows
-
-    #if ( !defined( WIN32_WINDOWS ) )
-        #define WIN32_WINDOWS       0x0401
-    #endif
-
-    #if ( !defined( _WIN32_WINDOWS ) )
-        #define _WIN32_WINDOWS      0x0401
-    #endif
-
-    #if ( !defined( WIN32_LEAN_AND_MEAN ) )
-        #define WIN32_LEAN_AND_MEAN         // Needed to avoid redefinitions by Windows interfaces.
-    #endif
-
-    #if ( defined( __MWERKS__ ) )
-
-        #if ( __option( c9x ) )
-            #include    <stdbool.h>
-        #endif
-
-        #include    <stdint.h>
-
-    #elif ( defined( _MSC_VER ) )
-
-    #include    "VisualStudioSupport.h"
-
-        #if ( _MSC_VER >= 1900 )
-            #include    <stdint.h>
-            #include    <stdbool.h>
-        #endif
-
-        #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros.
-        #pragma warning( disable:4706 ) // Disable "assignment within conditional expression" for Microsoft headers.
-
-    #endif
-
-    #include    <windows.h>
-    #include    <winsock2.h>
-    #include    <Ws2tcpip.h>
-
-    #if ( defined( _MSC_VER ) )
-        #pragma warning( default:4706 )
-    #endif
-
-#else
-    #error unknown OS - update this file to support your OS
-#endif
-
-#if ( !defined( TARGET_BUILD_MAIN ) )
-    #define TARGET_BUILD_MAIN       1
-#endif
-
-#if 0
-#pragma mark == CPU ==
-#endif
-
-//===========================================================================================================================
-//	CPU
-//===========================================================================================================================
-
-// PowerPC
-
-#if ( !defined( TARGET_CPU_PPC ) )
-    #if ( defined( __ppc__ ) || defined( __PPC__ ) || defined( powerpc ) || defined( ppc ) || defined( _M_MPPC ) )
-        #define TARGET_CPU_PPC              1
-    #else
-        #define TARGET_CPU_PPC              0
-    #endif
-#endif
-
-// x86
-
-#if ( !defined( TARGET_CPU_X86 ) )
-    #if ( __INTEL__ || defined( __i386__ ) || defined( i386 ) || defined( intel ) || defined( _M_IX86 ) )
-        #define TARGET_CPU_X86              1
-    #else
-        #define TARGET_CPU_X86              0
-    #endif
-#endif
-
-// MIPS
-
-#if ( !defined( TARGET_CPU_MIPS ) )
-    #if ( __MIPS__ || defined( MIPS32 ) || 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 ) && !defined( TARGET_CPU_X86 ) && !defined( TARGET_CPU_MIPS ) )
-    #error unknown CPU - update this file to support your CPU
-#endif
-
-#if 0
-#pragma mark == Byte Order ==
-#endif
-
-//===========================================================================================================================
-//	Byte Order
-//===========================================================================================================================
-
-// TARGET_RT_LITTLE_ENDIAN
-
-#if ( !defined( TARGET_RT_LITTLE_ENDIAN ) )
-    #if ( MIPSEL || IL_LITTLE_ENDIAN || defined( __LITTLE_ENDIAN__ )                                         || \
-    ( defined(   BYTE_ORDER ) && defined(   LITTLE_ENDIAN ) && (   BYTE_ORDER ==   LITTLE_ENDIAN ) )   || \
-    ( defined(  _BYTE_ORDER ) && defined(  _LITTLE_ENDIAN ) && (  _BYTE_ORDER ==  _LITTLE_ENDIAN ) )   || \
-    ( defined( __BYTE_ORDER ) && defined( __LITTLE_ENDIAN ) && ( __BYTE_ORDER == __LITTLE_ENDIAN ) )   || \
-    TARGET_CPU_X86 || ( defined( TARGET_RT_BIG_ENDIAN ) && !TARGET_RT_BIG_ENDIAN ) )
-        #define TARGET_RT_LITTLE_ENDIAN     1
-    #else
-        #define TARGET_RT_LITTLE_ENDIAN     0
-    #endif
-#endif
-
-// TARGET_RT_BIG_ENDIAN
-
-#if ( !defined( TARGET_RT_BIG_ENDIAN ) )
-    #if ( MIPSEB || IL_BIG_ENDIAN || defined( __BIG_ENDIAN__ )                                       || \
-    ( defined(   BYTE_ORDER ) && defined(   BIG_ENDIAN ) && (   BYTE_ORDER ==   BIG_ENDIAN ) ) || \
-    ( defined(  _BYTE_ORDER ) && defined(  _BIG_ENDIAN ) && (  _BYTE_ORDER ==  _BIG_ENDIAN ) ) || \
-    ( defined( __BYTE_ORDER ) && defined( __BIG_ENDIAN ) && ( __BYTE_ORDER == __BIG_ENDIAN ) ) || \
-    ( defined( TARGET_RT_LITTLE_ENDIAN ) && !TARGET_RT_LITTLE_ENDIAN ) )
-        #define TARGET_RT_BIG_ENDIAN        1
-    #else
-        #define TARGET_RT_BIG_ENDIAN        0
-    #endif
-#endif
-
-#if ( defined( TARGET_RT_LITTLE_ENDIAN ) && !defined( TARGET_RT_BIG_ENDIAN ) )
-    #if ( TARGET_RT_LITTLE_ENDIAN )
-        #define TARGET_RT_BIG_ENDIAN        0
-    #else
-        #define TARGET_RT_BIG_ENDIAN        1
-    #endif
-#endif
-
-#if ( defined( TARGET_RT_BIG_ENDIAN ) && !defined( TARGET_RT_LITTLE_ENDIAN ) )
-    #if ( TARGET_RT_BIG_ENDIAN )
-        #define TARGET_RT_LITTLE_ENDIAN     0
-    #else
-        #define TARGET_RT_LITTLE_ENDIAN     1
-    #endif
-#endif
-
-#if ( !defined( TARGET_RT_LITTLE_ENDIAN ) || !defined( TARGET_RT_BIG_ENDIAN ) )
-    #error unknown byte order - update this file to support your byte order
-#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
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#if ( !TARGET_OS_MAC )
-    #define CR      '\r'
-#endif
-
-#define LF          '\n'
-#define CRSTR       "\r"
-#define LFSTR       "\n"
-#define CRLF        "\r\n"
-#define CRCR        "\r\r"
-
-#if 0
-#pragma mark == Compatibility ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility
-//===========================================================================================================================
-
-// Macros to allow the same code to work on Windows and other sockets API-compatible platforms.
-
-#if ( TARGET_OS_WIN32 )
-    #define close_compat( X )       closesocket( X )
-    #define errno_compat()          (int) GetLastError()
-    #define set_errno_compat( X )   SetLastError( X )
-    #define EWOULDBLOCK_compat      WSAEWOULDBLOCK
-    #define ETIMEDOUT_compat        WSAETIMEDOUT
-    #define ENOTCONN_compat         WSAENOTCONN
-    #define IsValidSocket( X )      ( ( X ) != INVALID_SOCKET )
-    #define kInvalidSocketRef       INVALID_SOCKET
-typedef SOCKET SocketRef;
-#else
-    #define close_compat( X )       close( X )
-    #define errno_compat()          errno
-    #define set_errno_compat( X )   do { errno = ( X ); } while( 0 )
-    #define EWOULDBLOCK_compat      EWOULDBLOCK
-    #define ETIMEDOUT_compat        ETIMEDOUT
-    #define ENOTCONN_compat         ENOTCONN
-    #define IsValidSocket( X )      ( ( X ) >= 0 )
-    #define kInvalidSocketRef       -1
-typedef int SocketRef;
-#endif
-
-// 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.
-
-#if ( ( TARGET_OS_MAC && !defined( SO_NOADDRERR ) ) || ( TARGET_OS_WIN32 && !defined( EAI_AGAIN ) ) )
-typedef int socklen_t;
-#endif
-
-// ssize_t is not defined on the following platforms so emulate it if not defined:
-//
-// - Mac OS X when not building with BSD headers
-// - Windows
-
-#if ( !defined(_SSIZE_T) && ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_FREEBSD && !TARGET_OS_LINUX && !TARGET_OS_MAC)
-typedef int ssize_t;
-#endif
-
-// sockaddr_storage is not supported on non-IPv6 machines so alias it to an IPv4-compatible structure.
-
-#if ( !defined( AF_INET6 ) )
-        #define sockaddr_storage        sockaddr_in
-        #define ss_family               sin_family
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	SOCKADDR_IS_IP_LOOPBACK
-
-    @abstract	Determines if a sockaddr is an IPv4 or IPv6 loopback address (if IPv6 is supported).
- */
-
-#if ( defined( AF_INET6 ) )
-    #define SOCKADDR_IS_IP_LOOPBACK( SA )                                                           \
-    ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET )                               \
-    ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) )   \
-    : ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET6 )                            \
-    ? IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr )           \
-    : 0
-#else
-    #define SOCKADDR_IS_IP_LOOPBACK( SA )                                                           \
-    ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET )                               \
-    ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) )   \
-    : 0
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	SOCKADDR_IS_IP_LINK_LOCAL
-
-    @abstract	Determines if a sockaddr is an IPv4 or IPv6 link-local address (if IPv6 is supported).
- */
-
-#if ( defined( AF_INET6 ) )
-    #define SOCKADDR_IS_IP_LINK_LOCAL( SA )                                                             \
-    ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET )                                 \
-      ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) &&   \
-          ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) )    \
-      : IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) )
-#else
-    #define SOCKADDR_IS_IP_LINK_LOCAL( SA )                                                             \
-    ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET )                                 \
-      ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) &&   \
-          ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) )    \
-      : 0 )
-#endif
-
-// _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.
-
-#if ( TARGET_OS_WINDOWS_CE )
-    #define _beginthreadex_compat( SECURITY_PTR, STACK_SIZE, START_ADDRESS, ARG_LIST, FLAGS, THREAD_ID_PTR )            \
-    (uintptr_t) CreateThread( SECURITY_PTR, STACK_SIZE, (LPTHREAD_START_ROUTINE) START_ADDRESS, ARG_LIST, FLAGS,    \
-                              (LPDWORD) THREAD_ID_PTR )
-
-    #define _endthreadex_compat( RESULT )       ExitThread( (DWORD) RESULT )
-#elif ( TARGET_OS_WIN32 )
-    #define _beginthreadex_compat               _beginthreadex
-    #define _endthreadex_compat                 _endthreadex
-#endif
-
-// The C99 "inline" keyword is not supported by Microsoft compilers, but they do support __inline so map it when needed.
-
-#if ( defined( _MSC_VER ) )
-    #define inline_compat       __inline
-#else
-    #define inline_compat       inline
-#endif
-
-// Calling conventions
-
-#if ( !defined( CALLBACK_COMPAT ) )
-    #if ( TARGET_OS_WIN32 || TARGET_OS_WINDOWS_CE )
-        #define CALLBACK_COMPAT     CALLBACK
-    #else
-        #define CALLBACK_COMPAT
-    #endif
-#endif
-
-#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	sizeof_array
-
-    @abstract	Determines the number of elements in an array.
- */
-
-#define sizeof_array( X )       ( sizeof( X ) / sizeof( X[ 0 ] ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_element
-
-    @abstract	Determines the size of an array element.
- */
-
-#define sizeof_element( X )     sizeof( X[ 0 ] )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_string
-
-    @abstract	Determines the size of a constant C string, excluding the null terminator.
- */
-
-#define sizeof_string( X )      ( sizeof( ( X ) ) - 1 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_field
-
-    @abstract	Determines the size of a field of a type.
- */
-
-#define sizeof_field( TYPE, FIELD )     sizeof( ( ( (TYPE *) 0 )->FIELD ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	RoundUp
-
-    @abstract	Rounds X up to a multiple of Y.
- */
-
-#define RoundUp( X, Y )     ( ( X ) + ( ( Y ) -( ( X ) % ( Y ) ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@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	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	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	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	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 )
-
-#if 0
-#pragma mark == Types ==
-#endif
-
-//===========================================================================================================================
-//	 Standard Types
-//===========================================================================================================================
-
-#if ( !defined( INT8_MIN ) )
-
-    #define INT8_MIN                    SCHAR_MIN
-
-    #if ( defined( _MSC_VER ) )
-
-// C99 stdint.h not supported in VC++/VS.NET yet.
-
-typedef INT8 int8_t;
-typedef UINT8 uint8_t;
-typedef INT16 int16_t;
-typedef UINT16 uint16_t;
-typedef INT32 int32_t;
-typedef UINT32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-    #endif
-
-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 ( !defined( _MSC_VER ) || TARGET_OS_WINDOWS_CE )
-typedef long int intptr_t;
-typedef unsigned long int uintptr_t;
-    #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 ## L
-#endif
-
-#if ( !defined( INT64_C ) )
-    #if ( defined( _MSC_VER ) )
-        #define INT64_C( value )    value ## i64
-    #else
-        #define INT64_C( value )    value ## LL
-    #endif
-#endif
-
-#if ( !defined( UINT8_C ) )
-    #define UINT8_C( value )        value ## U
-#endif
-
-#if ( !defined( UINT16_C ) )
-    #define UINT16_C( value )       value ## U
-#endif
-
-#if ( !defined( UINT32_C ) )
-    #define UINT32_C( value )       value ## UL
-#endif
-
-#if ( !defined( UINT64_C ) )
-    #if ( defined( _MSC_VER ) )
-        #define UINT64_C( value )   value ## UI64
-    #else
-        #define UINT64_C( value )   value ## ULL
-    #endif
-#endif
-
-// Limits
-
-#if( !defined( UINT32_MAX ) )
-    #define UINT32_MAX      UINT32_C( 4294967295 )
-#endif
-
-#if 0
-#pragma mark == bool ==
-#endif
-
-//===========================================================================================================================
-//	 Boolean Constants and Types
-//===========================================================================================================================
-
-// 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 true and false (Mac builds only).
-//
-// 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.
-
-#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 )
-        #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( __MACTYPES__ ) && !defined( true ) && !defined( false ) )
-        #define true    1
-        #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.
-
-#if ( TARGET_API_MAC_OSX_KERNEL )
-    #define TYPE_BOOL       1
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	CStr255
-
-    @abstract	255 character null-terminated (C-style) string.
- */
-
-typedef char CStr255[ 256 ];
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	TYPE_LONGLONG_NATIVE
-
-    @abstract	Defines whether long long (or its equivalent) is natively supported or requires special libraries.
- */
-
-#if ( !defined( TYPE_LONGLONG_NATIVE ) )
-    #define TYPE_LONGLONG_NATIVE            1
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	long_long_compat
-
-    @abstract	Compatibility type to map to the closest thing to long long and unsigned long long.
-
-    @discussion
-
-    Neither long long nor unsigned long long are supported by Microsoft compilers, but they do support proprietary
-    "__int64" and "unsigned __int64" equivalents so map to those types if the real long long is not supported.
- */
-
-#if ( TARGET_OS_WIN32 )
-typedef __int64 long_long_compat;
-typedef unsigned __int64 unsigned_long_long_compat;
-#else
-typedef signed long long long_long_compat;
-typedef unsigned long long unsigned_long_long_compat;
-#endif
-
-#if 0
-#pragma mark == Errors ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@enum		OSStatus
-
-    @abstract	Status Code
-
-    @constant	kNoErr						    0 No error occurred.
-    @constant	kInProgressErr				    1 Operation in progress.
-    @constant	kUnknownErr					-6700 Unknown error occurred.
-    @constant	kOptionErr					-6701 Option was not acceptable.
-    @constant	kSelectorErr				-6702 Selector passed in is invalid or unknown.
-    @constant	kExecutionStateErr			-6703 Call made in the wrong execution state (e.g. called at interrupt time).
-    @constant	kPathErr					-6704 Path is invalid, too long, or otherwise not usable.
-    @constant	kParamErr					-6705 Parameter is incorrect, missing, or not appropriate.
-    @constant	kParamCountErr				-6706 Incorrect or unsupported number of parameters.
-    @constant	kCommandErr					-6707 Command invalid or not supported.
-    @constant	kIDErr						-6708 Unknown, invalid, or inappropriate identifier.
-    @constant	kStateErr					-6709 Not in appropriate state to perform operation.
-    @constant	kRangeErr					-6710 Index is out of range or not valid.
-    @constant	kRequestErr					-6711 Request was improperly formed or not appropriate.
-    @constant	kResponseErr				-6712 Response was incorrect or out of sequence.
-    @constant	kChecksumErr				-6713 Checksum does not match the actual data.
-    @constant	kNotHandledErr				-6714 Operation was not handled (or not handled completely).
-    @constant	kVersionErr					-6715 Version is not incorrect or not compatibile.
-    @constant	kSignatureErr				-6716 Signature did not match what was expected.
-    @constant	kFormatErr					-6717 Unknown, invalid, or inappropriate file/data format.
-    @constant	kNotInitializedErr			-6718 Action request before needed services were initialized.
-    @constant	kAlreadyInitializedErr		-6719 Attempt made to initialize when already initialized.
-    @constant	kNotInUseErr				-6720 Object not in use (e.g. cannot abort if not already in use).
-    @constant	kInUseErr					-6721 Object is in use (e.g. cannot reuse active param blocks).
-    @constant	kTimeoutErr					-6722 Timeout occurred.
-    @constant	kCanceledErr				-6723 Operation canceled (successful cancel).
-    @constant	kAlreadyCanceledErr			-6724 Operation has already been canceled.
-    @constant	kCannotCancelErr			-6725 Operation could not be canceled (maybe already done or invalid).
-    @constant	kDeletedErr					-6726 Object has already been deleted.
-    @constant	kNotFoundErr				-6727 Something was not found.
-    @constant	kNoMemoryErr				-6728 Not enough memory was available to perform the operation.
-    @constant	kNoResourcesErr				-6729 Resources unavailable to perform the operation.
-    @constant	kDuplicateErr				-6730 Duplicate found or something is a duplicate.
-    @constant	kImmutableErr				-6731 Entity is not changeable.
-    @constant	kUnsupportedDataErr			-6732 Data is unknown or not supported.
-    @constant	kIntegrityErr				-6733 Data is corrupt.
-    @constant	kIncompatibleErr			-6734 Data is not compatible or it is in an incompatible format.
-    @constant	kUnsupportedErr				-6735 Feature or option is not supported.
-    @constant	kUnexpectedErr				-6736 Error occurred that was not expected.
-    @constant	kValueErr					-6737 Value is not appropriate.
-    @constant	kNotReadableErr				-6738 Could not read or reading is not allowed.
-    @constant	kNotWritableErr				-6739 Could not write or writing is not allowed.
-    @constant	kBadReferenceErr			-6740 An invalid or inappropriate reference was specified.
-    @constant	kFlagErr					-6741 An invalid, inappropriate, or unsupported flag was specified.
-    @constant	kMalformedErr				-6742 Something was not formed correctly.
-    @constant	kSizeErr					-6743 Size was too big, too small, or not appropriate.
-    @constant	kNameErr					-6744 Name was not correct, allowed, or appropriate.
-    @constant	kNotReadyErr				-6745 Device or service is not ready.
-    @constant	kReadErr					-6746 Could not read.
-    @constant	kWriteErr					-6747 Could not write.
-    @constant	kMismatchErr				-6748 Something does not match.
-    @constant	kDateErr					-6749 Date is invalid or out-of-range.
-    @constant	kUnderrunErr				-6750 Less data than expected.
-    @constant	kOverrunErr					-6751 More data than expected.
-    @constant	kEndingErr					-6752 Connection, session, or something is ending.
-    @constant	kConnectionErr				-6753 Connection failed or could not be established.
-    @constant	kAuthenticationErr			-6754 Authentication failed or is not supported.
-    @constant	kOpenErr					-6755 Could not open file, pipe, device, etc.
-    @constant	kTypeErr					-6756 Incorrect or incompatible type (e.g. file, data, etc.).
-    @constant	kSkipErr					-6757 Items should be or was skipped.
-    @constant	kNoAckErr					-6758 No acknowledge.
-    @constant	kCollisionErr				-6759 Collision occurred (e.g. two on bus at same time).
-    @constant	kBackoffErr					-6760 Backoff in progress and operation intentionally failed.
-    @constant	kNoAddressAckErr			-6761 No acknowledge of address.
-    @constant	kBusyErr					-6762 Cannot perform because something is busy.
-    @constant	kNoSpaceErr					-6763 Not enough space to perform operation.
- */
-
-#if ( !TARGET_OS_MAC && !TARGET_API_MAC_OSX_KERNEL )
-typedef int32_t OSStatus;
-#endif
-
-#define kNoErr                      0
-#define kInProgressErr              1
-
-// Generic error codes are in the range -6700 to -6779.
-
-#define kGenericErrorBase           -6700   // Starting error code for all generic errors.
-
-#define kUnknownErr                 -6700
-#define kOptionErr                  -6701
-#define kSelectorErr                -6702
-#define kExecutionStateErr          -6703
-#define kPathErr                    -6704
-#define kParamErr                   -6705
-#define kParamCountErr              -6706
-#define kCommandErr                 -6707
-#define kIDErr                      -6708
-#define kStateErr                   -6709
-#define kRangeErr                   -6710
-#define kRequestErr                 -6711
-#define kResponseErr                -6712
-#define kChecksumErr                -6713
-#define kNotHandledErr              -6714
-#define kVersionErr                 -6715
-#define kSignatureErr               -6716
-#define kFormatErr                  -6717
-#define kNotInitializedErr          -6718
-#define kAlreadyInitializedErr      -6719
-#define kNotInUseErr                -6720
-#define kInUseErr                   -6721
-#define kTimeoutErr                 -6722
-#define kCanceledErr                -6723
-#define kAlreadyCanceledErr         -6724
-#define kCannotCancelErr            -6725
-#define kDeletedErr                 -6726
-#define kNotFoundErr                -6727
-#define kNoMemoryErr                -6728
-#define kNoResourcesErr             -6729
-#define kDuplicateErr               -6730
-#define kImmutableErr               -6731
-#define kUnsupportedDataErr         -6732
-#define kIntegrityErr               -6733
-#define kIncompatibleErr            -6734
-#define kUnsupportedErr             -6735
-#define kUnexpectedErr              -6736
-#define kValueErr                   -6737
-#define kNotReadableErr             -6738
-#define kNotWritableErr             -6739
-#define kBadReferenceErr            -6740
-#define kFlagErr                    -6741
-#define kMalformedErr               -6742
-#define kSizeErr                    -6743
-#define kNameErr                    -6744
-#define kNotReadyErr                -6745
-#define kReadErr                    -6746
-#define kWriteErr                   -6747
-#define kMismatchErr                -6748
-#define kDateErr                    -6749
-#define kUnderrunErr                -6750
-#define kOverrunErr                 -6751
-#define kEndingErr                  -6752
-#define kConnectionErr              -6753
-#define kAuthenticationErr          -6754
-#define kOpenErr                    -6755
-#define kTypeErr                    -6756
-#define kSkipErr                    -6757
-#define kNoAckErr                   -6758
-#define kCollisionErr               -6759
-#define kBackoffErr                 -6760
-#define kNoAddressAckErr            -6761
-#define kBusyErr                    -6762
-#define kNoSpaceErr                 -6763
-
-#define kGenericErrorEnd            -6779   // Last generic error code (inclusive)
-
-#if 0
-#pragma mark == Mac Compatibility ==
-#endif
-
-//===========================================================================================================================
-//	Mac Compatibility
-//===========================================================================================================================
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@enum		Duration
-
-    @abstract	Type used to specify a duration of time.
-
-    @constant	kDurationImmediate			Indicates no delay/wait time.
-    @constant	kDurationMicrosecond		Microsecond units.
-    @constant	kDurationMillisecond		Millisecond units.
-    @constant	kDurationSecond				Second units.
-    @constant	kDurationMinute				Minute units.
-    @constant	kDurationHour				Hour units.
-    @constant	kDurationDay				Day units.
-    @constant	kDurationForever			Infinite period of time (no timeout).
-
-    @discussion
-
-    Duration values are intended to be multiplied by the specific interval to achieve an actual duration. For example,
-    to wait for 5 seconds you would use "5 * kDurationSecond".
- */
-
-#if ( !TARGET_OS_MAC )
-typedef int32_t Duration;
-#endif
-
-#define kDurationImmediate              0L
-#define kDurationMicrosecond            -1L
-#define kDurationMillisecond            1L
-#define kDurationSecond                 ( 1000L * kDurationMillisecond )
-#define kDurationMinute                 ( 60L * kDurationSecond )
-#define kDurationHour                   ( 60L * kDurationMinute )
-#define kDurationDay                    ( 24L * kDurationHour )
-#define kDurationForever                0x7FFFFFFFL
-
-// Seconds <-> Minutes <-> Hours <-> Days <-> Weeks <-> Months <-> Years conversions
-
-#define kNanosecondsPerMicrosecond      1000
-#define kNanosecondsPerMillisecond      1000000
-#define kNanosecondsPerSecond           1000000000
-#define kMicrosecondsPerSecond          1000000
-#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 kMinutesPerHour                 60
-#define kMinutesPerDay                  ( 60 * 24 )             // 1440
-#define kHoursPerDay                    24
-#define kDaysPerWeek                    7
-#define kWeeksPerYear                   52
-#define kMonthsPerYear                  12
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	VersionStages
-
-    @abstract	NumVersion-style version stages.
- */
-
-#define kVersionStageDevelopment        0x20
-#define kVersionStageAlpha              0x40
-#define kVersionStageBeta               0x60
-#define kVersionStageFinal              0x80
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	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 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	NumVersionCompare
-
-    @abstract	Compares two NumVersion values and returns the following values:
-
-        left < right -> -1
-        left > right ->  1
-        left = right ->  0
- */
-
-int NumVersionCompare( uint32_t inLeft, uint32_t inRight );
-
-#if 0
-#pragma mark == Binary Constants ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	binary_4
-
-    @abstract	Macro to generate an 4-bit constant using binary notation (e.g. binary_4( 1010 ) == 0xA).
- */
-
-#define binary_4( a )                       binary_4_hex_wrap( hex_digit4( a ) )
-#define binary_4_hex_wrap( a )              binary_4_hex( a )
-#define binary_4_hex( a )                   ( 0x ## a )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	binary_8
-
-    @abstract	Macro to generate an 8-bit constant using binary notation (e.g. binary_8( 01111011 ) == 0x7B).
- */
-
-#define binary_8( a )                       binary_8_hex_wrap( hex_digit8( a ) )
-#define binary_8_hex_wrap( a )              binary_8_hex( a )
-#define binary_8_hex( a )                   ( 0x ## a )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	binary_16
-
-    @abstract	Macro to generate an 16-bit constant using binary notation (e.g. binary_16( 01111011, 01111011 ) == 0x7B7B).
- */
-
-#define binary_16( a, b )                   binary_16_hex_wrap( hex_digit8( a ), hex_digit8( b ) )
-#define binary_16_hex_wrap( a, b )          binary_16_hex( a, b )
-#define binary_16_hex( a, b )               ( 0x ## a ## b )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	binary_32
-
-    @abstract	Macro to generate an 32-bit constant using binary notation
-                (e.g. binary_32( 01111011, 01111011, 01111011, 01111011 ) == 0x7B7B7B7B).
- */
-
-#define binary_32( a, b, c, d )             binary_32_hex_wrap( hex_digit8( a ), hex_digit8( b ), hex_digit8( c ), hex_digit8( d ) )
-#define binary_32_hex_wrap( a, b, c, d )    binary_32_hex( a, b, c, d )
-#define binary_32_hex( a, b, c, d )         ( 0x ## a ## b ## c ## d )
-
-// Binary Constant Helpers
-
-#define hex_digit8( a )                     HEX_DIGIT_ ## a
-#define hex_digit4( a )                     HEX_DIGIT_ ## 0000 ## a
-
-#define HEX_DIGIT_00000000                  00
-#define HEX_DIGIT_00000001                  01
-#define HEX_DIGIT_00000010                  02
-#define HEX_DIGIT_00000011                  03
-#define HEX_DIGIT_00000100                  04
-#define HEX_DIGIT_00000101                  05
-#define HEX_DIGIT_00000110                  06
-#define HEX_DIGIT_00000111                  07
-#define HEX_DIGIT_00001000                  08
-#define HEX_DIGIT_00001001                  09
-#define HEX_DIGIT_00001010                  0A
-#define HEX_DIGIT_00001011                  0B
-#define HEX_DIGIT_00001100                  0C
-#define HEX_DIGIT_00001101                  0D
-#define HEX_DIGIT_00001110                  0E
-#define HEX_DIGIT_00001111                  0F
-#define HEX_DIGIT_00010000                  10
-#define HEX_DIGIT_00010001                  11
-#define HEX_DIGIT_00010010                  12
-#define HEX_DIGIT_00010011                  13
-#define HEX_DIGIT_00010100                  14
-#define HEX_DIGIT_00010101                  15
-#define HEX_DIGIT_00010110                  16
-#define HEX_DIGIT_00010111                  17
-#define HEX_DIGIT_00011000                  18
-#define HEX_DIGIT_00011001                  19
-#define HEX_DIGIT_00011010                  1A
-#define HEX_DIGIT_00011011                  1B
-#define HEX_DIGIT_00011100                  1C
-#define HEX_DIGIT_00011101                  1D
-#define HEX_DIGIT_00011110                  1E
-#define HEX_DIGIT_00011111                  1F
-#define HEX_DIGIT_00100000                  20
-#define HEX_DIGIT_00100001                  21
-#define HEX_DIGIT_00100010                  22
-#define HEX_DIGIT_00100011                  23
-#define HEX_DIGIT_00100100                  24
-#define HEX_DIGIT_00100101                  25
-#define HEX_DIGIT_00100110                  26
-#define HEX_DIGIT_00100111                  27
-#define HEX_DIGIT_00101000                  28
-#define HEX_DIGIT_00101001                  29
-#define HEX_DIGIT_00101010                  2A
-#define HEX_DIGIT_00101011                  2B
-#define HEX_DIGIT_00101100                  2C
-#define HEX_DIGIT_00101101                  2D
-#define HEX_DIGIT_00101110                  2E
-#define HEX_DIGIT_00101111                  2F
-#define HEX_DIGIT_00110000                  30
-#define HEX_DIGIT_00110001                  31
-#define HEX_DIGIT_00110010                  32
-#define HEX_DIGIT_00110011                  33
-#define HEX_DIGIT_00110100                  34
-#define HEX_DIGIT_00110101                  35
-#define HEX_DIGIT_00110110                  36
-#define HEX_DIGIT_00110111                  37
-#define HEX_DIGIT_00111000                  38
-#define HEX_DIGIT_00111001                  39
-#define HEX_DIGIT_00111010                  3A
-#define HEX_DIGIT_00111011                  3B
-#define HEX_DIGIT_00111100                  3C
-#define HEX_DIGIT_00111101                  3D
-#define HEX_DIGIT_00111110                  3E
-#define HEX_DIGIT_00111111                  3F
-#define HEX_DIGIT_01000000                  40
-#define HEX_DIGIT_01000001                  41
-#define HEX_DIGIT_01000010                  42
-#define HEX_DIGIT_01000011                  43
-#define HEX_DIGIT_01000100                  44
-#define HEX_DIGIT_01000101                  45
-#define HEX_DIGIT_01000110                  46
-#define HEX_DIGIT_01000111                  47
-#define HEX_DIGIT_01001000                  48
-#define HEX_DIGIT_01001001                  49
-#define HEX_DIGIT_01001010                  4A
-#define HEX_DIGIT_01001011                  4B
-#define HEX_DIGIT_01001100                  4C
-#define HEX_DIGIT_01001101                  4D
-#define HEX_DIGIT_01001110                  4E
-#define HEX_DIGIT_01001111                  4F
-#define HEX_DIGIT_01010000                  50
-#define HEX_DIGIT_01010001                  51
-#define HEX_DIGIT_01010010                  52
-#define HEX_DIGIT_01010011                  53
-#define HEX_DIGIT_01010100                  54
-#define HEX_DIGIT_01010101                  55
-#define HEX_DIGIT_01010110                  56
-#define HEX_DIGIT_01010111                  57
-#define HEX_DIGIT_01011000                  58
-#define HEX_DIGIT_01011001                  59
-#define HEX_DIGIT_01011010                  5A
-#define HEX_DIGIT_01011011                  5B
-#define HEX_DIGIT_01011100                  5C
-#define HEX_DIGIT_01011101                  5D
-#define HEX_DIGIT_01011110                  5E
-#define HEX_DIGIT_01011111                  5F
-#define HEX_DIGIT_01100000                  60
-#define HEX_DIGIT_01100001                  61
-#define HEX_DIGIT_01100010                  62
-#define HEX_DIGIT_01100011                  63
-#define HEX_DIGIT_01100100                  64
-#define HEX_DIGIT_01100101                  65
-#define HEX_DIGIT_01100110                  66
-#define HEX_DIGIT_01100111                  67
-#define HEX_DIGIT_01101000                  68
-#define HEX_DIGIT_01101001                  69
-#define HEX_DIGIT_01101010                  6A
-#define HEX_DIGIT_01101011                  6B
-#define HEX_DIGIT_01101100                  6C
-#define HEX_DIGIT_01101101                  6D
-#define HEX_DIGIT_01101110                  6E
-#define HEX_DIGIT_01101111                  6F
-#define HEX_DIGIT_01110000                  70
-#define HEX_DIGIT_01110001                  71
-#define HEX_DIGIT_01110010                  72
-#define HEX_DIGIT_01110011                  73
-#define HEX_DIGIT_01110100                  74
-#define HEX_DIGIT_01110101                  75
-#define HEX_DIGIT_01110110                  76
-#define HEX_DIGIT_01110111                  77
-#define HEX_DIGIT_01111000                  78
-#define HEX_DIGIT_01111001                  79
-#define HEX_DIGIT_01111010                  7A
-#define HEX_DIGIT_01111011                  7B
-#define HEX_DIGIT_01111100                  7C
-#define HEX_DIGIT_01111101                  7D
-#define HEX_DIGIT_01111110                  7E
-#define HEX_DIGIT_01111111                  7F
-#define HEX_DIGIT_10000000                  80
-#define HEX_DIGIT_10000001                  81
-#define HEX_DIGIT_10000010                  82
-#define HEX_DIGIT_10000011                  83
-#define HEX_DIGIT_10000100                  84
-#define HEX_DIGIT_10000101                  85
-#define HEX_DIGIT_10000110                  86
-#define HEX_DIGIT_10000111                  87
-#define HEX_DIGIT_10001000                  88
-#define HEX_DIGIT_10001001                  89
-#define HEX_DIGIT_10001010                  8A
-#define HEX_DIGIT_10001011                  8B
-#define HEX_DIGIT_10001100                  8C
-#define HEX_DIGIT_10001101                  8D
-#define HEX_DIGIT_10001110                  8E
-#define HEX_DIGIT_10001111                  8F
-#define HEX_DIGIT_10010000                  90
-#define HEX_DIGIT_10010001                  91
-#define HEX_DIGIT_10010010                  92
-#define HEX_DIGIT_10010011                  93
-#define HEX_DIGIT_10010100                  94
-#define HEX_DIGIT_10010101                  95
-#define HEX_DIGIT_10010110                  96
-#define HEX_DIGIT_10010111                  97
-#define HEX_DIGIT_10011000                  98
-#define HEX_DIGIT_10011001                  99
-#define HEX_DIGIT_10011010                  9A
-#define HEX_DIGIT_10011011                  9B
-#define HEX_DIGIT_10011100                  9C
-#define HEX_DIGIT_10011101                  9D
-#define HEX_DIGIT_10011110                  9E
-#define HEX_DIGIT_10011111                  9F
-#define HEX_DIGIT_10100000                  A0
-#define HEX_DIGIT_10100001                  A1
-#define HEX_DIGIT_10100010                  A2
-#define HEX_DIGIT_10100011                  A3
-#define HEX_DIGIT_10100100                  A4
-#define HEX_DIGIT_10100101                  A5
-#define HEX_DIGIT_10100110                  A6
-#define HEX_DIGIT_10100111                  A7
-#define HEX_DIGIT_10101000                  A8
-#define HEX_DIGIT_10101001                  A9
-#define HEX_DIGIT_10101010                  AA
-#define HEX_DIGIT_10101011                  AB
-#define HEX_DIGIT_10101100                  AC
-#define HEX_DIGIT_10101101                  AD
-#define HEX_DIGIT_10101110                  AE
-#define HEX_DIGIT_10101111                  AF
-#define HEX_DIGIT_10110000                  B0
-#define HEX_DIGIT_10110001                  B1
-#define HEX_DIGIT_10110010                  B2
-#define HEX_DIGIT_10110011                  B3
-#define HEX_DIGIT_10110100                  B4
-#define HEX_DIGIT_10110101                  B5
-#define HEX_DIGIT_10110110                  B6
-#define HEX_DIGIT_10110111                  B7
-#define HEX_DIGIT_10111000                  B8
-#define HEX_DIGIT_10111001                  B9
-#define HEX_DIGIT_10111010                  BA
-#define HEX_DIGIT_10111011                  BB
-#define HEX_DIGIT_10111100                  BC
-#define HEX_DIGIT_10111101                  BD
-#define HEX_DIGIT_10111110                  BE
-#define HEX_DIGIT_10111111                  BF
-#define HEX_DIGIT_11000000                  C0
-#define HEX_DIGIT_11000001                  C1
-#define HEX_DIGIT_11000010                  C2
-#define HEX_DIGIT_11000011                  C3
-#define HEX_DIGIT_11000100                  C4
-#define HEX_DIGIT_11000101                  C5
-#define HEX_DIGIT_11000110                  C6
-#define HEX_DIGIT_11000111                  C7
-#define HEX_DIGIT_11001000                  C8
-#define HEX_DIGIT_11001001                  C9
-#define HEX_DIGIT_11001010                  CA
-#define HEX_DIGIT_11001011                  CB
-#define HEX_DIGIT_11001100                  CC
-#define HEX_DIGIT_11001101                  CD
-#define HEX_DIGIT_11001110                  CE
-#define HEX_DIGIT_11001111                  CF
-#define HEX_DIGIT_11010000                  D0
-#define HEX_DIGIT_11010001                  D1
-#define HEX_DIGIT_11010010                  D2
-#define HEX_DIGIT_11010011                  D3
-#define HEX_DIGIT_11010100                  D4
-#define HEX_DIGIT_11010101                  D5
-#define HEX_DIGIT_11010110                  D6
-#define HEX_DIGIT_11010111                  D7
-#define HEX_DIGIT_11011000                  D8
-#define HEX_DIGIT_11011001                  D9
-#define HEX_DIGIT_11011010                  DA
-#define HEX_DIGIT_11011011                  DB
-#define HEX_DIGIT_11011100                  DC
-#define HEX_DIGIT_11011101                  DD
-#define HEX_DIGIT_11011110                  DE
-#define HEX_DIGIT_11011111                  DF
-#define HEX_DIGIT_11100000                  E0
-#define HEX_DIGIT_11100001                  E1
-#define HEX_DIGIT_11100010                  E2
-#define HEX_DIGIT_11100011                  E3
-#define HEX_DIGIT_11100100                  E4
-#define HEX_DIGIT_11100101                  E5
-#define HEX_DIGIT_11100110                  E6
-#define HEX_DIGIT_11100111                  E7
-#define HEX_DIGIT_11101000                  E8
-#define HEX_DIGIT_11101001                  E9
-#define HEX_DIGIT_11101010                  EA
-#define HEX_DIGIT_11101011                  EB
-#define HEX_DIGIT_11101100                  EC
-#define HEX_DIGIT_11101101                  ED
-#define HEX_DIGIT_11101110                  EE
-#define HEX_DIGIT_11101111                  EF
-#define HEX_DIGIT_11110000                  F0
-#define HEX_DIGIT_11110001                  F1
-#define HEX_DIGIT_11110010                  F2
-#define HEX_DIGIT_11110011                  F3
-#define HEX_DIGIT_11110100                  F4
-#define HEX_DIGIT_11110101                  F5
-#define HEX_DIGIT_11110110                  F6
-#define HEX_DIGIT_11110111                  F7
-#define HEX_DIGIT_11111000                  F8
-#define HEX_DIGIT_11111001                  F9
-#define HEX_DIGIT_11111010                  FA
-#define HEX_DIGIT_11111011                  FB
-#define HEX_DIGIT_11111100                  FC
-#define HEX_DIGIT_11111101                  FD
-#define HEX_DIGIT_11111110                  FE
-#define HEX_DIGIT_11111111                  FF
-
-#if 0
-#pragma mark == Debugging ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	CommonServicesTest
-
-    @abstract	Unit test.
- */
-
-#if ( defined( DEBUG ) && DEBUG )
-OSStatus    CommonServicesTest( void );
-#endif
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif  // __COMMON_SERVICES__
diff --git a/mDNSShared/DebugServices.c b/mDNSShared/DebugServices.c
deleted file mode 100644
index eda4c84..0000000
--- a/mDNSShared/DebugServices.c
+++ /dev/null
@@ -1,3027 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004, 2020-2021 Apple 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
- *
- *     https://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.
-
-    To Do:
-
-    - Use StackWalk on Windows to optionally print stack frames.
- */
-
-#if 0
-#pragma mark == Includes ==
-#endif
-
-//===========================================================================================================================
-//	Includes
-//===========================================================================================================================
-
-#if ( !KERNEL )
-    #include    <ctype.h>
-    #include    <stdio.h>
-    #include    <string.h>
-#endif
-
-#include    "CommonServices.h"
-
-#include    "DebugServices.h"
-
-#if ( DEBUG )
-
-#if ( TARGET_OS_WIN32 )
-    #include    <time.h>
-
-    #if ( !TARGET_OS_WINDOWS_CE )
-        #include    <fcntl.h>
-        #include    <io.h>
-    #endif
-#endif
-
-#if ( DEBUG_IDEBUG_ENABLED && TARGET_API_MAC_OSX_KERNEL )
-    #include    <IOKit/IOLib.h>
-#endif
-
-// If MDNS_DEBUGMSGS is defined (even if defined 0), it is aware of mDNS and it is probably safe to include mDNSEmbeddedAPI.h.
-
-#if ( defined( MDNS_DEBUGMSGS ) )
-    #include    "mDNSEmbeddedAPI.h"
-#endif
-
-#if 0
-#pragma mark == Macros ==
-#endif
-
-//===========================================================================================================================
-//	Macros
-//===========================================================================================================================
-
-#define DebugIsPrint( C )       ( ( ( C ) >= 0x20 ) && ( ( C ) <= 0x7E ) )
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize );
-
-// fprintf
-
-#if ( DEBUG_FPRINTF_ENABLED )
-static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename );
-static void     DebugFPrintFPrint( char *inData, size_t inSize );
-#endif
-
-// iDebug (Mac OS X user and kernel)
-
-#if ( DEBUG_IDEBUG_ENABLED )
-static OSStatus DebugiDebugInit( void );
-static void     DebugiDebugPrint( char *inData, size_t inSize );
-#endif
-
-// kprintf (Mac OS X Kernel)
-
-#if ( DEBUG_KPRINTF_ENABLED )
-static void DebugKPrintFPrint( char *inData, size_t inSize );
-#endif
-
-// Mac OS X IOLog (Mac OS X Kernel)
-
-#if ( DEBUG_MAC_OS_X_IOLOG_ENABLED )
-static void DebugMacOSXIOLogPrint( char *inData, size_t inSize );
-#endif
-
-// Mac OS X Log
-
-#if ( TARGET_OS_MAC )
-static OSStatus DebugMacOSXLogInit( void );
-static void     DebugMacOSXLogPrint( char *inData, size_t inSize );
-#endif
-
-// Windows Debugger
-
-#if ( TARGET_OS_WIN32 )
-static void DebugWindowsDebuggerPrint( char *inData, size_t inSize );
-#endif
-
-// Windows Event Log
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule );
-static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize );
-#endif
-
-// DebugLib support
-
-#if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
-static pascal void
-DebugAssertOutputHandler(
-    OSType inComponentSignature,
-    UInt32 inOptions,
-    const char *        inAssertionString,
-    const char *        inExceptionString,
-    const char *        inErrorString,
-    const char *        inFileName,
-    long inLineNumber,
-    void *              inValue,
-    ConstStr255Param inOutputMsg );
-#endif
-
-// Utilities
-
-static char *   DebugNumVersionToString( uint32_t inVersion, char *inString );
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-static void DebugWinEnableConsole( void );
-#endif
-
-#if ( TARGET_OS_WIN32 )
-static TCHAR *
-DebugWinCharToTCharString(
-    const char *    inCharString,
-    size_t inCharCount,
-    TCHAR *         outTCharString,
-    size_t inTCharCountMax,
-    size_t *        outTCharCount );
-#endif
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Private Globals
-//===========================================================================================================================
-
-// General
-
-static bool gDebugInitialized               = false;
-static DebugOutputType gDebugOutputType                = kDebugOutputTypeNone;
-static DebugLevel gDebugPrintLevelMin             = kDebugLevelInfo;
-static DebugLevel gDebugPrintLevelMax             = kDebugLevelMax;
-static DebugLevel gDebugBreakLevel                = kDebugLevelAssert;
-#if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
-static DebugAssertOutputHandlerUPP gDebugAssertOutputHandlerUPP    = NULL;
-#endif
-
-// Custom
-
-static DebugOutputFunctionPtr gDebugCustomOutputFunction      = NULL;
-static void *                               gDebugCustomOutputContext       = NULL;
-
-// fprintf
-
-#if ( DEBUG_FPRINTF_ENABLED )
-static FILE *                           gDebugFPrintFFile               = NULL;
-#endif
-
-// MacOSXLog
-
-#if ( TARGET_OS_MAC )
-typedef int ( *DebugMacOSXLogFunctionPtr )( const char *inFormat, ... );
-
-static DebugMacOSXLogFunctionPtr gDebugMacOSXLogFunction         = NULL;
-#endif
-
-// WindowsEventLog
-
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-static HANDLE gDebugWindowsEventLogEventSource = NULL;
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == General ==
-#endif
-
-//===========================================================================================================================
-//	DebugInitialize
-//===========================================================================================================================
-
-DEBUG_EXPORT OSStatus   DebugInitialize( DebugOutputType inType, ... )
-{
-    OSStatus err;
-    DebugOutputType type;
-    va_list args;
-
-    va_start( args, inType );
-
-    // Set up DebugLib stuff (if building with Debugging.h).
-
-#if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
-    if( !gDebugAssertOutputHandlerUPP )
-    {
-        gDebugAssertOutputHandlerUPP = NewDebugAssertOutputHandlerUPP( DebugAssertOutputHandler );
-        check( gDebugAssertOutputHandlerUPP );
-        if( gDebugAssertOutputHandlerUPP )
-        {
-            InstallDebugAssertOutputHandler( gDebugAssertOutputHandlerUPP );
-        }
-    }
-#endif
-
-    // Pre-process meta-output kind to pick an appropriate output kind for the platform.
-
-    type = inType;
-    if( type == kDebugOutputTypeMetaConsole )
-    {
-        #if ( TARGET_OS_MAC )
-        type = kDebugOutputTypeMacOSXLog;
-        #elif ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-            #if ( DEBUG_FPRINTF_ENABLED )
-        type = kDebugOutputTypeFPrintF;
-            #else
-        type = kDebugOutputTypeWindowsDebugger;
-            #endif
-        #elif ( TARGET_API_MAC_OSX_KERNEL )
-            #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED )
-        type = kDebugOutputTypeMacOSXIOLog;
-            #elif ( DEBUG_IDEBUG_ENABLED )
-        type = kDebugOutputTypeiDebug;
-            #elif ( DEBUG_KPRINTF_ENABLED )
-        type = kDebugOutputTypeKPrintF;
-            #endif
-        #else
-            #if ( DEBUG_FPRINTF_ENABLED )
-        type = kDebugOutputTypeFPrintF;
-            #endif
-        #endif
-    }
-
-    // Process output kind.
-
-    gDebugOutputType = type;
-    switch( type )
-    {
-    case kDebugOutputTypeNone:
-        err = kNoErr;
-        break;
-
-    case kDebugOutputTypeCustom:
-        gDebugCustomOutputFunction = va_arg( args, DebugOutputFunctionPtr );
-        gDebugCustomOutputContext  = va_arg( args, void * );
-        err = kNoErr;
-        break;
-
-#if ( DEBUG_FPRINTF_ENABLED )
-    case kDebugOutputTypeFPrintF:
-        if( inType == kDebugOutputTypeMetaConsole )
-        {
-            err = DebugFPrintFInit( kDebugOutputTypeFlagsStdErr, NULL );
-        }
-        else
-        {
-            DebugOutputTypeFlags flags;
-            const char *                filename;
-
-            flags = (DebugOutputTypeFlags) va_arg( args, unsigned int );
-            if( ( flags & kDebugOutputTypeFlagsTypeMask ) == kDebugOutputTypeFlagsFile )
-            {
-                filename = va_arg( args, const char * );
-            }
-            else
-            {
-                filename = NULL;
-            }
-            err = DebugFPrintFInit( flags, filename );
-        }
-        break;
-#endif
-
-#if ( DEBUG_IDEBUG_ENABLED )
-    case kDebugOutputTypeiDebug:
-        err = DebugiDebugInit();
-        break;
-#endif
-
-#if ( DEBUG_KPRINTF_ENABLED )
-    case kDebugOutputTypeKPrintF:
-        err = kNoErr;
-        break;
-#endif
-
-#if ( DEBUG_MAC_OS_X_IOLOG_ENABLED )
-    case kDebugOutputTypeMacOSXIOLog:
-        err = kNoErr;
-        break;
-#endif
-
-#if ( TARGET_OS_MAC )
-    case kDebugOutputTypeMacOSXLog:
-        err = DebugMacOSXLogInit();
-        break;
-#endif
-
-#if ( TARGET_OS_WIN32 )
-    case kDebugOutputTypeWindowsDebugger:
-        err = kNoErr;
-        break;
-#endif
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-    case kDebugOutputTypeWindowsEventLog:
-    {
-        const char *        name;
-        HMODULE module;
-
-        name   = va_arg( args, const char * );
-        module = va_arg( args, HMODULE );
-        err = DebugWindowsEventLogInit( name, module );
-    }
-    break;
-#endif
-
-    default:
-        err = kParamErr;
-        goto exit;
-    }
-    gDebugInitialized = true;
-
-exit:
-    va_end( args );
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugFinalize
-//===========================================================================================================================
-
-DEBUG_EXPORT void       DebugFinalize( void )
-{
-#if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
-    check( gDebugAssertOutputHandlerUPP );
-    if( gDebugAssertOutputHandlerUPP )
-    {
-        InstallDebugAssertOutputHandler( NULL );
-        DisposeDebugAssertOutputHandlerUPP( gDebugAssertOutputHandlerUPP );
-        gDebugAssertOutputHandlerUPP = NULL;
-    }
-#endif
-}
-
-//===========================================================================================================================
-//	DebugGetProperty
-//===========================================================================================================================
-
-DEBUG_EXPORT OSStatus   DebugGetProperty( DebugPropertyTag inTag, ... )
-{
-    OSStatus err;
-    va_list args;
-    DebugLevel *        level;
-
-    va_start( args, inTag );
-    switch( inTag )
-    {
-    case kDebugPropertyTagPrintLevelMin:
-        level  = va_arg( args, DebugLevel * );
-        *level = gDebugPrintLevelMin;
-        err = kNoErr;
-        break;
-
-    case kDebugPropertyTagPrintLevelMax:
-        level  = va_arg( args, DebugLevel * );
-        *level = gDebugPrintLevelMax;
-        err = kNoErr;
-        break;
-
-    case kDebugPropertyTagBreakLevel:
-        level  = va_arg( args, DebugLevel * );
-        *level = gDebugBreakLevel;
-        err = kNoErr;
-        break;
-
-    default:
-        err = kUnsupportedErr;
-        break;
-    }
-    va_end( args );
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugSetProperty
-//===========================================================================================================================
-
-DEBUG_EXPORT OSStatus   DebugSetProperty( DebugPropertyTag inTag, ... )
-{
-    OSStatus err;
-    va_list args;
-    DebugLevel level;
-
-    va_start( args, inTag );
-    switch( inTag )
-    {
-    case kDebugPropertyTagPrintLevelMin:
-        level  = va_arg( args, DebugLevel );
-        gDebugPrintLevelMin = level;
-        err = kNoErr;
-        break;
-
-    case kDebugPropertyTagPrintLevelMax:
-        level  = va_arg( args, DebugLevel );
-        gDebugPrintLevelMax = level;
-        err = kNoErr;
-        break;
-
-    case kDebugPropertyTagBreakLevel:
-        level  = va_arg( args, DebugLevel );
-        gDebugBreakLevel = level;
-        err = kNoErr;
-        break;
-
-    default:
-        err = kUnsupportedErr;
-        break;
-    }
-    va_end( args );
-    return( err );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Output ==
-#endif
-
-//===========================================================================================================================
-//	DebugPrintF
-//===========================================================================================================================
-
-DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... )
-{
-    va_list args;
-    size_t n;
-
-    // Skip if the level is not in the enabled range..
-
-    if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) )
-    {
-        n = 0;
-        goto exit;
-    }
-
-    va_start( args, inFormat );
-    n = DebugPrintFVAList( inLevel, inFormat, args );
-    va_end( args );
-
-exit:
-    return( n );
-}
-
-//===========================================================================================================================
-//	DebugPrintFVAList
-//===========================================================================================================================
-
-DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs )
-{
-    size_t n;
-    char buffer[ 512 ];
-
-    // Skip if the level is not in the enabled range..
-
-    if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) )
-    {
-        n = 0;
-        goto exit;
-    }
-
-    n = DebugSNPrintFVAList( buffer, sizeof( buffer ), inFormat, inArgs );
-    DebugPrint( inLevel, buffer, (size_t) n );
-
-exit:
-    return( n );
-}
-
-//===========================================================================================================================
-//	DebugPrint
-//===========================================================================================================================
-
-static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize )
-{
-    OSStatus err;
-
-    // Skip if the level is not in the enabled range..
-
-    if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) )
-    {
-        err = kRangeErr;
-        goto exit;
-    }
-
-    // Printing is not safe at interrupt time so check for this and warn with an interrupt safe mechanism (if available).
-
-    if( DebugTaskLevel() & kDebugInterruptLevelMask )
-    {
-        err = kExecutionStateErr;
-        goto exit;
-    }
-
-    // Initialize the debugging library if it hasn't already been initialized (allows for zero-config usage).
-
-    if( !gDebugInitialized )
-    {
-        debug_initialize( kDebugOutputTypeMetaConsole );
-    }
-
-    // Print based on the current output type.
-
-    switch( gDebugOutputType )
-    {
-    case kDebugOutputTypeNone:
-        break;
-
-    case kDebugOutputTypeCustom:
-        if( gDebugCustomOutputFunction )
-        {
-            gDebugCustomOutputFunction( inData, inSize, gDebugCustomOutputContext );
-        }
-        break;
-
-#if ( DEBUG_FPRINTF_ENABLED )
-    case kDebugOutputTypeFPrintF:
-        DebugFPrintFPrint( inData, inSize );
-        break;
-#endif
-
-#if ( DEBUG_IDEBUG_ENABLED )
-    case kDebugOutputTypeiDebug:
-        DebugiDebugPrint( inData, inSize );
-        break;
-#endif
-
-#if ( DEBUG_KPRINTF_ENABLED )
-    case kDebugOutputTypeKPrintF:
-        DebugKPrintFPrint( inData, inSize );
-        break;
-#endif
-
-#if ( DEBUG_MAC_OS_X_IOLOG_ENABLED )
-    case kDebugOutputTypeMacOSXIOLog:
-        DebugMacOSXIOLogPrint( inData, inSize );
-        break;
-#endif
-
-#if ( TARGET_OS_MAC )
-    case kDebugOutputTypeMacOSXLog:
-        DebugMacOSXLogPrint( inData, inSize );
-        break;
-#endif
-
-#if ( TARGET_OS_WIN32 )
-    case kDebugOutputTypeWindowsDebugger:
-        DebugWindowsDebuggerPrint( inData, inSize );
-        break;
-#endif
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-    case kDebugOutputTypeWindowsEventLog:
-        DebugWindowsEventLogPrint( inLevel, inData, inSize );
-        break;
-#endif
-
-    default:
-        break;
-    }
-    err = kNoErr;
-
-exit:
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugPrintAssert
-//
-//	Warning: This routine relies on several of the strings being string constants that will exist forever because the
-//           underlying logMsg API that does the printing is asynchronous so it cannot use temporary/stack-based
-//           pointer variables (e.g. local strings). The debug macros that invoke this function only use constant
-//           constant strings, but if this function is invoked directly from other places, it must use constant strings.
-//===========================================================================================================================
-
-DEBUG_EXPORT void
-DebugPrintAssert(
-    int_least32_t inErrorCode,
-    const char *    inAssertString,
-    const char *    inMessage,
-    const char *    inFilename,
-    int_least32_t inLineNumber,
-    const char *    inFunction )
-{
-    // Skip if the level is not in the enabled range..
-
-    if( ( kDebugLevelAssert < gDebugPrintLevelMin ) || ( kDebugLevelAssert > gDebugPrintLevelMax ) )
-    {
-        return;
-    }
-
-    if( inErrorCode != 0 )
-    {
-        DebugPrintF(
-            kDebugLevelAssert,
-            "\n"
-            "[ASSERT] error:  %ld (%m)\n"
-            "[ASSERT] where:  \"%s\", line %ld, \"%s\"\n"
-            "\n",
-            inErrorCode, inErrorCode,
-            inFilename ? inFilename : "",
-            inLineNumber,
-            inFunction ? inFunction : "" );
-    }
-    else
-    {
-        DebugPrintF(
-            kDebugLevelAssert,
-            "\n"
-            "[ASSERT] assert: \"%s\" %s\n"
-            "[ASSERT] where:  \"%s\", line %ld, \"%s\"\n"
-            "\n",
-            inAssertString ? inAssertString : "",
-            inMessage ? inMessage : "",
-            inFilename ? inFilename : "",
-            inLineNumber,
-            inFunction ? inFunction : "" );
-    }
-
-    // Break into the debugger if enabled.
-
-    #if ( TARGET_OS_WIN32 )
-    if( gDebugBreakLevel <= kDebugLevelAssert )
-    {
-        if( IsDebuggerPresent() )
-        {
-            DebugBreak();
-        }
-    }
-    #endif
-}
-
-#if 0
-#pragma mark -
-#endif
-
-#if ( DEBUG_FPRINTF_ENABLED )
-//===========================================================================================================================
-//	DebugFPrintFInit
-//===========================================================================================================================
-
-static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename )
-{
-    OSStatus err;
-    DebugOutputTypeFlags typeFlags;
-
-    typeFlags = inFlags & kDebugOutputTypeFlagsTypeMask;
-    if( typeFlags == kDebugOutputTypeFlagsStdOut )
-    {
-        #if ( TARGET_OS_WIN32 )
-        DebugWinEnableConsole();
-        #endif
-
-        gDebugFPrintFFile = stdout;
-    }
-    else if( typeFlags == kDebugOutputTypeFlagsStdErr )
-    {
-        #if ( TARGET_OS_WIN32 )
-        DebugWinEnableConsole();
-        #endif
-
-        gDebugFPrintFFile = stdout;
-    }
-    else if( typeFlags == kDebugOutputTypeFlagsFile )
-    {
-        require_action_quiet( inFilename && ( *inFilename != '\0' ), exit, err = kOpenErr );
-
-        gDebugFPrintFFile = fopen( inFilename, "a" );
-        require_action_quiet( gDebugFPrintFFile, exit, err = kOpenErr );
-    }
-    else
-    {
-        err = kParamErr;
-        goto exit;
-    }
-    err = kNoErr;
-
-exit:
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugFPrintFPrint
-//===========================================================================================================================
-
-static void DebugFPrintFPrint( char *inData, size_t inSize )
-{
-    char *      p;
-    char *      q;
-
-    // Convert \r to \n. fprintf will interpret \n and convert to whatever is appropriate for the platform.
-
-    p = inData;
-    q = p + inSize;
-    while( p < q )
-    {
-        if( *p == '\r' )
-        {
-            *p = '\n';
-        }
-        ++p;
-    }
-
-    // Write the data and flush.
-
-    if( gDebugFPrintFFile )
-    {
-        fprintf( gDebugFPrintFFile, "%.*s", (int) inSize, inData );
-        fflush( gDebugFPrintFFile );
-    }
-}
-#endif  // DEBUG_FPRINTF_ENABLED
-
-#if ( DEBUG_IDEBUG_ENABLED )
-//===========================================================================================================================
-//	DebugiDebugInit
-//===========================================================================================================================
-
-static OSStatus DebugiDebugInit( void )
-{
-    OSStatus err;
-
-    #if ( TARGET_API_MAC_OSX_KERNEL )
-
-    extern uint32_t *       _giDebugReserved1;
-
-    // Emulate the iDebugSetOutputType macro in iDebugServices.h.
-    // Note: This is not thread safe, but neither is iDebugServices.h nor iDebugKext.
-
-    if( !_giDebugReserved1 )
-    {
-        _giDebugReserved1 = (uint32_t *) IOMalloc( sizeof( uint32_t ) );
-        require_action_quiet( _giDebugReserved1, exit, err = kNoMemoryErr );
-    }
-    *_giDebugReserved1 = 0x00010000U;
-    err = kNoErr;
-exit:
-    #else
-
-    __private_extern__ void iDebugSetOutputTypeInternal( uint32_t inType );
-
-    iDebugSetOutputTypeInternal( 0x00010000U );
-    err = kNoErr;
-
-    #endif
-
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugiDebugPrint
-//===========================================================================================================================
-
-static void DebugiDebugPrint( char *inData, size_t inSize )
-{
-    #if ( TARGET_API_MAC_OSX_KERNEL )
-
-    // Locally declared here so we do not need to include iDebugKext.h.
-    // Note: IOKit uses a global namespace for all code and only a partial link occurs at build time. When the
-    // KEXT is loaded, the runtime linker will link in this extern'd symbol (assuming iDebug is present).
-    // _giDebugLogInternal is actually part of IOKit proper so this should link even if iDebug is not present.
-
-    typedef void ( *iDebugLogFunctionPtr )( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... );
-
-    extern iDebugLogFunctionPtr _giDebugLogInternal;
-
-    if( _giDebugLogInternal )
-    {
-        _giDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData );
-    }
-
-    #else
-
-    __private_extern__ void iDebugLogInternal( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... );
-
-    iDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData );
-
-    #endif
-}
-#endif
-
-#if ( DEBUG_KPRINTF_ENABLED )
-//===========================================================================================================================
-//	DebugKPrintFPrint
-//===========================================================================================================================
-
-static void DebugKPrintFPrint( char *inData, size_t inSize )
-{
-    extern void kprintf( const char *inFormat, ... );
-
-    kprintf( "%.*s", (int) inSize, inData );
-}
-#endif
-
-#if ( DEBUG_MAC_OS_X_IOLOG_ENABLED )
-//===========================================================================================================================
-//	DebugMacOSXIOLogPrint
-//===========================================================================================================================
-
-static void DebugMacOSXIOLogPrint( char *inData, size_t inSize )
-{
-    extern void IOLog( const char *inFormat, ... );
-
-    IOLog( "%.*s", (int) inSize, inData );
-}
-#endif
-
-#if ( TARGET_OS_MAC )
-//===========================================================================================================================
-//	DebugMacOSXLogInit
-//===========================================================================================================================
-
-static OSStatus DebugMacOSXLogInit( void )
-{
-    OSStatus err;
-    CFStringRef path;
-    CFURLRef url;
-    CFBundleRef bundle;
-    CFStringRef functionName;
-    void *          functionPtr;
-
-    bundle = NULL;
-
-    // Create a bundle reference for System.framework.
-
-    path = CFSTR( "/System/Library/Frameworks/System.framework" );
-    url = CFURLCreateWithFileSystemPath( NULL, path, kCFURLPOSIXPathStyle, true );
-    require_action_quiet( url, exit, err = memFullErr );
-
-    bundle = CFBundleCreate( NULL, url );
-    CFRelease( url );
-    require_action_quiet( bundle, exit, err = memFullErr );
-
-    // Get a ptr to the system's "printf" function from System.framework.
-
-    functionName = CFSTR( "printf" );
-    functionPtr = CFBundleGetFunctionPointerForName( bundle, functionName );
-    require_action_quiet( functionPtr, exit, err = memFullErr );
-
-    // Success! Note: The bundle cannot be released because it would invalidate the function ptr.
-
-    gDebugMacOSXLogFunction = (DebugMacOSXLogFunctionPtr) functionPtr;
-    bundle = NULL;
-    err = noErr;
-
-exit:
-    if( bundle )
-    {
-        CFRelease( bundle );
-    }
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugMacOSXLogPrint
-//===========================================================================================================================
-
-static void DebugMacOSXLogPrint( char *inData, size_t inSize )
-{
-    if( gDebugMacOSXLogFunction )
-    {
-        gDebugMacOSXLogFunction( "%.*s", (int) inSize, inData );
-    }
-}
-#endif
-
-#if ( TARGET_OS_WIN32 )
-//===========================================================================================================================
-//	DebugWindowsDebuggerPrint
-//===========================================================================================================================
-
-void    DebugWindowsDebuggerPrint( char *inData, size_t inSize )
-{
-    TCHAR buffer[ 512 ];
-    const char *        src;
-    const char *        end;
-    TCHAR *             dst;
-    char c;
-
-    // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are
-    // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process.
-
-    src = inData;
-    if( inSize >= sizeof_array( buffer ) )
-    {
-        inSize = sizeof_array( buffer ) - 1;
-    }
-    end = src + inSize;
-    dst = buffer;
-    while( src < end )
-    {
-        c = *src++;
-        if( c == '\r' )
-        {
-            c = '\n';
-        }
-        *dst++ = (TCHAR) c;
-    }
-    *dst = 0;
-
-    // Print out the string to the debugger.
-
-    OutputDebugString( buffer );
-}
-#endif
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-//===========================================================================================================================
-//	DebugWindowsEventLogInit
-//===========================================================================================================================
-
-static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule )
-{
-    OSStatus err;
-    HKEY key;
-    TCHAR name[ 128 ];
-    const char *        src;
-    TCHAR path[ MAX_PATH ];
-    size_t size;
-    DWORD typesSupported;
-    DWORD n;
-
-    key = NULL;
-
-    // Use a default name if needed then convert the name to TCHARs so it works on ANSI or Unicode builds.
-
-    if( !inName || ( *inName == '\0' ) )
-    {
-        inName = "DefaultApp";
-    }
-    DebugWinCharToTCharString( inName, kSizeCString, name, sizeof( name ), NULL );
-
-    // Build the path string using the fixed registry path and app name.
-
-    src = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";
-    DebugWinCharToTCharString( src, kSizeCString, path, sizeof_array( path ), &size );
-    DebugWinCharToTCharString( inName, kSizeCString, path + size, sizeof_array( path ) - size, NULL );
-
-    // Add/Open the source name as a sub-key under the Application key in the EventLog registry key.
-
-    err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL );
-    require_noerr_quiet( err, exit );
-
-    // Set the path in the EventMessageFile subkey. Add 1 to the TCHAR count to include the null terminator.
-
-    n = GetModuleFileName( inModule, path, sizeof_array( path ) );
-    err = translate_errno( n > 0, (OSStatus) GetLastError(), kParamErr );
-    require_noerr_quiet( err, exit );
-    n += 1;
-    n *= sizeof( TCHAR );
-
-    err = RegSetValueEx( key, TEXT( "EventMessageFile" ), 0, REG_EXPAND_SZ, (const LPBYTE) path, n );
-    require_noerr_quiet( err, exit );
-
-    // Set the supported event types in the TypesSupported subkey.
-
-    typesSupported = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE |
-                     EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE;
-    err = RegSetValueEx( key, TEXT( "TypesSupported" ), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) );
-    require_noerr_quiet( err, exit );
-
-    // Set up the event source.
-
-    gDebugWindowsEventLogEventSource = RegisterEventSource( NULL, name );
-    err = translate_errno( gDebugWindowsEventLogEventSource, (OSStatus) GetLastError(), kParamErr );
-    require_noerr_quiet( err, exit );
-
-exit:
-    if( key )
-    {
-        RegCloseKey( key );
-    }
-    return( err );
-}
-
-//===========================================================================================================================
-//	DebugWindowsEventLogPrint
-//===========================================================================================================================
-
-static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize )
-{
-    WORD type;
-    TCHAR buffer[ 512 ];
-    const char *        src;
-    const char *        end;
-    TCHAR *             dst;
-    char c;
-    const TCHAR *       array[ 1 ];
-
-    // Map the debug level to a Windows EventLog type.
-
-    if( inLevel <= kDebugLevelNotice )
-    {
-        type = EVENTLOG_INFORMATION_TYPE;
-    }
-    else if( inLevel <= kDebugLevelWarning )
-    {
-        type = EVENTLOG_WARNING_TYPE;
-    }
-    else
-    {
-        type = EVENTLOG_ERROR_TYPE;
-    }
-
-    // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are
-    // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process.
-
-    src = inData;
-    if( inSize >= sizeof_array( buffer ) )
-    {
-        inSize = sizeof_array( buffer ) - 1;
-    }
-    end = src + inSize;
-    dst = buffer;
-    while( src < end )
-    {
-        c = *src++;
-        if( c == '\r' )
-        {
-            c = '\n';
-        }
-        *dst++ = (TCHAR) c;
-    }
-    *dst = 0;
-
-    // Add the the string to the event log.
-
-    array[ 0 ] = buffer;
-    if( gDebugWindowsEventLogEventSource )
-    {
-        ReportEvent( gDebugWindowsEventLogEventSource, type, 0, 0x20000001L, NULL, 1, 0, array, NULL );
-    }
-}
-#endif  // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE
-
-#if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
-//===========================================================================================================================
-//	DebugAssertOutputHandler
-//===========================================================================================================================
-
-static pascal void
-DebugAssertOutputHandler(
-    OSType inComponentSignature,
-    UInt32 inOptions,
-    const char *        inAssertString,
-    const char *        inExceptionString,
-    const char *        inErrorString,
-    const char *        inFileName,
-    long inLineNumber,
-    void *              inValue,
-    ConstStr255Param inOutputMsg )
-{
-    DEBUG_UNUSED( inComponentSignature );
-    DEBUG_UNUSED( inOptions );
-    DEBUG_UNUSED( inExceptionString );
-    DEBUG_UNUSED( inValue );
-    DEBUG_UNUSED( inOutputMsg );
-
-    DebugPrintAssert( 0, inAssertString, inErrorString, inFileName, (int_least32_t) inLineNumber, "" );
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Utilities ==
-#endif
-
-//===========================================================================================================================
-//	DebugSNPrintF
-//
-//	Stolen from mDNS.c's mDNS_snprintf/mDNS_vsnprintf with the following changes:
-//
-//	Changed names to avoid name collisions with the mDNS versions.
-//	Changed types to standard C types since mDNSEmbeddedAPI.h may not be available.
-//	Conditionalized mDNS stuff so it can be used with or with mDNSEmbeddedAPI.h.
-//	Added 64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb).
-//	Added %@   - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription.
-//	Added %.8a - FIbre Channel address. Arg=ptr to address.
-//	Added %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr.
-//	Added %b   - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc.
-//	Added %C   - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode.
-//	Added %H   - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-//	Added %#H  - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-//	Added %m   - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code args are the same as %d, %x, etc.
-//	Added %S   - UTF-16 string. Host order if no BOM. Precision is UTF-16 char count. BOM counts in any precision. Arg=ptr.
-//	Added %#S  - Big Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S.
-//	Added %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S.
-//	Added %U   - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID.
-//===========================================================================================================================
-
-DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...)
-{
-    size_t length;
-
-    va_list ptr;
-    va_start(ptr,fmt);
-    length = DebugSNPrintFVAList(sbuffer, buflen, fmt, ptr);
-    va_end(ptr);
-
-    return(length);
-}
-
-//===========================================================================================================================
-//	DebugSNPrintFVAList	- va_list version of DebugSNPrintF. See DebugSNPrintF for more info.
-//===========================================================================================================================
-
-DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg)
-{
-    static const struct DebugSNPrintF_format
-    {
-        unsigned leftJustify : 1;
-        unsigned forceSign : 1;
-        unsigned zeroPad : 1;
-        unsigned havePrecision : 1;
-        unsigned hSize : 1;
-        char lSize;
-        char altForm;
-        char sign;              // +, - or space
-        unsigned int fieldWidth;
-        unsigned int precision;
-    } DebugSNPrintF_format_default = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-    size_t nwritten = 0;
-    int c;
-#if TYPE_LONGLONG_NATIVE
-    unsigned_long_long_compat n;
-    unsigned_long_long_compat base;
-#else
-    unsigned long n;
-    unsigned long base;
-#endif
-    if (buflen == 0) return(0);
-    buflen--;       // Pre-reserve one space in the buffer for the terminating nul
-    if (buflen == 0) goto exit;
-
-    for (c = *fmt; c != 0; c = *++fmt)
-    {
-        if (c != '%')
-        {
-            *sbuffer++ = (char)c;
-            if (++nwritten >= buflen) goto exit;
-        }
-        else
-        {
-            size_t 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_Size 300
-            char mDNS_VACB[mDNS_VACB_Size];
-            #define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size])
-            #define mDNS_VACB_Remain(s) ((size_t)(mDNS_VACB_Lim - s))
-            char *s = mDNS_VACB_Lim;
-            const char *digits = "0123456789ABCDEF";
-            struct DebugSNPrintF_format F = DebugSNPrintF_format_default;
-
-            for(;;) //  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
-            {
-            case 'h':  F.hSize = 1; c = *++fmt; goto conv;
-            case 'l':       // fall through
-            case 'L':  F.lSize++; c = *++fmt; goto conv;
-            case 'd':
-            case 'i':  base = 10;
-                goto canBeSigned;
-            case 'u':  base = 10;
-                goto notSigned;
-            case 'o':  base = 8;
-                goto notSigned;
-            case 'b':  base = 2;
-                goto notSigned;
-            case 'p':  n = va_arg(arg, uintptr_t);
-                F.havePrecision = 1;
-                F.precision = (sizeof(uintptr_t) == 4) ? 8 : 16;
-                F.sign = 0;
-                base = 16;
-                c = 'x';
-                goto number;
-            case 'x':  digits = "0123456789abcdef";
-            case 'X':  base = 16;
-                goto notSigned;
-canBeSigned:
-                            #if TYPE_LONGLONG_NATIVE
-                if (F.lSize == 1) n = (unsigned_long_long_compat)va_arg(arg, long);
-                else if (F.lSize == 2) n = (unsigned_long_long_compat)va_arg(arg, long_long_compat);
-                else n = (unsigned_long_long_compat)va_arg(arg, int);
-                            #else
-                if (F.lSize == 1) n = (unsigned long)va_arg(arg, long);
-                else if (F.lSize == 2) goto exit;
-                else n = (unsigned long)va_arg(arg, int);
-                            #endif
-                if (F.hSize) n = (short) n;
-                            #if TYPE_LONGLONG_NATIVE
-                if ((long_long_compat) n < 0) { n = (unsigned_long_long_compat)-(long_long_compat)n; F.sign = '-'; }
-                            #else
-                if ((long) n < 0) { n = (unsigned long)-(long)n; F.sign = '-'; }
-                            #endif
-                else if (F.forceSign) F.sign = '+';
-                goto number;
-
-notSigned:  if (F.lSize == 1) n = va_arg(arg, unsigned long);
-                else if (F.lSize == 2)
-                {
-                                #if TYPE_LONGLONG_NATIVE
-                    n = va_arg(arg, unsigned_long_long_compat);
-                                #else
-                    goto exit;
-                                #endif
-                }
-                else n = va_arg(arg, unsigned int);
-                if (F.hSize) n = (unsigned short) n;
-                F.sign = 0;
-                goto number;
-
-number:     if (!F.havePrecision)
-                {
-                    if (F.zeroPad)
-                    {
-                        F.precision = F.fieldWidth;
-                        if (F.altForm) F.precision -= 2;
-                        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 /= base, i++) *--s = (char)(digits[n % base]);
-                for (; i < F.precision; i++) *--s = '0';
-                if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; }
-                if (F.sign) { *--s = F.sign; i++; }
-                break;
-
-            case 'a':  {
-                unsigned char *a = va_arg(arg, unsigned char *);
-                char pre[4] = "";
-                char post[32] = "";
-                if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
-                else
-                {
-                    s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                    if (F.altForm == 1)
-                    {
-                                    #if (defined(MDNS_DEBUGMSGS))
-                        mDNSAddr *ip = (mDNSAddr*)a;
-                        switch (ip->type)
-                        {
-                        case mDNSAddrType_IPv4: F.precision =  4; a = (unsigned char *)&ip->ip.v4; break;
-                        case mDNSAddrType_IPv6: F.precision = 16; a = (unsigned char *)&ip->ip.v6; break;
-                        default:                F.precision =  0; break;
-                        }
-                                    #else
-                        F.precision = 0;                    // mDNSEmbeddedAPI.h not included so no mDNSAddr support
-                                    #endif
-                    }
-                    else if (F.altForm == 2)
-                    {
-                                    #ifdef AF_INET
-                        const struct sockaddr *sa;
-                        unsigned char *port;
-                        sa = (const struct sockaddr*)a;
-                        switch (sa->sa_family)
-                        {
-                        case AF_INET:  F.precision =  4; a = (unsigned char*)&((const struct sockaddr_in *)a)->sin_addr;
-                            port = (unsigned char*)&((const struct sockaddr_in *)sa)->sin_port;
-                            DebugSNPrintF(post, sizeof(post), ":%d", (port[0] << 8) | port[1]); break;
-                                            #ifdef AF_INET6
-                        case AF_INET6: F.precision = 16; a = (unsigned char*)&((const struct sockaddr_in6 *)a)->sin6_addr;
-                            pre[0] = '['; pre[1] = '\0';
-                            port = (unsigned char*)&((const struct sockaddr_in6 *)sa)->sin6_port;
-                            DebugSNPrintF(post, sizeof(post), "%%%d]:%d",
-                                          (int)((const struct sockaddr_in6 *)sa)->sin6_scope_id,
-                                          (port[0] << 8) | port[1]); break;
-                                            #endif
-                        default:       F.precision =  0; break;
-                        }
-                                    #else
-                        F.precision = 0;                    // socket interfaces not included so no sockaddr support
-                                    #endif
-                    }
-                    switch (F.precision)
-                    {
-                    case  4: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%d.%d.%d.%d%s",
-                                               a[0], a[1], a[2], a[3], post); break;
-                    case  6: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X",
-                                               a[0], a[1], a[2], a[3], a[4], a[5]); break;
-                    case  8: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
-                                               a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break;
-                    case 16: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB),
-                                               "%s%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%s",
-                                               pre, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8],
-                                               a[9], a[10], a[11], a[12], a[13], a[14], a[15], post); break;
-                    default: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify address size "
-                                               "(i.e. %.4a=IPv4, %.6a=Ethernet, %.8a=Fibre Channel %.16a=IPv6) >>"); break;
-                    }
-                }
-            }
-            break;
-
-            case 'U':  {
-                unsigned char *a = va_arg(arg, unsigned char *);
-                if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
-                else
-                {
-                    s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                    i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                                      *((uint32_t*) &a[0]), *((uint16_t*) &a[4]), *((uint16_t*) &a[6]),
-                                      a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); break;
-                }
-            }
-            break;
-
-            case 'c':  *--s = (char)va_arg(arg, int); i = 1; break;
-
-            case 'C':  if (F.lSize) n = va_arg(arg, unsigned long);
-                else n = va_arg(arg, unsigned int);
-                if (F.hSize) n = (unsigned short) n;
-                c = (int)( n        & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^');
-                c = (int)((n >>  8) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^');
-                c = (int)((n >> 16) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^');
-                c = (int)((n >> 24) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^');
-                i = 4;
-                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: i=0;
-                        if (F.havePrecision)                                // C string
-                        {
-                            while((i < F.precision) && s[i]) i++;
-                            // Make sure we don't truncate in the middle of a UTF-8 character.
-                            // If the last character is part of a multi-byte UTF-8 character, back up to the start of it.
-                            j=0;
-                            while((i > 0) && ((c = s[i-1]) & 0x80)) { j++; i--; if((c & 0xC0) != 0x80) break;}
-                            // If the actual count of UTF-8 characters matches the encoded UTF-8 count, add it back.
-                            if((j > 1) && (j <= 6))
-                            {
-                                int test = (0xFF << (8-j)) & 0xFF;
-                                int mask = test | (1 << ((8-j)-1));
-                                if((c & mask) == test) i += j;
-                            }
-                        }
-                        else
-                            while(s[i]) i++;
-                        break;
-                    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 += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<INVALID LABEL LENGTH %u>>", *a); break; }
-                            if (s + *a >= &mDNS_VACB[254]) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<NAME TOO LONG>>"); break; }
-                            s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "%#s.", a);
-                            a += 1 + *a;
-                        }
-                        i = (size_t)(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 'S':   {       // UTF-16 string
-                unsigned char *a = va_arg(arg, unsigned char *);
-                uint16_t      *u = (uint16_t*)a;
-                if (!u) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
-                if ((!F.havePrecision || F.precision))
-                {
-                    if      ((a[0] == 0xFE) && (a[1] == 0xFF)) { F.altForm = 1; u += 1; a += 2; F.precision--; }                // Big Endian
-                    else if ((a[0] == 0xFF) && (a[1] == 0xFE)) { F.altForm = 2; u += 1; a += 2; F.precision--; }                // Little Endian
-                }
-                s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                switch (F.altForm)
-                {
-                case 0: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s))                  // Host Endian
-                    { c = u[i]; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; }
-                    break;
-                case 1: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s))                  // Big Endian
-                    { c = ((a[0] << 8) | a[1]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; }
-                    break;
-                case 2: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s))                  // Little Endian
-                    { c = ((a[1] << 8) | a[0]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; }
-                    break;
-                }
-            }
-                s = mDNS_VACB;              // Reset s back to the start of the buffer
-                break;
-
-            #if TARGET_OS_MAC
-            case '@':   {       // Cocoa/CoreFoundation object
-                CFTypeRef cfObj;
-                CFStringRef cfStr;
-                cfObj = (CFTypeRef) va_arg(arg, void *);
-                cfStr = (CFGetTypeID(cfObj) == CFStringGetTypeID()) ? (CFStringRef)CFRetain(cfObj) : CFCopyDescription(cfObj);
-                s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                if (cfStr)
-                {
-                    CFRange range;
-                    CFIndex m;
-                    range = CFRangeMake(0, CFStringGetLength(cfStr));
-                    m = 0;
-                    CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, '^', false, (UInt8*)mDNS_VACB, (CFIndex)sizeof(mDNS_VACB), &m);
-                    CFRelease(cfStr);
-                    i = (size_t) m;
-                }
-                else
-                {
-                    i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "ERROR: <invalid CF object>" );
-                }
-            }
-                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;
-            #endif
-
-            case 'm':  {        // Error Message
-                long err;
-                if (F.lSize) err = va_arg(arg, long);
-                else err = va_arg(arg, int);
-                if (F.hSize) err = (short)err;
-                DebugGetErrorString(err, mDNS_VACB, sizeof(mDNS_VACB));
-                s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                for(i=0; s[i]; i++) {}
-            }
-            break;
-
-            case 'H':  {        // Hex Dump
-                void *a = va_arg(arg, void *);
-                size_t size = (size_t)va_arg(arg, int);
-                size_t max = (size_t)va_arg(arg, int);
-                DebugFlags flags =
-                    kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine |
-                    kDebugFlags8BitSeparator | kDebugFlagsNo32BitSeparator |
-                    kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount;
-                if (F.altForm == 0) flags |= kDebugFlagsNoASCII;
-                size = (max < size) ? max : size;
-                s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                i = DebugHexDump(kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, a, a, size, flags, mDNS_VACB, sizeof(mDNS_VACB));
-            }
-            break;
-
-            case 'v':  {        // Version
-                uint32_t version;
-                version = va_arg(arg, unsigned int);
-                DebugNumVersionToString(version, mDNS_VACB);
-                s = mDNS_VACB;              // Adjust s to point to the start of the buffer, not the end
-                for(i=0; s[i]; 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 = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "<<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:
-    *sbuffer++ = 0;
-    return(nwritten);
-}
-
-//===========================================================================================================================
-//	DebugGetErrorString
-//===========================================================================================================================
-
-DEBUG_EXPORT const char *   DebugGetErrorString( long inErrorCode, char *inBuffer, size_t inBufferSize )
-{
-    const char *        s;
-    char *              dst;
-    char *              end;
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-    char buffer[ 256 ];
-#endif
-
-    switch( inErrorCode )
-    {
-        #define CaseErrorString( X, STR )                   case X: s = STR; break
-        #define CaseErrorStringify( X )                     case X: s = # X; break
-        #define CaseErrorStringifyHardCode( VALUE, X )      case VALUE: s = # X; break
-
-        // General Errors
-
-        CaseErrorString( 0,  "no error" );
-        CaseErrorString( 1,  "in-progress/waiting" );
-        CaseErrorString( -1, "catch-all unknown error" );
-
-        // ACP Errors
-
-        CaseErrorStringifyHardCode( -2,  kACPBadRequestErr );
-        CaseErrorStringifyHardCode( -3,  kACPNoMemoryErr );
-        CaseErrorStringifyHardCode( -4,  kACPBadParamErr );
-        CaseErrorStringifyHardCode( -5,  kACPNotFoundErr );
-        CaseErrorStringifyHardCode( -6,  kACPBadChecksumErr );
-        CaseErrorStringifyHardCode( -7,  kACPCommandNotHandledErr );
-        CaseErrorStringifyHardCode( -8,  kACPNetworkErr );
-        CaseErrorStringifyHardCode( -9,  kACPDuplicateCommandHandlerErr );
-        CaseErrorStringifyHardCode( -10, kACPUnknownPropertyErr );
-        CaseErrorStringifyHardCode( -11, kACPImmutablePropertyErr );
-        CaseErrorStringifyHardCode( -12, kACPBadPropertyValueErr );
-        CaseErrorStringifyHardCode( -13, kACPNoResourcesErr );
-        CaseErrorStringifyHardCode( -14, kACPBadOptionErr );
-        CaseErrorStringifyHardCode( -15, kACPBadSizeErr );
-        CaseErrorStringifyHardCode( -16, kACPBadPasswordErr );
-        CaseErrorStringifyHardCode( -17, kACPNotInitializedErr );
-        CaseErrorStringifyHardCode( -18, kACPNonReadablePropertyErr );
-        CaseErrorStringifyHardCode( -19, kACPBadVersionErr );
-        CaseErrorStringifyHardCode( -20, kACPBadSignatureErr );
-        CaseErrorStringifyHardCode( -21, kACPBadIndexErr );
-        CaseErrorStringifyHardCode( -22, kACPUnsupportedErr );
-        CaseErrorStringifyHardCode( -23, kACPInUseErr );
-        CaseErrorStringifyHardCode( -24, kACPParamCountErr );
-        CaseErrorStringifyHardCode( -25, kACPIDErr );
-        CaseErrorStringifyHardCode( -26, kACPFormatErr );
-        CaseErrorStringifyHardCode( -27, kACPUnknownUserErr );
-        CaseErrorStringifyHardCode( -28, kACPAccessDeniedErr );
-        CaseErrorStringifyHardCode( -29, kACPIncorrectFWErr );
-
-        // Common Services Errors
-
-        CaseErrorStringify( kUnknownErr );
-        CaseErrorStringify( kOptionErr );
-        CaseErrorStringify( kSelectorErr );
-        CaseErrorStringify( kExecutionStateErr );
-        CaseErrorStringify( kPathErr );
-        CaseErrorStringify( kParamErr );
-        CaseErrorStringify( kParamCountErr );
-        CaseErrorStringify( kCommandErr );
-        CaseErrorStringify( kIDErr );
-        CaseErrorStringify( kStateErr );
-        CaseErrorStringify( kRangeErr );
-        CaseErrorStringify( kRequestErr );
-        CaseErrorStringify( kResponseErr );
-        CaseErrorStringify( kChecksumErr );
-        CaseErrorStringify( kNotHandledErr );
-        CaseErrorStringify( kVersionErr );
-        CaseErrorStringify( kSignatureErr );
-        CaseErrorStringify( kFormatErr );
-        CaseErrorStringify( kNotInitializedErr );
-        CaseErrorStringify( kAlreadyInitializedErr );
-        CaseErrorStringify( kNotInUseErr );
-        CaseErrorStringify( kInUseErr );
-        CaseErrorStringify( kTimeoutErr );
-        CaseErrorStringify( kCanceledErr );
-        CaseErrorStringify( kAlreadyCanceledErr );
-        CaseErrorStringify( kCannotCancelErr );
-        CaseErrorStringify( kDeletedErr );
-        CaseErrorStringify( kNotFoundErr );
-        CaseErrorStringify( kNoMemoryErr );
-        CaseErrorStringify( kNoResourcesErr );
-        CaseErrorStringify( kDuplicateErr );
-        CaseErrorStringify( kImmutableErr );
-        CaseErrorStringify( kUnsupportedDataErr );
-        CaseErrorStringify( kIntegrityErr );
-        CaseErrorStringify( kIncompatibleErr );
-        CaseErrorStringify( kUnsupportedErr );
-        CaseErrorStringify( kUnexpectedErr );
-        CaseErrorStringify( kValueErr );
-        CaseErrorStringify( kNotReadableErr );
-        CaseErrorStringify( kNotWritableErr );
-        CaseErrorStringify( kBadReferenceErr );
-        CaseErrorStringify( kFlagErr );
-        CaseErrorStringify( kMalformedErr );
-        CaseErrorStringify( kSizeErr );
-        CaseErrorStringify( kNameErr );
-        CaseErrorStringify( kNotReadyErr );
-        CaseErrorStringify( kReadErr );
-        CaseErrorStringify( kWriteErr );
-        CaseErrorStringify( kMismatchErr );
-        CaseErrorStringify( kDateErr );
-        CaseErrorStringify( kUnderrunErr );
-        CaseErrorStringify( kOverrunErr );
-        CaseErrorStringify( kEndingErr );
-        CaseErrorStringify( kConnectionErr );
-        CaseErrorStringify( kAuthenticationErr );
-        CaseErrorStringify( kOpenErr );
-        CaseErrorStringify( kTypeErr );
-        CaseErrorStringify( kSkipErr );
-        CaseErrorStringify( kNoAckErr );
-        CaseErrorStringify( kCollisionErr );
-        CaseErrorStringify( kBackoffErr );
-        CaseErrorStringify( kNoAddressAckErr );
-        CaseErrorStringify( kBusyErr );
-        CaseErrorStringify( kNoSpaceErr );
-
-        // mDNS/DNS-SD Errors
-
-        CaseErrorStringifyHardCode( -65537, mStatus_UnknownErr );
-        CaseErrorStringifyHardCode( -65538, mStatus_NoSuchNameErr );
-        CaseErrorStringifyHardCode( -65539, mStatus_NoMemoryErr );
-        CaseErrorStringifyHardCode( -65540, mStatus_BadParamErr );
-        CaseErrorStringifyHardCode( -65541, mStatus_BadReferenceErr );
-        CaseErrorStringifyHardCode( -65542, mStatus_BadStateErr );
-        CaseErrorStringifyHardCode( -65543, mStatus_BadFlagsErr );
-        CaseErrorStringifyHardCode( -65544, mStatus_UnsupportedErr );
-        CaseErrorStringifyHardCode( -65545, mStatus_NotInitializedErr );
-        CaseErrorStringifyHardCode( -65546, mStatus_NoCache );
-        CaseErrorStringifyHardCode( -65547, mStatus_AlreadyRegistered );
-        CaseErrorStringifyHardCode( -65548, mStatus_NameConflict );
-        CaseErrorStringifyHardCode( -65549, mStatus_Invalid );
-        CaseErrorStringifyHardCode( -65550, mStatus_GrowCache );
-        CaseErrorStringifyHardCode( -65551, mStatus_Incompatible );
-        CaseErrorStringifyHardCode( -65552, mStatus_BadInterfaceErr );
-        CaseErrorStringifyHardCode( -65791, mStatus_ConfigChanged );
-        CaseErrorStringifyHardCode( -65792, mStatus_MemFree );
-
-        // RSP Errors
-
-        CaseErrorStringifyHardCode( -400000, kRSPUnknownErr );
-        CaseErrorStringifyHardCode( -400050, kRSPParamErr );
-        CaseErrorStringifyHardCode( -400108, kRSPNoMemoryErr );
-        CaseErrorStringifyHardCode( -405246, kRSPRangeErr );
-        CaseErrorStringifyHardCode( -409057, kRSPSizeErr );
-        CaseErrorStringifyHardCode( -400200, kRSPHardwareErr );
-        CaseErrorStringifyHardCode( -401712, kRSPTimeoutErr );
-        CaseErrorStringifyHardCode( -402053, kRSPUnsupportedErr );
-        CaseErrorStringifyHardCode( -402419, kRSPIDErr );
-        CaseErrorStringifyHardCode( -403165, kRSPFlagErr );
-        CaseErrorString(            -200000, "kRSPControllerStatusBase - 0x50" );
-        CaseErrorString(            -200080, "kRSPCommandSucceededErr - 0x50" );
-        CaseErrorString(            -200001, "kRSPCommandFailedErr - 0x01" );
-        CaseErrorString(            -200051, "kRSPChecksumErr - 0x33" );
-        CaseErrorString(            -200132, "kRSPCommandTimeoutErr - 0x84" );
-        CaseErrorString(            -200034, "kRSPPasswordRequiredErr - 0x22 OBSOLETE" );
-        CaseErrorString(            -200128, "kRSPCanceledErr - 0x02 Async" );
-
-        // XML Errors
-
-        CaseErrorStringifyHardCode( -100043, kXMLNotFoundErr );
-        CaseErrorStringifyHardCode( -100050, kXMLParamErr );
-        CaseErrorStringifyHardCode( -100108, kXMLNoMemoryErr );
-        CaseErrorStringifyHardCode( -100206, kXMLFormatErr );
-        CaseErrorStringifyHardCode( -100586, kXMLNoRootElementErr );
-        CaseErrorStringifyHardCode( -101703, kXMLWrongDataTypeErr );
-        CaseErrorStringifyHardCode( -101726, kXMLKeyErr );
-        CaseErrorStringifyHardCode( -102053, kXMLUnsupportedErr );
-        CaseErrorStringifyHardCode( -102063, kXMLMissingElementErr );
-        CaseErrorStringifyHardCode( -103026, kXMLParseErr );
-        CaseErrorStringifyHardCode( -103159, kXMLBadDataErr );
-        CaseErrorStringifyHardCode( -103170, kXMLBadNameErr );
-        CaseErrorStringifyHardCode( -105246, kXMLRangeErr );
-        CaseErrorStringifyHardCode( -105251, kXMLUnknownElementErr );
-        CaseErrorStringifyHardCode( -108739, kXMLMalformedInputErr );
-        CaseErrorStringifyHardCode( -109057, kXMLBadSizeErr );
-        CaseErrorStringifyHardCode( -101730, kXMLMissingChildElementErr );
-        CaseErrorStringifyHardCode( -102107, kXMLMissingParentElementErr );
-        CaseErrorStringifyHardCode( -130587, kXMLNonRootElementErr );
-        CaseErrorStringifyHardCode( -102015, kXMLDateErr );
-
-    #if ( __MACH__ )
-
-        // Mach Errors
-
-        CaseErrorStringifyHardCode( 0x00002000, MACH_MSG_IPC_SPACE );
-        CaseErrorStringifyHardCode( 0x00001000, MACH_MSG_VM_SPACE );
-        CaseErrorStringifyHardCode( 0x00000800, MACH_MSG_IPC_KERNEL );
-        CaseErrorStringifyHardCode( 0x00000400, MACH_MSG_VM_KERNEL );
-        CaseErrorStringifyHardCode( 0x10000001, MACH_SEND_IN_PROGRESS );
-        CaseErrorStringifyHardCode( 0x10000002, MACH_SEND_INVALID_DATA );
-        CaseErrorStringifyHardCode( 0x10000003, MACH_SEND_INVALID_DEST );
-        CaseErrorStringifyHardCode( 0x10000004, MACH_SEND_TIMED_OUT );
-        CaseErrorStringifyHardCode( 0x10000007, MACH_SEND_INTERRUPTED );
-        CaseErrorStringifyHardCode( 0x10000008, MACH_SEND_MSG_TOO_SMALL );
-        CaseErrorStringifyHardCode( 0x10000009, MACH_SEND_INVALID_REPLY );
-        CaseErrorStringifyHardCode( 0x1000000A, MACH_SEND_INVALID_RIGHT );
-        CaseErrorStringifyHardCode( 0x1000000B, MACH_SEND_INVALID_NOTIFY );
-        CaseErrorStringifyHardCode( 0x1000000C, MACH_SEND_INVALID_MEMORY );
-        CaseErrorStringifyHardCode( 0x1000000D, MACH_SEND_NO_BUFFER );
-        CaseErrorStringifyHardCode( 0x1000000E, MACH_SEND_TOO_LARGE );
-        CaseErrorStringifyHardCode( 0x1000000F, MACH_SEND_INVALID_TYPE );
-        CaseErrorStringifyHardCode( 0x10000010, MACH_SEND_INVALID_HEADER );
-        CaseErrorStringifyHardCode( 0x10000011, MACH_SEND_INVALID_TRAILER );
-        CaseErrorStringifyHardCode( 0x10000015, MACH_SEND_INVALID_RT_OOL_SIZE );
-        CaseErrorStringifyHardCode( 0x10004001, MACH_RCV_IN_PROGRESS );
-        CaseErrorStringifyHardCode( 0x10004002, MACH_RCV_INVALID_NAME );
-        CaseErrorStringifyHardCode( 0x10004003, MACH_RCV_TIMED_OUT );
-        CaseErrorStringifyHardCode( 0x10004004, MACH_RCV_TOO_LARGE );
-        CaseErrorStringifyHardCode( 0x10004005, MACH_RCV_INTERRUPTED );
-        CaseErrorStringifyHardCode( 0x10004006, MACH_RCV_PORT_CHANGED );
-        CaseErrorStringifyHardCode( 0x10004007, MACH_RCV_INVALID_NOTIFY );
-        CaseErrorStringifyHardCode( 0x10004008, MACH_RCV_INVALID_DATA );
-        CaseErrorStringifyHardCode( 0x10004009, MACH_RCV_PORT_DIED );
-        CaseErrorStringifyHardCode( 0x1000400A, MACH_RCV_IN_SET );
-        CaseErrorStringifyHardCode( 0x1000400B, MACH_RCV_HEADER_ERROR );
-        CaseErrorStringifyHardCode( 0x1000400C, MACH_RCV_BODY_ERROR );
-        CaseErrorStringifyHardCode( 0x1000400D, MACH_RCV_INVALID_TYPE );
-        CaseErrorStringifyHardCode( 0x1000400E, MACH_RCV_SCATTER_SMALL );
-        CaseErrorStringifyHardCode( 0x1000400F, MACH_RCV_INVALID_TRAILER );
-        CaseErrorStringifyHardCode( 0x10004011, MACH_RCV_IN_PROGRESS_TIMED );
-
-        // Mach OSReturn Errors
-
-        CaseErrorStringifyHardCode( 0xDC000001, kOSReturnError );
-        CaseErrorStringifyHardCode( 0xDC004001, kOSMetaClassInternal );
-        CaseErrorStringifyHardCode( 0xDC004002, kOSMetaClassHasInstances );
-        CaseErrorStringifyHardCode( 0xDC004003, kOSMetaClassNoInit );
-        CaseErrorStringifyHardCode( 0xDC004004, kOSMetaClassNoTempData );
-        CaseErrorStringifyHardCode( 0xDC004005, kOSMetaClassNoDicts );
-        CaseErrorStringifyHardCode( 0xDC004006, kOSMetaClassNoKModSet );
-        CaseErrorStringifyHardCode( 0xDC004007, kOSMetaClassNoInsKModSet );
-        CaseErrorStringifyHardCode( 0xDC004008, kOSMetaClassNoSuper );
-        CaseErrorStringifyHardCode( 0xDC004009, kOSMetaClassInstNoSuper );
-        CaseErrorStringifyHardCode( 0xDC00400A, kOSMetaClassDuplicateClass );
-
-        // IOKit Errors
-
-        CaseErrorStringifyHardCode( 0xE00002BC, kIOReturnError );
-        CaseErrorStringifyHardCode( 0xE00002BD, kIOReturnNoMemory );
-        CaseErrorStringifyHardCode( 0xE00002BE, kIOReturnNoResources );
-        CaseErrorStringifyHardCode( 0xE00002BF, kIOReturnIPCError );
-        CaseErrorStringifyHardCode( 0xE00002C0, kIOReturnNoDevice );
-        CaseErrorStringifyHardCode( 0xE00002C1, kIOReturnNotPrivileged );
-        CaseErrorStringifyHardCode( 0xE00002C2, kIOReturnBadArgument );
-        CaseErrorStringifyHardCode( 0xE00002C3, kIOReturnLockedRead );
-        CaseErrorStringifyHardCode( 0xE00002C4, kIOReturnLockedWrite );
-        CaseErrorStringifyHardCode( 0xE00002C5, kIOReturnExclusiveAccess );
-        CaseErrorStringifyHardCode( 0xE00002C6, kIOReturnBadMessageID );
-        CaseErrorStringifyHardCode( 0xE00002C7, kIOReturnUnsupported );
-        CaseErrorStringifyHardCode( 0xE00002C8, kIOReturnVMError );
-        CaseErrorStringifyHardCode( 0xE00002C9, kIOReturnInternalError );
-        CaseErrorStringifyHardCode( 0xE00002CA, kIOReturnIOError );
-        CaseErrorStringifyHardCode( 0xE00002CC, kIOReturnCannotLock );
-        CaseErrorStringifyHardCode( 0xE00002CD, kIOReturnNotOpen );
-        CaseErrorStringifyHardCode( 0xE00002CE, kIOReturnNotReadable );
-        CaseErrorStringifyHardCode( 0xE00002CF, kIOReturnNotWritable );
-        CaseErrorStringifyHardCode( 0xE00002D0, kIOReturnNotAligned );
-        CaseErrorStringifyHardCode( 0xE00002D1, kIOReturnBadMedia );
-        CaseErrorStringifyHardCode( 0xE00002D2, kIOReturnStillOpen );
-        CaseErrorStringifyHardCode( 0xE00002D3, kIOReturnRLDError );
-        CaseErrorStringifyHardCode( 0xE00002D4, kIOReturnDMAError );
-        CaseErrorStringifyHardCode( 0xE00002D5, kIOReturnBusy );
-        CaseErrorStringifyHardCode( 0xE00002D6, kIOReturnTimeout );
-        CaseErrorStringifyHardCode( 0xE00002D7, kIOReturnOffline );
-        CaseErrorStringifyHardCode( 0xE00002D8, kIOReturnNotReady );
-        CaseErrorStringifyHardCode( 0xE00002D9, kIOReturnNotAttached );
-        CaseErrorStringifyHardCode( 0xE00002DA, kIOReturnNoChannels );
-        CaseErrorStringifyHardCode( 0xE00002DB, kIOReturnNoSpace );
-        CaseErrorStringifyHardCode( 0xE00002DD, kIOReturnPortExists );
-        CaseErrorStringifyHardCode( 0xE00002DE, kIOReturnCannotWire );
-        CaseErrorStringifyHardCode( 0xE00002DF, kIOReturnNoInterrupt );
-        CaseErrorStringifyHardCode( 0xE00002E0, kIOReturnNoFrames );
-        CaseErrorStringifyHardCode( 0xE00002E1, kIOReturnMessageTooLarge );
-        CaseErrorStringifyHardCode( 0xE00002E2, kIOReturnNotPermitted );
-        CaseErrorStringifyHardCode( 0xE00002E3, kIOReturnNoPower );
-        CaseErrorStringifyHardCode( 0xE00002E4, kIOReturnNoMedia );
-        CaseErrorStringifyHardCode( 0xE00002E5, kIOReturnUnformattedMedia );
-        CaseErrorStringifyHardCode( 0xE00002E6, kIOReturnUnsupportedMode );
-        CaseErrorStringifyHardCode( 0xE00002E7, kIOReturnUnderrun );
-        CaseErrorStringifyHardCode( 0xE00002E8, kIOReturnOverrun );
-        CaseErrorStringifyHardCode( 0xE00002E9, kIOReturnDeviceError     );
-        CaseErrorStringifyHardCode( 0xE00002EA, kIOReturnNoCompletion    );
-        CaseErrorStringifyHardCode( 0xE00002EB, kIOReturnAborted     );
-        CaseErrorStringifyHardCode( 0xE00002EC, kIOReturnNoBandwidth     );
-        CaseErrorStringifyHardCode( 0xE00002ED, kIOReturnNotResponding   );
-        CaseErrorStringifyHardCode( 0xE00002EE, kIOReturnIsoTooOld   );
-        CaseErrorStringifyHardCode( 0xE00002EF, kIOReturnIsoTooNew   );
-        CaseErrorStringifyHardCode( 0xE00002F0, kIOReturnNotFound );
-        CaseErrorStringifyHardCode( 0xE0000001, kIOReturnInvalid );
-
-        // IOKit FireWire Errors
-
-        CaseErrorStringifyHardCode( 0xE0008010, kIOFireWireResponseBase );
-        CaseErrorStringifyHardCode( 0xE0008020, kIOFireWireBusReset );
-        CaseErrorStringifyHardCode( 0xE0008001, kIOConfigNoEntry );
-        CaseErrorStringifyHardCode( 0xE0008002, kIOFireWirePending );
-        CaseErrorStringifyHardCode( 0xE0008003, kIOFireWireLastDCLToken );
-        CaseErrorStringifyHardCode( 0xE0008004, kIOFireWireConfigROMInvalid );
-        CaseErrorStringifyHardCode( 0xE0008005, kIOFireWireAlreadyRegistered );
-        CaseErrorStringifyHardCode( 0xE0008006, kIOFireWireMultipleTalkers );
-        CaseErrorStringifyHardCode( 0xE0008007, kIOFireWireChannelActive );
-        CaseErrorStringifyHardCode( 0xE0008008, kIOFireWireNoListenerOrTalker );
-        CaseErrorStringifyHardCode( 0xE0008009, kIOFireWireNoChannels );
-        CaseErrorStringifyHardCode( 0xE000800A, kIOFireWireChannelNotAvailable );
-        CaseErrorStringifyHardCode( 0xE000800B, kIOFireWireSeparateBus );
-        CaseErrorStringifyHardCode( 0xE000800C, kIOFireWireBadSelfIDs );
-        CaseErrorStringifyHardCode( 0xE000800D, kIOFireWireLowCableVoltage );
-        CaseErrorStringifyHardCode( 0xE000800E, kIOFireWireInsufficientPower );
-        CaseErrorStringifyHardCode( 0xE000800F, kIOFireWireOutOfTLabels );
-        CaseErrorStringifyHardCode( 0xE0008101, kIOFireWireBogusDCLProgram );
-        CaseErrorStringifyHardCode( 0xE0008102, kIOFireWireTalkingAndListening );
-        CaseErrorStringifyHardCode( 0xE0008103, kIOFireWireHardwareSlept );
-        CaseErrorStringifyHardCode( 0xE00087D0, kIOFWMessageServiceIsRequestingClose );
-        CaseErrorStringifyHardCode( 0xE00087D1, kIOFWMessagePowerStateChanged );
-        CaseErrorStringifyHardCode( 0xE00087D2, kIOFWMessageTopologyChanged );
-
-        // IOKit USB Errors
-
-        CaseErrorStringifyHardCode( 0xE0004061, kIOUSBUnknownPipeErr );
-        CaseErrorStringifyHardCode( 0xE0004060, kIOUSBTooManyPipesErr );
-        CaseErrorStringifyHardCode( 0xE000405F, kIOUSBNoAsyncPortErr );
-        CaseErrorStringifyHardCode( 0xE000405E, kIOUSBNotEnoughPipesErr );
-        CaseErrorStringifyHardCode( 0xE000405D, kIOUSBNotEnoughPowerErr );
-        CaseErrorStringifyHardCode( 0xE0004057, kIOUSBEndpointNotFound );
-        CaseErrorStringifyHardCode( 0xE0004056, kIOUSBConfigNotFound );
-        CaseErrorStringifyHardCode( 0xE0004051, kIOUSBTransactionTimeout );
-        CaseErrorStringifyHardCode( 0xE0004050, kIOUSBTransactionReturned );
-        CaseErrorStringifyHardCode( 0xE000404F, kIOUSBPipeStalled );
-        CaseErrorStringifyHardCode( 0xE000404E, kIOUSBInterfaceNotFound );
-        CaseErrorStringifyHardCode( 0xE000404D, kIOUSBLowLatencyBufferNotPreviouslyAllocated );
-        CaseErrorStringifyHardCode( 0xE000404C, kIOUSBLowLatencyFrameListNotPreviouslyAllocated );
-        CaseErrorStringifyHardCode( 0xE000404B, kIOUSBHighSpeedSplitError );
-        CaseErrorStringifyHardCode( 0xE0004010, kIOUSBLinkErr );
-        CaseErrorStringifyHardCode( 0xE000400F, kIOUSBNotSent2Err );
-        CaseErrorStringifyHardCode( 0xE000400E, kIOUSBNotSent1Err );
-        CaseErrorStringifyHardCode( 0xE000400D, kIOUSBBufferUnderrunErr );
-        CaseErrorStringifyHardCode( 0xE000400C, kIOUSBBufferOverrunErr );
-        CaseErrorStringifyHardCode( 0xE000400B, kIOUSBReserved2Err );
-        CaseErrorStringifyHardCode( 0xE000400A, kIOUSBReserved1Err );
-        CaseErrorStringifyHardCode( 0xE0004007, kIOUSBWrongPIDErr );
-        CaseErrorStringifyHardCode( 0xE0004006, kIOUSBPIDCheckErr );
-        CaseErrorStringifyHardCode( 0xE0004003, kIOUSBDataToggleErr );
-        CaseErrorStringifyHardCode( 0xE0004002, kIOUSBBitstufErr );
-        CaseErrorStringifyHardCode( 0xE0004001, kIOUSBCRCErr );
-
-    #endif  // __MACH__
-
-    // Other Errors
-
-    default:
-        s = NULL;
-            #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-        if( inBuffer && ( inBufferSize > 0 ) )
-        {
-            DWORD n;
-
-            n = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) inErrorCode,
-                                MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), buffer, sizeof( buffer ), NULL );
-            if( n > 0 )
-            {
-                // Remove any trailing CR's or LF's since some messages have them.
-
-                while( ( n > 0 ) && isspace( ( (unsigned char *) buffer )[ n - 1 ] ) )
-                {
-                    buffer[ --n ] = '\0';
-                }
-                s = buffer;
-            }
-        }
-            #endif
-
-        if( !s )
-        {
-                #if ( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE )
-            if( ( inErrorCode >= INT_MIN ) && ( inErrorCode <= INT_MAX ) )
-            {
-                s = strerror( (int) inErrorCode );
-            }
-                #endif
-            if( !s )
-            {
-                s = "<unknown error code>";
-            }
-        }
-        break;
-    }
-
-    // Copy the string to the output buffer. If no buffer is supplied or it is empty, return an empty string.
-
-    if( inBuffer && ( inBufferSize > 0 ) )
-    {
-        dst = inBuffer;
-        end = dst + ( inBufferSize - 1 );
-        while( ( ( end - dst ) > 0 ) && ( *s != '\0' ) )
-        {
-            *dst++ = *s++;
-        }
-        *dst = '\0';
-        s = inBuffer;
-    }
-    return( s );
-}
-
-//===========================================================================================================================
-//	DebugHexDump
-//===========================================================================================================================
-
-DEBUG_EXPORT size_t
-DebugHexDump(
-    DebugLevel inLevel,
-    int inIndent,
-    const char *    inLabel,
-    size_t inLabelSize,
-    int inLabelMinWidth,
-    const char *    inType,
-    size_t inTypeSize,
-    const void *    inDataStart,
-    const void *    inData,
-    size_t inDataSize,
-    DebugFlags inFlags,
-    char *          outBuffer,
-    size_t inBufferSize )
-{
-    static const char kHexChars[] = "0123456789ABCDEF";
-    const uint8_t *         start;
-    const uint8_t *         src;
-    char *                  dst;
-    char *                  end;
-    size_t n;
-    int offset;
-    int width;
-    const char *            newline;
-    char separator[ 8 ];
-    char *                  s;
-
-    DEBUG_UNUSED( inType );
-    DEBUG_UNUSED( inTypeSize );
-
-    // Set up the function-wide variables.
-
-    if( inLabelSize == kSizeCString )
-    {
-        inLabelSize = strlen( inLabel );
-    }
-    start   = (const uint8_t *) inData;
-    src     = start;
-    dst     = outBuffer;
-    end     = dst + inBufferSize;
-    offset  = (int)( (intptr_t) inData - (intptr_t) inDataStart );
-    width   = ( (int) inLabelSize > inLabelMinWidth ) ? (int) inLabelSize : inLabelMinWidth;
-    newline = ( inFlags & kDebugFlagsNoNewLine ) ? "" : "\n";
-
-    // Set up the separator string. This is used to insert spaces on subsequent "lines" when not using newlines.
-
-    s = separator;
-    if( inFlags & kDebugFlagsNoNewLine )
-    {
-        if( inFlags & kDebugFlags8BitSeparator )
-        {
-            *s++ = ' ';
-        }
-        if( inFlags & kDebugFlags16BitSeparator )
-        {
-            *s++ = ' ';
-        }
-        if( !( inFlags & kDebugFlagsNo32BitSeparator ) )
-        {
-            *s++ = ' ';
-        }
-        check( ( (size_t)( s - separator ) ) < sizeof( separator ) );
-    }
-    *s = '\0';
-
-    for( ;; )
-    {
-        char prefixString[ 32 ];
-        char hexString[ 64 ];
-        char asciiString[ 32 ];
-        char byteCountString[ 32 ];
-        int c;
-        size_t chunkSize;
-        size_t i;
-
-        // If this is a label-only item (i.e. no data), print the label (accounting for prefix string spacing) and exit.
-
-        if( inDataSize == 0 )
-        {
-            if( inLabel && ( inLabelSize > 0 ) )
-            {
-                width = 0;
-                if( !( inFlags & kDebugFlagsNoAddress ) )
-                {
-                    width += 8;         // "00000000"
-                    if( !( inFlags & kDebugFlagsNoOffset ) )
-                    {
-                        width += 1;     // "+"
-                    }
-                }
-                if( inFlags & kDebugFlags32BitOffset )
-                {
-                    width += 8;         // "00000000"
-                }
-                else if( !( inFlags & kDebugFlagsNoOffset ) )
-                {
-                    width += 4;         // "0000"
-                }
-
-                if( outBuffer )
-                {
-                    dst += DebugSNPrintF( dst, (size_t)( end - dst ), "%*s" "%-*.*s" "%.*s" "%s",
-                                          width, "",
-                                          ( width > 0 ) ? ": " : "",
-                                          width, (int) inLabelSize, inLabel,
-                                          newline );
-                }
-                else
-                {
-                    dst += DebugPrintF( inLevel, "%*s" "%-*.*s" "%.*s" "%s",
-                                        width, "",
-                                        ( width > 0 ) ? ": " : "",
-                                        width, (int) inLabelSize, inLabel,
-                                        newline );
-                }
-            }
-            break;
-        }
-
-        // Build the prefix string. It will be in one of the following formats:
-        //
-        // 1) "00000000+0000[0000]"	(address and offset)
-        // 2) "00000000"			(address only)
-        // 3) "0000[0000]"			(offset only)
-        // 4) ""					(no address or offset)
-        //
-        // Note: If we're printing multiple "lines", but not printing newlines, a space is used to separate.
-
-        s = prefixString;
-        if( !( inFlags & kDebugFlagsNoAddress ) )
-        {
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 28 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 24 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 20 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 16 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 12 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >>  8 ) & 0xF ];
-            *s++ = kHexChars[ ( ( (uintptr_t) src ) >>  4 ) & 0xF ];
-            *s++ = kHexChars[   ( (uintptr_t) src )         & 0xF ];
-
-            if( !( inFlags & kDebugFlagsNoOffset ) )
-            {
-                *s++ = '+';
-            }
-        }
-        if( !( inFlags & kDebugFlagsNoOffset ) )
-        {
-            if( inFlags & kDebugFlags32BitOffset )
-            {
-                *s++ = kHexChars[ ( offset >> 28 ) & 0xF ];
-                *s++ = kHexChars[ ( offset >> 24 ) & 0xF ];
-                *s++ = kHexChars[ ( offset >> 20 ) & 0xF ];
-                *s++ = kHexChars[ ( offset >> 16 ) & 0xF ];
-            }
-            *s++ = kHexChars[ ( offset >> 12 ) & 0xF ];
-            *s++ = kHexChars[ ( offset >>  8 ) & 0xF ];
-            *s++ = kHexChars[ ( offset >>  4 ) & 0xF ];
-            *s++ = kHexChars[   offset         & 0xF ];
-        }
-        if( s != prefixString )
-        {
-            *s++ = ':';
-            *s++ = ' ';
-        }
-        check( ( (size_t)( s - prefixString ) ) < sizeof( prefixString ) );
-        *s = '\0';
-
-        // Build a hex string with a optional spaces after every 1, 2, and/or 4 bytes to make it easier to read.
-        // Optionally pads the hex string with space to fill the full 16 byte range (so it lines up).
-
-        s = hexString;
-        chunkSize = ( inDataSize < 16 ) ? inDataSize : 16;
-        n = ( inFlags & kDebugFlagsNo16ByteHexPad ) ? chunkSize : 16;
-        for( i = 0; i < n; ++i )
-        {
-            if( ( inFlags & kDebugFlags8BitSeparator ) && ( i > 0 ) )
-            {
-                *s++ = ' ';
-            }
-            if( ( inFlags & kDebugFlags16BitSeparator ) && ( i > 0 ) && ( ( i % 2 ) == 0 ) )
-            {
-                *s++ = ' ';
-            }
-            if( !( inFlags & kDebugFlagsNo32BitSeparator ) && ( i > 0 ) && ( ( i % 4 ) == 0 ) )
-            {
-                *s++ = ' ';
-            }
-            if( i < chunkSize )
-            {
-                *s++ = kHexChars[ src[ i ] >> 4   ];
-                *s++ = kHexChars[ src[ i ] &  0xF ];
-            }
-            else
-            {
-                *s++ = ' ';
-                *s++ = ' ';
-            }
-        }
-        check( ( (size_t)( s - hexString ) ) < sizeof( hexString ) );
-        *s = '\0';
-
-        // Build a string with the ASCII version of the data (replaces non-printable characters with '^').
-        // Optionally pads the string with '`' to fill the full 16 byte range (so it lines up).
-
-        s = asciiString;
-        if( !( inFlags & kDebugFlagsNoASCII ) )
-        {
-            *s++ = ' ';
-            *s++ = '|';
-            for( i = 0; i < n; ++i )
-            {
-                if( i < chunkSize )
-                {
-                    c = src[ i ];
-                    if( !DebugIsPrint( c ) )
-                    {
-                        c = '^';
-                    }
-                }
-                else
-                {
-                    c = '`';
-                }
-                *s++ = (char) c;
-            }
-            *s++ = '|';
-            check( ( (size_t)( s - asciiString ) ) < sizeof( asciiString ) );
-        }
-        *s = '\0';
-
-        // Build a string indicating how bytes are in the hex dump. Only printed on the first line.
-
-        s = byteCountString;
-        if( !( inFlags & kDebugFlagsNoByteCount ) )
-        {
-            if( src == start )
-            {
-                s += DebugSNPrintF( s, sizeof( byteCountString ), " (%d bytes)", (int) inDataSize );
-            }
-        }
-        check( ( (size_t)( s - byteCountString ) ) < sizeof( byteCountString ) );
-        *s = '\0';
-
-        // Build the entire line from all the pieces we've previously built.
-
-        if( outBuffer )
-        {
-            if( src == start )
-            {
-                dst += DebugSNPrintF( dst, (size_t)( end - dst ),
-                                      "%*s" // Indention
-                                      "%s" // Separator (only if needed)
-                                      "%s" // Prefix
-                                      "%-*.*s" // Label
-                                      "%s" // Separator
-                                      "%s" // Hex
-                                      "%s" // ASCII
-                                      "%s" // Byte Count
-                                      "%s", // Newline
-                                      inIndent, "",
-                                      ( src != start ) ? separator : "",
-                                      prefixString,
-                                      width, (int) inLabelSize, inLabel ? inLabel : "",
-                                      ( width > 0 ) ? " " : "",
-                                      hexString,
-                                      asciiString,
-                                      byteCountString,
-                                      newline );
-            }
-            else
-            {
-                dst += DebugSNPrintF( dst, (size_t)( end - dst ),
-                                      "%*s" // Indention
-                                      "%s" // Separator (only if needed)
-                                      "%s" // Prefix
-                                      "%*s" // Label Spacing
-                                      "%s" // Separator
-                                      "%s" // Hex
-                                      "%s" // ASCII
-                                      "%s" // Byte Count
-                                      "%s", // Newline
-                                      inIndent, "",
-                                      ( src != start ) ? separator : "",
-                                      prefixString,
-                                      width, "",
-                                      ( width > 0 ) ? " " : "",
-                                      hexString,
-                                      asciiString,
-                                      byteCountString,
-                                      newline );
-            }
-        }
-        else
-        {
-            if( src == start )
-            {
-                dst += DebugPrintF( inLevel,
-                                    "%*s" // Indention
-                                    "%s" // Separator (only if needed)
-                                    "%s" // Prefix
-                                    "%-*.*s" // Label
-                                    "%s" // Separator
-                                    "%s" // Hex
-                                    "%s" // ASCII
-                                    "%s" // Byte Count
-                                    "%s", // Newline
-                                    inIndent, "",
-                                    ( src != start ) ? separator : "",
-                                    prefixString,
-                                    width, (int) inLabelSize, inLabel,
-                                    ( width > 0 ) ? " " : "",
-                                    hexString,
-                                    asciiString,
-                                    byteCountString,
-                                    newline );
-            }
-            else
-            {
-                dst += DebugPrintF( inLevel,
-                                    "%*s" // Indention
-                                    "%s" // Separator (only if needed)
-                                    "%s" // Prefix
-                                    "%*s" // Label Spacing
-                                    "%s" // Separator
-                                    "%s" // Hex
-                                    "%s" // ASCII
-                                    "%s" // Byte Count
-                                    "%s", // Newline
-                                    inIndent, "",
-                                    ( src != start ) ? separator : "",
-                                    prefixString,
-                                    width, "",
-                                    ( width > 0 ) ? " " : "",
-                                    hexString,
-                                    asciiString,
-                                    byteCountString,
-                                    newline );
-            }
-        }
-
-        // Move to the next chunk. Exit if there is no more data.
-
-        offset      += (int) chunkSize;
-        src         += chunkSize;
-        inDataSize  -= chunkSize;
-        if( inDataSize == 0 )
-        {
-            break;
-        }
-    }
-
-    // Note: The "dst - outBuffer" size calculation works even if "outBuffer" is NULL because it's all relative.
-
-    return( (size_t)( dst - outBuffer ) );
-}
-
-//===========================================================================================================================
-//	DebugNumVersionToString
-//===========================================================================================================================
-
-static char *   DebugNumVersionToString( uint32_t inVersion, char *inString )
-{
-    char *      s;
-    uint8_t majorRev;
-    uint8_t minor;
-    uint8_t bugFix;
-    uint8_t stage;
-    uint8_t revision;
-
-    check( inString );
-
-    majorRev    = (uint8_t)( ( inVersion >> 24 ) & 0xFF );
-    minor       = (uint8_t)( ( inVersion >> 20 ) & 0x0F );
-    bugFix      = (uint8_t)( ( inVersion >> 16 ) & 0x0F );
-    stage       = (uint8_t)( ( inVersion >>  8 ) & 0xFF );
-    revision    = (uint8_t)(   inVersion         & 0xFF );
-
-    // Convert the major, minor, and bugfix numbers.
-
-    s  = inString;
-    s += sprintf( s, "%u", majorRev );
-    s += sprintf( s, ".%u", minor );
-    if( bugFix != 0 )
-    {
-        s += sprintf( s, ".%u", bugFix );
-    }
-
-    // Convert the version stage and non-release revision number.
-
-    switch( stage )
-    {
-    case kVersionStageDevelopment:
-        s += sprintf( s, "d%u", revision );
-        break;
-
-    case kVersionStageAlpha:
-        s += sprintf( s, "a%u", revision );
-        break;
-
-    case kVersionStageBeta:
-        s += sprintf( s, "b%u", revision );
-        break;
-
-    case kVersionStageFinal:
-
-        // A non-release revision of zero is a special case indicating the software is GM (at the golden master
-        // stage) and therefore, the non-release revision should not be added to the string.
-
-        if( revision != 0 )
-        {
-            s += sprintf( s, "f%u", revision );
-        }
-        break;
-
-    default:
-        dlog( kDebugLevelError, "invalid NumVersion stage (0x%02X)\n", stage );
-        break;
-    }
-    return( inString );
-}
-
-//===========================================================================================================================
-//	DebugTaskLevel
-//===========================================================================================================================
-
-DEBUG_EXPORT uint32_t   DebugTaskLevel( void )
-{
-    uint32_t level;
-
-    level = 0;
-
-    return( level );
-}
-
-#if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
-//===========================================================================================================================
-//	DebugWinEnableConsole
-//===========================================================================================================================
-
-#pragma warning( disable:4311 )
-
-static void DebugWinEnableConsole( void )
-{
-    static bool sConsoleEnabled = false;
-    BOOL result;
-    int fileHandle;
-    FILE *          file;
-    int err;
-
-    if( sConsoleEnabled )
-    {
-        goto exit;
-    }
-
-    // Create console window.
-
-    result = AllocConsole();
-    require_quiet( result, exit );
-
-    // Redirect stdin to the console stdin.
-
-    fileHandle = _open_osfhandle( (long) GetStdHandle( STD_INPUT_HANDLE ), _O_TEXT );
-
-    #if ( defined( __MWERKS__ ) )
-    file = __handle_reopen( (unsigned long) fileHandle, "r", stdin );
-    require_quiet( file, exit );
-    #else
-    file = _fdopen( fileHandle, "r" );
-    require_quiet( file, exit );
-
-    *stdin = *file;
-    #endif
-
-    err = setvbuf( stdin, NULL, _IONBF, 0 );
-    require_noerr_quiet( err, exit );
-
-    // Redirect stdout to the console stdout.
-
-    fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT );
-
-    #if ( defined( __MWERKS__ ) )
-    file = __handle_reopen( (unsigned long) fileHandle, "w", stdout );
-    require_quiet( file, exit );
-    #else
-    file = _fdopen( fileHandle, "w" );
-    require_quiet( file, exit );
-
-    *stdout = *file;
-    #endif
-
-    err = setvbuf( stdout, NULL, _IONBF, 0 );
-    require_noerr_quiet( err, exit );
-
-    // Redirect stderr to the console stdout.
-
-    fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT );
-
-    #if ( defined( __MWERKS__ ) )
-    file = __handle_reopen( (unsigned long) fileHandle, "w", stderr );
-    require_quiet( file, exit );
-    #else
-    file = _fdopen( fileHandle, "w" );
-    require_quiet( file, exit );
-
-    *stderr = *file;
-    #endif
-
-    err = setvbuf( stderr, NULL, _IONBF, 0 );
-    require_noerr_quiet( err, exit );
-
-    sConsoleEnabled = true;
-
-exit:
-    return;
-}
-
-#pragma warning( default:4311 )
-
-#endif  // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE
-
-#if ( TARGET_OS_WIN32 )
-//===========================================================================================================================
-//	DebugWinCharToTCharString
-//===========================================================================================================================
-
-static TCHAR *
-DebugWinCharToTCharString(
-    const char *    inCharString,
-    size_t inCharCount,
-    TCHAR *         outTCharString,
-    size_t inTCharCountMax,
-    size_t *        outTCharCount )
-{
-    const char *        src;
-    TCHAR *             dst;
-    TCHAR *             end;
-
-    if( inCharCount == kSizeCString )
-    {
-        inCharCount = strlen( inCharString );
-    }
-    src = inCharString;
-    dst = outTCharString;
-    if( inTCharCountMax > 0 )
-    {
-        inTCharCountMax -= 1;
-        if( inTCharCountMax > inCharCount )
-        {
-            inTCharCountMax = inCharCount;
-        }
-
-        end = dst + inTCharCountMax;
-        while( dst < end )
-        {
-            *dst++ = (TCHAR) *src++;
-        }
-        *dst = 0;
-    }
-    if( outTCharCount )
-    {
-        *outTCharCount = (size_t)( dst - outTCharString );
-    }
-    return( outTCharString );
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Debugging ==
-#endif
-
-//===========================================================================================================================
-//	DebugServicesTest
-//===========================================================================================================================
-
-DEBUG_EXPORT OSStatus   DebugServicesTest( void )
-{
-    OSStatus err;
-    char s[ 512 ];
-    uint8_t *       p;
-    uint8_t data[] =
-    {
-        0x11, 0x22, 0x33, 0x44,
-        0x55, 0x66,
-        0x77, 0x88, 0x99, 0xAA,
-        0xBB, 0xCC, 0xDD,
-        0xEE,
-        0xFF,
-        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
-        0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,
-        0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1
-    };
-
-    debug_initialize( kDebugOutputTypeMetaConsole );
-
-    // check's
-
-    check( 0 && "SHOULD SEE: check" );
-    check( 1 && "SHOULD *NOT* SEE: check (valid)" );
-    check_string( 0, "SHOULD SEE: check_string" );
-    check_string( 1, "SHOULD *NOT* SEE: check_string (valid)" );
-    check_noerr( -123 );
-    check_noerr( 10038 );
-    check_noerr( 22 );
-    check_noerr( 0 );
-    check_noerr_string( -6712, "SHOULD SEE: check_noerr_string" );
-    check_noerr_string( 0, "SHOULD *NOT* SEE: check_noerr_string (valid)" );
-    check_translated_errno( 0 >= 0 && "SHOULD *NOT* SEE", -384, -999 );
-    check_translated_errno( -1 >= 0 && "SHOULD SEE", -384, -999 );
-    check_translated_errno( -1 >= 0 && "SHOULD SEE", 0, -999 );
-    check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 22, 10 );
-    check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10,  5, 10 );
-    check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 12,  6 );
-    check_ptr_overlap( "SHOULD SEE" ? 12 : 0,  6, 10, 10 );
-    check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 10, 10, 10 );
-    check_ptr_overlap( "SHOULD *NOT* SEE" ? 22 : 0, 10, 10, 10 );
-    check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 20, 10 );
-    check_ptr_overlap( "SHOULD *NOT* SEE" ? 20 : 0, 10, 10, 10 );
-
-    // require's
-
-    require( 0 && "SHOULD SEE", require1 );
-    { err = kResponseErr; goto exit; }
-require1:
-    require( 1 && "SHOULD *NOT* SEE", require2 );
-    goto require2Good;
-require2:
-    { err = kResponseErr; goto exit; }
-require2Good:
-    require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" );
-    { err = kResponseErr; goto exit; }
-require3:
-    require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" );
-    goto require4Good;
-require4:
-    { err = kResponseErr; goto exit; }
-require4Good:
-    require_quiet( 0 && "SHOULD SEE", require5 );
-    { err = kResponseErr; goto exit; }
-require5:
-    require_quiet( 1 && "SHOULD *NOT* SEE", require6 );
-    goto require6Good;
-require6:
-    { err = kResponseErr; goto exit; }
-require6Good:
-    require_noerr( -1, require7 );
-    { err = kResponseErr; goto exit; }
-require7:
-    require_noerr( 0, require8 );
-    goto require8Good;
-require8:
-    { err = kResponseErr; goto exit; }
-require8Good:
-    require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string");
-    { err = kResponseErr; goto exit; }
-require9:
-    require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" );
-    goto require10Good;
-require10:
-    { err = kResponseErr; goto exit; }
-require10Good:
-    require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" );
-    { err = kResponseErr; goto exit; }
-require11:
-    require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" );
-    goto require12Good;
-require12:
-    { err = kResponseErr; goto exit; }
-require12Good:
-    require_noerr_quiet( -4, require13 );
-    { err = kResponseErr; goto exit; }
-require13:
-    require_noerr_quiet( 0, require14 );
-    goto require14Good;
-require14:
-    { err = kResponseErr; goto exit; }
-require14Good:
-    require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) );
-    { err = kResponseErr; goto exit; }
-require15:
-    require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) );
-    goto require16Good;
-require16:
-    { err = kResponseErr; goto exit; }
-require16Good:
-    require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) );
-    { err = kResponseErr; goto exit; }
-require17:
-    require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) );
-    goto require18Good;
-require18:
-    { err = kResponseErr; goto exit; }
-require18Good:
-    require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) );
-    { err = kResponseErr; goto exit; }
-require19:
-    require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) );
-    goto require20Good;
-require20:
-    { err = kResponseErr; goto exit; }
-require20Good:
-    require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) );
-    { err = kResponseErr; goto exit; }
-require21:
-    require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) );
-    goto require22Good;
-require22:
-    { err = kResponseErr; goto exit; }
-require22Good:
-    require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" );
-    { err = kResponseErr; goto exit; }
-require23:
-    require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" );
-    goto require24Good;
-require24:
-    { err = kResponseErr; goto exit; }
-require24Good:
-
-#if ( defined( __MWERKS__ )  )
-    #if ( defined( __cplusplus ) && __option( exceptions ) )
-        #define COMPILER_HAS_EXCEPTIONS     1
-    #else
-        #define COMPILER_HAS_EXCEPTIONS     0
-    #endif
-#else
-    #if ( defined( __cplusplus ) )
-        #define COMPILER_HAS_EXCEPTIONS     1
-    #else
-        #define COMPILER_HAS_EXCEPTIONS     0
-    #endif
-#endif
-
-#if ( COMPILER_HAS_EXCEPTIONS )
-    try
-    {
-        require_throw( 1 && "SHOULD *NOT* SEE" );
-        require_throw( 0 && "SHOULD SEE" );
-    }
-    catch(... )
-    {
-        goto require26Good;
-    }
-    { err = kResponseErr; goto exit; }
-require26Good:
-#endif
-
-    // translate_errno
-
-    err = translate_errno( 1 != -1, -123, -567 );
-    require( ( err == 0 ) && "SHOULD *NOT* SEE", exit );
-
-    err = translate_errno( -1 != -1, -123, -567 );
-    require( ( err == -123 ) && "SHOULD *NOT* SEE", exit );
-
-    err = translate_errno( -1 != -1, 0, -567 );
-    require( ( err == -567 ) && "SHOULD *NOT* SEE", exit );
-
-    // debug_string
-
-    debug_string( "debug_string" );
-
-    // DebugSNPrintF
-
-    DebugSNPrintF( s, sizeof( s ), "%d", 1234 );
-    require_action( strcmp( s, "1234" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%X", 0x2345 );
-    require_action( strcmp( s, "2345" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%#s", "\05test" );
-    require_action( strcmp( s, "test" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%##s", "\03www\05apple\03com" );
-    require_action( strcmp( s, "www.apple.com." ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%ld", (long) INT32_C( 2147483647 ) );
-    require_action( strcmp( s, "2147483647" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%lu", (unsigned long) UINT32_C( 4294967295 ) );
-    require_action( strcmp( s, "4294967295" ) == 0, exit, err = -1 );
-
-    #if ( TYPE_LONGLONG_NATIVE )
-    DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( 9223372036854775807 ) );
-    require_action( strcmp( s, "9223372036854775807" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( -9223372036854775807 ) );
-    require_action( strcmp( s, "-9223372036854775807" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%llu", (unsigned_long_long_compat) UINT64_C( 18446744073709551615 ) );
-    require_action( strcmp( s, "18446744073709551615" ) == 0, exit, err = -1 );
-    #endif
-
-    DebugSNPrintF( s, sizeof( s ), "%lb", (unsigned long) binary_32( 01111011, 01111011, 01111011, 01111011 ) );
-    require_action( strcmp( s, "1111011011110110111101101111011" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%C", 0x41624364 );  // 'AbCd'
-    require_action( strcmp( s, "AbCd" ) == 0, exit, err = -1 );
-
-    #if ( defined( MDNS_DEBUGMSGS ) )
-    {
-        mDNSAddr maddr;
-
-        memset( &maddr, 0, sizeof( maddr ) );
-        maddr.type = mDNSAddrType_IPv4;
-        maddr.ip.v4.b[ 0 ] = 127;
-        maddr.ip.v4.b[ 1 ] = 0;
-        maddr.ip.v4.b[ 2 ] = 0;
-        maddr.ip.v4.b[ 3 ] = 1;
-        DebugSNPrintF( s, sizeof( s ), "%#a", &maddr );
-        require_action( strcmp( s, "127.0.0.1" ) == 0, exit, err = -1 );
-
-        memset( &maddr, 0, sizeof( maddr ) );
-        maddr.type = mDNSAddrType_IPv6;
-        maddr.ip.v6.b[  0 ] = 0xFE;
-        maddr.ip.v6.b[  1 ] = 0x80;
-        maddr.ip.v6.b[ 15 ] = 0x01;
-        DebugSNPrintF( s, sizeof( s ), "%#a", &maddr );
-        require_action( strcmp( s, "FE80:0000:0000:0000:0000:0000:0000:0001" ) == 0, exit, err = -1 );
-    }
-    #endif
-
-    #if ( AF_INET )
-    {
-        struct sockaddr_in sa4;
-
-        memset( &sa4, 0, sizeof( sa4 ) );
-        sa4.sin_family      = AF_INET;
-        p                   = (uint8_t *) &sa4.sin_port;
-        p[ 0 ]              = (uint8_t)( ( 80 >> 8 ) & 0xFF );
-        p[ 1 ]              = (uint8_t)(   80        & 0xFF );
-        p                   = (uint8_t *) &sa4.sin_addr.s_addr;
-        p[ 0 ]              = (uint8_t)( ( INADDR_LOOPBACK >> 24 ) & 0xFF );
-        p[ 1 ]              = (uint8_t)( ( INADDR_LOOPBACK >> 16 ) & 0xFF );
-        p[ 2 ]              = (uint8_t)( ( INADDR_LOOPBACK >>  8 ) & 0xFF );
-        p[ 3 ]              = (uint8_t)(   INADDR_LOOPBACK         & 0xFF );
-        DebugSNPrintF( s, sizeof( s ), "%##a", &sa4 );
-        require_action( strcmp( s, "127.0.0.1:80" ) == 0, exit, err = -1 );
-    }
-    #endif
-
-    #if ( AF_INET6 )
-    {
-        struct sockaddr_in6 sa6;
-
-        memset( &sa6, 0, sizeof( sa6 ) );
-        sa6.sin6_family             = AF_INET6;
-        p                           = (uint8_t *) &sa6.sin6_port;
-        p[ 0 ]                      = (uint8_t)( ( 80 >> 8 ) & 0xFF );
-        p[ 1 ]                      = (uint8_t)(   80        & 0xFF );
-        sa6.sin6_addr.s6_addr[  0 ] = 0xFE;
-        sa6.sin6_addr.s6_addr[  1 ] = 0x80;
-        sa6.sin6_addr.s6_addr[ 15 ] = 0x01;
-        sa6.sin6_scope_id           = 2;
-        DebugSNPrintF( s, sizeof( s ), "%##a", &sa6 );
-        require_action( strcmp( s, "[FE80:0000:0000:0000:0000:0000:0000:0001%2]:80" ) == 0, exit, err = -1 );
-    }
-    #endif
-
-    // Unicode
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes" );
-    require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "test" );
-    require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "testing" );
-    require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9" );
-    require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9ing" );
-    require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes\xC3\xA9ing" );
-    require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbf" );
-    require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbfing" );
-    require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbf" );
-    require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbfing" );
-    require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 7, "te\xC3\xA9\xed\x9f\xbfing" );
-    require_action( strcmp( s, "te\xC3\xA9\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 6, "te\xC3\xA9\xed\x9f\xbfing" );
-    require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
-
-    DebugSNPrintF(s, sizeof(s), "%.*s", 5, "te\xC3\xA9\xed\x9f\xbfing" );
-    require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
-
-    #if ( TARGET_RT_BIG_ENDIAN )
-    DebugSNPrintF( s, sizeof( s ), "%S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" );
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-    #else
-    DebugSNPrintF( s, sizeof( s ), "%S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" );
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-    #endif
-
-    DebugSNPrintF( s, sizeof( s ), "%S",
-                   "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian BOM
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%S",
-                   "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian BOM
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%#S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" );  // Big Endian
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%##S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian
-    require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%.*S",
-                   4, "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian BOM
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%.*S",
-                   4, "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian BOM
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-
-    #if ( TARGET_RT_BIG_ENDIAN )
-    DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" );
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-    #else
-    DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" );
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-    #endif
-
-    DebugSNPrintF( s, sizeof( s ), "%#.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" );   // Big Endian
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%##.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" );  // Little Endian
-    require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
-
-    // Misc
-
-    DebugSNPrintF( s, sizeof( s ), "%U", "\x10\xb8\xa7\x6b" "\xad\x9d" "\xd1\x11" "\x80\xb4" "\x00\xc0\x4f\xd4\x30\xc8" );
-    require_action( strcmp( s, "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%m", 0 );
-    require_action( strcmp( s, "no error" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "%lm", (long) 0 );
-    require_action( strcmp( s, "no error" ) == 0, exit, err = -1 );
-
-    DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 16, 16 );
-    DebugPrintF( kDebugLevelMax, "%s\n\n", s );
-
-    DebugSNPrintF( s, sizeof( s ), "\"%H\"",
-                   "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
-                   "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8",
-                   32, 32 );
-    DebugPrintF( kDebugLevelMax, "%s\n\n", s );
-
-    DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7", 2, 2 );
-    DebugPrintF( kDebugLevelMax, "%s\n\n", s );
-
-    // Hex Dumps
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNone, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoAddress, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoOffset, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoAddress, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoOffset, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoByteCount, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, "\x41\x62\x43\x64", "\x41\x62\x43\x64", 4,    // 'AbCd'
-                  kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine |
-                  kDebugFlagsNo32BitSeparator | kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount,
-                  s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
-                  kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoASCII | kDebugFlagsNoNewLine |
-                  kDebugFlags16BitSeparator | kDebugFlagsNo32BitSeparator |
-                  kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    s[ 0 ] = '\0';
-    DebugHexDump( kDebugLevelMax, 8, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), kDebugFlagsNone, s, sizeof( s ) );
-    DebugPrintF( kDebugLevelMax, "%s\n", s );
-
-    // dlog's
-
-    dlog( kDebugLevelNotice, "dlog\n" );
-    dlog( kDebugLevelNotice, "dlog integer: %d\n", 123 );
-    dlog( kDebugLevelNotice, "dlog string:  \"%s\"\n", "test string" );
-    dlogmem( kDebugLevelNotice, data, sizeof( data ) );
-
-    // Done
-
-    DebugPrintF( kDebugLevelMax, "\n\nALL TESTS DONE\n\n" );
-    err = kNoErr;
-
-exit:
-    if( err )
-    {
-        DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" );
-    }
-    return( err );
-}
-
-#endif  // DEBUG
diff --git a/mDNSShared/DebugServices.h b/mDNSShared/DebugServices.h
deleted file mode 100644
index e567c83..0000000
--- a/mDNSShared/DebugServices.h
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004, 2020 Apple 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.
- */
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@header		DebugServices
-
-    Debugging Library
- */
-
-#ifndef __DEBUG_SERVICES__
-#define __DEBUG_SERVICES__
-
-#include    <stdarg.h>
-
-#include    "CommonServices.h"
-
-#if 0
-#pragma mark == Settings ==
-#endif
-
-//===========================================================================================================================
-//	Settings
-//===========================================================================================================================
-
-// General
-
-#if ( !defined( DEBUG ) )
-    #define DEBUG       0
-#endif
-
-#if ( defined( NDEBUG ) && DEBUG )
-    #error NDEBUG defined and DEBUG is also enabled...they need to be in-sync
-#endif
-
-// AssertMacros.h/Debugging.h overrides.
-
-#if ( !defined( DEBUG_OVERRIDE_APPLE_MACROS ) )
-    #define DEBUG_OVERRIDE_APPLE_MACROS     1
-#endif
-
-// Routine name. Uses ISO __func__ where possible. Otherwise, uses the best thing that is available (if anything).
-
-#if ( defined( __MWERKS__ ) || ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) )
-    #define __ROUTINE__                 __func__
-#elif ( defined( __GNUC__ ) )
-    #define __ROUTINE__                 __PRETTY_FUNCTION__
-#elif ( defined( _MSC_VER ) && !defined( _WIN32_WCE ) )
-    #define __ROUTINE__                 __FUNCTION__
-#else
-    #define __ROUTINE__                 ""
-#endif
-
-// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
-
-#if ( defined( __GNUC__ ) )
-    #if ( ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 3) ) )
-        #define DEBUG_C99_VA_ARGS       1
-        #define DEBUG_GNU_VA_ARGS       0
-    #else
-        #define DEBUG_C99_VA_ARGS       0
-        #define DEBUG_GNU_VA_ARGS       1
-    #endif
-#elif ( defined( __MWERKS__ ) )
-    #define DEBUG_C99_VA_ARGS           1
-    #define DEBUG_GNU_VA_ARGS           0
-#else
-    #define DEBUG_C99_VA_ARGS           0
-    #define DEBUG_GNU_VA_ARGS           0
-#endif
-
-#if 0
-#pragma mark == Output ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_FPRINTF_ENABLED
-
-    @abstract	Enables ANSI C fprintf output.
- */
-
-#if ( !defined( DEBUG_FPRINTF_ENABLED ) )
-    #if ( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE )
-        #define DEBUG_FPRINTF_ENABLED           1
-    #else
-        #define DEBUG_FPRINTF_ENABLED           0
-    #endif
-#else
-    #if ( TARGET_API_MAC_OSX_KERNEL || TARGET_OS_WINDOWS_CE )
-        #error fprintf enabled, but not supported on Mac OS X kernel or Windows CE
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_MAC_OS_X_IOLOG_ENABLED
-
-    @abstract	Enables IOLog (Mac OS X Kernel) output.
- */
-
-#if ( !defined( DEBUG_MAC_OS_X_IOLOG_ENABLED ) )
-    #define DEBUG_MAC_OS_X_IOLOG_ENABLED        TARGET_API_MAC_OSX_KERNEL
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_KPRINTF_ENABLED
-
-    @abstract	Enables kprintf (Mac OS X Kernel) output.
- */
-
-#if ( !defined( DEBUG_KPRINTF_ENABLED ) )
-    #define DEBUG_KPRINTF_ENABLED               TARGET_API_MAC_OSX_KERNEL
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_IDEBUG_ENABLED
-
-    @abstract	Enables iDebug (Mac OS X user and Kernel) output.
-
-    @discussion
-
-    For Mac OS X kernel development, iDebug is enabled by default because we can dynamically check for the presence
-    of iDebug via some exported IOKit symbols. Mac OS X app usage doesn't allow dynamic detection because it relies
-    on statically linking to the iDebugServices.cp file so for Mac OS X app usage, you have to manually enable iDebug.
- */
-
-#if ( !defined( DEBUG_IDEBUG_ENABLED ) )
-    #define DEBUG_IDEBUG_ENABLED                TARGET_API_MAC_OSX_KERNEL
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_CORE_SERVICE_ASSERTS_ENABLED
-
-    @abstract	Controls whether Core Services assert handling is enabled. Enabling requires CoreServices framework.
- */
-
-#if ( !defined( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) )
-    #if ( defined( __DEBUGGING__ ) )
-        #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED      1
-    #else
-        #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED      0
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugOutputType
-
-    @abstract	Type of debug output (i.e. where the output goes).
- */
-
-typedef uint32_t DebugOutputType;
-
-#define kDebugOutputTypeNone                0x6E6F6E65U // 'none' - no params
-#define kDebugOutputTypeCustom              0x63757374U // 'cust' - 1st param = function ptr, 2nd param = context
-#define kDebugOutputTypeFPrintF             0x66707269U // 'fpri' - 1st param = DebugOutputTypeFlags [, 2nd param = filename]
-#define kDebugOutputTypeiDebug              0x69646267U // 'idbg' - no params
-#define kDebugOutputTypeKPrintF             0x6B707266U // 'kprf' - no params
-#define kDebugOutputTypeMacOSXIOLog         0x696C6F67U // 'ilog' - no params
-#define kDebugOutputTypeMacOSXLog           0x786C6F67U // 'xlog' - no params
-#define kDebugOutputTypeWindowsDebugger     0x77696E64U // 'wind' - no params
-#define kDebugOutputTypeWindowsEventLog     0x7765766CU // 'wevl' - 1st param = C-string name, 2nd param = HMODULE or NULL.
-
-// Console meta output kind - Any kind of Console output (in horizontal order of preference):
-//
-// Mac OS X			= ANSI printf (viewable in Console.app)
-// Mac OS X Kernel	= IOLog (/var/log/system.log) or kprintf (serial).
-// Windows			= ANSI printf (Console window) or OutputDebugString (debugger).
-// Other			= ANSI printf (viewer varies).
-
-#define kDebugOutputTypeMetaConsole         0x434F4E53U // 'CONS' - no params
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugOutputTypeFlags
-
-    @abstract	Flags controlling how the output type is configured.
-
-    @constant	kDebugOutputTypeFlagsTypeMask	Bit mask for the output type (e.g. stdout, stderr, file, etc.).
-    @constant	kDebugOutputTypeFlagsStdOut		fprintf should go to stdout.
-    @constant	kDebugOutputTypeFlagsStdErr		fprintf should go to stderr.
-    @constant	kDebugOutputTypeFlagsFile		fprintf should go to a specific file (filename passed as va_arg).
- */
-
-typedef unsigned int DebugOutputTypeFlags;
-
-#define kDebugOutputTypeFlagsTypeMask   0xF
-#define kDebugOutputTypeFlagsStdOut     1
-#define kDebugOutputTypeFlagsStdErr     2
-#define kDebugOutputTypeFlagsFile       10
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugOutputFunctionPtr
-
-    @abstract	Function ptr for a custom callback to print debug output.
- */
-
-typedef void ( *DebugOutputFunctionPtr )( char *inData, size_t inSize, void *inContext );
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#if 0
-#pragma mark == Flags ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugFlags
-
-    @abstract	Flags controlling how output is printed.
- */
-
-typedef uint32_t DebugFlags;
-
-#define kDebugFlagsNone                 0
-#define kDebugFlagsNoAddress            ( 1 << 0 )
-#define kDebugFlagsNoOffset             ( 1 << 1 )
-#define kDebugFlags32BitOffset          ( 1 << 2 )
-#define kDebugFlagsNoASCII              ( 1 << 3 )
-#define kDebugFlagsNoNewLine            ( 1 << 4 )
-#define kDebugFlags8BitSeparator        ( 1 << 5 )
-#define kDebugFlags16BitSeparator       ( 1 << 6 )
-#define kDebugFlagsNo32BitSeparator     ( 1 << 7 )
-#define kDebugFlagsNo16ByteHexPad       ( 1 << 8 )
-#define kDebugFlagsNoByteCount          ( 1 << 9 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@enum		DebugTaskLevelFlags
-
-    @abstract	Flags indicating the task level.
- */
-
-enum
-{
-    kDebugInterruptLevelShift               = 0,
-    kDebugInterruptLevelMask                = 0x00000007,
-    kDebugInVBLTaskMask                     = 0x00000010,
-    kDebugInDeferredTaskMask                = 0x00000020,
-    kDebugInSecondaryInterruptHandlerMask   = 0x00000040,
-    kDebugPageFaultFatalMask                = 0x00000100,   // There should be a "kPageFaultFatalMask" in Debugging.h.
-    kDebugMPTaskLevelMask                   = 0x00000200,   // There should be a "kMPTaskLevelMask" in Debugging.h.
-    kDebugInterruptDepthShift               = 16,
-    kDebugInterruptDepthMask                = 0x00FF0000
-};
-
-#define DebugExtractTaskLevelInterruptLevel( LEVEL )    \
-    ( ( ( LEVEL ) &kDebugInterruptLevelMask ) >> kDebugInterruptLevelShift )
-
-#define DebugExtractTaskLevelInterruptDepth( LEVEL )    \
-    ( ( ( LEVEL ) &kDebugInterruptDepthMask ) >> kDebugInterruptDepthShift )
-
-#if 0
-#pragma mark == Levels ==
-#endif
-
-//===========================================================================================================================
-//	Constants & Types - Levels
-//===========================================================================================================================
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugLevel
-
-    @abstract	Level used to control debug logging.
- */
-
-typedef int32_t DebugLevel;
-
-// Levels
-
-#define kDebugLevelMask                 0x0000FFFF
-#define kDebugLevelChatty               100
-#define kDebugLevelVerbose              500
-#define kDebugLevelTrace                800
-#define kDebugLevelInfo                 1000
-#define kDebugLevelNotice               3000
-#define kDebugLevelWarning              5000
-#define kDebugLevelAssert               6000
-#define kDebugLevelRequire              7000
-#define kDebugLevelError                8000
-#define kDebugLevelCritical             9000
-#define kDebugLevelAlert                10000
-#define kDebugLevelEmergency            11000
-#define kDebugLevelTragic               12000
-#define kDebugLevelMax                  0x0000FFFF
-
-// Level Flags
-
-#define kDebugLevelFlagMask             0xFFFF0000
-#define kDebugLevelFlagStackTrace       0x00010000
-#define kDebugLevelFlagDebugBreak       0x00020000
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	LogLevel
-
-    @abstract	Level used to control which events are logged.
- */
-
-typedef int32_t LogLevel;
-
-#define kLogLevelUninitialized      -1L
-#define kLogLevelAll                0L
-#define kLogLevelChatty             100L
-#define kLogLevelVerbose            500L
-#define kLogLevelTrace              800L
-#define kLogLevelInfo               1000L
-#define kLogLevelNotice             3000L
-#define kLogLevelWarning            4000L
-#define kLogLevelAssert             6000L
-#define kLogLevelRequire            7000L
-#define kLogLevelError              8000L
-#define kLogLevelCritical           9000L
-#define kLogLevelAlert              10000L
-#define kLogLevelEmergency          11000L
-#define kLogLevelTragic             12000L
-#define kLogLevelOff                0x0000FFFEL
-
-#if 0
-#pragma mark == Properties ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	DebugPropertyTag
-
-    @abstract	Tag for properties.
- */
-
-typedef uint32_t DebugPropertyTag;
-
-#define kDebugPropertyTagPrintLevelMin      0x6D696E70U     // 'minp'	Get: 1st param = DebugLevel *
-                                                            //			Set: 1st param = DebugLevel
-
-#define kDebugPropertyTagPrintLevel         kDebugPropertyTagPrintLevelMin
-
-#define kDebugPropertyTagPrintLevelMax      0x706D786CU     // 'maxp'	Get: 1st param = DebugLevel *
-                                                            //			Set: 1st param = DebugLevel
-
-#define kDebugPropertyTagBreakLevel         0x62726B6CU     // 'brkl'	Get: 1st param = DebugLevel *
-                                                            //			Set: 1st param = DebugLevel
-#if 0
-#pragma mark == General macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_UNUSED
-
-    @abstract	Macro to mark a paramter as unused to avoid unused parameter warnings.
-
-    @discussion
-
-    There is no universally supported pragma/attribute for indicating a variable is unused. DEBUG_UNUSED lets us
-    indicate a variable is unused in a manner that is supported by most compilers.
- */
-
-#define DEBUG_UNUSED( X )           (void)( X )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_USE_ONLY
-
-    @abstract	Macro to mark a variable as used only when debugging is enabled.
-
-    @discussion
-
-    Variables are sometimes needed only for debugging. When debugging is turned off, these debug-only variables generate
-    compiler warnings about unused variables. To eliminate these warnings, use these macros to indicate variables that
-    are only used for debugging.
- */
-
-#if ( DEBUG )
-    #define DEBUG_USE_ONLY( X )
-#else
-    #define DEBUG_USE_ONLY( X )     (void)( X )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_LOCAL
-
-    @abstract	Macros to make variables and functions static when debugging is off, but extern when debugging is on.
-
-    @discussion
-
-    Rather than using "static" directly, using this macros allows you to access these variables external while
-    debugging without being penalized for production builds.
- */
-
-#if ( DEBUG )
-    #define DEBUG_LOCAL
-#else
-    #define DEBUG_LOCAL         static
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_STATIC
-
-    @abstract	Macros to make variables and functions static when debugging is off, but extern when debugging is on.
-
-    @discussion
-
-    Rather than using "static" directly, using this macros allows you to access these variables external while
-    debugging without being penalized for production builds.
- */
-
-#if ( DEBUG )
-    #define DEBUG_STATIC
-#else
-    #define DEBUG_STATIC    static
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DEBUG_EXPORT
-
-    @abstract	Macros to export variables.
-
-    @discussion
-
-    "__private_extern__" is a hack for IOKit to allow symbols to be exported from compilation units, but
-    // not exported outside a driver (IOKit uses a lame global namespace for symbols). This still does not
-    // solve the problem of multiple drivers in the same dependency chain since they share symbols.
- */
-
-#if ( TARGET_API_MAC_OSX_KERNEL )
-    #define DEBUG_EXPORT        __private_extern__
-#else
-    #define DEBUG_EXPORT        extern
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	debug_add
-
-    @abstract	Macro to add (or subtract if negative) a value when debugging is on. Does nothing if debugging is off.
- */
-
-#if ( DEBUG )
-    #define debug_add( A, B )       ( A ) += ( B )
-#else
-    #define debug_add( A, B )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	debug_perform
-
-    @abstract	Macro to perform something in debug-only builds.
- */
-
-#if ( DEBUG )
-    #define debug_perform( X )      do { X; } while( 0 )
-#else
-    #define debug_perform( X )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	translate_errno
-
-    @abstract	Returns 0 if the test success. If the test fails, returns errno if non-zero and othewise the alternate error.
- */
-
-#define translate_errno( TEST, ERRNO, ALTERNATE_ERROR )     ( ( TEST ) ? 0 : ( ERRNO ) ? ( ERRNO ) : ( ALTERNATE_ERROR ) )
-
-#if 0
-#pragma mark == Compile Time macros ==
-#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 allow a zero-length array. Using a -1 condition turned out to be more portable.
- */
-
-#ifndef check_compile_time
-    #define check_compile_time( X )     extern int debug_compile_time_name[ ( X ) ? 1 : -1 ]
-#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>
- */
-
-#ifndef check_compile_time_code
-    #define check_compile_time_code( X )    switch( 0 ) { case 0: case X:; }
-#endif
-
-#if 0
-#pragma mark == check macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check
-
-    @abstract	Check that an expression is true (non-zero).
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method.
-
-    Code inside check() statements is not compiled into production builds.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef check
-#endif
-#if ( !defined( check ) )
-    #if ( DEBUG )
-        #define check( X )                                                                                  \
-    do                                                                                              \
-    {                                                                                               \
-        if( !( X ) )                                                                                \
-        {                                                                                           \
-            debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ );                     \
-        }                                                                                           \
-    } while( 0 )
-    #else
-        #define check( X )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_string
-
-    @abstract	Check that an expression is true (non-zero) with an explanation.
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) and a custom explanation string using the default debugging output method.
-
-    Code inside check_string() statements is not compiled into production builds.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef check_string
-#endif
-#if ( !defined( check_string ) )
-    #if ( DEBUG )
-        #define check_string( X, STR )                                                                      \
-    do                                                                                              \
-    {                                                                                               \
-        if( !( X ) )                                                                                \
-        {                                                                                           \
-            debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ );                      \
-        }                                                                                           \
-                                                                                                            \
-    }   while( 0 )
-    #else
-        #define check_string( X, STR )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_noerr
-
-    @abstract	Check that an error code is noErr (0).
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method.
-
-    Code inside check_noerr() statements is not compiled into production builds.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef check_noerr
-#endif
-#if ( !defined( check_noerr ) )
-    #if ( DEBUG )
-        #define check_noerr( ERR )                                                                          \
-    do                                                                                              \
-    {                                                                                               \
-        int_least32_t localErr;                                                               \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                          \
-        if( localErr != 0 )                                                                         \
-        {                                                                                           \
-            debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ );            \
-        }                                                                                           \
-                                                                                                            \
-    }   while( 0 )
-    #else
-        #define check_noerr( ERR )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_noerr_string
-
-    @abstract	Check that an error code is noErr (0) with an explanation.
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) and a custom explanation string using the default debugging output method.
-
-    Code inside check_noerr_string() statements is not compiled into production builds.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef check_noerr_string
-#endif
-#if ( !defined( check_noerr_string ) )
-    #if ( DEBUG )
-        #define check_noerr_string( ERR, STR )                                                              \
-    do                                                                                              \
-    {                                                                                               \
-        int_least32_t localErr;                                                               \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                          \
-        if( localErr != 0 )                                                                         \
-        {                                                                                           \
-            debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ );             \
-        }                                                                                           \
-                                                                                                            \
-    }   while( 0 )
-    #else
-        #define check_noerr_string( ERR, STR )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_translated_errno
-
-    @abstract	Check a condition and prints errno (if non-zero) to the log.
-
-    @discussion
-
-    Code inside check_translated_errno() statements is not compiled into production builds.
- */
-
-#if ( !defined( check_translated_errno ) )
-    #if ( DEBUG )
-        #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR )                                      \
-    do                                                                                              \
-    {                                                                                               \
-        if( !( TEST ) )                                                                             \
-        {                                                                                           \
-            int_least32_t localErr;                                                           \
-                                                                                                            \
-            localErr = (int_least32_t)( ERRNO );                                                    \
-            localErr = ( localErr != 0 ) ? localErr : (int_least32_t)( ALTERNATE_ERROR );           \
-            debug_print_assert( localErr, # TEST, NULL, __FILE__, __LINE__, __ROUTINE__ );           \
-        }                                                                                           \
-                                                                                                            \
-    }   while( 0 )
-    #else
-        #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_ptr_overlap
-
-    @abstract	Checks that two ptrs do not overlap.
- */
-
-#define check_ptr_overlap( P1, P1_SIZE, P2, P2_SIZE )                                       \
-    do                                                                                      \
-    {                                                                                       \
-        check( !( ( (uintptr_t)( P1 ) >=     (uintptr_t)( P2 ) ) &&                         \
-                  ( (uintptr_t)( P1 ) <  ( ( (uintptr_t)( P2 ) ) + ( P2_SIZE ) ) ) ) );     \
-        check( !( ( (uintptr_t)( P2 ) >=     (uintptr_t)( P1 ) ) &&                         \
-                  ( (uintptr_t)( P2 ) <  ( ( (uintptr_t)( P1 ) ) + ( P1_SIZE ) ) ) ) );     \
-                                                                                            \
-    }   while( 0 )
-
-#if 0
-#pragma mark == require macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require
-
-    @abstract	Requires that an expression evaluate to true.
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method then jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require
-#endif
-#if ( !defined( require ) )
-    #define require( X, LABEL )                                                                             \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ );                         \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_string
-
-    @abstract	Requires that an expression evaluate to true with an explanation.
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_string
-#endif
-#if ( !defined( require_string ) )
-    #define require_string( X, LABEL, STR )                                                                 \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ );                          \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_quiet
-
-    @abstract	Requires that an expression evaluate to true.
-
-    @discussion
-
-    If expression evalulates to false, this jumps to a label. No debugging information is printed.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_quiet
-#endif
-#if ( !defined( require_quiet ) )
-    #define require_quiet( X, LABEL )                                                                       \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr
-
-    @abstract	Require that an error code is noErr (0).
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method then jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr
-#endif
-#if ( !defined( require_noerr ) )
-    #define require_noerr( ERR, LABEL )                                                                     \
-    do                                                                                                  \
-    {                                                                                                   \
-        int_least32_t localErr;                                                                   \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                              \
-        if( localErr != 0 )                                                                             \
-        {                                                                                               \
-            debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ );                \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr_string
-
-    @abstract	Require that an error code is noErr (0).
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.), and a custom explanation string using the default debugging output method using the
-    default debugging output method then jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr_string
-#endif
-#if ( !defined( require_noerr_string ) )
-    #define require_noerr_string( ERR, LABEL, STR )                                                         \
-    do                                                                                                  \
-    {                                                                                                   \
-        int_least32_t localErr;                                                                   \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                              \
-        if( localErr != 0 )                                                                             \
-        {                                                                                               \
-            debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ );                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr_action_string
-
-    @abstract	Require that an error code is noErr (0).
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.), and a custom explanation string using the default debugging output method using the
-    default debugging output method then executes an action and jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr_action_string
-#endif
-#if ( !defined( require_noerr_action_string ) )
-    #define require_noerr_action_string( ERR, LABEL, ACTION, STR )                                          \
-    do                                                                                                  \
-    {                                                                                                   \
-        int_least32_t localErr;                                                                   \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                              \
-        if( localErr != 0 )                                                                             \
-        {                                                                                               \
-            debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ );                 \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr_quiet
-
-    @abstract	Require that an error code is noErr (0).
-
-    @discussion
-
-    If the error code is non-0, this jumps to a label. No debugging information is printed.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr_quiet
-#endif
-#if ( !defined( require_noerr_quiet ) )
-    #define require_noerr_quiet( ERR, LABEL )                                                               \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( ( ERR ) != 0 )                                                                              \
-        {                                                                                               \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr_action
-
-    @abstract	Require that an error code is noErr (0) with an action to execute otherwise.
-
-    @discussion
-
-    If the error code is non-0, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method then executes an action and jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr_action
-#endif
-#if ( !defined( require_noerr_action ) )
-    #define require_noerr_action( ERR, LABEL, ACTION )                                                      \
-    do                                                                                                  \
-    {                                                                                                   \
-        int_least32_t localErr;                                                                   \
-                                                                                                            \
-        localErr = (int_least32_t)( ERR );                                                              \
-        if( localErr != 0 )                                                                             \
-        {                                                                                               \
-            debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ );                \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_noerr_action_quiet
-
-    @abstract	Require that an error code is noErr (0) with an action to execute otherwise.
-
-    @discussion
-
-    If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_noerr_action_quiet
-#endif
-#if ( !defined( require_noerr_action_quiet ) )
-    #define require_noerr_action_quiet( ERR, LABEL, ACTION )                                                \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( ( ERR ) != 0 )                                                                              \
-        {                                                                                               \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_action
-
-    @abstract	Requires that an expression evaluate to true with an action to execute otherwise.
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) using the default debugging output method then executes an action and jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_action
-#endif
-#if ( !defined( require_action ) )
-    #define require_action( X, LABEL, ACTION )                                                              \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ );                         \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_action_quiet
-
-    @abstract	Requires that an expression evaluate to true with an action to execute otherwise.
-
-    @discussion
-
-    If expression evalulates to false, this executes an action and jumps to a label. No debugging information is printed.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_action_quiet
-#endif
-#if ( !defined( require_action_quiet ) )
-    #define require_action_quiet( X, LABEL, ACTION )                                                        \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_action_string
-
-    @abstract	Requires that an expression evaluate to true with an explanation and action to execute otherwise.
-
-    @discussion
-
-    If expression evalulates to false, this prints debugging information (actual expression string, file, line number,
-    function name, etc.) and a custom explanation string using the default debugging output method then executes an
-    action and jumps to a label.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef require_action_string
-#endif
-#if ( !defined( require_action_string ) )
-    #define require_action_string( X, LABEL, ACTION, STR )                                                  \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ );                      \
-            { ACTION; }                                                                                 \
-            goto LABEL;                                                                                 \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	require_throw
-
-    @abstract	Requires that an expression evaluates to true or an exception is thrown.
-
-    @discussion
-
-    If the expression evaluates to false, this prints debugging information (actual expression string, file,
-    line number, function name, etc.) using the default debugging output method then throws an exception.
- */
-
-#if ( defined( __cplusplus ) )
-    #define require_throw( X )                                                                              \
-    do                                                                                                  \
-    {                                                                                                   \
-        if( !( X ) )                                                                                    \
-        {                                                                                               \
-            debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ );                         \
-            throw kUnknownErr;                                                                          \
-        }                                                                                               \
-                                                                                                            \
-    }   while( 0 )
-#endif
-
-#if 0
-#pragma mark == Design-By-Contract macros ==
-#endif
-
-//===========================================================================================================================
-//	Design-By-Contract macros
-//===========================================================================================================================
-
-#define ensure( X )                                                 check( X )
-#define ensure_string( X, STR )                                     check_string( X, STR )
-#define ensure_noerr( ERR )                                         check_noerr( ERR )
-#define ensure_noerr_string( ERR, STR )                             check_noerr_string( ERR, STR )
-#define ensure_translated_errno( TEST, ERRNO, ALTERNATE_ERROR )     check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR )
-
-// Note: Design-By-Contract "require" macros are already defined elsewhere.
-
-#if 0
-#pragma mark == Expect macros ==
-#endif
-
-//===========================================================================================================================
-//	Expect macros
-//===========================================================================================================================
-
-// Expect macros allow code to include runtime checking of things that should not happen in shipping code (e.g. internal
-// programmer errors, such as a NULL parameter where it is not allowed). Once the code has been verified to work correctly
-// without asserting, the DEBUG_EXPECT_VERIFIED conditional can be set to eliminate the error checking entirely. It can
-// also be useful to measure the cost of error checking code by profiling with it enable and with it disabled.
-
-#if ( defined(DEBUG_EXPECT_VERIFIED) && DEBUG_EXPECT_VERIFIED )
-    #define require_expect
-    #define require_string_expect
-    #define require_quiet_expect
-    #define require_noerr_expect
-    #define require_noerr_string_expect
-    #define require_noerr_action_string_expect
-    #define require_noerr_quiet_expect
-    #define require_noerr_action_expect
-    #define require_noerr_action_quiet_expect
-    #define require_action_expect
-    #define require_action_quiet_expect
-    #define require_action_string_expect
-#else
-    #define require_expect                          require
-    #define require_string_expect                   require_string
-    #define require_quiet_expect                    require_quiet
-    #define require_noerr_expect                    require_noerr
-    #define require_noerr_string_expect             require_noerr_string
-    #define require_noerr_action_string_expect      require_noerr_action_string
-    #define require_noerr_quiet_expect              require_noerr_quiet
-    #define require_noerr_action_expect             require_noerr_action
-    #define require_noerr_action_quiet_expect       require_noerr_action_quiet
-    #define require_action_expect                   require_action
-    #define require_action_quiet_expect             require_action_quiet
-    #define require_action_string_expect            require_action_string
-#endif
-
-#if 0
-#pragma mark == Output macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	debug_string
-
-    @abstract	Prints a debugging C string.
- */
-
-#if ( DEBUG_OVERRIDE_APPLE_MACROS )
-    #undef debug_string
-#endif
-#if ( !defined( debug_string ) )
-    #if ( DEBUG )
-        #define debug_string( STR )                                                                     \
-    do                                                                                          \
-    {                                                                                           \
-        debug_print_assert( 0, NULL, STR, __FILE__, __LINE__, __ROUTINE__ );                    \
-                                                                                                        \
-    }   while( 0 )
-    #else
-        #define debug_string( STR )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	debug_print_assert
-
-    @abstract	Prints an assertion.
- */
-
-#if ( DEBUG )
-    #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION )   \
-    DebugPrintAssert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION )
-#else
-    #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	dlog
-
-    @abstract	Prints a debug-only message.
- */
-
-#if ( DEBUG )
-    #if ( DEBUG_C99_VA_ARGS )
-        #define dlog(... )         DebugPrintF( __VA_ARGS__ )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define dlog( ARGS... )     DebugPrintF( ## ARGS )
-    #else
-        #define dlog                DebugPrintF
-    #endif
-#else
-    #if ( DEBUG_C99_VA_ARGS )
-        #define dlog(... )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define dlog( ARGS... )
-    #else
-        #define dlog                while( 0 )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	dlogv
-
-    @abstract	Prints a debug-only message.
- */
-
-#if ( DEBUG )
-    #define dlogv( LEVEL, FORMAT, LIST )        DebugPrintFVAList( ( LEVEL ), ( FORMAT ), ( LIST ) )
-#else
-    #define dlogv( LEVEL, FORMAT, LIST )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	dlogmem
-
-    @abstract	Prints a debug-only dump of memory.
- */
-
-#if ( DEBUG )
-    #define dlogmem( LEVEL, PTR, SIZE )     \
-    DebugHexDump( ( LEVEL ), 0, NULL, 0, 0, NULL, 0, ( PTR ), ( PTR ), ( SIZE ), kDebugFlagsNone, NULL, 0 )
-#else
-    #define dlogmem( LEVEL, PTR, SIZE )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	DebugNSLog
-
-    @abstract	Debug-only macro for the Cocoa NSLog function.
- */
-
-#if ( DEBUG )
-    #if ( DEBUG_C99_VA_ARGS )
-        #define DebugNSLog(... )           NSLog( __VA_ARGS__ )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define DebugNSLog( ARGS... )       NSLog( ## ARGS )
-    #else
-        #define DebugNSLog                  NSLog
-    #endif
-#else
-    #if ( DEBUG_C99_VA_ARGS )
-        #define DebugNSLog(... )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define DebugNSLog( ARGS... )
-    #else
-        #define DebugNSLog                  while( 0 )
-    #endif
-#endif
-
-#if 0
-#pragma mark == Routines - General ==
-#endif
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugInitialize
-
-    @abstract	Initializes the debugging library for a specific kind of output.
-
-    @param		inType
-    @param		varArg		Variable number parameters, controlled by the "inType" parameter.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT OSStatus   DebugInitialize( DebugOutputType inType, ... );
-#endif
-
-#if ( DEBUG )
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_initialize(... )         DebugInitialize( __VA_ARGS__ )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_initialize( ARGS... )     DebugInitialize( ## ARGS )
-    #else
-        #define debug_initialize                DebugInitialize
-    #endif
-#else
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_initialize(... )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_initialize( ARGS... )
-    #else
-        #define debug_initialize                while( 0 )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugFinalize
-
-    @abstract	Releases any resources used by the debugging library
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT void       DebugFinalize( void );
-#endif
-
-#if ( DEBUG )
-    #define debug_terminate()   DebugFinalize()
-#else
-    #define debug_terminate()
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugGetProperty
-
-    @abstract	Gets the specified property from the debugging library.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT OSStatus   DebugGetProperty( DebugPropertyTag inTag, ... );
-#endif
-
-#if ( DEBUG )
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_get_property(... )           DebugGetProperty( __VA_ARGS__ )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_get_property( ARGS... )       DebugGetProperty( ## ARGS )
-    #else
-        #define debug_get_property                  DebugGetProperty
-    #endif
-#else
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_get_property(... )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_get_property( ARGS... )
-    #else
-        #define debug_get_property                  while( 0 )
-    #endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugSetProperty
-
-    @abstract	Sets the specified property from the debugging library.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT OSStatus   DebugSetProperty( DebugPropertyTag inTag, ... );
-#endif
-
-#if ( DEBUG )
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_set_property(... )           DebugSetProperty( __VA_ARGS__ )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_set_property( ARGS... )       DebugSetProperty( ## ARGS )
-    #else
-        #define debug_set_property                  DebugSetProperty
-    #endif
-#else
-    #if ( DEBUG_C99_VA_ARGS )
-        #define debug_set_property(... )
-    #elif ( DEBUG_GNU_VA_ARGS )
-        #define debug_set_property( ARGS... )
-    #else
-        #define debug_set_property                  while( 0 )
-    #endif
-#endif
-
-#if 0
-#pragma mark == Routines - Debugging Output ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugPrintF
-
-    @abstract	Prints a debug message with printf-style formatting.
-
-    @param		inLevel	Error that generated this assert or noErr.
-
-    @param		inFormatString
-                    C string containing assertion text.
-
-    @param		VAR_ARG
-                    Variable number of arguments depending on the format string.
-
-    @result		Number of bytes printed or -1 on error.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT size_t     DebugPrintF( DebugLevel inLevel, const char *inFormat, ... );
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugPrintFVAList
-
-    @abstract	va_list version of DebugPrintF. See DebugPrintF for more info.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT size_t     DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs );
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugPrintAssert
-
-    @abstract	Prints a message describing the reason the (e.g. an assert failed), an optional error message,
-                an optional source filename, an optional source line number.
-
-    @param		inErrorCode			Error that generated this assert or noErr.
-    @param		inAssertString		C string containing assertion text.
-    @param		inMessage			C string containing a message about the assert.
-    @param		inFileName			C string containing path of file where the error occurred.
-    @param		inLineNumber		Line number in source file where the error occurred.
-    @param		inFunction			C string containing name of function where assert occurred.
-
-    @discussion
-
-    Example output:
-
-    [ASSERT] assert: "dataPtr != NULL" allocate memory for object failed
-    [ASSERT] where:  "MyFile.c", line 123, ("MyFunction")
-
-    OR
-
-    [ASSERT] error:  -6728 (kNoMemoryErr)
-    [ASSERT] where:  "MyFile.c", line 123, ("MyFunction")
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT void
-DebugPrintAssert(
-    int_least32_t inErrorCode,
-    const char *    inAssertString,
-    const char *    inMessage,
-    const char *    inFilename,
-    int_least32_t inLineNumber,
-    const char *    inFunction );
-#endif
-
-#if 0
-#pragma mark == Routines - Utilities ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugSNPrintF
-
-    @abstract	Debugging versions of standard C snprintf with extra features.
-
-    @param		sbuffer		Buffer to receive result. Null terminated unless the buffer size is 0.
-    @param		buflen		Size of the buffer including space for the null terminator.
-    @param		fmt			printf-style format string.
-    @param		VAR_ARG		Variable number of arguments depending on the format string.
-
-    @result		Number of characters written (minus the null terminator).
-
-    @discussion
-
-    Extra features over the standard C snprintf:
-    <pre>
-        64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb).
-        %@   - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription.
-        %a   - Network Address: %.4a=IPv4, %.6a=Ethernet, %.8a Fibre Channel, %.16a=IPv6. Arg=ptr to network address.
-        %#a  - IPv4 or IPv6 mDNSAddr. Arg=ptr to mDNSAddr.
-        %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr.
-        %b   - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc.
-        %C   - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode.
-        %H   - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-        %#H  - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-        %m   - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code arg=the same as %d, %x, etc.
-        %#s  - Pascal-style length-prefixed string. Arg=ptr to string.
-        %##s - DNS label-sequence name. Arg=ptr to name.
-        %S   - UTF-16 string, 0x0000 terminated. Host order if no BOM. Precision is UTF-16 count. Precision includes BOM.
-        %#S  - Big Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
-        %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
-        %U   - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID.
-    </pre>
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...);
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugSNPrintFVAList
-
-    @abstract	va_list version of DebugSNPrintF. See DebugSNPrintF for more info.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg);
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugGetErrorString
-
-    @abstract	Gets an error string from an error code.
-
-    @param		inStatus		Error code to get the string for.
-    @param		inBuffer		Optional buffer to copy the string to for non-static strings. May be null.
-    @param		inBufferSize	Size of optional buffer. May be 0.
-
-    @result		C string containing error string for the error code. Guaranteed to be a valid, static string. If a
-                buffer is supplied, the return value will always be a pointer to the supplied buffer, which will
-                contain the best available description of the error code. If a buffer is not supplied, the return
-                value will be the best available description of the error code that can be represented as a static
-                string. This allows code that cannot use a temporary buffer to hold the result to still get a useful
-                error string in most cases, but also allows code that can use a temporary buffer to get the best
-                available description.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT const char *   DebugGetErrorString( long inErrorCode, char *inBuffer, size_t inBufferSize );
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugHexDump
-
-    @abstract	Hex dumps data to a string or to the output device.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT size_t
-DebugHexDump(
-    DebugLevel inLevel,
-    int inIndent,
-    const char *    inLabel,
-    size_t inLabelSize,
-    int inLabelMinWidth,
-    const char *    inType,
-    size_t inTypeSize,
-    const void *    inDataStart,
-    const void *    inData,
-    size_t inDataSize,
-    DebugFlags inFlags,
-    char *          outBuffer,
-    size_t inBufferSize );
-#endif
-
-#if ( DEBUG )
-    #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE )   \
-    DebugHexDump( ( LEVEL ), (INDENT), ( LABEL ), ( LABEL_SIZE ), ( LABEL_MIN_SIZE ), ( TYPE ), ( TYPE_SIZE ),                              \
-                  ( DATA_START ), ( DATA ), ( DATA_SIZE ), ( FLAGS ), ( BUFFER ), ( BUFFER_SIZE ) )
-#else
-    #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugTaskLevel
-
-    @abstract	Returns the current task level.
-
-    @result		Current task level
-
-    @discussion
-
-    Bit masks to isolate portions of the result (note that some masks may also need bit shifts to right justify):
-    <pre>
-        kDebugInterruptLevelMask				- Indicates the current interrupt level (> 0 means interrupt time).
-        kDebugInVBLTaskMask						- Indicates if a VBL task is currently being executed.
-        kDebugInDeferredTaskMask				- Indicates if a Deferred Task is currently being executed.
-        kDebugInSecondaryInterruptHandlerMask	- Indicates if a Secondary Interrupt Handler is currently being executed.
-        kDebugPageFaultFatalMask				- Indicates if it is unsafe to cause a page fault (worse than interrupt time).
-        kDebugMPTaskLevelMask					- Indicates if being called from an MP task.
-        kDebugInterruptDepthMask				- 0 means task level, 1 means in interrupt, > 1 means in nested interrupt.
-    </pre>
-
-    Helpers:
-    <pre>
-        DebugExtractTaskLevelInterruptDepth()   - Macro to extract interrupt depth from task level value.
-    </pre>
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT uint32_t   DebugTaskLevel( void );
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DebugServicesTest
-
-    @abstract	Unit test.
- */
-
-#if ( DEBUG )
-DEBUG_EXPORT OSStatus   DebugServicesTest( void );
-#endif
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif  // __DEBUG_SERVICES__
diff --git a/mDNSShared/GenLinkedList.c b/mDNSShared/GenLinkedList.c
deleted file mode 100644
index 2135c6a..0000000
--- a/mDNSShared/GenLinkedList.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2003-2019 Apple 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.
- */
-
-#include "GenLinkedList.h"
-
-
-// Return the link pointer contained within element e at offset o.
-#define     GETLINK( e, o)          ( *(void**)((char*) (e) + (o)) )
-
-// Assign the link pointer l to element e at offset o.
-#define     ASSIGNLINK( e, l, o)    ( *((void**)((char*) (e) + (o))) = (l))
-
-
-//		GenLinkedList		/////////////////////////////////////////////////////////////
-
-void        InitLinkedList( GenLinkedList *pList, size_t linkOffset)
-/* Initialize the block of memory pointed to by pList as a linked list. */
-{
-    pList->Head = NULL;
-    pList->Tail = NULL;
-    pList->LinkOffset = linkOffset;
-}
-
-
-void        AddToTail( GenLinkedList *pList, void *elem)
-/* Add a linked list element to the tail of the list. */
-{
-    if ( pList->Tail) {
-        ASSIGNLINK( pList->Tail, elem, pList->LinkOffset);
-    } else
-        pList->Head = elem;
-    ASSIGNLINK( elem, NULL, pList->LinkOffset);
-
-    pList->Tail = elem;
-}
-
-
-void        AddToHead( GenLinkedList *pList, void *elem)
-/* Add a linked list element to the head of the list. */
-{
-    ASSIGNLINK( elem, pList->Head, pList->LinkOffset);
-    if ( pList->Tail == NULL)
-        pList->Tail = elem;
-
-    pList->Head = elem;
-}
-
-
-int     RemoveFromList( GenLinkedList *pList, void *elem)
-/* Remove a linked list element from the list. Return 0 if it was not found. */
-/* If the element is removed, its link will be set to NULL. */
-{
-    void    *iElem, *lastElem;
-
-    for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset)) {
-        if ( iElem == elem) {
-            if ( lastElem) {        // somewhere past the head
-                ASSIGNLINK( lastElem, GETLINK( elem, pList->LinkOffset), pList->LinkOffset);
-            } else {                // at the head
-                pList->Head = GETLINK( elem, pList->LinkOffset);
-            }
-            if ( pList->Tail == elem)
-                pList->Tail = lastElem ? lastElem : NULL;
-            ASSIGNLINK( elem, NULL, pList->LinkOffset);         // maybe catch a stale reference bug.
-            return 1;
-        }
-        lastElem = iElem;
-    }
-
-    return 0;
-}
-
-
-int         ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem)
-/* Replace an element in the list with a new element, in the same position. */
-{
-    void    *iElem, *lastElem;
-
-    if ( elemInList == NULL || newElem == NULL)
-        return 0;
-
-    for ( iElem = pList->Head, lastElem = NULL; iElem; iElem = GETLINK( iElem, pList->LinkOffset))
-    {
-        if ( iElem == elemInList)
-        {
-            ASSIGNLINK( newElem, GETLINK( elemInList, pList->LinkOffset), pList->LinkOffset);
-            if ( lastElem)      // somewhere past the head
-            {
-                ASSIGNLINK( lastElem, newElem, pList->LinkOffset);
-            }
-            else                // at the head
-            {
-                pList->Head = newElem;
-            }
-            if ( pList->Tail == elemInList)
-                pList->Tail = newElem;
-            return 1;
-        }
-        lastElem = iElem;
-    }
-
-    return 0;
-}
-
-
-//		GenDoubleLinkedList		/////////////////////////////////////////////////////////
-
-void        InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
-                                  size_t backLinkOffset)
-/* Initialize the block of memory pointed to by pList as a double linked list. */
-{
-    pList->Head = NULL;
-    pList->Tail = NULL;
-    pList->FwdLinkOffset = fwdLinkOffset;
-    pList->BackLinkOffset = backLinkOffset;
-}
-
-
-void            DLLAddToHead( GenDoubleLinkedList *pList, void *elem)
-/* Add a linked list element to the head of the list. */
-{
-    void        *pNext;
-
-    pNext = pList->Head;
-
-    // fix up the forward links
-    ASSIGNLINK( elem, pList->Head, pList->FwdLinkOffset);
-    pList->Head = elem;
-
-    // fix up the backward links
-    if ( pNext) {
-        ASSIGNLINK( pNext, elem, pList->BackLinkOffset);
-    } else
-        pList->Tail = elem;
-    ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
-}
-
-
-void            DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem)
-/* Remove a linked list element from the list. */
-/* When the element is removed, its link will be set to NULL. */
-{
-    void        *pNext, *pPrev;
-
-    pNext = GETLINK( elem, pList->FwdLinkOffset);
-    pPrev = GETLINK( elem, pList->BackLinkOffset);
-
-    // fix up the forward links
-    if ( pPrev)
-        ASSIGNLINK( pPrev, pNext, pList->FwdLinkOffset);
-    else
-        pList->Head = pNext;
-
-    // fix up the backward links
-    if ( pNext)
-        ASSIGNLINK( pNext, pPrev, pList->BackLinkOffset);
-    else
-        pList->Tail = pPrev;
-
-    ASSIGNLINK( elem, NULL, pList->FwdLinkOffset);
-    ASSIGNLINK( elem, NULL, pList->BackLinkOffset);
-}
-
-
-//		GenLinkedOffsetList		/////////////////////////////////////////////////////
-
-// Extract the Next offset from element
-#define     GETOFFSET( e, o)    ( *(size_t*)((char*) (e) + (o)) )
-
-static void     AssignOffsetLink( void *elem, void *link, size_t linkOffset);
-
-
-static void AssignOffsetLink( void *elem, void *link, size_t linkOffset)
-// Assign link to elem as an offset from elem. Assign 0 to elem if link is NULL.
-{
-    GETOFFSET( elem, linkOffset) = link ? (size_t) link - (size_t) elem : 0;
-}
-
-
-void        *GetHeadPtr( GenLinkedOffsetList *pList)
-/* Return a pointer to the head element of a list, or NULL if none. */
-{
-    return pList->Head ? ( (char*) (pList) + pList->Head) : NULL;
-}
-
-
-void        *GetTailPtr( GenLinkedOffsetList *pList)
-/* Return a pointer to the tail element of a list, or NULL if none. */
-{
-    return pList->Tail ? ( (char*) (pList) + pList->Tail) : NULL;
-}
-
-
-void        *GetOffsetLink( GenLinkedOffsetList *pList, void *elem)
-/* Return the link pointer contained within element e for pList, or NULL if it is 0. */
-{
-    size_t nextOffset;
-
-    nextOffset = GETOFFSET( elem, pList->LinkOffset);
-
-    return nextOffset ? (char*) elem + nextOffset : NULL;
-}
-
-
-void        InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset)
-/* Initialize the block of memory pointed to by pList as a linked list. */
-{
-    pList->Head = 0;
-    pList->Tail = 0;
-    pList->LinkOffset = linkOffset;
-}
-
-
-void        OffsetAddToTail( GenLinkedOffsetList *pList, void *elem)
-/* Add a linked list element to the tail of the list. */
-{
-    if ( pList->Tail) {
-        AssignOffsetLink( GetTailPtr( pList), elem, pList->LinkOffset);
-    } else
-        pList->Head = (size_t) elem - (size_t) pList;
-    AssignOffsetLink( elem, NULL, pList->LinkOffset);
-
-    pList->Tail = (size_t) elem - (size_t) pList;
-}
-
-
-void        OffsetAddToHead( GenLinkedOffsetList *pList, void *elem)
-/* Add a linked list element to the head of the list. */
-{
-    AssignOffsetLink( elem, GetHeadPtr( pList), pList->LinkOffset);
-    if ( pList->Tail == 0)
-        pList->Tail = (size_t) elem - (size_t) pList;
-
-    pList->Head = (size_t) elem - (size_t) pList;
-}
-
-
-int     OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem)
-/* Remove a linked list element from the list. Return 0 if it was not found. */
-/* If the element is removed, its link will be set to NULL. */
-{
-    void    *iElem, *lastElem;
-
-    if (elem == NULL) {
-        return 0;
-    }
-    for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
-          iElem = GetOffsetLink( pList, iElem))
-    {
-        if ( iElem == elem) {
-            if ( lastElem) {        // somewhere past the head
-                AssignOffsetLink( lastElem, GetOffsetLink( pList, elem), pList->LinkOffset);
-            } else {                // at the head
-                iElem = GetOffsetLink( pList, elem);
-                pList->Head = iElem ? (size_t) iElem - (size_t) pList : 0;
-            }
-            if ( GetTailPtr( pList) == elem)
-                pList->Tail = lastElem ? (size_t) lastElem - (size_t) pList : 0;
-            AssignOffsetLink( elem, NULL, pList->LinkOffset);   // maybe catch a stale reference bug.
-            return 1;
-        }
-        lastElem = iElem;
-    }
-
-    return 0;
-}
-
-
-int         OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem)
-/* Replace an element in the list with a new element, in the same position. */
-{
-    void    *iElem, *lastElem;
-
-    if ( elemInList == NULL || newElem == NULL)
-        return 0;
-
-    for ( iElem = GetHeadPtr( pList), lastElem = NULL; iElem;
-          iElem = GetOffsetLink( pList, iElem))
-    {
-        if ( iElem == elemInList)
-        {
-            AssignOffsetLink( newElem, GetOffsetLink( pList, elemInList), pList->LinkOffset);
-            if ( lastElem)      // somewhere past the head
-            {
-                AssignOffsetLink( lastElem, newElem, pList->LinkOffset);
-            }
-            else                // at the head
-            {
-                pList->Head = (size_t) newElem - (size_t) pList;
-            }
-            if ( GetTailPtr( pList) == elemInList)
-                pList->Tail = (size_t) newElem - (size_t) pList;
-            return 1;
-        }
-        lastElem = iElem;
-    }
-
-    return 0;
-}
-
-
diff --git a/mDNSShared/GenLinkedList.h b/mDNSShared/GenLinkedList.h
deleted file mode 100644
index 2d0ada6..0000000
--- a/mDNSShared/GenLinkedList.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 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.
- */
-
-#ifndef __GenLinkedList__
-#define __GenLinkedList__
-
-
-#include <stddef.h>
-
-
-struct  GenLinkedList
-{
-    void        *Head,
-    *Tail;
-    size_t LinkOffset;
-};
-typedef struct GenLinkedList GenLinkedList;
-
-
-void        InitLinkedList( GenLinkedList *pList, size_t linkOffset);
-
-void        AddToHead( GenLinkedList *pList, void *elem);
-void        AddToTail( GenLinkedList *pList, void *elem);
-
-int     RemoveFromList( GenLinkedList *pList, void *elem);
-
-int     ReplaceElem( GenLinkedList *pList, void *elemInList, void *newElem);
-
-
-
-struct  GenDoubleLinkedList
-{
-    void        *Head,
-    *Tail;
-    size_t FwdLinkOffset,
-           BackLinkOffset;
-};
-typedef struct GenDoubleLinkedList GenDoubleLinkedList;
-
-
-void        InitDoubleLinkedList( GenDoubleLinkedList *pList, size_t fwdLinkOffset,
-                                  size_t backLinkOffset);
-
-void        DLLAddToHead( GenDoubleLinkedList *pList, void *elem);
-
-void        DLLRemoveFromList( GenDoubleLinkedList *pList, void *elem);
-
-
-
-/* A GenLinkedOffsetList is like a GenLinkedList that stores the *Next field as a signed */
-/* offset from the address of the beginning of the element, rather than as a pointer. */
-
-struct  GenLinkedOffsetList
-{
-    size_t Head,
-           Tail;
-    size_t LinkOffset;
-};
-typedef struct GenLinkedOffsetList GenLinkedOffsetList;
-
-
-void        InitLinkedOffsetList( GenLinkedOffsetList *pList, size_t linkOffset);
-
-void        *GetHeadPtr( GenLinkedOffsetList *pList);
-void        *GetTailPtr( GenLinkedOffsetList *pList);
-void        *GetOffsetLink( GenLinkedOffsetList *pList, void *elem);
-
-void        OffsetAddToHead( GenLinkedOffsetList *pList, void *elem);
-void        OffsetAddToTail( GenLinkedOffsetList *pList, void *elem);
-
-int     OffsetRemoveFromList( GenLinkedOffsetList *pList, void *elem);
-
-int     OffsetReplaceElem( GenLinkedOffsetList *pList, void *elemInList, void *newElem);
-
-
-#endif //	__GenLinkedList__
diff --git a/mDNSShared/Java/JNISupport.c b/mDNSShared/Java/JNISupport.c
deleted file mode 100644
index 22b4093..0000000
--- a/mDNSShared/Java/JNISupport.c
+++ /dev/null
@@ -1,1072 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2004 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.
-
-    This file contains the platform support for DNSSD and related Java classes.
-    It is used to shim through to the underlying <dns_sd.h> API.
- */
-
-// AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response
-// callbacks automatically (as in the early Windows prototypes).
-// AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to
-// invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.).
-// (Invoking callbacks automatically on a different thread sounds attractive, but while
-// the client gains by not needing to add an event source to its main event loop, it loses
-// by being forced to deal with concurrency and locking, which can be a bigger burden.)
-#ifndef AUTO_CALLBACKS
-#define AUTO_CALLBACKS  0
-#endif
-
-#if !AUTO_CALLBACKS
-#ifdef _WIN32
-#include <winsock2.h>
-#else //_WIN32
-#include <sys/types.h>
-#include <sys/select.h>
-#endif // _WIN32
-#endif // AUTO_CALLBACKS
-
-#include <dns_sd.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef _WIN32
-#include <winsock2.h>
-#include <iphlpapi.h>
-static char *   win32_if_indextoname( DWORD ifIndex, char * nameBuff);
-static DWORD    win32_if_nametoindex( const char * nameStr );
-#define if_indextoname win32_if_indextoname
-#define if_nametoindex win32_if_nametoindex
-#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH
-#else // _WIN32
-#include <sys/socket.h>
-#include <net/if.h>
-#endif // _WIN32
-
-// When compiling with "-Wshadow" set, including jni.h produces the following error:
-// /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration
-// To work around this, we use the preprocessor to map the identifier 'index', which appears harmlessly in function prototype declarations,
-// to something 'jni_index', which doesn't conflict
-#define index jni_index
-#include "DNSSD.java.h"
-#undef index
-
-//#include <syslog.h>
-
-// convenience definition
-#ifdef __GNUC__
-#define _UNUSED __attribute__ ((unused))
-#else
-#define _UNUSED
-#endif
-
-enum {
-    kInterfaceVersionOne = 1,
-    kInterfaceVersionCurrent        // Must match version in .jar file
-};
-
-typedef struct OpContext OpContext;
-
-struct  OpContext
-{
-    DNSServiceRef ServiceRef;
-    JNIEnv          *Env;
-    jobject JavaObj;
-    jobject ClientObj;
-    jmethodID Callback;
-    jmethodID Callback2;
-};
-
-// For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall.
-#if AUTO_CALLBACKS
-JavaVM      *gJavaVM = NULL;
-#endif
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls,
-                                                                    jint callerVersion)
-{
-    /* Ensure that caller & interface versions match. */
-    if ( callerVersion != kInterfaceVersionCurrent)
-        return kDNSServiceErr_Incompatible;
-
-#if AUTO_CALLBACKS
-    {
-        jsize numVMs;
-
-        if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs))
-            return kDNSServiceErr_BadState;
-    }
-#endif
-
-    // Set AppleDNSSD.hasAutoCallbacks
-    {
-#if AUTO_CALLBACKS
-        jboolean hasAutoC = JNI_TRUE;
-#else
-        jboolean hasAutoC = JNI_FALSE;
-#endif
-        jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z");
-        (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC);
-    }
-
-    return kDNSServiceErr_NoError;
-}
-
-
-static const char*  SafeGetUTFChars( JNIEnv *pEnv, jstring str)
-// Wrapper for JNI GetStringUTFChars() that returns NULL for null str.
-{
-    return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL;
-}
-
-static void         SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff)
-// Wrapper for JNI GetStringUTFChars() that handles null str.
-{
-    if ( str != NULL)
-        (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff);
-}
-
-
-#if AUTO_CALLBACKS
-static void SetupCallbackState( JNIEnv **ppEnv)
-{
-    (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL);
-}
-
-static void TeardownCallbackState( void )
-{
-    (*gJavaVM)->DetachCurrentThread( gJavaVM);
-}
-
-#else   // AUTO_CALLBACKS
-
-static void SetupCallbackState( JNIEnv **ppEnv _UNUSED)
-{
-    // No setup necessary if ProcessResults() has been called
-}
-
-static void TeardownCallbackState( void )
-{
-    // No teardown necessary if ProcessResults() has been called
-}
-#endif  // AUTO_CALLBACKS
-
-
-static OpContext    *NewContext( JNIEnv *pEnv, jobject owner,
-                                 const char *callbackName, const char *callbackSig)
-// Create and initialize a new OpContext.
-{
-    OpContext               *pContext = (OpContext*) malloc( sizeof *pContext);
-
-    if ( pContext != NULL)
-    {
-        jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner),
-                                                    "fListener", "Lcom/apple/dnssd/BaseListener;");
-
-        pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner);    // must convert local ref to global to cache;
-        pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField);
-        pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj);    // must convert local ref to global to cache
-        pContext->Callback = (*pEnv)->GetMethodID( pEnv,
-                                                   (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
-                                                   callbackName, callbackSig);
-        pContext->Callback2 = NULL;     // not always used
-    }
-
-    return pContext;
-}
-
-
-static void         ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err)
-// Invoke operationFailed() method on target with err.
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, target);
-    jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed",
-                                               "(Lcom/apple/dnssd/DNSSDService;I)V");
-
-    (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err);
-}
-
-JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis)
-/* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-
-    if ( contextField != 0)
-    {
-        OpContext   *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
-        if ( pContext != NULL)
-        {
-            // MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate()
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, 0);
-            if ( pContext->ServiceRef != NULL)
-                DNSServiceRefDeallocate( pContext->ServiceRef);
-
-            (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj);
-            (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj);
-            free( pContext);
-        }
-    }
-}
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis)
-/* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */
-{
-// BlockForData() not supported with AUTO_CALLBACKS
-#if !AUTO_CALLBACKS
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-
-    if ( contextField != 0)
-    {
-        OpContext   *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
-        if ( pContext != NULL)
-        {
-            fd_set readFDs;
-            int sd = DNSServiceRefSockFD( pContext->ServiceRef);
-            struct timeval timeout = { 1, 0 };
-            FD_ZERO( &readFDs);
-            FD_SET( sd, &readFDs);
-
-            // Q: Why do we poll here?
-            // A: Because there's no other thread-safe way to do it.
-            // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not,
-            // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>)
-            // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while
-            // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way
-            // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously.
-            // If we try to do this without holding any lock, then right as we jump to the select() routine,
-            // some other thread could stop our operation (thereby closing the socket),
-            // and then that thread (or even some third, unrelated thread)
-            // could do some other DNS-SD operation (or some other operation that opens a new file descriptor)
-            // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor
-            // that may coincidentally have the same numerical value, but is semantically unrelated
-            // to the true file descriptor we thought we were blocking on.
-            // We can't stop this race condition from happening, but at least if we wake up once a second we can detect
-            // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd.
-
-            if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1);
-        }
-    }
-#endif // !AUTO_CALLBACKS
-    return(0);
-}
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis)
-/* Call through to DNSServiceProcessResult() while data remains on socket. */
-{
-#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS
-
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext       *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
-    DNSServiceErrorType err = kDNSServiceErr_BadState;
-
-    if ( pContext != NULL)
-    {
-        int sd = DNSServiceRefSockFD( pContext->ServiceRef);
-        fd_set readFDs;
-        struct timeval zeroTimeout = { 0, 0 };
-
-        pContext->Env = pEnv;
-
-        FD_ZERO( &readFDs);
-        FD_SET( sd, &readFDs);
-
-        err = kDNSServiceErr_NoError;
-        if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout))
-        {
-            err = DNSServiceProcessResult(pContext->ServiceRef);
-            // Use caution here!
-            // We cannot touch any data structures associated with this operation!
-            // The DNSServiceProcessResult() routine should have invoked our callback,
-            // and our callback could have terminated the operation with op.stop();
-            // and that means HaltOperation() will have been called, which frees pContext.
-            // Basically, from here we just have to get out without touching any stale
-            // data structures that could blow up on us! Particularly, any attempt
-            // to loop here reading more results from the file descriptor is unsafe.
-        }
-    }
-    return err;
-#endif // AUTO_CALLBACKS
-}
-
-
-static void DNSSD_API   ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
-                                            DNSServiceErrorType errorCode, const char *serviceName, const char *regtype,
-                                            const char *replyDomain, void *context)
-{
-    OpContext       *pContext = (OpContext*) context;
-
-    SetupCallbackState( &pContext->Env);
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
-                                              ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
-                                              pContext->JavaObj, flags, interfaceIndex,
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, regtype),
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis,
-                                                                        jint flags, jint ifIndex, jstring regType, jstring domain)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "serviceFound",
-                               "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        const char  *regStr = SafeGetUTFChars( pEnv, regType);
-        const char  *domainStr = SafeGetUTFChars( pEnv, domain);
-
-        pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
-                                                    (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
-                                                    "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-
-        err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-
-        SafeReleaseUTFChars( pEnv, regType, regStr);
-        SafeReleaseUTFChars( pEnv, domain, domainStr);
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-
-static void DNSSD_API   ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
-                                             DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget,
-                                             uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context)
-{
-    OpContext       *pContext = (OpContext*) context;
-    jclass txtCls;
-    jmethodID txtCtor;
-    jbyteArray txtBytes;
-    jobject txtObj;
-    jbyte           *pBytes;
-
-    SetupCallbackState( &pContext->Env);
-
-    txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord");
-    txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V");
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL &&
-         NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen)))
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit
-            // pattern into a number here.
-            port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1];
-
-            // Initialize txtBytes with contents of txtRecord
-            pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL);
-            memcpy( pBytes, txtRecord, txtLen);
-            (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT);
-
-            // Construct txtObj with txtBytes
-            txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes);
-            (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes);
-
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
-                                              pContext->JavaObj, flags, interfaceIndex,
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, fullname),
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget),
-                                              port, txtObj);
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis,
-                                                                          jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "serviceResolved",
-                               "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        const char  *servStr = SafeGetUTFChars( pEnv, serviceName);
-        const char  *regStr = SafeGetUTFChars( pEnv, regType);
-        const char  *domainStr = SafeGetUTFChars( pEnv, domain);
-
-        err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex,
-                                 servStr, regStr, domainStr, ServiceResolveReply, pContext);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-
-        SafeReleaseUTFChars( pEnv, serviceName, servStr);
-        SafeReleaseUTFChars( pEnv, regType, regStr);
-        SafeReleaseUTFChars( pEnv, domain, domainStr);
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-
-static void DNSSD_API   ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags,
-                                              DNSServiceErrorType errorCode, const char *serviceName,
-                                              const char *regType, const char *domain, void *context)
-{
-    OpContext       *pContext = (OpContext*) context;
-
-    SetupCallbackState( &pContext->Env);
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
-                                              pContext->JavaObj, flags,
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, regType),
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, domain));
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis,
-                                                                             jint ifIndex, jint flags, jstring serviceName, jstring regType,
-                                                                             jstring domain, jstring host, jint port, jbyteArray txtRecord)
-{
-    //syslog(LOG_ERR, "BR");
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    jbyte                   *pBytes;
-    jsize numBytes;
-
-    //syslog(LOG_ERR, "BR: contextField %d", contextField);
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "serviceRegistered",
-                               "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        const char  *servStr = SafeGetUTFChars( pEnv, serviceName);
-        const char  *regStr = SafeGetUTFChars( pEnv, regType);
-        const char  *domainStr = SafeGetUTFChars( pEnv, domain);
-        const char  *hostStr = SafeGetUTFChars( pEnv, host);
-
-        //syslog(LOG_ERR, "BR: regStr %s", regStr);
-
-        // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a
-        // big-endian number into a 16-bit pattern here.
-        uint16_t portBits = port;
-        portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1];
-
-        pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL;
-        numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0;
-
-        err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr,
-                                  domainStr, hostStr, portBits,
-                                  numBytes, pBytes, ServiceRegisterReply, pContext);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-
-        if ( pBytes != NULL)
-            (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0);
-
-        SafeReleaseUTFChars( pEnv, serviceName, servStr);
-        SafeReleaseUTFChars( pEnv, regType, regStr);
-        SafeReleaseUTFChars( pEnv, domain, domainStr);
-        SafeReleaseUTFChars( pEnv, host, hostStr);
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis,
-                                                                         jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
-    jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    jbyte                   *pBytes;
-    jsize numBytes;
-    DNSRecordRef recRef;
-
-    if ( contextField != 0)
-        pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
-    if ( pContext == NULL || pContext->ServiceRef == NULL)
-        return kDNSServiceErr_BadParam;
-
-    pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
-    numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
-
-    err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl);
-    if ( err == kDNSServiceErr_NoError)
-    {
-        (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
-    }
-
-    if ( pBytes != NULL)
-        (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
-
-    return err;
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis,
-                                                                   jint flags, jbyteArray rData, jint ttl)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
-    jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    jbyte                   *pBytes;
-    jsize numBytes;
-    DNSRecordRef recRef = NULL;
-
-    if ( ownerField != 0)
-    {
-        jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
-        jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
-        jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
-        if ( contextField != 0)
-            pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
-    }
-    if ( recField != 0)
-        recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
-    if ( pContext == NULL || pContext->ServiceRef == NULL)
-        return kDNSServiceErr_BadParam;
-
-    pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
-    numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
-
-    err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl);
-
-    if ( pBytes != NULL)
-        (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
-
-    return err;
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;");
-    jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    DNSRecordRef recRef = NULL;
-
-    if ( ownerField != 0)
-    {
-        jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField);
-        jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj);
-        jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J");
-        if ( contextField != 0)
-            pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField);
-    }
-    if ( recField != 0)
-        recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField);
-    if ( pContext == NULL || pContext->ServiceRef == NULL)
-        return kDNSServiceErr_BadParam;
-
-    err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0);
-
-    return err;
-}
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        err = DNSServiceCreateConnection( &pContext->ServiceRef);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-struct RecordRegistrationRef
-{
-    OpContext       *Context;
-    jobject RecordObj;
-};
-typedef struct RecordRegistrationRef RecordRegistrationRef;
-
-static void DNSSD_API   RegisterRecordReply( DNSServiceRef sdRef _UNUSED,
-                                             DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags,
-                                             DNSServiceErrorType errorCode, void *context)
-{
-    RecordRegistrationRef   *regEnvelope = (RecordRegistrationRef*) context;
-    OpContext       *pContext = regEnvelope->Context;
-
-    SetupCallbackState( &pContext->Env);
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
-                                              regEnvelope->RecordObj, flags);
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-
-    (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj);
-    free( regEnvelope);
-
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis,
-                                                                                 jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass,
-                                                                                 jbyteArray rData, jint ttl, jobject destObj)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj);
-    jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J");
-    const char              *nameStr = SafeGetUTFChars( pEnv, fullname);
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    jbyte                   *pBytes;
-    jsize numBytes;
-    DNSRecordRef recRef;
-    RecordRegistrationRef   *regEnvelope;
-
-    if ( contextField != 0)
-        pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField);
-    if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL)
-        return kDNSServiceErr_BadParam;
-
-    regEnvelope = calloc( 1, sizeof *regEnvelope);
-    if ( regEnvelope == NULL)
-        return kDNSServiceErr_NoMemory;
-    regEnvelope->Context = pContext;
-    regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache
-
-    pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL);
-    numBytes = (*pEnv)->GetArrayLength( pEnv, rData);
-
-    err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex,
-                                    nameStr, rrType, rrClass, numBytes, pBytes, ttl,
-                                    RegisterRecordReply, regEnvelope);
-
-    if ( err == kDNSServiceErr_NoError)
-    {
-        (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef);
-    }
-    else
-    {
-        if ( regEnvelope->RecordObj != NULL)
-            (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj);
-        free( regEnvelope);
-    }
-
-    if ( pBytes != NULL)
-        (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0);
-
-    SafeReleaseUTFChars( pEnv, fullname, nameStr);
-
-    return err;
-}
-
-
-static void DNSSD_API   ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
-                                           DNSServiceErrorType errorCode, const char *serviceName,
-                                           uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
-                                           const void *rdata, uint32_t ttl, void *context)
-{
-    OpContext       *pContext = (OpContext*) context;
-    jbyteArray rDataObj;
-    jbyte           *pBytes;
-
-    SetupCallbackState( &pContext->Env);
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL &&
-         NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen)))
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            // Initialize rDataObj with contents of rdata
-            pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL);
-            memcpy( pBytes, rdata, rdlen);
-            (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT);
-
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback,
-                                              pContext->JavaObj, flags, interfaceIndex,
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, serviceName),
-                                              rrtype, rrclass, rDataObj, ttl);
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis,
-                                                                    jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "queryAnswered",
-                               "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        const char  *servStr = SafeGetUTFChars( pEnv, serviceName);
-
-        err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr,
-                                     rrtype, rrclass, ServiceQueryReply, pContext);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-
-        SafeReleaseUTFChars( pEnv, serviceName, servStr);
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-
-static void DNSSD_API   DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex,
-                                         DNSServiceErrorType errorCode, const char *replyDomain, void *context)
-{
-    OpContext       *pContext = (OpContext*) context;
-
-    SetupCallbackState( &pContext->Env);
-
-    if ( pContext->ClientObj != NULL && pContext->Callback != NULL)
-    {
-        if ( errorCode == kDNSServiceErr_NoError)
-        {
-            (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj,
-                                              ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2,
-                                              pContext->JavaObj, flags, interfaceIndex,
-                                              (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain));
-        }
-        else
-            ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode);
-    }
-    TeardownCallbackState();
-}
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis,
-                                                                       jint flags, jint ifIndex)
-{
-    jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis);
-    jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J");
-    OpContext               *pContext = NULL;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if ( contextField != 0)
-        pContext = NewContext( pEnv, pThis, "domainFound",
-                               "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
-    else
-        err = kDNSServiceErr_BadParam;
-
-    if ( pContext != NULL)
-    {
-        pContext->Callback2 = (*pEnv)->GetMethodID( pEnv,
-                                                    (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj),
-                                                    "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V");
-
-        err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex,
-                                          DomainEnumReply, pContext);
-        if ( err == kDNSServiceErr_NoError)
-        {
-            (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext);
-        }
-    }
-    else
-        err = kDNSServiceErr_NoMemory;
-
-    return err;
-}
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED,
-                                                                      jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut)
-{
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-    const char              *nameStr = SafeGetUTFChars( pEnv, serviceName);
-    const char              *regStr = SafeGetUTFChars( pEnv, regtype);
-    const char              *domStr = SafeGetUTFChars( pEnv, domain);
-    char buff[ kDNSServiceMaxDomainName + 1];
-
-    err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr);
-
-    if ( err == kDNSServiceErr_NoError)
-    {
-        // pOut is expected to be a String[1] array.
-        (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff));
-    }
-
-    SafeReleaseUTFChars( pEnv, serviceName, nameStr);
-    SafeReleaseUTFChars( pEnv, regtype, regStr);
-    SafeReleaseUTFChars( pEnv, domain, domStr);
-
-    return err;
-}
-
-JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED,
-                                                                        jint flags, jint ifIndex, jstring fullName,
-                                                                        jint rrtype, jint rrclass, jbyteArray rdata)
-{
-    jbyte                   *pBytes;
-    jsize numBytes;
-    const char              *nameStr = SafeGetUTFChars( pEnv, fullName);
-
-    pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL);
-    numBytes = (*pEnv)->GetArrayLength( pEnv, rdata);
-
-    DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes);
-
-    if ( pBytes != NULL)
-        (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0);
-
-    SafeReleaseUTFChars( pEnv, fullName, nameStr);
-}
-
-#define LOCAL_ONLY_NAME "loo"
-#define P2P_NAME "p2p"
-
-JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED,
-                                                                             jint ifIndex)
-{
-    char                    *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE];
-
-    if (ifIndex == (jint) kDNSServiceInterfaceIndexP2P)
-        p = P2P_NAME;
-    else if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly)
-        p = if_indextoname( ifIndex, nameBuff );
-
-    return (*pEnv)->NewStringUTF( pEnv, p);
-}
-
-
-JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED,
-                                                                          jstring ifName)
-{
-    uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly;
-    const char              *nameStr = SafeGetUTFChars( pEnv, ifName);
-
-    if (strcmp(nameStr, P2P_NAME) == 0)
-        ifIndex = kDNSServiceInterfaceIndexP2P;
-    else if (strcmp(nameStr, LOCAL_ONLY_NAME))
-        ifIndex = if_nametoindex( nameStr);
-
-    SafeReleaseUTFChars( pEnv, ifName, nameStr);
-
-    return ifIndex;
-}
-
-
-#if defined(_WIN32)
-static char*
-win32_if_indextoname( DWORD ifIndex, char * nameBuff)
-{
-    PIP_ADAPTER_INFO pAdapterInfo = NULL;
-    PIP_ADAPTER_INFO pAdapter = NULL;
-    DWORD dwRetVal = 0;
-    char            *   ifName = NULL;
-    ULONG ulOutBufLen = 0;
-
-    if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
-    {
-        goto exit;
-    }
-
-    pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
-
-    if (pAdapterInfo == NULL)
-    {
-        goto exit;
-    }
-
-    dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
-
-    if (dwRetVal != NO_ERROR)
-    {
-        goto exit;
-    }
-
-    pAdapter = pAdapterInfo;
-    while (pAdapter)
-    {
-        if (pAdapter->Index == ifIndex)
-        {
-            // It would be better if we passed in the length of nameBuff to this
-            // function, so we would have absolute certainty that no buffer
-            // overflows would occur.  Buffer overflows *shouldn't* occur because
-            // nameBuff is of size MAX_ADAPTER_NAME_LENGTH.
-            strcpy( nameBuff, pAdapter->AdapterName );
-            ifName = nameBuff;
-            break;
-        }
-
-        pAdapter = pAdapter->Next;
-    }
-
-exit:
-
-    if (pAdapterInfo != NULL)
-    {
-        free( pAdapterInfo );
-        pAdapterInfo = NULL;
-    }
-
-    return ifName;
-}
-
-
-static DWORD
-win32_if_nametoindex( const char * nameStr )
-{
-    PIP_ADAPTER_INFO pAdapterInfo = NULL;
-    PIP_ADAPTER_INFO pAdapter = NULL;
-    DWORD dwRetVal = 0;
-    DWORD ifIndex = 0;
-    ULONG ulOutBufLen = 0;
-
-    if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW)
-    {
-        goto exit;
-    }
-
-    pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
-
-    if (pAdapterInfo == NULL)
-    {
-        goto exit;
-    }
-
-    dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen );
-
-    if (dwRetVal != NO_ERROR)
-    {
-        goto exit;
-    }
-
-    pAdapter = pAdapterInfo;
-    while (pAdapter)
-    {
-        if (strcmp(pAdapter->AdapterName, nameStr) == 0)
-        {
-            ifIndex = pAdapter->Index;
-            break;
-        }
-
-        pAdapter = pAdapter->Next;
-    }
-
-exit:
-
-    if (pAdapterInfo != NULL)
-    {
-        free( pAdapterInfo );
-        pAdapterInfo = NULL;
-    }
-
-    return ifIndex;
-}
-#endif
-
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// NOT static -- otherwise the compiler may optimize it out
-// The "@(#) " pattern is a special prefix the "what" command looks for
-const char VersionString_SCCS[] = "@(#) libjdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
diff --git a/mDNSShared/PlatformCommon.c b/mDNSShared/PlatformCommon.c
deleted file mode 100644
index 6554cdb..0000000
--- a/mDNSShared/PlatformCommon.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2004-2021 Apple 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
- *
- *     https://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.
- *
- * This file defines functions that are common to platforms with Posix APIs.
- * Current examples are mDNSMacOSX and mDNSPosix.
- */
-
-#include <stdio.h>              // Needed for fopen() etc.
-#include <unistd.h>             // Needed for close()
-#include <stdlib.h>             // Needed for malloc()
-#include <string.h>             // Needed for strlen() etc.
-#include <errno.h>              // Needed for errno etc.
-#include <sys/socket.h>         // Needed for socket() etc.
-#include <netinet/in.h>         // Needed for sockaddr_in
-#include <syslog.h>
-#include <sys/fcntl.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <sys/time.h>           // Needed for #include <sys/time.h>().
-#include <assert.h>
-
-
-#include "mDNSEmbeddedAPI.h"    // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "PlatformCommon.h"
-#include "mdns_strict.h"
-
-#ifdef NOT_HAVE_SOCKLEN_T
-typedef unsigned int socklen_t;
-#endif
-
-#if MDNS_MALLOC_DEBUGGING
-// We ONLY want this for malloc debugging--on a running production system we want to deal with
-// malloc failures, not just die.   There is a small performance penalty for enabling these options
-// as well, so they are all only appropriate for debugging.   The flags mean:
-//
-// A = warnings are errors
-// X = abort on failure
-// Z = sets J & R
-// J = allocated memory is initialized to a pattern
-// R causes realloc to always reallocate even if not needed
-
-char _malloc_options[] = "AXZ";
-
-mDNSlocal mDNSListValidator *listValidators;
-
-mDNSexport void mDNSPlatformAddListValidator(mDNSListValidator *lv, mDNSListValidationFunction *lvf,
-                                             const char *lvfName, void *context)
-{
-    mDNSPlatformMemZero(lv, sizeof *lv);
-    lv->validator = lvf;
-    lv->validationFunctionName = lvfName;
-    lv->context = context;
-    lv->next = listValidators;
-    listValidators = lv;
-}
-
-mDNSlocal void validateLists(void)
-{
-    mDNSListValidator *vfp;
-    // Check Unix Domain Socket client lists (uds_daemon.c)
-    for (vfp = listValidators; vfp; vfp = vfp->next)
-    {
-        vfp->validator(vfp->context);
-    }
-
-    mDNSPlatformValidateLists();
-}
-
-#define kAllocMagic     0xDEAD1234
-#define kGuardMagic     0xDEAD1234
-#define kFreeMagic      0xDEADDEAD
-#define kAllocLargeSize 32768
-
-mDNSexport void *mallocL(const char *msg, mDNSu32 size)
-{
-    // Allocate space for two words of sanity checking data before the requested block and two words after.
-    // Adjust the length for alignment.
-    mDNSu32 *mem = malloc(sizeof(mDNSu32) * 4 + size);
-    mDNSu32 guard[2];
-    if (!mem)
-    { LogMsg("malloc( %s : %u ) failed", msg, size); return(NULL); }
-    else
-    {
-        mDNSu32 *after = (mDNSu32 *)((mDNSu8 *)(mem + 2) + size);
-        if      (size > kAllocLargeSize)      LogMsg("malloc( %s : %lu ) @ %p suspiciously large", msg, size, &mem[2]);
-        else if (MDNS_MALLOC_DEBUGGING >= 2)  LogMsg("malloc( %s : %lu ) @ %p",                    msg, size, &mem[2]);
-        mem[  0] = kAllocMagic;
-        guard[0] = kGuardMagic;
-        mem[  1] = size;
-        guard[1] = size;
-        memcpy(after, &guard, sizeof guard);
-        memset(&mem[2], 0xFF, size);
-        validateLists();
-        return(&mem[2]);
-    }
-}
-
-mDNSexport void *callocL(const char *msg, mDNSu32 size)
-{
-    mDNSu32 guard[2];
-    const mDNSu32 headerSize = 4 * sizeof(mDNSu32);
-
-    // Allocate space for two words of sanity checking data before the requested block and two words after.
-    // Adjust the length for alignment.
-    mDNSu32 *mem = (mDNSu32 *)calloc(1, headerSize + size);
-    if (!mem)
-    { LogMsg("calloc( %s : %u ) failed", msg, size); return(NULL); }
-    else
-    {
-        mDNSu32 *after = (mDNSu32 *)((mDNSu8 *)(mem + 2) + size);
-        if      (size > kAllocLargeSize)     LogMsg("calloc( %s : %lu ) @ %p suspiciously large", msg, size, &mem[2]);
-        else if (MDNS_MALLOC_DEBUGGING >= 2) LogMsg("calloc( %s : %lu ) @ %p",                    msg, size, &mem[2]);
-        mem[  0] = kAllocMagic;
-        guard[0] = kGuardMagic;
-        mem[  1] = size;
-        guard[1] = size;
-        memcpy(after, guard, sizeof guard);
-        validateLists();
-        return(&mem[2]);
-    }
-}
-
-mDNSexport void freeL(const char *msg, void *x)
-{
-    if (!x)
-        LogMsg("free( %s @ NULL )!", msg);
-    else
-    {
-        mDNSu32 *mem = ((mDNSu32 *)x) - 2;
-        if      (mem[0] == kFreeMagic)  { LogMemCorruption("free( %s : %lu @ %p ) !!!! ALREADY DISPOSED !!!!", msg, mem[1], &mem[2]); return; }
-        if      (mem[0] != kAllocMagic) { LogMemCorruption("free( %s : %lu @ %p ) !!!! NEVER ALLOCATED !!!!",  msg, mem[1], &mem[2]); return; }
-        if      (mem[1] > kAllocLargeSize)          LogMsg("free( %s : %lu @ %p) suspiciously large",          msg, mem[1], &mem[2]);
-        else if (MDNS_MALLOC_DEBUGGING >= 2)        LogMsg("free( %s : %ld @ %p)",                             msg, mem[1], &mem[2]);
-        mDNSu32 *after = (mDNSu32 *)((mDNSu8 *)x + mem[1]);
-        mDNSu32 guard[2];
-
-        memcpy(guard, after, sizeof guard);
-        if (guard[0] != kGuardMagic)    { LogMemCorruption("free( %s : %lu @ %p ) !!!! END GUARD OVERWRITE !!!!",
-                                                           msg, mem[1], &mem[2]); return; }
-        if (guard[1] != mem[1])         { LogMemCorruption("free( %s : %lu @ %p ) !!!! LENGTH MISMATCH !!!!",
-                                                           msg, mem[1], &mem[2]); return; }
-        mem[0] = kFreeMagic;
-        memset(mem + 2, 0xFF, mem[1] + 2 * sizeof(mDNSu32));
-        validateLists();
-        free(mem);
-    }
-}
-
-#endif
-
-// Bind a UDP socket to find the source address to a destination
-mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
-{
-    union { struct sockaddr s; struct sockaddr_in a4; struct sockaddr_in6 a6; } addr;
-    socklen_t len = sizeof(addr);
-    socklen_t inner_len = 0;
-    int sock = socket(AF_INET, SOCK_DGRAM, 0);
-    src->type = mDNSAddrType_None;
-    if (sock == -1) return;
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        inner_len = sizeof(addr.a4);
-        #ifndef NOT_HAVE_SA_LEN
-        addr.a4.sin_len         = (unsigned char)inner_len;
-        #endif
-        addr.a4.sin_family      = AF_INET;
-        addr.a4.sin_port        = 1;    // Not important, any port will do
-        addr.a4.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
-    }
-    else if (dst->type == mDNSAddrType_IPv6)
-    {
-        inner_len = sizeof(addr.a6);
-        #ifndef NOT_HAVE_SA_LEN
-        addr.a6.sin6_len      = (unsigned char)inner_len;
-        #endif
-        addr.a6.sin6_family   = AF_INET6;
-        addr.a6.sin6_flowinfo = 0;
-        addr.a6.sin6_port     = 1;  // Not important, any port will do
-        addr.a6.sin6_addr     = *(const struct in6_addr*)&dst->ip.v6;
-        addr.a6.sin6_scope_id = 0;
-    }
-    else return;
-
-    if ((connect(sock, &addr.s, inner_len)) < 0)
-    { LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; }
-
-    if ((getsockname(sock, &addr.s, &len)) < 0)
-    { LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; }
-
-    src->type = dst->type;
-    if (dst->type == mDNSAddrType_IPv4) src->ip.v4.NotAnInteger = addr.a4.sin_addr.s_addr;
-    else src->ip.v6 = *(mDNSv6Addr*)&addr.a6.sin6_addr;
-exit:
-    close(sock);
-}
-
-// dst must be at least MAX_ESCAPED_DOMAIN_NAME bytes, and option must be less than 32 bytes in length
-mDNSlocal mDNSBool GetConfigOption(char *dst, const char *option, FILE *f)
-{
-    char buf[32+1+MAX_ESCAPED_DOMAIN_NAME]; // Option name, one space, option value
-    size_t len = strlen(option);
-    if (len + 1 + MAX_ESCAPED_DOMAIN_NAME > sizeof(buf)-1) { LogMsg("GetConfigOption: option %s too long", option); return mDNSfalse; }
-    fseek(f, 0, SEEK_SET);  // set position to beginning of stream
-    while (fgets(buf, sizeof(buf), f))      // Read at most sizeof(buf)-1 bytes from file, and append '\0' C-string terminator
-    {
-        if (!strncmp(buf, option, len))
-        {
-            mDNSPlatformStrLCopy(dst, buf + len + 1, MAX_ESCAPED_DOMAIN_NAME-1);
-            if (dst[MAX_ESCAPED_DOMAIN_NAME-1]) dst[MAX_ESCAPED_DOMAIN_NAME-1] = '\0';
-            len = strlen(dst);
-            if (len && dst[len-1] == '\n') dst[len-1] = '\0';  // chop newline
-            return mDNStrue;
-        }
-    }
-    debugf("Option %s not set", option);
-    return mDNSfalse;
-}
-
-mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled)
-{
-    char buf[MAX_ESCAPED_DOMAIN_NAME] = "";
-    mStatus err;
-    FILE *f = fopen(filename, "r");
-
-    if (hostname) hostname->c[0] = 0;
-    if (domain) domain->c[0] = 0;
-    if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse;
-
-    if (f)
-    {
-        if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue;
-        if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf;
-        if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf;
-        buf[0] = 0;
-        GetConfigOption(buf, "secret-64", f);  // failure means no authentication
-        fclose(f);
-        f = NULL;
-    }
-    else
-    {
-        if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened.");
-        return;
-    }
-
-    if (domain && domain->c[0] && buf[0])
-    {
-        DomainAuthInfo *info = (DomainAuthInfo*) mDNSPlatformMemAllocateClear(sizeof(*info));
-        // for now we assume keyname = service reg domain and we use same key for service and hostname registration
-        err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0);
-        if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
-    }
-
-    return;
-
-badf:
-    LogMsg("ERROR: malformatted config file");
-    if (f) fclose(f);
-}
-
-#if MDNS_DEBUGMSGS
-mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
-{
-    fprintf(stderr,"%s\n", msg);
-    fflush(stderr);
-}
-#endif
-
-#if !MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, mDNSLogLevel_t loglevel)
-{
-
-    if (mDNS_DebugMode) // In debug mode we write to stderr
-    {
-        fprintf(stderr,"%s\n", buffer);
-        fflush(stderr);
-    }
-    else                // else, in production mode, we write to syslog
-    {
-        static int log_inited = 0;
-
-        int syslog_level;
-        switch (loglevel)
-        {
-            case MDNS_LOG_FAULT:     syslog_level = LOG_ERR;     break;
-            case MDNS_LOG_ERROR:     syslog_level = LOG_ERR;     break;
-            case MDNS_LOG_WARNING:   syslog_level = LOG_WARNING; break;
-            case MDNS_LOG_DEFAULT:   syslog_level = LOG_NOTICE;  break;
-            case MDNS_LOG_INFO:      syslog_level = LOG_INFO;    break;
-            case MDNS_LOG_DEBUG:     syslog_level = LOG_DEBUG;   break;
-            default:                 syslog_level = LOG_NOTICE;  break;
-        }
-
-        if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
-
-        {
-            syslog(syslog_level, "%s", buffer);
-        }
-    }
-}
-#endif // !MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-
-mDNSexport mDNSBool mDNSPosixTCPSocketSetup(int *fd, mDNSAddr_Type addrType, mDNSIPPort *port, mDNSIPPort *outTcpPort)
-{
-    const sa_family_t sa_family = (addrType == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
-    int err;
-    int sock;
-    mDNSu32 lowWater = 15384;
-
-    sock = socket(sa_family, SOCK_STREAM, IPPROTO_TCP);
-    if (sock < 3)
-    {
-        if (errno != EAFNOSUPPORT)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSPosixTCPSocketSetup: socket error %d errno %d (" PUB_S ")", sock, errno, strerror(errno));
-        }
-        return mDNStrue;
-    }
-    *fd = sock;
-
-    union
-    {
-        struct sockaddr sa;
-        struct sockaddr_in sin;
-        struct sockaddr_in6 sin6;
-    } addr;
-    // If port is not NULL, bind to it.
-    if (port != NULL)
-    {
-        socklen_t len = (sa_family == AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
-        mDNSPlatformMemZero(&addr, sizeof addr);
-
-        addr.sa.sa_family = sa_family;
-#ifndef NOT_HAVE_SA_LEN
-        addr.sa.sa_len = (unsigned char)len;
-#endif
-        if (sa_family == AF_INET6)
-        {
-            addr.sin6.sin6_port = port->NotAnInteger;
-        }
-        else
-        {
-            addr.sin.sin_port = port->NotAnInteger;
-        }
-        err = bind(sock, &addr.sa, len);
-        if (err < 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSPosixTCPSocketSetup getsockname: " PUB_S, strerror(errno));
-            return mDNSfalse;
-        }
-    }
-
-    socklen_t addrlen = sizeof addr;
-    err = getsockname(sock, (struct sockaddr *)&addr, &addrlen);
-    if (err < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSPosixTCPSocketSetup getsockname: " PUB_S, strerror(errno));
-        return mDNSfalse;
-    }
-    if (sa_family == AF_INET6)
-    {
-        outTcpPort->NotAnInteger = addr.sin6.sin6_port;
-
-    } else
-    {
-        outTcpPort->NotAnInteger = addr.sin.sin_port;
-    }
-    if (port)
-        port->NotAnInteger = outTcpPort->NotAnInteger;
-
-#ifdef TCP_NOTSENT_LOWAT
-    err = setsockopt(sock, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &lowWater, sizeof lowWater);
-    if (err < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNSPosixTCPSocketSetup: TCP_NOTSENT_LOWAT failed: " PUB_S, strerror(errno));
-        return mDNSfalse;
-    }
-#endif // TCP_NOTSENT_LOWAT
-
-    return mDNStrue;
-}
-
-mDNSexport TCPSocket *mDNSPosixDoTCPListenCallback(int fd, mDNSAddr_Type addressType, TCPSocketFlags socketFlags,
-                                             TCPAcceptedCallback callback, void *context)
-{
-    union
-    {
-        struct sockaddr_in6 sin6;
-        struct sockaddr_in sin;
-        struct sockaddr sa;
-    } address;
-
-    socklen_t slen = sizeof address;
-    int remoteSock;
-    mDNSAddr addr;
-    mDNSIPPort port;
-    TCPSocket *sock = mDNSNULL;
-    int failed;
-    char *nbp;
-    int i;
-    mDNSu32 lowWater = 16384;
-    // When we remember our connection, we remember a name that we can print for logging.   But
-    // since we are the listener in this case, we don't /have/ a name for it.   This buffer
-    // is used to print the IP address into a human readable string which will serve that purpose
-    // for this case.
-    char namebuf[INET6_ADDRSTRLEN + 1 + 5 + 1];
-
-    remoteSock = accept(fd, &address.sa, &slen);
-    if (remoteSock < 0)
-    {
-        LogMsg("mDNSPosixDoTCPListenCallback: accept returned %d", remoteSock);
-        goto out;
-    }
-
-    failed = fcntl(remoteSock, F_SETFL, O_NONBLOCK);
-    if (failed < 0)
-    {
-        close(remoteSock);
-        LogMsg("mDNSPosixDoTCPListenCallback: fcntl returned %d", errno);
-        goto out;
-    }
-
-#ifdef TCP_NOTSENT_LOWAT
-    failed = setsockopt(remoteSock, IPPROTO_TCP, TCP_NOTSENT_LOWAT,
-                        &lowWater, sizeof lowWater);
-    if (failed < 0)
-    {
-        close(remoteSock);
-        LogMsg("mDNSPosixDoTCPListenCallback: TCP_NOTSENT_LOWAT returned %d", errno);
-        goto out;
-    }
-#endif // TCP_NOTSENT_LOWAT
-
-    if (address.sa.sa_family == AF_INET6)
-    {
-        // If we are listening on an IPv4/IPv6 socket, the incoming address might be an IPv4-in-IPv6 address
-        for (i = 0; i < 10; i++)
-        {
-            if (address.sin6.sin6_addr.s6_addr[i] != 0)
-            {
-                addr.type = mDNSAddrType_IPv6;
-                goto nope;
-            }
-        }
-
-        // a legit IPv4 address would be ::ffff:a.b.c.d; if there's no ::ffff bit, then it's an IPv6
-        // address with a really weird prefix.
-        if (address.sin6.sin6_addr.s6_addr[10] != 0xFF || address.sin6.sin6_addr.s6_addr[11] != 0xFF)
-        {
-            addr.type = mDNSAddrType_IPv6;
-        } else if (addressType != mDNSAddrType_None)
-        {
-            if (inet_ntop(AF_INET, &address.sin6.sin6_addr.s6_addr[12], namebuf, INET6_ADDRSTRLEN + 1) == NULL)
-            {
-                strcpy(namebuf, ":unknown:");
-            }
-            LogMsg("mDNSPosixDoTCPListenCallback received an IPv4 connection from %s on an IPv6-only socket.",
-                   namebuf);
-            close(remoteSock);
-            goto out;
-        }
-        else
-        {
-            addr.type = mDNSAddrType_IPv4;
-        }
-    nope:
-        if (addr.type == mDNSAddrType_IPv6)
-        {
-            if (inet_ntop(address.sin6.sin6_family, &address.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN + 1) == NULL)
-            {
-                strcpy(namebuf, ":unknown:");
-            }
-            memcpy(&addr.ip.v6, &address.sin6.sin6_addr, sizeof addr.ip.v6);
-        }
-        else
-        {
-            if (inet_ntop(AF_INET, &address.sin6.sin6_addr.s6_addr[12], namebuf, INET6_ADDRSTRLEN + 1) == NULL)
-            {
-                strcpy(namebuf, ":unknown:");
-            }
-            memcpy(&addr.ip.v4, &address.sin6.sin6_addr.s6_addr[12], sizeof addr.ip.v4);
-        }
-        port.NotAnInteger = address.sin6.sin6_port;
-    }
-    else if (address.sa.sa_family == AF_INET)
-    {
-        addr.type = mDNSAddrType_IPv4;
-        memcpy(&addr.ip.v4, &address.sin.sin_addr, sizeof addr.ip.v4);
-        port.NotAnInteger = address.sin.sin_port;
-        if (inet_ntop(AF_INET, &address.sin.sin_addr, namebuf, INET6_ADDRSTRLEN + 1) == NULL)
-        {
-            strcpy(namebuf, ":unknown:");
-        }
-    } else {
-        LogMsg("mDNSPosixDoTCPListenCallback: connection from unknown address family %d", address.sa.sa_family);
-        close(remoteSock);
-        goto out;
-    }
-    nbp = namebuf + strlen(namebuf);
-    *nbp++ = '%';
-    snprintf(nbp, 6, "%u", ntohs(port.NotAnInteger));
-
-    sock = mDNSPlatformTCPAccept(socketFlags, remoteSock);
-    if (sock == NULL)
-    {
-        LogMsg("mDNSPosixDoTCPListenCallback: mDNSPlatformTCPAccept returned NULL; dropping connection from %s",
-               namebuf);
-        close(remoteSock);
-        goto out;
-    }
-    callback(sock, &addr, &port, namebuf, context);
-out:
-    return sock;
-}
-
-mDNSexport mDNSBool mDNSPosixTCPListen(int *fd, mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
-                                       mDNSBool reuseAddr, int queueLength)
-
-{
-    union
-    {
-        struct sockaddr_in6 sin6;
-        struct sockaddr_in sin;
-        struct sockaddr sa;
-    } address;
-
-    int failed;
-    int sock;
-    int one = 1;
-    socklen_t sock_len;
-
-    // We require an addrtype parameter because addr is allowed to be null, but they have to agree.
-    if (addr != mDNSNULL && addr->type != addrtype)
-    {
-        LogMsg("mDNSPlatformTCPListen: address type conflict: %d:%d", addr->type, addrtype);
-        return mDNSfalse;
-    }
-    if (port == mDNSNULL)
-    {
-        LogMsg("mDNSPlatformTCPListen: port must not be NULL");
-        return mDNSfalse;
-    }
-
-    mDNSPlatformMemZero(&address, sizeof address);
-    if (addrtype == mDNSAddrType_None || addrtype == mDNSAddrType_IPv6)
-    {
-        // Set up DNS listener socket
-        if (addr != mDNSNULL)
-        {
-            memcpy(&address.sin6.sin6_addr.s6_addr, &addr->ip, sizeof address.sin6.sin6_addr.s6_addr);
-        }
-        address.sin6.sin6_port = port->NotAnInteger;
-
-        sock_len = sizeof address.sin6;
-        address.sin6.sin6_family = AF_INET6;
-    }
-    else if (addrtype == mDNSAddrType_IPv4)
-    {
-        if (addr != mDNSNULL)
-        {
-            memcpy(&address.sin.sin_addr.s_addr, &addr->ip, sizeof address.sin.sin_addr.s_addr);
-        }
-        address.sin.sin_port = port->NotAnInteger;
-        sock_len = sizeof address.sin;
-        address.sin.sin_family = AF_INET;
-    }
-    else
-    {
-        LogMsg("mDNSPlatformTCPListen: invalid address type: %d", addrtype);
-        return mDNSfalse;
-    }
-#ifndef NOT_HAVE_SA_LEN
-    address.sa.sa_len = (unsigned char)sock_len;
-#endif
-    sock = socket(address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
-
-    if (sock < 0)
-    {
-        LogMsg("mDNSPlatformTCPListen: socket call failed: %s", strerror(errno));
-        return mDNSfalse;
-    }
-    *fd = sock;
-
-    // The reuseAddr flag is used to indicate that we want to listen on this port even if
-    // there are still lingering sockets.   We will still fail if there is another listener.
-    // Note that this requires SO_REUSEADDR, not SO_REUSEPORT, which does not have special
-    // handling for lingering sockets.
-    if (reuseAddr)
-    {
-        failed = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
-        if (failed < 0)
-        {
-            LogMsg("mDNSPlatformTCPListen: SO_REUSEADDR failed %s", strerror(errno));
-            return mDNSfalse;
-        }
-    }
-
-    // Bind to the port and (if provided) address
-    failed = bind(sock, &address.sa, sock_len);
-    if (failed < 0)
-    {
-        LogMsg("mDNSPlatformTCPListen: bind failed %s", strerror(errno));
-        return mDNSfalse;
-    }
-
-    // If there was no specified listen port, we need to know what port we got.
-    if (port->NotAnInteger == 0)
-    {
-        mDNSPlatformMemZero(&address, sizeof address);
-        failed = getsockname(sock, &address.sa, &sock_len);
-        if (failed < 0)
-        {
-            LogMsg("mDNSRelay: getsockname failed: %s", strerror(errno));
-            return mDNSfalse;
-        }
-        if (address.sa.sa_family == AF_INET)
-        {
-            port->NotAnInteger = address.sin.sin_port;
-        }
-        else
-        {
-            port->NotAnInteger = address.sin6.sin6_port;
-        }
-    }
-
-    failed = listen(sock, queueLength);
-    if (failed < 0)
-    {
-        LogMsg("mDNSPlatformTCPListen: listen failed: %s", strerror(errno));
-        return mDNSfalse;
-    }
-    return mDNStrue;
-}
-
-mDNSexport long mDNSPosixReadTCP(int fd, void *buf, unsigned long buflen, mDNSBool *closed)
-{
-    static int CLOSEDcount = 0;
-    static int EAGAINcount = 0;
-#ifndef FUZZING
-    ssize_t nread = recv(fd, buf, buflen, 0);
-#else
-    ssize_t nread = read(fd, buf, buflen);
-#endif
-
-    if (nread > 0)
-    {
-        CLOSEDcount = 0;
-        EAGAINcount = 0;
-    } // On success, clear our error counters
-    else if (nread == 0)
-    {
-        *closed = mDNStrue;
-        if ((++CLOSEDcount % 20) == 0)
-        {
-            LogMsg("ERROR: mDNSPosixReadFromSocket - recv %d got CLOSED %d times", fd, CLOSEDcount);
-            assert(CLOSEDcount < 1000);
-            // Recovery Mechanism to bail mDNSResponder out of trouble: Instead of logging the same error
-            // msg multiple times, crash mDNSResponder using assert() and restart fresh. See advantages
-            // below:
-            // 1.Better User Experience
-            // 2.CrashLogs frequency can be monitored
-            // 3.StackTrace can be used for more info
-        }
-    }
-    // else nread is negative -- see what kind of error we got
-    else if (errno == ECONNRESET)
-    {
-        nread = 0; *closed = mDNStrue;
-    }
-    else if (errno != EAGAIN)
-    {
-        LogMsg("ERROR: mDNSPosixReadFromSocket - recv: %d (%s)", errno, strerror(errno));
-        nread = -1;
-    }
-    else
-    { // errno is EAGAIN (EWOULDBLOCK) -- no data available
-        nread = 0;
-        if ((++EAGAINcount % 1000) == 0)
-        {
-            LogMsg("ERROR: mDNSPosixReadFromSocket - recv %d got EAGAIN %d times", fd, EAGAINcount);
-            sleep(1);
-        }
-    }
-    return nread;
-}
-
-mDNSexport long mDNSPosixWriteTCP(int fd, const char *msg, unsigned long len)
-{
-    ssize_t result;
-    long nsent;
-
-    result = write(fd, msg, len);
-    if (result < 0)
-    {
-        if (errno == EAGAIN)
-        {
-            nsent = 0;
-        }
-        else
-        {
-            LogMsg("ERROR: mDNSPosixWriteTCP - send %s", strerror(errno)); nsent = -1;
-        }
-    }
-    else
-    {
-        nsent = (long)result;
-    }
-    return nsent;
-}
-
-mDNSlocal void timevalFromPlatformTime(const mDNSs32 platformTimeNow, const mDNSs32 platformTime,
-                                       struct timeval *const outTv)
-{
-    struct timeval now;
-    gettimeofday(&now, mDNSNULL);
-
-    // Ensure that mDNSPlatformOneSecond * USEC_PER_SEC does not overflow for mDNSs32.
-    if (INT32_MAX / (mDNSs32)USEC_PER_SEC < mDNSPlatformOneSecond)
-    {
-        outTv->tv_sec = now.tv_sec;
-        outTv->tv_usec = now.tv_usec;
-        return;
-    }
-
-    if (platformTime - platformTimeNow > 0)
-    {
-        // The time is in the future.
-        const mDNSs32 remainingTime = platformTime - platformTimeNow;
-        const mDNSs32 remainingSeconds = remainingTime / mDNSPlatformOneSecond;
-        const mDNSs32 remainingMicroSeconds = (remainingTime % mDNSPlatformOneSecond) * (mDNSs32)USEC_PER_SEC / mDNSPlatformOneSecond;
-
-        outTv->tv_sec = now.tv_sec + remainingSeconds + ((now.tv_usec + remainingMicroSeconds) / (mDNSs32)USEC_PER_SEC);
-        outTv->tv_usec = ((now.tv_usec + remainingMicroSeconds) % (mDNSs32)USEC_PER_SEC);
-    }
-    else
-    {
-        // The time is in the past.
-        const mDNSs32 passedTime = platformTimeNow - platformTime;
-        const mDNSs32 passedSeconds = passedTime / mDNSPlatformOneSecond;
-        const mDNSs32 passedMicroSeconds = (passedTime % mDNSPlatformOneSecond) * (mDNSs32)USEC_PER_SEC / mDNSPlatformOneSecond;
-
-        outTv->tv_sec = now.tv_sec - passedSeconds - (passedMicroSeconds > now.tv_usec ? 1 : 0);
-        outTv->tv_usec = (passedMicroSeconds > now.tv_usec ? (mDNSs32)USEC_PER_SEC : 0) + now.tv_usec - passedMicroSeconds;
-    }
-}
-
-mDNSlocal void getLocalTimestampFromTimeval(const struct timeval *const tv,
-                                            char *const outBuffer, const mDNSu32 bufferLen)
-{
-    struct tm localTime;
-    char dateTimeStr[20]; // 1900-01-01 00:00:00\0
-    char timeZoneStr[6]; // -0000\0
-
-    localtime_r(&tv->tv_sec, &localTime);
-
-    // Get formatted date and time.
-    strftime(dateTimeStr, sizeof(dateTimeStr), "%F %T", &localTime);
-    // Get formatted time zone offset.
-    strftime(timeZoneStr, sizeof(timeZoneStr), "%z", &localTime);
-
-    // Construct the final timestamp with the milliseconds.
-    snprintf(outBuffer, bufferLen, "%s.%03u%s", dateTimeStr, (mDNSs32)tv->tv_usec / (mDNSs32)USEC_PER_MSEC,
-             timeZoneStr);
-}
-
-mDNSexport void getLocalTimestampFromPlatformTime(const mDNSs32 platformTimeNow, const mDNSs32 platformTime,
-                                                  char *const outBuffer, const mDNSu32 bufferLen)
-{
-    struct timeval tv;
-    timevalFromPlatformTime(platformTimeNow, platformTime, &tv);
-    getLocalTimestampFromTimeval(&tv, outBuffer, bufferLen);
-}
-
-mDNSexport void getLocalTimestampNow(char *const outBuffer, const mDNSu32 bufferLen)
-{
-    struct timeval now;
-    gettimeofday(&now, mDNSNULL);
-    getLocalTimestampFromTimeval(&now, outBuffer, bufferLen);
-}
diff --git a/mDNSShared/PlatformCommon.h b/mDNSShared/PlatformCommon.h
deleted file mode 100644
index 05059ca..0000000
--- a/mDNSShared/PlatformCommon.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
- *
- * Copyright (c) 2004 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.
- */
-
-#ifndef __PLATFORM_COMMON_H
-#define __PLATFORM_COMMON_H
-
-#ifndef NSEC_PER_SEC
-    #define NSEC_PER_SEC 1000000000ull
-#endif
-#ifndef USEC_PER_SEC
-    #define USEC_PER_SEC 1000000ull
-#endif
-#ifndef NSEC_PER_USEC
-    #define NSEC_PER_USEC 1000ull
-#endif
-#ifndef NSEC_PER_MSEC
-    #define NSEC_PER_MSEC 1000000ull
-#endif
-#ifndef USEC_PER_MSEC
-    #define USEC_PER_MSEC (NSEC_PER_MSEC / NSEC_PER_USEC)
-#endif
-
-extern void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename,
-										 domainname *const hostname, domainname *const domain,
-										 mDNSBool *DomainDiscoveryDisabled);
-extern mDNSBool mDNSPosixTCPSocketSetup(int *fd, mDNSAddr_Type addrType, mDNSIPPort *port, mDNSIPPort *outTcpPort);
-extern TCPSocket *mDNSPosixDoTCPListenCallback(int fd, mDNSAddr_Type addressType, TCPSocketFlags socketFlags,
-                     TCPAcceptedCallback callback, void *context);
-extern mDNSBool mDNSPosixTCPListen(int *fd, mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
-                   mDNSBool reuseAddr, int queueLength);
-extern long mDNSPosixReadTCP(int fd, void *buf, unsigned long buflen, mDNSBool *closed);
-extern long mDNSPosixWriteTCP(int fd, const char *msg, unsigned long len);
-#endif
diff --git a/mDNSShared/discover_resolver.c b/mDNSShared/discover_resolver.c
deleted file mode 100644
index bd5f83b..0000000
--- a/mDNSShared/discover_resolver.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains code to let mDNSResponder set up the resolver for
- * the automatic browsing domain learned from "lb._dns-sd._udp.local PTR"
- * query. To setup the resolver, it will get the NS record for the domain
- * and the A/AAAA record for the resolver name in the NS record rdata.
- * Once it knows about resolver's address, it will set the resolver with
- * configuration change to let mDNSResponder add it as a regular DNS resolver.
- */
-
-#include "mDNSFeatures.h" // for MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include <stdio.h>
-#include <mdns/private.h>
-#include "mDNSEmbeddedAPI.h"
-#include "mdns_strict.h"
-#include "uds_daemon.h"
-#include "bsd_queue.h"			// For SLIST.
-#include "discover_resolver.h"
-#include "tls-keychain.h"		// For init_tls_cert().
-#include "uDNS.h"				// For mDNS_StartQuery_internal() and mDNS_StopQuery_internal().
-
-
-#include "DNSCommon.h"			// For mDNS_Lock() and mDNS_Unlock().
-
-// for require_*
-#if defined(__APPLE__)
-	#include <AssertMacros.h>
-#elif defined(POSIX_BUILD)
-	#include "DebugServices.h"
-#else
-	#ifndef require
-		#define require(assertion, exception_label)					\
-			do {													\
-				if (!(assertion)) {									\
-					goto exception_label;							\
-				}													\
-			} while (false)
-	#endif // #ifndef require
-
-	#ifndef require_action
-		#define require_action(assertion, exception_label, action)	\
-			do {													\
-				if (!(assertion)) {									\
-					{												\
-						action;										\
-					}												\
-					goto exception_label;							\
-				}													\
-			} while (false)
-	#endif // #ifndef require_action
-#endif
-
-//======================================================================================================================
-// MARK: - Macros
-
-// Retain and release macros that are used to do reference counting for the discover_resolver_t object.
-#define DISCOVER_RESOLVER_RETAIN(OBJ)															\
-	do {																						\
-		(OBJ)->ref_count++;																		\
-		LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "discover_resolver_t retained "	\
-			"- ref count after retaining: %u.", (OBJ)->ref_count); 								\
-	} while (false)
-
-#define DISCOVER_RESOLVER_RELEASE(OBJ)															\
-	do {																						\
-		(OBJ)->ref_count--;																		\
-		LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "discover_resolver_t released "	\
-			"- ref count after releasing: %u.", (OBJ)->ref_count); 								\
-		if ((OBJ)->ref_count == 0) {															\
-			_MDNS_STRICT_DISPOSE_TEMPLATE((OBJ), (OBJ)->finalizer);								\
-		}																						\
-	} while (false)
-
-//======================================================================================================================
-// MARK: - Structures
-
-// the addresse of the discovered resolver get by resolving the resolver's name
-typedef struct resolver_address resolver_address_t;
-struct resolver_address {
-	mDNSAddr addr;
-	resolver_address_t * NULLABLE next;
-};
-
-// the name of the discovered resolver for the given domain.
-typedef struct discover_resolver_name discover_resolver_name_t;
-struct discover_resolver_name {
-	domainname resolver_name; // the discovered resolver name for the given domain
-	mDNSInterfaceID NULLABLE interface_id; // the interface id where the response was received
-	DNSQuestion ipv4_question; // used to query for IPv4 address of the resolver name
-	DNSQuestion ipv6_question; // used to query for IPv6 address of the resolver name
-
-	resolver_address_t * NULLABLE addresses; // linked list of all addresses for the resolver name
-	discover_resolver_name_t * NULLABLE next;
-};
-
-// the context of resolver discovery.
-typedef struct discover_resolver_context discover_resolver_context_t;
-struct discover_resolver_context {
-	DNSQuestion ns_question; // used to query for the resolver name for the given domain
-	discover_resolver_name_t * NULLABLE resolver_names; // linked list of all resolver names for the given domain
-};
-
-// This object is used by the caller to start or stop the resolver discovery.
-typedef struct discover_resolver discover_resolver_t;
-typedef void (* discover_resolver_finalizer_t)(discover_resolver_t * NULLABLE discover_resolver);
-struct discover_resolver {
-	domainname domain; // The domain that is used to discover the local DNS resolver.
-	discover_resolver_context_t * NULLABLE context;
-	// The finalizer that will be called to invalidate any ongoing activity and free the memory associated with this
-	// object, when the reference count becomes 0.
-	discover_resolver_finalizer_t NONNULL finalizer;
-	uint32_t ref_count;
-};
-
-// The single-linked node type that contains discover_resolver_t.
-typedef struct discover_resolver_node discover_resolver_node_t;
-struct discover_resolver_node {
-	SLIST_ENTRY(discover_resolver_node) __entries;
-	discover_resolver_t * NULLABLE discover_resolver;
-};
-
-// The single-linked list that contains multiple discover_resolver_t objects.
-typedef struct discover_resolver_slist discover_resolver_slist_t;
-SLIST_HEAD(discover_resolver_slist, discover_resolver_node);
-
-//======================================================================================================================
-// MARK: - Globals
-
-extern mDNS mDNSStorage;
-static discover_resolver_slist_t * g_discover_resolvers = NULL;
-
-//======================================================================================================================
-// MARK: - Forward Declarations
-
-discover_resolver_t *
-discover_resolver_create(const domainname * NONNULL domain);
-
-static void
-discover_resolver_finalize(discover_resolver_t * NULLABLE discover_resolver);
-#define MDNS_DISPOSE_DISCOVER_RESOLVER(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, discover_resolver_finalize)
-
-static discover_resolver_context_t *
-discover_resolver_context_create(void);
-
-static void
-discover_resolver_context_dispose(discover_resolver_context_t * NULLABLE context);
-#define MDNS_DISPOSE_DISCOVER_RESOLVER_CONTEXT(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, discover_resolver_context_dispose)
-
-static bool
-discover_resolver_start(discover_resolver_context_t * NULLABLE context, const domainname * NONNULL domain);
-
-void
-discover_resolver_stop(discover_resolver_context_t * NULLABLE context);
-
-//======================================================================================================================
-// MARK: - Functions
-
-// discover_resolver_slist_t
-
-static discover_resolver_slist_t * NULLABLE
-discover_resolver_slist_create(void)
-{
-	discover_resolver_slist_t * const me = mdns_calloc(1, sizeof(*me));
-	require(me != NULL, exit);
-
-	SLIST_INIT(me);
-
-exit:
-	return me;
-}
-
-//======================================================================================================================
-
-static discover_resolver_node_t *
-discover_resolver_slist_add_front(discover_resolver_slist_t * const NONNULL me,
-								  discover_resolver_t * const NONNULL discover_resolver)
-{
-	discover_resolver_node_t * const n = mdns_calloc(1, sizeof(*n));
-	require(n != NULL, exit);
-
-	n->discover_resolver = discover_resolver;
-	SLIST_INSERT_HEAD(me, n, __entries);
-
-exit:
-	return n;
-}
-
-//======================================================================================================================
-
-static bool
-discover_resolver_slist_empty(const discover_resolver_slist_t * const NONNULL me)
-{
-	return SLIST_EMPTY(me);
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_slist_dispose(discover_resolver_slist_t * const NONNULL me)
-{
-	discover_resolver_node_t * n;
-
-	while (!SLIST_EMPTY(me)) {
-		n = SLIST_FIRST(me);
-		SLIST_REMOVE_HEAD(me, __entries);
-		mdns_free(n);
-	}
-
-	discover_resolver_slist_t * temp_me = me;
-	mdns_free(temp_me);
-}
-#define MDNS_DISPOSE_DISCOVER_RESOLVER_SLIST(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, discover_resolver_slist_dispose)
-
-//======================================================================================================================
-
-// resolver_address_t
-
-static resolver_address_t *
-resolver_address_create(const void * const NONNULL addr_data, mDNSAddr_Type addr_type)
-{
-	resolver_address_t * resolver_address = NULL;
-
-	require(addr_type == mDNSAddrType_IPv4|| addr_type == mDNSAddrType_IPv6, exit);
-
-	resolver_address = mdns_calloc(1, sizeof(*resolver_address));
-	require(resolver_address != NULL, exit);
-
-	if (addr_type == mDNSAddrType_IPv4) {
-		memcpy(&resolver_address->addr.ip.v4, addr_data, sizeof(resolver_address->addr.ip.v4));
-	} else { // sa_family == mDNSAddrType_IPv6
-		memcpy(&resolver_address->addr.ip.v6, addr_data, sizeof(resolver_address->addr.ip.v6));
-	}
-
-	resolver_address->addr.type = addr_type;
-
-exit:
-	return resolver_address;
-}
-
-//======================================================================================================================
-
-static void
-resolver_address_delete(resolver_address_t * NONNULL to_be_deleted)
-{
-	resolver_address_t * temp = to_be_deleted;
-	mdns_free(temp);
-}
-
-//======================================================================================================================
-
-static resolver_address_t *
-resolver_addresses_add(const void * const NONNULL addr_data, const mDNSAddr_Type addr_type,
-	resolver_address_t * NULLABLE * const NONNULL out_addresses)
-{
-	resolver_address_t * resolver_address = resolver_address_create(addr_data, addr_type);
-	require(resolver_address != NULL, exit);
-
-	if (*out_addresses != NULL) {
-		resolver_address->next = *out_addresses;
-	}
-	*out_addresses = resolver_address;
-
-exit:
-	return resolver_address;
-}
-
-//======================================================================================================================
-
-static bool
-resolver_addresses_remove(const void * const NONNULL addr_data, mDNSAddr_Type addr_type,
-	resolver_address_t * NULLABLE * const NONNULL out_addresses)
-{
-	bool succeeded;
-
-	require_action(addr_type == mDNSAddrType_IPv4 || addr_type == mDNSAddrType_IPv6, exit, succeeded = false);
-
-	resolver_address_t * prev = NULL;
-	resolver_address_t * current = NULL;
-	resolver_address_t * next;
-
-	for (current = *out_addresses; current != NULL; current = next) {
-		bool found = false;
-		next = current->next;
-		if (current->addr.type != addr_type) {
-			continue;
-		}
-		if (addr_type == mDNSAddrType_IPv4) {
-			found = (memcmp(&current->addr.ip.v4, addr_data, sizeof(current->addr.ip.v4)) == 0);
-		} else { // sa_family == AF_INET6
-			found = (memcmp(&current->addr.ip.v6, addr_data, sizeof(current->addr.ip.v6)) == 0);
-		}
-		if (found) {
-			break;
-		}
-		prev = current;
-	}
-
-	require_action(current != NULL, exit, succeeded = false);
-
-	if (prev != NULL) {
-		prev->next = current->next;
-	} else {
-		*out_addresses = current->next;
-	}
-
-	resolver_address_delete(current);
-
-	succeeded = true;
-exit:
-	return succeeded;
-}
-
-//======================================================================================================================
-
-static void
-resolver_addresses_remove_all(resolver_address_t * const NONNULL addresses)
-{
-	resolver_address_t * current, * next;
-	for (current = addresses; current != NULL; current = next) {
-		next = current->next;
-		resolver_address_delete(current);
-	}
-}
-
-//======================================================================================================================
-
-static resolver_address_t *
-resolver_addresses_find(const void * const NONNULL addr_data, const mDNSAddr_Type addr_type,
-	resolver_address_t * const addresses)
-{
-	resolver_address_t * current = NULL;
-
-	require(addr_type == mDNSAddrType_IPv4 || addr_type == mDNSAddrType_IPv6, exit);
-
-	for (current = addresses; current != NULL; current = current->next) {
-		bool found = false;
-		if (current->addr.type != mDNSAddrType_IPv6) {
-			continue;
-		}
-		if (addr_type == mDNSAddrType_IPv4) {
-			found = (memcmp(&current->addr.ip.v4, addr_data, sizeof(current->addr.ip.v4)) == 0);
-		} else { // sa_family == AF_INET6
-			found = (memcmp(&current->addr.ip.v6, addr_data, sizeof(current->addr.ip.v6)) == 0);
-		}
-		if (found) {
-			break;
-		}
-	}
-
-exit:
-	return current;
-}
-
-//======================================================================================================================
-// discover_resolver_name_t
-
-static discover_resolver_name_t *
-discover_resolver_name_create(const domainname * const NONNULL resolver_name, const mDNSInterfaceID interface_id)
-{
-	bool succeeded;
-	discover_resolver_name_t * resolver = NULL;
-
-	resolver = mdns_calloc(1, sizeof(*resolver));
-	require_action(resolver != NULL, exit, succeeded = false);
-
-	AssignDomainName(&resolver->resolver_name, resolver_name);
-	resolver->interface_id = interface_id;
-
-	succeeded = true;
-exit:
-	if (!succeeded) {
-		mdns_free(resolver);
-	}
-	return resolver;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_name_delete(discover_resolver_name_t * NONNULL to_be_deleted)
-{
-	if (to_be_deleted->addresses != NULL) {
-		resolver_addresses_remove_all(to_be_deleted->addresses);
-	}
-	discover_resolver_name_t * NULLABLE temp_to_be_deleted = to_be_deleted;
-	mdns_free(temp_to_be_deleted);
-}
-
-//======================================================================================================================
-
-static discover_resolver_name_t *
-discover_resolver_name_add(const domainname * const name, const mDNSInterfaceID interface_id,
-		discover_resolver_name_t * NULLABLE * const NONNULL out_resolver_names)
-{
-	bool succeeded;
-	discover_resolver_name_t * new_resolver_name = NULL;
-
-	new_resolver_name = discover_resolver_name_create(name, interface_id);
-	require_action(new_resolver_name != NULL, exit, succeeded = false);
-
-	memset(&new_resolver_name->ipv4_question, 0, sizeof(new_resolver_name->ipv4_question));
-	memset(&new_resolver_name->ipv6_question, 0, sizeof(new_resolver_name->ipv6_question));
-
-	if (*out_resolver_names != NULL) {
-		new_resolver_name->next = *out_resolver_names;
-	}
-	*out_resolver_names = new_resolver_name;
-
-	succeeded = true;
-exit:
-	if (!succeeded) {
-		if (new_resolver_name != NULL) {
-			discover_resolver_name_delete(new_resolver_name);
-		}
-	}
-	return new_resolver_name;
-}
-
-//======================================================================================================================
-
-static bool
-discover_resolver_name_remove(const domainname * const resolver_name, const mDNSInterfaceID interface_id,
-	discover_resolver_name_t * NULLABLE * const NONNULL out_resolver_names)
-{
-	bool succeeded;
-	discover_resolver_name_t * prev = NULL;
-	discover_resolver_name_t * current, * next;
-
-	for (current = *out_resolver_names; current != NULL; current = next) {
-		next = current->next;
-		if (SameDomainName(&current->resolver_name, resolver_name) && current->interface_id == interface_id) {
-			break;
-		}
-		prev = current;
-	}
-
-	require_action(current != NULL, exit, succeeded = false);
-
-	if (prev != NULL) {
-		prev->next = current->next;
-	} else {
-		*out_resolver_names = current->next;
-	}
-	discover_resolver_name_delete(current);
-
-	succeeded = true;
-exit:
-	return succeeded;
-}
-
-//======================================================================================================================
-
-static discover_resolver_name_t *
-discover_resolver_name_find(const domainname * const name, mDNSInterfaceID interface_id,
-	discover_resolver_name_t * const NULLABLE resolver_names)
-{
-	discover_resolver_name_t * resolver_name = NULL;
-
-	for (resolver_name = resolver_names; resolver_name != NULL; resolver_name = resolver_name->next) {
-		if (SameDomainName(&resolver_name->resolver_name, name) && resolver_name->interface_id == interface_id) {
-			break;
-		}
-	}
-
-	return resolver_name;
-}
-
-//======================================================================================================================
-
-bool
-resolver_discovery_add(const domainname * const NONNULL domain_to_discover, const bool grab_mdns_lock)
-{
-	bool succeeded;
-	discover_resolver_node_t * np;
-	discover_resolver_t * discover_resolver_to_retain = NULL;
-
-	// The list has not been initialized.
-	if (g_discover_resolvers == NULL) {
-		g_discover_resolvers = discover_resolver_slist_create();
-		require_action(g_discover_resolvers != NULL, exit, succeeded = false);
-	}
-
-	// Looking for the existing resolver discovery.
-	SLIST_FOREACH(np, g_discover_resolvers, __entries) {
-		if (!SameDomainName(&np->discover_resolver->domain, domain_to_discover)) {
-			continue;
-		}
-		discover_resolver_to_retain = np->discover_resolver;
-		break;
-	}
-
-	// Retain the existing one if exists.
-	if (discover_resolver_to_retain != NULL) {
-		DISCOVER_RESOLVER_RETAIN(discover_resolver_to_retain);
-		discover_resolver_to_retain = NULL;
-		succeeded = true;
-		goto exit;
-	}
-
-	// Or create and start a new resolver discovery for the given domain.
-	discover_resolver_to_retain = discover_resolver_create(domain_to_discover);
-	require_action(discover_resolver_to_retain != NULL, exit, succeeded = false);
-
-	if (grab_mdns_lock) {
-		mDNS_Lock(&mDNSStorage);
-	}
-	succeeded = discover_resolver_start(discover_resolver_to_retain->context, domain_to_discover);
-	if (grab_mdns_lock) {
-		mDNS_Unlock(&mDNSStorage);
-	}
-	require(succeeded, exit);
-
-	// Add the new one to the list.
-	np = discover_resolver_slist_add_front(g_discover_resolvers, discover_resolver_to_retain);
-	require_action(np != NULL, exit, succeeded = false);
-
-	discover_resolver_to_retain = NULL;
-
-exit:
-	if (discover_resolver_to_retain != NULL) {
-		DISCOVER_RESOLVER_RELEASE(discover_resolver_to_retain);
-	}
-
-	return succeeded;
-}
-
-//======================================================================================================================
-
-bool
-resolver_discovery_remove(const domainname * const NONNULL domain_to_discover, const bool grab_mdns_lock)
-{
-	bool succeeded = false;
-	discover_resolver_node_t * np, * np_temp;
-
-	require_action(g_discover_resolvers != NULL, exit, LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT,
-		"Trying to stop a domain resolver discovery that does not exist - domain: " PRI_DM_NAME ".",
-		DM_NAME_PARAM(domain_to_discover)));
-
-	SLIST_FOREACH_SAFE(np, g_discover_resolvers, __entries, np_temp) {
-		if (!SameDomainName(&np->discover_resolver->domain, domain_to_discover)) {
-			continue;
-		}
-
-		if (grab_mdns_lock) {
-			mDNS_Lock(&mDNSStorage);
-		}
-		DISCOVER_RESOLVER_RELEASE(np->discover_resolver);
-		if (grab_mdns_lock) {
-			mDNS_Unlock(&mDNSStorage);
-		}
-
-		// If np->discover_resolver is finalized by DISCOVER_RESOLVER_RELEASE() above, np->discover_resolver will be
-		// set to NULL. If so, delete this node from the list.
-		if (np->discover_resolver == NULL) {
-			SLIST_REMOVE(g_discover_resolvers, np, discover_resolver_node, __entries);
-			mdns_free(np);
-		}
-
-		succeeded = true;
-		break;
-	}
-
-	// If the entire list is now empty, delete the list.
-	if (discover_resolver_slist_empty(g_discover_resolvers)) {
-		MDNS_DISPOSE_DISCOVER_RESOLVER_SLIST(g_discover_resolvers);
-	}
-
-exit:
-	return succeeded;
-}
-
-//======================================================================================================================
-
-bool
-dns_question_requires_resolver_discovery(const DNSQuestion * NONNULL q, const domainname ** const out_domain)
-{
-	// Currently, we only support discovering local resolvers for "openthread.thread.home.arpa."
-	// We only do the discovery when the question is not forced to use multicast DNS, because mDNS does not use resolver.
-	if (!q->ForceMCast && IsSubdomain(&q->qname, THREAD_DOMAIN_NAME)) {
-		*out_domain = THREAD_DOMAIN_NAME;
-		return true;
-	} else {
-		*out_domain = NULL;
-		return false;
-	}
-}
-
-//======================================================================================================================
-
-discover_resolver_t * NULLABLE
-discover_resolver_create(const domainname * const NONNULL domain)
-{
-	discover_resolver_t * returned_discover_resolver = NULL;
-	discover_resolver_context_t * discover_resolver_context = NULL;
-
-	discover_resolver_t * discover_resolver = mdns_calloc(1, sizeof(*discover_resolver));
-	require(discover_resolver != NULL, exit);
-
-	AssignDomainName(&discover_resolver->domain, domain);
-
-	discover_resolver_context = discover_resolver_context_create();
-	require(discover_resolver_context != NULL, exit);
-
-	discover_resolver->context = discover_resolver_context;
-	discover_resolver_context = NULL;
-
-	discover_resolver->finalizer = discover_resolver_finalize;
-	discover_resolver->ref_count = 1;
-
-	returned_discover_resolver = discover_resolver;
-	discover_resolver = NULL;
-exit:
-	MDNS_DISPOSE_DISCOVER_RESOLVER_CONTEXT(discover_resolver_context);
-	MDNS_DISPOSE_DISCOVER_RESOLVER(discover_resolver);
-	return returned_discover_resolver;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_finalize(discover_resolver_t * const NULLABLE discover_resolver)
-{
-	if (discover_resolver == NULL) {
-		return;
-	}
-
-	LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Stopping the resolver discovery for domain - "
-		"domain: " PRI_DM_NAME, DM_NAME_PARAM(&discover_resolver->domain));
-
-	if (discover_resolver->context != NULL) {
-		discover_resolver_stop(discover_resolver->context);
-		MDNS_DISPOSE_DISCOVER_RESOLVER_CONTEXT(discover_resolver->context);
-	}
-
-	discover_resolver_t * temp_discover_resolver = discover_resolver;
-	mdns_free(temp_discover_resolver);
-}
-
-//======================================================================================================================
-// discover_resolver_context_t
-
-static discover_resolver_context_t *
-discover_resolver_context_create(void)
-{
-	discover_resolver_context_t * const context = mdns_calloc(1, sizeof(*context));
-
-	memset(&context->ns_question, 0, sizeof(context->ns_question));
-	context->resolver_names = NULL;
-
-	return context;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_context_dispose(discover_resolver_context_t * const NULLABLE context)
-{
-	if (context == NULL) {
-		return;
-	}
-
-	if (context->resolver_names != NULL) {
-		discover_resolver_name_t * current, * next;
-		for (current = context->resolver_names; current != NULL; current = next) {
-			next = current->next;
-			discover_resolver_name_delete(current);
-		}
-		context->resolver_names = NULL;
-	}
-	discover_resolver_context_t * temp_context = context;
-	mdns_free(temp_context);
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_setup_question(DNSQuestion * const NONNULL q, mDNSInterfaceID interface_id,
-	const domainname * const NONNULL q_name, uint16_t q_type, bool force_multicast,
-	mDNSQuestionCallback * const NULLABLE callback, void * const NONNULL context)
-{
-	q->InterfaceID = interface_id;
-	q->flags = force_multicast ? kDNSServiceFlagsForceMulticast : 0;
-	AssignDomainName(&q->qname, q_name);
-	q->qtype = q_type;
-	q->qclass = kDNSClass_IN;
-	q->LongLived = false;
-	q->ExpectUnique = false;
-	q->ForceMCast = force_multicast;
-	q->ReturnIntermed = false;
-	q->SuppressUnusable = false;
-	q->AppendSearchDomains = false;
-	q->TimeoutQuestion = 0;
-	q->WakeOnResolve = 0;
-	q->UseBackgroundTraffic = false;
-	q->pid = mDNSPlatformGetPID();
-	q->euid = 0;
-	q->QuestionCallback = callback;
-	q->QuestionContext = context;
-}
-
-
-//======================================================================================================================
-
-static bool
-native_dns_service_register(const domainname * const NONNULL resolver_domain,
-	const resolver_address_t * const NONNULL addrs, const uint32_t interface_index,
-	const bool reinit_dns_service_definition, discover_resolver_name_t * const NONNULL out_resolver_name)
-{
-	(void)resolver_domain;
-	(void)addrs;
-	(void)interface_index;
-	(void)reinit_dns_service_definition;
-	(void)out_resolver_name;
-	return false;
-}
-
-//======================================================================================================================
-
-static bool
-native_dns_service_deregister(discover_resolver_name_t * const NONNULL resolver_name)
-{
-	(void) resolver_name;
-	return false;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_addr_query_callback(mDNS * const NONNULL m, DNSQuestion * const NONNULL q,
-	const ResourceRecord * const NONNULL answer, const QC_result change_event)
-{
-	bool succeeded;
-	bool new_address_created = false;
-	discover_resolver_context_t * context = q->QuestionContext;
-	discover_resolver_name_t * resolver_name = NULL;
-	const void * const addr_data = answer->rdata->u.data;
-	const mDNSAddr_Type addr_type = answer->rrtype == kDNSType_A ? mDNSAddrType_IPv4 : mDNSAddrType_IPv6;
-	const domainname * const browsing_domain = &context->ns_question.qname;
-	mDNS_Lock(m);
-	const char * const if_name = InterfaceNameForID(m, q->InterfaceID);
-	const uint32_t if_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, q->InterfaceID, mDNSfalse);
-	mDNS_Unlock(m);
-	const char * action = NULL;
-	mDNSAddr addr_changed;
-
-	require_action(change_event == QC_add ||change_event == QC_rmv, exit, succeeded = false);
-	require_action(answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA, exit, succeeded = false);
-	require_action(q->InterfaceID == answer->InterfaceID, exit, succeeded = false);
-
-	// Find the corresponding discover_resolver_name_t that starts this address query.
-	resolver_name = discover_resolver_name_find(&q->qname, q->InterfaceID, context->resolver_names);
-	require_action(resolver_name, exit, succeeded = false);
-
-	// Try to find if there is existing address in the list.
-	resolver_address_t * resolver_addr = resolver_addresses_find(addr_data, addr_type, resolver_name->addresses);
-
-	if (change_event == QC_add) {
-		// Should have no duplicate addresses for the QC_add event.
-		require_action(resolver_addr == NULL, exit, succeeded = false);
-
-		if (resolver_name->addresses == NULL) {
-			action = "newly added";
-		} else {
-			action = "added into the existing one";
-		}
-
-		// Add the address into list.
-		resolver_addr = resolver_addresses_add(addr_data, addr_type, &resolver_name->addresses);
-		require_action(resolver_addr != NULL, exit, succeeded = false);
-		new_address_created = true;
-		memcpy(&addr_changed, &resolver_addr->addr, sizeof(addr_changed));
-
-		// Add new DNS configuration.
-		succeeded = native_dns_service_register(browsing_domain, resolver_addr, if_index, false, resolver_name);
-		require(succeeded, exit);
-
-	} else {
-		// Should be the added address in the list and should not be removed twice.
-		require_action(resolver_addr != NULL, exit, succeeded = false);
-		// Should already have configured resolver.
-
-		memcpy(&addr_changed, &resolver_addr->addr, sizeof(addr_changed));
-
-		// Remove the address from the list.
-		succeeded = resolver_addresses_remove(addr_data, addr_type, &resolver_name->addresses);
-		require(succeeded, exit);
-
-		if (resolver_name->addresses != NULL) {
-			succeeded = native_dns_service_register(browsing_domain, resolver_name->addresses, if_index, true,
-													resolver_name);
-			require(succeeded, exit);
-			action = "removed from the existing one";
-		} else {
-			succeeded = native_dns_service_deregister(resolver_name);
-			require(succeeded, exit);
-			action = "removed entirely";
-		}
-	}
-
-	LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[Q%u] Resolver " PUB_S " - "
-		"browsing domain: " PRI_DM_NAME ", resolver name: " PRI_DM_NAME ", address: " PRI_IP_ADDR
-		", interface: " PUB_S ".", mDNSVal16(q->TargetQID), action,
-		DM_NAME_PARAM(&context->ns_question.qname), DM_NAME_PARAM(&q->qname), &addr_changed, if_name);
-
-exit:
-	if (!succeeded) {
-		if (new_address_created) {
-			resolver_addresses_remove(addr_data, addr_type, &resolver_name->addresses);
-		}
-	}
-	return;
-}
-
-//======================================================================================================================
-
-static bool
-discover_resolver_start_addr_query(discover_resolver_context_t * const NONNULL context,
-	discover_resolver_name_t * const NONNULL resolver_name, const domainname * const name)
-{
-	bool succeeded;
-
-	DNSQuestion * const ipv4 = &resolver_name->ipv4_question;
-	DNSQuestion * const ipv6 = &resolver_name->ipv6_question;
-
-	// Send address queries as normal
-	discover_resolver_setup_question(ipv4, resolver_name->interface_id, name, kDNSType_A, false,
-		discover_resolver_addr_query_callback, context);
-	discover_resolver_setup_question(ipv6, resolver_name->interface_id, name, kDNSType_AAAA, false,
-		discover_resolver_addr_query_callback, context);
-
-	// discover_resolver_start_addr_query() is called as a callback, therefore, mDNSCore lock is not held.
-	// mDNS_StartQuery() must be used here instead of mDNS_StartQuery_internal().
-	mStatus mdns_err = mDNS_StartQuery(&mDNSStorage, ipv4);
-	require_action(mdns_err == mStatus_NoError, exit, succeeded = false);
-
-	mdns_err = mDNS_StartQuery(&mDNSStorage, ipv6);
-	require_action(mdns_err == mStatus_NoError, exit, succeeded = false);
-
-	LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Starting A/AAAA queries for resolver - name: " PRI_DM_NAME,
-		DM_NAME_PARAM(name));
-
-	succeeded = true;
-exit:
-	return succeeded;
-}
-
-static bool
-discover_resolver_stop_addr_query(discover_resolver_name_t * const NONNULL resolver_name)
-{
-	bool succeeded = true;
-
-	// Remove the DNS config added by the resolved addresses.
-	succeeded = native_dns_service_deregister(resolver_name);
-
-	// Stop the address queries.
-	// discover_resolver_stop_addr_query() is called with lock held, and the two mDNS_StopQuery_internal() below are
-	// used to stop the two queries started by mDNS_StartQuery() in discover_resolver_start_addr_query().
-	mStatus ipv4_err = mDNS_StopQuery_internal(&mDNSStorage, &resolver_name->ipv4_question);
-	mStatus ipv6_err = mDNS_StopQuery_internal(&mDNSStorage, &resolver_name->ipv6_question);
-	if (ipv4_err != mStatus_NoError || ipv6_err != mStatus_NoError) {
-		succeeded = false;
-	}
-
-	return succeeded;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_ns_query_callback(mDNS * const NONNULL UNUSED m, DNSQuestion * const NONNULL q,
-	const ResourceRecord * const NONNULL answer, const QC_result change_event)
-{
-	bool succeeded;
-	bool new_resolver_name_created = false;
-	discover_resolver_context_t * context = q->QuestionContext;
-	const mDNSInterfaceID if_id = answer->InterfaceID;
-	const char * const if_name = InterfaceNameForID(&mDNSStorage, if_id);
-
-	require_action(change_event == QC_add || change_event == QC_rmv, exit, succeeded = false);
-
-	if (if_id == mDNSInterface_LocalOnly) {
-		succeeded = true;
-		goto exit;
-	}
-
-	// Find out the corresponding discover_resolver_name_t for resolver name, if exists.
-	const domainname * const name = &answer->rdata->u.name;
-	discover_resolver_name_t * resolver_name = discover_resolver_name_find(name, if_id, context->resolver_names);
-
-	if (change_event == QC_add) {
-		// If there is existing discover_resolver_name_t, do not start duplicate query.
-		if (resolver_name != NULL) {
-			succeeded = true;
-			goto exit;
-		}
-
-		// Add current name into list.
-		resolver_name = discover_resolver_name_add(name, if_id, &context->resolver_names);
-		require_action(resolver_name != NULL, exit, succeeded = false);
-		new_resolver_name_created = true;
-
-		LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Name server found for the browsing domain - "
-			PRI_DM_NAME " -NS-> " PRI_DM_NAME ", interface: " PUB_S, DM_NAME_PARAM(&q->qname), DM_NAME_PARAM(name),
-			if_name ? if_name : "any");
-
-		// Start to resolve the resolver name.
-		succeeded = discover_resolver_start_addr_query(context, resolver_name, name);
-		require_action(succeeded, exit, false);
-	} else { // change_event == QC_rmv
-		// Should have the added discover_resolver_name_t
-		require_action(resolver_name != NULL, exit, succeeded = false);
-
-		LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Name server disappeared for the browsing domain - "
-			PRI_DM_NAME " -NS-> " PRI_DM_NAME ", interface: " PUB_S, DM_NAME_PARAM(&q->qname), DM_NAME_PARAM(name),
-			if_name ? if_name : "any");
-
-		// Stop all the address queries started by this resolver name.
-		// Since discover_resolver_ns_query_callback() is always called as a callback function without mDNS_Lock held,
-		// we need to grab the lock explicitly.
-		mDNS_Lock(&mDNSStorage);
-		discover_resolver_stop_addr_query(resolver_name);
-		mDNS_Unlock(&mDNSStorage);
-
-		// Remove the name from the list
-		discover_resolver_name_remove(name, if_id, &context->resolver_names);
-	}
-
-	succeeded = true;
-exit:
-	if (!succeeded) {
-		if (new_resolver_name_created) {
-			discover_resolver_name_remove(name, if_id, &context->resolver_names);
-		}
-	}
-	return;
-}
-
-//======================================================================================================================
-
-static bool
-discover_resolver_start_ns_query(discover_resolver_context_t * const NONNULL context,
-	const domainname * const NONNULL domain)
-{
-	bool succeeded;
-
-	// Start NS query with kDNSServiceFlagsForceMulticast.
-	DNSQuestion * const q = &context->ns_question;
-
-	discover_resolver_setup_question(q, mDNSInterface_Any, domain, kDNSType_NS, true,
-		discover_resolver_ns_query_callback, context);
-
-	LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Sending NS query to discover name server - "
-		"browsing domain: " PRI_DM_NAME, DM_NAME_PARAM(domain));
-
-	// discover_resolver_start_ns_query() is called with lock held, therefore, mDNS_StartQuery_internal() must be used
-	// here instead of mDNS_StartQuery().
-	mStatus err = mDNS_StartQuery_internal(&mDNSStorage, q);
-	require_action(err == mStatus_NoError, exit, succeeded = false);
-
-	succeeded = true;
-exit:
-	return succeeded;
-}
-
-//======================================================================================================================
-
-static void
-discover_resolver_stop_ns_query(discover_resolver_context_t * const NONNULL context)
-{
-	// Stop all address subqueries.
-	for (discover_resolver_name_t * current = context->resolver_names; current != NULL; current = current->next) {
-		discover_resolver_stop_addr_query(current);
-	}
-
-	// Stop the original NS query.
-	mDNS_StopQuery_internal(&mDNSStorage, &context->ns_question);
-}
-
-//======================================================================================================================
-
-static bool
-discover_resolver_start(discover_resolver_context_t * const NULLABLE context,
-	const domainname * const NONNULL domain)
-{
-	bool succeeded;
-	require_action(context != NULL, exit, succeeded = false);
-
-	LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Starting the resolver discovery for domain - "
-		"domain: " PRI_DM_NAME, DM_NAME_PARAM(domain));
-	// Start NS query with kDNSServiceFlagsForceMulticast to learn about the browsing domain with mDNS.
-	succeeded = discover_resolver_start_ns_query(context, domain);
-
-exit:
-	return succeeded;
-}
-
-//======================================================================================================================
-
-void
-discover_resolver_stop(discover_resolver_context_t * const NULLABLE context)
-{
-	if (context == NULL) {
-		return;
-	}
-	discover_resolver_stop_ns_query(context);
-}
-
-#else // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-// iso C requires a translation unit to contain at least one declaration
-typedef int __make_iso_c_happy_about_no_declaration;
-
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
diff --git a/mDNSShared/discover_resolver.h b/mDNSShared/discover_resolver.h
deleted file mode 100644
index 7ea5770..0000000
--- a/mDNSShared/discover_resolver.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2020-2022 Apple 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
- *
- *     https://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.
- *
- * This file contains the function declarations for discover_resolver.c,
- * which will be called by mDNSCore code to set up the automatic browsing
- * domain resolver.
- */
-
-#ifndef __RESOLVER_DISCOVER_H__
-#define __RESOLVER_DISCOVER_H__
-
-#include "mDNSFeatures.h" // for MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-#include "mdns_strict.h"
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include "mDNSEmbeddedAPI.h"
-#include <stdbool.h>
-#include "nullability.h"
-
-//======================================================================================================================
-// MARK: - Functions
-
-/*!
- *	@brief
- *		Start the local DNS resolver discovery for the domain specified, by using reference counting to add/retain the discovery process.
- *
- *	@param domain_to_discover
- *		The domain where the local DNS resolver should be discovered.
- *
- *	@param grab_mdns_lock
- *		The boolean value of whether to grab the mDNS_Lock when doing query-related operation.
- *
- *	@result
- *		True if the function succeeds, otherwise, false.
- *
- *	@discussion
- *		When <code>resolver_discovery_add</code> is called, the discovery is not necessarily started on behalf of the caller. The discovery may have been
- *		started earlier by other caller. In which case, the same discovery activity will be retained and reused for the current caller.
- */
-
-bool
-resolver_discovery_add(const domainname * NONNULL domain_to_discover, bool grab_mdns_lock);
-
-/*!
- *	@brief
- *		Stop the local DNS resolver discovery for the domain specified, by using reference counting to remove/release the discovery process.
- *
- *	@param domain_to_discover
- *		The domain where the local DNS resolver should be discovered.
- *
- *	@param grab_mdns_lock
- *		The boolean value of whether to grab the mDNS_Lock when doing query-related operation.
- *
- *	@result
- *		True if the function succeeds, otherwise, false.
- *
- *	@discussion
- *		When <code>resolver_discovery_remove</code> is called, the discovery is not necessarily stopped on behalf of the caller. The discovery may be still used
- *		by other callers. In which case, the discovery will not be stopped, instead, it will be removed/released with reference counting. The resolver discovery will
- *		not be stopped until the last caller of <code>resolver_discovery_add</code> calls <code>resolver_discovery_remove</code>.
- */
-
-bool
-resolver_discovery_remove(const domainname * NONNULL domain_to_discover, bool grab_mdns_lock);
-
-bool
-dns_question_requires_resolver_discovery(const DNSQuestion * NONNULL q, const domainname * NULLABLE * NONNULL out_domain);
-
-#endif // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-
-#endif /* __RESOLVER_DISCOVER_H__ */
diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h
deleted file mode 100644
index a1baf44..0000000
--- a/mDNSShared/dns_sd.h
+++ /dev/null
@@ -1,3482 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*! @header     DNS Service Discovery
- *
- * @discussion  This section describes the functions, callbacks, and data structures
- *              that make up the DNS Service Discovery API.
- *
- *              The DNS Service Discovery API is part of Bonjour, Apple's implementation
- *              of zero-configuration networking (ZEROCONF).
- *
- *              Bonjour allows you to register a network service, such as a
- *              printer or file server, so that it can be found by name or browsed
- *              for by service type and domain. Using Bonjour, applications can
- *              discover what services are available on the network, along with
- *              all the information -- such as name, IP address, and port --
- *              necessary to access a particular service.
- *
- *              In effect, Bonjour combines the functions of a local DNS server and
- *              AppleTalk. Bonjour allows applications to provide user-friendly printer
- *              and server browsing, among other things, over standard IP networks.
- *              This behavior is a result of combining protocols such as multicast and
- *              DNS to add new functionality to the network (such as multicast DNS).
- *
- *              Bonjour gives applications easy access to services over local IP
- *              networks without requiring the service or the application to support
- *              an AppleTalk or a Netbeui stack, and without requiring a DNS server
- *              for the local network.
- */
-
-/* _DNS_SD_H contains the API version number for this header file
- * The API version defined in this header file symbol allows for compile-time
- * checking, so that C code building with earlier versions of the header file
- * can avoid compile errors trying to use functions that aren't even defined
- * in those earlier versions. Similar checks may also be performed at run-time:
- *  => weak linking -- to avoid link failures if run with an earlier
- *     version of the library that's missing some desired symbol, or
- *  => DNSServiceGetProperty(DaemonVersion) -- to verify whether the running daemon
- *     ("system service" on Windows) meets some required minimum functionality level.
- */
-
-#ifndef _DNS_SD_H
-#if defined(DNS_SD_VERSION_NUMBER_OVERRIDE) && (DNS_SD_VERSION_NUMBER_OVERRIDE > 0)
-#define _DNS_SD_H DNS_SD_VERSION_NUMBER_OVERRIDE
-#else
-#define _DNS_SD_H 16610000
-#endif
-
-/* DNS-SD API version strings are of the form x[.y[.z]].
- * Version strings less than or equal to 1661 are encoded as (x * 10000) + (y * 100) + z, where 0 ≤ y,z ≤ 99.
- * Version strings greater than 1661 are encoded as (x * 1000000) + (y * 1000) + z, where 0 ≤ y,z ≤ 999.
- * Therefore, the greatest version number for the original encoding is 16610000.
- */
-#define DNS_SD_ORIGINAL_ENCODING_VERSION_NUMBER_MAX 16610000
-
-#if !defined(__BEGIN_DECLS)
-    #if defined(__cplusplus)
-        #define __BEGIN_DECLS               extern "C" {
-        #define __END_DECLS                     }
-    #else
-        #define __BEGIN_DECLS
-        #define __END_DECLS
-    #endif
-#endif
-
-__BEGIN_DECLS
-
-/* Set to 1 if libdispatch is supported
- * Note: May also be set by project and/or Makefile
- */
-#if defined(__APPLE__)
-#define _DNS_SD_LIBDISPATCH 1
-#else
-#define _DNS_SD_LIBDISPATCH 0
-#endif
-
-/* standard calling convention under Win32 is __stdcall */
-/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
-/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
-#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
-#define DNSSD_API __stdcall
-#else
-#define DNSSD_API
-#endif
-
-#if (defined(__GNUC__) && (__GNUC__ >= 4))
-#define DNSSD_EXPORT __attribute__((visibility("default")))
-#else
-#define DNSSD_EXPORT
-#endif
-
-#if defined(_WIN32)
-#include <winsock2.h>
-typedef SOCKET dnssd_sock_t;
-#else
-typedef int dnssd_sock_t;
-#endif
-
-/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
-#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
-#include <sys/types.h>
-
-/* Likewise, on Sun, standard integer types are in sys/types.h */
-#elif defined(__sun__)
-#include <sys/types.h>
-
-/* EFI does not have stdint.h, or anything else equivalent */
-#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
-#include "Tiano.h"
-#if !defined(_STDINT_H_)
-typedef UINT8 uint8_t;
-typedef INT8 int8_t;
-typedef UINT16 uint16_t;
-typedef INT16 int16_t;
-typedef UINT32 uint32_t;
-typedef INT32 int32_t;
-#endif
-/* Windows has its own differences */
-#elif defined(_WIN32)
-#include <windows.h>
-#define _UNUSED
-#ifndef _MSL_STDINT_H
-typedef UINT8 uint8_t;
-typedef INT8 int8_t;
-typedef UINT16 uint16_t;
-typedef INT16 int16_t;
-typedef UINT32 uint32_t;
-typedef INT32 int32_t;
-#endif
-
-/* All other Posix platforms use stdint.h */
-#else
-#include <stdint.h>
-#endif
-
-#if !defined(__has_extension)
-    #define __has_extension(X)              0
-#endif
-
-#if !defined(__has_feature)
-    #define __has_feature(X)                0
-#endif
-
-#if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || __has_extension(cxx_strong_enums)
-    #define DNS_SERVICE_FLAGS_ENUM          enum : uint32_t
-#else
-    #define DNS_SERVICE_FLAGS_ENUM          enum
-#endif
-
-#if _DNS_SD_LIBDISPATCH
-#include <dispatch/dispatch.h>
-#endif
-
-#ifndef DNS_SD_NULLABLE
-    #if __has_feature(nullability)
-        #define DNS_SD_NULLABLE             _Nullable
-        #define DNS_SD_NONNULL              _Nonnull
-    #else
-        #define DNS_SD_NULLABLE
-        #define DNS_SD_NONNULL
-    #endif
-#endif
-
-/* DNSServiceRef, DNSRecordRef
- *
- * Opaque internal data types.
- * Note: client is responsible for serializing access to these structures if
- * they are shared between concurrent threads.
- */
-
-typedef struct _DNSServiceRef_t *DNSServiceRef;
-typedef struct _DNSRecordRef_t *DNSRecordRef;
-typedef struct DNSServiceAttribute_s DNSServiceAttribute;
-typedef DNSServiceAttribute *DNSServiceAttributeRef;
-
-#if defined(__APPLE__)
-    #define DNS_SD_API_AVAILABLE(...)   API_AVAILABLE(__VA_ARGS__)
-#else
-    #define DNS_SD_API_AVAILABLE(...)   DNSSD_EXPORT
-#endif
-typedef enum
-{
-    kDNSServiceAAAAPolicyNone      = 0,
-    kDNSServiceAAAAPolicyFallback  = 1  // If AAAA record doesn't exist, query for A.
-} DNS_SD_API_AVAILABLE(macos(12.0), ios(15.0), tvos(15.0), watchos(8.0)) DNSServiceAAAAPolicy;
-
-DNSSD_EXPORT
-extern const DNSServiceAttribute kDNSServiceAttributeAAAAFallback;
-
-struct sockaddr;
-
-/*! @enum General flags
- * Most DNS-SD API functions and callbacks include a DNSServiceFlags parameter.
- * As a general rule, any given bit in the 32-bit flags field has a specific fixed meaning,
- * regardless of the function or callback being used. For any given function or callback,
- * typically only a subset of the possible flags are meaningful, and all others should be zero.
- * The discussion section for each API call describes which flags are valid for that call
- * and callback. In some cases, for a particular call, it may be that no flags are currently
- * defined, in which case the DNSServiceFlags parameter exists purely to allow future expansion.
- * In all cases, developers should expect that in future releases, it is possible that new flag
- * values will be defined, and write code with this in mind. For example, code that tests
- *     if (flags == kDNSServiceFlagsAdd) ...
- * will fail if, in a future release, another bit in the 32-bit flags field is also set.
- * The reliable way to test whether a particular bit is set is not with an equality test,
- * but with a bitwise mask:
- *     if (flags & kDNSServiceFlagsAdd) ...
- * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set)
- * EITHER only as an input to one of the DNSService*() APIs OR only as an output
- * (provide status) through any of the callbacks used. For example, kDNSServiceFlagsAdd
- * can be set only as an output in the callback, whereas the kDNSServiceFlagsIncludeP2P
- * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate
- * defined in enum below.
- */
-
-DNS_SERVICE_FLAGS_ENUM
-{
-    kDNSServiceFlagsMoreComing          = 0x1,
-    /* MoreComing indicates to a callback that at least one more result is
-     * queued and will be delivered following immediately after this one.
-     * When the MoreComing flag is set, applications should not immediately
-     * update their UI, because this can result in a great deal of ugly flickering
-     * on the screen, and can waste a great deal of CPU time repeatedly updating
-     * the screen with content that is then immediately erased, over and over.
-     * Applications should wait until MoreComing is not set, and then
-     * update their UI when no more changes are imminent.
-     * When MoreComing is not set, that doesn't mean there will be no more
-     * answers EVER, just that there are no more answers immediately
-     * available right now at this instant. If more answers become available
-     * in the future they will be delivered as usual.
-     */
-
-    kDNSServiceFlagsQueueRequest       = 0x1,
-    /* kDNSServiceFlagsQueueRequest indicates that the request will be queued;
-     * otherwise the request is sent immediately.
-     * All the queued requests will be sent to server in scatter/gather IO when function
-     * DNSServiceSendQueuedRequests is called.
-     * This flag is an input value to functions generate requests to server such as
-     * DNSServiceRegisterRecord(), which is why we can use the same value as
-     * kDNSServiceFlagsMoreComing, which is an output flag for various client callbacks.
-     */
-
-    kDNSServiceFlagsAutoTrigger        = 0x1,
-    /* Valid for browses using kDNSServiceInterfaceIndexAny.
-     * Will auto trigger the browse over AWDL as well once the service is discovered
-     * over BLE.
-     * This flag is an input value to DNSServiceBrowse(), which is why we can
-     * use the same value as kDNSServiceFlagsMoreComing, which is an output flag
-     * for various client callbacks.
-    */
-
-    kDNSServiceFlagsAdd                 = 0x2,
-    kDNSServiceFlagsDefault             = 0x4,
-    /* Flags for domain enumeration and browse/query reply callbacks.
-     * "Default" applies only to enumeration and is only valid in
-     * conjunction with "Add". An enumeration callback with the "Add"
-     * flag NOT set indicates a "Remove", i.e. the domain is no longer
-     * valid.
-     */
-
-    kDNSServiceFlagsNoAutoRename        = 0x8,
-    /* Flag for specifying renaming behavior on name conflict when registering
-     * non-shared records. By default, name conflicts are automatically handled
-     * by renaming the service. NoAutoRename overrides this behavior - with this
-     * flag set, name conflicts will result in a callback. The NoAutorename flag
-     * is only valid if a name is explicitly specified when registering a service
-     * (i.e. the default name is not used.)
-     */
-
-    kDNSServiceFlagsShared              = 0x10,
-    kDNSServiceFlagsUnique              = 0x20,
-    /* Flag for registering individual records on a connected
-     * DNSServiceRef. Shared indicates that there may be multiple records
-     * with this name on the network (e.g. PTR records). Unique indicates that the
-     * record's name is to be unique on the network (e.g. SRV records).
-     */
-
-    kDNSServiceFlagsBrowseDomains       = 0x40,
-    kDNSServiceFlagsRegistrationDomains = 0x80,
-    /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
-     * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
-     * enumerates domains recommended for registration.
-     */
-
-    kDNSServiceFlagsLongLivedQuery      = 0x100,
-    /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
-
-    kDNSServiceFlagsAllowRemoteQuery    = 0x200,
-    /* Flag for creating a record for which we will answer remote queries
-     * (queries from hosts more than one hop away; hosts not directly connected to the local link).
-     */
-
-    kDNSServiceFlagsForceMulticast      = 0x400,
-    /* Flag for signifying that a query or registration should be performed exclusively via multicast
-     * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
-     */
-
-    kDNSServiceFlagsForce               = 0x800,    // This flag is deprecated.
-
-    kDNSServiceFlagsKnownUnique         = 0x800,
-    /*
-     * Client guarantees that record names are unique, so we can skip sending out initial
-     * probe messages.  Standard name conflict resolution is still done if a conflict is discovered.
-     */
-
-    kDNSServiceFlagsReturnIntermediates = 0x1000,
-    /* Flag for returning intermediate results.
-     * For example, if a query results in an authoritative NXDomain (name does not exist)
-     * then that result is returned to the client. However the query is not implicitly
-     * cancelled -- it remains active and if the answer subsequently changes
-     * (e.g. because a VPN tunnel is subsequently established) then that positive
-     * result will still be returned to the client.
-     * Similarly, if a query results in a CNAME record, then in addition to following
-     * the CNAME referral, the intermediate CNAME result is also returned to the client.
-     * When this flag is not set, NXDomain errors are not returned, and CNAME records
-     * are followed silently without informing the client of the intermediate steps.
-     * (In earlier builds this flag was briefly calledkDNSServiceFlagsReturnCNAME)
-     */
-
-    kDNSServiceFlagsShareConnection     = 0x4000,
-    /* For efficiency, clients that perform many concurrent operations may want to use a
-     * single Unix Domain Socket connection with the background daemon, instead of having a
-     * separate connection for each independent operation. To use this mode, clients first
-     * call DNSServiceCreateConnection(&SharedRef) to initialize the main DNSServiceRef.
-     * For each subsequent operation that is to share that same connection, the client copies
-     * the SharedRef, and then passes the address of that copy, setting the ShareConnection flag
-     * to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef;
-     * it's a copy of an existing DNSServiceRef whose connection information should be reused.
-     *
-     * For example:
-     *
-     * DNSServiceErrorType error;
-     * DNSServiceRef SharedRef;
-     * error = DNSServiceCreateConnection(&SharedRef);
-     * if (error) ...
-     * DNSServiceRef BrowseRef = SharedRef;  // Important: COPY the primary DNSServiceRef first...
-     * error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, ...); // then use the copy
-     * if (error) ...
-     * ...
-     * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
-     * DNSServiceRefDeallocate(SharedRef); // Terminate the shared connection
-     *
-     * Notes:
-     *
-     * 1. Collective kDNSServiceFlagsMoreComing flag
-     * When callbacks are invoked using a shared DNSServiceRef, the
-     * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
-     * operations sharing the same parent DNSServiceRef. If the MoreComing flag is
-     * set it means that there are more results queued on this parent DNSServiceRef,
-     * but not necessarily more results for this particular callback function.
-     * The implication of this for client programmers is that when a callback
-     * is invoked with the MoreComing flag set, the code should update its
-     * internal data structures with the new result, and set a variable indicating
-     * that its UI needs to be updated. Then, later when a callback is eventually
-     * invoked with the MoreComing flag not set, the code should update *all*
-     * stale UI elements related to that shared parent DNSServiceRef that need
-     * updating, not just the UI elements related to the particular callback
-     * that happened to be the last one to be invoked.
-     *
-     * 2. Canceling operations and kDNSServiceFlagsMoreComing
-     * Whenever you cancel any operation for which you had deferred UI updates
-     * waiting because of a kDNSServiceFlagsMoreComing flag, you should perform
-     * those deferred UI updates. This is because, after cancelling the operation,
-     * you can no longer wait for a callback *without* MoreComing set, to tell
-     * you do perform your deferred UI updates (the operation has been canceled,
-     * so there will be no more callbacks). An implication of the collective
-     * kDNSServiceFlagsMoreComing flag for shared connections is that this
-     * guideline applies more broadly -- any time you cancel an operation on
-     * a shared connection, you should perform all deferred UI updates for all
-     * operations sharing that connection. This is because the MoreComing flag
-     * might have been referring to events coming for the operation you canceled,
-     * which will now not be coming because the operation has been canceled.
-     *
-     * 3. Only share DNSServiceRef's created with DNSServiceCreateConnection
-     * Calling DNSServiceCreateConnection(&ref) creates a special shareable DNSServiceRef.
-     * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
-     * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
-     *
-     * 4. Don't Double-Deallocate
-     * Calling DNSServiceRefDeallocate(OpRef) for a particular operation's DNSServiceRef terminates
-     * just that operation. Calling DNSServiceRefDeallocate(SharedRef) for the main shared DNSServiceRef
-     * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&SharedRef))
-     * automatically terminates the shared connection *and* all operations that were still using it.
-     * After doing this, DO NOT then attempt to deallocate any remaining subordinate DNSServiceRef's.
-     * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
-     * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
-     * to freed memory, leading to crashes or other equally undesirable results.
-     * You can deallocate individual operations first and then deallocate the parent DNSServiceRef last,
-     * but if you deallocate the parent DNSServiceRef first, then all of the subordinate DNSServiceRef's
-     * are implicitly deallocated, and explicitly deallocating them a second time will lead to crashes.
-     *
-     * 5. Thread Safety
-     * The dns_sd.h API does not presuppose any particular threading model, and consequently
-     * does no locking internally (which would require linking with a specific threading library).
-     * If the client concurrently, from multiple threads (or contexts), calls API routines using
-     * the same DNSServiceRef, it is the client's responsibility to provide mutual exclusion for
-     * that DNSServiceRef.
-     *
-     * For example, use of DNSServiceRefDeallocate requires caution. A common mistake is as follows:
-     * Thread B calls DNSServiceRefDeallocate to deallocate sdRef while Thread A is processing events
-     * using sdRef. Doing this will lead to intermittent crashes on thread A if the sdRef is used after
-     * it was deallocated.
-     *
-     * A telltale sign of this crash type is to see DNSServiceProcessResult on the stack preceding the
-     * actual crash location.
-     *
-     * To state this more explicitly, mDNSResponder does not queue DNSServiceRefDeallocate so
-     * that it occurs discretely before or after an event is handled.
-     */
-
-    kDNSServiceFlagsSuppressUnusable    = 0x8000,
-    /*
-     * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
-     * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
-     * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses
-     * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly,
-     * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
-     * "hostname".
-     */
-
-    kDNSServiceFlagsTimeout            = 0x10000,
-    /*
-     * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is
-     * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped
-     * is determined by the system and cannot be configured by the user. The query will be stopped irrespective
-     * of whether a response was given earlier or not. When the query is stopped, the callback will be called
-     * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo
-     * and zero length rdata will be returned for DNSServiceQueryRecord.
-     */
-
-    kDNSServiceFlagsIncludeP2P          = 0x20000,
-    /*
-     * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified.
-     * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces.
-     */
-
-    kDNSServiceFlagsWakeOnResolve      = 0x40000,
-    /*
-    * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
-    * to wake up the client.
-    */
-
-    kDNSServiceFlagsBackgroundTrafficClass  = 0x80000,
-    /*
-    * This flag is meaningful for Unicast DNS queries. When set, it uses the background traffic
-    * class for packets that service the request.
-    */
-
-    kDNSServiceFlagsIncludeAWDL      = 0x100000,
-   /*
-    * Include AWDL interface when kDNSServiceInterfaceIndexAny is specified.
-    */
-
-    kDNSServiceFlagsEnableDNSSEC           = 0x200000,
-    /*
-     * Perform DNSSEC validation on the client request when kDNSServiceFlagsEnableDNSSEC is specified
-     * Since the client API has not been finalized, we will use it as a temporary flag to turn on the DNSSEC validation.
-     */
-
-    kDNSServiceFlagsValidate               = 0x200000,
-   /*
-    * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid
-    * as an input to the APIs and also an output through the callbacks in the APIs.
-    *
-    * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names,
-    * the response  will be validated using DNSSEC. The validation results are delivered using the flags field in
-    * the callback and kDNSServiceFlagsValidate is marked in the flags to indicate that DNSSEC status is also available.
-    * When the callback is called to deliver the query results, the validation results may or may not be available.
-    * If it is not delivered along with the results, the validation status is delivered when the validation completes.
-    *
-    * When the validation results are delivered in the callback, it is indicated by marking the flags with
-    * kDNSServiceFlagsValidate and kDNSServiceFlagsAdd along with the DNSSEC status flags (described below) and a NULL
-    * sockaddr will be returned for DNSServiceGetAddrInfo and zero length rdata will be returned for DNSServiceQueryRecord.
-    * DNSSEC validation results are for the whole RRSet and not just individual records delivered in the callback. When
-    * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the
-    * RRSet that has been delivered up until that point is not valid anymore, till another callback is called with
-    * kDNSServiceFlagsAdd and kDNSServiceFlagsValidate.
-    *
-    * The following four flags indicate the status of the DNSSEC validation and marked in the flags field of the callback.
-    * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the
-    * other applicable output flags should be masked.
-    */
-
-    kDNSServiceFlagsSecure                 = 0x200010,
-   /*
-    * The response has been validated by verifying all the signatures in the response and was able to
-    * build a successful authentication chain starting from a known trust anchor.
-    */
-
-    kDNSServiceFlagsInsecure               = 0x200020,
-   /*
-    * A chain of trust cannot be built starting from a known trust anchor to the response.
-    */
-
-    kDNSServiceFlagsBogus                  = 0x200040,
-   /*
-    * If the response cannot be verified to be secure due to expired signatures, missing signatures etc.,
-    * then the results are considered to be bogus.
-    */
-
-    kDNSServiceFlagsIndeterminate          = 0x200080,
-   /*
-    * There is no valid trust anchor that can be used to determine whether a response is secure or not.
-    */
-
-    kDNSServiceFlagsUnicastResponse        = 0x400000,
-   /*
-    * Request unicast response to query.
-    */
-    kDNSServiceFlagsValidateOptional       = 0x800000,
-
-    /*
-     * This flag is identical to kDNSServiceFlagsValidate except for the case where the response
-     * cannot be validated. If this flag is set in DNSServiceQueryRecord or DNSServiceGetAddrInfo,
-     * the DNSSEC records will be requested for validation. If they cannot be received for some reason
-     * during the validation (e.g., zone is not signed, zone is signed but cannot be traced back to
-     * root, recursive server does not understand DNSSEC etc.), then this will fallback to the default
-     * behavior where the validation will not be performed and no DNSSEC results will be provided.
-     *
-     * If the zone is signed and there is a valid path to a known trust anchor configured in the system
-     * and the application requires DNSSEC validation irrespective of the DNSSEC awareness in the current
-     * network, then this option MUST not be used. This is only intended to be used during the transition
-     * period where the different nodes participating in the DNS resolution may not understand DNSSEC or
-     * managed properly (e.g. missing DS record) but still want to be able to resolve DNS successfully.
-     */
-
-    kDNSServiceFlagsWakeOnlyService        = 0x1000000,
-    /*
-     * This flag is meaningful only in DNSServiceRegister. When set, the service will not be registered
-     * with sleep proxy server during sleep.
-     */
-
-    kDNSServiceFlagsThresholdOne           = 0x2000000,
-    kDNSServiceFlagsThresholdFinder        = 0x4000000,
-    kDNSServiceFlagsThresholdReached       = kDNSServiceFlagsThresholdOne,
-    /*
-     * kDNSServiceFlagsThresholdOne is used only with DNSServiceBrowse, and is not meaningful
-     * with any other API call. This flag limits the number of retries that are performed when
-     * doing mDNS service discovery. As soon as a single answer is received, retransmission
-     * is discontinued. This allows the caller to determine whether or not a particular service
-     * is present on the network in as efficient a way as possible. As answers expire from the
-     * cache or are explicitly removed as a consequence of the service being discontinued, if
-     * the number of still-valid answers reaches zero, mDNSResponder will resume periodic querying
-     * on the network until at least one valid answer is present. Because this flag only controls
-     * retransmission, when more than one service of the type being browsed is present on the
-     * network, it is quite likely that more than one answer will be delivered to the callback.
-     *
-     * kDNSServiceFlagsThresholdFinder is used only in DNSServiceBrowse, and is not meaningful
-     * in other API calls. When set, this flag limits the number of retries that are performed
-     * when doing mDNS service discovery, similar to kDNSServiceFlagsThresholdOne. The difference
-     * is that the threshold here is higher: retransmissions will continue until some system-
-     * dependent number of answers are present, or the retransmission process is complete.
-     * Because the number of answers that ends retransmission varies, developers should not
-     * depend on there being some specific threshold; rather, this flag can be used in cases
-     * where it is preferred to give the user a choice, but where once a small number of
-     * such services are discovered, retransmission is discontinued.
-     *
-     * When kDNSServiceFlagsThresholdReached is set in the client callback add or remove event,
-     * it indicates that the browse answer threshold has been reached and no
-     * browse requests will be generated on the network until the number of answers falls
-     * below the threshold value.  Add and remove events can still occur based
-     * on incoming Bonjour traffic observed by the system.
-     * The set of services return to the client is not guaranteed to represent the
-     * entire set of services present on the network once the threshold has been reached.
-     *
-     * Note, while kDNSServiceFlagsThresholdReached and kDNSServiceFlagsThresholdOne
-     * have the same value, there  isn't a conflict because kDNSServiceFlagsThresholdReached
-     * is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on
-     * input to a DNSServiceBrowse call.
-     */
-
-     kDNSServiceFlagsPrivateOne          = 0x2000,
-    /*
-     * This flag is private and should not be used.
-     */
-
-     kDNSServiceFlagsPrivateTwo           = 0x8000000,
-    /*
-     * This flag is private and should not be used.
-     */
-
-     kDNSServiceFlagsPrivateThree         = 0x10000000,
-    /*
-     * This flag is private and should not be used.
-     */
-
-     kDNSServiceFlagsPrivateFour          = 0x20000000,
-    /*
-     * This flag is private and should not be used.
-     */
-
-    kDNSServiceFlagsPrivateFive          = 0x40000000,
-    /*
-     * This flag is private and should not be used.
-     */
-
-
-    kDNSServiceFlagAnsweredFromCache     = 0x40000000,
-    /*
-     * When kDNSServiceFlagAnsweredFromCache is passed back in the flags parameter of DNSServiceQueryRecordReply or DNSServiceGetAddrInfoReply,
-     * an answer will have this flag set if it was answered from the cache.
-     */
-
-    kDNSServiceFlagsAllowExpiredAnswers   = 0x80000000,
-    /*
-     * When kDNSServiceFlagsAllowExpiredAnswers is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo,
-     * if there are matching expired records still in the cache, then they are immediately returned to the
-     * client, and in parallel a network query for that name is issued. All returned records from the query will
-     * remain in the cache after expiration.
-     */
-
-    kDNSServiceFlagsExpiredAnswer         = 0x80000000
-    /*
-     * When kDNSServiceFlagsAllowExpiredAnswers is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo,
-     * an expired answer will have this flag set.
-     */
-
-};
-
-/* Possible protocol values */
-enum
-{
-    /* for DNSServiceGetAddrInfo() */
-    kDNSServiceProtocol_IPv4 = 0x01,
-    kDNSServiceProtocol_IPv6 = 0x02,
-    /* 0x04 and 0x08 reserved for future internetwork protocols */
-
-    /* for DNSServiceNATPortMappingCreate() */
-    kDNSServiceProtocol_UDP  = 0x10,
-    kDNSServiceProtocol_TCP  = 0x20
-                               /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960]
-                                * or DCCP [RFC 4340]. If future NAT gateways are created that support port
-                                * mappings for these protocols, new constants will be defined here.
-                                */
-};
-
-/*
- * The values for DNS Classes and Types are listed in RFC 1035, and are available
- * on every OS in its DNS header file. Unfortunately every OS does not have the
- * same header file containing DNS Class and Type constants, and the names of
- * the constants are not consistent. For example, BIND 8 uses "T_A",
- * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
- * For this reason, these constants are also listed here, so that code using
- * the DNS-SD programming APIs can use these constants, so that the same code
- * can compile on all our supported platforms.
- */
-
-enum
-{
-    kDNSServiceClass_IN       = 1       /* Internet */
-};
-
-enum
-{
-    kDNSServiceType_A          = 1,      /* Host address. */
-    kDNSServiceType_NS         = 2,      /* Authoritative server. */
-    kDNSServiceType_MD         = 3,      /* Mail destination. */
-    kDNSServiceType_MF         = 4,      /* Mail forwarder. */
-    kDNSServiceType_CNAME      = 5,      /* Canonical name. */
-    kDNSServiceType_SOA        = 6,      /* Start of authority zone. */
-    kDNSServiceType_MB         = 7,      /* Mailbox domain name. */
-    kDNSServiceType_MG         = 8,      /* Mail group member. */
-    kDNSServiceType_MR         = 9,      /* Mail rename name. */
-    kDNSServiceType_NULL       = 10,     /* Null resource record. */
-    kDNSServiceType_WKS        = 11,     /* Well known service. */
-    kDNSServiceType_PTR        = 12,     /* Domain name pointer. */
-    kDNSServiceType_HINFO      = 13,     /* Host information. */
-    kDNSServiceType_MINFO      = 14,     /* Mailbox information. */
-    kDNSServiceType_MX         = 15,     /* Mail routing information. */
-    kDNSServiceType_TXT        = 16,     /* One or more text strings (NOT "zero or more..."). */
-    kDNSServiceType_RP         = 17,     /* Responsible person. */
-    kDNSServiceType_AFSDB      = 18,     /* AFS cell database. */
-    kDNSServiceType_X25        = 19,     /* X_25 calling address. */
-    kDNSServiceType_ISDN       = 20,     /* ISDN calling address. */
-    kDNSServiceType_RT         = 21,     /* Router. */
-    kDNSServiceType_NSAP       = 22,     /* NSAP address. */
-    kDNSServiceType_NSAP_PTR   = 23,     /* Reverse NSAP lookup (deprecated). */
-    kDNSServiceType_SIG        = 24,     /* Security signature. */
-    kDNSServiceType_KEY        = 25,     /* Security key. */
-    kDNSServiceType_PX         = 26,     /* X.400 mail mapping. */
-    kDNSServiceType_GPOS       = 27,     /* Geographical position (withdrawn). */
-    kDNSServiceType_AAAA       = 28,     /* IPv6 Address. */
-    kDNSServiceType_LOC        = 29,     /* Location Information. */
-    kDNSServiceType_NXT        = 30,     /* Next domain (security). */
-    kDNSServiceType_EID        = 31,     /* Endpoint identifier. */
-    kDNSServiceType_NIMLOC     = 32,     /* Nimrod Locator. */
-    kDNSServiceType_SRV        = 33,     /* Server Selection. */
-    kDNSServiceType_ATMA       = 34,     /* ATM Address */
-    kDNSServiceType_NAPTR      = 35,     /* Naming Authority PoinTeR */
-    kDNSServiceType_KX         = 36,     /* Key Exchange */
-    kDNSServiceType_CERT       = 37,     /* Certification record */
-    kDNSServiceType_A6         = 38,     /* IPv6 Address (deprecated) */
-    kDNSServiceType_DNAME      = 39,     /* Non-terminal DNAME (for IPv6) */
-    kDNSServiceType_SINK       = 40,     /* Kitchen sink (experimental) */
-    kDNSServiceType_OPT        = 41,     /* EDNS0 option (meta-RR) */
-    kDNSServiceType_APL        = 42,     /* Address Prefix List */
-    kDNSServiceType_DS         = 43,     /* Delegation Signer */
-    kDNSServiceType_SSHFP      = 44,     /* SSH Key Fingerprint */
-    kDNSServiceType_IPSECKEY   = 45,     /* IPSECKEY */
-    kDNSServiceType_RRSIG      = 46,     /* RRSIG */
-    kDNSServiceType_NSEC       = 47,     /* Denial of Existence */
-    kDNSServiceType_DNSKEY     = 48,     /* DNSKEY */
-    kDNSServiceType_DHCID      = 49,     /* DHCP Client Identifier */
-    kDNSServiceType_NSEC3      = 50,     /* Hashed Authenticated Denial of Existence */
-    kDNSServiceType_NSEC3PARAM = 51,     /* Hashed Authenticated Denial of Existence */
-
-    kDNSServiceType_HIP        = 55,     /* Host Identity Protocol */
-
-    kDNSServiceType_SVCB       = 64,     /* Service Binding. */
-    kDNSServiceType_HTTPS      = 65,      /* HTTPS Service Binding. */
-
-    kDNSServiceType_SPF        = 99,     /* Sender Policy Framework for E-Mail */
-    kDNSServiceType_UINFO      = 100,    /* IANA-Reserved */
-    kDNSServiceType_UID        = 101,    /* IANA-Reserved */
-    kDNSServiceType_GID        = 102,    /* IANA-Reserved */
-    kDNSServiceType_UNSPEC     = 103,    /* IANA-Reserved */
-
-    kDNSServiceType_TKEY       = 249,    /* Transaction key */
-    kDNSServiceType_TSIG       = 250,    /* Transaction signature. */
-    kDNSServiceType_IXFR       = 251,    /* Incremental zone transfer. */
-    kDNSServiceType_AXFR       = 252,    /* Transfer zone of authority. */
-    kDNSServiceType_MAILB      = 253,    /* Transfer mailbox records. */
-    kDNSServiceType_MAILA      = 254,    /* Transfer mail agent records. */
-    kDNSServiceType_ANY        = 255    /* Wildcard match. */
-};
-
-/* possible error code values */
-enum
-{
-    kDNSServiceErr_NoError                   = 0,
-    kDNSServiceErr_Unknown                   = -65537,  /* 0xFFFE FFFF */
-    kDNSServiceErr_NoSuchName                = -65538,
-    kDNSServiceErr_NoMemory                  = -65539,
-    kDNSServiceErr_BadParam                  = -65540,
-    kDNSServiceErr_BadReference              = -65541,
-    kDNSServiceErr_BadState                  = -65542,
-    kDNSServiceErr_BadFlags                  = -65543,
-    kDNSServiceErr_Unsupported               = -65544,
-    kDNSServiceErr_NotInitialized            = -65545,
-    kDNSServiceErr_AlreadyRegistered         = -65547,
-    kDNSServiceErr_NameConflict              = -65548,
-    kDNSServiceErr_Invalid                   = -65549,
-    kDNSServiceErr_Firewall                  = -65550,
-    kDNSServiceErr_Incompatible              = -65551,  /* client library incompatible with daemon */
-    kDNSServiceErr_BadInterfaceIndex         = -65552,
-    kDNSServiceErr_Refused                   = -65553,
-    kDNSServiceErr_NoSuchRecord              = -65554,
-    kDNSServiceErr_NoAuth                    = -65555,
-    kDNSServiceErr_NoSuchKey                 = -65556,
-    kDNSServiceErr_NATTraversal              = -65557,
-    kDNSServiceErr_DoubleNAT                 = -65558,
-    kDNSServiceErr_BadTime                   = -65559,  /* Codes up to here existed in Tiger */
-    kDNSServiceErr_BadSig                    = -65560,
-    kDNSServiceErr_BadKey                    = -65561,
-    kDNSServiceErr_Transient                 = -65562,
-    kDNSServiceErr_ServiceNotRunning         = -65563,  /* Background daemon not running */
-    kDNSServiceErr_NATPortMappingUnsupported = -65564,  /* NAT doesn't support PCP, NAT-PMP or UPnP */
-    kDNSServiceErr_NATPortMappingDisabled    = -65565,  /* NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator */
-    kDNSServiceErr_NoRouter                  = -65566,  /* No router currently configured (probably no network connectivity) */
-    kDNSServiceErr_PollingMode               = -65567,
-    kDNSServiceErr_Timeout                   = -65568,
-    kDNSServiceErr_DefunctConnection         = -65569,  /* Connection to daemon returned a SO_ISDEFUNCT error result */
-    kDNSServiceErr_PolicyDenied              = -65570,
-    kDNSServiceErr_NotPermitted              = -65571
-
-
-                                               /* mDNS Error codes are in the range
-                                                * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
-};
-
-/* Maximum length, in bytes, of a service name represented as a */
-/* literal C-String, including the terminating NULL at the end. */
-
-#define kDNSServiceMaxServiceName 64
-
-/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
-/* including the final trailing dot, and the C-String terminating NULL at the end. */
-
-#define kDNSServiceMaxDomainName 1009
-
-/*
- * Notes on DNS Name Escaping
- *   -- or --
- * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
- *
- * All strings used in the DNS-SD APIs are UTF-8 strings.
- * Apart from the exceptions noted below, the APIs expect the strings to be properly escaped, using the
- * conventional DNS escaping rules, as used by the traditional DNS res_query() API, as described below:
- *
- * Generally all UTF-8 characters (which includes all US ASCII characters) represent themselves,
- * with three exceptions:
- * the dot ('.') character, which is the DNS label separator,
- * the backslash ('\') character, which is the DNS escape character, and
- * the ASCII NUL (0) byte value, which is the C-string terminator character.
- * The escape character ('\') is interpreted as described below:
- *
- *   '\ddd', where ddd is a three-digit decimal value from 000 to 255,
- *        represents a single literal byte with that value. Any byte value may be
- *        represented in '\ddd' format, even characters that don't strictly need to be escaped.
- *        For example, the ASCII code for 'w' is 119, and therefore '\119' is equivalent to 'w'.
- *        Thus the command "ping '\119\119\119.apple.com'" is the equivalent to the command "ping 'www.apple.com'".
- *        Nonprinting ASCII characters in the range 0-31 are often represented this way.
- *        In particular, the ASCII NUL character (0) cannot appear in a C-string because C uses it as the
- *        string terminator character, so ASCII NUL in a domain name has to be represented in a C-string as '\000'.
- *        Other characters like space (ASCII code 32) are sometimes represented as '\032'
- *        in contexts where having an actual space character in a C-string would be inconvenient.
- *
- *   Otherwise, for all cases where a '\' is followed by anything other than a three-digit decimal value
- *        from 000 to 255, the character sequence '\x' represents a single literal occurrence of character 'x'.
- *        This is legal for any character, so, for example, '\w' is equivalent to 'w'.
- *        Thus the command "ping '\w\w\w.apple.com'" is the equivalent to the command "ping 'www.apple.com'".
- *        However, this encoding is most useful when representing the characters '.' and '\',
- *        which otherwise would have special meaning in DNS name strings.
- *        This means that the following encodings are particularly common:
- *        '\\' represents a single literal '\' in the name
- *        '\.' represents a single literal '.' in the name
- *
- *   A lone escape character ('\') appearing at the end of a string is not allowed, since it is
- *        followed by neither a three-digit decimal value from 000 to 255 nor a single character.
- *        If a lone escape character ('\') does appear as the last character of a string, it is silently ignored.
- *
- * The worse-case length for an escaped domain name is calculated as follows:
- * The longest legal domain name is 256 bytes in wire format (see RFC 6762, Appendix C, DNS Name Length).
- * For our calculation of the longest *escaped* domain name, we use
- * the longest legal domain name, with the most characters escaped.
- *
- * We consider a domain name of the form: "label63.label63.label63.label62."
- * where "label63" is a 63-byte label and "label62" is a 62-byte label.
- * Counting four label-length bytes, 251 bytes of label data, and the terminating zero,
- * this makes a total of 256 bytes in wire format, the longest legal domain name.
- *
- * If each one of the 251 bytes of label data is represented using '\ddd',
- * then it takes 251 * 4 = 1004 bytes to represent these in a C-string.
- * Adding four '.' characters as shown above, plus the C-string terminating
- * zero at the end, results in a maximum storage requirement of 1009 bytes.
- *
- * The exceptions, that do not use escaping, are the routines where the full
- * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
- * In these routines, the "servicename" is NOT escaped. It does not need to be, since
- * it is, by definition, just a single literal string. Any characters in that string
- * represent exactly what they are. The "regtype" portion is, technically speaking,
- * escaped, but since legal regtypes are only allowed to contain US ASCII letters,
- * digits, and hyphens, there is nothing to escape, so the issue is moot.
- * The "domain" portion is also escaped, though most domains in use on the public
- * Internet today, like regtypes, don't contain any characters that need to be escaped.
- * As DNS-SD becomes more popular, rich-text domains for service discovery will
- * become common, so software should be written to cope with domains with escaping.
- *
- * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
- * terminating NULL at the end). The regtype is of the form _service._tcp or
- * _service._udp, where the "service" part is 1-15 characters, which may be
- * letters, digits, or hyphens. The domain part of the three-part name may be
- * any legal domain, providing that the resulting servicename+regtype+domain
- * name does not exceed 256 bytes.
- *
- * For most software, these issues are transparent. When browsing, the discovered
- * servicenames should simply be displayed as-is. When resolving, the discovered
- * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
- * When a DNSServiceResolve() succeeds, the returned fullname is already in
- * the correct format to pass to standard system DNS APIs such as res_query().
- * For converting from servicename/regtype/domain to a single properly-escaped
- * full DNS name, the helper function DNSServiceConstructFullName() is provided.
- *
- * The following (highly contrived) example illustrates the escaping process.
- * Suppose you have a service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
- * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
- * The full (escaped) DNS name of this service's SRV record would be:
- * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
- */
-
-
-/*
- * Constants for specifying an interface index
- *
- * Specific interface indexes are identified via a 32-bit unsigned integer returned
- * by the if_nametoindex() family of calls.
- *
- * If the client passes 0 for interface index, that means "do the right thing",
- * which (at present) means, "if the name is in an mDNS local multicast domain
- * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
- * on all applicable interfaces, otherwise send via unicast to the appropriate
- * DNS server." Normally, most clients will use 0 for interface index to
- * automatically get the default sensible behaviour.
- *
- * If the client passes a positive interface index, then that indicates to do the
- * operation only on that one specified interface.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
- * a service, then that service will be found *only* by other local clients
- * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
- * or kDNSServiceInterfaceIndexAny.
- * If a client has a 'private' service, accessible only to other processes
- * running on the same machine, this allows the client to advertise that service
- * in a way such that it does not inadvertently appear in service lists on
- * all the other machines on the network.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when querying or
- * browsing, then the LocalOnly authoritative records and /etc/hosts caches
- * are searched and will find *all* records registered or configured on that
- * same local machine.
- *
- * If interested in getting negative answers to local questions while querying
- * or browsing, then set both the kDNSServiceInterfaceIndexLocalOnly and the
- * kDNSServiceFlagsReturnIntermediates flags. If no local answers exist at this
- * moment in time, then the reply will return an immediate negative answer. If
- * local records are subsequently created that answer the question, then those
- * answers will be delivered, for as long as the question is still active.
- *
- * If the kDNSServiceFlagsTimeout and kDNSServiceInterfaceIndexLocalOnly flags
- * are set simultaneously when either DNSServiceQueryRecord or DNSServiceGetAddrInfo
- * is called then both flags take effect. However, if DNSServiceQueryRecord is called
- * with both the kDNSServiceFlagsSuppressUnusable and kDNSServiceInterfaceIndexLocalOnly
- * flags set, then the kDNSServiceFlagsSuppressUnusable flag is ignored.
- *
- * Clients explicitly wishing to discover *only* LocalOnly services during a
- * browse may do this, without flags, by inspecting the interfaceIndex of each
- * service reported to a DNSServiceBrowseReply() callback function, and
- * discarding those answers where the interface index is not set to
- * kDNSServiceInterfaceIndexLocalOnly.
- *
- * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register,
- * and Resolve operations. It should not be used in other DNSService APIs.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
- *   DNSServiceQueryRecord, it restricts the operation to P2P.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceRegister, it is
- *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
- *   set.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
- *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
- *   set, because resolving a P2P service may create and/or enable an interface whose
- *   index is not known a priori. The resolve callback will indicate the index of the
- *   interface via which the service can be accessed.
- *
- * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
- * or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
- * to include P2P. In this case, if a service instance or the record being queried
- * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
- * as the interface index.
- */
-
-#define kDNSServiceInterfaceIndexAny 0
-#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
-#define kDNSServiceInterfaceIndexUnicast   ((uint32_t)-2)
-#define kDNSServiceInterfaceIndexP2P       ((uint32_t)-3)
-#define kDNSServiceInterfaceIndexBLE       ((uint32_t)-4)
-
-typedef uint32_t DNSServiceFlags;
-typedef uint32_t DNSServiceProtocol;
-typedef int32_t DNSServiceErrorType;
-
-#if (defined(__clang__) && __clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnullability-completeness"
-#endif
-/*********************************************************************************************
-*
-* Version checking
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  Get value of service property.
- *
- *  @param property
- *                  The requested property.
- *                  Currently the only property defined is kDNSServiceProperty_DaemonVersion.
- *
- *  @param result
- *                  Place to store result.
- *                  For retrieving DaemonVersion, this should be the address of a uint32_t.
- *
- *  @param size
- *                  Pointer to uint32_t containing size of the result location.
- *                  For retrieving DaemonVersion, this should be sizeof(uint32_t).
- *                  On return the uint32_t is updated to the size of the data returned.
- *                  For DaemonVersion, the returned size is always sizeof(uint32_t), but
- *                  future properties could be defined which return variable-sized results.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
- *                  if the daemon (or "system service" on Windows) is not running.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceGetProperty
-(
-    const char *property,           /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
-    void *result,                   /* Pointer to place to store result */
-    uint32_t *size                  /* size of result location */
-);
-
-/*
- * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point
- * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t).
- *
- * On return, the 32-bit unsigned integer contains the API version number
- *
- * For example, Mac OS X 10.4.9 has API version 1080400.
- * This allows applications to do simple greater-than and less-than comparisons:
- * e.g. an application that requires at least API version 1080400 can check:
- *   if (version >= 1080400) ...
- *
- * Example usage:
- * uint32_t version;
- * uint32_t size = sizeof(version);
- * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
- * if (!err)
- * {
- *     if (version > DNS_SD_ORIGINAL_ENCODING_VERSION_NUMBER_MAX)
- *     {
- *         printf("DNS_SD API version is %u.%u.%u\n", version / 1000000, (version / 1000) % 1000, version % 1000);
- *     }
- *     else
- *     {
- *         printf("DNS_SD API version is %u.%u.%u\n", version / 10000, (version / 100) % 100, version % 100);
- *     }
- * }
- */
-
-#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
-
-/*********************************************************************************************
-*
-* Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  Access underlying Unix domain socket for an initialized DNSServiceRef.
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by any of the DNSService calls.
- *
- *  @result
- *                  The DNSServiceRef's underlying socket descriptor, or -1 on error.
- *
- *  @discussion
- *                  The DNS Service Discovery implementation uses this socket to communicate between the client and
- *                  the daemon. The application MUST NOT directly read from or write to this socket.
- *                  Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop
- *                  event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/
- *                  select/CFRunLoop etc.) indicates to the client that data is available for reading on the
- *                  socket, the client should call DNSServiceProcessResult(), which will extract the daemon's
- *                  reply from the socket, and pass it to the appropriate application callback. By using a run
- *                  loop or select(), results from the daemon can be processed asynchronously. Alternatively,
- *                  a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
- *                  If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
- *                  will block until data does become available, and then process the data and return to the caller.
- *                  The application is responsible for checking the return value of DNSServiceProcessResult()
- *                  to determine if the socket is valid and if it should continue to process data on the socket.
- *                  When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
- *                  in a timely fashion -- if the client allows a large backlog of data to build up the daemon
- *                  may terminate the connection.
- */
-DNSSD_EXPORT
-dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
-
-/*!
- *  @brief
- *                  Read a reply from the daemon, calling the appropriate application callback.
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by any of the DNSService calls
- *                  that take a callback parameter.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns
- *                  an error code indicating the specific failure that occurred.
- *
- *  @discussion
- *                  This call will block until the daemon's response is received. Use DNSServiceRefSockFD() in
- *                  conjunction with a run loop or select() to determine the presence of a response from the
- *                  server before calling this function to process the reply without blocking. Call this function
- *                  at any point if it is acceptable to block until the daemon's response arrives. Note that the
- *                  client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
- *                  a reply from the daemon - the daemon may terminate its connection with a client that does not
- *                  process the daemon's responses.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
-
-/*!
- *  @brief
- *                  Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by any of the DNSService calls.
- *
- *  @discussion
- *                  Any services or records registered with this DNSServiceRef will be deregistered. Any
- *                  Browse, Resolve, or Query operations called with this reference will be terminated.
- *
- *                  Note: If the reference's underlying socket is used in a run loop or select() call, it should
- *                  be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
- *                  socket.
- *
- *                  Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
- *                  created via this reference will be invalidated by this call - the resource records are
- *                  deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
- *                  if the reference was initialized with DNSServiceRegister, and an extra resource record was
- *                  added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
- *                  is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
- *                  functions.
- *
- *                  If the reference was passed to DNSServiceSetDispatchQueue(), DNSServiceRefDeallocate() must
- *                  be called on the same queue originally passed as an argument to DNSServiceSetDispatchQueue().
- *
- *                  Note: This call is to be used only with the DNSServiceRef defined by this API.
- */
-DNSSD_EXPORT
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
-
-/*********************************************************************************************
-*
-* Domain Enumeration
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceEnumerateDomains callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceEnumerateDomains().
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsMoreComing
- *                  kDNSServiceFlagsAdd
- *                  kDNSServiceFlagsDefault
- *
- *  @param interfaceIndex
- *                  Specifies the interface on which the domain exists. (The index for a given
- *                  interface is determined via the if_nametoindex() family of calls.)
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
- *                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
- *
- *  @param replyDomain
- *                  The name of the domain.
- *
- *  @param context
- *                  The context pointer passed to DNSServiceEnumerateDomains.
- */
-typedef void (DNSSD_API *DNSServiceDomainEnumReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char *replyDomain,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Asynchronously enumerate domains available for browsing and registration.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the enumeration operation
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
- *                  kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
- *                  for registration.
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to look for domains.
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to enumerate domains on
- *                  all interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param callBack
- *                  The function to be called when a domain is found or the call asynchronously
- *                  fails.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- *  @discussion
- *                  The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
- *                  are to be found.
- *
- *                  Note that the names returned are (like all of DNS-SD) UTF-8 strings,
- *                  and are escaped using standard DNS escaping rules.
- *                  (See "Notes on DNS Name Escaping" earlier in this file for more details.)
- *                  A graphical browser displaying a hierarchical tree-structured view should cut
- *                  the names at the bare dots to yield individual labels, then de-escape each
- *                  label according to the escaping rules, and then display the resulting UTF-8 text.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceDomainEnumReply callBack,
-    void *context
-);
-
-
-/*********************************************************************************************
-*
-*  Service Registration
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceRegister callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceRegister().
- *
- *  @param flags
- *                  When a name is successfully registered, the callback will be
- *                  invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
- *                  DNS-SD is in use, it is possible for a single service to get
- *                  more than one success callback (e.g. one in the "local" multicast
- *                  DNS domain, and another in a wide-area unicast DNS domain).
- *                  If a successfully-registered name later suffers a name conflict
- *                  or similar problem and has to be deregistered, the callback will
- *                  be invoked with the kDNSServiceFlagsAdd flag not set. The callback
- *                  is *not* invoked in the case where the caller explicitly terminates
- *                  the service registration by calling DNSServiceRefDeallocate(ref);
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts,
- *                  if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- *  @param name
- *                  The service name registered (if the application did not specify a name in
- *                  DNSServiceRegister(), this indicates what name was automatically chosen).
- *
- *  @param regtype
- *                  The type of service registered, as it was passed to the callout.
- *
- *  @param domain
- *                  The domain on which the service was registered (if the application did not
- *                  specify a domain in DNSServiceRegister(), this indicates the default domain
- *                  on which the service was registered).
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceRegisterReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    DNSServiceErrorType errorCode,
-    const char *name,
-    const char *regtype,
-    const char *domain,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Register a service that is discovered via Browse() and Resolve() calls.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the service registration
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  Other flags indicate the renaming behavior on name conflict
- *                  (not required for most applications).
- *                  See flag definitions above for details.
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to register the service
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to register on all
- *                  available interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param name
- *                  If non-NULL, specifies the service name to be registered.
- *                  Most applications will not specify a name, in which case the computer
- *                  name is used (this name is communicated to the client via the callback).
- *                  If a name is specified, it must be 1-63 bytes of UTF-8 text.
- *                  If the name is longer than 63 bytes it will be automatically truncated
- *                  to a legal length, unless the NoAutoRename flag is set,
- *                  in which case kDNSServiceErr_BadParam will be returned.
- *
- *  @param regtype
- *                  The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp"). The service type must be an underscore, followed
- *                  by 1-15 characters, which may be letters, digits, or hyphens.
- *                  The transport protocol must be "_tcp" or "_udp". New service types
- *                  should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
- *
- *                  Additional subtypes of the primary service type (where a service
- *                  type has defined subtypes) follow the primary service type in a
- *                  comma-separated list, with no additional spaces, e.g.
- *                      "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
- *                  Subtypes provide a mechanism for filtered browsing: A client browsing
- *                  for "_primarytype._tcp" will discover all instances of this type;
- *                  a client browsing for "_primarytype._tcp,_subtype2" will discover only
- *                  those instances that were registered with "_subtype2" in their list of
- *                  registered subtypes.
- *
- *                  The subtype mechanism can be illustrated with some examples using the
- *                  dns-sd command-line tool:
- *
- *                  % dns-sd -R Simple _test._tcp "" 1001 &
- *                  % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
- *                  % dns-sd -R Best   _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
- *
- *                  Now:
- *                  % dns-sd -B _test._tcp             # will find all three services
- *                  % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
- *                  % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
- *
- *                  Subtype labels may be up to 63 bytes long, and may contain any eight-
- *                  bit byte values, including zero bytes. However, due to the nature of
- *                  using a C-string-based API, conventional DNS escaping must be used for
- *                  dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
- *
- *                  % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
- *
- *  @param domain
- *                  If non-NULL, specifies the domain on which to advertise the service.
- *                  Most applications will not specify a domain, instead automatically
- *                  registering in the default domain(s).
- *
- *  @param host
- *                  If non-NULL, specifies the SRV target host name. Most applications
- *                  will not specify a host, instead automatically using the machine's
- *                  default host name(s). Note that specifying a non-NULL host does NOT
- *                  create an address record for that host - the application is responsible
- *                  for ensuring that the appropriate address record exists, or creating it
- *                  via DNSServiceRegisterRecord().
- *
- *  @param port
- *                  The port, in network byte order, on which the service accepts connections.
- *                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
- *                  by browsing, but will cause a name conflict if another client tries to
- *                  register that same name). Most clients will not use placeholder services.
- *
- *  @param txtLen
- *                  The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
- *
- *  @param txtRecord
- *                  The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
- *                  TXT record, i.e. <length byte> <data> <length byte> <data> ...
- *                  Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
- *                  i.e. it creates a TXT record of length one containing a single empty string.
- *                  RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
- *                  string is the smallest legal DNS TXT record.
- *                  As with the other parameters, the DNSServiceRegister call copies the txtRecord
- *                  data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
- *                  then you can safely free that memory right after the DNSServiceRegister call returns.
- *
- *  @param callBack
- *                  The function to be called when the registration completes or asynchronously
- *                  fails. The client MAY pass NULL for the callback -  The client will NOT be notified
- *                  of the default values picked on its behalf, and the client will NOT be notified of any
- *                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
- *                  of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
- *                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,                  /* may be NULL */
-    const char *regtype,
-    const char *domain,                /* may be NULL */
-    const char *host,                  /* may be NULL */
-    uint16_t port,                     /* In network byte order */
-    uint16_t txtLen,
-    const void *txtRecord,             /* may be NULL */
-    DNSServiceRegisterReply callBack,  /* may be NULL */
-    void *context
-);
-
-/*!
- *  @brief
- *                  Add a record to a registered service.
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by DNSServiceRegister().
- *
- *  @param RecordRef
- *                  A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
- *                  invalidated and may not be used further.
- *
- *  @param flags
- *                  Currently ignored, reserved for future use.
- *
- *  @param rrtype
- *                  The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
- *
- *  @param rdlen
- *                  The length, in bytes, of the rdata.
- *
- *  @param rdata
- *                  The raw rdata to be contained in the added resource record.
- *
- *  @param ttl
- *                  The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred (the RecordRef is not initialized).
- *
- *  @discussion
- *                  The name of the record will be the same as the
- *                  registered service's name.
- *                  The record can later be updated or deregistered by passing the RecordRef initialized
- *                  by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *
- *                  Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
- *                  with respect to a single DNSServiceRef. If you plan to have multiple threads
- *                  in your program simultaneously add, update, or remove records from the same
- *                  DNSServiceRef, then it's the caller's responsibility to use a mutex lock
- *                  or take similar appropriate precautions to serialize those calls.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef *RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rrtype,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl
-);
-
-/*!
- *  @brief
- *                  Update a registered resource record.
- *
- *  @param sdRef
- *                  A DNSServiceRef that was initialized by DNSServiceRegister()
- *                  or DNSServiceCreateConnection().
- *
- *  @param recordRef
- *                  A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
- *                  service's primary txt record.
- *
- *  @param flags
- *                  Currently ignored, reserved for future use.
- *
- *  @param rdlen
- *                  The length, in bytes, of the new rdata.
- *
- *  @param rdata
- *                  The new rdata to be contained in the updated resource record.
- *
- *  @param ttl
- *                  The time to live of the updated resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- *
- *  @discussion
- *                  The record must either be:
- *                  - The primary txt record of a service registered via DNSServiceRegister()
- *                  - A record added to a registered service via DNSServiceAddRecord()
- *                  - An individual record registered by DNSServiceRegisterRecord()
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef recordRef,                  /* may be NULL */
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl
-);
-
-#if (defined(__clang__) && __clang__)
-#pragma clang diagnostic pop
-#endif
-
-/*!
- *  @brief
- *                  Update a registered resource record with attribute.
- *
- *  @param sdRef
- *                  A DNSServiceRef that was initialized by DNSServiceRegister()
- *                  or DNSServiceCreateConnection().
- *
- *  @param recordRef
- *                  A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
- *                  service's primary txt record.
- *
- *  @param flags
- *                  Currently ignored, reserved for future use.
- *
- *  @param rdlen
- *                  The length, in bytes, of the new rdata.
- *
- *  @param rdata
- *                  The new rdata to be contained in the updated resource record.
- *
- *  @param ttl
- *                  The time to live of the updated resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- *  @param attr
- *                  An DNSServiceAttribute pointer which is used to specify the attribute
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- *
- *  @discussion
- *                  When atrr is NULL, the functionality of the this function will be the same as
- *                  DNSServiceUpdateRecord().
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecordWithAttribute
-(
-    DNSServiceRef DNS_SD_NULLABLE sdRef,
-    DNSRecordRef DNS_SD_NULLABLE recordRef,
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void * DNS_SD_NULLABLE rdata,
-    uint32_t ttl,
-    const DNSServiceAttributeRef DNS_SD_NULLABLE attr
-);
-
-#if (defined(__clang__) && __clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnullability-completeness"
-#endif
-
-/*!
- *  @brief
- *                  Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
- *                  a record registered individually via DNSServiceRegisterRecord().
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by DNSServiceRegister() (if the
- *                  record being removed was registered via DNSServiceAddRecord()) or by
- *                  DNSServiceCreateConnection() (if the record being removed was registered via
- *                  DNSServiceRegisterRecord()).
- *
- *  @param RecordRef
- *                  A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
- *                  or DNSServiceRegisterRecord().
- *
- *  @param flags
- *                  Currently ignored, reserved for future use.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags
-);
-
-/*********************************************************************************************
-*
-*  Service Discovery
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceBrowse callback function
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceBrowse().
- *
- *  @param flags
- *                  Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
- *                  See flag definitions for details.
- *
- *  @param interfaceIndex
- *                  The interface on which the service is advertised. This index should
- *                  be passed to DNSServiceResolve() when resolving the service.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- *  @param serviceName
- *                  The discovered service name. This name should be displayed to the user,
- *                  and stored for subsequent use in the DNSServiceResolve() call.
- *
- *  @param regtype
- *                  The service type, which is usually (but not always) the same as was passed
- *                  to DNSServiceBrowse(). One case where the discovered service type may
- *                  not be the same as the requested service type is when using subtypes:
- *                  The client may want to browse for only those ftp servers that allow
- *                  anonymous connections. The client will pass the string "_ftp._tcp,_anon"
- *                  to DNSServiceBrowse(), but the type of the service that's discovered
- *                  is simply "_ftp._tcp". The regtype for each discovered service instance
- *                  should be stored along with the name, so that it can be passed to
- *                  DNSServiceResolve() when the service is later resolved.
- *
- *  @param replyDomain
- *                  The domain of the discovered service instance. This may or may not be the
- *                  same as the domain that was passed to DNSServiceBrowse(). The domain for each
- *                  discovered service instance should be stored along with the name, so that
- *                  it can be passed to DNSServiceResolve() when the service is later resolved.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceBrowseReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char *serviceName,
-    const char *regtype,
-    const char *replyDomain,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Browse for instances of a service.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the browse operation
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to browse for services
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to browse on all available
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param regtype
- *                  The service type being browsed for followed by the protocol, separated by a
- *                  dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
- *                  A client may optionally specify a single subtype to perform filtered browsing:
- *                  e.g. browsing for "_primarytype._tcp,_subtype" will discover only those
- *                  instances of "_primarytype._tcp" that were registered specifying "_subtype"
- *                  in their list of registered subtypes.
- *
- *  @param domain
- *                  If non-NULL, specifies the domain on which to browse for services.
- *                  Most applications will not specify a domain, instead browsing on the
- *                  default domain(s).
- *
- *  @param callBack
- *                  The function to be called when an instance of the service being browsed for
- *                  is found, or if the call asynchronously fails.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *regtype,
-    const char *domain,            /* may be NULL */
-    DNSServiceBrowseReply callBack,
-    void *context
-);
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceResolve callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceResolve().
- *
- *  @param flags
- *                  Possible values: kDNSServiceFlagsMoreComing
- *
- *  @param interfaceIndex
- *                  The interface on which the service was resolved.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- *  @param fullname
- *                  The full service domain name, in the form <servicename>.<protocol>.<domain>.
- *                  (This name is escaped following standard DNS rules, making it suitable for
- *                  passing to standard system DNS APIs such as res_query(), or to the
- *                  special-purpose functions included in this API that take fullname parameters.
- *                  See "Notes on DNS Name Escaping" earlier in this file for more details.)
- *
- *  @param hosttarget
- *                  The target hostname of the machine providing the service. This name can
- *                  be passed to functions like gethostbyname() to identify the host's IP address.
- *
- *  @param port
- *                  The port, in network byte order, on which connections are accepted for this service.
- *
- *  @param txtLen
- *                  The length of the txt record, in bytes.
- *
- *  @param txtRecord
- *                  The service's primary txt record, in standard txt record format.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceResolveReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char *fullname,
-    const char *hosttarget,
-    uint16_t port,                  /* In network byte order */
-    uint16_t txtLen,
-    const unsigned char *txtRecord,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
- *                  txt record.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the resolve operation
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  Specifying kDNSServiceFlagsForceMulticast will cause query to be
- *                  performed with a link-local mDNS query, even if the name is an
- *                  apparently non-local name (i.e. a name not ending in ".local.")
- *
- *  @param interfaceIndex
- *                  The interface on which to resolve the service. If this resolve call is
- *                  as a result of a currently active DNSServiceBrowse() operation, then the
- *                  interfaceIndex should be the index reported in the DNSServiceBrowseReply
- *                  callback. If this resolve call is using information previously saved
- *                  (e.g. in a preference file) for later use, then use interfaceIndex 0, because
- *                  the desired service may now be reachable via a different physical interface.
- *                  See "Constants for specifying an interface index" for more details.
- *
- *  @param name
- *                  The name of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- *  @param regtype
- *                  The type of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- *  @param domain
- *                  The domain of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- *  @param callBack
- *                  The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- *  @discussion
- *                  Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
- *                  DNSServiceQueryRecord() instead, as it is more efficient for this task.
- *
- *                  Note: When the desired results have been returned, the client MUST terminate the resolve by calling
- *                  DNSServiceRefDeallocate().
- *
- *                  Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
- *                  and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
- *                  DNSServiceQueryRecord() should be used.
- *
- *                  NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
- *                  This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
- *                  Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
- *                  These should be fixed by updating your own callback function definition to match the corrected
- *                  function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
- *                  bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
- *                  as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
- *                  If you need to maintain portable code that will compile cleanly with both the old and new versions of
- *                  this header file, you should update your callback function definition to use the correct unsigned value,
- *                  and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
- *                  the compiler warning, e.g.:
- *                  DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
- *                  This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
- *                  with both the old header and with the new corrected version.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,
-    const char *regtype,
-    const char *domain,
-    DNSServiceResolveReply callBack,
-    void *context
-);
-
-/*********************************************************************************************
-*
-*  Querying Individual Specific Records
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceQueryRecord callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceQueryRecord().
- *
- *  @param flags
- *                  Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
- *                  with a ttl of 0, i.e. "Remove" events.
- *
- *  @param interfaceIndex
- *                  The interface on which the query was resolved (the index for a given
- *                  interface is determined via the if_nametoindex() family of calls).
- *                  See "Constants for specifying an interface index" for more details.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  errorCode is nonzero.
- *
- *  @param fullname
- *                  The resource record's full domain name.
- *
- *  @param rrtype
- *                  The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN).
- *
- *  @param rdlen
- *                  The length, in bytes, of the resource record rdata.
- *
- *  @param rdata
- *                  The raw rdata of the resource record.
- *
- *  @param ttl
- *                  If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise. The ttl value is not
- *                  updated when the daemon answers from the cache, hence relying on
- *                  the accuracy of the ttl value is not recommended.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceQueryRecordReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Query for an arbitrary DNS record.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the query operation
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query to a unicast DNS server that implements the protocol. This flag
- *                  has no effect on link-local multicast queries.
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to issue the query
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the name to be queried for on all
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param fullname
- *                  The full domain name of the resource record to be queried for.
- *
- *  @param rrtype
- *                  The numerical type of the resource record to be queried for
- *                  (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN).
- *
- *  @param callBack
- *                  The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result:
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    DNSServiceQueryRecordReply callBack,
-    void *context
-);
-
-/*********************************************************************************************
-*
-*  Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceGetAddrInfo callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceGetAddrInfo().
- *
- *  @param flags
- *                  Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd.
- *
- *  @param interfaceIndex
- *                  The interface to which the answers pertain.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred.  Other parameters are
- *                  undefined if errorCode is nonzero.
- *
- *  @param hostname
- *                  The fully qualified domain name of the host to be queried for.
- *
- *  @param address
- *                  IPv4 or IPv6 address.
- *
- *  @param ttl
- *                  If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise. The ttl value is not
- *                  updated when the daemon answers from the cache, hence relying on
- *                  the accuracy of the ttl value is not recommended.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceGetAddrInfoReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char *hostname,
-    const struct sockaddr *address,
-    uint32_t ttl,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the address query operation
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  kDNSServiceFlagsForceMulticast
- *
- *  @param interfaceIndex
- *                  The interface on which to issue the query.  Passing 0 causes the query to be
- *                  sent on all active interfaces via Multicast or the primary interface via Unicast.
- *
- *  @param protocol
- *                  Pass in kDNSServiceProtocol_IPv4 to look up IPv4 addresses, or kDNSServiceProtocol_IPv6
- *                  to look up IPv6 addresses, or both to look up both kinds. If neither flag is
- *                  set, the system will apply an intelligent heuristic, which is (currently)
- *                  that it will attempt to look up both, except:
- *
- *                  * If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
- *                  but this host has no routable IPv6 address, then the call will not try to
- *                  look up IPv6 addresses for "hostname", since any addresses it found would be
- *                  unlikely to be of any use anyway. Similarly, if this host has no routable
- *                  IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
- *
- *  @param hostname
- *                  The fully qualified domain name of the host to be queried for.
- *
- *  @param callBack
- *                  The function to be called when the query succeeds or fails asynchronously.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceProtocol protocol,
-    const char *hostname,
-    DNSServiceGetAddrInfoReply callBack,
-    void *context
-);
-
-/*********************************************************************************************
-*
-*  Special Purpose Calls:
-*  DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord()
-*  (most applications will not use these)
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  Create a connection to the daemon allowing efficient registration of
- *                  multiple individual records.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef.
- *                  Deallocating the reference (via DNSServiceRefDeallocate())
- *                  severs the connection and cancels all operations and
- *                  deregisters all records registered on this connection.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success, otherwise returns
- *                  an error code indicating the specific failure that occurred
- *                  (in which case the DNSServiceRef is not initialized).
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceRegisterRecord callback function.
- *
- *  @param sdRef
- *                  The connected DNSServiceRef initialized by
- *                  DNSServiceCreateConnection().
- *
- *  @param RecordRef
- *                  The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
- *                  DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
- *                  invalidated, and may not be used further.
- *
- *  @param flags
- *                  Currently unused, reserved for future use.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags,
-    DNSServiceErrorType errorCode,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Register an individual resource record on a connected DNSServiceRef.
- *
- *  @param sdRef
- *                  A DNSServiceRef initialized by DNSServiceCreateConnection().
- *
- *  @param RecordRef
- *                  A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  (To deregister ALL records registered on a single connected DNSServiceRef
- *                  and deallocate each of their corresponding DNSServiceRecordRefs, call
- *                  DNSServiceRefDeallocate()).
- *
- *  @param flags
- *                  Required values are:
- *                  One of kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique flags.
- *
- *                  Possible values are:
- *                  kDNSServiceFlagsForceMulticast: If it is specified, the registration will be performed just like
- *                  a link-local mDNS registration even if the name is an apparently non-local name (i.e. a name not
- *                  ending in ".local.")
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to register the record
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the record to be registered on all interfaces.
- *                  See "Constants for specifying an interface index" for more details.
- *
- *  @param fullname
- *                  The full domain name of the resource record.
- *
- *  @param rrtype
- *                  The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN)
- *
- *  @param rdlen
- *                  Length, in bytes, of the rdata.
- *
- *  @param rdata
- *                  A pointer to the raw rdata, as it is to appear in the DNS record.
- *
- *  @param ttl
- *                  The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- *  @param callBack
- *                  The function to be called when a result is found, or if the call
- *                  asynchronously fails (e.g. because of a name conflict.)
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSRecordRef is
- *                  not initialized).
- *
- *  @discussion
- *                  Note that name conflicts occurring for records registered via this call must be handled
- *                  by the client in the callback.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef *RecordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    DNSServiceRegisterRecordReply callBack,
-    void *context
-);
-
-/*!
- *  @brief
- *                  Instruct the daemon to verify the validity of a resource record that appears
- *                  to be out of date (e.g. because TCP connection to a service's target failed.)
- *                  Causes the record to be flushed from the daemon's cache (as well as all other
- *                  daemons' caches on the network) if the record is determined to be invalid.
- *                  Use this routine conservatively. Reconfirming a record necessarily consumes
- *                  network bandwidth, so this should not be done indiscriminately.
- *
- *  @param flags
- *                  Not currently used.
- *
- *  @param interfaceIndex
- *                  Specifies the interface of the record in question.
- *                  The caller must specify the interface.
- *                  This API (by design) causes increased network traffic, so it requires
- *                  the caller to be precise about which record should be reconfirmed.
- *                  It is not possible to pass zero for the interface index to perform
- *                  a "wildcard" reconfirmation, where *all* matching records are reconfirmed.
- *
- *  @param fullname
- *                  The resource record's full domain name.
- *
- *  @param rrtype
- *                  The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN).
- *
- *  @param rdlen
- *                  The length, in bytes, of the resource record rdata.
- *
- *  @param rdata
- *                  The raw rdata of the resource record.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-(
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata
-);
-
-
-/*********************************************************************************************
-*
-*  NAT Port Mapping
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  The definition of the DNSServiceNATPortMappingCreate callback function.
- *
- *  @param sdRef
- *                  The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
- *
- *  @param flags
- *                  Currently unused, reserved for future use.
- *
- *  @param interfaceIndex
- *                  The interface through which the NAT gateway is reached.
- *
- *  @param errorCode
- *                  Will be kDNSServiceErr_NoError on success.
- *                  Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
- *                  more layers of NAT, in which case the other parameters have the defined values.
- *                  For other failures, will indicate the failure that occurred, and the other
- *                  parameters are undefined.
- *
- *  @param externalAddress
- *                  Four byte IPv4 address in network byte order.
- *
- *  @param protocol
- *                  Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
- *
- *  @param internalPort
- *                  The port on the local machine that was mapped.
- *
- *  @param externalPort
- *                  The actual external port in the NAT gateway that was mapped.
- *                  This is likely to be different than the requested external port.
- *
- *  @param ttl
- *                  The lifetime of the NAT port mapping created on the gateway.
- *                  This controls how quickly stale mappings will be garbage-collected
- *                  if the client machine crashes, suffers a power failure, is disconnected
- *                  from the network, or suffers some other unfortunate demise which
- *                  causes it to vanish without explicitly removing its NAT port mapping.
- *                  It's possible that the ttl value will differ from the requested ttl value.
- *
- *  @param context
- *                  The context pointer that was passed to the callout.
- */
-typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    uint32_t externalAddress,             /* four byte IPv4 address in network byte order */
-    DNSServiceProtocol protocol,
-    uint16_t internalPort,                /* In network byte order */
-    uint16_t externalPort,                /* In network byte order and may be different than the requested port */
-    uint32_t ttl,                         /* may be different than the requested ttl */
-    void *context
-);
-
-/*!
- *  @brief
- *                  Request a port mapping in the NAT gateway, which maps a port on the local machine
- *                  to an external port on the NAT.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the NAT port mapping
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *
- *  @param interfaceIndex
- *                  The interface on which to create port mappings in a NAT gateway.
- *                  Passing 0 causes the port mapping request to be sent on the primary interface.
- *
- *  @param protocol
- *                  To request a port mapping, pass in kDNSServiceProtocol_UDP, or kDNSServiceProtocol_TCP,
- *                  or (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP) to map both.
- *                  The local listening port number must also be specified in the internalPort parameter.
- *                  To just discover the NAT gateway's external IP address, pass zero for protocol,
- *                  internalPort, externalPort and ttl.
- *
- *  @param internalPort
- *                  The port number in network byte order on the local machine which is listening for packets.
- *
- *  @param externalPort
- *                  The requested external port in network byte order in the NAT gateway that you would
- *                  like to map to the internal port. Pass 0 if you don't care which external port is chosen for you.
- *
- *  @param ttl
- *                  The requested renewal period of the NAT port mapping, in seconds.
- *                  If the client machine crashes, suffers a power failure, is disconnected from
- *                  the network, or suffers some other unfortunate demise which causes it to vanish
- *                  unexpectedly without explicitly removing its NAT port mappings, then the NAT gateway
- *                  will garbage-collect old stale NAT port mappings when their lifetime expires.
- *                  Requesting a short TTL causes such orphaned mappings to be garbage-collected
- *                  more promptly, but consumes system resources and network bandwidth with
- *                  frequent renewal packets to keep the mapping from expiring.
- *                  Requesting a long TTL is more efficient on the network, but in the event of the
- *                  client vanishing, stale NAT port mappings will not be garbage-collected as quickly.
- *                  Most clients should pass 0 to use a system-wide default value.
- *
- *  @param callBack
- *                  The function to be called when the port mapping request succeeds or fails asynchronously.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- *
- *                  If you don't actually want a port mapped, and are just calling the API
- *                  because you want to find out the NAT's external IP address (e.g. for UI
- *                  display) then pass zero for protocol, internalPort, externalPort and ttl.
- *
- *  @discussion
- *                  The NAT should support either PCP, NAT-PMP or the
- *                  UPnP/IGD protocol for this API to create a successful mapping. Note that this API
- *                  currently supports IPv4 addresses/mappings only. If the NAT gateway supports PCP and
- *                  returns an IPv6 address (incorrectly, since this API specifically requests IPv4
- *                  addresses), the DNSServiceNATPortMappingReply callback will be invoked with errorCode
- *                  kDNSServiceErr_NATPortMappingUnsupported.
- *
- *                  The port mapping will be renewed indefinitely until the client process exits, or
- *                  explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
- *                  The client callback will be invoked, informing the client of the NAT gateway's
- *                  external IP address and the external port that has been allocated for this client.
- *                  The client should then record this external IP address and port using whatever
- *                  directory service mechanism it is using to enable peers to connect to it.
- *                  (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
- *                  -- when a client calls DNSServiceRegister() NAT mappings are automatically created
- *                  and the external IP address and port for the service are recorded in the global DNS.
- *                  Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
- *                  this API to explicitly map their own ports.)
- *
- *                  It's possible that the client callback could be called multiple times, for example
- *                  if the NAT gateway's IP address changes, or if a configuration change results in a
- *                  different external port being mapped for this client. Over the lifetime of any long-lived
- *                  port mapping, the client should be prepared to handle these notifications of changes
- *                  in the environment, and should update its recorded address and/or port as appropriate.
- *
- *                  NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
- *                  which were intentionally designed to help simplify client code:
- *
- *                  1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
- *                      In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
- *                      gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
- *                      NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
- *                      whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
- *                      a machine with multiple active network interfaces. Rather than make every client recreate
- *                      this logic for deciding whether a NAT mapping is required, the PortMapping API does that
- *                      work for you. If the client calls the PortMapping API when the machine already has a
- *                      routable public IP address, then instead of complaining about it and giving an error,
- *                      the PortMapping API just invokes your callback, giving the machine's public address
- *                      and your own port number. This means you don't need to write code to work out whether
- *                      your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
- *                      necessary, no harm is done:
- *
- *                      - If the machine already has a routable public IP address, then your callback
- *                        will just be invoked giving your own address and port.
- *                      - If a NAT mapping is required and obtained, then your callback will be invoked
- *                        giving you the external address and port.
- *                      - If a NAT mapping is required but not obtained from the local NAT gateway,
- *                        or the machine has no network connectivity, then your callback will be
- *                        invoked giving zero address and port.
- *
- *                  2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
- *                      network, it's the client's job to notice this, and work out whether a NAT mapping
- *                      is required on the new network, and make a new NAT mapping request if necessary.
- *                      The DNSServiceNATPortMappingCreate API does this for you, automatically.
- *                      The client just needs to make one call to the PortMapping API, and its callback will
- *                      be invoked any time the mapping state changes. This property complements point (1) above.
- *                      If the client didn't make a NAT mapping request just because it determined that one was
- *                      not required at that particular moment in time, the client would then have to monitor
- *                      for network state changes to determine if a NAT port mapping later became necessary.
- *                      By unconditionally making a NAT mapping request, even when a NAT mapping not to be
- *                      necessary, the PortMapping API will then begin monitoring network state changes on behalf of
- *                      the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
- *                      mapping and inform the client with a new callback giving the new address and port information.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceProtocol protocol,                      /* TCP and/or UDP          */
-    uint16_t internalPort,                            /* network byte order      */
-    uint16_t externalPort,                            /* network byte order      */
-    uint32_t ttl,                                     /* time to live in seconds */
-    DNSServiceNATPortMappingReply callBack,
-    void *context
-);
-
-/*********************************************************************************************
-*
-*  General Utility Functions
-*
-*********************************************************************************************/
-
-/*!
- *  @brief
- *                  Concatenate a three-part domain name (as returned by the above callbacks) into a
- *                  properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
- *                  strings where necessary.
- *
- *  @param fullName
- *                  A pointer to a buffer that where the resulting full domain name is to be written.
- *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
- *                  accommodate the longest legal domain name without buffer overrun.
- *
- *  @param service
- *                  The service name - any dots or backslashes must NOT be escaped.
- *                  May be NULL (to construct a PTR record name, e.g.
- *                  "_ftp._tcp.apple.com.").
- *
- *  @param regtype
- *                  The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp").
- *
- *  @param domain
- *                  The domain name, e.g. "apple.com.". Literal dots or backslashes,
- *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
- *
- *  @result:
- *                  Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
-(
-    char * const fullName,
-    const char * const service,      /* may be NULL */
-    const char * const regtype,
-    const char * const domain
-);
-
-/*********************************************************************************************
-*
-*   TXT Record Construction Functions
-*
-*********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record construction is something like:
- *
- * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
- * TXTRecordCreate();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * ...
- * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
- * TXTRecordDeallocate();
- * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
- */
-
-
-/* TXTRecordRef
- *
- * Opaque internal data type.
- * Note: Represents a DNS-SD TXT record.
- */
-
-typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
-
-
-/*!
- *  @brief
- *                  Creates a new empty TXTRecordRef referencing the specified storage.
- *
- *  @param txtRecord
- *                  A pointer to an uninitialized TXTRecordRef.
- *
- *  @param bufferLen
- *                  The size of the storage provided in the "buffer" parameter.
- *
- *  @param buffer
- *                  Optional caller-supplied storage used to hold the TXTRecord data.
- *                  This storage must remain valid for as long as
- *                  the TXTRecordRef.
- *  @discussion
- *                  If the buffer parameter is NULL, or the specified storage size is not
- *                  large enough to hold a key subsequently added using TXTRecordSetValue(),
- *                  then additional memory will be added as needed using malloc(). Note that
- *                  an existing TXT record buffer should not be passed to TXTRecordCreate
- *                  to create a copy of another TXT Record. The correct way to copy TXTRecordRef
- *                  is creating an empty TXTRecordRef with TXTRecordCreate() first, and using
- *                  TXTRecordSetValue to set the same value.
- *
- *                  On some platforms, when memory is low, malloc() may fail. In this
- *                  case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
- *                  error condition will need to be handled as appropriate by the caller.
- *
- *                  You can avoid the need to handle this error condition if you ensure
- *                  that the storage you initially provide is large enough to hold all
- *                  the key/value pairs that are to be added to the record.
- *                  The caller can precompute the exact length required for all of the
- *                  key/value pairs to be added, or simply provide a fixed-sized buffer
- *                  known in advance to be large enough.
- *                  A no-value (key-only) key requires  (1 + key length) bytes.
- *                  A key with empty value requires     (1 + key length + 1) bytes.
- *                  A key with non-empty value requires (1 + key length + 1 + value length).
- *                  For most applications, DNS-SD TXT records are generally
- *                  less than 100 bytes, so in most cases a simple fixed-sized
- *                  256-byte buffer will be more than sufficient.
- *                  Recommended size limits for DNS-SD TXT Records are discussed in RFC 6763
- *                  <https://tools.ietf.org/html/rfc6763#section-6.2>
- *
- *                  Note: When passing parameters to and from these TXT record APIs,
- *                  the key name does not include the '=' character. The '=' character
- *                  is the separator between the key and value in the on-the-wire
- *                  packet format; it is not part of either the key or the value.
- */
-DNSSD_EXPORT
-void DNSSD_API TXTRecordCreate
-(
-    TXTRecordRef *txtRecord,
-    uint16_t bufferLen,
-    void *buffer
-);
-
-/*!
- *  @brief
- *                  Releases any resources allocated in the course of preparing a TXT Record
- *                  using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
- *                  Ownership of the buffer provided in TXTRecordCreate() returns to the client.
- *
- *  @param txtRecord
- *                  A TXTRecordRef initialized by calling TXTRecordCreate().
- */
-DNSSD_EXPORT
-void DNSSD_API TXTRecordDeallocate
-(
-    TXTRecordRef *txtRecord
-);
-
-/*!
- *  @brief
- *                  Adds a key (optionally with value) to a TXTRecordRef.
- *
- *  @param txtRecord
- *                  A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- *  @param key
- *                  A null-terminated string which only contains printable ASCII
- *                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
- *                  9 characters or fewer (not counting the terminating null).
- *
- *  @param valueSize
- *                  The size of the value.
- *
- *  @param value
- *                  Any binary value. For values that represent
- *                  textual data, UTF-8 is STRONGLY recommended.
- *                  For values that represent textual data, valueSize
- *                  should NOT include the terminating null (if any)
- *                  at the end of the string.
- *                  If NULL, then "key" will be added with no value.
- *                  If non-NULL but valueSize is zero, then "key=" will be
- *                  added with empty value.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_Invalid if the "key" string contains
- *                  illegal characters.
- *                  Returns kDNSServiceErr_NoMemory if adding this key would
- *                  exceed the available storage.
- *
- *  @discussion
- *                  If the "key" already
- *                  exists in the TXTRecordRef, then the current value will be replaced with
- *                  the new value.
- *                  Keys may exist in four states with respect to a given TXT record:
- *                   - Absent (key does not appear at all)
- *                   - Present with no value ("key" appears alone)
- *                   - Present with empty value ("key=" appears in TXT record)
- *                   - Present with non-empty value ("key=value" appears in TXT record)
- *                  For more details refer to "Data Syntax for DNS-SD TXT Records" in RFC 6763
- *                  <https://tools.ietf.org/html/rfc6763#section-6>
-*/
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API TXTRecordSetValue
-(
-    TXTRecordRef *txtRecord,
-    const char *key,
-    uint8_t valueSize,           /* may be zero */
-    const void *value            /* may be NULL */
-);
-
-/*!
- *  @brief
- *                  Removes a key from a TXTRecordRef. The "key" must be an
- *                  ASCII string which exists in the TXTRecordRef.
- *
- *  @param txtRecord
- *                  A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- *  @param key
- *                  A key name which exists in the TXTRecordRef.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoSuchKey if the "key" does not
- *                  exist in the TXTRecordRef.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
-(
-    TXTRecordRef *txtRecord,
-    const char *key
-);
-
-/*!
- *  @brief
- *                  Allows you to determine the length of the raw bytes within a TXTRecordRef.
- *
- *  @param txtRecord
- *                  A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- *  @result
- *                  Returns the size of the raw bytes inside a TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- *                  Returns 0 if the TXTRecordRef is empty.
- */
-DNSSD_EXPORT
-uint16_t DNSSD_API TXTRecordGetLength
-(
-    const TXTRecordRef *txtRecord
-);
-
-/*!
- *  @brief
- *                  Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
- *
- *  @param txtRecord
- *                  A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- *  @result
- *                  Returns a pointer to the raw bytes inside the TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- */
-DNSSD_EXPORT
-const void * DNSSD_API TXTRecordGetBytesPtr
-(
-    const TXTRecordRef *txtRecord
-);
-
-/*********************************************************************************************
-*
-*   TXT Record Parsing Functions
-*
-*********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record parsing is something like:
- *
- * Receive TXT record data in DNSServiceResolve() callback
- * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
- * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
- * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
- * ...
- * memcpy(myval1, val1ptr, len1);
- * memcpy(myval2, val2ptr, len2);
- * ...
- * return;
- *
- * If you wish to retain the values after return from the DNSServiceResolve()
- * callback, then you need to copy the data to your own storage using memcpy()
- * or similar, as shown in the example above.
- *
- * If for some reason you need to parse a TXT record you built yourself
- * using the TXT record construction functions above, then you can do
- * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
- * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
- *
- * Most applications only fetch keys they know about from a TXT record and
- * ignore the rest.
- * However, some debugging tools wish to fetch and display all keys.
- * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
- */
-
-/*!
- *  @brief
- *                  Allows you to determine if a given TXT Record contains a specified key.
- *
- *  @param txtLen
- *                  The size of the received TXT Record.
- *
- *  @param txtRecord
- *                  Pointer to the received TXT Record bytes.
- *
- *  @param key
- *                  A null-terminated ASCII string containing the key name.
- *
- *  @result
- *                  Returns 1 if the TXT Record contains the specified key.
- *                  Otherwise, it returns 0.
- */
-DNSSD_EXPORT
-int DNSSD_API TXTRecordContainsKey
-(
-    uint16_t txtLen,
-    const void *txtRecord,
-    const char *key
-);
-
-/*!
- *  @brief
- *                  Allows you to retrieve the value for a given key from a TXT Record.
- *
- *  @param txtLen
- *                  The size of the received TXT Record
- *
- *  @param txtRecord
- *                  Pointer to the received TXT Record bytes.
- *
- *  @param key
- *                  A null-terminated ASCII string containing the key name.
- *
- *  @param valueLen
- *                  On output, will be set to the size of the "value" data.
- *
- *  @discussion
- *                  Returns NULL if the key does not exist in this TXT record,
- *                  or exists with no value (to differentiate between
- *                  these two cases use TXTRecordContainsKey()).
- *                  Returns pointer to location within TXT Record bytes
- *                  if the key exists with empty or non-empty value.
- *                  For empty value, valueLen will be zero.
- *                  For non-empty value, valueLen will be length of value data.
- */
-DNSSD_EXPORT
-const void * DNSSD_API TXTRecordGetValuePtr
-(
-    uint16_t txtLen,
-    const void *txtRecord,
-    const char *key,
-    uint8_t *valueLen
-);
-
-/*!
- *  @brief
- *                  Returns the number of keys stored in the TXT Record. The count
- *                  can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
- *
- *  @param txtLen
- *                  The size of the received TXT Record.
- *
- *  @param txtRecord
- *                  Pointer to the received TXT Record bytes.
- *
- *  @result
- *                  Returns the total number of keys in the TXT Record.
- */
-DNSSD_EXPORT
-uint16_t DNSSD_API TXTRecordGetCount
-(
-    uint16_t txtLen,
-    const void *txtRecord
-);
-
-/*!
- *  @brief
- *                  Allows you to retrieve a key name and value pointer, given an index into
- *                  a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
- *                  It's also possible to iterate through keys in a TXT record by simply
- *                  calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
- *                  and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
- *
- *
- *  @param txtLen
- *                  The size of the received TXT Record.
- *
- *  @param txtRecord
- *                  Pointer to the received TXT Record bytes.
- *
- *  @param itemIndex
- *                  An index into the TXT Record.
- *
- *  @param keyBufLen
- *                  The size of the string buffer being supplied.
- *
- *  @param key
- *                  A string buffer used to store the key name.
- *                  On return, the buffer contains a null-terminated C-string
- *                  giving the key name. DNS-SD TXT keys are usually
- *                  9 characters or fewer. To hold the maximum possible
- *                  key name, the buffer should be 256 bytes long.
- *
- *  @param valueLen
- *                  On output, will be set to the size of the "value" data.
- *
- *  @param value
- *                  On output, *value is set to point to location within TXT
- *                  Record bytes that holds the value data.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
- *                  Returns kDNSServiceErr_Invalid if index is greater than
- *                  TXTRecordGetCount()-1.
- *                  On return:
- *                  For keys with no value, *value is set to NULL and *valueLen is zero.
- *                  For keys with empty value, *value is non-NULL and *valueLen is zero.
- *                  For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
-(
-    uint16_t txtLen,
-    const void *txtRecord,
-    uint16_t itemIndex,
-    uint16_t keyBufLen,
-    char *key,
-    uint8_t *valueLen,
-    const void **value
-);
-
-#if _DNS_SD_LIBDISPATCH
-/*!
- *  @brief
- *                  Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous
- *                  callbacks.  It's the clients responsibility to ensure that the provided dispatch queue is running.
- *
- *  @param service
- *                  DNSServiceRef that was allocated and returned to the application, when the
- *                  application calls one of the DNSService API.
- *
- *  @param queue
- *                  dispatch queue where the application callback will be scheduled
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source
- *                  Returns kDNSServiceErr_BadParam if the service param is invalid or the
- *                  queue param is invalid
- *
- *  @discussion
- *                  A typical application that uses CFRunLoopRun or dispatch_main on its main thread will
- *                  usually schedule DNSServiceRefs on its main queue (which is always a serial queue)
- *                  using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());"
- *
- *                  If there is any error during the processing of events, the application callback will
- *                  be called with an error code. For shared connections, each subordinate DNSServiceRef
- *                  will get its own error callback. Currently these error callbacks only happen
- *                  if the daemon is manually terminated or crashes, and the error
- *                  code in this case is kDNSServiceErr_ServiceNotRunning. The application must call
- *                  DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code.
- *                  These error callbacks are rare and should not normally happen on customer machines,
- *                  but application code should be written defensively to handle such error callbacks
- *                  gracefully if they occur.
- *
- *                  After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult
- *                  on the same DNSServiceRef will result in undefined behavior and should be avoided.
- *
- *                  Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using
- *                  DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use
- *                  DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch
- *                  queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until
- *                  the application no longer requires that operation and terminates it using DNSServiceRefDeallocate.
- *                  Note that the call to DNSServiceRefDeallocate() must be done on the same queue originally passed
- *                  as an argument to DNSServiceSetDispatchQueue().
-*/
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
-(
-    DNSServiceRef service,
-    dispatch_queue_t queue
-);
-#endif //_DNS_SD_LIBDISPATCH
-
-#if !defined(_WIN32)
-typedef void (DNSSD_API *DNSServiceSleepKeepaliveReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceErrorType errorCode,
-    void *context
-);
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    int fd,
-    unsigned int timeout,
-    DNSServiceSleepKeepaliveReply callBack,
-    void *context
-);
-#endif
-
-/* Some C compiler cleverness. We can make the compiler check certain things for us,
- * and report errors at compile-time if anything is wrong. The usual way to do this would
- * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, 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_DNS_SD
-{
-    char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
-};
-
-#if (defined(__clang__) && __clang__)
-#pragma clang diagnostic pop
-#endif
-
-/*!
- *  @result
- *                  Returns a DNSServiceAttribute pointer.
- */
-DNSSD_EXPORT
-DNSServiceAttributeRef DNSSD_API DNS_SD_NULLABLE DNSServiceAttributeCreate(void);
-
-/*!
- *  @brief
- *                  Set the aaaa_policy value in attr.
- *
- *  @param attr
- *                  DNSServiceAttribute pointer.
- *  @param policy
- *                  DNSServiceAAAAPolicy enum value.
- *  @result
- *                  Returns kDNSServiceErr_NoError.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceAttributeSetAAAAPolicy
-(
-    DNSServiceAttributeRef DNS_SD_NONNULL attr,
-    DNSServiceAAAAPolicy policy
-);
-
-/*!
- *  @brief
- *                  Set the timestamp value in attr.
- *
- *  @param attr
- *                  DNSServiceAttribute pointer.
- *  @param timestamp
- *                  Relative time in seconds. Should be zero if the timestamp is now,
- *                  30 if the timestamp is 30 seconds in the past, and so on.
- *  @result
- *                  Returns kDNSServiceErr_NoError.
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceAttributeSetTimestamp
-(
-    DNSServiceAttributeRef DNS_SD_NONNULL attr,
-    uint32_t timestamp
-);
-
-/*!
- *  @brief
- *                  Free DNSServiceAttribute pointer pointed by attr,
- *
- *  @param attr
- *                  An DNSServiceAttribute pointer(may be NULL).
- */
-DNSSD_EXPORT
-void DNSSD_API DNSServiceAttributeDeallocate
-(
-    DNSServiceAttributeRef DNS_SD_NONNULL attr
-);
-
-/*!
- *  @brief
- *                  DNSServiceQueryRecordWithAttribute is an extention to API DNSServiceQueryRecord,
- *                  accepting another parameter with type DNSServiceAttributeRef to specify extra attributes.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the service registration
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query to a unicast DNS server that implements the protocol. This flag
- *                  has no effect on link-local multicast queries.
- *
- *  @param ifindex
- *                  If non-zero, specifies the interface on which to register the service
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to register on all
- *                  available interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param name
- *                  The full domain name of the resource record to be queried for.
- *
- *  @param rrtype
- *                  The numerical type of the resource record to be queried for
- *                  (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN).
- *
- *  @param attr
- *                  An DNSServiceAttribute pointer which is used to specify the attribute
- *                  (may be NULL).
- *
- *  @param callback
- *                  The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- *
- *  @discussion
- *                  When atrr is NULL, the functionality of the this function will be the same as
- *                  DNSServiceQueryRecord().
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecordWithAttribute
-(
-    DNSServiceRef DNS_SD_NONNULL * DNS_SD_NULLABLE sdRef,
-    DNSServiceFlags flags,
-    uint32_t ifindex,
-    const char * DNS_SD_NULLABLE name,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    const DNSServiceAttribute * DNS_SD_NULLABLE attr,
-    DNSServiceQueryRecordReply DNS_SD_NULLABLE callback,
-    void * DNS_SD_NULLABLE context
-);
-
-/*!
- *  @brief
- *                  DNSServiceRegisterWithAttribute is an extention to API DNSServiceRegister,
- *                  accepting another parameter with type DNSServiceAttributeRef to specify extra attributes.
- *
- *  @param sdRef
- *                  A pointer to an uninitialized DNSServiceRef
- *                  (or, if the kDNSServiceFlagsShareConnection flag is used,
- *                  a copy of the shared connection reference that is to be used).
- *                  If the call succeeds then it initializes (or updates) the DNSServiceRef,
- *                  returns kDNSServiceErr_NoError, and the service registration
- *                  will remain active indefinitely until the client terminates it
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate()
- *                  (or by closing the underlying shared connection, if used).
- *
- *  @param flags
- *                  Possible values are:
- *                  kDNSServiceFlagsShareConnection to use a shared connection.
- *                  Other flags indicate the renaming behavior on name conflict
- *                  (not required for most applications).
- *                  See flag definitions above for details.
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to register the service
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to register on all
- *                  available interfaces. See "Constants for specifying an interface index" for more details.
- *
- *  @param name
- *                  If non-NULL, specifies the service name to be registered.
- *                  Most applications will not specify a name, in which case the computer
- *                  name is used (this name is communicated to the client via the callback).
- *                  If a name is specified, it must be 1-63 bytes of UTF-8 text.
- *                  If the name is longer than 63 bytes it will be automatically truncated
- *                  to a legal length, unless the NoAutoRename flag is set,
- *                  in which case kDNSServiceErr_BadParam will be returned.
- *
- *  @param regtype
- *                  The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp"). The service type must be an underscore, followed
- *                  by 1-15 characters, which may be letters, digits, or hyphens.
- *                  The transport protocol must be "_tcp" or "_udp". New service types
- *                  should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
- *
- *                  Additional subtypes of the primary service type (where a service
- *                  type has defined subtypes) follow the primary service type in a
- *                  comma-separated list, with no additional spaces, e.g.
- *                      "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
- *                  Subtypes provide a mechanism for filtered browsing: A client browsing
- *                  for "_primarytype._tcp" will discover all instances of this type;
- *                  a client browsing for "_primarytype._tcp,_subtype2" will discover only
- *                  those instances that were registered with "_subtype2" in their list of
- *                  registered subtypes.
- *
- *                  The subtype mechanism can be illustrated with some examples using the
- *                  dns-sd command-line tool:
- *
- *                  % dns-sd -R Simple _test._tcp "" 1001 &
- *                  % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
- *                  % dns-sd -R Best   _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
- *
- *                  Now:
- *                  % dns-sd -B _test._tcp             # will find all three services
- *                  % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
- *                  % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
- *
- *                  Subtype labels may be up to 63 bytes long, and may contain any eight-
- *                  bit byte values, including zero bytes. However, due to the nature of
- *                  using a C-string-based API, conventional DNS escaping must be used for
- *                  dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
- *
- *                  % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
- *
- *  @param domain
- *                  If non-NULL, specifies the domain on which to advertise the service.
- *                  Most applications will not specify a domain, instead automatically
- *                  registering in the default domain(s).
- *
- *  @param host
- *                  If non-NULL, specifies the SRV target host name. Most applications
- *                  will not specify a host, instead automatically using the machine's
- *                  default host name(s). Note that specifying a non-NULL host does NOT
- *                  create an address record for that host - the application is responsible
- *                  for ensuring that the appropriate address record exists, or creating it
- *                  via DNSServiceRegisterRecord().
- *
- *  @param PortInNetworkByteOrder
- *                  The port, in network byte order, on which the service accepts connections.
- *                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
- *                  by browsing, but will cause a name conflict if another client tries to
- *                  register that same name). Most clients will not use placeholder services.
- *
- *  @param txtLen
- *                  The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
- *
- *  @param txtRecord
- *                  The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
- *                  TXT record, i.e. <length byte> <data> <length byte> <data> ...
- *                  Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
- *                  i.e. it creates a TXT record of length one containing a single empty string.
- *                  RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
- *                  string is the smallest legal DNS TXT record.
- *                  As with the other parameters, the DNSServiceRegister call copies the txtRecord
- *                  data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
- *                  then you can safely free that memory right after the DNSServiceRegister call returns.
- *
- *  @param attr
- *                  An DNSServiceAttribute pointer which is used to specify the attribute
- *                  (may be NULL).
- *
- *  @param callBack
- *                  The function to be called when the registration completes or asynchronously
- *                  fails. The client MAY pass NULL for the callback -  The client will NOT be notified
- *                  of the default values picked on its behalf, and the client will NOT be notified of any
- *                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
- *                  of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
- *                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- *
- *  @discussion
- *                  When atrr is NULL, the functionality of the this function will be the same as
- *                  DNSServiceRegister().
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceRegisterWithAttribute
-(
-    DNSServiceRef DNS_SD_NONNULL * DNS_SD_NULLABLE sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char * DNS_SD_NULLABLE name,
-    const char * DNS_SD_NULLABLE regtype,
-    const char * DNS_SD_NULLABLE domain,
-    const char * DNS_SD_NULLABLE host,
-    uint16_t portInNetworkByteOrder,
-    uint16_t txtLen,
-    const void * DNS_SD_NULLABLE txtRecord,
-    const DNSServiceAttributeRef DNS_SD_NULLABLE attr,
-    DNSServiceRegisterReply DNS_SD_NULLABLE callBack,
-    void * DNS_SD_NULLABLE context
-);
-
-/*!
- *  @brief
- *                  DNSServiceRegisterRecordWithAttribute is an extention to API DNSServiceRegisterRecord,
- *                  accepting another parameter with type DNSServiceAttributeRef to specify extra attributes.
- *
- *  @param sdRef
- *                  The connected DNSServiceRef that was initialized by DNSServiceCreateConnection().
- *
- *  @param flags
- *                  Required values are:
- *                  One of kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique flags.
- *
- *                  Possible values are:
- *                  kDNSServiceFlagsForceMulticast: If it is specified, the registration will be performed just like
- *                  a link-local mDNS registration even if the name is an apparently non-local name (i.e. a name not
- *                  ending in ".local.")
- *
- *  @param interfaceIndex
- *                  If non-zero, specifies the interface on which to register the record
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the record to be registered on all interfaces.
- *                  See "Constants for specifying an interface index" for more details.
- *
- *  @param fullname
- *                  The full domain name of the resource record.
- *
- *  @param rrtype
- *                  The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- *  @param rrclass
- *                  The class of the resource record (usually kDNSServiceClass_IN)
- *
- *  @param rdlen
- *                  Length, in bytes, of the rdata.
- *
- *  @param rdata
- *                  A pointer to the raw rdata, as it is to appear in the DNS record.
- *
- *  @param ttl
- *                  The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- *  @param attr
- *                  An DNSServiceAttribute pointer which is used to specify the attribute
- *                  (may be NULL).
- *
- *  @param callBack
- *                  The function to be called when a result is found, or if the call
- *                  asynchronously fails (e.g. because of a name conflict.)
- *
- *  @param context
- *                  An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- *
- *  @discussion
- *                  When atrr is NULL, the functionality of the this function will be the same as
- *                  DNSServiceRegister().
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecordWithAttribute
-(
-    DNSServiceRef DNS_SD_NULLABLE sdRef,
-    DNSRecordRef DNS_SD_NONNULL * DNS_SD_NULLABLE recordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char * DNS_SD_NULLABLE fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void * DNS_SD_NULLABLE rdata,
-    uint32_t ttl,
-    const DNSServiceAttributeRef DNS_SD_NULLABLE attr,
-    DNSServiceRegisterRecordReply DNS_SD_NULLABLE callBack,
-    void * DNS_SD_NULLABLE context
-);
-
-/*!
- *  @brief
- *                  Send all the queued requests to server in scatter/gather IO.
- *
- *  @param sdRef
- *                  The connected DNSServiceRef that was initialized by DNSServiceCreateConnection.
- *
- *  @result
- *                  Returns kDNSServiceErr_NoError on success;
- *                  Returns kDNSServiceErr_BadParam if the DNSServiceRef is not initialized;
- *                  Returns kDNSServiceErr_Invalid if there is no queued request;
- *                  Returns kDNSServiceErr_NoMemory if memory allocation fail.
- *
- *  @discussion
- *                  The queued requests will be freed in this function.
- *                  Example of usage:
- *                  DNSServiceCreateConnection(sdRef)                                 //create DNSServiceRef
- *                  DNSServiceRegisterRecord with flag kDNSServiceFlagsQueueRequest   //create and queue request
- *                  DNSServiceRegisterRecord with flag kDNSServiceFlagsQueueRequest   //create and queue another request
- *                  DNSServiceSendQueuedRequests(sdRef)                               //send the queued requests
- */
-DNSSD_EXPORT
-DNSServiceErrorType DNSSD_API DNSServiceSendQueuedRequests
-(
-    DNSServiceRef DNS_SD_NULLABLE sdRef
-);
-
-__END_DECLS
-
-#endif  /* _DNS_SD_H */
diff --git a/mDNSShared/dns_sd_internal.h b/mDNSShared/dns_sd_internal.h
deleted file mode 100644
index 85a8a00..0000000
--- a/mDNSShared/dns_sd_internal.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2016-2020 Apple 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
- *
- *     https://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.
- */
-
-#ifndef _DNS_SD_INTERNAL_H
-#define _DNS_SD_INTERNAL_H
-
-// The mDNSResponder daemon doesn't call the private DNS-SD API.
-
-
-#include "dns_sd_private.h"
-
-#endif  // _DNS_SD_INTERNAL_H
diff --git a/mDNSShared/dns_sd_private.h b/mDNSShared/dns_sd_private.h
deleted file mode 100644
index ec0fefd..0000000
--- a/mDNSShared/dns_sd_private.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2015-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef _DNS_SD_PRIVATE_H
-#define _DNS_SD_PRIVATE_H
-
-#include <dns_sd.h>
-
-
-    #define DNS_SD_ENUM_SPI_AVAILABLE(...)
-
-#define DNS_SD_ENUM_SPI_AVAILABLE_FALL_2021 DNS_SD_ENUM_SPI_AVAILABLE(macos(12.0), ios(15.0), tvos(15.0), watchos(8.0))
-#define DNS_SD_ENUM_SPI_AVAILABLE_FALL_2022 DNS_SD_ENUM_SPI_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
-
-__BEGIN_DECLS
-
-// Private flags (kDNSServiceFlagsPrivateOne, kDNSServiceFlagsPrivateTwo, kDNSServiceFlagsPrivateThree, kDNSServiceFlagsPrivateFour, kDNSServiceFlagsPrivateFive) from dns_sd.h
-enum
-{
-    kDNSServiceFlagsDenyConstrained        = 0x2000,
-    /*
-     * This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict
-     * DNS resolutions on interfaces defined as constrained for that request.
-     */
-
-    kDNSServiceFlagsDenyCellular           = 0x8000000,
-    /*
-     * This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict
-     * DNS resolutions on the cellular interface for that request.
-     */
-    kDNSServiceFlagsServiceIndex           = 0x10000000,
-    /*
-     * This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries.
-     * When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call
-     * as the "serviceIndex".
-     */
-
-    kDNSServiceFlagsDenyExpensive          = 0x20000000,
-    /*
-     * This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict
-     * DNS resolutions on interfaces defined as expensive for that request.
-     */
-
-    kDNSServiceFlagsPathEvaluationDone     = 0x40000000
-    /*
-     * This flag is meaningful for only Unicast DNS queries.
-     * When set, it indicates that Network PathEvaluation has already been performed.
-     */
-};
-
-typedef enum
-{
-    kDNSServiceFailoverPolicyNone  DNS_SD_ENUM_SPI_AVAILABLE_FALL_2021 = 0,
-    kDNSServiceFailoverPolicyAllow DNS_SD_ENUM_SPI_AVAILABLE_FALL_2021 = 1
-} DNSServiceFailoverPolicy;
-
-typedef enum
-{
-    kDNSServiceValidationPolicyNone     DNS_SD_ENUM_SPI_AVAILABLE_FALL_2022 = 0,
-    kDNSServiceValidationPolicyRequired DNS_SD_ENUM_SPI_AVAILABLE_FALL_2022 = 1
-} DNSServiceValidationPolicy;
-
-
-#define kDNSServiceCompPrivateDNS   "PrivateDNS"
-#define kDNSServiceCompMulticastDNS "MulticastDNS"
-
-__END_DECLS
-
-#endif  // _DNS_SD_PRIVATE_H
diff --git a/mDNSShared/dnsextd.c b/mDNSShared/dnsextd.c
deleted file mode 100644
index 30e9043..0000000
--- a/mDNSShared/dnsextd.c
+++ /dev/null
@@ -1,3141 +0,0 @@
-/*
- * Copyright (c) 2002-2019 Apple 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.
- */
-
-#if __APPLE__
-// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
-// error, which prevents compilation because we build with "-Werror".
-// Since this is supposed to be portable cross-platform code, we don't care that daemon is
-// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
-#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
-#endif
-
-#include <signal.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <time.h>
-#include <errno.h>
-
-#if __APPLE__
-#undef daemon
-extern int daemon(int, int);
-#endif
-
-// Solaris doesn't have daemon(), so we define it here
-#ifdef NOT_HAVE_DAEMON
-#include "../mDNSPosix/mDNSUNP.h"       // For daemon()
-#endif // NOT_HAVE_DAEMON
-
-#include "dnsextd.h"
-#include "../mDNSShared/uds_daemon.h"
-#include "../mDNSShared/dnssd_ipc.h"
-#include "../mDNSCore/uDNS.h"
-#include "../mDNSShared/DebugServices.h"
-
-// Compatibility workaround
-#ifndef AF_LOCAL
-#define AF_LOCAL AF_UNIX
-#endif
-
-//
-// Constants
-//
-mDNSexport const char ProgramName[] = "dnsextd";
-
-#define LOOPBACK                    "127.0.0.1"
-#if !defined(LISTENQ)
-#   define LISTENQ                  128                 // tcp connection backlog
-#endif
-#define RECV_BUFLEN                 9000
-#define LEASETABLE_INIT_NBUCKETS    256                 // initial hashtable size (doubles as table fills)
-#define EXPIRATION_INTERVAL         300                 // check for expired records every 5 minutes
-#define SRV_TTL                     7200                // TTL For _dns-update SRV records
-#define CONFIG_FILE                 "/etc/dnsextd.conf"
-#define TCP_SOCKET_FLAGS            kTCPSocketFlags_UseTLS
-
-// LLQ Lease bounds (seconds)
-#define LLQ_MIN_LEASE (15 * 60)
-#define LLQ_MAX_LEASE (120 * 60)
-#define LLQ_LEASE_FUDGE 60
-
-// LLQ SOA poll interval (microseconds)
-#define LLQ_MONITOR_ERR_INTERVAL (60 * 1000000)
-#define LLQ_MONITOR_INTERVAL 250000
-#ifdef SIGINFO
-#define INFO_SIGNAL SIGINFO
-#else
-#define INFO_SIGNAL SIGUSR1
-#endif
-
-#define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y))
-
-//
-// Data Structures
-// Structs/fields that must be locked for thread safety are explicitly commented
-//
-
-// args passed to UDP request handler thread as void*
-
-typedef struct
-{
-    PktMsg pkt;
-    struct sockaddr_in cliaddr;
-    DaemonInfo *d;
-    int sd;
-} UDPContext;
-
-// args passed to TCP request handler thread as void*
-typedef struct
-{
-    PktMsg pkt;
-    struct sockaddr_in cliaddr;
-    TCPSocket *sock;           // socket connected to client
-    DaemonInfo *d;
-} TCPContext;
-
-// args passed to UpdateAnswerList thread as void*
-typedef struct
-{
-    DaemonInfo *d;
-    AnswerListElem *a;
-} UpdateAnswerListArgs;
-
-//
-// Global Variables
-//
-
-// booleans to determine runtime output
-// read-only after initialization (no mutex protection)
-static mDNSBool foreground = 0;
-static mDNSBool verbose = 0;
-
-// globals set via signal handler (accessed exclusively by main select loop and signal handler)
-static mDNSBool terminate = 0;
-static mDNSBool dumptable = 0;
-static mDNSBool hangup    = 0;
-
-// global for config file location
-static char *   cfgfile   = NULL;
-
-//
-// Logging Routines
-// Log messages are delivered to syslog unless -f option specified
-//
-
-// common message logging subroutine
-mDNSlocal void PrintLog(const char *buffer)
-{
-    if (foreground)
-    {
-        fprintf(stderr,"%s\n", buffer);
-        fflush(stderr);
-    }
-    else
-    {
-        openlog("dnsextd", LOG_CONS, LOG_DAEMON);
-        syslog(LOG_ERR, "%s", buffer);
-        closelog();
-    }
-}
-
-// Verbose Logging (conditional on -v option)
-mDNSlocal void VLog(const char *format, ...)
-{
-    char buffer[512];
-    va_list ptr;
-
-    if (!verbose) return;
-    va_start(ptr,format);
-    buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-    va_end(ptr);
-    PrintLog(buffer);
-}
-
-// Unconditional Logging
-mDNSlocal void Log(const char *format, ...)
-{
-    char buffer[512];
-    va_list ptr;
-
-    va_start(ptr,format);
-    buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-    va_end(ptr);
-    PrintLog(buffer);
-}
-
-// Error Logging
-// prints message "dnsextd <function>: <operation> - <error message>"
-// must be compiled w/ -D_REENTRANT for thread-safe errno usage
-mDNSlocal void LogErr(const char *fn, const char *operation)
-{
-    char buf[512], errbuf[256];
-    strerror_r(errno, errbuf, sizeof(errbuf));
-    snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf);
-    PrintLog(buf);
-}
-
-//
-// Networking Utility Routines
-//
-
-// Convert DNS Message Header from Network to Host byte order
-mDNSlocal void HdrNToH(PktMsg *pkt)
-{
-    // Read the integer parts which are in IETF byte-order (MSB first, LSB second)
-    mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions;
-    pkt->msg.h.numQuestions   = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-    pkt->msg.h.numAnswers     = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-    pkt->msg.h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] <<  8 | ptr[5]);
-    pkt->msg.h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] <<  8 | ptr[7]);
-}
-
-// Convert DNS Message Header from Host to Network byte order
-mDNSlocal void HdrHToN(PktMsg *pkt)
-{
-    mDNSu16 numQuestions   = pkt->msg.h.numQuestions;
-    mDNSu16 numAnswers     = pkt->msg.h.numAnswers;
-    mDNSu16 numAuthorities = pkt->msg.h.numAuthorities;
-    mDNSu16 numAdditionals = pkt->msg.h.numAdditionals;
-    mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions;
-
-    // Put all the integer values in IETF byte-order (MSB first, LSB second)
-    *ptr++ = (mDNSu8)(numQuestions   >> 8);
-    *ptr++ = (mDNSu8)(numQuestions   &  0xFF);
-    *ptr++ = (mDNSu8)(numAnswers     >> 8);
-    *ptr++ = (mDNSu8)(numAnswers     &  0xFF);
-    *ptr++ = (mDNSu8)(numAuthorities >> 8);
-    *ptr++ = (mDNSu8)(numAuthorities &  0xFF);
-    *ptr++ = (mDNSu8)(numAdditionals >> 8);
-    *ptr++ = (mDNSu8)(numAdditionals &  0xFF);
-}
-
-
-// Add socket to event loop
-
-mDNSlocal mStatus AddSourceToEventLoop( DaemonInfo * self, TCPSocket *sock, EventCallback callback, void *context )
-{
-    EventSource * newSource;
-    mStatus err = mStatus_NoError;
-
-    if ( self->eventSources.LinkOffset == 0 )
-    {
-        InitLinkedList( &self->eventSources, offsetof( EventSource, next));
-    }
-
-    newSource = ( EventSource*) malloc( sizeof *newSource );
-    if ( newSource == NULL )
-    {
-        err = mStatus_NoMemoryErr;
-        goto exit;
-    }
-
-    newSource->callback = callback;
-    newSource->context = context;
-    newSource->sock = sock;
-    newSource->fd = mDNSPlatformTCPGetFD( sock );
-
-    AddToTail( &self->eventSources, newSource );
-
-exit:
-
-    return err;
-}
-
-
-// Remove socket from event loop
-
-mDNSlocal mStatus RemoveSourceFromEventLoop( DaemonInfo * self, TCPSocket *sock )
-{
-    EventSource *   source;
-    mStatus err;
-
-    for ( source = ( EventSource* ) self->eventSources.Head; source; source = source->next )
-    {
-        if ( source->sock == sock )
-        {
-            RemoveFromList( &self->eventSources, source );
-
-            free( source );
-            err = mStatus_NoError;
-            goto exit;
-        }
-    }
-
-    err = mStatus_NoSuchNameErr;
-
-exit:
-
-    return err;
-}
-
-// create a socket connected to nameserver
-// caller terminates connection via close()
-mDNSlocal TCPSocket *ConnectToServer(DaemonInfo *d)
-{
-    int ntries = 0, retry = 0;
-
-    while (1)
-    {
-        mDNSIPPort port = zeroIPPort;
-        int fd;
-
-        TCPSocket *sock = mDNSPlatformTCPSocket(0, mDNSAddrType_IPv4, &port, NULL, mDNSfalse );
-        if ( !sock ) { LogErr("ConnectToServer", "socket");  return NULL; }
-        fd = mDNSPlatformTCPGetFD( sock );
-        if (!connect( fd, (struct sockaddr *)&d->ns_addr, sizeof(d->ns_addr))) return sock;
-        mDNSPlatformTCPCloseConnection( sock );
-        if (++ntries < 10)
-        {
-            LogErr("ConnectToServer", "connect");
-            Log("ConnectToServer - retrying connection");
-            if (!retry) retry = 500000 + random() % 500000;
-            usleep(retry);
-            retry *= 2;
-        }
-        else { Log("ConnectToServer - %d failed attempts.  Aborting.", ntries); return NULL; }
-    }
-}
-
-// send an entire block of data over a connected socket
-mDNSlocal int MySend(TCPSocket *sock, const void *msg, int len)
-{
-    int selectval, n, nsent = 0;
-    fd_set wset;
-    struct timeval timeout = { 3, 0 };  // until we remove all calls from main thread, keep timeout short
-
-    while (nsent < len)
-    {
-        int fd;
-
-        FD_ZERO(&wset);
-
-        fd = mDNSPlatformTCPGetFD( sock );
-
-        FD_SET( fd, &wset );
-        selectval = select( fd+1, NULL, &wset, NULL, &timeout);
-        if (selectval < 0) { LogErr("MySend", "select");  return -1; }
-        if (!selectval || !FD_ISSET(fd, &wset)) { Log("MySend - timeout"); return -1; }
-
-        n = mDNSPlatformWriteTCP( sock, ( char* ) msg + nsent, len - nsent);
-
-        if (n < 0) { LogErr("MySend", "send");  return -1; }
-        nsent += n;
-    }
-    return 0;
-}
-
-// Transmit a DNS message, prefixed by its length, over TCP, blocking if necessary
-mDNSlocal int SendPacket(TCPSocket *sock, PktMsg *pkt)
-{
-    // send the lenth, in network byte order
-    mDNSu16 len = htons((mDNSu16)pkt->len);
-    if (MySend(sock, &len, sizeof(len)) < 0) return -1;
-
-    // send the message
-    VLog("SendPacket Q:%d A:%d A:%d A:%d ",
-         ntohs(pkt->msg.h.numQuestions),
-         ntohs(pkt->msg.h.numAnswers),
-         ntohs(pkt->msg.h.numAuthorities),
-         ntohs(pkt->msg.h.numAdditionals));
-    return MySend(sock, &pkt->msg, pkt->len);
-}
-
-// Receive len bytes, waiting until we have all of them.
-// Returns number of bytes read (which should always be the number asked for).
-static int my_recv(TCPSocket *sock, void *const buf, const int len, mDNSBool * closed)
-{
-    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions;
-    // use an explicit while() loop instead.
-    // Also, don't try to do '+=' arithmetic on the original "void *" pointer --
-    // arithmetic on "void *" pointers is compiler-dependent.
-
-    fd_set rset;
-    struct timeval timeout = { 3, 0 };  // until we remove all calls from main thread, keep timeout short
-    int selectval, remaining = len;
-    char *ptr = (char *)buf;
-    ssize_t num_read;
-
-    while (remaining)
-    {
-        int fd;
-
-        fd = mDNSPlatformTCPGetFD( sock );
-
-        FD_ZERO(&rset);
-        FD_SET(fd, &rset);
-        selectval = select(fd+1, &rset, NULL, NULL, &timeout);
-        if (selectval < 0) { LogErr("my_recv", "select");  return -1; }
-        if (!selectval || !FD_ISSET(fd, &rset))
-        {
-            Log("my_recv - timeout");
-            return -1;
-        }
-
-        num_read = mDNSPlatformReadTCP( sock, ptr, remaining, closed );
-
-        if (((num_read == 0) && *closed) || (num_read < 0) || (num_read > remaining)) return -1;
-        if (num_read == 0) return 0;
-        ptr       += num_read;
-        remaining -= num_read;
-    }
-    return(len);
-}
-
-// Return a DNS Message read off of a TCP socket, or NULL on failure
-// If storage is non-null, result is placed in that buffer.  Otherwise,
-// returned value is allocated with Malloc, and contains sufficient extra
-// storage for a Lease OPT RR
-
-mDNSlocal PktMsg*
-RecvPacket
-(
-    TCPSocket * sock,
-    PktMsg      *   storage,
-    mDNSBool    *   closed
-)
-{
-    int nread;
-    int allocsize;
-    mDNSu16 msglen = 0;
-    PktMsg      *   pkt = NULL;
-    unsigned int srclen;
-    int fd;
-    mStatus err = 0;
-
-    fd = mDNSPlatformTCPGetFD( sock );
-
-    nread = my_recv( sock, &msglen, sizeof( msglen ), closed );
-
-    require_action_quiet( nread != -1, exit, err = mStatus_UnknownErr );
-    require_action_quiet( nread > 0, exit, err = mStatus_NoError );
-
-    msglen = ntohs( msglen );
-    require_action_quiet( nread == sizeof( msglen ), exit, err = mStatus_UnknownErr; Log( "Could not read length field of message") );
-
-    if ( storage )
-    {
-        require_action_quiet( msglen <= sizeof( storage->msg ), exit, err = mStatus_UnknownErr; Log( "RecvPacket: provided buffer too small." ) );
-        pkt = storage;
-    }
-    else
-    {
-        // buffer extra space to add an OPT RR
-
-        if ( msglen > sizeof(DNSMessage))
-        {
-            allocsize = sizeof(PktMsg) - sizeof(DNSMessage) + msglen;
-        }
-        else
-        {
-            allocsize = sizeof(PktMsg);
-        }
-
-        pkt = malloc(allocsize);
-        require_action_quiet( pkt, exit, err = mStatus_NoMemoryErr; LogErr( "RecvPacket", "malloc" ) );
-        mDNSPlatformMemZero( pkt, sizeof( *pkt ) );
-    }
-
-    pkt->len = msglen;
-    srclen = sizeof(pkt->src);
-
-    if ( getpeername( fd, ( struct sockaddr* ) &pkt->src, &srclen ) || ( srclen != sizeof( pkt->src ) ) )
-    {
-        LogErr("RecvPacket", "getpeername");
-        mDNSPlatformMemZero(&pkt->src, sizeof(pkt->src));
-    }
-
-    nread = my_recv(sock, &pkt->msg, msglen, closed );
-    require_action_quiet( nread >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvPacket", "recv" ) );
-    require_action_quiet( nread == msglen, exit, err = mStatus_UnknownErr ; Log( "Could not read entire message" ) );
-    require_action_quiet( pkt->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr ; Log( "RecvPacket: Message too short (%d bytes)", pkt->len ) );
-
-exit:
-
-    if ( err && pkt )
-    {
-        if ( pkt != storage )
-        {
-            free(pkt);
-        }
-
-        pkt = NULL;
-    }
-
-    return pkt;
-}
-
-
-mDNSlocal DNSZone*
-FindZone
-(
-    DaemonInfo  *   self,
-    domainname  *   name
-)
-{
-    DNSZone * zone;
-
-    for ( zone = self->zones; zone; zone = zone->next )
-    {
-        if ( SameDomainName( &zone->name, name ) )
-        {
-            break;
-        }
-    }
-
-    return zone;
-}
-
-
-mDNSlocal mDNSBool
-ZoneHandlesName
-(
-    const domainname * zname,
-    const domainname * dname
-)
-{
-    mDNSu16 i = DomainNameLength( zname );
-    mDNSu16 j = DomainNameLength( dname );
-
-    if ( ( i == ( MAX_DOMAIN_NAME + 1 ) ) || ( j == ( MAX_DOMAIN_NAME + 1 ) ) || ( i > j )  || ( memcmp( zname->c, dname->c + ( j - i ), i ) != 0 ) )
-    {
-        return mDNSfalse;
-    }
-
-    return mDNStrue;
-}
-
-
-mDNSlocal mDNSBool IsQuery( PktMsg * pkt )
-{
-    return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery );
-}
-
-
-mDNSlocal mDNSBool IsUpdate( PktMsg * pkt )
-{
-    return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_OP_Update );
-}
-
-
-mDNSlocal mDNSBool IsNotify(PktMsg *pkt)
-{
-    return ( pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( mDNSu8) ( kDNSFlag0_OP_Notify );
-}
-
-
-mDNSlocal mDNSBool IsLLQRequest(PktMsg *pkt)
-{
-    const mDNSu8 *ptr = NULL, *end = (mDNSu8 *)&pkt->msg + pkt->len;
-    LargeCacheRecord lcr;
-    int i;
-    mDNSBool result = mDNSfalse;
-
-    HdrNToH(pkt);
-    if ((mDNSu8)(pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (mDNSu8)(kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery)) goto end;
-
-    if (!pkt->msg.h.numAdditionals) goto end;
-    ptr = LocateAdditionals(&pkt->msg, end);
-    if (!ptr) goto end;
-
-    bzero(&lcr, sizeof(lcr));
-    // find last Additional info.
-    for (i = 0; i < pkt->msg.h.numAdditionals; i++)
-    {
-        ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
-        if (!ptr) { Log("Unable to read additional record"); goto end; }
-    }
-
-    if ( lcr.r.resrec.rrtype == kDNSType_OPT && lcr.r.resrec.rdlength >= DNSOpt_LLQData_Space && lcr.r.resrec.rdata->u.opt[0].opt == kDNSOpt_LLQ )
-    {
-        result = mDNStrue;
-    }
-
-end:
-    HdrHToN(pkt);
-    return result;
-}
-
-// !!!KRS implement properly
-mDNSlocal mDNSBool IsLLQAck(PktMsg *pkt)
-{
-    if ((pkt->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == (mDNSu8) ( kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery ) &&
-        pkt->msg.h.numQuestions && !pkt->msg.h.numAnswers && !pkt->msg.h.numAuthorities) return mDNStrue;
-    return mDNSfalse;
-}
-
-
-mDNSlocal mDNSBool
-IsPublicSRV
-(
-    DaemonInfo  *   self,
-    DNSQuestion *   q
-)
-{
-    DNameListElem   *   elem;
-    mDNSBool ret     = mDNSfalse;
-    int i       = ( int ) DomainNameLength( &q->qname ) - 1;
-
-    for ( elem = self->public_names; elem; elem = elem->next )
-    {
-        int j = ( int ) DomainNameLength( &elem->name ) - 1;
-
-        if ( i > j )
-        {
-            for ( ; i >= 0; i--, j-- )
-            {
-                if ( q->qname.c[ i ] != elem->name.c[ j ] )
-                {
-                    ret = mDNStrue;
-                    goto exit;
-                }
-            }
-        }
-    }
-
-exit:
-
-    return ret;
-}
-
-
-mDNSlocal void
-SetZone
-(
-    DaemonInfo  * self,
-    PktMsg      * pkt
-)
-{
-    domainname zname;
-    const mDNSu8    *   ptr = pkt->msg.data;
-    mDNSBool exception = mDNSfalse;
-
-    // Initialize
-
-    pkt->zone           = NULL;
-    pkt->isZonePublic   = mDNStrue;
-    zname.c[0]          = '\0';
-
-    // Figure out what type of packet this is
-
-    if ( IsQuery( pkt ) )
-    {
-        DNSQuestion question;
-
-        // It's a query
-
-        getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question );
-
-        AppendDomainName( &zname, &question.qname );
-
-        exception = ( ( question.qtype == kDNSType_SOA ) || ( question.qtype == kDNSType_NS ) || ( ( question.qtype == kDNSType_SRV ) && IsPublicSRV( self, &question ) ) );
-    }
-    else if ( IsUpdate( pkt ) )
-    {
-        DNSQuestion question;
-
-        // It's an update.  The format of the zone section is the same as the format for the question section
-        // according to RFC 2136, so we'll just treat this as a question so we can get at the zone.
-
-        getQuestion( &pkt->msg, ptr, ( ( mDNSu8* ) &pkt->msg ) + pkt->len, NULL, &question );
-
-        AppendDomainName( &zname, &question.qname );
-
-        exception = mDNSfalse;
-    }
-
-    if ( zname.c[0] != '\0' )
-    {
-        // Find the right zone
-
-        for ( pkt->zone = self->zones; pkt->zone; pkt->zone = pkt->zone->next )
-        {
-            if ( ZoneHandlesName( &pkt->zone->name, &zname ) )
-            {
-                VLog( "found correct zone %##s for query", pkt->zone->name.c );
-
-                pkt->isZonePublic = ( ( pkt->zone->type == kDNSZonePublic ) || exception );
-
-                VLog( "zone %##s is %s", pkt->zone->name.c, ( pkt->isZonePublic ) ? "public" : "private" );
-
-                break;
-            }
-        }
-    }
-}
-
-
-mDNSlocal int
-UDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc)
-{
-    fd_set rset;
-    struct timeval timeout = { 3, 0 };   // until we remove all calls from main thread, keep timeout short
-    int sd;
-    int res;
-    mStatus err = mStatus_NoError;
-
-    // Initialize
-
-    *trunc = mDNSfalse;
-
-    // Create a socket
-
-    sd = socket( AF_INET, SOCK_DGRAM, 0 );
-    require_action( sd >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "socket" ) );
-
-    // Send the packet to the nameserver
-
-    VLog("UDPServerTransaction Q:%d A:%d A:%d A:%d ",
-         ntohs(request->msg.h.numQuestions),
-         ntohs(request->msg.h.numAnswers),
-         ntohs(request->msg.h.numAuthorities),
-         ntohs(request->msg.h.numAdditionals));
-    res = sendto( sd, (char *)&request->msg, request->len, 0, ( struct sockaddr* ) &d->ns_addr, sizeof( d->ns_addr ) );
-    require_action( res == (int) request->len, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "sendto" ) );
-
-    // Wait for reply
-
-    FD_ZERO( &rset );
-    FD_SET( sd, &rset );
-    res = select( sd + 1, &rset, NULL, NULL, &timeout );
-    require_action( res >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "select" ) );
-    require_action( ( res > 0 ) && FD_ISSET( sd, &rset ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - timeout" ) );
-
-    // Receive reply
-
-    reply->len = recvfrom( sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL );
-    require_action( ( ( int ) reply->len ) >= 0, exit, err = mStatus_UnknownErr; LogErr( "UDPServerTransaction", "recvfrom" ) );
-    require_action( reply->len >= sizeof( DNSMessageHeader ), exit, err = mStatus_UnknownErr; Log( "UDPServerTransaction - Message too short (%d bytes)", reply->len ) );
-
-    // Check for truncation bit
-
-    if ( reply->msg.h.flags.b[0] & kDNSFlag0_TC )
-    {
-        *trunc = mDNStrue;
-    }
-
-exit:
-
-    if ( sd >= 0 )
-    {
-        close( sd );
-    }
-
-    return err;
-}
-
-//
-// Dynamic Update Utility Routines
-//
-
-// check if a request and server response complete a successful dynamic update
-mDNSlocal mDNSBool SuccessfulUpdateTransaction(PktMsg *request, PktMsg *reply)
-{
-    char buf[32];
-    char *vlogmsg = NULL;
-
-    // check messages
-    if (!request || !reply) { vlogmsg = "NULL message"; goto failure; }
-    if (request->len < sizeof(DNSMessageHeader) || reply->len < sizeof(DNSMessageHeader)) { vlogmsg = "Malformatted message"; goto failure; }
-
-    // check request operation
-    if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask))
-    { vlogmsg = "Request opcode not an update"; goto failure; }
-
-    // check result
-    if ((reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask)) { vlogmsg = "Reply contains non-zero rcode";  goto failure; }
-    if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_OP_Update | kDNSFlag0_QR_Response))
-    { vlogmsg = "Reply opcode not an update response"; goto failure; }
-
-    VLog("Successful update from %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32));
-    return mDNStrue;
-
-failure:
-    VLog("Request %s: %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32), vlogmsg);
-    return mDNSfalse;
-}
-
-// Allocate an appropriately sized CacheRecord and copy data from original.
-// Name pointer in CacheRecord object is set to point to the name specified
-//
-mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name)
-{
-    CacheRecord *cr;
-    size_t size = sizeof(*cr);
-    if (orig->resrec.rdlength > InlineCacheRDSize) size += orig->resrec.rdlength - InlineCacheRDSize;
-    cr = malloc(size);
-    if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; }
-    memcpy(cr, orig, size);
-    cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
-    cr->resrec.name = name;
-
-    return cr;
-}
-
-
-//
-// Lease Hashtable Utility Routines
-//
-
-// double hash table size
-// caller must lock table prior to invocation
-mDNSlocal void RehashTable(DaemonInfo *d)
-{
-    RRTableElem *ptr, *tmp, **new;
-    int i, bucket, newnbuckets = d->nbuckets * 2;
-
-    VLog("Rehashing lease table (new size %d buckets)", newnbuckets);
-    new = malloc(sizeof(RRTableElem *) * newnbuckets);
-    if (!new) { LogErr("RehashTable", "malloc");  return; }
-    mDNSPlatformMemZero(new, newnbuckets * sizeof(RRTableElem *));
-
-    for (i = 0; i < d->nbuckets; i++)
-    {
-        ptr = d->table[i];
-        while (ptr)
-        {
-            bucket = ptr->rr.resrec.namehash % newnbuckets;
-            tmp = ptr;
-            ptr = ptr->next;
-            tmp->next = new[bucket];
-            new[bucket] = tmp;
-        }
-    }
-    d->nbuckets = newnbuckets;
-    free(d->table);
-    d->table = new;
-}
-
-// print entire contents of hashtable, invoked via SIGINFO
-mDNSlocal void PrintLeaseTable(DaemonInfo *d)
-{
-    int i;
-    RRTableElem *ptr;
-    char rrbuf[MaxMsg], addrbuf[16];
-    struct timeval now;
-    int hr, min, sec;
-
-    if (gettimeofday(&now, NULL)) { LogErr("PrintTable", "gettimeofday"); return; }
-    if (pthread_mutex_lock(&d->tablelock)) { LogErr("PrintTable", "pthread_mutex_lock"); return; }
-
-    Log("Dumping Lease Table Contents (table contains %d resource records)", d->nelems);
-    for (i = 0; i < d->nbuckets; i++)
-    {
-        for (ptr = d->table[i]; ptr; ptr = ptr->next)
-        {
-            hr = ((ptr->expire - now.tv_sec) / 60) / 60;
-            min = ((ptr->expire - now.tv_sec) / 60) % 60;
-            sec = (ptr->expire - now.tv_sec) % 60;
-            Log("Update from %s, Expires in %d:%d:%d\n\t%s", inet_ntop(AF_INET, &ptr->cli.sin_addr, addrbuf, 16), hr, min, sec,
-                GetRRDisplayString_rdb(&ptr->rr.resrec, &ptr->rr.resrec.rdata->u, rrbuf));
-        }
-    }
-    pthread_mutex_unlock(&d->tablelock);
-}
-
-//
-// Startup SRV Registration Routines
-// Register _dns-update._udp/_tcp.<zone> SRV records indicating the port on which
-// the daemon accepts requests
-//
-
-// delete all RRS of a given name/type
-mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit,  ResourceRecord *rr)
-{
-    ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name);
-    if (!ptr || ptr + 10 >= limit) return NULL;  // out of space
-    ptr[0] = (mDNSu8)(rr->rrtype  >> 8);
-    ptr[1] = (mDNSu8)(rr->rrtype  &  0xFF);
-    ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8);
-    ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY &  0xFF);
-    mDNSPlatformMemZero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata
-    msg->h.mDNS_numUpdates++;
-    return ptr + 10;
-}
-
-mDNSlocal mDNSu8 *PutUpdateSRV(DaemonInfo *d, DNSZone * zone, PktMsg *pkt, mDNSu8 *ptr, char *regtype, mDNSIPPort port, mDNSBool registration)
-{
-    AuthRecord rr;
-    char hostname[1024], buf[MaxMsg];
-    mDNSu8 *end = (mDNSu8 *)&pkt->msg + sizeof(DNSMessage);
-
-    ( void ) d;
-
-    mDNS_SetupResourceRecord(&rr, NULL, 0, kDNSType_SRV, SRV_TTL, kDNSRecordTypeUnique, AuthRecordAny, NULL, NULL);
-    rr.resrec.rrclass = kDNSClass_IN;
-    rr.resrec.rdata->u.srv.priority = 0;
-    rr.resrec.rdata->u.srv.weight   = 0;
-    rr.resrec.rdata->u.srv.port     = port;
-    if (gethostname(hostname, 1024) < 0 || !MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname))
-        rr.resrec.rdata->u.srv.target.c[0] = '\0';
-
-    MakeDomainNameFromDNSNameString(&rr.namestorage, regtype);
-    AppendDomainName(&rr.namestorage, &zone->name);
-    VLog("%s  %s", registration ? "Registering SRV record" : "Deleting existing RRSet",
-         GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf));
-    if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec);
-    else ptr = putRRSetDeletion(&pkt->msg, ptr, end, &rr.resrec);
-    return ptr;
-}
-
-
-// perform dynamic update.
-// specify deletion by passing false for the register parameter, otherwise register the records.
-mDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration)
-{
-    TCPSocket *sock = NULL;
-    DNSZone * zone;
-    int err = mStatus_NoError;
-
-    sock = ConnectToServer( d );
-    require_action( sock, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: ConnectToServer failed" ) );
-
-    for ( zone = d->zones; zone; zone = zone->next )
-    {
-        PktMsg pkt;
-        mDNSu8 *ptr = pkt.msg.data;
-        mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage);
-        PktMsg *reply = NULL;
-        mDNSBool closed;
-        mDNSBool ok;
-
-        // Initialize message
-        InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags);
-        pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines
-        pkt.src.sin_family = AF_INET;
-
-        // format message body
-        ptr = putZone(&pkt.msg, ptr, end, &zone->name, mDNSOpaque16fromIntVal(kDNSClass_IN));
-        require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-
-        if ( zone->type == kDNSZonePrivate )
-        {
-            ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls._tcp.", d->private_port, registration);
-            require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-            ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls._tcp.", d->private_port, registration);
-            require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-            ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls._tcp.", d->private_port, registration);
-            require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-
-            if ( !registration )
-            {
-                ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration);
-                require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-                ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration);
-                require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-            }
-        }
-        else
-        {
-            if ( !registration )
-            {
-                ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update-tls.", d->private_port, registration);
-                require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-                ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-query-tls.", d->private_port, registration);
-                require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-                ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq-tls.", d->private_port, registration);
-                require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-            }
-
-            ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-update._udp.", d->llq_port, registration);
-            require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-            ptr = PutUpdateSRV(d, zone, &pkt, ptr, "_dns-llq._udp.", d->llq_port, registration);
-            require_action( ptr, exit, err = mStatus_UnknownErr; Log("UpdateSRV: Error constructing lease expiration update" ) );
-        }
-
-        HdrHToN(&pkt);
-
-        if ( zone->updateKeys )
-        {
-            DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 );
-            require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) );
-        }
-
-        pkt.len = ptr - (mDNSu8 *)&pkt.msg;
-
-        // send message, receive reply
-
-        err = SendPacket( sock, &pkt );
-        require_action( !err, exit, Log( "UpdateSRV: SendPacket failed" ) );
-
-        reply = RecvPacket( sock, NULL, &closed );
-        require_action( reply, exit, err = mStatus_UnknownErr; Log( "UpdateSRV: RecvPacket returned NULL" ) );
-
-        ok = SuccessfulUpdateTransaction( &pkt, reply );
-
-        if ( !ok )
-        {
-            Log("SRV record registration failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask);
-        }
-
-        free( reply );
-    }
-
-exit:
-
-    if ( sock )
-    {
-        mDNSPlatformTCPCloseConnection( sock );
-    }
-
-    return err;
-}
-
-// wrapper routines/macros
-#define ClearUpdateSRV(d) UpdateSRV(d, 0)
-
-// clear any existing records prior to registration
-mDNSlocal int SetUpdateSRV(DaemonInfo *d)
-{
-    int err;
-
-    err = ClearUpdateSRV(d);         // clear any existing record
-    if (!err) err = UpdateSRV(d, 1);
-    return err;
-}
-
-//
-// Argument Parsing and Configuration
-//
-
-mDNSlocal void PrintUsage(void)
-{
-    fprintf(stderr, "Usage: dnsextd [-f <config file>] [-vhd] ...\n"
-            "Use \"dnsextd -h\" for help\n");
-}
-
-mDNSlocal void PrintHelp(void)
-{
-    fprintf(stderr, "\n\n");
-    PrintUsage();
-
-    fprintf(stderr,
-            "dnsextd is a daemon that implements DNS extensions supporting Dynamic DNS Update Leases\n"
-            "and Long Lived Queries, used in Wide-Area DNS Service Discovery, on behalf of name servers\n"
-            "that do not natively support these extensions.  (See dns-sd.org for more info on DNS Service\n"
-            "Discovery, Update Leases, and Long Lived Queries.)\n\n"
-
-            "dnsextd requires one argument,the zone, which is the domain for which Update Leases\n"
-            "and Long Lived Queries are to be administered.  dnsextd communicates directly with the\n"
-            "primary master server for this zone.\n\n"
-
-            "The options are as follows:\n\n"
-
-            "-f    Specify configuration file. The default is /etc/dnsextd.conf.\n\n"
-
-            "-d    Run daemon in foreground.\n\n"
-
-            "-h    Print help.\n\n"
-
-            "-v    Verbose output.\n\n"
-            );
-}
-
-
-// Note: ProcessArgs called before process is daemonized, and therefore must open no descriptors
-// returns 0 (success) if program is to continue execution
-// output control arguments (-f, -v) do not affect this routine
-mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d)
-{
-    DNSZone *   zone;
-    int opt;
-    int err = 0;
-
-    cfgfile = strdup( CONFIG_FILE );
-    require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr );
-
-    // defaults, may be overriden by command option
-
-    // setup our sockaddr
-
-    mDNSPlatformMemZero( &d->addr, sizeof( d->addr ) );
-    d->addr.sin_addr.s_addr = zerov4Addr.NotAnInteger;
-    d->addr.sin_port        = UnicastDNSPort.NotAnInteger;
-    d->addr.sin_family      = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-    d->addr.sin_len         = sizeof( d->addr );
-#endif
-
-    // setup nameserver's sockaddr
-
-    mDNSPlatformMemZero(&d->ns_addr, sizeof(d->ns_addr));
-    d->ns_addr.sin_family   = AF_INET;
-    inet_pton( AF_INET, LOOPBACK, &d->ns_addr.sin_addr );
-    d->ns_addr.sin_port     = NSIPCPort.NotAnInteger;
-#ifndef NOT_HAVE_SA_LEN
-    d->ns_addr.sin_len      = sizeof( d->ns_addr );
-#endif
-
-    // setup our ports
-
-    d->private_port = PrivateDNSPort;
-    d->llq_port     = DNSEXTPort;
-
-    while ((opt = getopt(argc, argv, "f:hdv")) != -1)
-    {
-        switch(opt)
-        {
-        case 'f': free( cfgfile ); cfgfile = strdup( optarg ); require_action( cfgfile, arg_error, err = mStatus_NoMemoryErr ); break;
-        case 'h': PrintHelp();    return -1;
-        case 'd': foreground = 1; break;            // Also used when launched via OS X's launchd mechanism
-        case 'v': verbose = 1;    break;
-        default:  goto arg_error;
-        }
-    }
-
-    err = ParseConfig( d, cfgfile );
-    require_noerr( err, arg_error );
-
-    // Make sure we've specified some zones
-
-    require_action( d->zones, arg_error, err = mStatus_UnknownErr );
-
-    // if we have a shared secret, use it for the entire zone
-
-    for ( zone = d->zones; zone; zone = zone->next )
-    {
-        if ( zone->updateKeys )
-        {
-            AssignDomainName( &zone->updateKeys->domain, &zone->name );
-        }
-    }
-
-    return 0;
-
-arg_error:
-
-    PrintUsage();
-    return -1;
-}
-
-
-//
-// Initialization Routines
-//
-
-// Allocate memory, initialize locks and bookkeeping variables
-mDNSlocal int InitLeaseTable(DaemonInfo *d)
-{
-    if (pthread_mutex_init(&d->tablelock, NULL)) { LogErr("InitLeaseTable", "pthread_mutex_init"); return -1; }
-    d->nbuckets = LEASETABLE_INIT_NBUCKETS;
-    d->nelems = 0;
-    d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
-    if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; }
-    mDNSPlatformMemZero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS);
-    return 0;
-}
-
-
-mDNSlocal int
-SetupSockets
-(
-    DaemonInfo * self
-)
-{
-    static const int kOn = 1;
-    int sockpair[2];
-    mDNSBool private = mDNSfalse;
-    struct sockaddr_in daddr;
-    DNSZone         *   zone;
-    mStatus err = 0;
-
-    // set up sockets on which we all ns requests
-
-    self->tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
-    require_action( dnssd_SocketValid(self->tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
-#if defined(SO_REUSEADDR)
-    err = setsockopt(self->tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-    require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tcpsd" ) );
-#endif
-
-    err = bind( self->tcpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) );
-    require_action( !err, exit, LogErr( "SetupSockets", "bind self->tcpsd" ) );
-
-    err = listen( self->tcpsd, LISTENQ );
-    require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
-
-    self->udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
-    require_action( dnssd_SocketValid(self->udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
-#if defined(SO_REUSEADDR)
-    err = setsockopt(self->udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-    require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->udpsd" ) );
-#endif
-
-    err = bind( self->udpsd, ( struct sockaddr* ) &self->addr, sizeof( self->addr ) );
-    require_action( !err, exit, LogErr( "SetupSockets", "bind self->udpsd" ) );
-
-    // set up sockets on which we receive llq requests
-
-    mDNSPlatformMemZero(&self->llq_addr, sizeof(self->llq_addr));
-    self->llq_addr.sin_family       = AF_INET;
-    self->llq_addr.sin_addr.s_addr  = zerov4Addr.NotAnInteger;
-    self->llq_addr.sin_port         = ( self->llq_port.NotAnInteger ) ? self->llq_port.NotAnInteger : DNSEXTPort.NotAnInteger;
-
-    if (self->llq_addr.sin_port == self->addr.sin_port)
-    {
-        self->llq_tcpsd = self->tcpsd;
-        self->llq_udpsd = self->udpsd;
-    }
-    else
-    {
-        self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
-        require_action( dnssd_SocketValid(self->llq_tcpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
-#if defined(SO_REUSEADDR)
-        err = setsockopt(self->llq_tcpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-        require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_tcpsd" ) );
-#endif
-
-        err = bind( self->llq_tcpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
-        require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_tcpsd" ) );
-
-        err = listen( self->llq_tcpsd, LISTENQ );
-        require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
-
-        self->llq_udpsd = socket( AF_INET, SOCK_DGRAM, 0 );
-        require_action( dnssd_SocketValid(self->llq_udpsd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
-#if defined(SO_REUSEADDR)
-        err = setsockopt(self->llq_udpsd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-        require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->llq_udpsd" ) );
-#endif
-
-        err = bind(self->llq_udpsd, ( struct sockaddr* ) &self->llq_addr, sizeof( self->llq_addr ) );
-        require_action( !err, exit, LogErr( "SetupSockets", "bind self->llq_udpsd" ) );
-    }
-
-    // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred
-
-    err = socketpair( AF_LOCAL, SOCK_STREAM, 0, sockpair );
-    require_action( !err, exit, LogErr( "SetupSockets", "socketpair" ) );
-
-    self->LLQEventListenSock = sockpair[0];
-    self->LLQEventNotifySock = sockpair[1];
-
-    // set up socket on which we receive private requests
-
-    self->llq_tcpsd = socket( AF_INET, SOCK_STREAM, 0 );
-    require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-    mDNSPlatformMemZero(&daddr, sizeof(daddr));
-    daddr.sin_family        = AF_INET;
-    daddr.sin_addr.s_addr   = zerov4Addr.NotAnInteger;
-    daddr.sin_port          = ( self->private_port.NotAnInteger ) ? self->private_port.NotAnInteger : PrivateDNSPort.NotAnInteger;
-
-    self->tlssd = socket( AF_INET, SOCK_STREAM, 0 );
-    require_action( dnssd_SocketValid(self->tlssd), exit, err = mStatus_UnknownErr; LogErr( "SetupSockets", "socket" ) );
-
-#if defined(SO_REUSEADDR)
-    err = setsockopt(self->tlssd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-    require_action( !err, exit, LogErr( "SetupSockets", "SO_REUSEADDR self->tlssd" ) );
-#endif
-
-    err = bind( self->tlssd, ( struct sockaddr* ) &daddr, sizeof( daddr ) );
-    require_action( !err, exit, LogErr( "SetupSockets", "bind self->tlssd" ) );
-
-    err = listen( self->tlssd, LISTENQ );
-    require_action( !err, exit, LogErr( "SetupSockets", "listen" ) );
-
-    // Do we have any private zones?
-
-    for ( zone = self->zones; zone; zone = zone->next )
-    {
-        if ( zone->type == kDNSZonePrivate )
-        {
-            private = mDNStrue;
-            break;
-        }
-    }
-
-    if ( private )
-    {
-        err = mDNSPlatformTLSSetupCerts();
-        require_action( !err, exit, LogErr( "SetupSockets", "mDNSPlatformTLSSetupCerts" ) );
-    }
-
-exit:
-
-    return err;
-}
-
-//
-// periodic table updates
-//
-
-// Delete a resource record from the nameserver via a dynamic update
-// sd is a socket already connected to the server
-mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zname, TCPSocket *sock)
-{
-    DNSZone *   zone;
-    PktMsg pkt;
-    mDNSu8 *ptr = pkt.msg.data;
-    mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage);
-    char buf[MaxMsg];
-    mDNSBool closed;
-    PktMsg *reply = NULL;
-
-    VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf));
-
-    InitializeDNSMessage(&pkt.msg.h, zeroID, UpdateReqFlags);
-
-    ptr = putZone(&pkt.msg, ptr, end, zname, mDNSOpaque16fromIntVal(rr->resrec.rrclass));
-    if (!ptr) goto end;
-    ptr = putDeletionRecord(&pkt.msg, ptr, &rr->resrec);
-    if (!ptr) goto end;
-
-    HdrHToN(&pkt);
-
-    zone = FindZone( d, zname );
-
-    if ( zone && zone->updateKeys)
-    {
-        DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 );
-        if (!ptr) goto end;
-    }
-
-    pkt.len = ptr - (mDNSu8 *)&pkt.msg;
-    pkt.src.sin_addr.s_addr = zerov4Addr.NotAnInteger; // address field set solely for verbose logging in subroutines
-    pkt.src.sin_family = AF_INET;
-    if (SendPacket( sock, &pkt)) { Log("DeleteOneRecord: SendPacket failed"); }
-    reply = RecvPacket( sock, NULL, &closed );
-    if (reply) HdrNToH(reply);
-    require_action( reply, end, Log( "DeleteOneRecord: RecvPacket returned NULL" ) );
-
-    if (!SuccessfulUpdateTransaction(&pkt, reply))
-        Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask : -1);
-
-end:
-    if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); }
-    if (reply) free(reply);
-}
-
-// iterate over table, deleting expired records (or all records if DeleteAll is true)
-mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll)
-{
-    struct timeval now;
-    int i;
-    TCPSocket *sock = ConnectToServer(d);
-    if (!sock) { Log("DeleteRecords: ConnectToServer failed"); return; }
-    if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; }
-    if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; }
-
-    for (i = 0; i < d->nbuckets; i++)
-    {
-        RRTableElem **ptr = &d->table[i];
-        while (*ptr)
-        {
-            if (DeleteAll || (*ptr)->expire - now.tv_sec < 0)
-            {
-                RRTableElem *fptr;
-                // delete record from server
-                DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sock);
-                fptr = *ptr;
-                *ptr = (*ptr)->next;
-                free(fptr);
-                d->nelems--;
-            }
-            else ptr = &(*ptr)->next;
-        }
-    }
-    pthread_mutex_unlock(&d->tablelock);
-    mDNSPlatformTCPCloseConnection( sock );
-}
-
-//
-// main update request handling
-//
-
-// Add, delete, or refresh records in table based on contents of a successfully completed dynamic update
-mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
-{
-    int i, allocsize;
-    LargeCacheRecord lcr;
-    ResourceRecord *rr = &lcr.r.resrec;
-    const mDNSu8 *ptr, *end;
-    struct timeval tv;
-    DNSQuestion zone;
-    char buf[MaxMsg];
-
-    if (pthread_mutex_lock(&d->tablelock)) { LogErr("UpdateLeaseTable", "pthread_mutex_lock"); return; }
-    HdrNToH(pkt);
-    ptr = pkt->msg.data;
-    end = (mDNSu8 *)&pkt->msg + pkt->len;
-    ptr = getQuestion(&pkt->msg, ptr, end, 0, &zone);
-    if (!ptr) { Log("UpdateLeaseTable: cannot read zone");  goto cleanup; }
-    ptr = LocateAuthorities(&pkt->msg, end);
-    if (!ptr) { Log("UpdateLeaseTable: Format error");  goto cleanup; }
-
-    for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++)
-    {
-        mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse;
-
-        ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
-        if (!ptr || lcr.r.resrec.RecordType == kDNSRecordTypePacketNegative) { Log("UpdateLeaseTable: GetLargeResourceRecord failed"); goto cleanup; }
-        int bucket = rr->namehash % d->nbuckets;
-        RRTableElem *tmp, **rptr = &d->table[bucket];
-
-        // handle deletions
-        if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
-            DeleteAllRRSets = mDNStrue; // delete all rrsets for a name
-        else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength)
-            DeleteOneRRSet = mDNStrue;
-        else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE)
-            DeleteOneRR = mDNStrue;
-
-        if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR)
-        {
-            while (*rptr)
-            {
-                if (SameDomainName((*rptr)->rr.resrec.name, rr->name) &&
-                    (DeleteAllRRSets ||
-                     (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) ||
-                     (DeleteOneRR && IdenticalResourceRecord(&(*rptr)->rr.resrec, rr))))
-                {
-                    tmp = *rptr;
-                    VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf));
-                    *rptr = (*rptr)->next;
-                    free(tmp);
-                    d->nelems--;
-                }
-                else rptr = &(*rptr)->next;
-            }
-        }
-        else if (lease > 0)
-        {
-            // see if add or refresh
-            while (*rptr && !IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next;
-            if (*rptr)
-            {
-                // refresh
-                if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
-                (*rptr)->expire = tv.tv_sec + (unsigned)lease;
-                VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
-            }
-            else
-            {
-                // New record - add to table
-                if (d->nelems > d->nbuckets)
-                {
-                    RehashTable(d);
-                    bucket = rr->namehash % d->nbuckets;
-                }
-                if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
-                allocsize = sizeof(RRTableElem);
-                if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize);
-                tmp = malloc(allocsize);
-                if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; }
-                memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize);
-                tmp->rr.resrec.rdata = (RData *)&tmp->rr.smallrdatastorage;
-                AssignDomainName(&tmp->name, rr->name);
-                tmp->rr.resrec.name = &tmp->name;
-                tmp->expire = tv.tv_sec + (unsigned)lease;
-                tmp->cli.sin_addr = pkt->src.sin_addr;
-                AssignDomainName(&tmp->zone, &zone.qname);
-                tmp->next = d->table[bucket];
-                d->table[bucket] = tmp;
-                d->nelems++;
-                VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
-            }
-        }
-    }
-
-cleanup:
-    pthread_mutex_unlock(&d->tablelock);
-    HdrHToN(pkt);
-}
-
-// Given a successful reply from a server, create a new reply that contains lease information
-// Replies are currently not signed !!!KRS change this
-mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease)
-{
-    PktMsg *const reply = malloc(sizeof(*reply));
-    mDNSu8 *ptr;
-    mDNSOpaque16 flags;
-    (void)d;  //unused
-    
-    if (!reply) { LogErr("FormatLeaseReply", "malloc"); return NULL; }
-    flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
-    flags.b[1] = 0;
-
-    InitializeDNSMessage(&reply->msg.h, orig->msg.h.id, flags);
-    reply->src.sin_addr.s_addr = zerov4Addr.NotAnInteger;            // unused except for log messages
-    reply->src.sin_family = AF_INET;
-    ptr = putUpdateLease(&reply->msg, reply->msg.data, lease);
-    if (!ptr) { Log("FormatLeaseReply: putUpdateLease failed"); free(reply); return NULL; }
-    reply->len = ptr - (mDNSu8 *)&reply->msg;
-    HdrHToN(reply);
-    return reply;
-}
-
-
-// pkt is thread-local, not requiring locking
-
-mDNSlocal PktMsg*
-HandleRequest
-(
-    DaemonInfo  *   self,
-    PktMsg      *   request
-)
-{
-    PktMsg      *   reply = NULL;
-    PktMsg      *   leaseReply;
-    PktMsg buf;
-    char addrbuf[32];
-    TCPSocket * sock = NULL;
-    mDNSu32 lease = 0;
-    mDNSBool gotlease;
-    if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) == kDNSFlag0_OP_Update)
-    {
-        int i, adds = 0, dels = 0;
-        const mDNSu8 *ptr, *end = (mDNSu8 *)&request->msg + request->len;
-        HdrNToH(request);
-        gotlease = GetPktLease(&mDNSStorage, &request->msg, end, &lease);
-        ptr = LocateAuthorities(&request->msg, end);
-        for (i = 0; i < request->msg.h.mDNS_numUpdates; i++)
-        {
-            LargeCacheRecord lcr;
-            ptr = GetLargeResourceRecord(NULL, &request->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr);
-            if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rroriginalttl) adds++;else dels++;
-        }
-        HdrHToN(request);
-        if (adds && !gotlease)
-        {
-            static const mDNSOpaque16 UpdateRefused = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, kDNSFlag1_RC_Refused } };
-            Log("Rejecting Update Request with %d additions but no lease", adds);
-            reply = malloc(sizeof(*reply));
-            mDNSPlatformMemZero(&reply->src, sizeof(reply->src));
-            reply->len = sizeof(DNSMessageHeader);
-            reply->zone = NULL;
-            reply->isZonePublic = 0;
-            InitializeDNSMessage(&reply->msg.h, request->msg.h.id, UpdateRefused);
-            return(reply);
-        }
-        if (lease > 7200)   // Don't allow lease greater than two hours; typically 90-minute renewal period
-            lease = 7200;
-    }
-    // Send msg to server, read reply
-
-    if ( request->len <= 512 )
-    {
-        mDNSBool trunc;
-
-        if ( UDPServerTransaction( self, request, &buf, &trunc) < 0 )
-        {
-            Log("HandleRequest - UDPServerTransaction failed.  Trying TCP");
-        }
-        else if ( trunc )
-        {
-            VLog("HandleRequest - answer truncated.  Using TCP");
-        }
-        else
-        {
-            reply = &buf; // success
-        }
-    }
-
-    if ( !reply )
-    {
-        mDNSBool closed;
-        int res;
-
-        sock = ConnectToServer( self );
-        require_action_quiet( sock, exit, Log( "Discarding request from %s due to connection errors", inet_ntop( AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
-
-        res = SendPacket( sock, request );
-        require_action_quiet( res >= 0, exit, Log( "Couldn't relay message from %s to server.  Discarding.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
-
-        reply = RecvPacket( sock, &buf, &closed );
-    }
-
-    // IMPORTANT: reply is in network byte order at this point in the code
-    // We keep it this way because we send it back to the client in the same form
-
-    // Is it an update?
-
-    if ( reply && ( ( reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask ) == ( kDNSFlag0_OP_Update | kDNSFlag0_QR_Response ) ) )
-    {
-        char pingmsg[4];
-        mDNSBool ok = SuccessfulUpdateTransaction( request, reply );
-        require_action( ok, exit, VLog( "Message from %s not a successful update.", inet_ntop(AF_INET, &request->src.sin_addr, addrbuf, 32 ) ) );
-
-        UpdateLeaseTable( request, self, lease );
-
-        if ( lease > 0 )
-        {
-            leaseReply = FormatLeaseReply( self, reply, lease );
-
-            if ( !leaseReply )
-            {
-                Log("HandleRequest - unable to format lease reply");
-            }
-
-            // %%% Looks like a potential memory leak -- who frees the original reply?
-            reply = leaseReply;
-        }
-
-        // tell the main thread there was an update so it can send LLQs
-
-        if ( send( self->LLQEventNotifySock, pingmsg, sizeof( pingmsg ), 0 ) != sizeof( pingmsg ) )
-        {
-            LogErr("HandleRequest", "send");
-        }
-    }
-
-exit:
-
-    if ( sock )
-    {
-        mDNSPlatformTCPCloseConnection( sock );
-    }
-
-    if ( reply == &buf )
-    {
-        reply = malloc( sizeof( *reply ) );
-
-        if ( reply )
-        {
-            reply->len = buf.len;
-            memcpy(&reply->msg, &buf.msg, buf.len);
-        }
-        else
-        {
-            LogErr("HandleRequest", "malloc");
-        }
-    }
-
-    return reply;
-}
-
-
-//
-// LLQ Support Routines
-//
-
-// Set fields of an LLQ OPT Resource Record
-mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, const mDNSOpaque64 *const id, mDNSs32 lease)
-{
-    mDNSPlatformMemZero(opt, sizeof(*opt));
-    mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
-    opt->resrec.rrclass = NormalMaxDNSMessageData;
-    opt->resrec.rdlength   = sizeof(rdataOPT);  // One option in this OPT record
-    opt->resrec.rdestimate = sizeof(rdataOPT);
-    opt->resrec.rdata->u.opt[0].opt = kDNSOpt_LLQ;
-    opt->resrec.rdata->u.opt[0].u.llq.vers  = kLLQ_Vers;
-    opt->resrec.rdata->u.opt[0].u.llq.llqOp = opcode;
-    opt->resrec.rdata->u.opt[0].u.llq.err   = LLQErr_NoError;
-    opt->resrec.rdata->u.opt[0].u.llq.id    = *id;
-    opt->resrec.rdata->u.opt[0].u.llq.llqlease = lease;
-}
-
-// Calculate effective remaining lease of an LLQ
-mDNSlocal mDNSu32 LLQLease(LLQEntry *e)
-{
-    struct timeval t;
-
-    gettimeofday(&t, NULL);
-    if (e->expire < t.tv_sec) return 0;
-    else return e->expire - t.tv_sec;
-}
-
-mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e)
-{
-    int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
-    LLQEntry **ptr = &d->LLQTable[bucket];
-    AnswerListElem *a = e->AnswerList;
-    char addr[32];
-
-    inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
-    VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr);
-
-    if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE)
-    {
-        // currently, generating initial answers blocks the main thread, so we keep the answer list
-        // even if the ref count drops to zero.  To prevent unbounded table growth, we free shared answers
-        // if the ref count drops to zero AND there are more table elements than buckets
-        // !!!KRS update this when we make the table dynamically growable
-
-        CacheRecord *cr = a->KnownAnswers, *tmp;
-        AnswerListElem **tbl = &d->AnswerTable[bucket];
-
-        while (cr)
-        {
-            tmp = cr;
-            cr = cr->next;
-            free(tmp);
-        }
-
-        while (*tbl && *tbl != a) tbl = &(*tbl)->next;
-        if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; }
-        else Log("Error: DeleteLLQ - AnswerList not found in table");
-    }
-
-    // remove LLQ from table, free memory
-    while(*ptr && *ptr != e) ptr = &(*ptr)->next;
-    if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; }
-    *ptr = (*ptr)->next;
-    free(e);
-}
-
-mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst, TCPSocket *sock)
-{
-    char addr[32];
-    int err = -1;
-
-    HdrHToN(pkt);
-
-    if ( sock )
-    {
-        if ( SendPacket( sock, pkt ) != 0 )
-        {
-            LogErr("DaemonInfo", "MySend");
-            Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32));
-        }
-    }
-    else
-    {
-        if (sendto(d->llq_udpsd, &pkt->msg, pkt->len, 0, (struct sockaddr *)&dst, sizeof(dst)) != (int)pkt->len)
-        {
-            LogErr("DaemonInfo", "sendto");
-            Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32));
-        }
-    }
-
-    err = 0;
-    HdrNToH(pkt);
-    return err;
-}
-
-mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e)
-{
-    PktMsg q;
-    int i;
-    TCPSocket *sock = NULL;
-    const mDNSu8 *ansptr;
-    mDNSu8 *end = q.msg.data;
-    PktMsg buf, *reply = NULL;
-    LargeCacheRecord lcr;
-    CacheRecord *AnswerList = NULL;
-    mDNSu8 rcode;
-
-    VLog("Querying server for %##s type %d", e->name.c, e->type);
-
-    InitializeDNSMessage(&q.msg.h, zeroID, uQueryFlags);
-
-    end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN);
-    if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; }
-    q.len = (int)(end - (mDNSu8 *)&q.msg);
-
-    HdrHToN(&q);
-
-    if (!e->UseTCP)
-    {
-        mDNSBool trunc;
-
-        if (UDPServerTransaction(d, &q, &buf, &trunc) < 0)
-            Log("AnswerQuestion %##s - UDPServerTransaction failed.  Trying TCP", e->name.c);
-        else if (trunc)
-        { VLog("AnswerQuestion %##s - answer truncated.  Using TCP", e->name.c); e->UseTCP = mDNStrue; }
-        else reply = &buf;  // success
-    }
-
-    if (!reply)
-    {
-        mDNSBool closed;
-
-        sock = ConnectToServer(d);
-        if (!sock) { Log("AnswerQuestion: ConnectToServer failed"); goto end; }
-        if (SendPacket( sock, &q)) { Log("AnswerQuestion: SendPacket failed"); mDNSPlatformTCPCloseConnection( sock ); goto end; }
-        reply = RecvPacket( sock, NULL, &closed );
-        mDNSPlatformTCPCloseConnection( sock );
-        require_action( reply, end, Log( "AnswerQuestion: RecvPacket returned NULL" ) );
-    }
-
-    HdrNToH(&q);
-    if (reply) HdrNToH(reply);
-
-    if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery))
-    { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; }
-    rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC_Mask);
-    if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; }
-
-    end = (mDNSu8 *)&reply->msg + reply->len;
-    ansptr = LocateAnswers(&reply->msg, end);
-    if (!ansptr) { Log("Error: AnswerQuestion - LocateAnswers returned NULL"); goto end; }
-
-    for (i = 0; i < reply->msg.h.numAnswers; i++)
-    {
-        ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr);
-        if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; }
-        if (lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative)
-        {
-            if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name))
-            {
-                Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d.  Discarding",
-                    lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type);
-            }
-            else
-            {
-                CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name);
-                if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; }
-                cr->next = AnswerList;
-                AnswerList = cr;
-            }
-        }
-    }
-
-end:
-    if (reply && reply != &buf) free(reply);
-    return AnswerList;
-}
-
-// Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list
-mDNSlocal void *UpdateAnswerList(void *args)
-{
-    CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer"
-    DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d;
-    AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a;
-
-    free(args);
-    args = NULL;
-
-    // get up to date answers
-    NewAnswers = AnswerQuestion(d, a);
-
-    // first pass - mark all answers for deletion
-    for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
-        (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete
-
-    // second pass - mark answers pre-existent
-    for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
-    {
-        for (na = &NewAnswers; *na; na = &(*na)->next)
-        {
-            if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec))
-            { (*ka)->resrec.rroriginalttl = 0; break; }     // 0 means no change
-        }
-    }
-
-    // third pass - add new records to Event list
-    na = &NewAnswers;
-    while (*na)
-    {
-        for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
-            if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break;
-        if (!*ka)
-        {
-            // answer is not in list - splice from NewAnswers list, add to Event list
-            cr = *na;
-            *na = (*na)->next;        // splice from list
-            cr->next = a->EventList;  // add spliced record to event list
-            a->EventList = cr;
-            cr->resrec.rroriginalttl = 1; // 1 means add
-        }
-        else na = &(*na)->next;
-    }
-
-    // move all the removes from the answer list to the event list
-    ka = &a->KnownAnswers;
-    while (*ka)
-    {
-        if ((*ka)->resrec.rroriginalttl == (unsigned)-1)
-        {
-            cr = *ka;
-            *ka = (*ka)->next;
-            cr->next = a->EventList;
-            a->EventList = cr;
-        }
-        else ka = &(*ka)->next;
-    }
-
-    // lastly, free the remaining records (known answers) in NewAnswers list
-    while (NewAnswers)
-    {
-        cr = NewAnswers;
-        NewAnswers = NewAnswers->next;
-        free(cr);
-    }
-
-    return NULL;
-}
-
-mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e)
-{
-    PktMsg response;
-    CacheRecord *cr;
-    mDNSu8 *end = (mDNSu8 *)&response.msg.data;
-    mDNSOpaque16 msgID;
-    char rrbuf[MaxMsg], addrbuf[32];
-    AuthRecord opt;
-
-    // Should this really be random?  Do we use the msgID on the receiving end?
-    msgID.NotAnInteger = random();
-    if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
-    InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags);
-    end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
-    if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; }
-
-    // put adds/removes in packet
-    for (cr = e->AnswerList->EventList; cr; cr = cr->next)
-    {
-        if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf);
-        VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove" : "Add", rrbuf);
-        end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl);
-        if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; }
-    }
-
-    FormatLLQOpt(&opt, kLLQOp_Event, &e->id, LLQLease(e));
-    end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0);
-    if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; }
-
-    response.len = (int)(end - (mDNSu8 *)&response.msg);
-    if (SendLLQ(d, &response, e->cli, NULL ) < 0) LogMsg("Error: SendEvents - SendLLQ");
-}
-
-mDNSlocal void PrintLLQAnswers(DaemonInfo *d)
-{
-    int i;
-    char rrbuf[MaxMsg];
-
-    Log("Printing LLQ Answer Table contents");
-
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        AnswerListElem *a = d->AnswerTable[i];
-        while(a)
-        {
-            int ancount = 0;
-            const CacheRecord *rr = a->KnownAnswers;
-            while (rr) { ancount++; rr = rr->next; }
-            Log("%p : Question %##s;  type %d;  referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount);
-            for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf));
-            a = a->next;
-        }
-    }
-}
-
-mDNSlocal void PrintLLQTable(DaemonInfo *d)
-{
-    LLQEntry *e;
-    char addr[32];
-    int i;
-
-    Log("Printing LLQ table contents");
-
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        e = d->LLQTable[i];
-        while(e)
-        {
-            char *state;
-
-            switch (e->state)
-            {
-            case RequestReceived: state = "RequestReceived"; break;
-            case ChallengeSent:   state = "ChallengeSent";   break;
-            case Established:     state = "Established";     break;
-            default:              state = "unknown";
-            }
-            inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
-
-            Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)",
-                addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList);
-            e = e->next;
-        }
-    }
-}
-
-// Send events to clients as a result of a change in the zone
-mDNSlocal void GenLLQEvents(DaemonInfo *d)
-{
-    LLQEntry **e;
-    int i;
-    struct timeval t;
-    UpdateAnswerListArgs *args;
-
-    VLog("Generating LLQ Events");
-
-    gettimeofday(&t, NULL);
-
-    // get all answers up to date
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        AnswerListElem *a = d->AnswerTable[i];
-        while(a)
-        {
-            args = malloc(sizeof(*args));
-            if (!args) { LogErr("GenLLQEvents", "malloc"); return; }
-            args->d = d;
-            args->a = a;
-            if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; }
-            usleep(1);
-            a = a->next;
-        }
-    }
-
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        AnswerListElem *a = d->AnswerTable[i];
-        while(a)
-        {
-            if (pthread_join(a->tid, NULL)) LogErr("GenLLQEvents", "pthread_join");
-            a = a->next;
-        }
-    }
-
-    // for each established LLQ, send events
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        e = &d->LLQTable[i];
-        while(*e)
-        {
-            if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e);
-            else
-            {
-                if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e);
-                e = &(*e)->next;
-            }
-        }
-    }
-
-    // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes
-    for (i = 0; i < LLQ_TABLESIZE; i++)
-    {
-        AnswerListElem *a = d->AnswerTable[i];
-        while(a)
-        {
-            if (a->EventList)
-            {
-                CacheRecord *cr = a->EventList, *tmp;
-                while (cr)
-                {
-                    tmp = cr;
-                    cr = cr->next;
-                    if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp);
-                    else
-                    {
-                        tmp->next = a->KnownAnswers;
-                        a->KnownAnswers = tmp;
-                        tmp->resrec.rroriginalttl = 0;
-                    }
-                }
-                a->EventList = NULL;
-            }
-            a = a->next;
-        }
-    }
-}
-
-mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e)
-{
-    int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE;
-    AnswerListElem *a = d->AnswerTable[bucket];
-    while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next;
-    if (!a)
-    {
-        a = malloc(sizeof(*a));
-        if (!a) { LogErr("SetAnswerList", "malloc"); return; }
-        AssignDomainName(&a->name, &e->qname);
-        a->type = e->qtype;
-        a->refcount = 0;
-        a->EventList = NULL;
-        a->UseTCP = mDNSfalse;
-        a->next = d->AnswerTable[bucket];
-        d->AnswerTable[bucket] = a;
-        d->AnswerTableCount++;
-        a->KnownAnswers = AnswerQuestion(d, a);
-    }
-
-    e->AnswerList = a;
-    a->refcount++;
-}
-
-// Allocate LLQ entry, insert into table
-mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease )
-{
-    char addr[32];
-    struct timeval t;
-    int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
-    LLQEntry *e;
-
-    e = malloc(sizeof(*e));
-    if (!e) { LogErr("NewLLQ", "malloc"); return NULL; }
-
-    inet_ntop(AF_INET, &cli.sin_addr, addr, 32);
-    VLog("Allocating LLQ entry for client %s question %##s type %d", addr, qname->c, qtype);
-
-    // initialize structure
-    e->cli = cli;
-    AssignDomainName(&e->qname, qname);
-    e->qtype = qtype;
-    e->id    = zeroOpaque64;
-    e->state = RequestReceived;
-    e->AnswerList = NULL;
-
-    if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE;
-    else if (lease > LLQ_MAX_LEASE) lease = LLQ_MAX_LEASE;
-
-    gettimeofday(&t, NULL);
-    e->expire = t.tv_sec + (int)lease;
-    e->lease = lease;
-
-    // add to table
-    e->next = d->LLQTable[bucket];
-    d->LLQTable[bucket] = e;
-
-    return e;
-}
-
-// Handle a refresh request from client
-mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock )
-{
-    AuthRecord opt;
-    PktMsg ack;
-    mDNSu8 *end = (mDNSu8 *)&ack.msg.data;
-    char addr[32];
-
-    inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
-    VLog("%s LLQ for %##s from %s", llq->llqlease ? "Refreshing" : "Deleting", e->qname.c, addr);
-
-    if (llq->llqlease)
-    {
-        struct timeval t;
-        if (llq->llqlease < LLQ_MIN_LEASE) llq->llqlease = LLQ_MIN_LEASE;
-        else if (llq->llqlease > LLQ_MAX_LEASE) llq->llqlease = LLQ_MIN_LEASE;
-        gettimeofday(&t, NULL);
-        e->expire = t.tv_sec + llq->llqlease;
-    }
-
-    ack.src.sin_addr.s_addr = 0; // unused
-    InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags);
-    end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
-    if (!end) { Log("Error: putQuestion"); return; }
-
-    FormatLLQOpt(&opt, kLLQOp_Refresh, &e->id, llq->llqlease ? LLQLease(e) : 0);
-    end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0);
-    if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
-
-    ack.len = (int)(end - (mDNSu8 *)&ack.msg);
-    if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQRefresh");
-
-    if (llq->llqlease) e->state = Established;
-    else DeleteLLQ(d, e);
-}
-
-// Complete handshake with Ack an initial answers
-mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock)
-{
-    char addr[32];
-    CacheRecord *ptr;
-    AuthRecord opt;
-    PktMsg ack;
-    mDNSu8 *end = (mDNSu8 *)&ack.msg.data;
-    char rrbuf[MaxMsg], addrbuf[32];
-
-    inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32);
-
-    if (!mDNSSameOpaque64(&llq->id, &e->id) ||
-        llq->vers  != kLLQ_Vers             ||
-        llq->llqOp != kLLQOp_Setup          ||
-        llq->err   != LLQErr_NoError        ||
-        llq->llqlease > e->lease + LLQ_LEASE_FUDGE ||
-        llq->llqlease < e->lease - LLQ_LEASE_FUDGE)
-    {
-        Log("Incorrect challenge response from %s", addr);
-        return;
-    }
-
-    if (e->state == Established) VLog("Retransmitting LLQ ack + answers for %##s", e->qname.c);
-    else VLog("Delivering LLQ ack + answers for %##s", e->qname.c);
-
-    // format ack + answers
-    ack.src.sin_addr.s_addr = 0; // unused
-    InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags);
-    end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
-    if (!end) { Log("Error: putQuestion"); return; }
-
-    if (e->state != Established) { SetAnswerList(d, e); e->state = Established; }
-
-    if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32);
-    for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next)
-    {
-        if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf);
-        VLog("%s Intitial Answer - %s", addr, rrbuf);
-        end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAnswers, &ptr->resrec, 1);
-        if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
-    }
-
-    FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e));
-    end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0);
-    if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
-
-    ack.len = (int)(end - (mDNSu8 *)&ack.msg);
-    if (SendLLQ(d, &ack, e->cli, sock)) Log("Error: LLQCompleteHandshake");
-}
-
-mDNSlocal void LLQSetupChallenge(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID)
-{
-    struct timeval t;
-    PktMsg challenge;
-    mDNSu8 *end = challenge.msg.data;
-    AuthRecord opt;
-
-    if (e->state == ChallengeSent) VLog("Retransmitting LLQ setup challenge for %##s", e->qname.c);
-    else VLog("Sending LLQ setup challenge for %##s", e->qname.c);
-
-    if (!mDNSOpaque64IsZero(&llq->id)) { Log("Error: LLQSetupChallenge - nonzero ID"); return; } // server bug
-    if (llq->llqOp != kLLQOp_Setup) { Log("LLQSetupChallenge - incorrrect operation from client"); return; } // client error
-
-    if (mDNSOpaque64IsZero(&e->id)) // don't regenerate random ID for retransmissions
-    {
-        // construct ID <time><random>
-        gettimeofday(&t, NULL);
-        e->id.l[0] = t.tv_sec;
-        e->id.l[1] = random();
-    }
-
-    // format response (query + LLQ opt rr)
-    challenge.src.sin_addr.s_addr = 0; // unused
-    InitializeDNSMessage(&challenge.msg.h, msgID, ResponseFlags);
-    end = putQuestion(&challenge.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN);
-    if (!end) { Log("Error: putQuestion"); return; }
-    FormatLLQOpt(&opt, kLLQOp_Setup, &e->id, LLQLease(e));
-    end = PutResourceRecordTTLJumbo(&challenge.msg, end, &challenge.msg.h.numAdditionals, &opt.resrec, 0);
-    if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; }
-    challenge.len = (int)(end - (mDNSu8 *)&challenge.msg);
-    if (SendLLQ(d, &challenge, e->cli, NULL)) { Log("Error: LLQSetupChallenge"); return; }
-    e->state = ChallengeSent;
-}
-
-// Take action on an LLQ message from client.  Entry must be initialized and in table
-mDNSlocal void UpdateLLQ(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID, TCPSocket *sock )
-{
-    switch(e->state)
-    {
-    case RequestReceived:
-        if ( sock )
-        {
-            struct timeval t;
-            gettimeofday(&t, NULL);
-            e->id.l[0] = t.tv_sec;      // construct ID <time><random>
-            e->id.l[1] = random();
-            llq->id = e->id;
-            LLQCompleteHandshake( d, e, llq, msgID, sock );
-
-            // Set the state to established because we've just set the LLQ up using TCP
-            e->state = Established;
-        }
-        else
-        {
-            LLQSetupChallenge(d, e, llq, msgID);
-        }
-        return;
-    case ChallengeSent:
-        if (mDNSOpaque64IsZero(&llq->id)) LLQSetupChallenge(d, e, llq, msgID);     // challenge sent and lost
-        else LLQCompleteHandshake(d, e, llq, msgID, sock );
-        return;
-    case Established:
-        if (mDNSOpaque64IsZero(&llq->id))
-        {
-            // client started over.  reset state.
-            LLQEntry *newe = NewLLQ(d, e->cli, &e->qname, e->qtype, llq->llqlease );
-            if (!newe) return;
-            DeleteLLQ(d, e);
-            LLQSetupChallenge(d, newe, llq, msgID);
-            return;
-        }
-        else if (llq->llqOp == kLLQOp_Setup)
-        { LLQCompleteHandshake(d, e, llq, msgID, sock); return; }         // Ack lost
-        else if (llq->llqOp == kLLQOp_Refresh)
-        { LLQRefresh(d, e, llq, msgID, sock); return; }
-        else { Log("Unhandled message for established LLQ"); return; }
-    }
-}
-
-mDNSlocal LLQEntry *LookupLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, const mDNSOpaque64 *const id)
-{
-    int bucket = bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE;
-    LLQEntry *ptr = d->LLQTable[bucket];
-
-    while(ptr)
-    {
-        if (((ptr->state == ChallengeSent && mDNSOpaque64IsZero(id) && (cli.sin_port == ptr->cli.sin_port)) || // zero-id due to packet loss OK in state ChallengeSent
-             mDNSSameOpaque64(id, &ptr->id)) &&                        // id match
-            (cli.sin_addr.s_addr == ptr->cli.sin_addr.s_addr) && (qtype == ptr->qtype) && SameDomainName(&ptr->qname, qname)) // same source, type, qname
-            return ptr;
-        ptr = ptr->next;
-    }
-    return NULL;
-}
-
-mDNSlocal int
-RecvNotify
-(
-    DaemonInfo  *   d,
-    PktMsg      *   pkt
-)
-{
-    int res;
-    int err = 0;
-
-    pkt->msg.h.flags.b[0] |= kDNSFlag0_QR_Response;
-
-    res = sendto( d->udpsd, &pkt->msg, pkt->len, 0, ( struct sockaddr* ) &pkt->src, sizeof( pkt->src ) );
-    require_action( res == ( int ) pkt->len, exit, err = mStatus_UnknownErr; LogErr( "RecvNotify", "sendto" ) );
-
-exit:
-
-    return err;
-}
-
-
-mDNSlocal int RecvLLQ( DaemonInfo *d, PktMsg *pkt, TCPSocket *sock )
-{
-    DNSQuestion q;
-    LargeCacheRecord opt;
-    unsigned int i;
-    int err = -1;
-    char addr[32];
-    const mDNSu8 *qptr = pkt->msg.data;
-    const mDNSu8 *end = (mDNSu8 *)&pkt->msg + pkt->len;
-    const mDNSu8 *aptr;
-    LLQOptData *llq = NULL;
-    LLQEntry *e = NULL;
-
-    HdrNToH(pkt);
-    aptr = LocateAdditionals(&pkt->msg, end);   // Can't do this until after HdrNToH(pkt);
-    inet_ntop(AF_INET, &pkt->src.sin_addr, addr, 32);
-
-    VLog("Received LLQ msg from %s", addr);
-    // sanity-check packet
-    if (!pkt->msg.h.numQuestions || !pkt->msg.h.numAdditionals)
-    {
-        Log("Malformatted LLQ from %s with %d questions, %d additionals", addr, pkt->msg.h.numQuestions, pkt->msg.h.numAdditionals);
-        goto end;
-    }
-
-    // Locate the OPT record.
-    // According to RFC 2671, "One OPT pseudo-RR can be added to the additional data section of either a request or a response."
-    // This implies that there may be *at most* one OPT record per DNS message, in the Additional Section,
-    // but not necessarily the *last* entry in the Additional Section.
-    for (i = 0; i < pkt->msg.h.numAdditionals; i++)
-    {
-        aptr = GetLargeResourceRecord(NULL, &pkt->msg, aptr, end, 0, kDNSRecordTypePacketAdd, &opt);
-        if (!aptr) { Log("Malformatted LLQ from %s: could not get Additional record %u", addr, i); goto end; }
-        if (opt.r.resrec.RecordType != kDNSRecordTypePacketNegative && opt.r.resrec.rrtype == kDNSType_OPT) break;
-    }
-
-    // validate OPT
-    if (opt.r.resrec.rrtype != kDNSType_OPT) { Log("Malformatted LLQ from %s: last Additional not an OPT RR", addr); goto end; }
-    if (opt.r.resrec.rdlength < pkt->msg.h.numQuestions * DNSOpt_LLQData_Space) { Log("Malformatted LLQ from %s: OPT RR to small (%d bytes for %d questions)", addr, opt.r.resrec.rdlength, pkt->msg.h.numQuestions); }
-
-    // dispatch each question
-    for (i = 0; i < pkt->msg.h.numQuestions; i++)
-    {
-        qptr = getQuestion(&pkt->msg, qptr, end, 0, &q);
-        if (!qptr) { Log("Malformatted LLQ from %s: cannot read question %u", addr, i); goto end; }
-        llq = &opt.r.resrec.rdata->u.opt[i].u.llq; // point into OptData at index i
-        if (llq->vers != kLLQ_Vers) { Log("LLQ from %s contains bad version %d (expected %d)", addr, llq->vers, kLLQ_Vers); goto end; }
-
-        e = LookupLLQ(d, pkt->src, &q.qname, q.qtype, &llq->id);
-        if (!e)
-        {
-            // no entry - if zero ID, create new
-            e = NewLLQ(d, pkt->src, &q.qname, q.qtype, llq->llqlease );
-            if (!e) goto end;
-        }
-        UpdateLLQ(d, e, llq, pkt->msg.h.id, sock);
-    }
-    err = 0;
-
-end:
-    HdrHToN(pkt);
-    return err;
-}
-
-
-mDNSlocal mDNSBool IsAuthorized( DaemonInfo * d, PktMsg * pkt, DomainAuthInfo ** key, mDNSu16 * rcode, mDNSu16 * tcode )
-{
-    const mDNSu8    *   lastPtr = NULL;
-    const mDNSu8    *   ptr = NULL;
-    DomainAuthInfo  *   keys;
-    mDNSu8          *   end = ( mDNSu8* ) &pkt->msg + pkt->len;
-    LargeCacheRecord lcr;
-    mDNSBool hasTSIG = mDNSfalse;
-    mDNSBool strip = mDNSfalse;
-    mDNSBool ok = mDNSfalse;
-    int i;
-
-    // Unused parameters
-
-    ( void ) d;
-
-    HdrNToH(pkt);
-
-    *key = NULL;
-    bzero(&lcr, sizeof(lcr));
-
-    if ( pkt->msg.h.numAdditionals )
-    {
-        ptr = LocateAdditionals(&pkt->msg, end);
-        if (ptr)
-        {
-            for (i = 0; i < pkt->msg.h.numAdditionals; i++)
-            {
-                lastPtr = ptr;
-                ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr);
-                if (!ptr)
-                {
-                    Log("Unable to read additional record");
-                    lastPtr = NULL;
-                    break;
-                }
-            }
-
-            hasTSIG = ( ptr && lcr.r.resrec.RecordType != kDNSRecordTypePacketNegative && lcr.r.resrec.rrtype == kDNSType_TSIG );
-        }
-        else
-        {
-            LogMsg( "IsAuthorized: unable to find Additional section" );
-        }
-    }
-
-    // If we don't know what zone this is, then it's authorized.
-
-    if ( !pkt->zone )
-    {
-        ok = mDNStrue;
-        strip = mDNSfalse;
-        goto exit;
-    }
-
-    if ( IsQuery( pkt ) )
-    {
-        keys = pkt->zone->queryKeys;
-        strip = mDNStrue;
-    }
-    else if ( IsUpdate( pkt ) )
-    {
-        keys = pkt->zone->updateKeys;
-        strip = mDNSfalse;
-    }
-    else
-    {
-        ok = mDNStrue;
-        strip = mDNSfalse;
-        goto exit;
-    }
-
-    if ( pkt->isZonePublic )
-    {
-        ok = mDNStrue;
-        goto exit;
-    }
-
-    // If there are no keys, then we're authorized
-
-    if ( ( hasTSIG && !keys ) || ( !hasTSIG && keys ) )
-    {
-        Log( "Invalid TSIG spec %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c );
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadKey;
-        strip = mDNStrue;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    // Find the right key
-
-    for ( *key = keys; *key; *key = (*key)->next )
-    {
-        if ( SameDomainName( lcr.r.resrec.name, &(*key)->keyname ) )
-        {
-            break;
-        }
-    }
-
-    if ( !(*key) )
-    {
-        Log( "Invalid TSIG name %##s for zone %##s", lcr.r.resrec.name->c, pkt->zone->name.c );
-        *rcode = kDNSFlag1_RC_NotAuth;
-        *tcode = TSIG_ErrBadKey;
-        strip = mDNStrue;
-        ok = mDNSfalse;
-        goto exit;
-    }
-
-    // Okay, we have the correct key and a TSIG record.  DNSDigest_VerifyMessage does the heavy
-    // lifting of message verification
-
-    pkt->msg.h.numAdditionals--;
-
-    HdrHToN( pkt );
-
-    ok = DNSDigest_VerifyMessage( &pkt->msg, ( mDNSu8* ) lastPtr, &lcr, (*key), rcode, tcode );
-
-    HdrNToH( pkt );
-
-    pkt->msg.h.numAdditionals++;
-
-exit:
-
-    if ( hasTSIG && strip )
-    {
-        // Strip the TSIG from the message
-
-        pkt->msg.h.numAdditionals--;
-        pkt->len = lastPtr - ( mDNSu8* ) ( &pkt->msg );
-    }
-
-    HdrHToN(pkt);
-
-    return ok;
-}
-
-// request handler wrappers for TCP and UDP requests
-// (read message off socket, fork thread that invokes main processing routine and handles cleanup)
-
-mDNSlocal void*
-UDPMessageHandler
-(
-    void * vptr
-)
-{
-    UDPContext  *   context = ( UDPContext* ) vptr;
-    PktMsg      *   reply   = NULL;
-    int res;
-
-    // !!!KRS strictly speaking, we shouldn't use TCP for a UDP request because the server
-    // may give us a long answer that would require truncation for UDP delivery to client
-
-    reply = HandleRequest( context->d, &context->pkt );
-    require_action( reply, exit, );
-
-    res = sendto( context->sd, &reply->msg, reply->len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
-    require_action_quiet( res == ( int ) reply->len, exit, LogErr( "UDPMessageHandler", "sendto" ) );
-
-exit:
-
-    if ( reply )
-    {
-        free( reply );
-    }
-
-    free( context );
-
-    pthread_exit( NULL );
-
-    return NULL;
-}
-
-
-mDNSlocal int
-RecvUDPMessage
-(
-    DaemonInfo  *   self,
-    int sd
-)
-{
-    UDPContext      *   context = NULL;
-    pthread_t tid;
-    mDNSu16 rcode;
-    mDNSu16 tcode;
-    DomainAuthInfo  *   key;
-    unsigned int clisize = sizeof( context->cliaddr );
-    int res;
-    mStatus err = mStatus_NoError;
-
-    context = malloc( sizeof( UDPContext ) );
-    require_action( context, exit, err = mStatus_NoMemoryErr ; LogErr( "RecvUDPMessage", "malloc" ) );
-
-    mDNSPlatformMemZero( context, sizeof( *context ) );
-    context->d = self;
-    context->sd = sd;
-
-    res = recvfrom(sd, &context->pkt.msg, sizeof(context->pkt.msg), 0, (struct sockaddr *)&context->cliaddr, &clisize);
-
-    require_action( res >= 0, exit, err = mStatus_UnknownErr ; LogErr( "RecvUDPMessage", "recvfrom" ) );
-    context->pkt.len = res;
-    require_action( clisize == sizeof( context->cliaddr ), exit, err = mStatus_UnknownErr ; Log( "Client address of unknown size %d", clisize ) );
-    context->pkt.src = context->cliaddr;
-
-    // Set the zone in the packet
-
-    SetZone( context->d, &context->pkt );
-
-    // Notify messages handled by main thread
-
-    if ( IsNotify( &context->pkt ) )
-    {
-        int e = RecvNotify( self, &context->pkt );
-        free(context);
-        return e;
-    }
-    else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
-    {
-        if ( IsLLQRequest( &context->pkt ) )
-        {
-            // LLQ messages handled by main thread
-            int e = RecvLLQ( self, &context->pkt, NULL );
-            free(context);
-            return e;
-        }
-
-        if ( IsLLQAck(&context->pkt ) )
-        {
-            // !!!KRS need to do acks + retrans
-
-            free(context);
-            return 0;
-        }
-
-        err = pthread_create( &tid, NULL, UDPMessageHandler, context );
-        require_action( !err, exit, LogErr( "RecvUDPMessage", "pthread_create" ) );
-
-        pthread_detach(tid);
-    }
-    else
-    {
-        PktMsg reply;
-        int e;
-
-        memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
-
-        reply.msg.h.flags.b[0]  =  kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
-        reply.msg.h.flags.b[1]  =  kDNSFlag1_RA | kDNSFlag1_RC_NXDomain;
-
-        e = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
-        require_action_quiet( e == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) );
-
-        err = mStatus_NoAuth;
-    }
-
-exit:
-
-    if ( err && context )
-    {
-        free( context );
-    }
-
-    return err;
-}
-
-
-mDNSlocal void
-FreeTCPContext
-(
-    TCPContext * context
-)
-{
-    if ( context )
-    {
-        if ( context->sock )
-        {
-            mDNSPlatformTCPCloseConnection( context->sock );
-        }
-
-        free( context );
-    }
-}
-
-
-mDNSlocal void*
-TCPMessageHandler
-(
-    void * vptr
-)
-{
-    TCPContext  *   context = ( TCPContext* ) vptr;
-    PktMsg      *   reply = NULL;
-    int res;
-    char buf[32];
-
-    //!!!KRS if this read blocks indefinitely, we can run out of threads
-    // read the request
-
-    reply = HandleRequest( context->d, &context->pkt );
-    require_action_quiet( reply, exit, LogMsg( "TCPMessageHandler: No reply for client %s", inet_ntop( AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) );
-
-    // deliver reply to client
-
-    res = SendPacket( context->sock, reply );
-    require_action( res >= 0, exit, LogMsg("TCPMessageHandler: Unable to send reply to client %s", inet_ntop(AF_INET, &context->cliaddr.sin_addr, buf, 32 ) ) );
-
-exit:
-
-    FreeTCPContext( context );
-
-    if ( reply )
-    {
-        free( reply );
-    }
-
-    pthread_exit(NULL);
-}
-
-
-mDNSlocal void
-RecvTCPMessage
-(
-    void * param
-)
-{
-    TCPContext      *   context = ( TCPContext* ) param;
-    mDNSu16 rcode;
-    mDNSu16 tcode;
-    pthread_t tid;
-    DomainAuthInfo  *   key;
-    PktMsg          *   pkt;
-    mDNSBool closed;
-    mDNSBool freeContext = mDNStrue;
-    mStatus err = mStatus_NoError;
-
-    // Receive a packet.  It's okay if we don't actually read a packet, as long as the closed flag is
-    // set to false.  This is because SSL/TLS layer might gobble up the first packet that we read off the
-    // wire.  We'll let it do that, and wait for the next packet which will be ours.
-
-    pkt = RecvPacket( context->sock, &context->pkt, &closed );
-    if (pkt) HdrNToH(pkt);
-    require_action( pkt || !closed, exit, err = mStatus_UnknownErr; LogMsg( "client disconnected" ) );
-
-    if ( pkt )
-    {
-        // Always do this, regardless of what kind of packet it is.  If we wanted LLQ events to be sent over TCP,
-        // we would change this line of code.  As it is now, we will reply to an LLQ via TCP, but then events
-        // are sent over UDP
-
-        RemoveSourceFromEventLoop( context->d, context->sock );
-
-        // Set's the DNS Zone that is associated with this message
-
-        SetZone( context->d, &context->pkt );
-
-        // IsAuthorized will make sure the message is authorized for the designated zone.
-        // After verifying the signature, it will strip the TSIG from the message
-
-        if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
-        {
-            if ( IsLLQRequest( &context->pkt ) )
-            {
-                // LLQ messages handled by main thread
-                RecvLLQ( context->d, &context->pkt, context->sock);
-            }
-            else
-            {
-                err = pthread_create( &tid, NULL, TCPMessageHandler, context );
-
-                if ( err )
-                {
-                    LogErr( "RecvTCPMessage", "pthread_create" );
-                    err = mStatus_NoError;
-                    goto exit;
-                }
-
-                // Let the thread free the context
-
-                freeContext = mDNSfalse;
-
-                pthread_detach(tid);
-            }
-        }
-        else
-        {
-            PktMsg reply;
-
-            LogMsg( "Client %s Not authorized for zone %##s", inet_ntoa( context->pkt.src.sin_addr ), pkt->zone->name.c );
-
-            memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
-
-            reply.msg.h.flags.b[0]  =  kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
-            reply.msg.h.flags.b[1]  =  kDNSFlag1_RA | kDNSFlag1_RC_Refused;
-
-            SendPacket( context->sock, &reply );
-        }
-    }
-    else
-    {
-        freeContext = mDNSfalse;
-    }
-
-exit:
-
-    if ( err )
-    {
-        RemoveSourceFromEventLoop( context->d, context->sock );
-    }
-
-    if ( freeContext )
-    {
-        FreeTCPContext( context );
-    }
-}
-
-
-mDNSlocal int
-AcceptTCPConnection
-(
-    DaemonInfo      *   self,
-    int sd,
-    TCPSocketFlags flags
-)
-{
-    TCPContext *    context = NULL;
-    unsigned int clilen = sizeof( context->cliaddr);
-    int newSock;
-    mStatus err = mStatus_NoError;
-
-    context = ( TCPContext* ) malloc( sizeof( TCPContext ) );
-    require_action( context, exit, err = mStatus_NoMemoryErr; LogErr( "AcceptTCPConnection", "malloc" ) );
-    mDNSPlatformMemZero( context, sizeof( sizeof( TCPContext ) ) );
-    context->d       = self;
-    newSock = accept( sd, ( struct sockaddr* ) &context->cliaddr, &clilen );
-    require_action( newSock != -1, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "accept" ) );
-
-    context->sock = mDNSPlatformTCPAccept( flags, newSock );
-    require_action( context->sock, exit, err = mStatus_UnknownErr; LogErr( "AcceptTCPConnection", "mDNSPlatformTCPAccept" ) );
-
-    err = AddSourceToEventLoop( self, context->sock, RecvTCPMessage, context );
-    require_action( !err, exit, LogErr( "AcceptTCPConnection", "AddSourceToEventLoop" ) );
-
-exit:
-
-    if ( err && context )
-    {
-        free( context );
-        context = NULL;
-    }
-
-    return err;
-}
-
-
-// main event loop
-// listen for incoming requests, periodically check table for expired records, respond to signals
-mDNSlocal int Run(DaemonInfo *d)
-{
-    int staticMaxFD, nfds;
-    fd_set rset;
-    struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 };
-    mDNSBool EventsPending = mDNSfalse;
-
-    VLog("Listening for requests...");
-
-    staticMaxFD = 0;
-
-    if ( d->tcpsd + 1  > staticMaxFD ) staticMaxFD = d->tcpsd + 1;
-    if ( d->udpsd + 1  > staticMaxFD ) staticMaxFD = d->udpsd + 1;
-    if ( d->tlssd + 1  > staticMaxFD ) staticMaxFD = d->tlssd + 1;
-    if ( d->llq_tcpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_tcpsd + 1;
-    if ( d->llq_udpsd + 1 > staticMaxFD ) staticMaxFD = d->llq_udpsd + 1;
-    if ( d->LLQEventListenSock + 1 > staticMaxFD ) staticMaxFD = d->LLQEventListenSock + 1;
-
-    while(1)
-    {
-        EventSource * source;
-        int maxFD;
-
-        // set timeout
-        timeout.tv_sec = timeout.tv_usec = 0;
-        if (gettimeofday(&timenow, NULL)) { LogErr("Run", "gettimeofday"); return -1; }
-
-        if (EventsPending)
-        {
-            if (timenow.tv_sec - EventTS.tv_sec >= 5)           // if we've been waiting 5 seconds for a "quiet" period to send
-            { GenLLQEvents(d); EventsPending = mDNSfalse; }     // events, we go ahead and do it now
-            else timeout.tv_usec = 500000;                      // else do events after 1/2 second with no new events or LLQs
-        }
-        if (!EventsPending)
-        {
-            // if no pending events, timeout when we need to check for expired records
-            if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0)
-            { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; }     // table check overdue
-            if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL;
-            timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec;
-        }
-
-        FD_ZERO(&rset);
-        FD_SET( d->tcpsd, &rset );
-        FD_SET( d->udpsd, &rset );
-        FD_SET( d->tlssd, &rset );
-        FD_SET( d->llq_tcpsd, &rset );
-        FD_SET( d->llq_udpsd, &rset );
-        FD_SET( d->LLQEventListenSock, &rset );
-
-        maxFD = staticMaxFD;
-
-        for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next )
-        {
-            FD_SET( source->fd, &rset );
-
-            if ( source->fd > maxFD )
-            {
-                maxFD = source->fd;
-            }
-        }
-
-        nfds = select( maxFD + 1, &rset, NULL, NULL, &timeout);
-        if (nfds < 0)
-        {
-            if (errno == EINTR)
-            {
-                if (terminate)
-                {
-                    // close sockets to prevent clients from making new requests during shutdown
-                    close( d->tcpsd );
-                    close( d->udpsd );
-                    close( d->tlssd );
-                    close( d->llq_tcpsd );
-                    close( d->llq_udpsd );
-                    d->tcpsd = d->udpsd = d->tlssd = d->llq_tcpsd = d->llq_udpsd = -1;
-                    DeleteRecords(d, mDNStrue);
-                    return 0;
-                }
-                else if (dumptable)
-                {
-                    Log( "Received SIGINFO" );
-
-                    PrintLeaseTable(d);
-                    PrintLLQTable(d);
-                    PrintLLQAnswers(d);
-                    dumptable = 0;
-                }
-                else if (hangup)
-                {
-                    int err;
-
-                    Log( "Received SIGHUP" );
-
-                    err = ParseConfig( d, cfgfile );
-
-                    if ( err )
-                    {
-                        LogErr( "Run", "ParseConfig" );
-                        return -1;
-                    }
-
-                    hangup = 0;
-                }
-                else
-                {
-                    Log("Received unhandled signal - continuing");
-                }
-            }
-            else
-            {
-                LogErr("Run", "select"); return -1;
-            }
-        }
-        else if (nfds)
-        {
-            if (FD_ISSET(d->udpsd, &rset)) RecvUDPMessage( d, d->udpsd );
-            if (FD_ISSET(d->llq_udpsd, &rset)) RecvUDPMessage( d, d->llq_udpsd );
-            if (FD_ISSET(d->tcpsd, &rset)) AcceptTCPConnection( d, d->tcpsd, 0 );
-            if (FD_ISSET(d->llq_tcpsd, &rset)) AcceptTCPConnection( d, d->llq_tcpsd, 0 );
-            if (FD_ISSET(d->tlssd, &rset)) AcceptTCPConnection( d, d->tlssd, TCP_SOCKET_FLAGS );
-            if (FD_ISSET(d->LLQEventListenSock, &rset))
-            {
-                // clear signalling data off socket
-                char buf[256];
-                recv(d->LLQEventListenSock, buf, 256, 0);
-                if (!EventsPending)
-                {
-                    EventsPending = mDNStrue;
-                    if (gettimeofday(&EventTS, NULL)) { LogErr("Run", "gettimeofday"); return -1; }
-                }
-            }
-
-            for ( source = ( EventSource* ) d->eventSources.Head; source; source = source->next )
-            {
-                if ( FD_ISSET( source->fd, &rset ) )
-                {
-                    source->callback( source->context );
-                    break;  // in case we removed this guy from the event loop
-                }
-            }
-        }
-        else
-        {
-            // timeout
-            if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; }
-            else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; }
-        }
-    }
-    return 0;
-}
-
-// signal handler sets global variables, which are inspected by main event loop
-// (select automatically returns due to the handled signal)
-mDNSlocal void HndlSignal(int sig)
-{
-    if (sig == SIGTERM || sig == SIGINT ) { terminate = 1; return; }
-    if (sig == INFO_SIGNAL)               { dumptable = 1; return; }
-    if (sig == SIGHUP)                    { hangup    = 1; return; }
-}
-
-mDNSlocal mStatus
-SetPublicSRV
-(
-    DaemonInfo  *   d,
-    const char  *   name
-)
-{
-    DNameListElem * elem;
-    mStatus err = mStatus_NoError;
-
-    elem = ( DNameListElem* ) malloc( sizeof( DNameListElem ) );
-    require_action( elem, exit, err = mStatus_NoMemoryErr );
-    MakeDomainNameFromDNSNameString( &elem->name, name );
-    elem->next = d->public_names;
-    d->public_names = elem;
-
-exit:
-
-    return err;
-}
-
-
-int main(int argc, char *argv[])
-{
-    int started_via_launchd = 0;
-    DaemonInfo *d;
-    struct rlimit rlim;
-
-    Log("dnsextd starting");
-
-    d = malloc(sizeof(*d));
-    if (!d) { LogErr("main", "malloc"); exit(1); }
-    mDNSPlatformMemZero(d, sizeof(DaemonInfo));
-
-    // Setup the public SRV record names
-
-    SetPublicSRV(d, "_dns-update._udp.");
-    SetPublicSRV(d, "_dns-llq._udp.");
-    SetPublicSRV(d, "_dns-update-tls._tcp.");
-    SetPublicSRV(d, "_dns-query-tls._tcp.");
-    SetPublicSRV(d, "_dns-llq-tls._tcp.");
-
-    // Setup signal handling
-
-    if (signal(SIGHUP,      HndlSignal) == SIG_ERR) perror("Can't catch SIGHUP");
-    if (signal(SIGTERM,     HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM");
-    if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO");
-    if (signal(SIGINT,      HndlSignal) == SIG_ERR) perror("Can't catch SIGINT");
-    if (signal(SIGPIPE,     SIG_IGN  )  == SIG_ERR) perror("Can't ignore SIGPIPE");
-
-    // remove open file limit
-    rlim.rlim_max = RLIM_INFINITY;
-    rlim.rlim_cur = RLIM_INFINITY;
-    if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
-    {
-        LogErr("main", "setrlimit");
-        Log("Using default file descriptor resource limit");
-    }
-
-    if (argc > 1 && !strcasecmp(argv[1], "-launchd"))
-    {
-        Log("started_via_launchd");
-        started_via_launchd = 1;
-        argv++;
-        argc--;
-    }
-    if (ProcessArgs(argc, argv, d) < 0) { LogErr("main", "ProcessArgs"); exit(1); }
-
-    if (!foreground && !started_via_launchd)
-    {
-        if (daemon(0,0))
-        {
-            LogErr("main", "daemon");
-            foreground = 1;
-        }
-    }
-
-    if (InitLeaseTable(d) < 0) { LogErr("main", "InitLeaseTable"); exit(1); }
-    if (SetupSockets(d) < 0) { LogErr("main", "SetupSockets"); exit(1); }
-    if (SetUpdateSRV(d) < 0) { LogErr("main", "SetUpdateSRV"); exit(1); }
-
-    Run(d);
-
-    Log("dnsextd stopping");
-
-    if (ClearUpdateSRV(d) < 0) { LogErr("main", "ClearUpdateSRV"); exit(1); }  // clear update srv's even if Run or pthread_create returns an error
-    free(d);
-    exit(0);
-}
-
-
-// These are stubbed out implementations of up-call routines that the various platform support layers
-// call.  These routines are fully implemented in both mDNS.c and uDNS.c, but dnsextd doesn't
-// link this code in.
-//
-// It's an error for these routines to actually be called, so perhaps we should log any call
-// to them.
-void mDNSCoreInitComplete( mDNS * const m, mStatus result) { ( void ) m; ( void ) result; }
-void mDNS_ConfigChanged(mDNS *const m)  { ( void ) m; }
-void mDNSCoreMachineSleep(mDNS * const m, mDNSBool wake) { ( void ) m; ( void ) wake; }
-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 iid)
-{ ( void ) m; ( void ) msg; ( void ) end; ( void ) srcaddr; ( void ) srcport; ( void ) dstaddr; ( void ) dstport; ( void ) iid; }
-DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const int serviceID, const mDNSAddr *addr, const mDNSIPPort port, 
-                             mDNSu32 scopedType, mDNSu32 timeout, mDNSBool isCell, mDNSBool isExpensive, mDNSBool isConstrained,  mDNSBool isCLAT46, mDNSu32 resGroupID, mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO)
-{ ( void ) m; ( void ) d; ( void ) interface; ( void ) serviceID; ( void ) addr; ( void ) port; ( void ) scopedType; ( void ) timeout; (void) isCell; (void) isExpensive; (void) isConstrained; (void) isCLAT46;
-    (void) resGroupID; (void) reqA; (void) reqAAAA; (void) reqDO; return(NULL); }
-void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID) { (void)domain; (void) InterfaceID;}
-void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext)
-{ ( void ) m; ( void ) fqdn; ( void ) StatusCallback; ( void ) StatusContext; }
-mDNSs32 mDNS_Execute   (mDNS *const m) { ( void ) m; return 0; }
-mDNSs32 mDNS_TimeNow(const mDNS *const m) { ( void ) m; return 0; }
-mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; }
-void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed)
-{ ( void ) m; ( void ) set; ( void ) activationSpeed; }
-const char * const mDNS_DomainTypeNames[1] = {};
-mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
-                        const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
-{ ( void ) m; ( void ) question; ( void ) DomainType; ( void ) dom; ( void ) InterfaceID; ( void ) Callback; ( void ) Context; return 0; }
-mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr) { ( void ) m; ( void ) rr; return 0; }
-mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed)
-{ ( void ) m; ( void ) set; ( void ) activationSpeed; return 0; }
-void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) { ( void ) m; ( void ) fqdn; }
-void mDNS_SetFQDN(mDNS * const m) { ( void ) m; }
-void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router)
-{ ( void ) m; ( void ) v4addr; ( void ) v6addr; ( void ) router; }
-mStatus uDNS_SetupDNSConfig( mDNS *const m ) { ( void ) m; return 0; }
-mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
-                                const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port)
-{ ( void ) m; ( void ) info; ( void ) domain; ( void ) keyname; ( void ) b64keydata; ( void ) hostname; (void) port; return 0; }
-mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; ( void ) question; return 0; }
-void TriggerEventCompletion(void);
-void TriggerEventCompletion() {}
-mDNS mDNSStorage;
-
-
-// For convenience when using the "strings" command, this is the last thing in the file
-// The "@(#) " pattern is a special prefix the "what" command looks for
-const char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-
-#if _BUILDING_XCODE_PROJECT_
-// If the process crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
-asm (".desc ___crashreporter_info__, 0x10");
-#endif
diff --git a/mDNSShared/dnsextd.h b/mDNSShared/dnsextd.h
deleted file mode 100644
index a6a1668..0000000
--- a/mDNSShared/dnsextd.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2006-2018 Apple 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.
- */
-
-
-#ifndef _dnsextd_h
-#define _dnsextd_h
-
-
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-#include "GenLinkedList.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-
-#define LLQ_TABLESIZE   1024    // !!!KRS make this dynamically growable
-
-
-typedef enum DNSZoneSpecType
-{
-    kDNSZonePublic,
-    kDNSZonePrivate
-} DNSZoneSpecType;
-
-
-typedef struct DNSZone
-{
-    domainname name;
-    DNSZoneSpecType type;
-    DomainAuthInfo      *   updateKeys; // linked list of keys for signing deletion updates
-    DomainAuthInfo      *   queryKeys;  // linked list of keys for queries
-    struct DNSZone      *   next;
-} DNSZone;
-
-
-typedef struct
-{
-    struct sockaddr_in src;
-    size_t len;
-    DNSZone * zone;
-    mDNSBool isZonePublic;
-    DNSMessage msg;
-    // Note: extra storage for oversized (TCP) messages goes here
-} PktMsg;
-
-// lease table entry
-typedef struct RRTableElem
-{
-    struct RRTableElem *next;
-    struct sockaddr_in cli;   // client's source address
-    long expire;              // expiration time, in seconds since epoch
-    domainname zone;          // from zone field of update message
-    domainname name;          // name of the record
-    CacheRecord rr;           // last field in struct allows for allocation of oversized RRs
-} RRTableElem;
-
-typedef enum
-{
-    RequestReceived = 0,
-    ChallengeSent   = 1,
-    Established     = 2
-} LLQState;
-
-typedef struct AnswerListElem
-{
-    struct AnswerListElem *next;
-    domainname name;
-    mDNSu16 type;
-    CacheRecord *KnownAnswers;  // All valid answers delivered to client
-    CacheRecord *EventList;     // New answers (adds/removes) to be sent to client
-    int refcount;
-    mDNSBool UseTCP;            // Use TCP if UDP would cause truncation
-    pthread_t tid;              // Allow parallel list updates
-} AnswerListElem;
-
-// llq table entry
-typedef struct LLQEntry
-{
-    struct LLQEntry *next;
-    struct sockaddr_in cli;   // clien'ts source address
-    domainname qname;
-    mDNSu16 qtype;
-    mDNSOpaque64 id;
-    LLQState state;
-    mDNSu32 lease;            // original lease, in seconds
-    mDNSs32 expire;           // expiration, absolute, in seconds since epoch
-    AnswerListElem *AnswerList;
-} LLQEntry;
-
-
-typedef void (*EventCallback)( void * context );
-
-typedef struct EventSource
-{
-    EventCallback callback;
-    void                *   context;
-    TCPSocket *         sock;
-    int fd;
-    mDNSBool markedForDeletion;
-    struct  EventSource *   next;
-} EventSource;
-
-
-// daemon-wide information
-typedef struct
-{
-    // server variables - read only after initialization (no locking)
-    struct sockaddr_in addr;            // the address we will bind to
-    struct sockaddr_in llq_addr;        // the address we will receive llq requests on.
-    struct sockaddr_in ns_addr;         // the real ns server address
-    int tcpsd;                          // listening TCP socket for dns requests
-    int udpsd;                          // listening UDP socket for dns requests
-    int tlssd;                          // listening TCP socket for private browsing
-    int llq_tcpsd;                      // listening TCP socket for llq service
-    int llq_udpsd;                      // listening UDP socket for llq service
-    DNameListElem   *   public_names;   // list of public SRV names
-    DNSZone         *   zones;
-
-    // daemon variables - read only after initialization (no locking)
-    mDNSIPPort private_port;           // listening port for private messages
-    mDNSIPPort llq_port;           // listening port for llq
-
-    // lease table variables (locked via mutex after initialization)
-    RRTableElem **table;       // hashtable for records with leases
-    pthread_mutex_t tablelock; // mutex for lease table
-    mDNSs32 nbuckets;          // buckets allocated
-    mDNSs32 nelems;            // elements in table
-
-    // LLQ table variables
-    LLQEntry *LLQTable[LLQ_TABLESIZE];  // !!!KRS change this and RRTable to use a common data structure
-    AnswerListElem *AnswerTable[LLQ_TABLESIZE];
-    int AnswerTableCount;
-    int LLQEventNotifySock;          // Unix domain socket pair - update handling thread writes to EventNotifySock, which wakes
-    int LLQEventListenSock;          // the main thread listening on EventListenSock, indicating that the zone has changed
-
-    GenLinkedList eventSources;     // linked list of EventSource's
-} DaemonInfo;
-
-
-int
-ParseConfig
-(
-    DaemonInfo  *   d,
-    const char  *   file
-);
-
-
-#endif
diff --git a/mDNSShared/dnssd_clientlib.c b/mDNSShared/dnssd_clientlib.c
deleted file mode 100644
index a1d98d9..0000000
--- a/mDNSShared/dnssd_clientlib.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2004-2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "dns_sd.h"
-#include "mdns_strict.h"
-
-#if defined(_WIN32)
-// disable warning "conversion from <data> to uint16_t"
-#pragma warning(disable:4244)
-#define strncasecmp _strnicmp
-#define strcasecmp _stricmp
-#endif
-
-/*********************************************************************************************
-*
-*  Supporting Functions
-*
-*********************************************************************************************/
-
-#define mDNSIsDigit(X)     ((X) >= '0' && (X) <= '9')
-
-// DomainEndsInDot returns 1 if name ends with a dot, 0 otherwise
-// (DNSServiceConstructFullName depends this returning 1 for true, rather than any non-zero value meaning true)
-
-static int DomainEndsInDot(const char *dom)
-{
-    while (dom[0] && dom[1])
-    {
-        if (dom[0] == '\\') // advance past escaped byte sequence
-        {
-            if (mDNSIsDigit(dom[1]) && mDNSIsDigit(dom[2]) && mDNSIsDigit(dom[3]))
-                dom += 4;           // If "\ddd"    then skip four
-            else dom += 2;          // else if "\x" then skip two
-        }
-        else dom++;                 // else goto next character
-    }
-    return (dom[0] == '.');
-}
-
-static const uint8_t *InternalTXTRecordSearch
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    const char       *key,
-    unsigned long    *keylen
-)
-{
-    const uint8_t *p = (const uint8_t*)txtRecord;
-    const uint8_t *e = p + txtLen;
-    *keylen = (unsigned long) strlen(key);
-    while (p<e)
-    {
-        const uint8_t *x = p;
-        p += 1 + p[0];
-        if (p <= e && *keylen <= x[0] && !strncasecmp(key, (const char*)x+1, *keylen))
-            if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
-    }
-    return(NULL);
-}
-
-/*********************************************************************************************
-*
-*  General Utility Functions
-*
-*********************************************************************************************/
-
-// Note: Need to make sure we don't write more than kDNSServiceMaxDomainName (1009) bytes to fullName
-// In earlier builds this constant was defined to be 1005, so to avoid buffer overruns on clients
-// compiled with that constant we'll actually limit the output to 1005 bytes.
-
-DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
-(
-    char       *const fullName,
-    const char *const service,      // May be NULL
-    const char *const regtype,
-    const char *const domain
-)
-{
-    const size_t len = !regtype ? 0 : strlen(regtype) - DomainEndsInDot(regtype);
-    char       *fn   = fullName;
-    char *const lim  = fullName + 1005;
-    const char *s    = service;
-    const char *r    = regtype;
-    const char *d    = domain;
-
-    // regtype must be at least "x._udp" or "x._tcp"
-    if (len < 6 || !domain || !domain[0]) return kDNSServiceErr_BadParam;
-    if (strncasecmp((regtype + len - 4), "_tcp", 4) && strncasecmp((regtype + len - 4), "_udp", 4)) return kDNSServiceErr_BadParam;
-
-    if (service && *service)
-    {
-        while (*s)
-        {
-            unsigned char c = *s++;             // Needs to be unsigned, or values like 0xFF will be interpreted as < 32
-            if (c <= ' ')                       // Escape non-printable characters
-            {
-                if (fn+4 >= lim) goto fail;
-                *fn++ = '\\';
-                *fn++ = '0' + (c / 100);
-                *fn++ = '0' + (c /  10) % 10;
-                c     = '0' + (c      ) % 10;
-            }
-            else if (c == '.' || (c == '\\'))   // Escape dot and backslash literals
-            {
-                if (fn+2 >= lim) goto fail;
-                *fn++ = '\\';
-            }
-            else
-            if (fn+1 >= lim) goto fail;
-            *fn++ = (char)c;
-        }
-        *fn++ = '.';
-    }
-
-    while (*r) if (fn+1 >= lim) goto fail;else *fn++ = *r++;
-    if (!DomainEndsInDot(regtype)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';}
-
-    while (*d) if (fn+1 >= lim) goto fail;else *fn++ = *d++;
-    if (!DomainEndsInDot(domain)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';}
-
-    *fn = '\0';
-    return kDNSServiceErr_NoError;
-
-fail:
-    *fn = '\0';
-    return kDNSServiceErr_BadParam;
-}
-
-/*********************************************************************************************
-*
-*   TXT Record Construction Functions
-*
-*********************************************************************************************/
-
-typedef struct _TXTRecordRefRealType
-{
-    uint8_t  *buffer;       // Pointer to data
-    uint16_t buflen;        // Length of buffer
-    uint16_t datalen;       // Length currently in use
-    uint16_t malloced;  // Non-zero if buffer was allocated via malloc()
-} TXTRecordRefRealType;
-
-#define txtRec ((TXTRecordRefRealType*)txtRecord)
-
-// The opaque storage defined in the public dns_sd.h header is 16 bytes;
-// make sure we don't exceed that.
-struct CompileTimeAssertionCheck_dnssd_clientlib
-{
-    char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
-};
-
-void DNSSD_API TXTRecordCreate
-(
-    TXTRecordRef     *txtRecord,
-    uint16_t bufferLen,
-    void             *buffer
-)
-{
-    txtRec->buffer   = buffer;
-    txtRec->buflen   = buffer ? bufferLen : (uint16_t)0;
-    txtRec->datalen  = 0;
-    txtRec->malloced = 0;
-}
-
-void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord)
-{
-    if (txtRec->malloced) mdns_free(txtRec->buffer);
-}
-
-DNSServiceErrorType DNSSD_API TXTRecordSetValue
-(
-    TXTRecordRef     *txtRecord,
-    const char       *key,
-    uint8_t valueSize,
-    const void       *value
-)
-{
-    uint8_t *start, *p;
-    const char *k;
-    unsigned long keysize, keyvalsize;
-
-    for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid);
-    keysize = (unsigned long)(k - key);
-    keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0);
-    if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid);
-    (void)TXTRecordRemoveValue(txtRecord, key);
-    if (txtRec->datalen + keyvalsize > txtRec->buflen)
-    {
-        unsigned char *newbuf;
-        unsigned long newlen = txtRec->datalen + keyvalsize;
-        if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid);
-        newbuf = mdns_malloc((size_t)newlen);
-        if (!newbuf) return(kDNSServiceErr_NoMemory);
-        memcpy(newbuf, txtRec->buffer, txtRec->datalen);
-        if (txtRec->malloced) mdns_free(txtRec->buffer);
-        txtRec->buffer = newbuf;
-        txtRec->buflen = (uint16_t)(newlen);
-        txtRec->malloced = 1;
-    }
-    start = txtRec->buffer + txtRec->datalen;
-    p = start + 1;
-    memcpy(p, key, keysize);
-    p += keysize;
-    if (value)
-    {
-        *p++ = '=';
-        memcpy(p, value, valueSize);
-        p += valueSize;
-    }
-    *start = (uint8_t)(p - start - 1);
-    txtRec->datalen += p - start;
-    return(kDNSServiceErr_NoError);
-}
-
-DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
-(
-    TXTRecordRef     *txtRecord,
-    const char       *key
-)
-{
-    unsigned long keylen, itemlen, remainder;
-    uint8_t *item = (uint8_t *)InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen);
-    if (!item) return(kDNSServiceErr_NoSuchKey);
-    itemlen   = (unsigned long)(1 + item[0]);
-    remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen));
-    // Use memmove because memcpy behaviour is undefined for overlapping regions
-    memmove(item, item + itemlen, remainder);
-    txtRec->datalen -= itemlen;
-    return(kDNSServiceErr_NoError);
-}
-
-uint16_t DNSSD_API TXTRecordGetLength(const TXTRecordRef *txtRecord) { return(((const TXTRecordRefRealType*)txtRecord)->datalen); }
-const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(((const TXTRecordRefRealType*)txtRecord)->buffer); }
-
-/*********************************************************************************************
-*
-*   TXT Record Parsing Functions
-*
-*********************************************************************************************/
-
-int DNSSD_API TXTRecordContainsKey
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    const char       *key
-)
-{
-    unsigned long keylen;
-    return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0);
-}
-
-const void * DNSSD_API TXTRecordGetValuePtr
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    const char       *key,
-    uint8_t          *valueLen
-)
-{
-    unsigned long keylen;
-    const uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
-    if (!item || item[0] <= keylen) return(NULL);   // If key not found, or found with no value, return NULL
-    *valueLen = (uint8_t)(item[0] - (keylen + 1));
-    return (item + 1 + keylen + 1);
-}
-
-uint16_t DNSSD_API TXTRecordGetCount
-(
-    uint16_t txtLen,
-    const void       *txtRecord
-)
-{
-    uint16_t count = 0;
-    const uint8_t *p = (const uint8_t*)txtRecord;
-    const uint8_t *e = p + txtLen;
-    while (p<e) { p += 1 + p[0]; count++; }
-    return((p>e) ? (uint16_t)0 : count);
-}
-
-DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    uint16_t itemIndex,
-    uint16_t keyBufLen,
-    char             *key,
-    uint8_t          *valueLen,
-    const void       **value
-)
-{
-    uint16_t count = 0;
-    const uint8_t *p = (const uint8_t*)txtRecord;
-    const uint8_t *e = p + txtLen;
-    while (p<e && count<itemIndex) { p += 1 + p[0]; count++; }  // Find requested item
-    if (p<e && p + 1 + p[0] <= e)   // If valid
-    {
-        const uint8_t *x = p+1;
-        unsigned long len = 0;
-        e = p + 1 + p[0];
-        while (x+len<e && x[len] != '=') len++;
-        if (len >= keyBufLen) return(kDNSServiceErr_NoMemory);
-        memcpy(key, x, len);
-        key[len] = 0;
-        if (x+len<e)        // If we found '='
-        {
-            *value = x + len + 1;
-            *valueLen = (uint8_t)(p[0] - (len + 1));
-        }
-        else
-        {
-            *value = NULL;
-            *valueLen = 0;
-        }
-        return(kDNSServiceErr_NoError);
-    }
-    return(kDNSServiceErr_Invalid);
-}
-
-/*********************************************************************************************
-*
-*   SCCS-compatible version string
-*
-*********************************************************************************************/
-
-// For convenience when using the "strings" command, this is the last thing in the file
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// The "used" variable attribute prevents a non-exported variable from being stripped, even if its visibility is hidden,
-// e.g., when compiling with -fvisibility=hidden.
-#if defined(__GNUC__)
-#define DNSSD_USED __attribute__((used))
-#else
-#define DNSSD_USED
-#endif
-
-// NOT static -- otherwise the compiler may optimize it out
-// The "@(#) " pattern is a special prefix the "what" command looks for
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdate-time"
-#endif
-const char VersionString_SCCS_libdnssd[] DNSSD_USED = "@(#) libdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
diff --git a/mDNSShared/dnssd_clientshim.c b/mDNSShared/dnssd_clientshim.c
deleted file mode 100644
index def64ff..0000000
--- a/mDNSShared/dnssd_clientshim.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright (c) 2003-2022 Apple 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
- *
- *     https://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.
-
- * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
- * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
- * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
- * function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
- * The shim is responsible for two main things:
- * - converting string parameters between C string format and native DNS format,
- * - and for allocating and freeing memory.
- */
-
-#include "dns_sd.h"             // Defines the interface to the client layer above
-#include "mDNSEmbeddedAPI.h"        // The interface we're building on top of
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "DNSCommon.h"          // For mDNSPlatformInterfaceIndexfromInterfaceID().
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-#include "dnssec.h"
-#include "dnssec_obj_context.h"
-#endif
-
-extern mDNS mDNSStorage;        // We need to pass the address of this storage to the lower-layer functions
-
-// If a target complies this file, then it should be using the shim layer.
-#define MDNS_BUILDINGSHAREDLIBRARY 1
-
-//*************************************************************************************************************
-// General Utility Functions
-
-// All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
-// Optional type-specific data follows these three fields
-// When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
-// as the DNSServiceRef for the operation
-// We stash the value in core context fields so we can get it back to recover our state in our callbacks,
-// and pass it though to the client for it to recover its state
-
-typedef struct mDNS_DirectOP_struct mDNS_DirectOP;
-typedef void mDNS_DirectOP_Dispose (mDNS_DirectOP *op);
-struct mDNS_DirectOP_struct
-{
-    mDNS_DirectOP_Dispose  *disposefn;
-};
-
-typedef struct
-{
-    mDNS_DirectOP_Dispose  *disposefn;
-    DNSServiceRegisterReply callback;
-    void                   *context;
-    mDNSBool autoname;                      // Set if this name is tied to the Computer Name
-    mDNSBool autorename;                    // Set if we just got a name conflict and now need to automatically pick a new name
-    domainlabel name;
-    domainname host;
-    ServiceRecordSet s;
-} mDNS_DirectOP_Register;
-
-typedef struct
-{
-    mDNS_DirectOP_Dispose  *disposefn;
-    DNSServiceBrowseReply callback;
-    void                   *context;
-    DNSQuestion q;
-} mDNS_DirectOP_Browse;
-
-typedef struct
-{
-    mDNS_DirectOP_Dispose  *disposefn;
-    DNSServiceResolveReply callback;
-    void                   *context;
-    const ResourceRecord   *SRV;
-    const ResourceRecord   *TXT;
-    DNSQuestion qSRV;
-    DNSQuestion qTXT;
-} mDNS_DirectOP_Resolve;
-
-typedef struct
-{
-    mDNS_DirectOP_Dispose      *disposefn;
-    DNSServiceQueryRecordReply callback;
-    void                       *context;
-    DNSQuestion q;
-} mDNS_DirectOP_QueryRecord;
-
-typedef struct
-{
-    mDNS_DirectOP_Dispose     *disposefn;
-    DNSServiceGetAddrInfoReply callback;
-    void                      *context;
-    mDNSu32                    interfaceIndex;
-    DNSQuestion                a;
-    DNSQuestion                aaaa;
-} mDNS_DirectOP_GetAddrInfo;
-
-dnssd_sock_t DNSServiceRefSockFD(DNSServiceRef sdRef)
-{
-    (void)sdRef;    // Unused
-    return(0);
-}
-
-DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef)
-{
-    (void)sdRef;    // Unused
-    return(kDNSServiceErr_NoError);
-}
-
-void DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-    mDNS_DirectOP *op = (mDNS_DirectOP *)sdRef;
-    //LogMsg("DNSServiceRefDeallocate");
-    op->disposefn(op);
-}
-
-static mDNSInterfaceID DNSServiceInterfaceIndexToID(mDNSu32 interfaceIndex, DNSServiceFlags *flags)
-{
-    // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
-    // flag set so that the resolve will run over P2P interfaces that are not yet created.
-    if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
-    {
-        LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
-        if (flags != mDNSNULL) *flags |= kDNSServiceFlagsIncludeP2P;
-        interfaceIndex = kDNSServiceInterfaceIndexAny;
-    }
-    return mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-}
-
-//*************************************************************************************************************
-// Domain Enumeration
-
-// Not yet implemented, so don't include in stub library
-// We DO include it in the actual Extension, so that if a later client compiled to use this
-// is run against this Extension, it will get a reasonable error code instead of just
-// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
-#if MDNS_BUILDINGSHAREDLIBRARY
-DNSServiceErrorType DNSServiceEnumerateDomains
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceDomainEnumReply callback,
-    void                                *context  /* may be NULL */
-)
-{
-    (void)sdRef;            // Unused
-    (void)flags;            // Unused
-    (void)interfaceIndex;   // Unused
-    (void)callback;         // Unused
-    (void)context;          // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-#endif
-
-//*************************************************************************************************************
-// Register Service
-
-mDNSlocal void FreeDNSServiceRegistration(mDNS_DirectOP_Register *x)
-{
-    while (x->s.Extras)
-    {
-        ExtraResourceRecord *extras = x->s.Extras;
-        x->s.Extras = x->s.Extras->next;
-        if (extras->r.resrec.rdata != &extras->r.rdatastorage)
-            mDNSPlatformMemFree(extras->r.resrec.rdata);
-        mDNSPlatformMemFree(extras);
-    }
-
-    if (x->s.RR_TXT.resrec.rdata != &x->s.RR_TXT.rdatastorage)
-        mDNSPlatformMemFree(x->s.RR_TXT.resrec.rdata);
-
-    if (x->s.SubTypes) mDNSPlatformMemFree(x->s.SubTypes);
-
-    mDNSPlatformMemFree(x);
-}
-
-static void DNSServiceRegisterDispose(mDNS_DirectOP *op)
-{
-    mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)op;
-    x->autorename = mDNSfalse;
-    // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
-    // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
-    // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
-    // the list, so we should go ahead and free the memory right now
-    if (mDNS_DeregisterService(&mDNSStorage, &x->s) != mStatus_NoError)
-        FreeDNSServiceRegistration(x);
-}
-
-mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
-{
-    mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)sr->ServiceContext;
-
-    domainlabel name;
-    domainname type, dom;
-    char namestr[MAX_DOMAIN_LABEL+1];       // Unescaped name: up to 63 bytes plus C-string terminating NULL.
-    char typestr[MAX_ESCAPED_DOMAIN_NAME];
-    char domstr [MAX_ESCAPED_DOMAIN_NAME];
-    if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
-    if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
-    if (!ConvertDomainNameToCString(&type, typestr)) return;
-    if (!ConvertDomainNameToCString(&dom, domstr)) return;
-
-    if (result == mStatus_NoError)
-    {
-        if (x->callback)
-            x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
-    }
-    else if (result == mStatus_NameConflict)
-    {
-        if (x->autoname) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
-        else if (x->callback)
-            x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
-    }
-    else if (result == mStatus_MemFree)
-    {
-        if (x->autorename)
-        {
-            x->autorename = mDNSfalse;
-            x->name = mDNSStorage.nicelabel;
-            mDNS_RenameAndReregisterService(m, &x->s, &x->name);
-        }
-        else
-            FreeDNSServiceRegistration(x);
-    }
-}
-
-DNSServiceErrorType DNSServiceRegister
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,         /* may be NULL */
-    const char                          *regtype,
-    const char                          *domain,       /* may be NULL */
-    const char                          *host,         /* may be NULL */
-    uint16_t notAnIntPort,
-    uint16_t txtLen,
-    const void                          *txtRecord,    /* may be NULL */
-    DNSServiceRegisterReply callback,                  /* may be NULL */
-    void                                *context       /* may be NULL */
-)
-{
-    mStatus err = mStatus_NoError;
-    const char *errormsg = "Unknown";
-    domainlabel n;
-    domainname t, d, h, srv;
-    mDNSIPPort port;
-    unsigned int size = sizeof(RDataBody);
-    AuthRecord *SubTypes = mDNSNULL;
-    mDNSu32 NumSubTypes = 0;
-    mDNS_DirectOP_Register *x;
-    (void)flags;            // Unused
-    (void)interfaceIndex;   // Unused
-
-    // Check parameters
-    if (!name) name = "";
-    if (!name[0]) n = mDNSStorage.nicelabel;
-    else if (!MakeDomainLabelFromLiteralString(&n, name))                              { errormsg = "Bad Instance Name"; goto badparam; }
-    if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype))        { errormsg = "Bad Service Type";  goto badparam; }
-    if (!MakeDomainNameFromDNSNameString(&d, (domain && *domain) ? domain : "local.")) { errormsg = "Bad Domain";        goto badparam; }
-    if (!MakeDomainNameFromDNSNameString(&h, (host   && *host  ) ? host   : ""))       { errormsg = "Bad Target Host";   goto badparam; }
-    if (!ConstructServiceName(&srv, &n, &t, &d))                                       { errormsg = "Bad Name";          goto badparam; }
-    port.NotAnInteger = notAnIntPort;
-
-    // Allocate memory, and handle failure
-    if (size < txtLen)
-        size = txtLen;
-    x = (mDNS_DirectOP_Register *) mDNSPlatformMemAllocateClear(sizeof(*x) - sizeof(RDataBody) + size);
-    if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
-    // Set up object
-    x->disposefn = DNSServiceRegisterDispose;
-    x->callback  = callback;
-    x->context   = context;
-    x->autoname = (!name[0]);
-    x->autorename = mDNSfalse;
-    x->name = n;
-    x->host = h;
-
-    // Do the operation
-    err = mDNS_RegisterService(&mDNSStorage, &x->s,
-                               &x->name, &t, &d, // Name, type, domain
-                               &x->host, port, // Host and port
-                               mDNSNULL,
-                               txtRecord, txtLen, // TXT data, length
-                               SubTypes, NumSubTypes, // Subtypes
-                               mDNSInterface_Any, // Interface ID
-                               RegCallback, x, 0); // Callback, context, flags
-    if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_RegisterService"; goto fail; }
-
-    // Succeeded: Wrap up and return
-    *sdRef = (DNSServiceRef)x;
-    return(mStatus_NoError);
-
-badparam:
-    err = mStatus_BadParamErr;
-fail:
-    LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
-    return(err);
-}
-
-//*************************************************************************************************************
-// Add / Update / Remove records from existing Registration
-
-// Not yet implemented, so don't include in stub library
-// We DO include it in the actual Extension, so that if a later client compiled to use this
-// is run against this Extension, it will get a reasonable error code instead of just
-// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
-#if MDNS_BUILDINGSHAREDLIBRARY
-DNSServiceErrorType DNSServiceAddRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rrtype,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl
-)
-{
-    (void)sdRef;        // Unused
-    (void)RecordRef;    // Unused
-    (void)flags;        // Unused
-    (void)rrtype;       // Unused
-    (void)rdlen;        // Unused
-    (void)rdata;        // Unused
-    (void)ttl;          // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-
-DNSServiceErrorType DNSServiceUpdateRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,                            /* may be NULL */
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl
-)
-{
-    (void)sdRef;        // Unused
-    (void)RecordRef;    // Unused
-    (void)flags;        // Unused
-    (void)rdlen;        // Unused
-    (void)rdata;        // Unused
-    (void)ttl;          // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-
-DNSServiceErrorType DNSServiceRemoveRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags
-)
-{
-    (void)sdRef;        // Unused
-    (void)RecordRef;    // Unused
-    (void)flags;        // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-#endif
-
-//*************************************************************************************************************
-// Browse for services
-
-static void DNSServiceBrowseDispose(mDNS_DirectOP *op)
-{
-    mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)op;
-    //LogMsg("DNSServiceBrowseDispose");
-    mDNS_StopBrowse(&mDNSStorage, &x->q);
-    mDNSPlatformMemFree(x);
-}
-
-mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
-    domainlabel name;
-    domainname type, domain;
-    char cname[MAX_DOMAIN_LABEL+1];         // Unescaped name: up to 63 bytes plus C-string terminating NULL.
-    char ctype[MAX_ESCAPED_DOMAIN_NAME];
-    char cdom [MAX_ESCAPED_DOMAIN_NAME];
-    mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)question->QuestionContext;
-    (void)m;        // Unused
-
-    if (answer->rrtype != kDNSType_PTR)
-    { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; }
-
-    if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
-    {
-        LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
-               answer->name->c, answer->rdata->u.name.c);
-        return;
-    }
-
-    ConvertDomainLabelToCString_unescaped(&name, cname);
-    ConvertDomainNameToCString(&type, ctype);
-    ConvertDomainNameToCString(&domain, cdom);
-    if (x->callback)
-        x->callback((DNSServiceRef)x, flags, 0, 0, cname, ctype, cdom, x->context);
-}
-
-DNSServiceErrorType DNSServiceBrowse
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *regtype,
-    const char                          *domain,    /* may be NULL */
-    DNSServiceBrowseReply callback,
-    void                                *context    /* may be NULL */
-)
-{
-    mStatus err = mStatus_NoError;
-    const char *errormsg = "Unknown";
-    domainname t, d;
-    mDNS_DirectOP_Browse *x;
-    (void)flags;            // Unused
-    (void)interfaceIndex;   // Unused
-
-    // Check parameters
-    if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype))      { errormsg = "Illegal regtype"; goto badparam; }
-    if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain";  goto badparam; }
-
-    // Allocate memory, and handle failure
-    x = (mDNS_DirectOP_Browse *) mDNSPlatformMemAllocateClear(sizeof(*x));
-    if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
-    // Set up object
-    x->disposefn = DNSServiceBrowseDispose;
-    x->callback  = callback;
-    x->context   = context;
-    x->q.QuestionContext = x;
-
-    // Do the operation
-    err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, flags, (flags & kDNSServiceFlagsForceMulticast) != 0, (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, x);
-    if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; }
-
-    // Succeeded: Wrap up and return
-    *sdRef = (DNSServiceRef)x;
-    return(mStatus_NoError);
-
-badparam:
-    err = mStatus_BadParamErr;
-fail:
-    LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
-    return(err);
-}
-
-//*************************************************************************************************************
-// Resolve Service Info
-
-static void DNSServiceResolveDispose(mDNS_DirectOP *op)
-{
-    mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)op;
-    if (x->qSRV.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qSRV);
-    if (x->qTXT.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qTXT);
-    mDNSPlatformMemFree(x);
-}
-
-mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
-    (void)m;    // Unused
-    if (!AddRecord)
-    {
-        if (answer->rrtype == kDNSType_SRV && x->SRV == answer) x->SRV = mDNSNULL;
-        if (answer->rrtype == kDNSType_TXT && x->TXT == answer) x->TXT = mDNSNULL;
-    }
-    else
-    {
-        if (answer->rrtype == kDNSType_SRV) x->SRV = answer;
-        if (answer->rrtype == kDNSType_TXT) x->TXT = answer;
-        if (x->SRV && x->TXT && x->callback)
-        {
-            char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
-            ConvertDomainNameToCString(answer->name, fullname);
-            ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
-            x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
-                        x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (unsigned char*)x->TXT->rdata->u.txt.c, x->context);
-        }
-    }
-}
-
-DNSServiceErrorType DNSServiceResolve
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    DNSServiceResolveReply callback,
-    void                                *context  /* may be NULL */
-)
-{
-    mStatus err = mStatus_NoError;
-    const char *errormsg = "Unknown";
-    domainlabel n;
-    domainname t, d, srv;
-    mDNS_DirectOP_Resolve *x;
-
-    // Check parameters
-    if (!name[0]    || !MakeDomainLabelFromLiteralString(&n, name  )) { errormsg = "Bad Instance Name"; goto badparam; }
-    if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type";  goto badparam; }
-    if (!domain[0]  || !MakeDomainNameFromDNSNameString(&d, domain )) { errormsg = "Bad Domain";        goto badparam; }
-    if (!ConstructServiceName(&srv, &n, &t, &d))                      { errormsg = "Bad Name";          goto badparam; }
-
-    // Allocate memory, and handle failure
-    x = (mDNS_DirectOP_Resolve *) mDNSPlatformMemAllocateClear(sizeof(*x));
-    if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
-    // Set up object
-    x->disposefn = DNSServiceResolveDispose;
-    x->callback  = callback;
-    x->context   = context;
-    x->SRV       = mDNSNULL;
-    x->TXT       = mDNSNULL;
-
-    x->qSRV.ThisQInterval       = -1;       // So that DNSServiceResolveDispose() knows whether to cancel this question
-    x->qSRV.InterfaceID         = DNSServiceInterfaceIndexToID(interfaceIndex, &flags);
-    x->qSRV.flags               = flags;
-    AssignDomainName(&x->qSRV.qname, &srv);
-    x->qSRV.qtype               = kDNSType_SRV;
-    x->qSRV.qclass              = kDNSClass_IN;
-    x->qSRV.LongLived           = mDNSfalse;
-    x->qSRV.ExpectUnique        = mDNStrue;
-    x->qSRV.ForceMCast          = mDNSfalse;
-    x->qSRV.ReturnIntermed      = mDNSfalse;
-    x->qSRV.SuppressUnusable    = mDNSfalse;
-    x->qSRV.AppendSearchDomains = 0;
-    x->qSRV.TimeoutQuestion     = 0;
-    x->qSRV.WakeOnResolve       = 0;
-    x->qSRV.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    x->qSRV.ProxyQuestion       = 0;
-    x->qSRV.pid                 = mDNSPlatformGetPID();
-    x->qSRV.QuestionCallback    = FoundServiceInfo;
-    x->qSRV.QuestionContext     = x;
-
-    x->qTXT.ThisQInterval       = -1;       // So that DNSServiceResolveDispose() knows whether to cancel this question
-    x->qTXT.InterfaceID         = DNSServiceInterfaceIndexToID(interfaceIndex, mDNSNULL);
-    x->qTXT.flags               = flags;
-    AssignDomainName(&x->qTXT.qname, &srv);
-    x->qTXT.qtype               = kDNSType_TXT;
-    x->qTXT.qclass              = kDNSClass_IN;
-    x->qTXT.LongLived           = mDNSfalse;
-    x->qTXT.ExpectUnique        = mDNStrue;
-    x->qTXT.ForceMCast          = mDNSfalse;
-    x->qTXT.ReturnIntermed      = mDNSfalse;
-    x->qTXT.SuppressUnusable    = mDNSfalse;
-    x->qTXT.AppendSearchDomains = 0;
-    x->qTXT.TimeoutQuestion     = 0;
-    x->qTXT.WakeOnResolve       = 0;
-    x->qTXT.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    x->qTXT.ProxyQuestion       = 0;
-    x->qTXT.pid                 = mDNSPlatformGetPID();
-    x->qTXT.QuestionCallback    = FoundServiceInfo;
-    x->qTXT.QuestionContext     = x;
-
-    err = mDNS_StartQuery(&mDNSStorage, &x->qSRV);
-    if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qSRV"; goto fail; }
-    err = mDNS_StartQuery(&mDNSStorage, &x->qTXT);
-    if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qTXT"; goto fail; }
-
-    // Succeeded: Wrap up and return
-    *sdRef = (DNSServiceRef)x;
-    return(mStatus_NoError);
-
-badparam:
-    err = mStatus_BadParamErr;
-fail:
-    LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name, regtype, domain, errormsg, err);
-    return(err);
-}
-
-//*************************************************************************************************************
-// Connection-oriented calls
-
-// Not yet implemented, so don't include in stub library
-// We DO include it in the actual Extension, so that if a later client compiled to use this
-// is run against this Extension, it will get a reasonable error code instead of just
-// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
-#if MDNS_BUILDINGSHAREDLIBRARY
-DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef)
-{
-    (void)sdRef;    // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-
-DNSServiceErrorType DNSServiceRegisterRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl,
-    DNSServiceRegisterRecordReply callback,
-    void                                *context    /* may be NULL */
-)
-{
-    (void)sdRef;            // Unused
-    (void)RecordRef;        // Unused
-    (void)flags;            // Unused
-    (void)interfaceIndex;   // Unused
-    (void)fullname;         // Unused
-    (void)rrtype;           // Unused
-    (void)rrclass;          // Unused
-    (void)rdlen;            // Unused
-    (void)rdata;            // Unused
-    (void)ttl;              // Unused
-    (void)callback;         // Unused
-    (void)context;          // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-#endif
-
-//*************************************************************************************************************
-// DNSServiceQueryRecord
-
-static void DNSServiceQueryRecordDispose(mDNS_DirectOP *op)
-{
-    mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)op;
-    if (x->q.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->q);
-    mDNSPlatformMemFree(x);
-}
-
-mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
-    char fullname[MAX_ESCAPED_DOMAIN_NAME];
-    (void)m;    // Unused
-    ConvertDomainNameToCString(answer->name, fullname);
-
-    DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    if (dns_question_is_dnssec_requestor(question))
-    {
-        flags |= dns_service_flags_init_with_dnssec_result(question, answer);
-    }
-#endif
-
-    x->callback((DNSServiceRef)x, flags, 0, kDNSServiceErr_NoError, fullname, answer->rrtype, answer->rrclass,
-                answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
-}
-
-DNSServiceErrorType DNSServiceQueryRecord
-(
-    DNSServiceRef             *sdRef,
-    DNSServiceFlags            flags,
-    uint32_t                   interfaceIndex,
-    const char                *fullname,
-    uint16_t                   rrtype,
-    uint16_t                   rrclass,
-    DNSServiceQueryRecordReply callback,
-    void                      *context  /* may be NULL */
-)
-{
-    mStatus err = mStatus_NoError;
-    const char *errormsg = "Unknown";
-    mDNS_DirectOP_QueryRecord *x;
-
-    // Allocate memory, and handle failure
-    x = (mDNS_DirectOP_QueryRecord *) mDNSPlatformMemAllocateClear(sizeof(*x));
-    if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
-    // Set up object
-    x->disposefn = DNSServiceQueryRecordDispose;
-    x->callback  = callback;
-    x->context   = context;
-
-    x->q.ThisQInterval        = -1;      // So that DNSServiceResolveDispose() knows whether to cancel this question
-    x->q.InterfaceID          = DNSServiceInterfaceIndexToID(interfaceIndex, &flags);
-    x->q.flags                = flags;
-    MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
-    x->q.qtype                = rrtype;
-    x->q.qclass               = rrclass;
-    x->q.LongLived            = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
-    x->q.ExpectUnique         = mDNSfalse;
-    x->q.ForceMCast           = (flags & kDNSServiceFlagsForceMulticast) != 0;
-    x->q.ReturnIntermed       = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
-    x->q.SuppressUnusable     = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    x->q.enableDNSSEC         = dns_service_flags_enables_dnssec(flags);
-#endif
-    x->q.AppendSearchDomains  = 0;
-    x->q.TimeoutQuestion      = 0;
-    x->q.WakeOnResolve        = 0;
-    x->q.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    x->q.ProxyQuestion        = 0;
-    x->q.pid                  = mDNSPlatformGetPID();
-    x->q.QuestionCallback     = DNSServiceQueryRecordResponse;
-    x->q.QuestionContext      = x;
-
-    err = mDNS_StartQuery(&mDNSStorage, &x->q);
-    if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
-
-    // Succeeded: Wrap up and return
-    *sdRef = (DNSServiceRef)x;
-    return(mStatus_NoError);
-
-fail:
-    LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
-    return(err);
-}
-
-//*************************************************************************************************************
-// DNSServiceGetAddrInfo
-//
-
-static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
-{
-    mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
-    if (x->a.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->a);
-    if (x->aaaa.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->aaaa);
-    mDNSPlatformMemFree(x);
-}
-
-mDNSlocal void DNSServiceGetAddrInfoResponse(mDNS *const m, DNSQuestion *question,
-                                             const ResourceRecord *const answer, QC_result addRecord)
-{
-    mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)question->QuestionContext;
-    char fullname[MAX_ESCAPED_DOMAIN_NAME];
-
-    struct sockaddr_storage sas; // NOLINT(misc-uninitialized-record-variable): Initialized below by mDNSPlatformMemZero.
-    struct sockaddr_in *sin = (struct sockaddr_in *)&sas;
-    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sas;
-    void *sa_ap = mDNSNULL;
-    int sa_as = 0;
-    mStatus err = mStatus_NoError;
-
-    mDNSPlatformMemZero(&sas, sizeof sas);
-
-    ConvertDomainNameToCString(answer->name, fullname);
-
-    if (addRecord == QC_suppressed || answer->RecordType == kDNSRecordTypePacketNegative)
-    {
-        err = mStatus_NoSuchRecord;
-    }
-
-    mDNS_Lock(m);
-    const mDNSu32 interfaceIndex = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue);
-    mDNS_Unlock(m);
-
-    // There are three checks here for bad data: class != IN, RRTYPE not in {A,AAAA} and wrong length.
-    // None of these should be possible, because the cache code wouldn't cache malformed data and wouldn't
-    // return records we didn't ask for, but it doesn't hurt to check.
-    if (answer->rrclass != kDNSServiceClass_IN)
-    {
-        LogMsg("DNSServiceGetAddrInfoResponse: response of class %d received, which is bogus", answer->rrclass);
-    totally_invalid:
-        if (x->a.ThisQInterval >= 0)
-        {
-            sin->sin_family = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-            sin->sin_len = sizeof *sin;
-#endif
-            x->callback((DNSServiceRef)x, 0, interfaceIndex, kDNSServiceErr_Invalid, fullname,
-                        (const struct sockaddr *)&sas, 0, x->context);
-        }
-        if (x->aaaa.ThisQInterval >= 0)
-        {
-            sin6->sin6_family = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-            sin6->sin6_len = sizeof *sin6;
-#endif
-            x->callback((DNSServiceRef)x, 0, interfaceIndex, kDNSServiceErr_Invalid, fullname,
-                        (const struct sockaddr *)&sas, 0, x->context);
-        }
-        return;
-    }
-    else if (answer->rrtype == kDNSServiceType_A)
-    {
-        sin->sin_family = AF_INET;
-#ifndef NOT_HAVE_SA_LEN
-        sin->sin_len = sizeof *sin;
-#endif
-        sa_ap = &sin->sin_addr;
-        sa_as = sizeof sin->sin_addr.s_addr;
-    }
-    else if (answer->rrtype == kDNSServiceType_AAAA)
-    {
-        sin6->sin6_family = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-        sin6->sin6_len = sizeof *sin6;
-#endif
-        sa_ap = &sin6->sin6_addr;
-        sa_as = sizeof sin6->sin6_addr.s6_addr;
-    }
-    else
-    {
-        LogMsg("DNSServiceGetAddrInfoResponse: response of type %d received, which is bogus", answer->rrtype);
-        goto totally_invalid;
-    }
-
-    if (err == kDNSServiceErr_NoError && sa_ap != mDNSNULL)
-    {
-        if (err == mStatus_NoError)
-        {
-            if (answer->rdlength == sa_as)
-            {
-                mDNSPlatformMemCopy(sa_ap, answer->rdata->u.data, answer->rdlength);
-            }
-            else
-            {
-                LogMsg("DNSServiceGetAddrInfoResponse: %s rrtype with length %d received",
-                       answer->rrtype == kDNSServiceType_A ? "A" : "AAAA", answer->rdlength);
-                goto totally_invalid;
-            }
-        }
-    }
-
-    x->callback((DNSServiceRef)x, addRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, interfaceIndex, err, fullname,
-                (const struct sockaddr *)&sas, answer->rroriginalttl, x->context);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
-    DNSServiceRef             *outRef,
-    DNSServiceFlags            inFlags,
-    uint32_t                   inInterfaceIndex,
-    DNSServiceProtocol         inProtocol,
-    const char                *inHostName,
-    DNSServiceGetAddrInfoReply inCallback,
-    void                      *inContext )
-{
-    const char                *errormsg = "Unknown";
-    DNSServiceErrorType        err;
-    mDNS_DirectOP_GetAddrInfo *x;
-
-    // Allocate memory, and handle failure
-    x = (mDNS_DirectOP_GetAddrInfo *) mDNSPlatformMemAllocateClear(sizeof(*x));
-    if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
-    // Set up object
-    x->disposefn      = DNSServiceGetAddrInfoDispose;
-    x->callback       = inCallback;
-    x->context        = inContext;
-    x->interfaceIndex = inInterfaceIndex;
-
-    // Validate and default the protocols.
-    if ((inProtocol & (uint32_t)(~(kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6))) != 0)
-    {
-        err = mStatus_BadParamErr;
-        errormsg = "Unsupported protocol";
-        goto fail;
-    }
-    // In theory this API checks to see if we have a routable IPv6 address, but
-    if ((inProtocol & (kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6)) == 0)
-    {
-        inProtocol = kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6;
-        inFlags |= kDNSServiceFlagsSuppressUnusable;
-    }
-
-    x->a.ThisQInterval        = -1;      // So we know whether to cancel this question
-    x->a.InterfaceID          = DNSServiceInterfaceIndexToID(inInterfaceIndex, &inFlags);
-    x->a.flags                = inFlags;
-    MakeDomainNameFromDNSNameString(&x->a.qname, inHostName);
-    x->a.qtype                = kDNSType_A;
-    x->a.qclass               = kDNSClass_IN;
-    x->a.LongLived            = (inFlags & kDNSServiceFlagsLongLivedQuery) != 0;
-    x->a.ExpectUnique         = mDNSfalse;
-    x->a.ForceMCast           = (inFlags & kDNSServiceFlagsForceMulticast) != 0;
-    x->a.ReturnIntermed       = (inFlags & kDNSServiceFlagsReturnIntermediates) != 0;
-    x->a.SuppressUnusable     = (inFlags & kDNSServiceFlagsSuppressUnusable) != 0;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    x->a.enableDNSSEC         = dns_service_flags_enables_dnssec(inFlags);
-#endif
-    x->a.AppendSearchDomains  = 0;
-    x->a.TimeoutQuestion      = 0;
-    x->a.WakeOnResolve        = 0;
-    x->a.UseBackgroundTraffic = (inFlags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    x->a.ProxyQuestion        = 0;
-    x->a.pid                  = mDNSPlatformGetPID();
-    x->a.QuestionCallback     = DNSServiceGetAddrInfoResponse;
-    x->a.QuestionContext      = x;
-
-    x->aaaa = x->a;
-    x->aaaa.qtype = kDNSType_AAAA;
-
-    if (inProtocol & kDNSServiceProtocol_IPv4)
-    {
-        err = mDNS_StartQuery(&mDNSStorage, &x->a);
-        if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
-    }
-    if (inProtocol & kDNSServiceProtocol_IPv6)
-    {
-        err = mDNS_StartQuery(&mDNSStorage, &x->aaaa);
-        if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
-    }
-
-    *outRef = (DNSServiceRef)x;
-    return(mStatus_NoError);
-
-fail:
-    LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err);
-    return(err);
-}
-
-//*************************************************************************************************************
-// DNSServiceReconfirmRecord
-
-// Not yet implemented, so don't include in stub library
-// We DO include it in the actual Extension, so that if a later client compiled to use this
-// is run against this Extension, it will get a reasonable error code instead of just
-// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
-#if MDNS_BUILDINGSHAREDLIBRARY
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-(
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                         *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                         *rdata
-)
-{
-    (void)flags;            // Unused
-    (void)interfaceIndex;   // Unused
-    (void)fullname;         // Unused
-    (void)rrtype;           // Unused
-    (void)rrclass;          // Unused
-    (void)rdlen;            // Unused
-    (void)rdata;            // Unused
-    return(kDNSServiceErr_Unsupported);
-}
-
-#endif // MDNS_BUILDINGSHAREDLIBRARY
-
-// Local Variables:
-// mode: C
-// tab-width: 4
-// c-file-style: "bsd"
-// c-basic-offset: 4
-// fill-column: 108
-// indent-tabs-mode: nil
-// End:
diff --git a/mDNSShared/dnssd_clientstub.c b/mDNSShared/dnssd_clientstub.c
deleted file mode 100644
index 81186b4..0000000
--- a/mDNSShared/dnssd_clientstub.c
+++ /dev/null
@@ -1,2918 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dnssd_clientstub.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "dnssd_ipc.h"
-
-#include "mdns_strict.h"
-
-#ifndef DEBUG_64BIT_SCM_RIGHTS
-#define DEBUG_64BIT_SCM_RIGHTS 0
-#endif
-
-#if defined(_WIN32)
-
-    #define _SSIZE_T
-    #include <CommonServices.h>
-    #include <DebugServices.h>
-    #include <winsock2.h>
-    #include <ws2tcpip.h>
-    #include <windows.h>
-    #include <stdarg.h>
-    #include <stdio.h>
-
-    #define sockaddr_mdns sockaddr_in
-    #define AF_MDNS AF_INET
-
-// Disable warning: "'type cast' : from data pointer 'void *' to function pointer"
-    #pragma warning(disable:4055)
-
-// Disable warning: "nonstandard extension, function/data pointer conversion in expression"
-    #pragma warning(disable:4152)
-
-extern BOOL IsSystemServiceDisabled();
-
-    #define sleep(X) Sleep((X) * 1000)
-
-static int g_initWinsock = 0;
-    #define LOG_WARNING kDebugLevelWarning
-    #define LOG_INFO kDebugLevelInfo
-static void syslog( int priority, const char * message, ...)
-{
-    va_list args;
-    int len;
-    char * buffer;
-    DWORD err = WSAGetLastError();
-    (void) priority;
-    va_start( args, message );
-    len = _vscprintf( message, args ) + 1;
-    buffer = mdns_malloc( len * sizeof(char) );
-    if ( buffer ) { vsnprintf( buffer, len, message, args ); OutputDebugString( buffer ); mdns_free( buffer ); }
-    WSASetLastError( err );
-}
-#else
-
-    #include <fcntl.h>      // For O_RDWR etc.
-    #include <sys/time.h>
-    #include <sys/socket.h>
-    #include <syslog.h>
-    #include <sys/uio.h>
-
-#endif
-
-#if defined(_WIN32)
-// <rdar://problem/4096913> Specifies how many times we'll try and connect to the server.
-
-#define DNSSD_CLIENT_MAXTRIES 4
-#endif // _WIN32
-
-// Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp)
-//#define USE_NAMED_ERROR_RETURN_SOCKET 1
-
-// If the UDS client has not received a response from the daemon in 60 secs, it is unlikely to get one
-// Note: Timeout of 3 secs should be sufficient in normal scenarios, but 60 secs is chosen as a safeguard since
-// some clients may come up before mDNSResponder itself after a BOOT and on rare ocassions IOPM/Keychain/D2D calls
-// in mDNSResponder's INIT may take a much longer time to return
-#define DNSSD_CLIENT_TIMEOUT 60
-
-#ifdef USE_NAMED_ERROR_RETURN_SOCKET
-#ifndef CTL_PATH_PREFIX
-#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
-#endif
-#endif
-
-typedef struct
-{
-    ipc_msg_hdr ipc_hdr;
-    DNSServiceFlags cb_flags;
-    uint32_t cb_interface;
-    DNSServiceErrorType cb_err;
-} CallbackHeader;
-
-typedef struct _DNSServiceRef_t DNSServiceOp;
-typedef struct _DNSRecordRef_t DNSRecord;
-
-#if !defined(_WIN32)
-typedef struct
-{
-    void             *AppCallback;      // Client callback function and context
-    void             *AppContext;
-} SleepKAContext;
-#endif
-
-// client stub callback to process message from server and deliver results to client application
-typedef void (*ProcessReplyFn)(DNSServiceOp *sdr, const CallbackHeader *cbh, const uint8_t *msg, const uint8_t *end);
-
-#define ValidatorBits 0x12345678
-#define DNSServiceRefValid(X) (dnssd_SocketValid((X)->sockfd) && (((X)->sockfd ^ (X)->validator) == ValidatorBits))
-
-// When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
-// For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
-// For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
-//
-// _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the
-// DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible.
-struct _DNSServiceRef_t
-{
-    DNSServiceOp     *next;             // When sharing a connection, this is the next subordinate DNSServiceRef in
-                                        // the list. The connection being shared is the first in the list.
-    DNSServiceOp     *primary;          // When sharing a connection, the primary pointer of each subordinate
-                                        // DNSServiceRef points to the head of the list. If primary is null, and next is
-                                        // null, this is not a shared connection. If primary is null and next is
-                                        // non-null, this is the primary DNSServiceRef of the shared connection. If
-                                        // primary is non-null, this is a subordinate DNSServiceRef for the connection
-                                        // that is managed by the DNSServiceRef pointed to by primary.
-    dnssd_sock_t sockfd;                // Connected socket between client and daemon
-    dnssd_sock_t validator;             // Used to detect memory corruption, double disposals, etc.
-    client_context_t uid;               // For shared connection requests, each subordinate DNSServiceRef has its own ID,
-                                        // unique within the scope of the same shared parent DNSServiceRef. On the
-                                        // primary DNSServiceRef, uid matches the uid of the most recently allocated
-                                        // subordinate DNSServiceRef. Each time a new subordinate DNSServiceRef is
-                                        // allocated, uid on the primary is incremented by one and copied to the
-                                        // subordinate.
-    uint32_t op;                        // request_op_t or reply_op_t
-    uint32_t max_index;                 // Largest assigned record index - 0 if no additional records registered
-    uint32_t logcounter;                // Counter used to control number of syslog messages we write
-    int              *moreptr;          // Set while DNSServiceProcessResult working on this particular DNSServiceRef
-    ProcessReplyFn ProcessReply;        // Function pointer to the code to handle received messages
-    void             *AppCallback;      // Client callback function and context
-    void             *AppContext;
-    DNSRecord        *rec;
-#if _DNS_SD_LIBDISPATCH
-    dispatch_source_t disp_source;
-    dispatch_queue_t disp_queue;
-#endif
-    void             *kacontext;
-};
-
-// Any DNSServiceRef can have a list of one or more DNSRecordRefs. These DNSRecordRefs either come from
-// DNSServiceRegisterRecord calls on a DNSServiceRef allocated using DNSServiceCreateConnection, or else
-// they come from DNSServiceAddRecord calls on a DNSServiceRef allocated using DNSServiceRegisterRecord.
-// A connection created using DNSServiceCreateConnection can also be used as a shared connection for registering
-// services using DNSServiceRegister. Or a connection can have both records registered with
-// DNSServiceRegisterRecord and services registered with DNSServiceRegister. A shared connection can also have
-// browses, resolves, and so on, each of which will have a subordinate DNSServiceRef.
-// This data structure is mirrored in the server daemon. To summarize:
-// For any given DNSServiceRef created by DNSServiceCreateConnection,
-//   - there may be zero or more subordinate DNSServiceRefs.
-//   - there may be zero or more DNSRecordRefs
-// Any DNSServiceRef created by DNSServiceRegister may
-//   - be a subordinate DNSServiceRef of a DNSServiceRef created by DNSServiceCreateConnection, or not
-//   - be a standalone DNSServiceRef with its own connection
-//   - may have zero or more records registered with DNSServiceAddRecord
-//   - may not have any records registered with DNSServiceRegisterRecord
-//   - may not be used as a shared connection
-
-struct _DNSRecordRef_t
-{
-    DNSRecord       *recnext;
-    void *AppContext;
-    DNSServiceRegisterRecordReply AppCallback;
-    DNSRecordRef recref;
-    uint32_t record_index;  // index is unique within the set of DNSRecordRefs owned by its parent (sdr).
-    client_context_t uid;   // a copy of sdr->uid made when the recordref is created. if sdr is a shared
-                            // connection, this may not match sdr->uid later on. If it is a subordinate
-                            // connection or a non-shared connection, then sdr->uid should always match
-                            // uid.
-    DNSServiceOp *sdr;
-    ipc_msg_hdr *msg;
-};
-
-struct DNSServiceAttribute_s {
-    DNSServiceAAAAPolicy aaaa_policy;
-    uint32_t timestamp;    //Timestamp in seconds since epoch time to indicate when the service/record is registered.
-    bool timestamp_is_set;
-};
-
-const DNSServiceAttribute kDNSServiceAttributeAAAAFallback = {
-    .aaaa_policy = kDNSServiceAAAAPolicyFallback
-};
-
-
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecordWithAttribute
-(
-    DNSServiceRef * const sdRef,
-    const DNSServiceFlags flags,
-    const uint32_t ifindex,
-    const char * const name,
-    const uint16_t rrtype,
-    const uint16_t rrclass,
-    const DNSServiceAttribute * const attr,
-    const DNSServiceQueryRecordReply callback,
-    void * const context
-)
-{
-    return DNSServiceQueryRecordInternal(sdRef, flags, ifindex, name, rrtype, rrclass, attr, callback, context);
-}
-
-// send out all the linked requets in sdr->rec
-DNSServiceErrorType DNSSD_API DNSServiceSendQueuedRequests
-(
-    DNSServiceRef sdr
-)
-{
-    return DNSServiceSendQueuedRequestsInternal(sdr);
-}
-
-DNSServiceAttributeRef DNSSD_API DNSServiceAttributeCreate
-(
-    void
-)
-{
-    DNSServiceAttributeRef attr = (DNSServiceAttributeRef)mdns_calloc(1, sizeof(*attr));
-    return attr;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceAttributeSetAAAAPolicy
-(
-    const DNSServiceAttributeRef attr,
-    const DNSServiceAAAAPolicy policy
-)
-{
-    attr->aaaa_policy = policy;
-    return kDNSServiceErr_NoError;
-}
-
-
-DNSServiceErrorType DNSSD_API DNSServiceAttributeSetTimestamp
-(
-    const DNSServiceAttributeRef attr,
-    const uint32_t timestamp
-)
-{
-    attr->timestamp_is_set = true;
-    attr->timestamp = timestamp;
-    return kDNSServiceErr_NoError;
-}
-
-void DNSSD_API DNSServiceAttributeDeallocate(DNSServiceAttributeRef attr)
-{
-    mdns_free(attr);
-}
-
-size_t
-get_required_tlv_length_for_service_attr(const DNSServiceAttribute * const attr)
-{
-    // Length for IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY and IPC_TLV_TYPE_SERVICE_ATTR_FAILOVER_POLICY.
-    size_t len = 2 * get_required_tlv_uint32_length();
-
-    // IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP.
-    if (attr->timestamp_is_set)
-    {
-        len += get_required_tlv_uint32_length();
-    }
-    return len;
-}
-
-void
-put_tlvs_for_service_attr(const DNSServiceAttribute * const attr, ipc_msg_hdr * const hdr, uint8_t ** const ptr,
-                          const uint8_t * const limit)
-{
-    put_tlv_uint32(IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY, attr->aaaa_policy, ptr, limit);
-    if (attr->timestamp_is_set)
-    {
-        put_tlv_uint32(IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP, attr->timestamp, ptr, limit);
-    }
-    hdr->ipc_flags |= IPC_FLAGS_TRAILING_TLVS;
-}
-
-static bool _should_return_noauth_error(void)
-{
-    static bool s_should = false;
-    return s_should;
-}
-
-#if !defined(USE_TCP_LOOPBACK)
-static void SetUDSPath(struct sockaddr_un *saddr, const char *path)
-{
-    size_t pathLen;
-
-    pathLen = strlen(path);
-    if (pathLen < sizeof(saddr->sun_path))
-        memcpy(saddr->sun_path, path, pathLen + 1);
-    else
-        saddr->sun_path[0] = '\0';
-}
-#endif
-
-enum { write_all_success = 0, write_all_fail = -1, write_all_defunct = -2 };
-
-// Write len bytes. Return 0 on success, -1 on error
-static int write_all(dnssd_sock_t sd, char *buf, size_t len)
-{
-    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
-    //if (send(sd, buf, len, MSG_WAITALL) != len) return write_all_fail;
-    while (len)
-    {
-        ssize_t num_written = send(sd, buf, (long)len, 0);
-        if (num_written < 0 || (size_t)num_written > len)
-        {
-            // Check whether socket has gone defunct,
-            // otherwise, an error here indicates some OS bug
-            // or that the mDNSResponder daemon crashed (which should never happen).
-#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
-            int defunct = 0;
-            socklen_t dlen = sizeof (defunct);
-            if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
-                syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            if (!defunct)
-                syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
-                       (long)num_written, (long)len,
-                       (num_written < 0) ? dnssd_errno                 : 0,
-                       (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
-            else
-                syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
-            return defunct ? write_all_defunct : write_all_fail;
-#else
-            syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
-                   (long)num_written, (long)len,
-                   (num_written < 0) ? dnssd_errno                 : 0,
-                   (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
-            return write_all_fail;
-#endif
-        }
-        buf += num_written;
-        len -= num_written;
-    }
-    return write_all_success;
-}
-
-enum { read_all_success = 0, read_all_fail = -1, read_all_wouldblock = -2, read_all_defunct = -3 };
-
-// Read len bytes. Return 0 on success, read_all_fail on error, or read_all_wouldblock for
-static int read_all(const dnssd_sock_t sd, uint8_t *buf, size_t len)
-{
-    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
-    //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
-
-    while (len)
-    {
-        ssize_t num_read = recv(sd, buf, len, 0);
-        // It is valid to get an interrupted system call error e.g., somebody attaching
-        // in a debugger, retry without failing
-        if ((num_read < 0) && (errno == EINTR)) 
-        { 
-            syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); 
-            continue; 
-        }
-        if ((num_read == 0) || (num_read < 0) || (((size_t)num_read) > len))
-        {
-            int printWarn = 0;
-            int defunct = 0;
-
-            // Check whether socket has gone defunct,
-            // otherwise, an error here indicates some OS bug
-            // or that the mDNSResponder daemon crashed (which should never happen).
-#if defined(WIN32)
-            // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
-            //                          could not be completed immediately"
-            if (WSAGetLastError() != WSAEWOULDBLOCK)
-                printWarn = 1;
-#endif
-#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
-            {
-                socklen_t dlen = sizeof (defunct);
-                if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
-                    syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            }
-            if (!defunct)
-                printWarn = 1;
-#endif
-            if (printWarn)
-                syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd,
-                       (long)num_read, (long)len,
-                       (num_read < 0) ? dnssd_errno                 : 0,
-                       (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
-            else if (defunct)
-                syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd);
-            return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : (defunct ? read_all_defunct : read_all_fail);
-        }
-        buf += num_read;
-        len -= num_read;
-    }
-    return read_all_success;
-}
-
-// Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise
-static int more_bytes(dnssd_sock_t sd)
-{
-    struct timeval tv = { 0, 0 };
-    fd_set readfds;
-    fd_set *fs;
-    int ret;
-
-#if defined(_WIN32)
-    fs = &readfds;
-    FD_ZERO(fs);
-    FD_SET(sd, fs);
-    ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
-#else
-    // This whole thing would probably be better done using kevent() instead of select()
-    if (sd < FD_SETSIZE)
-    {
-        fs = &readfds;
-        FD_ZERO(fs);
-    }
-    else
-    {
-        // Compute the number of integers needed for storing "sd". Internally fd_set is stored
-        // as an array of ints with one bit for each fd and hence we need to compute
-        // the number of ints needed rather than the number of bytes. If "sd" is 32, we need
-        // two ints and not just one.
-        int nfdbits = sizeof (int) * 8;
-        int nints = (sd/nfdbits) + 1;
-        fs = (fd_set *)mdns_calloc(nints, (size_t)sizeof(int));
-        if (fs == NULL) 
-        { 
-            syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); 
-            return 0; 
-        }
-    }
-    FD_SET(sd, fs);
-    ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
-    if (fs != &readfds) 
-        mdns_free(fs);
-#endif
-    return (ret > 0);
-}
-
-// set_waitlimit() implements a timeout using select. It is called from deliver_request() before recv() OR accept()
-// to ensure the UDS clients are not blocked in these system calls indefinitely.
-// Note: Ideally one should never be blocked here, because it indicates either mDNSResponder daemon is not yet up/hung/
-// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software 
-// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible 
-// the next operation on this socket(recv/accept) is blocked since we depend on TCP to communicate with the system service.
-static int set_waitlimit(dnssd_sock_t sock, int timeout)
-{
-    int gDaemonErr = kDNSServiceErr_NoError;
-
-    // The comment below is wrong. The select() routine does not cause stack corruption.
-    // The use of FD_SET out of range for the bitmap is what causes stack corruption.
-    // For how to do this correctly, see the example using calloc() in more_bytes() above.
-    // Even better, both should be changed to use kevent() instead of select().
-    // To prevent stack corruption since select does not work with timeout if fds > FD_SETSIZE(1024)
-    if (!gDaemonErr && sock < FD_SETSIZE)
-    {
-        struct timeval tv;
-        fd_set set;
-
-        FD_ZERO(&set);
-        FD_SET(sock, &set);
-        tv.tv_sec = timeout;
-        tv.tv_usec = 0;
-        if (!select((int)(sock + 1), &set, NULL, NULL, &tv))
-        {
-            // Ideally one should never hit this case: See comments before set_waitlimit()
-            syslog(LOG_WARNING, "dnssd_clientstub set_waitlimit:_daemon timed out (%d secs) without any response: Socket %d", timeout, sock);
-            gDaemonErr = kDNSServiceErr_Timeout;
-        }
-    }
-    return gDaemonErr;
-}
-
-/* create_hdr
- *
- * allocate and initialize an ipc message header. Value of len should initially be the
- * length of the data, and is set to the value of the data plus the header. data_start
- * is set to point to the beginning of the data section. SeparateReturnSocket should be
- * non-zero for calls that can't receive an immediate error return value on their primary
- * socket, and therefore require a separate return path for the error code result.
- * if zero, the path to a control socket is appended at the beginning of the message buffer.
- * data_start is set past this string.
- */
-static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, uint8_t **data_start, int SeparateReturnSocket, DNSServiceOp *ref)
-{
-    uint8_t *msg = NULL;
-    ipc_msg_hdr *hdr;
-    int datalen;
-#if !defined(USE_TCP_LOOPBACK)
-    char ctrl_path[64] = "";    // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx"
-#endif
-
-    if (SeparateReturnSocket)
-    {
-#if defined(USE_TCP_LOOPBACK)
-        *len += 2;  // Allocate space for two-byte port number
-#elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        struct timeval tv;
-        if (gettimeofday(&tv, NULL) < 0)
-        { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
-        snprintf(ctrl_path, sizeof(ctrl_path), "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
-                (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
-        *len += strlen(ctrl_path) + 1;
-#else
-        *len += 1;      // Allocate space for single zero byte (empty C string)
-#endif
-    }
-
-    datalen = (int) *len;
-    *len += sizeof(ipc_msg_hdr);
-
-    // Write message to buffer
-    msg = (uint8_t *)mdns_malloc(*len);
-    if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; }
-
-    memset(msg, 0, *len);
-    hdr = (ipc_msg_hdr *)msg;
-    hdr->version                = VERSION;
-    hdr->datalen                = datalen;
-    hdr->ipc_flags              = 0;
-    hdr->op                     = op;
-    hdr->client_context         = ref->uid;
-    hdr->reg_index              = 0;
-    *data_start = msg + sizeof(ipc_msg_hdr);
-#if defined(USE_TCP_LOOPBACK)
-    // Put dummy data in for the port, since we don't know what it is yet.
-    // The data will get filled in before we send the message. This happens in deliver_request().
-    if (SeparateReturnSocket) put_uint16(0, data_start);
-#else
-    if (SeparateReturnSocket) put_string(ctrl_path, data_start);
-#endif
-    return hdr;
-}
-
-static void FreeDNSRecords(DNSServiceOp *sdRef)
-{
-    DNSRecord *rec = sdRef->rec;
-    while (rec)
-    {
-        DNSRecord *next = rec->recnext;
-        mdns_free(rec->msg);
-        mdns_free(rec);
-        rec = next;
-    }
-}
-
-static void FreeDNSServiceOp(DNSServiceOp *x)
-{
-    // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
-    // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
-    if ((x->sockfd ^ x->validator) != ValidatorBits)
-    {
-    }
-    else
-    {
-        x->next         = NULL;
-        x->primary      = NULL;
-        x->sockfd       = dnssd_InvalidSocket;
-        x->validator    = 0xDDDDDDDD;
-        x->op           = request_op_none;
-        x->max_index    = 0;
-        x->logcounter   = 0;
-        x->moreptr      = NULL;
-        x->ProcessReply = NULL;
-        x->AppCallback  = NULL;
-        x->AppContext   = NULL;
-#if _DNS_SD_LIBDISPATCH
-        MDNS_DISPOSE_DISPATCH(x->disp_source);
-        x->disp_queue   = NULL;
-#endif
-        // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
-        // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiceRegisterRecord.
-        // DNSRecords may have been freed if the application called DNSRemoveRecord.
-        FreeDNSRecords(x);
-        if (x->kacontext)
-        {
-            mdns_free(x->kacontext);
-            x->kacontext = NULL;
-        }
-        mdns_free(x);
-    }
-}
-
-// Return a connected service ref (deallocate with DNSServiceRefDeallocate)
-static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
-{
-    #if defined(_WIN32)
-    int NumTries = 0;
-    #endif // _WIN32
-
-    dnssd_sockaddr_t saddr;
-    DNSServiceOp *sdr;
-
-    if (!ref) 
-    { 
-        syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); 
-        return kDNSServiceErr_BadParam; 
-    }
-
-    if (flags & kDNSServiceFlagsShareConnection)
-    {
-        if (!*ref)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef");
-            return kDNSServiceErr_BadParam;
-        }
-        if (!DNSServiceRefValid(*ref) || ((*ref)->op != connection_request && (*ref)->op != connection_delegate_request) || (*ref)->primary)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X op %d",
-                   (*ref), (*ref)->sockfd, (*ref)->validator, (*ref)->op);
-            *ref = NULL;
-            return kDNSServiceErr_BadReference;
-        }
-    }
-
-    #if defined(_WIN32)
-    if (!g_initWinsock)
-    {
-        WSADATA wsaData;
-        g_initWinsock = 1;
-        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
-    }
-
-#ifndef WIN32_CENTENNIAL
-    // <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
-    if (IsSystemServiceDisabled())
-        NumTries = DNSSD_CLIENT_MAXTRIES;
-    #endif
-#endif
-
-    sdr = mdns_malloc(sizeof(DNSServiceOp));
-    if (!sdr) 
-    { 
-        syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); 
-        *ref = NULL; 
-        return kDNSServiceErr_NoMemory; 
-    }
-    sdr->next          = NULL;
-    sdr->primary       = NULL;
-    sdr->sockfd        = dnssd_InvalidSocket;
-    sdr->validator     = sdr->sockfd ^ ValidatorBits;
-    sdr->op            = op;
-    sdr->max_index     = 0;
-    sdr->logcounter    = 0;
-    sdr->moreptr       = NULL;
-    sdr->uid.u32[0]    = 0;
-    sdr->uid.u32[1]    = 0;
-    sdr->ProcessReply  = ProcessReply;
-    sdr->AppCallback   = AppCallback;
-    sdr->AppContext    = AppContext;
-    sdr->rec           = NULL;
-#if _DNS_SD_LIBDISPATCH
-    sdr->disp_source   = NULL;
-    sdr->disp_queue    = NULL;
-#endif
-    sdr->kacontext     = NULL;
-    
-    if (flags & kDNSServiceFlagsShareConnection)
-    {
-        DNSServiceOp **p = &(*ref)->next;       // Append ourselves to end of primary's list
-        while (*p) 
-            p = &(*p)->next;
-        *p = sdr;
-        // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear
-        if (++(*ref)->uid.u32[0] == 0) 
-            ++(*ref)->uid.u32[1];               // In parent DNSServiceOp increment UID counter
-        sdr->primary    = *ref;                 // Set our primary pointer
-        sdr->sockfd     = (*ref)->sockfd;       // Inherit primary's socket
-        sdr->validator  = (*ref)->validator;
-        sdr->uid        = (*ref)->uid;
-        //printf("ConnectToServer sharing socket %d\n", sdr->sockfd);
-    }
-    else
-    {
-        #ifdef SO_NOSIGPIPE
-        const unsigned long optval = 1;
-        #endif
-        #ifndef USE_TCP_LOOPBACK
-        char* uds_serverpath = getenv(MDNS_UDS_SERVERPATH_ENVVAR);
-        if (uds_serverpath == NULL)
-            uds_serverpath = MDNS_UDS_SERVERPATH;
-        else if (strlen(uds_serverpath) >= MAX_CTLPATH)
-        {
-            uds_serverpath = MDNS_UDS_SERVERPATH;
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: using default path since env len is invalid");
-        }
-        #endif
-        *ref = NULL;
-        sdr->sockfd    = socket(AF_DNSSD, SOCK_STREAM, 0);
-        sdr->validator = sdr->sockfd ^ ValidatorBits;
-        if (!dnssd_SocketValid(sdr->sockfd))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            FreeDNSServiceOp(sdr);
-            return kDNSServiceErr_NoMemory;
-        }
-#if !defined(_WIN32)
-        int fcntl_flags = fcntl(sdr->sockfd, F_GETFD);
-        if (fcntl_flags != -1)
-        {
-            fcntl_flags |= FD_CLOEXEC;
-            int ret = fcntl(sdr->sockfd, F_SETFD, fcntl_flags);
-            if (ret == -1)
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: Failed to set FD_CLOEXEC on socket %d %s",
-                       dnssd_errno, dnssd_strerror(dnssd_errno));
-        }
-        else
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: Failed to get the file descriptor flags of socket %d %s",
-                   dnssd_errno, dnssd_strerror(dnssd_errno));
-        }
-#endif // !defined(_WIN32)
-        #ifdef SO_NOSIGPIPE
-        // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
-        if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-        #endif
-        #if defined(USE_TCP_LOOPBACK)
-        saddr.sin_family      = AF_INET;
-        saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-        saddr.sin_port        = IsSystemServiceDisabled() ? htons(MDNS_TCP_SERVERPORT_CENTENNIAL) : htons(MDNS_TCP_SERVERPORT);
-        #else
-        saddr.sun_family      = AF_LOCAL;
-        SetUDSPath(&saddr, uds_serverpath);
-        #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
-        {
-            int defunct = 1;
-            if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-        }
-        #endif
-        #endif
-
-        #if defined(_WIN32)
-        while (1)
-        {
-#ifdef WIN32_CENTENNIAL
-            char port[128];
-            // Access to the process environment block is thread-safe
-            if (GetEnvironmentVariableA("MDNS_TCP_SERVERPORT_CENTENNIAL", port, sizeof(port)))
-            {
-                saddr.sin_port = htons((u_short)atoi(port));
-            }
-#endif
-            int err = connect(sdr->sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
-            if (!err)
-                break; // If we succeeded, return sdr
-
-            // If we failed, then it may be because the daemon is still launching.
-            // This can happen for processes that launch early in the boot process, while the
-            // daemon is still coming up. Rather than fail here, we wait 1 sec and try again.
-            // If, after DNSSD_CLIENT_MAXTRIES, we still can't connect to the daemon,
-            // then we give up and return a failure code.
-            if (++NumTries < DNSSD_CLIENT_MAXTRIES)
-            {
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries);
-                sleep(1); // Sleep a bit, then try again
-            }
-            else
-            {
-                #if !defined(USE_TCP_LOOPBACK)
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s",
-                       uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
-                #endif
-                dnssd_close(sdr->sockfd);
-                FreeDNSServiceOp(sdr);
-                return kDNSServiceErr_ServiceNotRunning;
-            }
-        }
-        #else
-        int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
-        if (err)
-        {
-            #if !defined(USE_TCP_LOOPBACK)
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s",
-                   uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
-            #endif
-            dnssd_close(sdr->sockfd);
-            FreeDNSServiceOp(sdr);
-            return kDNSServiceErr_ServiceNotRunning;
-        }
-        #endif
-    }
-
-    *ref = sdr;
-    return kDNSServiceErr_NoError;
-}
-
-#define deliver_request_bailout(MSG) \
-    do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0)
-
-static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
-{
-    uint32_t datalen;
-    dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
-    DNSServiceErrorType err = kDNSServiceErr_Unknown;   // Default for the "goto cleanup" cases
-    int MakeSeparateReturnSocket;
-    int ioresult;
-    #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
-    char *data;
-    #endif
-
-    if (!hdr)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr");
-        return kDNSServiceErr_Unknown;
-    }
-    
-    datalen = hdr->datalen;    // We take a copy here because we're going to convert hdr->datalen to network byte order
-    #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
-    data = (char *)hdr + sizeof(ipc_msg_hdr);
-    #endif
-
-    // Note: need to check hdr->op, not sdr->op.
-    // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
-    // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
-    // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
-    MakeSeparateReturnSocket = (sdr->primary ||
-        hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request);
-
-    if (!DNSServiceRefValid(sdr))
-    {
-        if (hdr)
-            mdns_free(hdr);
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (MakeSeparateReturnSocket)
-    {
-        #if defined(USE_TCP_LOOPBACK)
-        {
-            union { uint16_t s; u_char b[2]; } port;
-            dnssd_sockaddr_t caddr;
-            dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
-            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket");
-
-            caddr.sin_family      = AF_INET;
-            caddr.sin_port        = 0;
-            caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-            if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind");
-            if (getsockname(listenfd, (struct sockaddr*) &caddr, &len)   < 0) deliver_request_bailout("TCP getsockname");
-            if (listen(listenfd, 1)                                      < 0) deliver_request_bailout("TCP listen");
-            port.s = caddr.sin_port;
-            data[0] = port.b[0];  // don't switch the byte order, as the
-            data[1] = port.b[1];  // daemon expects it in network byte order
-        }
-        #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        {
-            mode_t mask;
-            int bindresult;
-            dnssd_sockaddr_t caddr;
-            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
-
-            caddr.sun_family = AF_LOCAL;
-            // According to Stevens (section 3.2), there is no portable way to
-            // determine whether sa_len is defined on a particular platform.
-            #ifndef NOT_HAVE_SA_LEN
-            caddr.sun_len = sizeof(struct sockaddr_un);
-            #endif
-            SetUDSPath(&caddr, data);
-            mask = umask(0);
-            bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
-            umask(mask);
-            if (bindresult          < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
-            if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
-        }
-        #else
-        {
-            dnssd_sock_t sp[2];
-            if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair");
-            else
-            {
-                errsd    = sp[0];   // We'll read our four-byte error code from sp[0]
-                listenfd = sp[1];   // We'll send sp[1] to the daemon
-                #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
-                {
-                    int defunct = 1;
-                    if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
-                        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-                }
-                #endif
-            }
-        }
-        #endif
-    }
-
-#if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
-    // If we're going to make a separate error return socket, and pass it to the daemon
-    // using sendmsg, then we'll hold back one data byte to go with it.
-    // On some versions of Unix (including Leopard) sending a control message without
-    // any associated data does not work reliably -- e.g. one particular issue we ran
-    // into is that if the receiving program is in a kqueue loop waiting to be notified
-    // of the received message, it doesn't get woken up when the control message arrives.
-    if (MakeSeparateReturnSocket || sdr->op == send_bpf) 
-        datalen--;     // Okay to use sdr->op when checking for op == send_bpf
-#endif
-
-    // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to
-    ConvertHeaderBytes(hdr);
-    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
-    //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data);
-#if defined(TEST_SENDING_ONE_BYTE_AT_A_TIME) && TEST_SENDING_ONE_BYTE_AT_A_TIME
-    unsigned int i;
-    for (i=0; i<datalen + sizeof(ipc_msg_hdr); i++)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %d", i);
-        ioresult = write_all(sdr->sockfd, ((char *)hdr)+i, 1);
-        if (ioresult < write_all_success)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub deliver_request write_all (byte %u) failed", i);
-            err = (ioresult == write_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning;
-            goto cleanup;
-        }
-        usleep(10000);
-    }
-#else
-    ioresult = write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr));
-    if (ioresult < write_all_success)
-    {
-        // write_all already prints an error message if there is an error writing to
-        // the socket except for DEFUNCT. Logging here is unnecessary and also wrong
-        // in the case of DEFUNCT sockets
-        syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
-               sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
-        err = (ioresult == write_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning;
-        goto cleanup;
-    }
-#endif
-
-    if (!MakeSeparateReturnSocket) 
-        errsd = sdr->sockfd;
-    if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-    {
-#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us,
-        // but that's okay -- the daemon should not take more than a few milliseconds to respond.
-        // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
-        dnssd_sockaddr_t daddr;
-        dnssd_socklen_t len = sizeof(daddr);
-        if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) 
-            goto cleanup;
-        errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
-        if (!dnssd_SocketValid(errsd)) 
-            deliver_request_bailout("accept");
-#else
-
-        struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
-        struct msghdr msg;
-        struct cmsghdr *cmsg;
-        char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
-
-        msg.msg_name       = 0;
-        msg.msg_namelen    = 0;
-        msg.msg_iov        = &vec;
-        msg.msg_iovlen     = 1;
-        msg.msg_flags      = 0;
-        if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-        {
-            if (sdr->op == send_bpf)
-            {
-                int i;
-                char p[12];     // Room for "/dev/bpf999" with terminating null
-                for (i=0; i<100; i++)
-                {
-                    snprintf(p, sizeof(p), "/dev/bpf%d", i);
-                    listenfd = open(p, O_RDWR, 0);
-                    //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "dnssd_clientstub deliver_request Sending fd %d for %s", listenfd, p);
-                    if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY)
-                        syslog(LOG_WARNING, "dnssd_clientstub deliver_request Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno));
-                    if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break;
-                }
-            }
-            msg.msg_control    = cbuf;
-            msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t));
-
-            cmsg = CMSG_FIRSTHDR(&msg);
-            cmsg->cmsg_len     = CMSG_LEN(sizeof(dnssd_sock_t));
-            cmsg->cmsg_level   = SOL_SOCKET;
-            cmsg->cmsg_type    = SCM_RIGHTS;
-            *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
-        }
-
-#if defined(TEST_KQUEUE_CONTROL_MESSAGE_BUG) && TEST_KQUEUE_CONTROL_MESSAGE_BUG
-        sleep(1);
-#endif
-
-#if DEBUG_64BIT_SCM_RIGHTS
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld",
-               errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*),
-               sizeof(struct cmsghdr) + sizeof(dnssd_sock_t),
-               CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)),
-               (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf));
-#endif // DEBUG_64BIT_SCM_RIGHTS
-
-        if (sendmsg(sdr->sockfd, &msg, 0) < 0)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
-                   errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno));
-            err = kDNSServiceErr_Incompatible;
-            goto cleanup;
-        }
-
-#if DEBUG_64BIT_SCM_RIGHTS
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request sendmsg read sd=%d write sd=%d okay", errsd, listenfd);
-#endif // DEBUG_64BIT_SCM_RIGHTS
-
-#endif
-        // Close our end of the socketpair *before* calling read_all() to get the four-byte error code.
-        // Otherwise, if the daemon closes our socket (or crashes), we will have to wait for a timeout
-        // in read_all() because the socket is not closed (we still have an open reference to it)
-        // Note: listenfd is overwritten in the case of send_bpf above and that will be closed here
-        // for send_bpf operation.
-        dnssd_close(listenfd);
-        listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below
-    }
-
-    // At this point we may wait in read_all for a few milliseconds waiting for the daemon to send us the error code,
-    // but that's okay -- the daemon should not take more than a few milliseconds to respond.
-    // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
-    if (sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-        err = kDNSServiceErr_NoError;
-    else if ((err = set_waitlimit(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError)
-    {
-        ioresult = read_all(errsd, (uint8_t *)&err, (int)sizeof(err));
-        if (ioresult < read_all_success)
-            err = (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
-        else
-            err = ntohl(err);
-    }
-    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err);
-
-cleanup:
-    if (MakeSeparateReturnSocket)
-    {
-        if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd);
-        if (dnssd_SocketValid(errsd)) dnssd_close(errsd);
-#if defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data);
-        if (unlink(data) != 0)
-            syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno));
-        // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data);
-#endif
-    }
-
-    mdns_free(hdr);
-    return err;
-}
-
-dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
-{
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X",
-               sdRef, sdRef->sockfd, sdRef->validator);
-        return dnssd_InvalidSocket;
-    }
-
-    if (sdRef->primary)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
-        return dnssd_InvalidSocket;
-    }
-
-    return sdRef->sockfd;
-}
-
-#if _DNS_SD_LIBDISPATCH
-static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error)
-{
-    DNSServiceOp *sdr = sdRef;
-    DNSServiceOp *sdrNext;
-    DNSRecord *rec;
-    DNSRecord *recnext;
-    int morebytes;
-
-    while (sdr)
-    {
-        // We can't touch the sdr after the callback as it can be deallocated in the callback
-        sdrNext = sdr->next;
-        morebytes = 1;
-        sdr->moreptr = &morebytes;
-        switch (sdr->op)
-        {
-        case resolve_request:
-            if (sdr->AppCallback) ((DNSServiceResolveReply)    sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL,    sdr->AppContext);
-            break;
-        case query_request:
-            if (sdr->AppCallback) ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext);
-            break;
-        case addrinfo_request:
-            if (sdr->AppCallback) ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0,          sdr->AppContext);
-            break;
-        case browse_request:
-            if (sdr->AppCallback) ((DNSServiceBrowseReply)     sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL,          sdr->AppContext);
-            break;
-        case reg_service_request:
-            if (sdr->AppCallback) ((DNSServiceRegisterReply)   sdr->AppCallback)(sdr, 0,    error, NULL, 0, NULL,          sdr->AppContext);
-            break;
-        case enumeration_request:
-            if (sdr->AppCallback) ((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL,                   sdr->AppContext);
-            break;
-        case connection_request:
-        case connection_delegate_request:
-            // This means Register Record, walk the list of DNSRecords to do the callback
-            rec = sdr->rec;
-            while (rec)
-            {
-                recnext = rec->recnext;
-                if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext);
-                // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records.
-                // Detect that and return early
-                if (!morebytes) { syslog(LOG_WARNING, "dnssd_clientstub:Record: CallbackwithError morebytes zero"); return; }
-                rec = recnext;
-            }
-            break;
-        case port_mapping_request:
-            if (sdr->AppCallback) ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext);
-            break;
-        default:
-            syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op);
-        }
-        // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. As the sdRef
-        // (and its subordinates) have been freed, we should not proceed further. Note that when we
-        // call the callback with a subordinate sdRef the application can call DNSServiceRefDeallocate
-        // on the main sdRef and DNSServiceRefDeallocate handles this case by walking all the sdRefs and
-        // clears the moreptr so that we can terminate here.
-        //
-        // If DNSServiceRefDeallocate was not called in the callback, then set moreptr to NULL so that
-        // we don't access the stack variable after we return from this function.
-        if (!morebytes) { syslog(LOG_WARNING, "dnssd_clientstub:sdRef: CallbackwithError morebytes zero sdr %p", sdr); return; }
-        else {sdr->moreptr = NULL;}
-        sdr = sdrNext;
-    }
-}
-#endif // _DNS_SD_LIBDISPATCH
-
-// Handle reply from server, calling application client callback. If there is no reply
-// from the daemon on the socket contained in sdRef, the call will block.
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
-{
-    int morebytes = 0;
-    int ioresult;
-    DNSServiceErrorType error;
-
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (sdRef->primary)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (!sdRef->ProcessReply)
-    {
-        static int num_logs = 0;
-        if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function");
-        if (num_logs < 1000) num_logs++;else sleep(1);
-        return kDNSServiceErr_BadReference;
-    }
-
-    do
-    {
-        CallbackHeader cbh;
-        uint8_t *data;
-
-        // return NoError on EWOULDBLOCK. This will handle the case
-        // where a non-blocking socket is told there is data, but it was a false positive.
-        // On error, read_all will write a message to syslog for us, so don't need to duplicate that here
-        // Note: If we want to properly support using non-blocking sockets in the future
-        ioresult = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr));
-        if (ioresult == read_all_fail || ioresult == read_all_defunct)
-        {
-            error = (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning;
-            
-            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
-            // in the callback.
-            sdRef->ProcessReply = NULL;
-#if _DNS_SD_LIBDISPATCH
-            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
-            // is not called by the application and hence need to communicate the error. Cancel the
-            // source so that we don't get any more events
-            // Note: read_all fails if we could not read from the daemon which can happen if the
-            // daemon dies or the file descriptor is disconnected (defunct).
-            if (sdRef->disp_source)
-            {
-                dispatch_source_cancel(sdRef->disp_source);
-                MDNS_DISPOSE_DISPATCH(sdRef->disp_source);
-                CallbackWithError(sdRef, error);
-            }
-#endif
-            // Don't touch sdRef anymore as it might have been deallocated
-            return error;
-        }
-        else if (ioresult == read_all_wouldblock)
-        {
-            if (morebytes && sdRef->logcounter < 100)
-            {
-                sdRef->logcounter++;
-                syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK");
-            }
-            return kDNSServiceErr_NoError;
-        }
-
-        ConvertHeaderBytes(&cbh.ipc_hdr);
-        if (cbh.ipc_hdr.version != VERSION)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION);
-            sdRef->ProcessReply = NULL;
-            return kDNSServiceErr_Incompatible;
-        }
-
-        data = mdns_malloc(cbh.ipc_hdr.datalen);
-        if (!data) return kDNSServiceErr_NoMemory;
-        ioresult = read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen);
-        if (ioresult < read_all_success) // On error, read_all will write a message to syslog for us
-        {
-            error = (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning;
-            
-            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
-            // in the callback.
-            sdRef->ProcessReply = NULL;
-#if _DNS_SD_LIBDISPATCH
-            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
-            // is not called by the application and hence need to communicate the error. Cancel the
-            // source so that we don't get any more events
-            if (sdRef->disp_source)
-            {
-                dispatch_source_cancel(sdRef->disp_source);
-                MDNS_DISPOSE_DISPATCH(sdRef->disp_source);
-                CallbackWithError(sdRef, error);
-            }
-#endif
-            // Don't touch sdRef anymore as it might have been deallocated
-            mdns_free(data);
-            return error;
-        }
-        else
-        {
-            const uint8_t *ptr = data;
-            cbh.cb_flags     = get_flags     (&ptr, data + cbh.ipc_hdr.datalen);
-            cbh.cb_interface = get_uint32    (&ptr, data + cbh.ipc_hdr.datalen);
-            cbh.cb_err       = get_error_code(&ptr, data + cbh.ipc_hdr.datalen);
-
-            // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function.
-            // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(),
-            // then that routine will clear morebytes for us, and cause us to exit our loop.
-            morebytes = more_bytes(sdRef->sockfd);
-            if (morebytes)
-            {
-                cbh.cb_flags |= kDNSServiceFlagsMoreComing;
-                sdRef->moreptr = &morebytes;
-            }
-            if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen);
-            // Careful code here:
-            // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not
-            // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray
-            // dangling pointer pointing to a long-gone stack variable.
-            // If morebytes is zero, then one of two thing happened:
-            // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it
-            // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()),
-            //     so we MUST NOT try to dereference our stale sdRef pointer.
-            if (morebytes) sdRef->moreptr = NULL;
-        }
-        mdns_free(data);
-    } while (morebytes);
-
-    return kDNSServiceErr_NoError;
-}
-
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; }
-
-    if (!DNSServiceRefValid(sdRef))     // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return;
-    }
-
-    // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop
-    if (sdRef->moreptr) *(sdRef->moreptr) = 0;
-
-    if (sdRef->primary)     // If this is a subordinate DNSServiceOp, just send a 'stop' command
-    {
-        DNSServiceOp **p = &sdRef->primary->next;
-        while (*p && *p != sdRef) p = &(*p)->next;
-        if (*p)
-        {
-            uint8_t *ptr;
-            size_t len = 0;
-            ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef);
-            if (hdr)
-            {
-                ConvertHeaderBytes(hdr);
-                write_all(sdRef->sockfd, (char *)hdr, len);
-                mdns_free(hdr);
-            }
-            *p = sdRef->next;
-            FreeDNSServiceOp(sdRef);
-        }
-    }
-    else                    // else, make sure to terminate all subordinates as well
-    {
-#if _DNS_SD_LIBDISPATCH
-        // The cancel handler will close the fd if a dispatch source has been set
-        if (sdRef->disp_source)
-        {
-            // By setting the ProcessReply to NULL, we make sure that we never call
-            // the application callbacks ever, after returning from this function. We
-            // assume that DNSServiceRefDeallocate is called from the serial queue
-            // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel
-            // should cancel all the blocks on the queue and hence there should be no more
-            // callbacks when we return from this function. Setting ProcessReply to NULL
-            // provides extra protection.
-            sdRef->ProcessReply = NULL;
-            shutdown(sdRef->sockfd, SHUT_WR);
-            dispatch_source_cancel(sdRef->disp_source);
-            MDNS_DISPOSE_DISPATCH(sdRef->disp_source);
-        }
-        // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case,
-        // when the source was cancelled, the fd was closed in the handler. Currently the source
-        // is cancelled only when the mDNSResponder daemon dies
-        else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd);
-#else
-        dnssd_close(sdRef->sockfd);
-#endif
-        // Free DNSRecords added in DNSRegisterRecord if they have not
-        // been freed in DNSRemoveRecord
-        while (sdRef)
-        {
-            DNSServiceOp *p = sdRef;
-            sdRef = sdRef->next;
-            // When there is an error reading from the daemon e.g., bad fd, CallbackWithError
-            // is called which sets moreptr. It might set the moreptr on a subordinate sdRef
-            // but the application might call DNSServiceRefDeallocate with the main sdRef from
-            // the callback. Hence, when we loop through the subordinate sdRefs, we need
-            // to clear the moreptr so that CallbackWithError can terminate itself instead of
-            // walking through the freed sdRefs.
-            if (p->moreptr) *(p->moreptr) = 0;
-            FreeDNSServiceOp(p);
-        }
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size)
-{
-    DNSServiceErrorType err;
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp;
-    uint32_t actualsize;
-    int ioresult;
-
-    if (!property || !result || !size)
-        return kDNSServiceErr_BadParam;
-
-    len = strlen(property) + 1;
-    err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_string(property, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(tmp); return err; }
-
-    ioresult = read_all(tmp->sockfd, (uint8_t *)&actualsize, sizeof(actualsize));
-    if (ioresult < read_all_success)
-    { DNSServiceRefDeallocate(tmp); return (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning; }
-
-    actualsize = ntohl(actualsize);
-    ioresult = read_all(tmp->sockfd, (uint8_t *)result, actualsize < *size ? actualsize : *size);
-    if (ioresult < read_all_success)
-    { DNSServiceRefDeallocate(tmp); return (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning; }
-    DNSServiceRefDeallocate(tmp);
-
-    // Swap version result back to local process byte order
-    if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4)
-        *(uint32_t*)result = ntohl(*(uint32_t*)result);
-
-    *size = actualsize;
-    return kDNSServiceErr_NoError;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t *pid)
-{
-    uint8_t *ptr;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp = NULL;
-    size_t len = sizeof(int32_t);
-    int ioresult;
-
-    DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_uint16(srcport, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(tmp); return err; }
-
-    ioresult = read_all(tmp->sockfd, (uint8_t *)pid, sizeof(int32_t));
-    if (ioresult < read_all_success)
-    { DNSServiceRefDeallocate(tmp); return (ioresult == read_all_defunct) ? kDNSServiceErr_DefunctConnection : kDNSServiceErr_ServiceNotRunning; }
-
-    DNSServiceRefDeallocate(tmp);
-    return kDNSServiceErr_NoError;
-}
-
-static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    char fullname[kDNSServiceMaxDomainName];
-    char target[kDNSServiceMaxDomainName];
-    uint16_t txtlen;
-    union { uint16_t s; u_char b[2]; } port;
-    const unsigned char *txtrecord;
-
-    get_string(&data, end, fullname, kDNSServiceMaxDomainName);
-    get_string(&data, end, target,   kDNSServiceMaxDomainName);
-    if (!data || data + 2 > end) goto fail;
-
-    port.b[0] = *data++;
-    port.b[1] = *data++;
-    txtlen = get_uint16(&data, end);
-    txtrecord = (const unsigned char *)get_rdata(&data, end, txtlen);
-
-    if (!data) goto fail;
-    ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
-    return;
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-fail:
-    syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-(
-    DNSServiceRef           *sdRef,
-    DNSServiceFlags         flags,
-    uint32_t                interfaceIndex,
-    const char              *name,
-    const char              *regtype,
-    const char              *domain,
-    DNSServiceResolveReply  callBack,
-    void                    *context
-)
-{
-    return DNSServiceResolveInternal(sdRef, flags, interfaceIndex, name, regtype, domain, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceResolveInternal
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,
-    const char *regtype,
-    const char *domain,
-    const DNSServiceAttribute *attr,
-    DNSServiceResolveReply callBack,
-    void *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if (!sdRef || !name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
-
-    // Need a real InterfaceID for WakeOnResolve
-    if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
-        ((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexP2P) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexBLE)))
-    {
-        return kDNSServiceErr_BadParam;
-    }
-
-    err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += strlen(name) + 1;
-    len += strlen(regtype) + 1;
-    len += strlen(domain) + 1;
-
-    (void)attr;
-
-    hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-    {
-        err = kDNSServiceErr_NoError;
-    }
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_query_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    if (cbh->cb_err == kDNSServiceErr_PolicyDenied && !_should_return_noauth_error())
-    {
-        return;
-    }
-    uint32_t ttl;
-    char name[kDNSServiceMaxDomainName];
-    uint16_t rrtype, rrclass, rdlen;
-    const uint8_t *rdata;
-
-    get_string(&data, end, name, kDNSServiceMaxDomainName);
-    rrtype  = get_uint16(&data, end);
-    rrclass = get_uint16(&data, end);
-    rdlen   = get_uint16(&data, end);
-    rdata   = get_rdata(&data, end, rdlen);
-    ttl     = get_uint32(&data, end);
-
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon");
-    else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-(
-    DNSServiceRef              *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                 *name,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    DNSServiceQueryRecordReply callBack,
-    void                       *context
-)
-{
-    return DNSServiceQueryRecordInternal(sdRef, flags, interfaceIndex, name, rrtype, rrclass, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceQueryRecordInternal
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    const DNSServiceAttribute *attr,
-    DNSServiceQueryRecordReply callBack,
-    void *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-    // NULL name handled below.
-    if (!sdRef || !callBack) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, query_request, handle_query_response, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    if (!name) name = "\0";
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(uint32_t);  // interfaceIndex
-    len += strlen(name) + 1;
-    len += 2 * sizeof(uint16_t);  // rrtype, rrclass
-    (void)attr;
-    hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr)
-    {
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-        return kDNSServiceErr_NoMemory;
-    }
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-    {
-        err = kDNSServiceErr_NoError;
-    }
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    if (cbh->cb_err == kDNSServiceErr_PolicyDenied && !_should_return_noauth_error())
-    {
-        return;
-    }
-    char hostname[kDNSServiceMaxDomainName];
-    uint16_t rrtype, rrclass, rdlen;
-    const uint8_t *rdata;
-    uint32_t ttl;
-
-    get_string(&data, end, hostname, kDNSServiceMaxDomainName);
-    rrtype  = get_uint16(&data, end);
-    rrclass = get_uint16(&data, end);
-    rdlen   = get_uint16(&data, end);
-    rdata   = get_rdata (&data, end, rdlen);
-    ttl     = get_uint32(&data, end);
-    (void)rrclass; // Unused
-    // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for
-    // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates).
-    // Other result types, specifically CNAME referrals, are not communicated to the client, because
-    // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals.
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon");
-    else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA)
-    {
-        struct sockaddr_in sa4;
-        struct sockaddr_in6 sa6;
-        const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6;
-        if (rrtype == kDNSServiceType_A)
-        {
-            memset(&sa4, 0, sizeof(sa4));
-            #ifndef NOT_HAVE_SA_LEN
-            sa4.sin_len = sizeof(struct sockaddr_in);
-            #endif
-            sa4.sin_family = AF_INET;
-            //  sin_port   = 0;
-            if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen);
-        }
-        else
-        {
-            memset(&sa6, 0, sizeof(sa6));
-            #ifndef NOT_HAVE_SA_LEN
-            sa6.sin6_len = sizeof(struct sockaddr_in6);
-            #endif
-            sa6.sin6_family     = AF_INET6;
-            //  sin6_port     = 0;
-            //  sin6_flowinfo = 0;
-            //  sin6_scope_id = 0;
-            if (!cbh->cb_err)
-            {
-                memcpy(&sa6.sin6_addr, rdata, rdlen);
-                if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface;
-            }
-        }
-
-        ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext);
-    }
-    else if (cbh->cb_err == kDNSServiceErr_PolicyDenied)
-    {
-        ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, NULL, ttl, sdr->AppContext);
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
-(
-    DNSServiceRef               *sdRef,
-    DNSServiceFlags             flags,
-    uint32_t                    interfaceIndex,
-    uint32_t                    protocol,
-    const char                  *hostname,
-    DNSServiceGetAddrInfoReply  callBack,
-    void                        *context          /* may be NULL */
-)
-{
-    return DNSServiceGetAddrInfoInternal(sdRef, flags, interfaceIndex, protocol, hostname, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceGetAddrInfoInternal
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    uint32_t protocol,
-    const char *hostname,
-    const DNSServiceAttribute *attr,
-    DNSServiceGetAddrInfoReply callBack,
-    void *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if (!sdRef || !hostname || !callBack) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, (void *)callBack, context);
-    if (err)
-    {
-         return err;    // On error ConnectToServer leaves *sdRef set to NULL
-    }
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(uint32_t);      // interfaceIndex
-    len += sizeof(uint32_t);      // protocol
-    len += strlen(hostname) + 1;
-    (void)attr;
-    hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr)
-    {
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-        return kDNSServiceErr_NoMemory;
-    }
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_uint32(protocol, &ptr);
-    put_string(hostname, &ptr);
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-    {
-        err = kDNSServiceErr_NoError;
-    }
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_browse_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    if (cbh->cb_err == kDNSServiceErr_PolicyDenied && !_should_return_noauth_error())
-    {
-        return;
-    }
-    char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName];
-    get_string(&data, end, replyName, 256);
-    get_string(&data, end, replyType, kDNSServiceMaxDomainName);
-    get_string(&data, end, replyDomain, kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon");
-    else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-(
-    DNSServiceRef         *sdRef,
-    DNSServiceFlags       flags,
-    uint32_t              interfaceIndex,
-    const char            *regtype,
-    const char            *domain,
-    DNSServiceBrowseReply callBack,
-    void                  *context
-)
-{
-    return DNSServiceBrowseInternal(sdRef, flags, interfaceIndex, regtype, domain, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceBrowseInternal
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *regtype,
-    const char *domain,
-    const DNSServiceAttribute *attr,
-    DNSServiceBrowseReply callBack,
-    void *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    // NULL domain handled below
-    if (!sdRef || !regtype || !callBack) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    if (!domain) domain = "";
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += strlen(regtype) + 1;
-    len += strlen(domain) + 1;
-
-    (void)attr;
-
-    hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-    {
-        err = kDNSServiceErr_NoError;
-    }
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
-{
-    DNSServiceErrorType err;
-    DNSServiceOp *tmp;
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-
-    if (!domain) return kDNSServiceErr_BadParam;
-    len = sizeof(flags) + strlen(domain) + 1;
-
-    err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_string(domain, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    DNSServiceRefDeallocate(tmp);
-    return err;
-}
-
-static void handle_regservice_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    if (cbh->cb_err == kDNSServiceErr_PolicyDenied && !_should_return_noauth_error())
-    {
-        return;
-    }
-    char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
-    get_string(&data, end, name, 256);
-    get_string(&data, end, regtype, kDNSServiceMaxDomainName);
-    get_string(&data, end, domain,  kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon");
-    else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    const char                          *host,
-    uint16_t PortInNetworkByteOrder,
-    uint16_t txtLen,
-    const void                          *txtRecord,
-    DNSServiceRegisterReply callBack,
-    void                                *context
-)
-{
-    return DNSServiceRegisterInternal(sdRef, flags, interfaceIndex, name, regtype, domain, host, PortInNetworkByteOrder, txtLen, txtRecord, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterWithAttribute
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,
-    const char *regtype,
-    const char *domain,
-    const char *host,
-    uint16_t portInNetworkByteOrder,
-    uint16_t txtLen,
-    const void *txtRecord,
-    const DNSServiceAttributeRef attr,
-    DNSServiceRegisterReply callBack,
-    void *context
-)
-{
-    return DNSServiceRegisterInternal(sdRef, flags, interfaceIndex, name, regtype, domain, host, portInNetworkByteOrder, txtLen, txtRecord, attr, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceRegisterInternal
-(
-    DNSServiceRef *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *name,
-    const char *regtype,
-    const char *domain,
-    const char *host,
-    uint16_t portInNetworkByteOrder,
-    uint16_t txtLen,
-    const void *txtRecord,
-    const DNSServiceAttribute *attr,
-    DNSServiceRegisterReply callBack,
-    void *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-    union { uint16_t s; u_char b[2]; } port = { portInNetworkByteOrder };
-    (void)attr;
-
-    if (!sdRef || !regtype) return kDNSServiceErr_BadParam;
-    if (!name) name = "";
-    if (!domain) domain = "";
-    if (!host) host = "";
-    if (!txtRecord) txtRecord = (void*)"";
-
-    // No callback must have auto-rename
-    if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);  // interfaceIndex
-    len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
-    len += 2 * sizeof(uint16_t);  // port, txtLen
-    len += txtLen;
-    (void)attr;
-
-    hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-    if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-    put_string(host, &ptr);
-    *ptr++ = port.b[0];
-    *ptr++ = port.b[1];
-    put_uint16(txtLen, &ptr);
-    put_rdata(txtLen, txtRecord, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-    {
-        err = kDNSServiceErr_NoError;
-    }
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_enumeration_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    char domain[kDNSServiceMaxDomainName];
-    get_string(&data, end, domain, kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon");
-    else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
-(
-    DNSServiceRef             *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceDomainEnumReply callBack,
-    void                      *context
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-    int f1;
-    int f2;
-
-    if (!sdRef || !callBack) return kDNSServiceErr_BadParam;
-
-    f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
-    f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
-    if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);
-
-    hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *const data, const uint8_t *const end)
-{
-    (void)data; // Unused
-
-    //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op);
-    if (cbh->ipc_hdr.op != reg_record_reply_op && cbh->ipc_hdr.op != async_error_op)
-    {
-        // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps
-        // to find the one this response is intended for, and then call through to its ProcessReply handler.
-        // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef.
-        DNSServiceOp *op = sdr->next;
-        while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1]))
-            op = op->next;
-        // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has
-        // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon
-        if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end);
-        // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate
-        return;
-    }
-    else
-    {
-        if (cbh->cb_err == kDNSServiceErr_PolicyDenied && !_should_return_noauth_error())
-        {
-            return;
-        }
-        DNSRecordRef rec;
-        for (rec = sdr->rec; rec; rec = rec->recnext)
-        {
-            if (rec->uid.u32[0] == cbh->ipc_hdr.client_context.u32[0] && rec->uid.u32[1] == cbh->ipc_hdr.client_context.u32[1])
-                break;
-        }
-        // The record might have been freed already and hence not an
-        // error if the record is not found.
-        if (!rec)
-        {
-            syslog(LOG_INFO, "dnssd_clientstub ConnectionResponse: Record not found");
-            return;
-        }
-        if (rec->sdr != sdr)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: Record sdr mismatch: rec %p sdr %p", rec->sdr, sdr);
-            return;
-        }
-
-        if (sdr->op == connection_request || sdr->op == connection_delegate_request)
-        {
-            rec->AppCallback(rec->sdr, rec, cbh->cb_flags, cbh->cb_err, rec->AppContext);
-        }
-        else
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request");
-            rec->AppCallback(rec->sdr, rec, 0, kDNSServiceErr_Unknown, rec->AppContext);
-        }
-        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
-{
-    DNSServiceErrorType err;
-    uint8_t *ptr;
-    size_t len = 0;
-    ipc_msg_hdr *hdr;
-
-    if (!sdRef) return kDNSServiceErr_BadParam;
-    err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-#if   TARGET_OS_SIMULATOR // This hack is for Simulator platform only
-DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid)
-{
-    (void) pid;
-    (void) uuid;
-    return DNSServiceCreateConnection(sdRef);
-}
-#endif
-
-DNSServiceErrorType DNSServiceSendQueuedRequestsInternal(DNSServiceRef sdr)
-{
-    struct iovec *iov;
-    ssize_t totalLength = 0, bytesWritten;
-    uint32_t numMsg, i;
-    DNSRecordRef rref;
-    DNSServiceErrorType err = kDNSServiceErr_NoError;
-
-    if (!sdr)
-    {
-        syslog(LOG_WARNING, "DNSServiceSendQueuedRequestsInternal: !sdr");
-        return kDNSServiceErr_BadParam;
-    }
-    for (rref = sdr->rec, numMsg = 0; rref != NULL; rref = rref->recnext)
-    {
-        if(rref->msg)
-        {
-            numMsg++;
-            totalLength += rref->msg->datalen + sizeof(ipc_msg_hdr);
-        }
-    }
-    if (numMsg == 0)
-    {
-        syslog(LOG_INFO, "DNSServiceSendQueuedRequestsInternal: numMsg is 0");
-        return kDNSServiceErr_Invalid;
-    }
-    iov = mdns_malloc(numMsg * sizeof(*iov));
-    if (!iov)
-    {
-        return kDNSServiceErr_NoMemory;
-    }
-    for (rref = sdr->rec, i = 0; rref != NULL; rref = rref->recnext)
-    {
-        if(rref->msg)
-        {
-            uint32_t datalen = rref->msg->datalen;
-            ConvertHeaderBytes(rref->msg);
-            iov[i].iov_base = rref->msg;
-            iov[i].iov_len = datalen + sizeof(ipc_msg_hdr);
-            i++;
-        }
-    }
-    bytesWritten = writev(sdr->sockfd, iov, numMsg);
-    if (bytesWritten != totalLength)
-    {
-        syslog(LOG_WARNING,"DNSServiceSendQueuedRequestsInternal ERROR: writev(fd:%d, written:%zu, total:%zu bytes) failed, errno[%d]:%s",
-               sdr->sockfd, bytesWritten, totalLength, errno, strerror(errno));
-        err = kDNSServiceErr_Unknown;
-    }
-    else
-    {
-        syslog(LOG_INFO, "DNSServiceSendQueuedRequestsInternal: writev(fd:%d, numMsg:%d, %zu bytes) succeed",
-               sdr->sockfd, numMsg, totalLength);
-    }
-    for (rref = sdr->rec; rref != NULL; rref = rref->recnext)
-    {
-        mdns_free(rref->msg);
-    }
-    mdns_free(iov);
-    return err;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef *recordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    DNSServiceRegisterRecordReply callBack,
-    void *context
-)
-{
-    return DNSServiceRegisterRecordInternal(sdRef, recordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, NULL, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecordWithAttribute
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef *recordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    const DNSServiceAttributeRef attr,
-    DNSServiceRegisterRecordReply callBack,
-    void *context
-)
-{
-    return DNSServiceRegisterRecordInternal(sdRef, recordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, attr, callBack, context);
-}
-
-DNSServiceErrorType DNSServiceRegisterRecordInternal
- (
-    DNSServiceRef sdRef,
-    DNSRecordRef *RecordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    const DNSServiceAttribute *attr,
-    DNSServiceRegisterRecordReply callBack,
-    void *context
-)
-{
-    DNSServiceErrorType err;
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr = NULL;
-    DNSRecordRef rref = NULL;
-    DNSRecord **p;
-    (void)attr;
-
-    // Verify that only one of the following flags is set.
-    int f1 = (flags & kDNSServiceFlagsShared) != 0;
-    int f2 = (flags & kDNSServiceFlagsUnique) != 0;
-    int f3 = (flags & kDNSServiceFlagsKnownUnique) != 0;
-    if (f1 + f2 + f3 != 1) return kDNSServiceErr_BadParam;
-
-    if (!sdRef || !RecordRef || !fullname || (!rdata && rdlen) || !callBack)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL parameter");
-        return kDNSServiceErr_BadParam;
-    }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (sdRef->op != connection_request && sdRef->op != connection_delegate_request)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op);
-        return kDNSServiceErr_BadReference;
-    }
-
-    *RecordRef = NULL;
-
-    len = sizeof(DNSServiceFlags);
-    len += 2 * sizeof(uint32_t);  // interfaceIndex, ttl
-    len += 3 * sizeof(uint16_t);  // rrtype, rrclass, rdlen
-    len += strlen(fullname) + 1;
-    len += rdlen;
-    (void)attr;
-
-    // Bump up the uid. Normally for shared operations (kDNSServiceFlagsShareConnection), this
-    // is done in ConnectToServer. For DNSServiceRegisterRecord, ConnectToServer has already
-    // been called. As multiple DNSServiceRegisterRecords can be multiplexed over a single
-    // connection, we need a way to demultiplex the response so that the callback corresponding
-    // to the right DNSServiceRegisterRecord instance can be called. Use the same mechanism that
-    // is used by kDNSServiceFlagsShareConnection. create_hdr copies the uid value to ipc
-    // hdr->client_context which will be returned in the ipc response.
-    if (++sdRef->uid.u32[0] == 0)
-        ++sdRef->uid.u32[1];
-    //If kDNSServiceFlagsQueueRequest flag is set, do not make separate return socket.
-    hdr = create_hdr(reg_record_request, &len, &ptr, !(flags & kDNSServiceFlagsQueueRequest), sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(fullname, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-    if (flags & kDNSServiceFlagsQueueRequest)
-    {
-        hdr->ipc_flags |= IPC_FLAGS_NOERRSD;
-    }
-    rref = mdns_calloc(1, sizeof(*rref));
-    if (!rref) { mdns_free(hdr); return kDNSServiceErr_NoMemory; }
-    rref->AppContext = context;
-    rref->AppCallback = callBack;
-    rref->record_index = sdRef->max_index++;
-    rref->sdr = sdRef;
-    *RecordRef = rref;
-    // Remember the uid that we are sending across so that we can match
-    // when the response comes back.
-    rref->uid = sdRef->uid;
-    hdr->reg_index = rref->record_index;
-
-    p = &(sdRef)->rec;
-    while (*p) p = &(*p)->recnext;
-    *p = rref;
-    // If kDNSServiceFlagsQueueRequest flag is set, put the hdr in linked records
-    if (flags & kDNSServiceFlagsQueueRequest)
-    {
-        rref->msg = hdr;
-        err = kDNSServiceErr_NoError;
-    }
-    else
-    {
-        err = deliver_request(hdr, sdRef);     // Will free hdr for us
-        if (err == kDNSServiceErr_NoAuth && !_should_return_noauth_error())
-        {
-            err = kDNSServiceErr_NoError;
-        }
-    }
-    return err;
-}
-
-// sdRef returned by DNSServiceRegister()
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef    *RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rrtype,
-    uint16_t rdlen,
-    const void      *rdata,
-    uint32_t ttl
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    uint8_t *ptr;
-    DNSRecordRef rref;
-    DNSRecord **p;
-
-    if (!sdRef || !RecordRef || (!rdata && rdlen))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL parameter");
-        return kDNSServiceErr_BadParam;
-    }
-    if (sdRef->op != reg_service_request)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    *RecordRef = NULL;
-
-    len += 2 * sizeof(uint16_t);  // rrtype, rdlen
-    len += rdlen;
-    len += sizeof(uint32_t);
-    len += sizeof(DNSServiceFlags);
-
-    hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    put_flags(flags, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-
-    rref = mdns_calloc(1, sizeof(*rref));
-    if (!rref) { mdns_free(hdr); return kDNSServiceErr_NoMemory; }
-    rref->record_index = sdRef->max_index++;
-    rref->sdr = sdRef;
-    *RecordRef = rref;
-    hdr->reg_index = rref->record_index;
-
-    p = &(sdRef)->rec;
-    while (*p) p = &(*p)->recnext;
-    *p = rref;
-
-    return deliver_request(hdr, sdRef);     // Will free hdr for us
-}
-
-static DNSServiceErrorType DNSServiceUpdateRecordInternal
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef recordRef,
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    const DNSServiceAttributeRef attr
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    uint8_t *ptr;
-    const uint8_t *limit;
-
-    if (!sdRef || (!rdata && rdlen))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL parameter");
-        return kDNSServiceErr_BadParam;
-    }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    // Note: RecordRef is allowed to be NULL
-
-    len += sizeof(uint16_t);
-    len += rdlen;
-    len += sizeof(uint32_t);
-    len += sizeof(DNSServiceFlags);
-    if (attr)
-    {
-        len += get_required_tlv_length_for_service_attr(attr);
-    }
-
-    hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    // This function can update records added with DNSServiceRegisterRecord or DNSServiceAddRecord. In the
-    // former case, these records are added on a connection that was created using DNSServiceCreateConnection(), and so
-    // they don't have a subordinate request. In the latter case, they are added on a connection that was created with
-    // DNSServiceRegister(); if these are created with the kDNSServiceFlagsSharedConnection flag set, then they will have
-    // a subordinate operation.
-    // In the case where there is no subordinate operations, we need to send a UID of zero, to avoid matching any subordinate
-    // operation that might have the same UID as the primary connection (this will be the case if there is an outstanding
-    // subordinate request that hasn't been canceled). Failure to send a zero UID can result in this function
-    // having no effect. Refer to rdar://93274463
-    if (sdRef->primary == NULL)
-    {
-        hdr->client_context.u32[0] = 0;
-        hdr->client_context.u32[1] = 0;
-    }
-    hdr->reg_index = recordRef ? recordRef->record_index : TXT_RECORD_INDEX;
-    limit = ptr + len;
-    put_flags(flags, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-    if (attr)
-    {
-        put_tlvs_for_service_attr(attr, hdr, &ptr, limit);
-    }
-    return deliver_request(hdr, sdRef);     // Will free hdr for us
-}
-
-// DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef recordRef,
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl
-)
-{
-    return DNSServiceUpdateRecordInternal(sdRef, recordRef, flags, rdlen, rdata, ttl, NULL);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecordWithAttribute
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef recordRef,
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void *rdata,
-    uint32_t ttl,
-    const DNSServiceAttributeRef attr
-)
-{
-    return DNSServiceUpdateRecordInternal(sdRef, recordRef, flags, rdlen, rdata, ttl, attr);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    uint8_t *ptr;
-    DNSServiceErrorType err;
-
-    if (!sdRef)            { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-    if (!RecordRef)        { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef");  return kDNSServiceErr_BadParam; }
-    if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef");  return kDNSServiceErr_BadReference; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    len += sizeof(flags);
-    hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    // DNSServiceRemoveRecord can remove records added with DNSServiceRegisterRecord or DNSServiceAddRecord. In the
-    // former case, these records are added on a connection that was created using DNSServiceCreateConnection(), and so
-    // they don't have a subordinate request. In the latter case, they are added on a connection that was created with
-    // DNSServiceRegister(); if these are created with the kDNSServiceFlagsSharedConnection flag set, then they will have
-    // a subordinate operation.
-    // In the case where there is no subordinate operation, we need to send a UID of zero, to avoid matching any subordinate
-    // operation that might have the same UID as the primary connection (this will be the case if there is an outstanding
-    // subordinate request that hasn't been canceled). Failure to send a zero UID can result in the DNSServiceRemoveRecord
-    // having no effect.
-    if (sdRef->primary == NULL)
-    {
-        hdr->client_context.u32[0] = 0;
-        hdr->client_context.u32[1] = 0;
-    }
-    hdr->reg_index = RecordRef->record_index;
-    put_flags(flags, &ptr);
-    err = deliver_request(hdr, sdRef);      // Will free hdr for us
-    if (!err)
-    {
-        // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord.
-        // If so, delink from the list before freeing
-        DNSRecord **p = &sdRef->rec;
-        while (*p && *p != RecordRef) p = &(*p)->recnext;
-        if (*p) *p = RecordRef->recnext;
-        mdns_free(RecordRef->msg);
-        mdns_free(RecordRef);
-    }
-    return err;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-(
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char      *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void      *rdata
-)
-{
-    DNSServiceErrorType err;
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp = NULL;
-
-    if (!fullname || (!rdata && rdlen)) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);
-    len += strlen(fullname) + 1;
-    len += 3 * sizeof(uint16_t);
-    len += rdlen;
-    hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(fullname, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    DNSServiceRefDeallocate(tmp);
-    return err;
-}
-
-
-static void handle_port_mapping_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const uint8_t *data, const uint8_t *const end)
-{
-    union { uint32_t l; u_char b[4]; } addr;
-    uint8_t protocol;
-    union { uint16_t s; u_char b[2]; } internalPort;
-    union { uint16_t s; u_char b[2]; } externalPort;
-    uint32_t ttl;
-
-    if (!data || data + 13 > end) goto fail;
-
-    addr.b[0] = *data++;
-    addr.b[1] = *data++;
-    addr.b[2] = *data++;
-    addr.b[3] = *data++;
-    protocol          = *data++;
-    internalPort.b[0] = *data++;
-    internalPort.b[1] = *data++;
-    externalPort.b[0] = *data++;
-    externalPort.b[1] = *data++;
-    ttl               = get_uint32(&data, end);
-    if (!data) goto fail;
-
-    ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
-    return;
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-
-    fail :
-    syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    uint32_t protocol,                                /* TCP and/or UDP */
-    uint16_t internalPortInNetworkByteOrder,
-    uint16_t externalPortInNetworkByteOrder,
-    uint32_t ttl,                                     /* time to live in seconds */
-    DNSServiceNATPortMappingReply callBack,
-    void                                *context      /* may be NULL */
-)
-{
-    uint8_t *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder };
-    union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder };
-
-    DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, (void *)callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += sizeof(protocol);
-    len += sizeof(internalPort);
-    len += sizeof(externalPort);
-    len += sizeof(ttl);
-
-    hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_uint32(protocol, &ptr);
-    *ptr++ = internalPort.b[0];
-    *ptr++ = internalPort.b[1];
-    *ptr++ = externalPort.b[0];
-    *ptr++ = externalPort.b[1];
-    put_uint32(ttl, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-#if _DNS_SD_LIBDISPATCH
-DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
-(
-    DNSServiceRef service,
-    dispatch_queue_t queue
-)
-{
-    int dnssd_fd  = DNSServiceRefSockFD(service);
-    if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam;
-    if (!queue)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL");
-        return kDNSServiceErr_BadParam;
-    }
-    if (service->disp_queue)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already");
-        return kDNSServiceErr_BadParam;
-    }
-    if (service->disp_source)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch source set already");
-        return kDNSServiceErr_BadParam;
-    }
-    service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue);
-    if (!service->disp_source)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch_source_create failed");
-        return kDNSServiceErr_NoMemory;
-    }
-    service->disp_queue = queue;
-    dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);});
-    dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);});
-    dispatch_resume(service->disp_source);
-    return kDNSServiceErr_NoError;
-}
-#endif // _DNS_SD_LIBDISPATCH
-
-#if !defined(_WIN32)
-
-static void DNSSD_API SleepKeepaliveCallback(DNSServiceRef sdRef, DNSRecordRef rec, const DNSServiceFlags flags,
-                                             DNSServiceErrorType errorCode, void *context)
-{
-    SleepKAContext *ka = (SleepKAContext *)context;
-    (void)rec;      // Unused
-    (void)flags;    // Unused
-
-    if (sdRef->kacontext != context)
-        syslog(LOG_WARNING, "dnssd_clientstub SleepKeepaliveCallback context mismatch");
-
-    if (ka->AppCallback)
-        ((DNSServiceSleepKeepaliveReply)ka->AppCallback)(sdRef, errorCode, ka->AppContext);
-}
-
-static DNSServiceErrorType _DNSServiceSleepKeepalive_sockaddr
-(
-    DNSServiceRef *                 sdRef,
-    DNSServiceFlags                 flags,
-    const struct sockaddr *         localAddr,
-    const struct sockaddr *         remoteAddr,
-    unsigned int                    timeout,
-    DNSServiceSleepKeepaliveReply   callBack,
-    void *                          context
-);
-
-DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    int fd,
-    unsigned int timeout,
-    DNSServiceSleepKeepaliveReply callBack,
-    void                                *context
-)
-{
-    struct sockaddr_storage lss;
-    struct sockaddr_storage rss;
-    socklen_t len1, len2;
-
-    len1 = sizeof(lss);
-    if (getsockname(fd, (struct sockaddr *)&lss, &len1) < 0)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive: getsockname %d\n", errno);
-        return kDNSServiceErr_BadParam;
-    }
-
-    len2 = sizeof(rss);
-    if (getpeername(fd, (struct sockaddr *)&rss, &len2) < 0)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive: getpeername %d\n", errno);
-        return kDNSServiceErr_BadParam;
-    }
-
-    if (len1 != len2)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive local/remote info not same");
-        return kDNSServiceErr_Unknown;
-    }
-    return _DNSServiceSleepKeepalive_sockaddr(sdRef, flags, (const struct sockaddr *)&lss, (const struct sockaddr *)&rss,
-        timeout, callBack, context);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive_sockaddr
-(
-    DNSServiceRef *                 sdRef,
-    DNSServiceFlags                 flags,
-    const struct sockaddr *         localAddr,
-    const struct sockaddr *         remoteAddr,
-    unsigned int                    timeout,
-    DNSServiceSleepKeepaliveReply   callBack,
-    void *                          context
-)
-{
-    return _DNSServiceSleepKeepalive_sockaddr(sdRef, flags, localAddr, remoteAddr, timeout, callBack, context );
-}
-
-static DNSServiceErrorType _DNSServiceSleepKeepalive_sockaddr
-(
-    DNSServiceRef *                 sdRef,
-    DNSServiceFlags                 flags,
-    const struct sockaddr *         localAddr,
-    const struct sockaddr *         remoteAddr,
-    unsigned int                    timeout,
-    DNSServiceSleepKeepaliveReply   callBack,
-    void *                          context
-)
-{
-    char source_str[INET6_ADDRSTRLEN];
-    char target_str[INET6_ADDRSTRLEN];
-    unsigned int len, proxyreclen;
-    char buf[256];
-    DNSServiceErrorType err;
-    DNSRecordRef record = NULL;
-    char name[10];
-    char recname[128];
-    SleepKAContext *ka;
-    unsigned int i, unique;
-
-    (void) flags; //unused
-    if (!timeout) return kDNSServiceErr_BadParam;
-
-    unique = 0;
-    if ((localAddr->sa_family == AF_INET) && (remoteAddr->sa_family == AF_INET))
-    {
-        const struct sockaddr_in *sl = (const struct sockaddr_in *)localAddr;
-        const struct sockaddr_in *sr = (const struct sockaddr_in *)remoteAddr;
-        const unsigned char *ptr = (const unsigned char *)&sl->sin_addr;
-
-        if (!inet_ntop(AF_INET, (const void *)&sr->sin_addr, target_str, sizeof (target_str)))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive remote info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        if (!inet_ntop(AF_INET, (const void *)&sl->sin_addr, source_str, sizeof (source_str)))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive local info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        // Sum of all bytes in the local address and port should result in a unique
-        // number in the local network
-        for (i = 0; i < sizeof(struct in_addr); i++)
-            unique += ptr[i];
-        unique += sl->sin_port;
-        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u h=%s d=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl->sin_port), ntohs(sr->sin_port));
-    }
-    else if ((localAddr->sa_family == AF_INET6) && (remoteAddr->sa_family == AF_INET6))
-    {
-        const struct sockaddr_in6 *sl6 = (const struct sockaddr_in6 *)localAddr;
-        const struct sockaddr_in6 *sr6 = (const struct sockaddr_in6 *)remoteAddr;
-        const unsigned char *ptr = (const unsigned char *)&sl6->sin6_addr;
-
-        if (!inet_ntop(AF_INET6, (const void *)&sr6->sin6_addr, target_str, sizeof (target_str)))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive remote6 info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        if (!inet_ntop(AF_INET6, (const void *)&sl6->sin6_addr, source_str, sizeof (source_str)))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive local6 info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        for (i = 0; i < sizeof(struct in6_addr); i++)
-            unique += ptr[i];
-        unique += sl6->sin6_port;
-        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u H=%s D=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl6->sin6_port), ntohs(sr6->sin6_port));
-    }
-    else
-    {
-        return kDNSServiceErr_BadParam;
-    }
-
-    if (len >= (sizeof(buf) - 1))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive could not fit local/remote info");
-        return kDNSServiceErr_Unknown;
-    }
-    // Include the NULL byte also in the first byte. The total length of the record includes the
-    // first byte also.
-    buf[0] = len + 1;
-    proxyreclen = len + 2;
-
-    len = snprintf(name, sizeof(name), "%u", unique);
-    if (len >= sizeof(name))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive could not fit unique");
-        return kDNSServiceErr_Unknown;
-    }
-
-    len = snprintf(recname, sizeof(recname), "%s.%s", name, "_keepalive._dns-sd._udp.local");
-    if (len >= sizeof(recname))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive could not fit name");
-        return kDNSServiceErr_Unknown;
-    }
-
-    ka = mdns_malloc(sizeof(SleepKAContext));
-    if (!ka) return kDNSServiceErr_NoMemory;
-    ka->AppCallback = (DNSServiceSleepKeepaliveReply*)callBack;
-    ka->AppContext = context;
-
-    err = DNSServiceCreateConnection(sdRef);
-    if (err)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive cannot create connection");
-        mdns_free(ka);
-        return err;
-    }
-
-    // we don't care about the "record". When sdRef gets deallocated later, it will be freed too
-    err = DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, 0, recname,
-                                   kDNSServiceType_NULL,  kDNSServiceClass_IN, proxyreclen, buf,  kDNSServiceInterfaceIndexAny, SleepKeepaliveCallback, ka);
-    if (err)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSleepKeepalive cannot create connection");
-        mdns_free(ka);
-        return err;
-    }
-    (*sdRef)->kacontext = ka;
-    return kDNSServiceErr_NoError;
-}
-#endif
diff --git a/mDNSShared/dnssd_clientstub.h b/mDNSShared/dnssd_clientstub.h
deleted file mode 100644
index 9b0dad8..0000000
--- a/mDNSShared/dnssd_clientstub.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dns_sd.h"
-#include "dnssd_ipc.h"
-
-DNSServiceErrorType
-DNSServiceBrowseInternal(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype,
-    const char *domain, const DNSServiceAttribute *attr, DNSServiceBrowseReply callBack, void *context);
-
-DNSServiceErrorType
-DNSServiceResolveInternal(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name,
-    const char *regtype, const char *domain, const DNSServiceAttribute *attr, DNSServiceResolveReply callBack,
-    void *context);
-
-DNSServiceErrorType
-DNSServiceGetAddrInfoInternal(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
-    DNSServiceProtocol protocol, const char *hostname, const DNSServiceAttribute *attr, DNSServiceGetAddrInfoReply callBack,
-    void *context);
-
-DNSServiceErrorType
-DNSServiceQueryRecordInternal(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name,
-    uint16_t rrtype, uint16_t rrclass, const DNSServiceAttribute *attr, const DNSServiceQueryRecordReply callback,
-    void *context);
-
-DNSServiceErrorType
-DNSServiceRegisterInternal(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name,
-    const char *regtype, const char *domain, const char *host, uint16_t portInNetworkByteOrder, uint16_t txtLen,
-    const void *txtRecord, const DNSServiceAttribute *attr, DNSServiceRegisterReply callBack, void *context);
-
-DNSServiceErrorType
-DNSServiceRegisterRecordInternal(DNSServiceRef sdRef, DNSRecordRef *recordRef, DNSServiceFlags flags,
-    uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
-    const void *rdata, uint32_t ttl, const DNSServiceAttribute *attr, DNSServiceRegisterRecordReply callBack,
-    void *context);
-
-DNSServiceErrorType
-DNSServiceSendQueuedRequestsInternal(DNSServiceRef sdr);
-
-size_t
-get_required_tlv_length_for_service_attr(const DNSServiceAttribute *attr);
-
-void
-put_tlvs_for_service_attr(const DNSServiceAttribute *attr, ipc_msg_hdr *hdr, uint8_t **ptr, const uint8_t *limit);
diff --git a/mDNSShared/dnssd_errstring.c b/mDNSShared/dnssd_errstring.c
deleted file mode 100644
index e3c7fea..0000000
--- a/mDNSShared/dnssd_errstring.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "dns_sd_private.h"
-#include "mdns_strict.h"
-
-const char * DNSSD_API
-DNSServiceErrorCodeToString(DNSServiceErrorType error_code)
-{
-#define CASE_TO_STR(s) case kDNSServiceErr_ ## s: return (#s);
-	switch (error_code) {
-		CASE_TO_STR(NoError)
-		CASE_TO_STR(Unknown)
-		CASE_TO_STR(NoSuchName)
-		CASE_TO_STR(NoMemory)
-		CASE_TO_STR(BadParam)
-		CASE_TO_STR(BadReference)
-		CASE_TO_STR(BadState)
-		CASE_TO_STR(BadFlags)
-		CASE_TO_STR(Unsupported)
-		CASE_TO_STR(NotInitialized)
-		CASE_TO_STR(AlreadyRegistered)
-		CASE_TO_STR(NameConflict)
-		CASE_TO_STR(Invalid)
-		CASE_TO_STR(Firewall)
-		CASE_TO_STR(Incompatible)
-		CASE_TO_STR(BadInterfaceIndex)
-		CASE_TO_STR(Refused)
-		CASE_TO_STR(NoSuchRecord)
-		CASE_TO_STR(NoAuth)
-		CASE_TO_STR(NoSuchKey)
-		CASE_TO_STR(NATTraversal)
-		CASE_TO_STR(DoubleNAT)
-		CASE_TO_STR(BadTime)
-		CASE_TO_STR(BadSig)
-		CASE_TO_STR(BadKey)
-		CASE_TO_STR(Transient)
-		CASE_TO_STR(ServiceNotRunning)
-		CASE_TO_STR(NATPortMappingUnsupported)
-		CASE_TO_STR(NATPortMappingDisabled)
-		CASE_TO_STR(NoRouter)
-		CASE_TO_STR(PollingMode)
-		CASE_TO_STR(Timeout)
-		CASE_TO_STR(DefunctConnection)
-		CASE_TO_STR(PolicyDenied)
-		CASE_TO_STR(NotPermitted)
-	}
-	return "<INVALID ERROR CODE>";
-#undef CASE_TO_STR
-}
-
diff --git a/mDNSShared/dnssd_ipc.c b/mDNSShared/dnssd_ipc.c
deleted file mode 100644
index 2f91f8b..0000000
--- a/mDNSShared/dnssd_ipc.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2003-2021 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dnssd_ipc.h"
-#include "mdns_strict.h"
-
-#if defined(_WIN32)
-
-char *win32_strerror(int inErrorCode)
-{
-    static char buffer[1024];
-    DWORD n;
-    memset(buffer, 0, sizeof(buffer));
-    n = FormatMessageA(
-        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-        NULL,
-        (DWORD) inErrorCode,
-        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-        buffer,
-        sizeof(buffer),
-        NULL);
-    if (n > 0)
-    {
-        // Remove any trailing CR's or LF's since some messages have them.
-        while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
-            buffer[--n] = '\0';
-    }
-    return buffer;
-}
-
-#endif
-
-static uint8_t *_write_big32(uint8_t *ptr, const uint32_t u32)
-{
-    *ptr++ = (uint8_t)((u32 >> 24) & 0xFF);
-    *ptr++ = (uint8_t)((u32 >> 16) & 0xFF);
-    *ptr++ = (uint8_t)((u32 >>  8) & 0xFF);
-    *ptr++ = (uint8_t)( u32        & 0xFF);
-    return ptr;
-}
-
-void put_uint32(const uint32_t u32, uint8_t **const ptr)
-{
-    *ptr = _write_big32(*ptr, u32);
-}
-
-#define _assign_null_safe(PTR, VALUE) \
-    do \
-    { \
-        if ((PTR)) \
-        { \
-            *(PTR) = (VALUE); \
-        } \
-    } while (0)
-
-static uint32_t _read_big32(const uint8_t *ptr, const uint8_t **const out_end)
-{
-    uint32_t u32 = 0;
-    u32 |= ((uint32_t)*ptr++) << 24;
-    u32 |= ((uint32_t)*ptr++) << 16;
-    u32 |= ((uint32_t)*ptr++) <<  8;
-    u32 |= ((uint32_t)*ptr++);
-    _assign_null_safe(out_end, ptr);
-    return u32;
-}
-
-uint32_t get_uint32(const uint8_t **const ptr, const uint8_t *const end)
-{
-    if (!*ptr || *ptr + sizeof(uint32_t) > end)
-    {
-        *ptr = NULL;
-        return(0);
-    }
-    else
-    {
-        return _read_big32(*ptr, ptr);
-    }
-}
-
-static uint8_t *_write_big16(uint8_t *ptr, const uint16_t u16)
-{
-    *ptr++ = (uint8_t)((u16 >> 8) & 0xFF);
-    *ptr++ = (uint8_t)( u16       & 0xFF);
-    return ptr;
-}
-
-void put_uint16(const uint16_t u16, uint8_t **const ptr)
-{
-    *ptr = _write_big16(*ptr, u16);
-}
-
-static uint16_t _read_big16(const uint8_t *ptr, const uint8_t **const out_end)
-{
-    uint16_t u16 = 0;
-    u16 |= ((uint16_t)*ptr++) << 8;
-    u16 |= ((uint16_t)*ptr++);
-    _assign_null_safe(out_end, ptr);
-    return u16;
-}
-
-uint16_t get_uint16(const uint8_t **ptr, const uint8_t *const end)
-{
-    if (!*ptr || *ptr + sizeof(uint16_t) > end)
-    {
-        *ptr = NULL;
-        return(0);
-    }
-    else
-    {
-        return _read_big16(*ptr, ptr);
-    }
-}
-
-int put_string(const char *str, uint8_t **const ptr)
-{
-    size_t len;
-    if (!str) str = "";
-    len = strlen(str) + 1;
-    memcpy(*ptr, str, len);
-    *ptr += len;
-    return 0;
-}
-
-int get_string(const uint8_t **const ptr, const uint8_t *const end, char *buffer, size_t buflen)
-{
-    if (!*ptr)
-    {
-        *buffer = 0;
-        return(-1);
-    }
-    else
-    {
-        const char *const lim = buffer + buflen;    // Calculate limit
-        while (*ptr < end && buffer < lim)
-        {
-            const uint8_t c = *(*ptr)++;
-            *buffer++ = (char)c;
-            if (c == 0) return(0);      // Success
-        }
-        if (buffer == lim) buffer--;
-        *buffer = 0;                    // Failed, so terminate string,
-        *ptr = NULL;                    // clear pointer,
-        return(-1);                     // and return failure indication
-    }
-}
-
-void put_rdata(const size_t rdlen, const uint8_t *const rdata, uint8_t **const ptr)
-{
-    memcpy(*ptr, rdata, rdlen);
-    *ptr += rdlen;
-}
-
-const uint8_t *get_rdata(const uint8_t **const ptr, const uint8_t *const end, int rdlen)
-{
-    if (!*ptr || *ptr + rdlen > end)
-    {
-        *ptr = NULL;
-        return(0);
-    }
-    else
-    {
-        const uint8_t *const rd = *ptr;
-        *ptr += rdlen;
-        return rd;
-    }
-}
-
-#define IPC_TLV16_OVERHEAD_LENGTH (2 + 2) // 2 bytes for 16-bit type + 2 bytes for 16-bit length
-
-size_t get_required_tlv_length(const uint16_t value_length)
-{
-    return (IPC_TLV16_OVERHEAD_LENGTH + value_length);
-}
-
-size_t get_required_tlv_uint8_length(void)
-{
-    return (IPC_TLV16_OVERHEAD_LENGTH + 1);
-}
-
-size_t get_required_tlv_uint32_length(void)
-{
-    return (IPC_TLV16_OVERHEAD_LENGTH + 4);
-}
-
-static int _tlv16_set(uint8_t *const dst, const uint8_t *const limit, const uint16_t type, const uint16_t length,
-    const uint8_t *const value, uint8_t **const out_end)
-{
-    if ((limit - dst) < (IPC_TLV16_OVERHEAD_LENGTH + length))
-    {
-        return -1;
-    }
-    uint8_t *ptr = dst;
-    ptr = _write_big16(ptr, type);
-    ptr = _write_big16(ptr, length);
-    if (length > 0)
-    {
-        memcpy(ptr, value, length);
-        ptr += length;
-    }
-    _assign_null_safe(out_end, ptr);
-    return 0;
-}
-
-void put_tlv(const uint16_t type, const uint16_t length, const uint8_t *const value, uint8_t **const ptr,
-    const uint8_t *const limit)
-{
-    uint8_t *dst = *ptr;
-    if (_tlv16_set(dst, limit, type, length, value, &dst) == 0)
-    {
-        *ptr = dst;
-    }
-}
-
-void put_tlv_uint8(const uint16_t type, const uint8_t u8, uint8_t **const ptr, const uint8_t *const limit)
-{
-    put_tlv(type, sizeof(u8), &u8, ptr, limit);
-}
-
-void put_tlv_uint16(const uint16_t type, const uint16_t u16, uint8_t **const ptr, const uint8_t *const limit)
-{
-    uint8_t value[2];
-    _write_big16(value, u16);
-    put_tlv(type, sizeof(value), value, ptr, limit);
-}
-
-void put_tlv_uint32(const uint16_t type, const uint32_t u32, uint8_t **const ptr, const uint8_t *const limit)
-{
-    uint8_t value[4];
-    _write_big32(value, u32);
-    put_tlv(type, sizeof(value), value, ptr, limit);
-}
-
-static const uint8_t *_tlv16_get_next(const uint8_t *ptr, const uint8_t *const end, uint16_t *const out_type,
-    size_t *const out_length, const uint8_t **const out_ptr)
-{
-    if ((end - ptr) >= IPC_TLV16_OVERHEAD_LENGTH)
-    {
-        const uint16_t type   = _read_big16(ptr, &ptr);
-        const uint16_t length = _read_big16(ptr, &ptr);
-        const uint8_t *const value = ptr;
-        if ((end - value) >= length)
-        {
-            ptr += length;
-            _assign_null_safe(out_type, type);
-            _assign_null_safe(out_length, length);
-            _assign_null_safe(out_ptr, ptr);
-            return value;
-        }
-    }
-    return NULL;
-}
-
-static const uint8_t *_tlv16_get_value(const uint8_t *const start, const uint8_t *const end, const uint16_t desired_type,
-    size_t *const out_length, const uint8_t **const out_ptr)
-{
-    const uint8_t *ptr = start;
-    uint16_t type;
-    size_t length;
-    const uint8_t *value;
-    while ((value = _tlv16_get_next(ptr, end, &type, &length, &ptr)) != NULL)
-    {
-        if (type == desired_type)
-        {
-            _assign_null_safe(out_length, length);
-            _assign_null_safe(out_ptr, ptr);
-            break;
-        }
-    }
-    return value;
-}
-
-const uint8_t *get_tlv(const uint8_t *const start, const uint8_t *const end, const uint16_t type, size_t *const out_length)
-{
-    return _tlv16_get_value(start, end, type, out_length, NULL);
-}
-
-uint32_t get_tlv_uint32(const uint8_t *const start, const uint8_t *const end, const uint16_t type, int *const out_error)
-{
-    size_t length;
-    const uint8_t *value;
-    int err = -1;
-    uint32_t u32 = 0;
-    if ((value = _tlv16_get_value(start, end, type, &length, NULL)) != NULL)
-    {
-        switch (length)
-        {
-            case 1:
-                u32 = *value;
-                err = 0;
-                break;
-            case 2:
-                u32 = _read_big16(value, NULL);
-                err = 0;
-                break;
-            case 4:
-                u32 = _read_big32(value, NULL);
-                err = 0;
-                break;
-        }
-    }
-    _assign_null_safe(out_error, err);
-    return u32;
-}
-
-void ConvertHeaderBytes(ipc_msg_hdr *hdr)
-{
-    hdr->version   = htonl(hdr->version);
-    hdr->datalen   = htonl(hdr->datalen);
-    hdr->ipc_flags = htonl(hdr->ipc_flags);
-    hdr->op        = htonl(hdr->op );
-    hdr->reg_index = htonl(hdr->reg_index);
-}
diff --git a/mDNSShared/dnssd_ipc.h b/mDNSShared/dnssd_ipc.h
deleted file mode 100644
index 0f0b6ad..0000000
--- a/mDNSShared/dnssd_ipc.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2022 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DNSSD_IPC_H
-#define DNSSD_IPC_H
-
-#include "dns_sd.h"
-
-//
-// Common cross platform services
-//
-#if defined(WIN32)
-#   include <winsock2.h>
-#   define dnssd_InvalidSocket  INVALID_SOCKET
-#   define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
-#   define dnssd_EWOULDBLOCK    WSAEWOULDBLOCK
-#   define dnssd_EINTR          WSAEINTR
-#   define dnssd_ECONNRESET     WSAECONNRESET
-#   define dnssd_socklen_t      int
-#   define dnssd_close(sock)    closesocket(sock)
-#   define dnssd_errno          WSAGetLastError()
-#   define dnssd_strerror(X)    win32_strerror(X)
-#   define ssize_t              int
-#   define getpid               _getpid
-#   define unlink               _unlink
-extern char *win32_strerror(int inErrorCode);
-#else
-#   include <sys/types.h>
-#   include <unistd.h>
-#   include <sys/un.h>
-#   include <string.h>
-#   include <stdio.h>
-#   include <stdlib.h>
-#   include <sys/stat.h>
-#   include <sys/socket.h>
-#   include <netinet/in.h>
-#   include <arpa/inet.h>
-#   define dnssd_InvalidSocket  -1
-#   define dnssd_SocketValid(s) ((s) >= 0)
-#   define dnssd_EWOULDBLOCK    EWOULDBLOCK
-#   define dnssd_EINTR          EINTR
-#   define dnssd_ECONNRESET     ECONNRESET
-#   define dnssd_EPIPE          EPIPE
-#   define dnssd_socklen_t      unsigned int
-#   define dnssd_close(sock)    close(sock)
-#   define dnssd_errno          errno
-#   define dnssd_strerror(X)    strerror(X)
-#endif
-
-#if defined(USE_TCP_LOOPBACK)
-#   define AF_DNSSD             AF_INET
-#   define MDNS_TCP_SERVERADDR  "127.0.0.1"
-#ifdef WIN32_CENTENNIAL
-#   define MDNS_TCP_SERVERPORT_CENTENNIAL  53545
-#endif
-#   define MDNS_TCP_SERVERPORT  5354
-#   define LISTENQ              5
-#   define dnssd_sockaddr_t     struct sockaddr_in
-#else
-#   define AF_DNSSD             AF_LOCAL
-#   ifndef MDNS_UDS_SERVERPATH
-#       define MDNS_UDS_SERVERPATH  "/var/run/mDNSResponder"
-#   endif
-#   define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH"
-#   define LISTENQ              100
-// longest legal control path length
-#   define MAX_CTLPATH          (sizeof(((struct sockaddr_un*)0)->sun_path))
-#   define dnssd_sockaddr_t     struct sockaddr_un
-#endif
-
-// Compatibility workaround
-#ifndef AF_LOCAL
-#define AF_LOCAL    AF_UNIX
-#endif
-
-// General UDS constants
-#define TXT_RECORD_INDEX ((uint32_t)(-1))   // record index for default text record
-
-// IPC data encoding constants and types
-#define VERSION 1
-#define IPC_FLAGS_NOREPLY       (1U << 0) // Set flag if no asynchronous replies are to be sent to client.
-#define IPC_FLAGS_TRAILING_TLVS (1U << 1) // Set flag if TLVs follow the standard request data.
-#define IPC_FLAGS_NOERRSD       (1U << 2) // Set flag if flag kDNSServiceFlagsMoreComing is set on client side.
-
-#define IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA     1 // An nw_resolver_config as a binary property list.
-#define IPC_TLV_TYPE_REQUIRE_PRIVACY                2 // A uint8. Non-zero means privacy required, zero means not required.
-#define IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY       3 // A uint32 for a DNSServiceAAAAPolicy value.
-#define IPC_TLV_TYPE_SERVICE_ATTR_FAILOVER_POLICY   4 // A uint32 for a DNSServiceFailoverPolicy value.
-#define IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP         5 // A uint32 value for the time, in seconds, since Jan 1st 1970 UTC.
-#define IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_POLICY 6 // A uint32 for a DNSServiceValidationPolicy value.
-#define IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA   7 // Validation data.
-
-// 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, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
-#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
-
-typedef enum
-{
-    request_op_none = 0,    // No request yet received on this connection
-    connection_request = 1, // connected socket via DNSServiceConnect()
-    reg_record_request,     // reg/remove record only valid for connected sockets
-    remove_record_request,
-    enumeration_request,
-    reg_service_request,
-    browse_request,
-    resolve_request,
-    query_request,
-    reconfirm_record_request,
-    add_record_request,
-    update_record_request,
-    setdomain_request,      // Up to here is in Tiger and B4W 1.0.3
-    getproperty_request,    // New in B4W 1.0.4
-    port_mapping_request,   // New in Leopard and B4W 2.0
-    addrinfo_request,
-    send_bpf,               // New in SL
-    getpid_request,
-    release_request,
-    connection_delegate_request,
-
-    cancel_request = 63
-} request_op_t;
-
-typedef enum
-{
-    enumeration_reply_op = 64,
-    reg_service_reply_op,
-    browse_reply_op,
-    resolve_reply_op,
-    query_reply_op,
-    reg_record_reply_op,    // Up to here is in Tiger and B4W 1.0.3
-    getproperty_reply_op,   // New in B4W 1.0.4
-    port_mapping_reply_op,  // New in Leopard and B4W 2.0
-    addrinfo_reply_op,
-    async_error_op
-} reply_op_t;
-
-#if defined(_WIN64)
-#   pragma pack(push,4)
-#endif
-
-// Define context object big enough to hold a 64-bit pointer,
-// to accomodate 64-bit clients communicating with 32-bit daemon.
-// There's no reason for the daemon to ever be a 64-bit process, but its clients might be
-typedef packedunion
-{
-    void *context;
-    uint32_t u32[2];
-} client_context_t;
-
-typedef packedstruct
-{
-    uint32_t version;
-    uint32_t datalen;
-    uint32_t ipc_flags;
-    uint32_t op;        // request_op_t or reply_op_t
-    client_context_t client_context; // context passed from client, returned by server in corresponding reply
-    uint32_t reg_index;            // identifier for a record registered via DNSServiceRegisterRecord() on a
-    // socket connected by DNSServiceCreateConnection().  Must be unique in the scope of the connection, such that and
-    // index/socket pair uniquely identifies a record.  (Used to select records for removal by DNSServiceRemoveRecord())
-} ipc_msg_hdr;
-
-#if defined(_WIN64)
-#   pragma pack(pop)
-#endif
-
-// routines to write to and extract data from message buffers.
-// caller responsible for bounds checking.
-// ptr is the address of the pointer to the start of the field.
-// it is advanced to point to the next field, or the end of the message
-
-void put_uint32(const uint32_t l, uint8_t **ptr);
-uint32_t get_uint32(const uint8_t **ptr, const uint8_t *end);
-
-void put_uint16(uint16_t s, uint8_t **ptr);
-uint16_t get_uint16(const uint8_t **ptr, const uint8_t *end);
-
-#define put_flags put_uint32
-#define get_flags get_uint32
-
-#define put_error_code put_uint32
-#define get_error_code get_uint32
-
-int put_string(const char *str, uint8_t **ptr);
-int get_string(const uint8_t **ptr, const uint8_t *end, char *buffer, size_t buflen);
-
-void put_rdata(const size_t rdlen, const uint8_t *rdata, uint8_t **ptr);
-const uint8_t *get_rdata(const uint8_t **ptr, const uint8_t *end, int rdlen);  // return value is rdata pointed to by *ptr -
-// rdata is not copied from buffer.
-
-size_t get_required_tlv_length(uint16_t value_length);
-size_t get_required_tlv_uint8_length(void);
-size_t get_required_tlv_uint32_length(void);
-void put_tlv(uint16_t type, uint16_t length, const uint8_t *value, uint8_t **ptr, const uint8_t *limit);
-void put_tlv_uint8(uint16_t type, uint8_t u8, uint8_t **ptr, const uint8_t *limit);
-void put_tlv_uint16(uint16_t type, uint16_t u16, uint8_t **ptr, const uint8_t *limit);
-void put_tlv_uint32(uint16_t type, uint32_t u32, uint8_t **ptr, const uint8_t *limit);
-const uint8_t *get_tlv(const uint8_t *src, const uint8_t *end, uint16_t type, size_t *out_length);
-uint32_t get_tlv_uint32(const uint8_t *src, const uint8_t *end, uint16_t type, int *out_error);
-
-void ConvertHeaderBytes(ipc_msg_hdr *hdr);
-
-struct CompileTimeAssertionChecks_dnssd_ipc
-{
-    // 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(client_context_t) ==  8) ? 1 : -1];
-    char assert1[(sizeof(ipc_msg_hdr)      == 28) ? 1 : -1];
-};
-
-#endif // DNSSD_IPC_H
diff --git a/mDNSShared/mDNSDebug.c b/mDNSShared/mDNSDebug.c
deleted file mode 100644
index 0db02f2..0000000
--- a/mDNSShared/mDNSDebug.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2003-2021 Apple 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
- *
- *     https://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.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#if defined(WIN32) || defined(EFI32) || defined(EFI64) || defined(EFIX64)
-// Need to add Windows/EFI syslog support here
-#define LOG_PID 0x01
-#define LOG_CONS 0x02
-#define LOG_PERROR 0x20
-#else
-#include <syslog.h>
-#endif
-
-#include "mDNSEmbeddedAPI.h"
-#include "mdns_strict.h"
-
-mDNSexport int mDNS_LoggingEnabled       = 0;
-mDNSexport int mDNS_PacketLoggingEnabled = 0;
-mDNSexport int mDNS_McastLoggingEnabled  = 0;
-mDNSexport int mDNS_McastTracingEnabled  = 0;
-
-#if MDNS_DEBUGMSGS && defined(__APPLE__)
-mDNSexport int mDNS_DebugMode = mDNStrue;
-#else
-mDNSexport int mDNS_DebugMode = mDNSfalse;
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-mDNSexport int gNumOfPrivateLogRedactionEnabledQueries = 0;
-mDNSexport int gPrivateLogRedactionEnabled = 0;
-#endif
-
-// 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
-#if MDNS_DEBUGMSGS > 1
-mDNSexport void verbosedebugf_(const char *format, ...)
-{
-    char buffer[512];
-    va_list args;
-    va_start(args, format);
-    mDNS_vsnprintf(buffer, sizeof(buffer), format, args);
-    va_end(args);
-    mDNSPlatformWriteDebugMsg(buffer);
-}
-#endif
-
-// Log message with default "mDNSResponder" ident string at the start
-#if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
-mDNSlocal void LogMsgWithLevelv(os_log_t category, os_log_type_t level, const char *format, va_list args)
-{
-    char buffer[512];
-    mDNS_vsnprintf(buffer, (mDNSu32)sizeof(buffer), format, args);
-    os_log_with_type(category ? category : mDNSLogCategory_Default, level, "%{private}s", buffer);
-}
-#else
-mDNSlocal void LogMsgWithLevelv(const char *category, mDNSLogLevel_t level, const char *format, va_list args)
-{
-    // Do not print the logs if the log category is MDNS_LOG_CATEGORY_DISABLED.
-    if (strcmp(category, MDNS_LOG_CATEGORY_DISABLED) == 0)
-    {
-        return;
-    }
-
-    char buffer[512];
-    char *dst = buffer;
-    const char *const lim = &buffer[512];
-    if (category) mDNS_snprintf_add(&dst, lim, "%s: ", category);
-    mDNS_vsnprintf(dst, (mDNSu32)(lim - dst), format, args);
-    mDNSPlatformWriteLogMsg(ProgramName, buffer, level);
-}
-#endif
-
-#define LOG_HELPER_BODY(CATEGORY, LEVEL) \
-    { \
-        va_list args; \
-        va_start(args,format); \
-        LogMsgWithLevelv(CATEGORY, LEVEL, format, args); \
-        va_end(args); \
-    }
-
-// see mDNSDebug.h
-#if !MDNS_HAS_VA_ARG_MACROS
-void LogMsg_(const char *format, ...)       LOG_HELPER_BODY(NULL, MDNS_LOG_DEFAULT)
-void LogOperation_(const char *format, ...) LOG_HELPER_BODY(NULL, MDNS_LOG_DEFAULT)
-void LogSPS_(const char *format, ...)       LOG_HELPER_BODY(NULL, MDNS_LOG_DEFAULT)
-void LogInfo_(const char *format, ...)      LOG_HELPER_BODY(NULL, MDNS_LOG_DEFAULT)
-void LogDebug_(const char *format, ...)     LOG_HELPER_BODY(NULL, MDNS_LOG_DEBUG)
-#endif
-
-#if MDNS_DEBUGMSGS
-void debugf_(const char *format, ...)       LOG_HELPER_BODY(NULL, MDNS_LOG_DEBUG)
-#endif
-
-// Log message with default "mDNSResponder" ident string at the start
-mDNSexport void LogMsgWithLevel(mDNSLogCategory_t category, mDNSLogLevel_t level, const char *format, ...)
-LOG_HELPER_BODY(category, level)
-
-mDNSexport void LogToFD(int fd, const char *format, ...)
-{
-    va_list args;
-    va_start(args, format);
-    (void)fd;
-    LogMsgWithLevelv(NULL, MDNS_LOG_DEFAULT, format, args);
-    va_end(args);
-}
diff --git a/mDNSShared/mDNSFeatures.h b/mDNSShared/mDNSFeatures.h
deleted file mode 100644
index f816840..0000000
--- a/mDNSShared/mDNSFeatures.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2019-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef __mDNSFeatures_h
-#define __mDNSFeatures_h
-
-#define HAS_FEATURE_CAT(A, B)       A ## B
-#define HAS_FEATURE_CHECK_0         1
-#define HAS_FEATURE_CHECK_1         1
-#define HAS_FEATURE(X)              ((X) / HAS_FEATURE_CAT(HAS_FEATURE_CHECK_, X))
-
-#define MDNSRESPONDER_SUPPORTS(PLATFORM, FEATURE) \
-    (MDNSRESPONDER_PLATFORM_ ## PLATFORM && \
-    HAS_FEATURE(MDNSRESPONDER_SUPPORTS_ ## PLATFORM ## _ ## FEATURE))
-
-#ifndef MDNSRESPONDER_PLATFORM_APPLE
-#define MDNSRESPONDER_PLATFORM_APPLE        0
-#endif
-
-#if MDNSRESPONDER_PLATFORM_APPLE
-#include "ApplePlatformFeatures.h"
-#endif
-
-// Common Features
-
-#undef MDNSRESPONDER_PLATFORM_COMMON
-#define MDNSRESPONDER_PLATFORM_COMMON       1
-
-// Feature: DNS Push
-// Radar:   <rdar://problem/23226275>
-// Enabled: Yes, for Apple.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_COMMON_DNS_PUSH)
-    #if MDNSRESPONDER_PLATFORM_APPLE
-        #define MDNSRESPONDER_SUPPORTS_COMMON_DNS_PUSH      1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_COMMON_DNS_PUSH      0
-    #endif
-#endif
-
-// Feature: DNS LLQ
-// Radar:   <rdar://problem/83483790>
-// Enabled: No.
-
-#if !defined(MDNSRESPONDER_SUPPORTS_COMMON_DNS_LLQ)
-    #if MDNSRESPONDER_PLATFORM_APPLE
-        #define MDNSRESPONDER_SUPPORTS_COMMON_DNS_LLQ 0
-    #else
-        #define MDNSRESPONDER_SUPPORTS_COMMON_DNS_LLQ 0
-    #endif
-#endif
-
-// Feature: Use Multicast DNS to discover the local DNS server that is authoritative for a given domain.
-// Radar:   <rdar://69957139>
-// Enabled: No
-
-#if !defined(MDNSRESPONDER_SUPPORTS_COMMON_LOCAL_DNS_RESOLVER_DISCOVERY)
-    #if MDNSRESPONDER_PLATFORM_APPLE
-        #define MDNSRESPONDER_SUPPORTS_COMMON_LOCAL_DNS_RESOLVER_DISCOVERY 1
-    #else
-        #define MDNSRESPONDER_SUPPORTS_COMMON_LOCAL_DNS_RESOLVER_DISCOVERY 0
-    #endif
-#endif
-
-#endif  // __mDNSFeatures_h
diff --git a/mDNSShared/tls-keychain.h b/mDNSShared/tls-keychain.h
deleted file mode 100644
index 480a4ef..0000000
--- a/mDNSShared/tls-keychain.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- *
- * This file contains function declarations for tls-keychain.c, which deals
- * with TLS certificate fetching and evaluation.
- */
-
-#ifndef __TLS_KEYCHAIN_H__
-#define __TLS_KEYCHAIN_H__
-
-#if __APPLE__
-#include <Security/Security.h>
-#endif
-
-//======================================================================================================================
-// MARK: - Macros
-
-#define SRP_APPLICATION_IDENTIFIER "com.apple.srp-mdns-proxy" // Application identifier for srp-mdns-proxy
-#define DNSSD_PROXY_APPLICATION_IDENTIFIER "com.apple.dnssd-proxy" // Application identifier for dnssd-proxy
-#define KEYCHAIN_ACCESS_GROUP SRP_APPLICATION_IDENTIFIER // Keychain access group of dnssd-proxy and mDNSResponder
-#define DNSSD_PROXY_IDENTITY_NAME SRP_APPLICATION_IDENTIFIER " identity" // The identity name used by dnssd-proxy
-#define KEY_ATTRIBUTE_LABEL_PREFIX "Key " // User-visible string put into the attribute label of the private key
-#define CERTIFICATE_ATTRIBUTE_LABEL_PREFIX "Certificate " // User-visible string put into the attribute label of the certificate
-
-// The TLS certificate in the keychain will be updated every two weeks(1209600s).
-#define TLS_CERTIFICATE_VALID_PERIOD_SECS 1209600
-// The TLS certificate that has been created for more than four weeks(2419200s) will be deleted from iCloud keychain no
-// matter who creates it.
-#define TLS_CERTIFICATE_EXISTENCE_PERIOD_SECS (TLS_CERTIFICATE_VALID_PERIOD_SECS * 2)
-
-//======================================================================================================================
-// MARK: - Structures
-
-// Context set in sec_protocol_options_set_verify_block() when trying to setup TLS connection with the server.
-typedef struct tls_keychain_context_t tls_keychain_context_t;
-struct tls_keychain_context_t {
-#if __APPLE__
-	sec_protocol_metadata_t _Nonnull metadata;
-	sec_trust_t _Nonnull trust_ref;
-#else // __APPLE__
-	uint8_t not_a_real_member;
-#endif // __APPLE__
-};
-
-//======================================================================================================================
-// MARK: - Functions
-
-/*!
- *	@brief
- *		Get the TLS certificate from the iCloud keychain.
- *
- *	@result
- *		True if the operation succeeds, otherwise, false.
- */
-bool
-tls_cert_init(void);
-
-/*!
- *	@brief
- *		Given the context, verify if the current TLS certificate should be trusted or not.
- *
- *	@param context
- *		Variables that are required to finish the TLS certificate evaluation.
- *
- *	@result
- *		True if it is trusted, false if not.
- */
-bool
-tls_cert_evaluate(const tls_keychain_context_t * _Nonnull context);
-
-/*!
- *	@brief
- *		Release the TLS certificate get from iCloud keychain.
- *
- *	@discussion
- *		If the certificate has been fetched from iCloud keychain, it will be released. If not, nothing will happen.
- */
-void
-tls_cert_dispose(void);
-
-#ifdef __APPLE__
-
-/*!
- *	@brief
- *		Add the identity into keychain.
- *
- *	@param identity
- *		A SecIdentityRef that contains a pair of SecKeyRef private key and SecCertificateRef certificate.
- *
- *	@param uuid
- *		An UUID that will be used to set three properties of the SecIdentityRef containing a pair of SecKeyRef and SecCertificateRef:
- *		1. UUID is used to set SecKeyRef's attribute label: "Key <UUID>".
- *		2. UUID is used to set SecCertificate's attribute label: "Certificate <UUID>".
- *		3. UUID is used to set the common name property in the subjects of SecCertificateRef: "<App Identifier> <UUID>".
- *		All the properties set above are used to match the specific SecItem when manipulating them.
- *
- *	@result
- *		errSecSuccess if the identity is added into keychain successfully, otherwise, an error code to indicate the error.
- *
- *	@discussion
- *		When an identity is added into keychain, the private key part of the identity will remain locally, and it will not be synced to iCloud keychain.
- *		The certificate part of the identity will be synced to iCloud keychain.
- */
-OSStatus
-keychain_identity_add(const SecIdentityRef _Nonnull identity, const CFStringRef _Nonnull uuid);
-
-/*!
- *	@brief
- *		Retrieve the identity added by <code>keychain_identity_add()</code> on the same device.
- *
- *	@param out_identity
- * 		A pointer to a SecIdentityRef variable that can be used to return the retrieved identity.
- *
- *	@param out_identity_creation_time
- * 		A pointer to a CFAbsoluteTime variable that can be used to return the creation time of the identity.
- *
- *	@result
- * 		errSecSuccess if the identity is found, errSecItemNotFound if the identity is not found, otherwise, an error code to indicate the error.
- *
- *	@discussion
- * 		Note that the identity being returned here is the one that gets added by <code>keychain_identity_add()</code> on the same device.
- * 		Which means the identity can only be returned to its creator by this function.
- */
-OSStatus
-keychain_identity_copy(CF_RETURNS_RETAINED SecIdentityRef * _Nonnull out_identity,
-					   CFAbsoluteTime * _Nonnull out_identity_creation_time);
-
-/*!
- *	@brief
- *		Remove the identity added by <code>keychain_identity_add()</code> on the same device.
- *
- *	@result
- *		errSecSuccess if the identity is removed from keychain, errSecItemNotFound if the identity is not found. Otherwise, an error code to indicate the error.
- *
- *	@discussion
- *		Here the identity is said to be removed from keychain if:
- *		1. The private key of the identity is removed from the local keychain.
- *		2. The certificate of the identity is removed from the iCloud keychain.
- */
-OSStatus
-keychain_identity_remove(void);
-
-/*!
- *	@brief
- *		Retrieve all the certificates from iCloud keychain that are added by <code>keychain_identity_add()</code>.
- *
- *	@param out_certificates
- *		A pointer to a CFArrayRef variable that can be used to return the retrieved SecCertificateRef array.
- *
- *	@param return_attributes
- *		A boolean value that determines whether it should return the attributes dictionary for the certificates or not.
- *
- *	@result
- *		errSecSuccess if the certificates on the iCloud keychain are found, errSecItemNotFound if the certificates are not found, otherwise an error code to indicate
- *		the error.
- */
-OSStatus
-keychain_certificates_copy(CF_RETURNS_RETAINED CFArrayRef * const _Nonnull out_certificates,
-						   bool return_attributes);
-
-/*!
- *	@brief
- *		Removes all the certificates that are more than TLS_CERTIFICATE_EXISTENCE_PERIOD_SECS seconds old.
- *
- *	@result
- *		errSecSuccess if there is any expired certificate that has been removed from keychain, errSecItemNotFound if the identity is not found. Otherwise, an error
- *		code to indicate the error.
- */
-OSStatus
-keychain_certificates_remove_expired(void);
-
-#endif // __APPLE__
-
-#endif // __TLS_KEYCHAIN_H__
diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c
deleted file mode 100644
index 9ae5f78..0000000
--- a/mDNSShared/uds_daemon.c
+++ /dev/null
@@ -1,7080 +0,0 @@
-/*
- * Copyright (c) 2003-2022 Apple 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
- *
- *     https://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.
- */
-
-#if defined(_WIN32)
-#include <process.h>
-#define usleep(X) Sleep(((X)+999)/1000)
-#else
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "mDNSEmbeddedAPI.h"
-#include "DNSCommon.h"
-#include "uDNS.h"
-#include "uds_daemon.h"
-#include "dns_sd_internal.h"
-
-// Apple-specific functionality, not required for other platforms
-
-#ifdef LOCAL_PEEREPID
-#include <sys/un.h>         // for LOCAL_PEEREPID
-#include <sys/socket.h>     // for getsockopt
-#endif //LOCAL_PEEREPID
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-#include "D2D.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-#include "mDNSMacOSX.h"
-#include <os/feature_private.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-#include <mdns/signed_result.h>
-#include <mdns/system.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-#include <bsm/libbsm.h>
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-#include "QuerierSupport.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
-#include "dnssd_server.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-#include "discover_resolver.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-#include "resolved_cache.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
-#include "dns_sd_internal.h"
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-#include "cf_support.h"
-#include "misc_utilities.h"
-#include "system_utilities.h"
-#endif
-
-#include "mdns_strict.h"
-
-// User IDs 0-500 are system-wide processes, not actual users in the usual sense
-// User IDs for real user accounts start at 501 and count up from there
-#define SystemUID(X) ((X) <= 500)
-
-// ***************************************************************************
-// MARK: - Globals
-
-// globals
-mDNSexport mDNS mDNSStorage;
-mDNSexport const char ProgramName[] = "mDNSResponder";
-
-#if defined(USE_TCP_LOOPBACK)
-static char* boundPath = NULL;
-#else
-static char* boundPath = MDNS_UDS_SERVERPATH;
-#endif
-#if DEBUG
-#define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder"
-#endif
-static dnssd_sock_t listenfd = dnssd_InvalidSocket;
-static request_state *all_requests = NULL;
-mDNSlocal void set_peer_pid(request_state *request);
-mDNSlocal void LogMcastClientInfo(request_state *req);
-mDNSlocal void GetMcastClients(request_state *req);
-mDNSlocal mStatus update_record(AuthRecord *ar, mDNSu16 rdlen, const mDNSu8 *rdata, mDNSu32 ttl,
-    const mDNSBool *external_advertise, mDNSu32 request_id);
-static mDNSu32 mcount;     // tracks the current active mcast operations for McastLogging
-static mDNSu32 i_mcount;   // sets mcount when McastLogging is enabled(PROF signal is sent)
-static mDNSu32 n_mrecords; // tracks the current active mcast records for McastLogging
-static mDNSu32 n_mquests;  // tracks the current active mcast questions for McastLogging
-
-
-// Note asymmetry here between registration and browsing.
-// For service registrations we only automatically register in domains that explicitly appear in local configuration data
-// (so AutoRegistrationDomains could equally well be called SCPrefRegDomains)
-// For service browsing we also learn automatic browsing domains from the network, so for that case we have:
-// 1. SCPrefBrowseDomains (local configuration data)
-// 2. LocalDomainEnumRecords (locally-generated local-only PTR records -- equivalent to slElem->AuthRecs in uDNS.c)
-// 3. AutoBrowseDomains, which is populated by tracking add/rmv events in AutomaticBrowseDomainChange, the callback function for our mDNS_GetDomains call.
-// By creating and removing our own LocalDomainEnumRecords, we trigger AutomaticBrowseDomainChange callbacks just like domains learned from the network would.
-
-mDNSexport DNameListElem *AutoRegistrationDomains;  // Domains where we automatically register for empty-string registrations
-
-static DNameListElem *SCPrefBrowseDomains;          // List of automatic browsing domains read from SCPreferences for "empty string" browsing
-static ARListElem    *LocalDomainEnumRecords;       // List of locally-generated PTR records to augment those we learn from the network
-mDNSexport DNameListElem *AutoBrowseDomains;        // List created from those local-only PTR records plus records we get from the network
-
-#define MSG_PAD_BYTES 5     // pad message buffer (read from client) with n zero'd bytes to guarantee
-                            // n get_string() calls w/o buffer overrun
-// initialization, setup/teardown functions
-
-// If a platform specifies its own PID file name, we use that
-#ifndef NO_PID_FILE
-    #ifndef PID_FILE
-    #define PID_FILE "/var/run/mDNSResponder.pid"
-    #endif
-#endif
-
-#ifndef NORETURN_ATTRIBUTE
-#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))
-#define NORETURN_ATTRIBUTE __attribute__((noreturn))
-#else
-#define NORETURN_ATTRIBUTE
-#endif
-#endif
-
-// ***************************************************************************
-// MARK: - General Utility Functions
-
-mDNSlocal mDNSu32 GetNewRequestID(void)
-{
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSD_XPC_SERVICE)
-    return dnssd_server_get_new_request_id();
-#else
-    static mDNSu32 s_last_id = 0;
-    return ++s_last_id;
-#endif
-}
-
-NORETURN_ATTRIBUTE
-mDNSlocal void FatalError(char *errmsg)
-{
-    LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno));
-    abort();
-}
-
-mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l)
-{
-    mDNSu32 ret;
-    uint8_t *data = (uint8_t *)&ret;
-    put_uint32(l, &data);
-    return ret;
-}
-
-// hack to search-replace perror's to LogMsg's
-mDNSlocal void my_perror(char *errmsg)
-{
-    LogMsg("%s: %d (%s)", errmsg, dnssd_errno, dnssd_strerror(dnssd_errno));
-}
-
-// Throttled version of my_perror: Logs once every 250 msgs
-mDNSlocal void my_throttled_perror(char *err_msg)
-{
-    static int uds_throttle_count = 0;
-    if ((uds_throttle_count++ % 250) == 0)
-        my_perror(err_msg);
-}
-
-// LogMcastQuestion/LogMcastQ should be called after the DNSQuestion struct is initialized(especially for q->TargetQID)
-// Hence all calls are made after mDNS_StartQuery()/mDNS_StopQuery()/mDNS_StopBrowse() is called.
-mDNSlocal void LogMcastQuestion(const DNSQuestion *const q, request_state *req, q_state status)
-{
-    if (mDNSOpaque16IsZero(q->TargetQID)) // Check for Mcast Query
-    {
-        mDNSBool mflag = mDNSfalse;
-        if (status == q_start)
-        {
-            if (++mcount == 1)
-                mflag = mDNStrue;
-        }
-        else
-        {
-            mcount--;
-        }
-        LogMcast("%s: %##s  (%s) (%s)  Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype),
-                 q->InterfaceID == mDNSInterface_LocalOnly ? "lo" :
-                 q->InterfaceID == mDNSInterface_P2P ? "p2p" :
-                 q->InterfaceID == mDNSInterface_BLE ? "BLE" :
-                 q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(&mDNSStorage, q->InterfaceID),
-                 req->process_id, req->pid_name);
-        LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
-    }
-    return;
-}
-
-// LogMcastService/LogMcastS should be called after the AuthRecord struct is initialized
-// Hence all calls are made after mDNS_Register()/ just before mDNS_Deregister()
-mDNSlocal void LogMcastService(const AuthRecord *const ar, request_state *req, reg_state status)
-{
-    if (!AuthRecord_uDNS(ar)) // Check for Mcast Service
-    {
-        mDNSBool mflag = mDNSfalse;
-        if (status == reg_start)
-        {
-            if (++mcount == 1)
-                mflag = mDNStrue;
-        }
-        else
-        {
-            mcount--;
-        }
-        LogMcast("%s: %##s  (%s)  (%s)  Client(%d)[%s]", status ? "+Service" : "-Service", ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype),
-                 ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" :
-                 ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" :
-                 ar->resrec.InterfaceID == mDNSInterface_BLE ? "BLE" :
-                 ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID),
-                 req->process_id, req->pid_name);
-        LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse);
-    }
-    return;
-}
-
-// For complete Mcast State Log, pass mDNStrue to mstatelog in LogMcastStateInfo()
-mDNSexport void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog)
-{
-    mDNS *const m = &mDNSStorage;
-    if (!mstatelog)
-    {
-        if (!all_requests)
-        {
-            LogMcastNoIdent("<None>");
-        }
-        else
-        {
-            request_state *req, *r;
-            for (req = all_requests; req; req=req->next)
-            {
-                if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
-                {
-                    for (r = all_requests; r && r != req; r=r->next)
-                        if (r == req->primary)
-                            goto foundpar;
-                }
-                // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
-                GetMcastClients(req);
-    foundpar:;
-            }
-            LogMcastNoIdent("--- MCAST RECORDS COUNT[%d] MCAST QUESTIONS COUNT[%d] ---", n_mrecords, n_mquests);
-            n_mrecords = n_mquests = 0; // Reset the values
-        }
-    }
-    else
-    {
-        static mDNSs32 i_mpktnum;
-        i_mcount = 0;
-        if (start)
-            mcount = 0;
-        // mcount is initialized to 0 when the PROF signal is sent since mcount could have
-        // wrong value if MulticastLogging is disabled and then re-enabled
-        LogMcastNoIdent("--- START MCAST STATE LOG ---");
-        if (!all_requests)
-        {
-            mcount = 0;
-            LogMcastNoIdent("<None>");
-        }
-        else
-        {
-            request_state *req, *r;
-            for (req = all_requests; req; req=req->next)
-            {
-                if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
-                {
-                    for (r = all_requests; r && r != req; r=r->next)
-                        if (r == req->primary)
-                            goto foundparent;
-                    LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req->sd);
-                }
-                // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
-                LogMcastClientInfo(req);
-    foundparent:;
-            }
-            if(!mcount) // To initially set mcount
-                mcount = i_mcount;
-        }
-        if (mcount == 0)
-        {
-            i_mpktnum = m->MPktNum;
-            LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount, i_mpktnum);
-        }
-        if (mflag)
-            LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum));
-        LogMcastNoIdent("--- END MCAST STATE LOG ---");
-    }
-}
-
-mDNSlocal void abort_request(request_state *req)
-{
-    if (req->terminate == (req_termination_fn) ~0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%d] abort_request: ERROR: Attempt to abort operation %p with req->terminate %p", req->request_id, req, req->terminate);
-        return;
-    }
-
-    // First stop whatever mDNSCore operation we were doing
-    // If this is actually a shared connection operation, then its req->terminate function will scan
-    // the all_requests list and terminate any subbordinate operations sharing this file descriptor
-    if (req->terminate) req->terminate(req);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    if (req->custom_service_id != 0)
-    {
-        Querier_DeregisterCustomDNSService(req->custom_service_id);
-        req->custom_service_id = 0;
-    }
-#endif
-
-    if (!dnssd_SocketValid(req->sd))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%d] abort_request: ERROR: Attempt to abort operation %p with invalid fd %d", req->request_id, req, req->sd);
-        return;
-    }
-
-    // Now, if this request_state is not subordinate to some other primary, close file descriptor and discard replies
-    if (!req->primary)
-    {
-        if (req->errsd != req->sd)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                      "[R%d] Removing FD %d and closing errsd %d", req->request_id, req->sd, req->errsd);
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                      "[R%d] Removing FD %d", req->request_id, req->sd);
-        }
-        udsSupportRemoveFDFromEventLoop(req->sd, req->platform_data);       // Note: This also closes file descriptor req->sd for us
-        if (req->errsd != req->sd) { dnssd_close(req->errsd); req->errsd = req->sd; }
-
-        while (req->replies)    // free pending replies
-        {
-            reply_state *ptr = req->replies;
-            req->replies = req->replies->next;
-            freeL("reply_state (abort)", ptr);
-        }
-    }
-
-    // Set req->sd to something invalid, so that udsserver_idle knows to unlink and free this structure
-#if MDNS_MALLOC_DEBUGGING
-    // Don't use dnssd_InvalidSocket (-1) because that's the sentinel value MDNS_MALLOC_DEBUGGING uses
-    // for detecting when the memory for an object is inadvertently freed while the object is still on some list
-#ifdef WIN32
-#error This will not work on Windows, look at IsValidSocket in mDNSShared/CommonServices.h to see why
-#endif
-    req->sd = req->errsd = -2;
-#else
-    req->sd = req->errsd = dnssd_InvalidSocket;
-#endif
-    // We also set req->terminate to a bogus value so we know if abort_request() gets called again for this request
-    req->terminate = (req_termination_fn) ~0;
-}
-
-#if DEBUG
-mDNSexport void SetDebugBoundPath(void)
-{
-#if !defined(USE_TCP_LOOPBACK)
-    boundPath = MDNS_UDS_SERVERPATH_DEBUG;
-#endif
-}
-
-mDNSexport int IsDebugSocketInUse(void)
-{
-#if !defined(USE_TCP_LOOPBACK)
-    return !strcmp(boundPath, MDNS_UDS_SERVERPATH_DEBUG);
-#else
-    return mDNSfalse;
-#endif
-}
-#endif
-
-mDNSlocal void AbortUnlinkAndFree(request_state *req)
-{
-    request_state **p = &all_requests;
-    abort_request(req);
-    while (*p && *p != req) p=&(*p)->next;
-    if (*p)
-    {
-        *p = req->next;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-        mdns_trust_forget(&req->trust);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-        mdns_forget(&req->signed_obj);
-#endif
-        freeL("request_state/AbortUnlinkAndFree", req);
-    }
-    else
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "AbortUnlinkAndFree: ERROR: Attempt to abort operation %p not in list", req);
-    }
-}
-
-mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, request_state *const request)
-{
-    reply_state *reply;
-
-    if ((unsigned)datalen < sizeof(reply_hdr))
-    {
-        LogMsg("ERROR: create_reply - data length less than length of required fields");
-        return NULL;
-    }
-
-    reply = (reply_state *) callocL("reply_state", sizeof(reply_state) + datalen - sizeof(reply_hdr));
-    if (!reply) FatalError("ERROR: calloc");
-
-    reply->next     = mDNSNULL;
-    reply->totallen = (mDNSu32)datalen + sizeof(ipc_msg_hdr);
-    reply->nwritten = 0;
-
-    reply->mhdr->version        = VERSION;
-    reply->mhdr->datalen        = (mDNSu32)datalen;
-    reply->mhdr->ipc_flags      = 0;
-    reply->mhdr->op             = op;
-    reply->mhdr->client_context = request->hdr.client_context;
-    reply->mhdr->reg_index      = 0;
-
-    return reply;
-}
-
-// Append a reply to the list in a request object
-// If our request is sharing a connection, then we append our reply_state onto the primary's list
-// If the request does not want asynchronous replies, then the reply is freed instead of being appended to any list.
-mDNSlocal void append_reply(request_state *req, reply_state *rep)
-{
-    request_state *r;
-    reply_state **ptr;
-
-    if (req->no_reply)
-    {
-        freeL("reply_state/append_reply", rep);
-        return;
-    }
-
-    r = req->primary ? req->primary : req;
-    ptr = &r->replies;
-    while (*ptr) ptr = &(*ptr)->next;
-    *ptr = rep;
-    rep->next = NULL;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-mDNSlocal const uint8_t * _get_signed_data_tlvs(request_state *const request, size_t *const out_length)
-{
-    const mDNSu8 *data = NULL;
-    if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
-    {
-        const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
-        const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
-        DNSServiceValidationPolicy policy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_POLICY, mDNSNULL);
-        if (policy == kDNSServiceValidationPolicyRequired)
-        {
-            request->sign_result = mDNStrue;
-            size_t len;
-            data = get_tlv(start, end, IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA, &len);
-            if (out_length)
-            {
-                *out_length = len;
-            }
-        }
-    }
-    return data;
-}
-
-mDNSlocal mStatus get_signed_result_flags_tlvs(request_state *const request)
-{
-    // No data is expected in this case
-    (void)_get_signed_data_tlvs(request, NULL);
-    return mStatus_NoError;
-}
-
-mDNSlocal mStatus get_signed_browse_tlvs(request_state *const request)
-{
-    size_t len = 0;
-    const mDNSu8 * const data = _get_signed_data_tlvs(request, &len);
-    if (request->sign_result)
-    {
-        if (!data)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_browse_tlvs data invalid");
-            return mStatus_Invalid;
-        }
-
-        OSStatus err;
-        mdns_signed_browse_result_t signed_obj = mdns_signed_browse_result_create_from_data(data, len, &err);
-        if (!signed_obj || err != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_browse_tlvs len %ld data invalid %ld", len,
-                (long)err);
-            return mStatus_Invalid;
-        }
-
-        request->signed_obj = mdns_signed_result_upcast(signed_obj);
-    }
-    return mStatus_NoError;
-}
-
-mDNSlocal mStatus get_signed_resolve_tlvs(request_state *const request)
-{
-    size_t len = 0;
-    const mDNSu8 * const data = _get_signed_data_tlvs(request, &len);
-    if (request->sign_result)
-    {
-        if (!data)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_resolve_tlvs data invalid");
-            return mStatus_Invalid;
-        }
-
-        OSStatus err;
-        mdns_signed_resolve_result_t signed_obj = mdns_signed_resolve_result_create_from_data(data, len, &err);
-        if (!signed_obj || err != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "get_signed_resolve_tlvs len %ld data invalid %ld", len,
-                (long)err);
-            return mStatus_Invalid;
-        }
-
-        request->signed_obj = mdns_signed_result_upcast(signed_obj);
-    }
-    return mStatus_NoError;
-}
-
-mDNSlocal void put_signed_result_tlvs(const uint8_t *data, uint16_t length, ipc_msg_hdr * const hdr,
-    uint8_t ** const ptr, const uint8_t * const limit)
-{
-    put_tlv(IPC_TLV_TYPE_SERVICE_ATTR_VALIDATION_DATA, length, data, ptr, limit);
-    hdr->ipc_flags |= IPC_FLAGS_TRAILING_TLVS;
-}
-#endif
-
-// Generates a response message giving name, type, domain, plus interface index,
-// suitable for a browse result or service registration result.
-// On successful completion rep is set to point to a malloc'd reply_state struct
-mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const mDNSInterfaceID id,
-                                      request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
-{
-    domainlabel name;
-    domainname type, dom;
-    *rep = NULL;
-    if (servicename && !DeconstructServiceName(servicename, &name, &type, &dom))
-        return kDNSServiceErr_Invalid;
-    else
-    {
-        char namestr[MAX_DOMAIN_LABEL+1];
-        char typestr[MAX_ESCAPED_DOMAIN_NAME];
-        char domstr [MAX_ESCAPED_DOMAIN_NAME];
-        size_t len;
-        uint8_t *data;
-
-        if (servicename)
-        {
-            ConvertDomainLabelToCString_unescaped(&name, namestr);
-            ConvertDomainNameToCString(&type, typestr);
-            ConvertDomainNameToCString(&dom, domstr);
-        }
-        else
-        {
-            namestr[0] = 0;
-            typestr[0] = 0;
-            domstr[0] = 0;
-        }
-
-        mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse);
-
-        // Calculate reply data length
-        len = sizeof(DNSServiceFlags);
-        len += sizeof(mDNSu32);  // if index
-        len += sizeof(DNSServiceErrorType);
-        len += (strlen(namestr) + 1);
-        len += (strlen(typestr) + 1);
-        len += (strlen(domstr) + 1);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-        mdns_signed_browse_result_t signed_result = NULL;
-        const uint8_t *signed_data = NULL;
-        uint16_t signed_data_length = 0;
-        if (request->sign_result && servicename)
-        {
-            OSStatus error;
-            signed_result = mdns_signed_browse_result_create(servicename->c, interface_index, &error);
-            if (!signed_result || error != 0)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "GenerateBrowseReply signed_browse failed %ld",
-                    (long)error);
-            }
-            else
-            {
-                size_t temp_size = 0;
-                const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
-                if (temp_size <= UINT16_MAX)
-                {
-                    signed_data = temp_data;
-                    signed_data_length = (uint16_t)temp_size;
-                    len += get_required_tlv_length(signed_data_length);
-                }
-            }
-        }
-#endif
-
-        // Build reply header
-        *rep = create_reply(op, len, request);
-        (*rep)->rhdr->flags = dnssd_htonl(flags);
-        (*rep)->rhdr->ifi   = dnssd_htonl(interface_index);
-        (*rep)->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
-
-        // Build reply body
-        data = (uint8_t *)&(*rep)->rhdr[1];
-        put_string(namestr, &data);
-        put_string(typestr, &data);
-        put_string(domstr, &data);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-        if (signed_data)
-        {
-            put_signed_result_tlvs(signed_data, signed_data_length, (*rep)->mhdr, &data, data+len);
-        }
-        mdns_forget(&signed_result);
-#endif
-
-        return mStatus_NoError;
-    }
-}
-
-mDNSlocal void GenerateBrowseReply(const domainname *const servicename, const mDNSInterfaceID id,
-                                              request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
-{
-    char namestr[MAX_DOMAIN_LABEL+1];
-    char typestr[MAX_ESCAPED_DOMAIN_NAME];
-    static const char domstr[] = ".";
-    size_t len;
-    uint8_t *data;
-
-    *rep = NULL;
-
-    if (servicename)
-    {
-        // 1. Put first label in namestr
-        ConvertDomainLabelToCString_unescaped((const domainlabel *)servicename, namestr);
-
-        // 2. Put second label and "local" into typestr
-        mDNS_snprintf(typestr, sizeof(typestr), "%#s.local.", SecondLabel(servicename));
-    }
-    else
-    {
-        namestr[0] = 0;
-        typestr[0] = 0;
-    }
-
-    // Calculate reply data length
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(mDNSu32);  // if index
-    len += sizeof(DNSServiceErrorType);
-    len += (strlen(namestr) + 1);
-    len += (strlen(typestr) + 1);
-    len += (strlen(domstr) + 1);
-
-    // Build reply header
-    *rep = create_reply(op, len, request);
-    (*rep)->rhdr->flags = dnssd_htonl(flags);
-    (*rep)->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, id, mDNSfalse));
-    (*rep)->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
-
-    // Build reply body
-    data = (uint8_t *)&(*rep)->rhdr[1];
-    put_string(namestr, &data);
-    put_string(typestr, &data);
-    put_string(domstr, &data);
-}
-
-// get IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP value
-// if tlv type IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP is present and found is not NULL, *found will be set to mDNStrue,
-// otherwise it will be set to mDNSfalse. The caller should check *found before using the returned value. The timestamp
-// is a number of seconds in the past, and is unsigned.
-mDNSlocal mDNSu32 get_service_attr_timestamp_value(const request_state *const request, mDNSBool *const outFound)
-{
-    mDNSu32 timestamp = 0;
-    if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
-    {
-        mDNSs32 error;
-        const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
-        const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
-        timestamp = (mDNSu32)get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_TIMESTAMP, &error);
-        if (outFound)
-        {
-            *outFound = error ? mDNSfalse : mDNStrue;
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "found[" PUB_S "] timestamp %u", error ? "no" : "yes", timestamp);
-    }
-    return timestamp;
-}
-
-// Returns a resource record (allocated w/ malloc) containing the data found in an IPC message
-// Data must be in the following format: flags, interfaceIndex, name, rrtype, rrclass, rdlen, rdata, (optional) ttl
-// (ttl only extracted/set if ttl argument is non-zero). Returns NULL for a bad-parameter error
-mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, int validate_flags)
-{
-    DNSServiceFlags flags  = get_flags(&request->msgptr, request->msgend);
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    char name[MAX_ESCAPED_DOMAIN_NAME];
-    int str_err = get_string(&request->msgptr, request->msgend, name, sizeof(name));
-    mDNSu16 type  = get_uint16(&request->msgptr, request->msgend);
-    mDNSu16 class = get_uint16(&request->msgptr, request->msgend);
-    mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
-    const mDNSu8 *const rdata = get_rdata(&request->msgptr, request->msgend, rdlen);
-    mDNSu32 ttl   = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
-    size_t rdcapacity;
-    AuthRecord *rr;
-    mDNSInterfaceID InterfaceID;
-    AuthRecType artype;
-    mDNSu8 recordType;
-
-    request->flags = flags;
-    request->interfaceIndex = interfaceIndex;
-
-    if (str_err) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL; }
-    if (!request->msgptr) { LogMsg("Error reading Resource Record from client"); return NULL; }
-
-    if (validate_flags &&
-        !((flags & kDNSServiceFlagsShared) == kDNSServiceFlagsShared) &&
-        !((flags & kDNSServiceFlagsUnique) == kDNSServiceFlagsUnique) &&
-        !((flags & kDNSServiceFlagsKnownUnique) == kDNSServiceFlagsKnownUnique))
-    {
-        LogMsg("ERROR: Bad resource record flags (must be one of either kDNSServiceFlagsShared, kDNSServiceFlagsUnique or kDNSServiceFlagsKnownUnique)");
-        return NULL;
-    }
-    InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-
-    // The registration is scoped to a specific interface index, but the interface is not currently on our list.
-    if ((InterfaceID == mDNSInterface_Any) && (interfaceIndex != kDNSServiceInterfaceIndexAny))
-    {
-        // On Apple platforms, an interface's mDNSInterfaceID is equal to its index. Using an interface index that isn't
-        // currently valid will cause the registration to take place as soon as it becomes valid. On other platforms,
-        // mDNSInterfaceID is actually a pointer to a platform-specific interface object, but we don't know what the pointer
-        // for the interface index will be ahead of time. For now, just return NULL to indicate an error condition since the
-        // interface index is invalid. Otherwise, the registration would be performed on all interfaces.
-        return NULL;
-    }
-    rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
-    rr = (AuthRecord *) callocL("AuthRecord/read_rr_from_ipc_msg", sizeof(*rr) - sizeof(RDataBody) + rdcapacity);
-    if (!rr) FatalError("ERROR: calloc");
-
-    if (InterfaceID == mDNSInterface_LocalOnly)
-        artype = AuthRecordLocalOnly;
-    else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
-        artype = AuthRecordP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
-            && (flags & kDNSServiceFlagsIncludeAWDL))
-        artype = AuthRecordAnyIncludeAWDLandP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
-        artype = AuthRecordAnyIncludeP2P;
-    else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL))
-        artype = AuthRecordAnyIncludeAWDL;
-    else
-        artype = AuthRecordAny;
-
-    if (flags & kDNSServiceFlagsShared)
-        recordType = (mDNSu8) kDNSRecordTypeShared;
-    else if (flags & kDNSServiceFlagsKnownUnique)
-        recordType = (mDNSu8) kDNSRecordTypeKnownUnique;
-    else
-        recordType = (mDNSu8) kDNSRecordTypeUnique;
-
-    mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, type, 0, recordType, artype, mDNSNULL, mDNSNULL);
-
-    if (!MakeDomainNameFromDNSNameString(&rr->namestorage, name))
-    {
-        LogMsg("ERROR: bad name: %s", name);
-        freeL("AuthRecord/read_rr_from_ipc_msg", rr);
-        return NULL;
-    }
-
-    if (flags & kDNSServiceFlagsAllowRemoteQuery) rr->AllowRemoteQuery = mDNStrue;
-    rr->resrec.rrclass = class;
-    rr->resrec.rdlength = rdlen;
-    rr->resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
-    if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr->resrec, rdlen))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
-            request->request_id, DM_NAME_PARAM(rr->resrec.name), DNSTypeName(type));
-        freeL("AuthRecord/read_rr_from_ipc_msg", rr);
-        return NULL;
-    }
-    if (GetTTL) rr->resrec.rroriginalttl = ttl;
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-    return rr;
-}
-
-mDNSlocal int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain)
-{
-    domainlabel n;
-    domainname d, t;
-
-    if (!MakeDomainLabelFromLiteralString(&n, name)) return -1;
-    if (!MakeDomainNameFromDNSNameString(&t, regtype)) return -1;
-    if (!MakeDomainNameFromDNSNameString(&d, domain)) return -1;
-    if (!ConstructServiceName(srv, &n, &t, &d)) return -1;
-    return 0;
-}
-
-mDNSlocal void send_all(dnssd_sock_t s, const char *ptr, const size_t len)
-{
-    const ssize_t n = send(s, ptr, len, 0);
-    // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a small write for us
-    // (four bytes for a typical error code return, 12 bytes for DNSServiceGetProperty(DaemonVersion)).
-    // If it does fail, we don't attempt to handle this failure, but we do log it so we know something is wrong.
-    if ((n < 0) || (((size_t)n) < len))
-    {
-        LogMsg("ERROR: send_all(%d) wrote %ld of %lu errno %d (%s)",
-            s, (long)n, (unsigned long)len, dnssd_errno, dnssd_strerror(dnssd_errno));
-    }
-}
-
-#if 0
-mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const domainname * const d, const DNameListElem * const doms)
-{
-    const DNameListElem   *delem = mDNSNULL;
-    int bestDelta   = -1;                           // the delta of the best match, lower is better
-    int dLabels     = 0;
-    mDNSBool allow       = mDNSfalse;
-
-    if (SystemUID(request->uid)) return mDNStrue;
-
-    dLabels = CountLabels(d);
-    for (delem = doms; delem; delem = delem->next)
-    {
-        if (delem->uid)
-        {
-            int delemLabels = CountLabels(&delem->name);
-            int delta       = dLabels - delemLabels;
-            if ((bestDelta == -1 || delta <= bestDelta) && SameDomainName(&delem->name, SkipLeadingLabels(d, delta)))
-            {
-                bestDelta = delta;
-                allow = (allow || (delem->uid == request->uid));
-            }
-        }
-    }
-
-    return bestDelta == -1 ? mDNStrue : allow;
-}
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-mDNSlocal void SetupAuditTokenForRequest(request_state *request)
-{
-
-    pid_t audit_pid = audit_token_to_pid(request->audit_token);
-    if (audit_pid == 0)
-    {
-#if !defined(LOCAL_PEERTOKEN)
-#define LOCAL_PEERTOKEN         0x006           /* retrieve peer audit token */
-#endif
-        socklen_t len = sizeof(audit_token_t);
-        int ret = getsockopt(request->sd, SOL_LOCAL, LOCAL_PEERTOKEN, &request->audit_token, &len);
-        if (ret != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                      "SetupAuditTokenForRequest: No audit_token using LOCAL_PEERTOKEN (%s PID %d) for op %d ret(%d)",
-                      request->pid_name, request->process_id, request->hdr.op, ret);
-        }
-    }
-}
-#endif
-
-// ***************************************************************************
-// MARK: - external helpers
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-mDNSlocal void external_start_advertising_helper(service_instance *const instance)
-{
-    AuthRecord *st = instance->subtypes;
-    ExtraResourceRecord *e;
-    mDNSu32 i;
-    const pid_t requestPID = instance->request->process_id;
-
-    if (mDNSIPPortIsZero(instance->request->u.servicereg.port))
-    {
-        LogInfo("external_start_advertising_helper: Not registering service with port number zero");
-        return;
-    }
-
-    if (instance->external_advertise) LogMsg("external_start_advertising_helper: external_advertise already set!");
-
-    for (i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
-        external_start_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
-
-    external_start_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
-    external_start_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
-    external_start_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
-
-    for (e = instance->srs.Extras; e; e = e->next)
-        external_start_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
-
-    instance->external_advertise = mDNStrue;
-}
-
-mDNSlocal void external_stop_advertising_helper(service_instance *const instance)
-{
-    AuthRecord *st = instance->subtypes;
-    ExtraResourceRecord *e;
-    mDNSu32 i;
-
-    if (!instance->external_advertise) return;
-
-    LogInfo("external_stop_advertising_helper: calling external_stop_advertising_service");
-
-    if (instance->request)
-    {
-        const pid_t requestPID = instance->request->process_id;
-        for (i = 0; i < instance->request->u.servicereg.num_subtypes; i++)
-        {
-            external_stop_advertising_service(&st[i].resrec, instance->request->flags, requestPID);
-        }
-
-        external_stop_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags, requestPID);
-        external_stop_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags, requestPID);
-        external_stop_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags, requestPID);
-
-        for (e = instance->srs.Extras; e; e = e->next)
-        {
-            external_stop_advertising_service(&e->r.resrec, instance->request->flags, requestPID);
-        }
-    }
-
-    instance->external_advertise = mDNSfalse;
-}
-#endif  // MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-mDNSlocal dispatch_queue_t _get_trust_results_dispatch_queue(void)
-{
-    static dispatch_once_t  once    = 0;
-    static dispatch_queue_t queue   = NULL;
-
-    dispatch_once(&once, ^{
-        dispatch_queue_attr_t const attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
-        queue = dispatch_queue_create("com.apple.mDNSResponder.trust_results-queue", attr);
-    });
-    return queue;
-}
-#endif
-
-// ***************************************************************************
-// MARK: - DNSServiceRegister
-
-mDNSexport void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    ExtraResourceRecord *extra = (ExtraResourceRecord *)rr->RecordContext;
-    (void)m;  // Unused
-
-    if (result != mStatus_MemFree) { LogMsg("Error: FreeExtraRR invoked with unexpected error %d", result); return; }
-
-    LogInfo("     FreeExtraRR %s", RRDisplayString(m, &rr->resrec));
-
-    if (rr->resrec.rdata != &rr->rdatastorage)
-        freeL("Extra RData", rr->resrec.rdata);
-    freeL("ExtraResourceRecord/FreeExtraRR", extra);
-}
-
-mDNSlocal void unlink_and_free_service_instance(service_instance *srv)
-{
-    ExtraResourceRecord *e = srv->srs.Extras, *tmp;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    external_stop_advertising_helper(srv);
-#endif
-
-    // clear pointers from parent struct
-    if (srv->request)
-    {
-        service_instance **p = &srv->request->u.servicereg.instances;
-        while (*p)
-        {
-            if (*p == srv) { *p = (*p)->next; break; }
-            p = &(*p)->next;
-        }
-    }
-
-    while (e)
-    {
-        e->r.RecordContext = e;
-        tmp = e;
-        e = e->next;
-        FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree);
-    }
-
-    if (srv->srs.RR_TXT.resrec.rdata != &srv->srs.RR_TXT.rdatastorage)
-        freeL("TXT RData", srv->srs.RR_TXT.resrec.rdata);
-
-    if (srv->subtypes)
-    {
-        freeL("ServiceSubTypes", srv->subtypes);
-        srv->subtypes = NULL;
-    }
-    freeL("service_instance", srv);
-}
-
-// Count how many other service records we have locally with the same name, but different rdata.
-// For auto-named services, we can have at most one per machine -- if we allowed two auto-named services of
-// the same type on the same machine, we'd get into an infinite autoimmune-response loop of continuous renaming.
-mDNSexport int CountPeerRegistrations(ServiceRecordSet *const srs)
-{
-    int count = 0;
-    ResourceRecord *r = &srs->RR_SRV.resrec;
-    AuthRecord *rr;
-
-    for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
-        if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r))
-            count++;
-
-    verbosedebugf("%d peer registrations for %##s", count, r->name->c);
-    return(count);
-}
-
-mDNSexport int CountExistingRegistrations(domainname *srv, mDNSIPPort port)
-{
-    int count = 0;
-    AuthRecord *rr;
-    for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
-        if (rr->resrec.rrtype == kDNSType_SRV &&
-            mDNSSameIPPort(rr->resrec.rdata->u.srv.port, port) &&
-            SameDomainName(rr->resrec.name, srv))
-            count++;
-    return(count);
-}
-
-mDNSlocal void SendServiceRemovalNotification(ServiceRecordSet *const srs)
-{
-    reply_state *rep;
-    service_instance *instance = srs->ServiceContext;
-    if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, 0, mStatus_NoError) != mStatus_NoError)
-        LogMsg("%3d: SendServiceRemovalNotification: %##s is not valid DNS-SD SRV name", instance->request->sd, srs->RR_SRV.resrec.name->c);
-    else { append_reply(instance->request, rep); instance->clientnotified = mDNSfalse; }
-}
-
-// service registration callback performs three duties - frees memory for deregistered services,
-// handles name conflicts, and delivers completed registration information to the client
-mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
-{
-    mStatus err;
-    mDNSBool SuppressError = mDNSfalse;
-    service_instance *instance;
-    reply_state         *rep;
-    (void)m; // Unused
-
-    if (!srs)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: srs is NULL %d", result);
-        return;
-    }
-
-    instance = srs->ServiceContext;
-    if (!instance)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: srs->ServiceContext is NULL %d", result);
-        return;
-    }
-
-    // don't send errors up to client for wide-area, empty-string registrations
-    if (instance->request &&
-        instance->request->u.servicereg.default_domain &&
-        !instance->default_local)
-        SuppressError = mDNStrue;
-
-    if (mDNS_LoggingEnabled)
-    {
-        const char *result_description;
-        char description[32]; // 32-byte is enough for holding "suppressed error -2147483648\0"
-        mDNSu32 request_id = instance->request ? instance->request->request_id : 0;
-        switch (result) {
-            case mStatus_NoError:
-                result_description = "REGISTERED";
-                break;
-            case mStatus_MemFree:
-                result_description = "DEREGISTERED";
-                break;
-            case mStatus_NameConflict:
-                result_description = "NAME CONFLICT";
-                break;
-            default:
-                mDNS_snprintf(description, sizeof(description), "%s %d", SuppressError ? "suppressed error" : "CALLBACK", result);
-                result_description = description;
-                break;
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegister(" PRI_DM_NAME ", %u) %s",
-                  request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name), mDNSVal16(srs->RR_SRV.resrec.rdata->u.srv.port), result_description);
-    }
-
-    if (!instance->request && result != mStatus_MemFree)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regservice_callback: instance->request is NULL %d", result);
-        return;
-    }
-
-    if (result == mStatus_NoError)
-    {
-        if (instance->request->u.servicereg.allowremotequery)
-        {
-            ExtraResourceRecord *e;
-            srs->RR_ADV.AllowRemoteQuery = mDNStrue;
-            srs->RR_PTR.AllowRemoteQuery = mDNStrue;
-            srs->RR_SRV.AllowRemoteQuery = mDNStrue;
-            srs->RR_TXT.AllowRemoteQuery = mDNStrue;
-            for (e = instance->srs.Extras; e; e = e->next) e->r.AllowRemoteQuery = mDNStrue;
-        }
-
-        if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
-        else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        if (callExternalHelpers(instance->request->u.servicereg.InterfaceID, &instance->domain, instance->request->flags))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: calling external_start_advertising_helper()", instance->request->request_id);
-            external_start_advertising_helper(instance);
-        }
-#endif
-        if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0)
-            RecordUpdatedNiceLabel(0);   // Successfully got new name, tell user immediately
-    }
-    else if (result == mStatus_MemFree)
-    {
-        if (instance->request && instance->renameonmemfree)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            external_stop_advertising_helper(instance);
-#endif
-            instance->renameonmemfree = 0;
-            err = mDNS_RenameAndReregisterService(m, srs, &instance->request->u.servicereg.name);
-            if (err)
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] ERROR: regservice_callback - RenameAndReregisterService returned %d", instance->request->request_id, err);
-            // error should never happen - safest to log and continue
-        }
-        else
-            unlink_and_free_service_instance(instance);
-    }
-    else if (result == mStatus_NameConflict)
-    {
-        if (instance->request->u.servicereg.autorename)
-        {
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            external_stop_advertising_helper(instance);
-#endif
-            if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0)
-            {
-                // On conflict for an autoname service, rename and reregister *all* autoname services
-                IncrementLabelSuffix(&m->nicelabel, mDNStrue);
-                mDNS_ConfigChanged(m);  // Will call back into udsserver_handle_configchange()
-            }
-            else    // On conflict for a non-autoname service, rename and reregister just that one service
-            {
-                if (instance->clientnotified) SendServiceRemovalNotification(srs);
-                mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
-            }
-        }
-        else
-        {
-            if (!SuppressError)
-            {
-                if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
-                else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
-            }
-            unlink_and_free_service_instance(instance);
-        }
-    }
-    else        // Not mStatus_NoError, mStatus_MemFree, or mStatus_NameConflict
-    {
-        if (!SuppressError)
-        {
-            if (GenerateNTDResponse(srs->RR_SRV.resrec.name, srs->RR_SRV.resrec.InterfaceID, instance->request, &rep, reg_service_reply_op, kDNSServiceFlagsAdd, result) != mStatus_NoError)
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] regservice_callback: " PRI_DM_NAME " is not valid DNS-SD SRV name", instance->request->request_id, DM_NAME_PARAM(srs->RR_SRV.resrec.name));
-            else { append_reply(instance->request, rep); instance->clientnotified = mDNStrue; }
-        }
-    }
-}
-
-mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result)
-{
-    (void)m; // Unused
-    if (!rr->RecordContext)     // parent struct already freed by termination callback
-    {
-        if (result == mStatus_NoError)
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Error: regrecord_callback: successful registration of orphaned record " PRI_S, ARDisplayString(m, rr));
-        else
-        {
-            if (result != mStatus_MemFree)
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "regrecord_callback: error %d received after parent termination", result);
-
-            // We come here when the record is being deregistered either from DNSServiceRemoveRecord or connection_termination.
-            // If the record has been updated, we need to free the rdata. Every time we call mDNS_Update, it calls update_callback
-            // with the old rdata (so that we can free it) and stores the new rdata in "rr->resrec.rdata". This means, we need
-            // to free the latest rdata for which the update_callback was never called with.
-            if (rr->resrec.rdata != &rr->rdatastorage) freeL("RData/regrecord_callback", rr->resrec.rdata);
-            freeL("AuthRecord/regrecord_callback", rr);
-        }
-    }
-    else
-    {
-        registered_record_entry *re = rr->RecordContext;
-        request_state *request = re->request;
-
-        if (mDNS_LoggingEnabled)
-        {
-            const char *result_description;
-            char description[16]; // 16-byte is enough for holding -2147483648\0
-            switch (result) {
-                case mStatus_NoError:
-                    result_description = "REGISTERED";
-                    break;
-                case mStatus_MemFree:
-                    result_description = "DEREGISTERED";
-                    break;
-                case mStatus_NameConflict:
-                    result_description = "NAME CONFLICT";
-                    break;
-                default:
-                    mDNS_snprintf(description, sizeof(description), "%d", result);
-                    result_description = description;
-                    break;
-            }
-
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegisterRecord(%u " PRI_S ")" PUB_S,
-                      request->request_id, re->key, RRDisplayString(m, &rr->resrec), result_description);
-        }
-
-        if (result != mStatus_MemFree)
-        {
-            const size_t len = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + sizeof(DNSServiceErrorType);
-            reply_state *reply = create_reply(reg_record_reply_op, len, request);
-            reply->mhdr->client_context = re->regrec_client_context;
-            reply->rhdr->flags = dnssd_htonl(0);
-            reply->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, rr->resrec.InterfaceID, mDNSfalse));
-            reply->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)result);
-            append_reply(request, reply);
-        }
-
-        if (result)
-        {
-            // If this is a callback to a keepalive record, do not free it.
-            if (result == mStatus_BadStateErr)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u] regrecord_callback: Callback with error code mStatus_BadStateErr - not freeing the record.", request->request_id);
-            }
-            else
-            {
-                // unlink from list, free memory
-                registered_record_entry **ptr = &request->u.reg_recs;
-                while (*ptr && (*ptr) != re) ptr = &(*ptr)->next;
-                if (!*ptr)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                              "[R%u] regrecord_callback - record not in list!", request->request_id);
-                    return;
-                }
-                *ptr = (*ptr)->next;
-                freeL("registered_record_entry AuthRecord regrecord_callback", re->rr);
-                freeL("registered_record_entry regrecord_callback", re);
-             }
-        }
-        else
-        {
-            if (re->external_advertise)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u] regrecord_callback: external_advertise already set!", request->request_id);
-            }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            if (callExternalHelpers(re->origInterfaceID, &rr->namestorage, request->flags))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                          "[R%u] regrecord_callback: calling external_start_advertising_service", request->request_id);
-                external_start_advertising_service(&rr->resrec, request->flags, request->process_id);
-                re->external_advertise = mDNStrue;
-            }
-#endif
-        }
-    }
-}
-
-// set_peer_pid() is called after mem is allocated for each new request in NewRequest()
-// This accounts for 2 places (connect_callback, request_callback)
-mDNSlocal void set_peer_pid(request_state *request)
-{
-    request->pid_name[0] = '\0';
-    request->process_id  = -1;
-#ifdef LOCAL_PEEREPID
-    pid_t           p    = (pid_t) -1;
-    socklen_t       len  = sizeof(p);
-    if (request->sd < 0)
-        return;
-    // to extract the effective pid value
-    if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &p, &len) != 0)
-        return;
-    debugf("set_peer_pid: Client PEEREPID is %d", p);
-    request->process_id = p;
-#else   // !LOCAL_PEEREPID
-    LogInfo("set_peer_pid: Not Supported on this version of OS");
-    if (request->sd < 0)
-        return;
-#endif  // LOCAL_PEEREPID
-}
-
-mDNSlocal void connection_termination(request_state *request)
-{
-    // When terminating a shared connection, we need to scan the all_requests list
-    // and terminate any subbordinate operations sharing this file descriptor
-    request_state **req = &all_requests;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceCreateConnection STOP PID[%d](" PUB_S ")",
-           request->request_id, request->process_id, request->pid_name);
-
-    while (*req)
-    {
-        if ((*req)->primary == request)
-        {
-            // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
-            request_state *tmp = *req;
-            if (tmp->primary == tmp) LogMsg("connection_termination ERROR (*req)->primary == *req for %p %d",                  tmp, tmp->sd);
-            if (tmp->replies) LogMsg("connection_termination ERROR How can subordinate req %p %d have replies queued?", tmp, tmp->sd);
-            abort_request(tmp);
-            *req = tmp->next;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-            mdns_trust_forget(&tmp->trust);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-            mdns_forget(&tmp->signed_obj);
-#endif
-            freeL("request_state/connection_termination", tmp);
-        }
-        else
-            req = &(*req)->next;
-    }
-
-    while (request->u.reg_recs)
-    {
-        registered_record_entry *ptr = request->u.reg_recs;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") STOP PID[%d](" PUB_S ")",
-               request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ptr->rr->resrec), request->process_id,
-               request->pid_name);
-        request->u.reg_recs = request->u.reg_recs->next;
-        ptr->rr->RecordContext = NULL;
-        if (ptr->external_advertise)
-        {
-            ptr->external_advertise = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            external_stop_advertising_service(&ptr->rr->resrec, request->flags, request->process_id);
-#endif
-        }
-        LogMcastS(ptr->rr, request, reg_stop);
-        mDNS_Deregister(&mDNSStorage, ptr->rr);     // Will free ptr->rr for us
-        freeL("registered_record_entry/connection_termination", ptr);
-    }
-}
-
-mDNSlocal void handle_cancel_request(request_state *request)
-{
-    request_state **req = &all_requests;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%d] Cancel %08X %08X",
-           request->request_id, request->hdr.client_context.u32[1], request->hdr.client_context.u32[0]);
-    while (*req)
-    {
-        if ((*req)->primary == request &&
-            (*req)->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
-            (*req)->hdr.client_context.u32[1] == request->hdr.client_context.u32[1])
-        {
-            // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
-            request_state *tmp = *req;
-            abort_request(tmp);
-            *req = tmp->next;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-            mdns_trust_forget(&tmp->trust);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-            mdns_forget(&tmp->signed_obj);
-#endif
-            freeL("request_state/handle_cancel_request", tmp);
-        }
-        else
-            req = &(*req)->next;
-    }
-}
-
-mDNSlocal mStatus _handle_regrecord_request_start(request_state *request, AuthRecord * rr)
-{
-    mStatus err;
-    registered_record_entry *re;
-    // Don't allow non-local domains to be regsitered as LocalOnly. Allowing this would permit
-    // clients to register records such as www.bigbank.com A w.x.y.z to redirect Safari.
-    if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly && !IsLocalDomain(rr->resrec.name) &&
-        rr->resrec.rrclass == kDNSClass_IN && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA ||
-                                               rr->resrec.rrtype == kDNSType_CNAME))
-    {
-        freeL("AuthRecord/handle_regrecord_request", rr);
-        return (mStatus_BadParamErr);
-    }
-    // allocate registration entry, link into list
-    re = (registered_record_entry *) callocL("registered_record_entry", sizeof(*re));
-    if (!re) FatalError("ERROR: calloc");
-    re->key                   = request->hdr.reg_index;
-    re->rr                    = rr;
-    re->regrec_client_context = request->hdr.client_context;
-    re->request               = request;
-    re->external_advertise    = mDNSfalse;
-    rr->RecordContext         = re;
-    rr->RecordCallback        = regrecord_callback;
-    rr->ForceMCast            = ((request->flags & kDNSServiceFlagsForceMulticast) != 0);
-
-    re->origInterfaceID = rr->resrec.InterfaceID;
-    if (rr->resrec.InterfaceID == mDNSInterface_P2P)
-        rr->resrec.InterfaceID = mDNSInterface_Any;
-#if 0
-    if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError);
-#endif
-    if (rr->resrec.rroriginalttl == 0)
-        rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") START PID[%d](" PUB_S ")",
-           request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &rr->resrec), request->process_id,
-           request->pid_name);
-
-    err = mDNS_Register(&mDNSStorage, rr);
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceRegisterRecord(0x%X, %d," PRI_S ") ERROR (%d)",
-               request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &rr->resrec), err);
-        freeL("registered_record_entry", re);
-        freeL("registered_record_entry/AuthRecord", rr);
-    }
-    else
-    {
-        LogMcastS(rr, request, reg_start);
-        re->next = request->u.reg_recs;
-        request->u.reg_recs = re;
-    }
-    return err;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_regrecord_request_error(request_state *request, mStatus error)
-{
-    reply_state *rep;
-    if (GenerateNTDResponse(NULL, 0, request, &rep, reg_record_reply_op, 0, error) != mStatus_NoError)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegisterRecord _return_regrecord_request_error: error(%d)", request->request_id, error);
-    }
-    else
-    {
-        append_reply(request, rep);
-    }
-}
-
-mDNSlocal mStatus _handle_regrecord_request_with_trust(request_state *request, AuthRecord * rr)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_regrecord_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_regrecord_request_start(request, rr);
-    }
-    else
-    {
-        const char *service_ptr = NULL;
-        char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
-        domainlabel name;
-        domainname type, domain;
-        bool good = DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
-        if (good)
-        {
-            ConvertDomainNameToCString(&type, type_str);
-            service_ptr = type_str;
-        }
-
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, service_ptr, &flags);
-        switch (status)
-        {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, service_ptr, flags);
-                if (!trust)
-                {
-                    freeL("AuthRecord/_handle_regrecord_request_with_trust", rr);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                mdns_trust_set_context(trust, rr);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("AuthRecord/_handle_regrecord_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        AuthRecord * _rr =  mdns_trust_get_context(trust);
-                        if (_rr)
-                        {
-                            if (!error)
-                            {
-                                mdns_trust_set_context(trust, NULL); // _handle_regrecord_request_start handles free
-                                error = _handle_regrecord_request_start(request, _rr);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_regrecord_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_handle_regrecord_request_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_regrecord_request_start(request, rr);
-                break;
-        }
-     }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-// Add a TSR record when DNSServiceRegisterRecordWithAttribute is called with timestamp set correctly
-mDNSlocal mStatus regRecordAddTSRRecord(request_state *const request, AuthRecord *const rr, const mDNSs32 tsrTimestamp)
-{
-    mStatus err = mStatus_NoError;
-    AuthRecord *ar;
-    size_t rdcapacity = sizeof(RDataBody2);
-
-    ar = (AuthRecord *) callocL("AuthRecord/regRecordAddTSRRecord", sizeof(*ar) - sizeof(RDataBody) + rdcapacity);
-    if (!ar)
-    {
-        FatalError("ERROR: calloc");
-    }
-    mDNS_SetupResourceRecord(ar, mDNSNULL, rr->resrec.InterfaceID, kDNSType_TSR, kHostNameTTL, rr->resrec.RecordType, rr->ARType, mDNSNULL, mDNSNULL);
-    AssignDomainName(&ar->namestorage, rr->resrec.name);
-    ar->resrec.rdlength = (mDNSu16)sizeof(tsrTimestamp);
-    ar->resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
-    // tsr timestamp in memory is time of receipt
-    ar->resrec.rdata->u.tsr_value = tsrTimestamp;
-    ar->resrec.namehash = DomainNameHashValue(ar->resrec.name);
-    SetNewRData(&ar->resrec, mDNSNULL, 0);  // Sets ar->rdatahash for us
-
-    ar->ForceMCast            = ((request->flags & kDNSServiceFlagsForceMulticast) != 0);
-    LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%d] DNSServiceRegisterRecord(0x%X, %d, " PRI_S ") START PID[%d](" PUB_S ")",
-              request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ar->resrec),
-              request->process_id, request->pid_name);
-
-    err = mDNS_Register(&mDNSStorage, ar);
-    if (err)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "[R%d] DNSServiceRegisterRecord(0x%X, %d," PRI_S ") ERROR (%d)",
-                  request->request_id, request->flags, request->interfaceIndex, RRDisplayString(&mDNSStorage, &ar->resrec), err);
-        freeL("registered_record_entry/AuthRecord", ar);
-    }
-    else
-    {
-        LogMcastS(ar, request, reg_start);
-        ar->RRSet = (uintptr_t)request->sd;
-    }
-    return err;
-}
-
-mDNSlocal mStatus updateTSRRecord(const request_state *const request, AuthRecord *const tsr, const mDNSs32 tsrTimestamp)
-{
-    mStatus err = mStatus_NoError;
-    const RDataBody2 *const rdb = (RDataBody2 *)tsr->resrec.rdata->u.data;
-    mDNSu32 unsignedTimestamp = (mDNSu32)tsrTimestamp;
-    LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "TSR timestamp - name: " PRI_DM_NAME ", new: %d  old: %d",
-              DM_NAME_PARAM(tsr->resrec.name), tsrTimestamp, rdb->tsr_value);
-    if (tsrTimestamp - rdb->tsr_value < 0)
-    {
-        const mDNSu8 rdata[4] = { (unsignedTimestamp >> 24) & 0xFF, (unsignedTimestamp >> 16) & 0xFF,
-            (unsignedTimestamp >> 8) & 0xFF, unsignedTimestamp & 0xFF};
-        err = update_record(tsr, sizeof(rdata), rdata, kHostNameTTL, mDNSNULL, request->request_id);
-    }
-    return err;
-}
-
-mDNSlocal mDNSBool validateTSRTimestamp(mDNSs32 *timestampContinuous, mDNSu32 tsrTimestamp, const AuthRecord *rr)
-{
-    if (tsrTimestamp > MaxTimeSinceReceived)
-    {
-        if (rr != NULL)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "tsrTimestamp[%u] out of range (%u) on TSR for " PRI_DM_NAME "",
-                      tsrTimestamp, MaxTimeSinceReceived, DM_NAME_PARAM(rr->resrec.name));
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
-                      "tsrTimestamp[%u] out of range (%u) on TSR", tsrTimestamp, MaxTimeSinceReceived);
-        }
-
-        return mDNSfalse;
-    }
-    *timestampContinuous = mDNSPlatformContinuousTimeSeconds() - (mDNSs32)tsrTimestamp;
-    return mDNStrue;
-}
-
-mDNSlocal mStatus handle_regrecord_request(request_state *request)
-{
-    mStatus err = mStatus_BadParamErr;
-    AuthRecord *rr;
-
-    if (request->terminate != connection_termination)
-    { LogMsg("%3d: DNSServiceRegisterRecord(not a shared connection ref)", request->sd); return(err); }
-
-    rr = read_rr_from_ipc_msg(request, 1, 1);
-    if (rr)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-        if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
-            IsLocalDomain(rr->resrec.name))
-        {
-            err = _handle_regrecord_request_with_trust(request, rr);
-        }
-        else
-        {
-            err = _handle_regrecord_request_start(request, rr);
-        }
-#else
-        err = _handle_regrecord_request_start(request, rr);
-#endif
-    }
-    if (!err)
-    {
-        mDNSBool foundTimestampTLV = mDNSfalse;
-        const mDNSu32 tsrTimestamp = get_service_attr_timestamp_value(request, &foundTimestampTLV);
-
-        if (foundTimestampTLV)
-        {
-            AuthRecord *currentTSR = mDNSGetTSRRecord(&mDNSStorage, rr);
-            mDNSs32 timestampContinuous;
-            if (!validateTSRTimestamp(&timestampContinuous, tsrTimestamp, rr))
-            {
-                return err;
-            }
-            if (currentTSR)
-            {
-                err = updateTSRRecord(request, currentTSR, timestampContinuous);
-            }
-            else
-            {
-                err = regRecordAddTSRRecord(request, rr, timestampContinuous);
-            }
-            if (!err)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT,
-                          "handle_regrecord_request: TSR record added with tsrTimestamp %d",
-                          timestampContinuous);
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR,
-                          "handle_regrecord_request: Failed to add TSR record with tsrTimestamp %d error %d",
-                          timestampContinuous, err);
-            }
-        }
-        rr->RRSet = (uintptr_t)request->sd;
-    }
-
-    return(err);
-}
-
-mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
-
-mDNSlocal void regservice_termination_callback(request_state *request)
-{
-    if (!request)
-    {
-        LogMsg("regservice_termination_callback context is NULL");
-        return;
-    }
-    while (request->u.servicereg.instances)
-    {
-        service_instance *p = request->u.servicereg.instances;
-        request->u.servicereg.instances = request->u.servicereg.instances->next;
-        // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d] DNSServiceRegister(" PRI_DM_NAME ", %u) STOP PID[%d](" PUB_S ")",
-               request->request_id, DM_NAME_PARAM(p->srs.RR_SRV.resrec.name),
-               mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port), request->process_id, request->pid_name);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        external_stop_advertising_helper(p);
-#endif
-
-        // Clear backpointer *before* calling mDNS_DeregisterService/unlink_and_free_service_instance
-        // We don't need unlink_and_free_service_instance to cut its element from the list, because we're already advancing
-        // request->u.servicereg.instances as we work our way through the list, implicitly cutting one element at a time
-        // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance
-        // because by then we might have already freed p
-        p->request = NULL;
-        LogMcastS(&p->srs.RR_SRV, request, reg_stop);
-        if (mDNS_DeregisterService(&mDNSStorage, &p->srs))
-        {
-            unlink_and_free_service_instance(p);
-            // Don't touch service_instance *p after this -- it's likely to have been freed already
-        }
-    }
-    if (request->u.servicereg.txtdata)
-    {
-        freeL("service_info txtdata", request->u.servicereg.txtdata);
-        request->u.servicereg.txtdata = NULL;
-    }
-    if (request->u.servicereg.autoname)
-    {
-        // Clear autoname before calling UpdateDeviceInfoRecord() so it doesn't mistakenly include this in its count of active autoname registrations
-        request->u.servicereg.autoname = mDNSfalse;
-        UpdateDeviceInfoRecord(&mDNSStorage);
-    }
-}
-
-mDNSlocal request_state *LocateSubordinateRequest(request_state *request)
-{
-    request_state *req;
-    for (req = all_requests; req; req = req->next)
-        if (req->primary == request &&
-            req->hdr.client_context.u32[0] == request->hdr.client_context.u32[0] &&
-            req->hdr.client_context.u32[1] == request->hdr.client_context.u32[1]) return(req);
-    return(request);
-}
-
-mDNSlocal mStatus add_record_to_service(request_state *request, service_instance *instance, mDNSu16 rrtype, mDNSu16 rdlen,
-    const mDNSu8 *const rdata, mDNSu32 ttl)
-{
-    ServiceRecordSet *srs = &instance->srs;
-    mStatus result;
-    const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
-    ExtraResourceRecord *extra = (ExtraResourceRecord *)callocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + rdcapacity);
-    if (!extra) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
-
-    extra->r.resrec.rrtype = rrtype;
-    extra->r.resrec.rdata = &extra->r.rdatastorage;
-    extra->r.resrec.rdata->MaxRDLength = (mDNSu16)rdcapacity;
-    extra->r.resrec.rdlength = rdlen;
-    if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &extra->r.resrec, rdlen))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[R%u] read_rr_from_ipc_msg: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
-            request->request_id, DM_NAME_PARAM(request->u.servicereg.instances ?
-            request->u.servicereg.instances->srs.RR_SRV.resrec.name : mDNSNULL), DNSTypeName(rrtype));
-        freeL("ExtraResourceRecord/add_record_to_service", extra);
-        return mStatus_BadParamErr;
-    }
-    SetNewRData(&extra->r.resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-    // use InterfaceID value from DNSServiceRegister() call that created the original service
-    extra->r.resrec.InterfaceID = request->u.servicereg.InterfaceID;
-
-    result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, request->flags);
-    if (result)
-    {
-        freeL("ExtraResourceRecord/add_record_to_service", extra);
-        return result;
-    }
-    LogMcastS(&srs->RR_PTR, request, reg_start);
-
-    extra->ClientID = request->hdr.reg_index;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    if (   instance->external_advertise
-           && callExternalHelpers(request->u.servicereg.InterfaceID, &instance->domain, request->flags))
-    {
-        LogInfo("add_record_to_service: calling external_start_advertising_service");
-        external_start_advertising_service(&extra->r.resrec, request->flags, request->process_id);
-    }
-#endif
-    return result;
-}
-
-mDNSlocal mStatus handle_add_request(request_state *request)
-{
-    service_instance *i;
-    mStatus result = mStatus_UnknownErr;
-    DNSServiceFlags flags  = get_flags (&request->msgptr, request->msgend);
-    mDNSu16 rrtype = get_uint16(&request->msgptr, request->msgend);
-    mDNSu16 rdlen  = get_uint16(&request->msgptr, request->msgend);
-    const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
-    mDNSu32 ttl    = get_uint32(&request->msgptr, request->msgend);
-    if (!ttl) ttl = DefaultTTLforRRType(rrtype);
-    (void)flags; // Unused
-
-    if (!request->msgptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceAddRecord(unreadable parameters)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
-    if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
-
-    if (request->terminate != regservice_termination_callback)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceAddRecord(not a registered service ref)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    // For a service registered with zero port, don't allow adding records. This mostly happens due to a bug
-    // in the application. See radar://9165807.
-    if (mDNSIPPortIsZero(request->u.servicereg.port))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceAddRecord: adding record to a service registered with zero port", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceAddRecord(%X, " PRI_DM_NAME ", " PUB_S ", %d) PID[%d](" PUB_S ")",
-           request->request_id, flags,
-           DM_NAME_PARAM((request->u.servicereg.instances) ? (request->u.servicereg.instances->srs.RR_SRV.resrec.name) : mDNSNULL),
-           DNSTypeName(rrtype), rdlen, request->process_id, request->pid_name);
-
-    for (i = request->u.servicereg.instances; i; i = i->next)
-    {
-        result = add_record_to_service(request, i, rrtype, rdlen, rdata, ttl);
-        if (result && i->default_local) break;
-        else result = mStatus_NoError;  // suppress non-local default errors
-    }
-
-    return(result);
-}
-
-mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd, mDNSu16 oldrdlen)
-{
-    mDNSBool external_advertise = (rr->UpdateContext) ? *((mDNSBool *)rr->UpdateContext) : mDNSfalse;
-    (void)m; // Unused
-
-    // There are three cases.
-    //
-    // 1. We have updated the primary TXT record of the service
-    // 2. We have updated the TXT record that was added to the service using DNSServiceAddRecord
-    // 3. We have updated the TXT record that was registered using DNSServiceRegisterRecord
-    //
-    // external_advertise is set if we have advertised at least once during the initial addition
-    // of the record in all of the three cases above. We should have checked for InterfaceID/LocalDomain
-    // checks during the first time and hence we don't do any checks here
-    if (external_advertise)
-    {
-        ResourceRecord ext = rr->resrec;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(rr->ARType);
-#endif
-
-        if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
-        SetNewRData(&ext, oldrd, oldrdlen);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        external_stop_advertising_service(&ext, flags, 0);
-        LogRedact(MDNS_LOG_CATEGORY_D2D, MDNS_LOG_DEFAULT, "update_callback: calling external_start_advertising_service");
-        external_start_advertising_service(&rr->resrec, flags, 0);
-#endif
-    }
-exit:
-    if (oldrd != &rr->rdatastorage) freeL("RData/update_callback", oldrd);
-}
-
-mDNSlocal mStatus update_record(AuthRecord *ar, mDNSu16 rdlen, const mDNSu8 *const rdata, mDNSu32 ttl,
-    const mDNSBool *const external_advertise, const mDNSu32 request_id)
-{
-    ResourceRecord rr;
-    mStatus result;
-    const size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
-    RData *newrd = (RData *) callocL("RData/update_record", sizeof(*newrd) - sizeof(RDataBody) + rdcapacity);
-    if (!newrd) FatalError("ERROR: calloc");
-    mDNSPlatformMemZero(&rr, (mDNSu32)sizeof(rr));
-    rr.name     = ar->resrec.name;
-    rr.rrtype   = ar->resrec.rrtype;
-    rr.rrclass  = ar->resrec.rrclass;
-    rr.rdata    = newrd;
-    rr.rdata->MaxRDLength = (mDNSu16)rdcapacity;
-    rr.rdlength = rdlen;
-    if (!SetRData(mDNSNULL, rdata, rdata + rdlen, &rr, rdlen))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[R%u] update_record: SetRData failed for " PRI_DM_NAME " (" PUB_S ")",
-            request_id, DM_NAME_PARAM(rr.name), DNSTypeName(rr.rrtype));
-        freeL("RData/update_record", newrd);
-        return mStatus_BadParamErr;
-    }
-    rdlen = GetRDLength(&rr, mDNSfalse);
-    // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
-    // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
-    // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
-    if (ar->resrec.rrtype == kDNSType_TXT && rdlen == 0) { rdlen = 1; newrd->u.txt.c[0] = 0; }
-
-    if (external_advertise) ar->UpdateContext = (void *)external_advertise;
-
-    result = mDNS_Update(&mDNSStorage, ar, ttl, rdlen, newrd, update_callback);
-    if (result) { LogMsg("update_record: Error %d for %s", (int)result, ARDisplayString(&mDNSStorage, ar)); freeL("RData/update_record", newrd); }
-    return result;
-}
-
-mDNSlocal mStatus handle_tsr_update_request(const request_state *const request, const AuthRecord *const rr, const mDNSu32 tsrTimestamp)
-{
-    mStatus result = mStatus_NoError;
-    AuthRecord *currentTSR = mDNSGetTSRRecord(&mDNSStorage, rr);
-    mDNSs32 timestampContinuous;
-    if (!validateTSRTimestamp(&timestampContinuous, tsrTimestamp, rr))
-    {
-        result = mStatus_BadParamErr;
-        goto end;
-    }
-    if (currentTSR)
-    {
-        result = updateTSRRecord(request, currentTSR, timestampContinuous);
-    }
-    else
-    {
-       LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "No existing TSR for " PRI_DM_NAME "", DM_NAME_PARAM(rr->resrec.name));
-       result = mStatus_BadReferenceErr;
-       goto end;
-    }
-
-end:
-    return result;
-}
-
-mDNSlocal mStatus handle_update_request(request_state *request)
-{
-    const ipc_msg_hdr *const hdr = &request->hdr;
-    mStatus result = mStatus_BadReferenceErr;
-    service_instance *i;
-    AuthRecord *rr = NULL;
-    mDNSBool foundTimestampTLV = mDNSfalse;
-
-    // get the message data
-    DNSServiceFlags flags = get_flags (&request->msgptr, request->msgend);  // flags unused
-    mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
-    const mDNSu8 *const rdata = (const mDNSu8 *)get_rdata(&request->msgptr, request->msgend, rdlen);
-    mDNSu32 ttl   = get_uint32(&request->msgptr, request->msgend);
-    (void)flags; // Unused
-
-    if (!request->msgptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceUpdateRecord(unreadable parameters)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    const mDNSu32 tsrTimestamp = get_service_attr_timestamp_value(request, &foundTimestampTLV);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "[R%d] DNSServiceUpdateRecord foundTimestampTLV[%s], tsrTimestamp[%u]", request->request_id,
-            foundTimestampTLV ? "true" : "false", tsrTimestamp);
-
-    // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
-    if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
-
-    if (request->terminate == connection_termination)
-    {
-        // update an individually registered record
-        registered_record_entry *reptr;
-        for (reptr = request->u.reg_recs; reptr; reptr = reptr->next)
-        {
-            if (reptr->key == hdr->reg_index)
-            {
-                if (foundTimestampTLV)
-                {
-                    result = handle_tsr_update_request(request, reptr->rr, tsrTimestamp);
-                }
-                else
-                {
-                    result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise, request->request_id);
-                }
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                       "[R%d] DNSServiceUpdateRecord(" PRI_DM_NAME ", " PUB_S ") PID[%d](" PUB_S ")",
-                       request->request_id, DM_NAME_PARAM(reptr->rr->resrec.name),
-                       reptr->rr ? foundTimestampTLV ? "TSR" : DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>",
-                       request->process_id, request->pid_name);
-                goto end;
-            }
-        }
-        result = mStatus_BadReferenceErr;
-        goto end;
-    }
-
-    if (request->terminate != regservice_termination_callback)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceUpdateRecord(not a registered service ref)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    // For a service registered with zero port, only SRV record is initialized. Don't allow any updates.
-    if (mDNSIPPortIsZero(request->u.servicereg.port))
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceUpdateRecord: updating the record of a service registered with zero port", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    // update the saved off TXT data for the service
-    if (!foundTimestampTLV && hdr->reg_index == TXT_RECORD_INDEX)
-    {
-        if (request->u.servicereg.txtdata)
-        { freeL("service_info txtdata", request->u.servicereg.txtdata); request->u.servicereg.txtdata = NULL; }
-        if (rdlen > 0)
-        {
-            request->u.servicereg.txtdata = mallocL("service_info txtdata", rdlen);
-            if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_update_request - malloc");
-            mDNSPlatformMemCopy(request->u.servicereg.txtdata, rdata, rdlen);
-        }
-        request->u.servicereg.txtlen = rdlen;
-    }
-
-    // update a record from a service record set
-    for (i = request->u.servicereg.instances; i; i = i->next)
-    {
-        if (hdr->reg_index == TXT_RECORD_INDEX) rr = &i->srs.RR_TXT;
-        else
-        {
-            ExtraResourceRecord *e;
-            for (e = i->srs.Extras; e; e = e->next)
-                if (e->ClientID == hdr->reg_index) { rr = &e->r; break; }
-        }
-
-        if (!rr) { result = mStatus_BadReferenceErr; goto end; }
-        if (foundTimestampTLV)
-        {
-            result = handle_tsr_update_request(request, rr, tsrTimestamp);
-            goto end;
-        }
-        else
-        {
-            result = update_record(rr, rdlen, rdata, ttl, &i->external_advertise, request->request_id);
-        }
-        if (result && i->default_local) goto end;
-        else result = mStatus_NoError;  // suppress non-local default errors
-    }
-
-end:
-    if (request->terminate == regservice_termination_callback)
-        LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)  PID[%d](%s)", request->sd,
-                     (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL,
-                     rr ? foundTimestampTLV ? "TSR" : DNSTypeName(rr->resrec.rrtype) : "<NONE>",
-                     request->process_id, request->pid_name);
-
-    return(result);
-}
-
-// remove a resource record registered via DNSServiceRegisterRecord()
-mDNSlocal mStatus remove_record(request_state *request)
-{
-    mStatus err = mStatus_UnknownErr;
-    registered_record_entry *e, **ptr = &request->u.reg_recs;
-
-    while (*ptr && (*ptr)->key != request->hdr.reg_index) ptr = &(*ptr)->next;
-    if (!*ptr) { LogMsg("%3d: DNSServiceRemoveRecord(%u) not found", request->sd, request->hdr.reg_index); return mStatus_BadReferenceErr; }
-    e = *ptr;
-    *ptr = e->next; // unlink
-
-    LogOperation("%3d: DNSServiceRemoveRecord(%u %s)  PID[%d](%s)",
-                request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec), request->process_id, request->pid_name);
-    e->rr->RecordContext = NULL;
-    if (e->external_advertise)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        external_stop_advertising_service(&e->rr->resrec, request->flags, request->process_id);
-#endif
-        e->external_advertise = mDNSfalse;
-    }
-    LogMcastS(e->rr, request, reg_stop);
-    err = mDNS_Deregister(&mDNSStorage, e->rr);     // Will free e->rr for us; we're responsible for freeing e
-    if (err)
-    {
-        LogMsg("ERROR: remove_record, mDNS_Deregister: %d", err);
-        freeL("registered_record_entry AuthRecord remove_record", e->rr);
-    }
-    freeL("registered_record_entry remove_record", e);
-    return err;
-}
-
-mDNSlocal mStatus remove_extra(const request_state *const request, service_instance *const serv, mDNSu16 *const rrtype)
-{
-    mStatus err = mStatus_BadReferenceErr;
-    ExtraResourceRecord *ptr;
-
-    for (ptr = serv->srs.Extras; ptr; ptr = ptr->next)
-    {
-        if (ptr->ClientID == request->hdr.reg_index) // found match
-        {
-            *rrtype = ptr->r.resrec.rrtype;
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            if (serv->external_advertise)
-            {
-                external_stop_advertising_service(&ptr->r.resrec, request->flags, request->process_id);
-            }
-#endif
-            err = mDNS_RemoveRecordFromService(&mDNSStorage, &serv->srs, ptr, FreeExtraRR, ptr);
-            break;
-        }
-    }
-    return err;
-}
-
-mDNSlocal mStatus handle_removerecord_request(request_state *request)
-{
-    mStatus err = mStatus_BadReferenceErr;
-    get_flags(&request->msgptr, request->msgend);   // flags unused
-
-    if (!request->msgptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceRemoveRecord(unreadable parameters)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    // If this is a shared connection, check if the operation actually applies to a subordinate request_state object
-    if (request->terminate == connection_termination) request = LocateSubordinateRequest(request);
-
-    // LocateSubordinateRequest returns the connection it was passed if the request is not referring to a
-    // subordinate request. In this case, if request->terminate == connection_terminate, that means that this
-    // is a connection created with DNSServiceCreateConnection, and so the remove would have to apply to a
-    // record added with DNSServiceRegisterRecord. We can remove this using remove_record.
-    if (request->terminate == connection_termination)
-        err = remove_record(request);
-
-    // Otherwise, the only type of request object to which DNSServiceRemoveRecord could apply is one that
-    // was created with DNSServiceRegister, which is indicated by request->terminate == regservice_termination_callback.
-    // So if that's not the case, the request is invalid.
-    else if (request->terminate != regservice_termination_callback)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%d] DNSServiceRemoveRecord(not a registered service ref)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-    else
-    {
-        service_instance *i;
-        mDNSu16 rrtype = 0;
-        // In this case request is a request created with DNSServiceRegister, and there may be more than one
-        // instance if there is more than one default registration domain, so we have to iterate across the
-        // instances and remove the record from each instance individually, if it is present.
-        for (i = request->u.servicereg.instances; i; i = i->next)
-        {
-            err = remove_extra(request, i, &rrtype);
-            if (err && i->default_local) break;
-            else err = mStatus_NoError;  // suppress non-local default errors
-        }
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%d] DNSServiceRemoveRecord(" PRI_DM_NAME ", " PUB_S ") PID[%d](" PUB_S "): %d",
-                  request->request_id,
-                  DM_NAME_PARAM((request->u.servicereg.instances)
-                                ? (request->u.servicereg.instances->srs.RR_SRV.resrec.name)
-                                : mDNSNULL),
-                  rrtype ? DNSTypeName(rrtype) : "<NONE>", request->process_id, request->pid_name, err);
-    }
-
-    return(err);
-}
-
-// If there's a comma followed by another character,
-// FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character.
-// Otherwise, it returns a pointer to the final nul at the end of the string
-mDNSlocal char *FindFirstSubType(char *p)
-{
-    while (*p)
-    {
-        if (p[0] == '\\' && p[1])
-        {
-             p += 2;
-        }
-        else if (p[0] == ',' && p[1])
-        {
-            *p++ = 0;
-            return(p);
-        }
-        else
-        {
-            p++;
-        }
-    }
-    return(p);
-}
-
-// If there's a comma followed by another character,
-// FindNextSubType overwrites the comma with a nul and returns the pointer to the next character.
-// If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL
-// Otherwise, it returns a pointer to the final nul at the end of the string
-mDNSlocal char *FindNextSubType(char *p)
-{
-    while (*p)
-    {
-        if (p[0] == '\\' && p[1])       // If escape character
-            p += 2;                     // ignore following character
-        else if (p[0] == ',')           // If we found a comma
-        {
-            if (p[1]) *p++ = 0;
-            return(p);
-        }
-        else if (p[0] == '.')
-            return(mDNSNULL);
-        else p++;
-    }
-    return(p);
-}
-
-// Returns -1 if illegal subtype found
-mDNSlocal mDNSs32 ChopSubTypes(char *regtype)
-{
-    mDNSs32 NumSubTypes = 0;
-    char *stp = FindFirstSubType(regtype);
-    while (stp && *stp)                 // If we found a comma...
-    {
-        if (*stp == ',') return(-1);
-        NumSubTypes++;
-        stp = FindNextSubType(stp);
-    }
-    if (!stp) return(-1);
-    return(NumSubTypes);
-}
-
-mDNSlocal AuthRecord *AllocateSubTypes(mDNSu32 NumSubTypes, char *p)
-{
-    AuthRecord *st = mDNSNULL;
-    if (NumSubTypes)
-    {
-        mDNSu32 i;
-        st = (AuthRecord *) callocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord));
-        if (!st) return(mDNSNULL);
-        for (i = 0; i < NumSubTypes; i++)
-        {
-            mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
-            while (*p) p++;
-            p++;
-            if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p))
-            {
-                freeL("ServiceSubTypes", st);
-                return(mDNSNULL);
-            }
-        }
-    }
-    return(st);
-}
-
-mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
-{
-    service_instance **ptr, *instance;
-    size_t extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
-    const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
-    mStatus result;
-    mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID;
-    mDNSBool foundTimestampTLV = mDNSfalse;
-    const mDNSu32 tsrTimestamp = get_service_attr_timestamp_value(request, &foundTimestampTLV);
-    mDNSs32 timestampContinuous = 0;
-
-    if (foundTimestampTLV)
-    {
-        if (!validateTSRTimestamp(&timestampContinuous, tsrTimestamp, NULL))
-        {
-            return mStatus_BadParamErr;
-        }
-    }
-
-    // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS)
-    // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast
-    // registrations scoped to a specific interface, so for the automatic domains we add we must *not* specify an interface.
-    // (Specifying an interface with an apparently wide-area domain (i.e. something other than "local")
-    // currently forces the registration to use mDNS multicast despite the apparently wide-area domain.)
-    if (request->u.servicereg.default_domain && !DomainIsLocal) interfaceID = mDNSInterface_Any;
-
-    for (ptr = &request->u.servicereg.instances; *ptr; ptr = &(*ptr)->next)
-    {
-        if (SameDomainName(&(*ptr)->domain, domain))
-        {
-            LogMsg("register_service_instance: domain %##s already registered for %#s.%##s",
-                   domain->c, &request->u.servicereg.name, &request->u.servicereg.type);
-            return mStatus_AlreadyRegistered;
-        }
-    }
-
-    instance = (service_instance *) callocL("service_instance", sizeof(*instance) + extra_size);
-    if (!instance) { my_perror("ERROR: calloc"); return mStatus_NoMemoryErr; }
-
-    instance->next                          = mDNSNULL;
-    instance->request                       = request;
-    instance->renameonmemfree               = 0;
-    instance->clientnotified                = mDNSfalse;
-    instance->default_local                 = (request->u.servicereg.default_domain && DomainIsLocal);
-    instance->external_advertise            = mDNSfalse;
-    AssignDomainName(&instance->domain, domain);
-
-    instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string);
-
-    if (request->u.servicereg.num_subtypes && !instance->subtypes)
-    {
-        unlink_and_free_service_instance(instance);
-        instance = NULL;
-        FatalError("ERROR: malloc");
-    }
-
-    result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
-                                  &request->u.servicereg.name, &request->u.servicereg.type, domain,
-                                  request->u.servicereg.host.c[0] ? &request->u.servicereg.host : NULL,
-                                  request->u.servicereg.port,
-                                  mDNSNULL, request->u.servicereg.txtdata, request->u.servicereg.txtlen,
-                                  instance->subtypes, request->u.servicereg.num_subtypes,
-                                  interfaceID, regservice_callback, instance, request->flags);
-    if (!result && foundTimestampTLV)
-    {
-        AuthRecord *currentTSR = mDNSGetTSRRecord(&mDNSStorage, &instance->srs.RR_SRV);
-
-        if (currentTSR)
-        {
-            result = updateTSRRecord(request, currentTSR, timestampContinuous);
-        }
-        else
-        {
-            // tsr timestamp in memory is absolute time of receipt
-            mDNSu32 uTimestamp = (mDNSu32)timestampContinuous;
-            const mDNSu8 rdata[4] = { (uTimestamp >> 24) & 0xFF, (uTimestamp >> 16) & 0xFF,
-                                      (uTimestamp >> 8)  & 0xFF,  uTimestamp        & 0xFF };
-            result = add_record_to_service(request, instance, kDNSType_TSR, sizeof(rdata), rdata, kHostNameTTL);
-        }
-        if (!result)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "TSR record added with tsrTimestamp %d", timestampContinuous);
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_ERROR, "Failed to add TSR record with tsrTimestamp %u error %d",
-                      tsrTimestamp, result);
-        }
-    }
-
-    if (!result)
-    {
-        *ptr = instance;        // Append this to the end of our request->u.servicereg.instances list
-        LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd,
-                     instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port));
-        LogMcastS(&instance->srs.RR_SRV, request, reg_start);
-    }
-    else
-    {
-        LogMsg("register_service_instance %#s.%##s%##s error %d",
-               &request->u.servicereg.name, &request->u.servicereg.type, domain->c, result);
-        unlink_and_free_service_instance(instance);
-    }
-
-    return result;
-}
-
-mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d, const mDNSBool add)
-{
-    request_state *request;
-
-    LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c);
-    for (request = all_requests; request; request = request->next)
-    {
-        if (request->terminate != regservice_termination_callback) continue;
-        if (!request->u.servicereg.default_domain) continue;
-        if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
-        {
-            service_instance **ptr = &request->u.servicereg.instances;
-            while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
-            if (add)
-            {
-                // If we don't already have this domain in our list for this registration, add it now
-                if (!*ptr) register_service_instance(request, &d->name);
-                else debugf("udsserver_default_reg_domain_changed %##s already in list, not re-adding", &d->name);
-            }
-            else
-            {
-                // Normally we should not fail to find the specified instance
-                // One case where this can happen is if a uDNS update fails for some reason,
-                // and regservice_callback then calls unlink_and_free_service_instance and disposes of that instance.
-                if (!*ptr)
-                    LogMsg("udsserver_default_reg_domain_changed domain %##s not found for service %#s type %s",
-                           &d->name, request->u.servicereg.name.c, request->u.servicereg.type_as_string);
-                else
-                {
-                    DNameListElem *p;
-                    for (p = AutoRegistrationDomains; p; p=p->next)
-                        if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
-                            if (SameDomainName(&d->name, &p->name)) break;
-                    if (p) debugf("udsserver_default_reg_domain_changed %##s still in list, not removing", &d->name);
-                    else
-                    {
-                        mStatus err;
-                        service_instance *si = *ptr;
-                        *ptr = si->next;
-                        if (si->clientnotified) SendServiceRemovalNotification(&si->srs); // Do this *before* clearing si->request backpointer
-                        // Now that we've cut this service_instance from the list, we MUST clear the si->request backpointer.
-                        // Otherwise what can happen is this: While our mDNS_DeregisterService is in the
-                        // process of completing asynchronously, the client cancels the entire operation, so
-                        // regservice_termination_callback then runs through the whole list deregistering each
-                        // instance, clearing the backpointers, and then disposing the parent request_state object.
-                        // However, because this service_instance isn't in the list any more, regservice_termination_callback
-                        // has no way to find it and clear its backpointer, and then when our mDNS_DeregisterService finally
-                        // completes later with a mStatus_MemFree message, it calls unlink_and_free_service_instance() with
-                        // a service_instance with a stale si->request backpointer pointing to memory that's already been freed.
-                        si->request = NULL;
-                        err = mDNS_DeregisterService(&mDNSStorage, &si->srs);
-                        if (err) { LogMsg("udsserver_default_reg_domain_changed err %d", err); unlink_and_free_service_instance(si); }
-                    }
-                }
-            }
-        }
-    }
-}
-
-// Returns true if the interfaceIndex value matches one of the pre-defined
-// special values listed in the switch statement below.
-mDNSlocal mDNSBool PreDefinedInterfaceIndex(mDNSu32 interfaceIndex)
-{
-    switch(interfaceIndex)
-    {
-        case kDNSServiceInterfaceIndexAny:
-        case kDNSServiceInterfaceIndexLocalOnly:
-        case kDNSServiceInterfaceIndexUnicast:
-        case kDNSServiceInterfaceIndexP2P:
-        case kDNSServiceInterfaceIndexBLE:
-            return mDNStrue;
-        default:
-            return mDNSfalse;
-    }
-}
-
-mDNSlocal mStatus _handle_regservice_request_start(request_state *request, const domainname * const d)
-{
-    mStatus err;
-
-    request->terminate = regservice_termination_callback;
-    err = register_service_instance(request, d);
-
-#if 0
-    err = AuthorizedDomain(request, d, AutoRegistrationDomains) ? register_service_instance(request, d) : mStatus_NoError;
-#endif
-    if (!err)
-    {
-        if (request->u.servicereg.autoname) UpdateDeviceInfoRecord(&mDNSStorage);
-
-        if (request->u.servicereg.default_domain)
-        {
-            DNameListElem *ptr;
-            // Note that we don't report errors for non-local, non-explicit domains
-            for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
-                if (!ptr->uid || SystemUID(request->uid) || request->uid == ptr->uid)
-                    register_service_instance(request, &ptr->name);
-        }
-    }
-    return err;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_regservice_request_error(request_state *request, mStatus error)
-{
-    if (request->u.servicereg.txtdata)
-    {
-        freeL("service_info txtdata", request->u.servicereg.txtdata);
-        request->u.servicereg.txtdata = NULL;
-    }
-
-    reply_state *rep;
-    if (GenerateNTDResponse(NULL, 0, request, &rep, reg_service_reply_op, 0, error) != mStatus_NoError)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceRegister _return_regservice_request_error: error(%d)", request->request_id, error);
-    }
-    else
-    {
-        append_reply(request, rep);
-    }
-}
-
-mDNSlocal mStatus _handle_regservice_request_with_trust(request_state *request, const domainname * const d)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_regservice_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_regservice_request_start(request, d);
-    }
-    else
-    {
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_register_service(request->audit_token, request->u.servicereg.type_as_string, &flags);
-        switch (status) {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, request->u.servicereg.type_as_string, flags);
-                if (!trust)
-                {
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                void * context = mallocL("context/_handle_regservice_request_with_trust", sizeof(domainname));
-                if (!context)
-                {
-                    my_perror("ERROR: mallocL context/_handle_regservice_request_with_trust");
-                    mdns_release(trust);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                memcpy(context, d, sizeof(domainname));
-                mdns_trust_set_context(trust, context);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("context/_handle_regservice_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        const domainname * _d = mdns_trust_get_context(trust);
-                        if (_d)
-                        {
-                            if (!error)
-                            {
-                                error = _handle_regservice_request_start(request, _d);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_regservice_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_register_service_instance_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_regservice_request_start(request, d);
-                break;
-        }
-    }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-mDNSlocal mStatus handle_regservice_request(request_state *request)
-{
-    char name[256]; // Lots of spare space for extra-long names that we'll auto-truncate down to 63 bytes
-    char domain[MAX_ESCAPED_DOMAIN_NAME], host[MAX_ESCAPED_DOMAIN_NAME];
-    char type_as_string[MAX_ESCAPED_DOMAIN_NAME];  // Note that this service type may include a trailing list of subtypes
-    domainname d, srv;
-    mStatus err;
-    const uint8_t *msgTXTData;
-
-    DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    mDNSInterfaceID InterfaceID;
-    mDNSs32 subtypeCount;
-
-    // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the
-    // kDNSServiceFlagsIncludeP2P flag set.
-    if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
-    {
-        LogOperation("handle_regservice_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
-        flags |= kDNSServiceFlagsIncludeP2P;
-        interfaceIndex = kDNSServiceInterfaceIndexAny;
-    }
-
-    InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-
-    // The registration is scoped to a specific interface index, but the
-    // interface is not currently in our list.
-    if (interfaceIndex && !InterfaceID)
-    {
-        // If it's one of the specially defined inteface index values, just return an error.
-        if (PreDefinedInterfaceIndex(interfaceIndex))
-        {
-            LogInfo("handle_regservice_request: bad interfaceIndex %d", interfaceIndex);
-            return(mStatus_BadParamErr);
-        }
-
-        // Otherwise, use the specified interface index value and the registration will
-        // be applied to that interface when it comes up.
-        InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
-        LogInfo("handle_regservice_request: registration pending for interface index %d", interfaceIndex);
-    }
-
-    if (get_string(&request->msgptr, request->msgend, name,           sizeof(name          )) < 0 ||
-        get_string(&request->msgptr, request->msgend, type_as_string, sizeof(type_as_string)) < 0 ||
-        get_string(&request->msgptr, request->msgend, domain,         sizeof(domain        )) < 0 ||
-        get_string(&request->msgptr, request->msgend, host,           sizeof(host          )) < 0)
-    { LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
-
-    request->flags = flags;
-    request->interfaceIndex = interfaceIndex;
-    request->u.servicereg.InterfaceID = InterfaceID;
-    request->u.servicereg.instances = NULL;
-    request->u.servicereg.txtlen  = 0;
-    request->u.servicereg.txtdata = NULL;
-    mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string));
-
-    if (request->msgptr + 2 > request->msgend) request->msgptr = NULL;
-    else
-    {
-        request->u.servicereg.port.b[0] = *request->msgptr++;
-        request->u.servicereg.port.b[1] = *request->msgptr++;
-    }
-
-    request->u.servicereg.txtlen = get_uint16(&request->msgptr, request->msgend);
-    msgTXTData = get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen);
-
-    if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
-
-    if (request->u.servicereg.txtlen)
-    {
-        request->u.servicereg.txtdata = mallocL("service_info txtdata", request->u.servicereg.txtlen);
-        if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_regservice_request - malloc");
-        mDNSPlatformMemCopy(request->u.servicereg.txtdata, msgTXTData, request->u.servicereg.txtlen);
-    }
-
-    // Check for sub-types after the service type
-    subtypeCount = ChopSubTypes(request->u.servicereg.type_as_string);    // Note: Modifies regtype string to remove trailing subtypes
-    if (subtypeCount < 0)
-    {
-        LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", request->u.servicereg.type_as_string);
-        goto bad_param;
-    }
-    request->u.servicereg.num_subtypes = (mDNSu32)subtypeCount;
-
-    // Don't try to construct "domainname t" until *after* ChopSubTypes has worked its magic
-    if (!*request->u.servicereg.type_as_string || !MakeDomainNameFromDNSNameString(&request->u.servicereg.type, request->u.servicereg.type_as_string))
-    { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", request->u.servicereg.type_as_string); goto bad_param; }
-
-    if (!name[0])
-    {
-        request->u.servicereg.name = mDNSStorage.nicelabel;
-        request->u.servicereg.autoname = mDNStrue;
-    }
-    else
-    {
-        // If the client is allowing AutoRename, then truncate name to legal length before converting it to a DomainLabel
-        if ((flags & kDNSServiceFlagsNoAutoRename) == 0)
-        {
-            const mDNSu32 newlen = TruncateUTF8ToLength((mDNSu8*)name, mDNSPlatformStrLen(name), MAX_DOMAIN_LABEL);
-            name[newlen] = 0;
-        }
-        if (!MakeDomainLabelFromLiteralString(&request->u.servicereg.name, name))
-        { LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; }
-        request->u.servicereg.autoname = mDNSfalse;
-    }
-
-    if (*domain)
-    {
-        request->u.servicereg.default_domain = mDNSfalse;
-        if (!MakeDomainNameFromDNSNameString(&d, domain))
-        { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); goto bad_param; }
-    }
-    else
-    {
-        request->u.servicereg.default_domain = mDNStrue;
-        MakeDomainNameFromDNSNameString(&d, "local.");
-    }
-
-    if (!ConstructServiceName(&srv, &request->u.servicereg.name, &request->u.servicereg.type, &d))
-    {
-        LogMsg("ERROR: handle_regservice_request - Couldn't ConstructServiceName from, “%#s” “%##s” “%##s”",
-               request->u.servicereg.name.c, request->u.servicereg.type.c, d.c); goto bad_param;
-    }
-
-    if (!MakeDomainNameFromDNSNameString(&request->u.servicereg.host, host))
-    { LogMsg("ERROR: handle_regservice_request - host bad %s", host); goto bad_param; }
-    request->u.servicereg.autorename       = (flags & kDNSServiceFlagsNoAutoRename    ) == 0;
-    request->u.servicereg.allowremotequery = (flags & kDNSServiceFlagsAllowRemoteQuery) != 0;
-
-    // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with
-    // a port number of zero. When two instances of the protected client are allowed to run on one
-    // machine, we don't want to see misleading "Bogus client" messages in syslog and the console.
-    if (!mDNSIPPortIsZero(request->u.servicereg.port))
-    {
-        int count = CountExistingRegistrations(&srv, request->u.servicereg.port);
-        if (count)
-            LogMsg("Client application[%d](%s) registered %d identical instances of service %##s port %u.", request->process_id,
-                   request->pid_name, count+1, srv.c, mDNSVal16(request->u.servicereg.port));
-    }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceRegister(%X, %d, \"" PRI_S "\", \"" PRI_S "\", \"" PRI_S "\", \"" PRI_S "\", %u) START PID[%d](" PUB_S ")",
-           request->request_id, request->flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host,
-           mDNSVal16(request->u.servicereg.port), request->process_id, request->pid_name);
-
-    // We need to unconditionally set request->terminate, because even if we didn't successfully
-    // start any registrations right now, subsequent configuration changes may cause successful
-    // registrations to be added, and we'll need to cancel them before freeing this memory.
-    // We also need to set request->terminate first, before adding additional service instances,
-    // because the udsserver_validatelists uses the request->terminate function pointer to determine
-    // what kind of request this is, and therefore what kind of list validation is required.
-    request->terminate = NULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
-        (request->u.servicereg.default_domain || IsLocalDomain(&d)))
-    {
-        err = _handle_regservice_request_with_trust(request, &d);
-        if (err == mStatus_NoAuth && request->u.servicereg.txtdata)
-        {
-            freeL("service_info txtdata", request->u.servicereg.txtdata);
-            request->u.servicereg.txtdata = NULL;
-        }
-    }
-    else
-    {
-        err = _handle_regservice_request_start(request, &d);
-    }
-#else
-    err = _handle_regservice_request_start(request, &d);
-#endif
-
-    return(err);
-
-bad_param:
-    freeL("handle_regservice_request (txtdata)", request->u.servicereg.txtdata);
-    request->u.servicereg.txtdata = NULL;
-    return mStatus_BadParamErr;
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceBrowse
-
-mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : 0;
-    request_state *req = question->QuestionContext;
-    reply_state *rep;
-    (void)m; // Unused
-
-    if (answer->rrtype != kDNSType_PTR)
-    { LogMsg("%3d: FoundInstance: Should not be called with rrtype %d (not a PTR record)", req->sd, answer->rrtype); return; }
-
-    if (mDNSOpaque16IsZero(question->TargetQID) && (question->BrowseThreshold > 0) && (question->CurrentAnswers >= question->BrowseThreshold))
-    {
-        flags |= kDNSServiceFlagsThresholdReached;
-    }
-
-    // if returning a negative answer, then use question's name in reply
-    if (answer->RecordType == kDNSRecordTypePacketNegative)
-    {
-        GenerateBrowseReply(&question->qname, answer->InterfaceID, req, &rep, browse_reply_op, flags, kDNSServiceErr_NoSuchRecord);
-        goto validReply;
-    }
-
-    if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
-    {
-        if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
-        {
-            // Special support to enable the DNSServiceBrowse call made by Bonjour Browser
-            // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
-            GenerateBrowseReply(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
-            goto validReply;
-        }
-
-        LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
-               req->sd, answer->name->c, answer->rdata->u.name.c);
-        return;
-    }
-
-validReply:
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d->Q%d] DNSServiceBrowse(" PRI_DM_NAME ", " PUB_S ") RESULT " PUB_S " interface %d: " PRI_S,
-           req->request_id, mDNSVal16(question->TargetQID), DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype),
-           AddRecord ? "ADD" : "RMV", mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse),
-           RRDisplayString(m, answer));
-
-    append_reply(req, rep);
-}
-
-mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req)
-{
-    q->euid = req->uid;
-    // The policy is either based on pid or UUID. Pass a zero pid
-    // to the "core" if the UUID is valid. If we always pass the pid,
-    // then the "core" needs to determine whether the uuid is valid
-    // by examining all the 16 bytes at the time of the policy
-    // check and also when setting the delegate socket option. Also, it
-    // requires that we zero out the uuid wherever the question is
-    // initialized to make sure that it is not interpreted as valid.
-    // To prevent these intrusive changes, just pass a zero pid to indicate
-    // that pid is not valid when uuid is valid. In future if we need the
-    // pid in the question, we will reevaluate this strategy.
-    if (req->validUUID)
-    {
-        mDNSPlatformMemCopy(q->uuid, req->uuid, UUID_SIZE);
-        q->pid = 0;
-    }
-    else
-    {
-        q->pid = req->process_id;
-    }
-
-    //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-mDNSlocal CFArrayRef _get_unicast_discovery_dns_services(request_state *info)
-{
-    CFArrayRef result = NULL;
-    CFMutableArrayRef defArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &mdns_cfarray_callbacks);
-    require_quiet(defArray, exit);
-
-    util_device_media_access_unicast_addr_enumerate(&info->audit_token,
-    ^bool(uint8_t family, uint8_t *addr, uint32_t ifindex)
-    {
-        mdns_dns_service_definition_t definition = NULL;
-        require_quiet(addr, exit);
-
-        definition = mdns_dns_service_definition_create();
-        require_quiet(definition, exit);
-
-        mdns_address_t serverAddr;
-        if (family == AF_INET) {
-            uint32_t ipv4_addr;
-            memcpy(&ipv4_addr, addr, sizeof(ipv4_addr));
-            serverAddr = mdns_address_create_ipv4(ipv4_addr, mDNSVal16(MulticastDNSPort));
-        } else if (family == AF_INET6) {
-            uint8_t ipv6_addr[16];
-            memcpy(&ipv6_addr, addr, sizeof(ipv6_addr));
-            serverAddr = mdns_address_create_ipv6(ipv6_addr, mDNSVal16(MulticastDNSPort), ifindex);
-        } else {
-            serverAddr = NULL;
-        }
-        require_quiet(serverAddr, exit);
-
-        OSStatus err = mdns_dns_service_definition_append_server_address(definition, serverAddr);
-        mdns_forget(&serverAddr);
-        require_noerr(err, exit);
-
-        mdns_dns_service_definition_set_interface_index(definition, ifindex, true);
-
-        CFArrayAppendValue(defArray, definition);
-
-    exit:
-        mdns_forget(&definition);
-        return true;
-    });
-
-    result = defArray;
-    defArray = NULL;
-
-exit:
-    STRICT_DISPOSE_CF_OBJECT(defArray);
-    return result;
-}
-#endif
-
-mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d)
-{
-    browser_t *b, *p;
-    __block mStatus err;
-
-    for (p = info->u.browser.browsers; p; p = p->next)
-    {
-        if (SameDomainName(&p->domain, d))
-        { debugf("add_domain_to_browser %##s already in list", d->c); return mStatus_AlreadyRegistered; }
-    }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
-    if (info->sign_result && SameDomainName(d, &localdomain))
-    {
-        CFArrayRef definitions = _get_unicast_discovery_dns_services(info);
-        if (definitions)
-        {
-            err = mStatus_NoError;
-            mdns_cfarray_enumerate(definitions,
-            ^ bool (const mdns_dns_service_definition_t definition)
-            {
-                uint32_t ifIndex = mdns_dns_service_definition_get_interface_index(definition);
-                mdns_address_t addr = mdns_dns_service_definition_get_first_address(definition);
-                if (!addr)
-                {
-                    return true;
-                }
-                browser_t *ubrowse = (browser_t *) callocL("browser_t", sizeof(*ubrowse));
-                if (!ubrowse)
-                {
-                    err = mStatus_NoMemoryErr;
-                    return false;
-                }
-                AssignDomainName(&ubrowse->domain, d);
-                SetQuestionPolicy(&ubrowse->q, info);
-                ubrowse->q.request_id = info->request_id; // This browse request is started on behalf of the original browse request.
-                ubrowse->q.UnicastMDNSResolver = mDNSAddr_from_sockaddr(mdns_address_get_sockaddr(addr));
-                mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, ifIndex);
-                err = mDNS_StartBrowse(&mDNSStorage, &ubrowse->q, &info->u.browser.regtype, d, InterfaceID, info->flags,
-                                        mDNSfalse, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, mDNSNULL, info);
-                if (err)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                        "[R%u] mDNS_StartBrowse returned error (UNICAST_DISCOVERY) -- "
-                        "error: %d, type: " PRI_DM_NAME ", domain: " PRI_DM_NAME,
-                        info->request_id, err, DM_NAME_PARAM(&info->u.browser.regtype), DM_NAME_PARAM(d));
-                    freeL("browser_t/add_domain_to_browser", ubrowse);
-                }
-                else
-                {
-                    ubrowse->next = info->u.browser.browsers;
-                    info->u.browser.browsers = ubrowse;
-                    LogMcastQ(&ubrowse->q, info, q_start);
-                }
-                return true;
-            });
-            STRICT_DISPOSE_CF_OBJECT(definitions);
-            if (err != mStatus_NoError) return err;
-        }
-    }
-#endif
-    
-    b = (browser_t *) callocL("browser_t", sizeof(*b));
-    if (!b) return mStatus_NoMemoryErr;
-    AssignDomainName(&b->domain, d);
-    SetQuestionPolicy(&b->q, info);
-    b->q.request_id = info->request_id; // This browse request is started on behalf of the original browse request.
-    err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.interface_id, info->flags,
-                            info->u.browser.ForceMCast, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, info);
-    if (err)
-    {
-        LogMsg("mDNS_StartBrowse returned %d for type %##s domain %##s", err, info->u.browser.regtype.c, d->c);
-        freeL("browser_t/add_domain_to_browser", b);
-    }
-    else
-    {
-        b->next = info->u.browser.browsers;
-        info->u.browser.browsers = b;
-
-        LogMcastQ(&b->q, info, q_start);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        if (callExternalHelpers(info->u.browser.interface_id, &b->domain, info->flags))
-        {
-            domainname tmp;
-            ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &b->domain);
-            LogDebug("add_domain_to_browser: calling external_start_browsing_for_service()");
-            external_start_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags, info->process_id);
-        }
-#endif
-    }
-    return err;
-}
-
-mDNSlocal void browse_termination_callback(request_state *info)
-{
-    if (info->u.browser.default_domain)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceBrowse Cancel domain enumeration for WAB and mDNS "
-            "PID[%d](" PUB_S ")" , info->request_id, info->process_id, info->pid_name);
-        // Stop the domain enumeration queries to discover the WAB legacy browse domains
-        uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
-
-    #if !TARGET_OS_WATCH // Disable the domain enumeration on watch.
-        // Stop the domain enumeration queries to discover the automatic browse domains on the local network.
-        mDNS_StopDomainEnumeration(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowseAutomatic);
-    #endif
-    }
-    while (info->u.browser.browsers)
-    {
-        browser_t *ptr = info->u.browser.browsers;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-        if (callExternalHelpers(ptr->q.InterfaceID, &ptr->domain, ptr->q.flags))
-        {
-            domainname tmp;
-            ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain);
-            LogInfo("browse_termination_callback: calling external_stop_browsing_for_service()");
-            external_stop_browsing_for_service(ptr->q.InterfaceID, &tmp, kDNSType_PTR, ptr->q.flags, info->process_id);
-        }
-#endif
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceBrowse(%X, %d, \"" PRI_DM_NAME "\") STOP PID[%d](" PUB_S ")",
-               info->request_id, info->flags, info->interfaceIndex, DM_NAME_PARAM(&ptr->q.qname),
-               info->process_id, info->pid_name);
-
-        info->u.browser.browsers = ptr->next;
-        mDNS_StopBrowse(&mDNSStorage, &ptr->q);  // no need to error-check result
-        LogMcastQ(&ptr->q, info, q_stop);
-        freeL("browser_t/browse_termination_callback", ptr);
-    }
-}
-
-mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *const d, const mDNSBool add)
-{
-    request_state *request;
-    debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c);
-
-    for (request = all_requests; request; request = request->next)
-    {
-        if (request->terminate != browse_termination_callback) continue;    // Not a browse operation
-        if (!request->u.browser.default_domain) continue;                   // Not an auto-browse operation
-        if (!d->uid || SystemUID(request->uid) || request->uid == d->uid)
-        {
-            browser_t **ptr = &request->u.browser.browsers;
-            while (*ptr && !SameDomainName(&(*ptr)->domain, &d->name)) ptr = &(*ptr)->next;
-            if (add)
-            {
-                // If we don't already have this domain in our list for this browse operation, add it now
-                if (!*ptr) add_domain_to_browser(request, &d->name);
-                else debugf("udsserver_automatic_browse_domain_changed %##s already in list, not re-adding", &d->name);
-            }
-            else
-            {
-                if (!*ptr) LogMsg("udsserver_automatic_browse_domain_changed ERROR %##s not found", &d->name);
-                else
-                {
-                    DNameListElem *p;
-                    for (p = AutoBrowseDomains; p; p=p->next)
-                        if (!p->uid || SystemUID(request->uid) || request->uid == p->uid)
-                            if (SameDomainName(&d->name, &p->name)) break;
-                    if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
-                    else
-                    {
-                        browser_t *rem = *ptr;
-                        *ptr = (*ptr)->next;
-                        mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
-                        freeL("browser_t/udsserver_automatic_browse_domain_changed", rem);
-                    }
-                }
-            }
-        }
-    }
-}
-
-mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;  // unused
-    if (result == mStatus_MemFree)
-    {
-        // On shutdown, mDNS_Close automatically deregisters all records
-        // Since in this case no one has called DeregisterLocalOnlyDomainEnumPTR to cut the record
-        // from the LocalDomainEnumRecords list, we do this here before we free the memory.
-        // (This should actually no longer be necessary, now that we do the proper cleanup in
-        // udsserver_exit. To confirm this, we'll log an error message if we do find a record that
-        // hasn't been cut from the list yet. If these messages don't appear, we can delete this code.)
-        ARListElem **ptr = &LocalDomainEnumRecords;
-        while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
-        if (*ptr)
-        {
-            *ptr = (*ptr)->next;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "FreeARElemCallback: Have to cut " PRI_S, ARDisplayString(m, rr));
-        }
-        mDNSPlatformMemFree(rr->RecordContext);
-    }
-}
-
-// RegisterLocalOnlyDomainEnumPTR and DeregisterLocalOnlyDomainEnumPTR largely duplicate code in
-// "FoundDomain" in uDNS.c for creating and destroying these special mDNSInterface_LocalOnly records.
-// We may want to turn the common code into a subroutine.
-
-mDNSlocal void RegisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
-{
-    // allocate/register legacy and non-legacy _browse PTR record
-    mStatus err;
-    ARListElem *ptr = (ARListElem *) mDNSPlatformMemAllocateClear(sizeof(*ptr));
-
-    debugf("Incrementing %s refcount for %##s",
-           (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
-           (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
-           (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
-
-    mDNS_SetupResourceRecord(&ptr->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, ptr);
-    MakeDomainNameFromDNSNameString(&ptr->ar.namestorage, mDNS_DomainTypeNames[type]);
-    AppendDNSNameString            (&ptr->ar.namestorage, "local");
-    AssignDomainName(&ptr->ar.resrec.rdata->u.name, d);
-    err = mDNS_Register(m, &ptr->ar);
-    if (err)
-    {
-        LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
-        mDNSPlatformMemFree(ptr);
-    }
-    else
-    {
-        ptr->next = LocalDomainEnumRecords;
-        LocalDomainEnumRecords = ptr;
-    }
-}
-
-mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, int type)
-{
-    DeregisterLocalOnlyDomainEnumPTR_Internal(m, d, type, mDNSfalse);
-}
-
-mDNSexport void DeregisterLocalOnlyDomainEnumPTR_Internal(mDNS *const m, const domainname *const d, const int type,
-    const mDNSBool LockHeld)
-{
-    ARListElem **ptr = &LocalDomainEnumRecords;
-    domainname lhs; // left-hand side of PTR, for comparison
-
-    debugf("Decrementing %s refcount for %##s",
-           (type == mDNS_DomainTypeBrowse         ) ? "browse domain   " :
-           (type == mDNS_DomainTypeRegistration   ) ? "registration dom" :
-           (type == mDNS_DomainTypeBrowseAutomatic) ? "automatic browse" : "?", d->c);
-
-    MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
-    AppendDNSNameString            (&lhs, "local");
-
-    while (*ptr)
-    {
-        if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
-        {
-            ARListElem *rem = *ptr;
-            *ptr = (*ptr)->next;
-            if (LockHeld)
-            {
-                mDNS_Deregister_internal(m, &rem->ar, mDNS_Dereg_normal);
-            }
-            else
-            {
-                mDNS_Deregister(m, &rem->ar);
-            }
-            return;
-        }
-        else ptr = &(*ptr)->next;
-    }
-}
-
-mDNSlocal DNameListElem * FindDNameListElem(const mDNSu32 uid, const domainname *const name, DNameListElem *domains)
-{
-    DNameListElem *domain = NULL;
-    for (domain = domains; domain != NULL; domain = domain->next)
-    {
-        if (SameDomainName(name, &domain->name) && domain->uid == uid)
-        {
-            break;
-        }
-    }
-
-    return domain;
-}
-
-mDNSlocal void AddAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
-{
-    DNameListElem *new = FindDNameListElem(uid, name, AutoBrowseDomains);
-    if (new != NULL)
-    {
-        return;
-    }
-
-    new = (DNameListElem *) mDNSPlatformMemAllocateClear(sizeof(*new));
-    if (new == NULL)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "mDNSPlatformMemAllocateClear failed");
-        return;
-    }
-
-    AssignDomainName(&new->name, name);
-    new->uid = uid;
-    new->next = AutoBrowseDomains;
-    AutoBrowseDomains = new;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Automatic browsing domain is added - "
-        "domain name: " PRI_DM_NAME ", uid: %u", DM_NAME_PARAM(name), uid);
-
-    udsserver_automatic_browse_domain_changed(new, mDNStrue);
-}
-
-mDNSlocal void RmvAutoBrowseDomain(const mDNSu32 uid, const domainname *const name)
-{
-    DNameListElem **p = &AutoBrowseDomains;
-    while (*p && (!SameDomainName(&(*p)->name, name) || (*p)->uid != uid)) p = &(*p)->next;
-    if (!*p) LogMsg("RmvAutoBrowseDomain: Got remove event for domain %##s not in list", name->c);
-    else
-    {
-        DNameListElem *ptr = *p;
-        *p = ptr->next;
-        udsserver_automatic_browse_domain_changed(ptr, mDNSfalse);
-        mDNSPlatformMemFree(ptr);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Automatic browsing domain is removed - "
-            "domain name: " PRI_DM_NAME ", uid: %u", DM_NAME_PARAM(name), uid);
-    }
-}
-
-mDNSlocal void SetPrefsBrowseDomains(mDNS *m, DNameListElem *browseDomains, mDNSBool add)
-{
-    DNameListElem *d;
-    for (d = browseDomains; d; d = d->next)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-            "SetPrefsBrowseDomains is adding/removing domain for Browsing and Automatic Browsing domains - "
-            "domain name: " PRI_DM_NAME ", uid: %u, result: " PUB_S, DM_NAME_PARAM(&d->name), d->uid,
-            add ? "add" : "remove");
-        if (add)
-        {
-            RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
-            // This AddAutoBrowseDomain() is a little bit different with the one in AutomaticBrowseDomainChange(),
-            // AutomaticBrowseDomainChange() adds automatic browsing domains with uid 0. Then the added domains can be
-            // used by any other browse requests. However, AppendDNameListElem() will also append DNameListElem into
-            // browseDomains list with uid == 0, which means the AddAutoBrowseDomain() below will:
-            // 1. Add domain with uid == 0, which will add duplicate domains into list.
-            // 2. Add domain with uid != 0, which is the valid case we want to handle here.
-            // When uid == 0, we should call RegisterLocalOnlyDomainEnumPTR() instead of AddAutoBrowseDomain().
-            if (d->uid != 0)
-            {
-                // The automatic browsing domain is added on behave of the user, which means only the same user that
-                // registers the record should be able to browse under this domain. All the browse requests started by
-                // other user(different uid) should not see this browsing domain.
-                AddAutoBrowseDomain(d->uid, &d->name);
-            }
-            else
-            {
-                // Notify AutomaticBrowseDomainChange() to call AddAutoBrowseDomain(0, &d->name); after checking for
-                // duplicates.
-                RegisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowseAutomatic);
-            }
-        }
-        else
-        {
-            DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowse);
-            if (d->uid != 0)
-            {
-                RmvAutoBrowseDomain(d->uid, &d->name);
-            }
-            else
-            {
-                // Notify AutomaticBrowseDomainChange() to call RmvAutoBrowseDomain(0, &d->name); after checking
-                // for duplicates.
-                DeregisterLocalOnlyDomainEnumPTR(m, &d->name, mDNS_DomainTypeBrowseAutomatic);
-            }
-        }
-    }
-}
-
-mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m)
-{
-    (void)m; // unused
-}
-
-mDNSexport void udsserver_handle_configchange(mDNS *const m)
-{
-    request_state *req;
-    service_instance *ptr;
-    DNameListElem *RegDomains = NULL;
-    DNameListElem *BrowseDomains = NULL;
-    DNameListElem *p;
-
-    UpdateDeviceInfoRecord(m);
-
-    // For autoname services, see if the default service name has changed, necessitating an automatic update
-    for (req = all_requests; req; req = req->next)
-        if (req->terminate == regservice_termination_callback)
-            if (req->u.servicereg.autoname && !SameDomainLabelCS(req->u.servicereg.name.c, m->nicelabel.c))
-            {
-                req->u.servicereg.name = m->nicelabel;
-                for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-                {
-                    ptr->renameonmemfree = 1;
-                    if (ptr->clientnotified) SendServiceRemovalNotification(&ptr->srs);
-                    LogInfo("udsserver_handle_configchange: Calling deregister for Service %##s", ptr->srs.RR_PTR.resrec.name->c);
-                    if (mDNS_DeregisterService_drt(m, &ptr->srs, mDNS_Dereg_rapid))
-                        regservice_callback(m, &ptr->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
-                }
-            }
-
-    // Let the platform layer get the current DNS information
-    mDNS_Lock(m);
-    mDNSPlatformSetDNSConfig(mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains, mDNSfalse);
-    mDNS_Unlock(m);
-
-    // Any automatic registration domains are also implicitly automatic browsing domains
-    if (RegDomains) SetPrefsBrowseDomains(m, RegDomains, mDNStrue);                             // Add the new list first
-    if (AutoRegistrationDomains) SetPrefsBrowseDomains(m, AutoRegistrationDomains, mDNSfalse);  // Then clear the old list
-
-    // Add any new domains not already in our AutoRegistrationDomains list
-    for (p=RegDomains; p; p=p->next)
-    {
-        DNameListElem **pp = &AutoRegistrationDomains;
-        while (*pp && ((*pp)->uid != p->uid || !SameDomainName(&(*pp)->name, &p->name))) pp = &(*pp)->next;
-        if (!*pp)       // If not found in our existing list, this is a new default registration domain
-        {
-            RegisterLocalOnlyDomainEnumPTR(m, &p->name, mDNS_DomainTypeRegistration);
-            udsserver_default_reg_domain_changed(p, mDNStrue);
-        }
-        else            // else found same domainname in both old and new lists, so no change, just delete old copy
-        {
-            DNameListElem *del = *pp;
-            *pp = (*pp)->next;
-            mDNSPlatformMemFree(del);
-        }
-    }
-
-    // Delete any domains in our old AutoRegistrationDomains list that are now gone
-    while (AutoRegistrationDomains)
-    {
-        DNameListElem *del = AutoRegistrationDomains;
-        AutoRegistrationDomains = AutoRegistrationDomains->next;        // Cut record from list FIRST,
-        DeregisterLocalOnlyDomainEnumPTR(m, &del->name, mDNS_DomainTypeRegistration);
-        udsserver_default_reg_domain_changed(del, mDNSfalse);           // before calling udsserver_default_reg_domain_changed()
-        mDNSPlatformMemFree(del);
-    }
-
-    // Now we have our new updated automatic registration domain list
-    AutoRegistrationDomains = RegDomains;
-
-    // Add new browse domains to internal list
-    if (BrowseDomains) SetPrefsBrowseDomains(m, BrowseDomains, mDNStrue);
-
-    // Remove old browse domains from internal list
-    if (SCPrefBrowseDomains)
-    {
-        SetPrefsBrowseDomains(m, SCPrefBrowseDomains, mDNSfalse);
-        while (SCPrefBrowseDomains)
-        {
-            DNameListElem *fptr = SCPrefBrowseDomains;
-            SCPrefBrowseDomains = SCPrefBrowseDomains->next;
-            mDNSPlatformMemFree(fptr);
-        }
-    }
-
-    // Replace the old browse domains array with the new array
-    SCPrefBrowseDomains = BrowseDomains;
-}
-
-mDNSexport void FoundNonLocalOnlyAutomaticBrowseDomain(mDNS *const m, DNSQuestion *const q,
-    const ResourceRecord *const answer, const QC_result add_record)
-{
-    (void)q; // unused
-    // Only accepts response from network.
-    if (answer->InterfaceID == mDNSInterface_BLE || answer->InterfaceID == mDNSInterface_P2P
-        || answer->InterfaceID == mDNSInterface_LocalOnly)
-    {
-        goto exit;
-    }
-    if (add_record != QC_add && add_record != QC_rmv)
-    {
-        goto exit;
-    }
-    if (answer->RecordType == kDNSRecordTypePacketNegative)
-    {
-        goto exit;
-    }
-
-    const domainname *const name = &answer->rdata->u.name;
-
-    if (add_record)
-    {
-        RegisterLocalOnlyDomainEnumPTR(m, name, mDNS_DomainTypeBrowseAutomatic);
-
-        mDNS_AddDomainDiscoveredForDomainEnumeration(m, &localdomain, mDNS_DomainTypeBrowseAutomatic, name);
-    }
-    else
-    {
-        DeregisterLocalOnlyDomainEnumPTR(m, name, mDNS_DomainTypeBrowseAutomatic);
-
-        mDNS_RemoveDomainDiscoveredForDomainEnumeration(m, &localdomain, mDNS_DomainTypeBrowseAutomatic, name);
-    }
-
-    const char *const if_name = InterfaceNameForID(m, answer->InterfaceID);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Automatic browsing domain discovered via network - "
-        "change: " PUB_S ", interface name: " PUB_S ", browsing domain: " PRI_DM_NAME,
-        add_record == QC_add ? "added" : "removed", if_name, DM_NAME_PARAM(name));
-
-exit:
-    return;
-}
-
-mDNSlocal void AutomaticBrowseDomainChange(mDNS *const m, DNSQuestion *q, const ResourceRecord *const answer,
-    QC_result AddRecord)
-{
-    (void)m; // unused
-    (void)q; // unused
-
-    const mDNSBool ignored = (answer->InterfaceID == mDNSInterface_Any);
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "Automatic browsing domain changes - "
-        "name: " PRI_DM_NAME ", event: " PUB_S ", interface ID: %p" PUB_S, DM_NAME_PARAM(&answer->rdata->u.name),
-        AddRecord == QC_add ? "adding" : "removing", answer->InterfaceID, ignored ? ", ignored." : ".");
-
-    if (ignored)
-    {
-        return;
-    }
-
-    if (AddRecord) AddAutoBrowseDomain(0, &answer->rdata->u.name);
-    else RmvAutoBrowseDomain(0, &answer->rdata->u.name);
-
-#if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
-    // We also start the local DNS resolver discovery if the automatic browsing domain discovered is the Thread domain.
-    if (SameDomainName(&answer->rdata->u.name, THREAD_DOMAIN_NAME))
-    {
-        // AutomaticBrowseDomainChange() is called as a callback function where the mDNS_Lock is dropped, to start the
-        // resolver discovery process, we need to grab the mDNS_Lock again.
-        if (AddRecord == QC_add) {
-            resolver_discovery_add(THREAD_DOMAIN_NAME, mDNStrue);
-        } else {
-            resolver_discovery_remove(THREAD_DOMAIN_NAME, mDNStrue);
-        }
-    }
-#endif
-}
-
-mDNSlocal mStatus _handle_browse_request_start(request_state *request, const char *domain)
-{
-    domainname d;
-    mStatus err = mStatus_NoError;
-
-    request->terminate = browse_termination_callback;
-
-    if (domain[0])
-    {
-        if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
-        err = add_domain_to_browser(request, &d);
-    }
-    else
-    {
-        DNameListElem *sdom;
-        for (sdom = AutoBrowseDomains; sdom; sdom = sdom->next)
-            if (!sdom->uid || SystemUID(request->uid) || request->uid == sdom->uid)
-            {
-                err = add_domain_to_browser(request, &sdom->name);
-                if (err)
-                {
-                    if (SameDomainName(&sdom->name, &localdomain)) break;
-                    else err = mStatus_NoError;  // suppress errors for non-local "default" domains
-                }
-            }
-    }
-
-    return(err);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_browse_request_error(request_state *request, mStatus error)
-{
-    reply_state *rep;
-
-    GenerateBrowseReply(NULL, 0, request, &rep, browse_reply_op, 0, error);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceBrowse _return_browse_request_error: error (%d)", request->request_id, error);
-
-    append_reply(request, rep);
-}
-
-mDNSlocal mStatus _handle_browse_request_with_trust(request_state *request, const char * domain)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_browse_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_browse_request_start(request, domain);
-    }
-    else
-    {
-        char typestr[MAX_ESCAPED_DOMAIN_NAME];
-        typestr[0] = 0;
-        domainlabel dName;
-        domainname dType, dDomain;
-        if (DeconstructServiceName(&request->u.browser.regtype, &dName, &dType, &dDomain))
-        {
-            ConvertDomainNameToCString(&dType, typestr);
-        }
-        else
-        {
-            ConvertDomainNameToCString(&request->u.browser.regtype, typestr);
-        }
-
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, typestr, &flags);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-        if ((flags & mdns_trust_flags_system_privileged) != mdns_trust_flags_system_privileged)
-        {
-            request->sign_result = mDNSfalse; // Reset this flag if not system privileged
-        }
-        if ((flags & mdns_trust_flags_media_discovery_entitlement) == mdns_trust_flags_media_discovery_entitlement)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                "[R%u] _handle_browse_request_with_trust: has media discovery entitlement", request->request_id);
-            request->sign_result = mDNStrue; // Always sign results for media discovery entitlement
-        }
-#endif
-        switch (status)
-        {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, typestr, flags);
-                if (!trust )
-                {
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-
-                size_t len = strlen(domain) + 1;
-                void * context = mallocL("context/_handle_browse_request_with_trust", len);
-                if (!context)
-                {
-                    my_perror("ERROR: mallocL context/_handle_browse_request_with_trust");
-                    mdns_release(trust);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                memcpy(context, domain, len);
-                mdns_trust_set_context(trust, context);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("context/_handle_browse_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        const char * _domain = mdns_trust_get_context(trust);
-                        if (_domain)
-                        {
-                            if (!error)
-                            {
-                                error = _handle_browse_request_start(request, _domain);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_browse_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_handle_browse_request_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_browse_request_start(request, domain);
-                break;
-        }
-    }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-mDNSlocal mStatus handle_browse_request(request_state *request)
-{
-    // Note that regtype may include a trailing subtype
-    char regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME];
-    domainname typedn, temp;
-    mDNSs32 NumSubTypes;
-    mStatus err = mStatus_NoError;
-
-    DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-
-    // The browse is scoped to a specific interface index, but the
-    // interface is not currently in our list.
-    if (interfaceIndex && !InterfaceID)
-    {
-        // If it's one of the specially defined inteface index values, just return an error.
-        if (PreDefinedInterfaceIndex(interfaceIndex))
-        {
-            LogInfo("handle_browse_request: bad interfaceIndex %d", interfaceIndex);
-            return(mStatus_BadParamErr);
-        }
-
-        // Otherwise, use the specified interface index value and the browse will
-        // be applied to that interface when it comes up.
-        InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
-        LogInfo("handle_browse_request: browse pending for interface index %d", interfaceIndex);
-    }
-
-    if (get_string(&request->msgptr, request->msgend, regtype, sizeof(regtype)) < 0 ||
-        get_string(&request->msgptr, request->msgend, domain,  sizeof(domain )) < 0) return(mStatus_BadParamErr);
-
-    if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    err = get_signed_result_flags_tlvs(request);
-    if (err) { LogMsg("%3d: handle_browse_request err reading Validation TLVS", request->sd); return(err); }
-#endif
-
-    request->flags = flags;
-    request->interfaceIndex = interfaceIndex;
-    typedn.c[0] = 0;
-    NumSubTypes = ChopSubTypes(regtype);    // Note: Modifies regtype string to remove trailing subtypes
-    if (NumSubTypes < 0 || NumSubTypes > 1)
-        return(mStatus_BadParamErr);
-    if (NumSubTypes == 1)
-    {
-        if (!AppendDNSNameString(&typedn, regtype + strlen(regtype) + 1))
-            return(mStatus_BadParamErr);
-    }
-
-    if (!regtype[0] || !AppendDNSNameString(&typedn, regtype)) return(mStatus_BadParamErr);
-
-    if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr);
-    // For over-long service types, we only allow domain "local"
-    if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain));
-
-    // Set up browser info
-    request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
-    request->u.browser.interface_id = InterfaceID;
-    AssignDomainName(&request->u.browser.regtype, &typedn);
-    request->u.browser.default_domain = !domain[0];
-    request->u.browser.browsers = NULL;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d] DNSServiceBrowse(%X, %d, \"" PRI_DM_NAME "\", \"" PRI_S "\") START PID[%d](" PUB_S ")",
-           request->request_id, request->flags, interfaceIndex, DM_NAME_PARAM(&request->u.browser.regtype), domain,
-           request->process_id, request->pid_name);
-
-    if (request->u.browser.default_domain)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u] DNSServiceBrowse Start domain enumeration for WAB and mDNS "
-            "PID[%d](" PUB_S ")", request->request_id, request->process_id, request->pid_name);
-        // Start the domain enumeration queries to discover the WAB browse domains
-        uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_LBROWSE_QUERY);
-
-    #if !TARGET_OS_WATCH // Disable the domain enumeration on watch.
-        // Start the domain enumeration queries to discover the automatic browse domains on the local network.
-        mDNS_StartDomainEnumeration(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowseAutomatic);
-    #endif
-    }
-    // We need to unconditionally set request->terminate, because even if we didn't successfully
-    // start any browses right now, subsequent configuration changes may cause successful
-    // browses to be added, and we'll need to cancel them before freeing this memory.
-    request->terminate = NULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    domainname d;
-    if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
-
-    if (os_feature_enabled(mDNSResponder, bonjour_privacy) &&
-        (request->u.browser.default_domain || IsLocalDomain(&d) || request->u.browser.ForceMCast))
-    {
-        err = _handle_browse_request_with_trust(request, domain);
-    }
-    else
-    {
-        err = _handle_browse_request_start(request, domain);
-    }
-#else
-    err = _handle_browse_request_start(request, domain);
-#endif
-
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceResolve
-
-mDNSlocal void resolve_termination_callback(request_state *request)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceResolve(%X, %d, \"" PRI_DM_NAME "\") STOP PID[%d](" PUB_S ")",
-           request->request_id, request->flags, request->interfaceIndex, DM_NAME_PARAM(&request->u.resolve.qtxt.qname),
-           request->process_id, request->pid_name);
-    mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt);
-    mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
-    LogMcastQ(&request->u.resolve.qsrv, request, q_stop);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-    if (request->u.resolve.external_advertise)
-    {
-        external_stop_resolving_service(request->u.resolve.qsrv.InterfaceID, &request->u.resolve.qsrv.qname, request->flags, request->process_id);
-    }
-#endif
-}
-
-typedef struct {
-    char            regtype[MAX_ESCAPED_DOMAIN_NAME];
-    domainname      fqdn;
-    mDNSInterfaceID InterfaceID;
-} _resolve_start_params_t;
-
-mDNSlocal mStatus _handle_resolve_request_start(request_state *request, const _resolve_start_params_t * const params)
-{
-    mStatus err;
-
-    err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv);
-
-    if (!err)
-    {
-        err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
-        if (err)
-        {
-            mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
-        }
-        else
-        {
-            request->terminate = resolve_termination_callback;
-            LogMcastQ(&request->u.resolve.qsrv, request, q_start);
-#if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
-            if (callExternalHelpers(params->InterfaceID, &params->fqdn, request->flags))
-            {
-                request->u.resolve.external_advertise    = mDNStrue;
-                LogInfo("handle_resolve_request: calling external_start_resolving_service()");
-                external_start_resolving_service(params->InterfaceID, &params->fqdn, request->flags, request->process_id);
-            }
-#else
-            (void)params;
-#endif
-        }
-    }
-    return err;
-}
-
-mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    size_t len = 0;
-    char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME] = "0";
-    uint8_t *data;
-    reply_state *rep;
-    request_state *req = question->QuestionContext;
-    const DNSServiceErrorType error =
-        (answer->RecordType == kDNSRecordTypePacketNegative) ? kDNSServiceErr_NoSuchRecord : kDNSServiceErr_NoError;
-    (void)m; // Unused
-
-    LogOperation("%3d: DNSServiceResolve(%##s) %s interface %d: %s",
-        req->sd, question->qname.c, AddRecord ? "ADD" : "RMV",
-        mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer));
-
-    if (!AddRecord)
-    {
-        if (req->u.resolve.srv == answer) req->u.resolve.srv = mDNSNULL;
-        if (req->u.resolve.txt == answer) req->u.resolve.txt = mDNSNULL;
-        return;
-    }
-
-    if (answer->rrtype == kDNSType_SRV) req->u.resolve.srv = answer;
-    if (answer->rrtype == kDNSType_TXT) req->u.resolve.txt = answer;
-
-    if (!req->u.resolve.txt || !req->u.resolve.srv) return;     // only deliver result to client if we have both answers
-
-    ConvertDomainNameToCString(answer->name, fullname);
-
-    if (answer->RecordType != kDNSRecordTypePacketNegative)
-        ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target);
-
-    mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse);
-    // calculate reply length
-    len += sizeof(DNSServiceFlags);
-    len += sizeof(mDNSu32);  // interface index
-    len += sizeof(DNSServiceErrorType);
-    len += strlen(fullname) + 1;
-    len += strlen(target) + 1;
-    len += 2 * sizeof(mDNSu16);  // port, txtLen
-    len += req->u.resolve.txt->rdlength;
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    mdns_signed_resolve_result_t signed_result = NULL;
-    const uint8_t *signed_data = NULL;
-    uint16_t signed_data_length = 0;
-    if (req->sign_result && req->signed_obj && AddRecord)
-    {
-        OSStatus err;
-        mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(req->signed_obj);
-        if (!browseResult)
-        {
-            err = mStatus_Invalid;
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "[R%u->Q%u] resolve_result_callback mdns_signed_resolve_result_downcast failed",
-                req->request_id, mDNSVal16(question->TargetQID));
-        }
-        else
-        {
-            signed_result = mdns_signed_resolve_result_create(browseResult, req->u.resolve.srv->rdata->u.srv.target.c,
-                req->u.resolve.srv->rdata->u.srv.port.NotAnInteger, interface_index, req->u.resolve.txt->rdata->u.data,
-                req->u.resolve.txt->rdlength, &err);
-        }
-        if (!signed_result || err != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                "[R%u->Q%u] resolve_result_callback signed_resolve failed %ld", req->request_id,
-                mDNSVal16(question->TargetQID), (long)err);
-        }
-        else
-        {
-            size_t temp_size = 0;
-            const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
-            if (temp_size <= UINT16_MAX)
-            {
-                signed_data = temp_data;
-                signed_data_length = (uint16_t)temp_size;
-                len += get_required_tlv_length(signed_data_length);
-            }
-        }
-    }
-#endif
-
-    // allocate/init reply header
-    rep = create_reply(resolve_reply_op, len, req);
-    rep->rhdr->flags = dnssd_htonl(0);
-    rep->rhdr->ifi   = dnssd_htonl(interface_index);
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    // write reply data to message
-    put_string(fullname, &data);
-    put_string(target, &data);
-    *data++ =  req->u.resolve.srv->rdata->u.srv.port.b[0];
-    *data++ =  req->u.resolve.srv->rdata->u.srv.port.b[1];
-    put_uint16(req->u.resolve.txt->rdlength, &data);
-    put_rdata(req->u.resolve.txt->rdlength, req->u.resolve.txt->rdata->u.data, &data);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    if (signed_data)
-    {
-        put_signed_result_tlvs(signed_data, signed_data_length, rep->mhdr, &data, data+len);
-    }
-    mdns_forget(&signed_result);
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] DNSServiceResolve(" PRI_S ") RESULT   " PRI_S ":%d",
-           req->request_id, mDNSVal16(question->TargetQID), fullname, target,
-           mDNSVal16(req->u.resolve.srv->rdata->u.srv.port));
-    append_reply(req, rep);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_resolve_request_error(request_state * request, mStatus error)
-{
-    size_t len;
-    char * emptystr = "\0";
-    uint8_t *data;
-    reply_state *rep;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-       "[R%u] DNSServiceResolve _return_resolve_request_error: error(%d)", request->request_id, error);
-
-    // calculate reply length
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(mDNSu32);  // interface index
-    len += sizeof(DNSServiceErrorType);
-    len += 2; // name, target
-    len += 2 * sizeof(mDNSu16);  // port, txtLen
-    len += 0; //req->u.resolve.txt->rdlength;
-
-    rep = create_reply(resolve_reply_op, len, request);
-
-    rep->rhdr->flags = 0;
-    rep->rhdr->ifi   = 0;
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    // write reply data to message
-    put_string(emptystr, &data); // name
-    put_string(emptystr, &data); // target
-    put_uint16(0,        &data); // port
-    put_uint16(0,        &data); // txtLen
-
-    append_reply(request, rep);
-}
-
-mDNSlocal mStatus _handle_resolve_request_with_trust(request_state *request, const _resolve_start_params_t * const params)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_resolve_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_resolve_request_start(request, params);
-    }
-    else
-    {
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_bonjour(request->audit_token, params->regtype, &flags);
-        switch (status)
-        {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, params->regtype, flags);
-                if (!trust )
-                {
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-
-                void * context = mallocL("context/_handle_resolve_request_with_trust", sizeof(_resolve_start_params_t));
-                if (!context)
-                {
-                    my_perror("ERROR: mallocL context/_handle_resolve_request_with_trust");
-                    mdns_release(trust);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                memcpy(context, params, sizeof(_resolve_start_params_t));
-                mdns_trust_set_context(trust, context);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("context/_handle_resolve_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        _resolve_start_params_t * _params =  mdns_trust_get_context(trust);
-                        if (_params)
-                        {
-                            if (!error)
-                            {
-                                error = _handle_resolve_request_start(request, _params);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_resolve_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_handle_resolve_request_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_resolve_request_start(request, params);
-                break;
-        }
-    }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-mDNSlocal mStatus handle_resolve_request(request_state *request)
-{
-    char name[256], domain[MAX_ESCAPED_DOMAIN_NAME];
-    _resolve_start_params_t params;
-    mStatus err;
-
-    // extract the data from the message
-    DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-
-    // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
-    // flag set so that the resolve will run over P2P interfaces that are not yet created.
-    if (interfaceIndex == kDNSServiceInterfaceIndexP2P)
-    {
-        LogOperation("handle_resolve_request: mapping kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny + kDNSServiceFlagsIncludeP2P");
-        flags |= kDNSServiceFlagsIncludeP2P;
-        interfaceIndex = kDNSServiceInterfaceIndexAny;
-    }
-
-    params.InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-
-    // The operation is scoped to a specific interface index, but the
-    // interface is not currently in our list.
-    if (interfaceIndex && !params.InterfaceID)
-    {
-        // If it's one of the specially defined inteface index values, just return an error.
-        if (PreDefinedInterfaceIndex(interfaceIndex))
-        {
-            LogInfo("handle_resolve_request: bad interfaceIndex %d", interfaceIndex);
-            return(mStatus_BadParamErr);
-        }
-
-        // Otherwise, use the specified interface index value and the operation will
-        // be applied to that interface when it comes up.
-        params.InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
-        LogInfo("handle_resolve_request: resolve pending for interface index %d", interfaceIndex);
-    }
-
-    if (get_string(&request->msgptr, request->msgend, name,           sizeof(name   )) < 0 ||
-        get_string(&request->msgptr, request->msgend, params.regtype, sizeof(params.regtype)) < 0 ||
-        get_string(&request->msgptr, request->msgend, domain,         sizeof(domain )) < 0)
-    { LogMsg("ERROR: handle_resolve_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); }
-
-    if (!request->msgptr) { LogMsg("%3d: DNSServiceResolve(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    err = get_signed_browse_tlvs(request);
-    if (err) { LogMsg("%3d: handle_resolve_request err reading Validation TLVS", request->sd); return(err); }
-#endif
-
-    if (build_domainname_from_strings(&params.fqdn, name, params.regtype, domain) < 0)
-    { LogMsg("ERROR: handle_resolve_request bad “%s” “%s” “%s”", name, params.regtype, domain); return(mStatus_BadParamErr); }
-
-    mDNSPlatformMemZero(&request->u.resolve, sizeof(request->u.resolve));
-
-    request->flags = flags;
-    request->interfaceIndex = interfaceIndex;
-
-    // format questions
-    request->u.resolve.qsrv.InterfaceID      = params.InterfaceID;
-    request->u.resolve.qsrv.flags            = flags;
-    AssignDomainName(&request->u.resolve.qsrv.qname, &params.fqdn);
-    request->u.resolve.qsrv.qtype            = kDNSType_SRV;
-    request->u.resolve.qsrv.qclass           = kDNSClass_IN;
-    request->u.resolve.qsrv.LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
-    request->u.resolve.qsrv.ExpectUnique     = mDNStrue;
-    request->u.resolve.qsrv.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
-    request->u.resolve.qsrv.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
-    request->u.resolve.qsrv.SuppressUnusable = mDNSfalse;
-    request->u.resolve.qsrv.AppendSearchDomains = 0;
-    request->u.resolve.qsrv.TimeoutQuestion  = 0;
-    request->u.resolve.qsrv.WakeOnResolve    = (flags & kDNSServiceFlagsWakeOnResolve) != 0;
-    request->u.resolve.qsrv.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    request->u.resolve.qsrv.ProxyQuestion    = 0;
-    request->u.resolve.qsrv.pid              = request->process_id;
-    request->u.resolve.qsrv.euid             = request->uid;
-    request->u.resolve.qsrv.QuestionCallback = resolve_result_callback;
-    request->u.resolve.qsrv.QuestionContext  = request;
-
-    request->u.resolve.qtxt.InterfaceID      = params.InterfaceID;
-    request->u.resolve.qtxt.flags            = flags;
-    AssignDomainName(&request->u.resolve.qtxt.qname, &params.fqdn);
-    request->u.resolve.qtxt.qtype            = kDNSType_TXT;
-    request->u.resolve.qtxt.qclass           = kDNSClass_IN;
-    request->u.resolve.qtxt.LongLived        = (flags & kDNSServiceFlagsLongLivedQuery     ) != 0;
-    request->u.resolve.qtxt.ExpectUnique     = mDNStrue;
-    request->u.resolve.qtxt.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
-    request->u.resolve.qtxt.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
-    request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
-    request->u.resolve.qtxt.AppendSearchDomains = 0;
-    request->u.resolve.qtxt.TimeoutQuestion  = 0;
-    request->u.resolve.qtxt.WakeOnResolve    = 0;
-    request->u.resolve.qtxt.UseBackgroundTraffic = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
-    request->u.resolve.qtxt.ProxyQuestion    = 0;
-    request->u.resolve.qtxt.pid              = request->process_id;
-    request->u.resolve.qtxt.euid             = request->uid;
-    request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
-    request->u.resolve.qtxt.QuestionContext  = request;
-
-    request->u.resolve.ReportTime            = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
-
-    request->u.resolve.external_advertise    = mDNSfalse;
-
-#if 0
-    if (!AuthorizedDomain(request, &fqdn, AutoBrowseDomains)) return(mStatus_NoError);
-#endif
-
-    // ask the questions
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceResolve(%X, %d, \"" PRI_DM_NAME "\") START PID[%d](" PUB_S ")",
-           request->request_id, flags, interfaceIndex, DM_NAME_PARAM(&request->u.resolve.qsrv.qname),
-           request->process_id, request->pid_name);
-
-    request->terminate = NULL;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    mDNSBool trust_check_done = mDNSfalse;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    if (request->signed_obj)
-    {
-        mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(request->signed_obj);
-        if (browseResult &&
-            mdns_signed_browse_result_contains(browseResult, params.fqdn.c, interfaceIndex))
-        {
-            if (mdns_system_is_signed_result_uuid_valid(mdns_signed_result_get_uuid(browseResult)))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                       "[R%d] DNSServiceResolve: Allowing signed result",
-                          request->request_id);
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-                trust_check_done = mDNStrue;
-#endif
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                       "[R%d] DNSServiceResolve: Signed result UUID revoked.",
-                          request->request_id);
-                return mStatus_PolicyDenied;
-            }
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                   "[R%d] DNSServiceResolve: Signed result does not cover service: " PRI_DM_NAME ", ifindex: %u.",
-                      request->request_id, DM_NAME_PARAM(&request->u.resolve.qsrv.qname), interfaceIndex);
-            request->sign_result = mDNSfalse;
-            mdns_forget(&request->signed_obj);
-        }
-    }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    domainname d;
-    if (!MakeDomainNameFromDNSNameString(&d, domain)) return(mStatus_BadParamErr);
-
-    if (!trust_check_done                                   &&
-        os_feature_enabled(mDNSResponder, bonjour_privacy)  &&
-        (IsLocalDomain(&d) || request->u.resolve.qsrv.ForceMCast))
-    {
-        err = _handle_resolve_request_with_trust(request, &params);
-    }
-    else
-    {
-        err = _handle_resolve_request_start(request, &params);
-    }
-#else
-    err = _handle_resolve_request_start(request, &params);
-#endif
-
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceQueryRecord
-
-mDNSlocal void queryrecord_result_reply(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord, DNSServiceErrorType error, void *context)
-{
-    char name[MAX_ESCAPED_DOMAIN_NAME];
-    size_t len;
-    DNSServiceFlags flags = 0;
-    reply_state *rep;
-    uint8_t *data;
-    request_state *req = (request_state *)context;
-
-    ConvertDomainNameToCString(answer->name, name);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    dnssec_result_t dnssec_result = dnssec_indeterminate;
-    if (dns_question_is_dnssec_requestor(question))
-    {
-        flags |= dns_service_flags_init_with_dnssec_result(question, answer);
-        dnssec_result = resource_record_get_validation_result(answer);
-    }
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-       "[R%u->Q%u] DNSService" PUB_S "(" PRI_DM_NAME ", " PUB_DNS_TYPE ") RESULT " PUB_ADD_RMV " interface %d: (" PUB_MORTALITY ", " PUB_DNSSEC_RESULT ")" PRI_S,
-       req->request_id, mDNSVal16(question->TargetQID), req->hdr.op == query_request ? "QueryRecord" : "GetAddrInfo",
-       DM_NAME_PARAM(&question->qname), DNS_TYPE_PARAM(question->qtype), ADD_RMV_PARAM(AddRecord),
-       mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse),
-       MORTALITY_PARAM(answer->mortality), DNSSEC_RESULT_PARAM(dnssec_result), RRDisplayString(m, answer));
-
-    // Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the
-    // InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions
-    // to be stopped and started including  *this* one. Normally the InterfaceID is valid. But when we
-    // are using the /etc/hosts entries to answer a question, the InterfaceID may not be known to the
-    // mDNS core . Eventually, we should remove the calls to "NetworkChanged" in
-    // mDNSPlatformInterfaceIndexfromInterfaceID when it can't find InterfaceID as ResourceRecords
-    // should not have existed to answer this question if the corresponding interface is not valid.
-    mDNSu32 interface_index = mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNStrue);
-    len = sizeof(DNSServiceFlags);  // calculate reply data length
-    len += sizeof(mDNSu32);     // interface index
-    len += sizeof(DNSServiceErrorType);
-    len += strlen(name) + 1;
-    len += 3 * sizeof(mDNSu16); // type, class, rdlen
-    len += answer->rdlength;
-    len += sizeof(mDNSu32);     // TTL
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    mdns_signed_result_t signed_result = NULL;
-    const uint8_t *signed_data = NULL;
-    uint16_t signed_data_length = 0;
-    if (req->sign_result && req->signed_obj && AddRecord &&
-        (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA || answer->rrtype == kDNSType_TXT))
-    {
-        OSStatus err = 0;
-        if (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA)
-        {
-            mdns_signed_hostname_result_t hostnameResult = NULL;
-            mdns_signed_resolve_result_t resolveResult = mdns_signed_resolve_result_downcast(req->signed_obj);
-            if (!resolveResult)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                    "[R%u->Q%u] queryrecord_result_reply mdns_signed_resolve_result_downcast failed",
-                    req->request_id, mDNSVal16(question->TargetQID));
-            }
-            else
-            {
-                if (answer->rrtype == kDNSType_AAAA)
-                {
-                    hostnameResult = mdns_signed_hostname_result_create_ipv6(resolveResult, answer->rdata->u.data,
-                        interface_index, &err);
-                }
-                else if (answer->rrtype == kDNSType_A)
-                {
-                    hostnameResult = mdns_signed_hostname_result_create_ipv4(resolveResult, answer->rdata->u.data, &err);
-                }
-
-                if (hostnameResult)
-                {
-                    signed_result = mdns_signed_result_upcast(hostnameResult);
-                }
-            }
-        }
-        else if (answer->rrtype == kDNSType_TXT)
-        {
-            mdns_signed_browse_result_t newBrowseResult = NULL;
-            mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(req->signed_obj);
-            if (!browseResult)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                    "[R%u->Q%u] queryrecord_result_reply mdns_signed_browse_result_downcast failed",
-                    req->request_id, mDNSVal16(question->TargetQID));
-            }
-            else
-            {
-                newBrowseResult = mdns_signed_browse_result_create_txt_variant(browseResult, interface_index,
-                    answer->rdata->u.data, answer->rdlength, &err);
-                if (newBrowseResult)
-                {
-                    signed_result = mdns_signed_result_upcast(newBrowseResult);
-                }
-            }
-        }
-        if (!signed_result || err != 0)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR, "[R%u->Q%u] queryrecord_result_reply signed_result failed %ld",
-                req->request_id, mDNSVal16(question->TargetQID), (long)err);
-        }
-        else
-        {
-            size_t temp_size = 0;
-            const uint8_t * temp_data = mdns_signed_result_get_data(signed_result, &temp_size);
-            if (temp_size <= UINT16_MAX)
-            {
-                signed_data = temp_data;
-                signed_data_length = (uint16_t)temp_size;
-                len += get_required_tlv_length(signed_data_length);
-            }
-        }
-    }
-#endif
-
-    rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req);
-
-    if (AddRecord)
-        flags |= kDNSServiceFlagsAdd;
-    if (answer->mortality == Mortality_Ghost)
-        flags |= kDNSServiceFlagsExpiredAnswer;
-    if (!question->InitialCacheMiss)
-        flags |= kDNSServiceFlagAnsweredFromCache;
-
-    rep->rhdr->flags = dnssd_htonl(flags);
-    rep->rhdr->ifi   = dnssd_htonl(interface_index);
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    put_string(name,             &data);
-    put_uint16(answer->rrtype,   &data);
-    put_uint16(answer->rrclass,  &data);
-    put_uint16(answer->rdlength, &data);
-    // We need to use putRData here instead of the crude put_rdata function, because the crude put_rdata
-    // function just does a blind memory copy without regard to structures that may have holes in them.
-    if (answer->rdlength)
-        if (!putRData(mDNSNULL, (mDNSu8 *)data, (mDNSu8 *)rep->rhdr + len, answer))
-            LogMsg("queryrecord_result_reply putRData failed %d", (mDNSu8 *)rep->rhdr + len - (mDNSu8 *)data);
-    data += answer->rdlength;
-    put_uint32(AddRecord ? answer->rroriginalttl : 0, &data);
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    if (signed_data)
-    {
-        put_signed_result_tlvs(signed_data, signed_data_length, rep->mhdr, &data, data+len);
-    }
-    mdns_forget(&signed_result);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRACKER_STATE)
-    if (resolved_cache_is_enabled() && AddRecord &&
-        ((answer->rrtype == kDNSType_A) || (answer->rrtype == kDNSType_AAAA)))
-    {
-        resolved_cache_update_tracking(question);
-    }
-#endif
-    append_reply(req, rep);
-}
-
-mDNSlocal void queryrecord_termination_callback(request_state *request)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%u] DNSServiceQueryRecord(%X, %d, " PRI_DM_NAME ", " PUB_S ") STOP PID[%d](" PUB_S ")",
-           request->request_id, request->flags, request->interfaceIndex,
-           DM_NAME_PARAM(QueryRecordClientRequestGetQName(&request->u.queryrecord)),
-           DNSTypeName(QueryRecordClientRequestGetType(&request->u.queryrecord)), request->process_id, request->pid_name);
-
-    QueryRecordClientRequestStop(&request->u.queryrecord);
-}
-
-typedef struct
-{
-    QueryRecordClientRequestParams cr;
-    char qname[MAX_ESCAPED_DOMAIN_NAME];
-} uds_queryrecord_params_t;
-
-static void _uds_queryrecord_params_init(uds_queryrecord_params_t *const params)
-{
-    mDNSPlatformMemZero(params, (mDNSu32)sizeof(*params));
-    QueryRecordClientRequestParamsInit(&params->cr);
-    params->cr.qnameStr = params->qname;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-static void _uds_queryrecord_params_copy(uds_queryrecord_params_t *const dst, const uds_queryrecord_params_t *const src)
-{
-	*dst = *src;
-    dst->cr.qnameStr = dst->qname; // Must point to own qname buffer.
-}
-#endif
-
-mDNSlocal mStatus _handle_queryrecord_request_start(request_state *request, const uds_queryrecord_params_t *const params)
-{
-    request->terminate = queryrecord_termination_callback;
-    return QueryRecordClientRequestStart(&request->u.queryrecord, &params->cr, queryrecord_result_reply, request);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_queryrecord_request_error(request_state * request, mStatus error)
-{
-    size_t len;
-    char * emptystr = "\0";
-    uint8_t *data;
-    reply_state *rep;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-       "[R%u] DNSService" PUB_S " _return_queryrecord_request_error: error(%d)",
-       request->request_id, request->hdr.op == query_request ? "QueryRecord" : "GetAddrInfo", error);
-
-    len = sizeof(DNSServiceFlags);  // calculate reply data length
-    len += sizeof(mDNSu32);     // interface index
-    len += sizeof(DNSServiceErrorType);
-    len += strlen(emptystr) + 1;
-    len += 3 * sizeof(mDNSu16); // type, class, rdlen
-    len += 0;//answer->rdlength;
-    len += sizeof(mDNSu32);     // TTL
-
-    rep = create_reply(request->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, request);
-
-    rep->rhdr->flags = 0;
-    rep->rhdr->ifi   = 0;
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    put_string(emptystr,    &data);
-    put_uint16(0,           &data);
-    put_uint16(0,           &data);
-    put_uint16(0,           &data);
-    data += 0;
-    put_uint32(0,           &data);
-
-    append_reply(request, rep);
-}
-
-mDNSlocal mStatus _handle_queryrecord_request_with_trust(request_state *request,
-    const uds_queryrecord_params_t *const params)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_queryrecord_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_queryrecord_request_start(request, params);
-    }
-    else
-    {
-        const char *service_ptr = NULL;
-        char type_str[MAX_ESCAPED_DOMAIN_NAME] = "";
-        domainname query_name;
-        if (MakeDomainNameFromDNSNameString(&query_name, params->qname))
-        {
-            domainlabel name;
-            domainname type, domain;
-            bool good = DeconstructServiceName(&query_name, &name, &type, &domain);
-            if (good)
-            {
-                ConvertDomainNameToCString(&type, type_str);
-                service_ptr = type_str;
-            }
-        }
-
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_query(request->audit_token, params->qname, service_ptr,
-            params->cr.qtype, (params->cr.flags & kDNSServiceFlagsForceMulticast) != 0, &flags);
-        switch (status)
-        {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, service_ptr, flags);
-                if (!trust )
-                {
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-
-                uds_queryrecord_params_t *const context =
-                    (uds_queryrecord_params_t *)mallocL("context/_handle_queryrecord_request_with_trust", sizeof(*context));
-                if (!context)
-                {
-                    my_perror("ERROR: mallocL context/_handle_queryrecord_request_with_trust");
-                    mdns_release(trust);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                _uds_queryrecord_params_copy(context, params);
-                mdns_trust_set_context(trust, context);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("context/_handle_queryrecord_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        uds_queryrecord_params_t * _params =  mdns_trust_get_context(trust);
-                        if (_params)
-                        {
-                            if (!error)
-                            {
-                                error = _handle_queryrecord_request_start(request, _params);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_queryrecord_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_handle_queryrecord_request_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_queryrecord_request_start(request, params);
-                break;
-        }
-    }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
-mDNSlocal void get_queryrecord_tlvs(request_state *const request, uds_queryrecord_params_t *const params)
-{
-    if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
-    {
-        const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
-        const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
-        const mDNSu32 aaaaPolicy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_AAAA_POLICY, mDNSNULL);
-        params->cr.useAAAAFallback = (aaaaPolicy == kDNSServiceAAAAPolicyFallback);
-        const mDNSu32 failoverPolicy = get_tlv_uint32(start, end, IPC_TLV_TYPE_SERVICE_ATTR_FAILOVER_POLICY, mDNSNULL);
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-        params->cr.useFailover = (failoverPolicy == kDNSServiceFailoverPolicyAllow);
-        size_t len;
-        const mDNSu8 *const data = get_tlv(start, end, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, &len);
-        if (data)
-        {
-            params->cr.customID = Querier_RegisterCustomDNSServiceWithPListData(data, len);
-            request->custom_service_id = params->cr.customID;
-        }
-        params->cr.needEncryption = (get_tlv_uint32(start, end, IPC_TLV_TYPE_REQUIRE_PRIVACY, mDNSNULL) != 0);
-#endif
-    }
-}
-#endif
-
-mDNSlocal mStatus handle_queryrecord_request(request_state *request)
-{
-    mStatus err;
-    uds_queryrecord_params_t params;
-    _uds_queryrecord_params_init(&params);
-    params.cr.flags          = get_flags(&request->msgptr, request->msgend);
-    params.cr.interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    if (get_string(&request->msgptr, request->msgend, params.qname, sizeof(params.qname)) < 0)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-    params.cr.qtype          = get_uint16(&request->msgptr, request->msgend);
-    params.cr.qclass         = get_uint16(&request->msgptr, request->msgend);
-    params.cr.requestID      = request->request_id;
-    params.cr.effectivePID   = request->validUUID ? 0 : request->process_id;
-    params.cr.effectiveUUID  = request->validUUID ? request->uuid : mDNSNULL;
-    params.cr.peerUID        = request->uid;
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    params.cr.peerAuditToken = &request->audit_token;
-#endif
-    if (!request->msgptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-            "[R%d] DNSServiceQueryRecord(unreadable parameters)", request->request_id);
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-    request->flags           = params.cr.flags;
-    request->interfaceIndex  = params.cr.interfaceIndex;
-#if MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
-    get_queryrecord_tlvs(request, &params);
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    err = get_signed_browse_tlvs(request);
-    if (err) { LogMsg("%3d: handle_queryrecord_request err reading Validation TLVS", request->sd); return(err); }
-#endif
-
-    mDNSBool enablesDNSSEC = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    enablesDNSSEC = dns_service_flags_enables_dnssec(request->flags);
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[R%d] DNSServiceQueryRecord(%X, %d, " PRI_S ", " PUB_S PUB_S ") START PID[%d](" PUB_S ")",
-        request->request_id, request->flags, request->interfaceIndex, params.qname, DNSTypeName(params.cr.qtype),
-        enablesDNSSEC ? ", DNSSEC" : "", request->process_id, request->pid_name);
-
-    mDNSPlatformMemZero(&request->u.queryrecord, (mDNSu32)sizeof(request->u.queryrecord));
-    request->terminate = NULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    mDNSBool trust_check_done = mDNSfalse;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    if (request->signed_obj)
-    {
-        domainname query_name;
-        mdns_signed_browse_result_t browseResult = mdns_signed_browse_result_downcast(request->signed_obj);
-        if (browseResult &&
-            MakeDomainNameFromDNSNameString(&query_name, params.qname) &&
-            mdns_signed_browse_result_contains(browseResult, query_name.c, request->interfaceIndex))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                   "[R%d] DNSServiceQueryRecord: Allowing signed result",
-                      request->request_id);
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-            trust_check_done = mDNStrue;
-#endif
-        }
-        else
-        {
-            request->sign_result = mDNSfalse;
-            mdns_forget(&request->signed_obj);
-        }
-    }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    if (!trust_check_done && os_feature_enabled(mDNSResponder, bonjour_privacy) )
-    {
-        err = _handle_queryrecord_request_with_trust(request, &params);
-    }
-    else
-#endif
-    {
-        err = _handle_queryrecord_request_start(request, &params);
-    }
-
-exit:
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceEnumerateDomains
-
-mDNSlocal reply_state *format_enumeration_reply(request_state *request,
-                                                const char *domain, DNSServiceFlags flags, mDNSu32 ifi, DNSServiceErrorType err)
-{
-    size_t len;
-    reply_state *reply;
-    uint8_t *data;
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(mDNSu32);
-    len += sizeof(DNSServiceErrorType);
-    len += strlen(domain) + 1;
-
-    reply = create_reply(enumeration_reply_op, len, request);
-    reply->rhdr->flags = dnssd_htonl(flags);
-    reply->rhdr->ifi   = dnssd_htonl(ifi);
-    reply->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)err);
-    data = (uint8_t *)&reply->rhdr[1];
-    put_string(domain, &data);
-    return reply;
-}
-
-mDNSlocal void enum_termination_callback(request_state *request)
-{
-    // Stop the domain enumeration queries to discover the WAB Browse/Registration domains
-    if (request->u.enumeration.flags & kDNSServiceFlagsRegistrationDomains)
-    {
-        LogInfo("%3d: DNSServiceEnumeration Cancel WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
-        uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
-    }
-    else
-    {
-        LogInfo("%3d: DNSServiceEnumeration Cancel WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
-        uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
-        mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_autoall);
-    }
-    mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
-    mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
-}
-
-mDNSlocal void enum_result_callback(mDNS *const m,
-                                    DNSQuestion *const question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    char domain[MAX_ESCAPED_DOMAIN_NAME];
-    request_state *request = question->QuestionContext;
-    DNSServiceFlags flags = 0;
-    reply_state *reply;
-    (void)m; // Unused
-
-    if (answer->rrtype != kDNSType_PTR) return;
-
-#if 0
-    if (!AuthorizedDomain(request, &answer->rdata->u.name, request->u.enumeration.flags ? AutoRegistrationDomains : AutoBrowseDomains)) return;
-#endif
-
-    // We only return add/remove events for the browse and registration lists
-    // For the default browse and registration answers, we only give an "ADD" event
-    if (question == &request->u.enumeration.q_default && !AddRecord) return;
-
-    if (AddRecord)
-    {
-        flags |= kDNSServiceFlagsAdd;
-        if (question == &request->u.enumeration.q_default) flags |= kDNSServiceFlagsDefault;
-    }
-
-    ConvertDomainNameToCString(&answer->rdata->u.name, domain);
-    // Note that we do NOT propagate specific interface indexes to the client - for example, a domain we learn from
-    // a machine's system preferences may be discovered on the LocalOnly interface, but should be browsed on the
-    // network, so we just pass kDNSServiceInterfaceIndexAny
-    reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError);
-    if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; }
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d->Q%d] DNSServiceEnumerateDomains(%2.*s) RESULT " PUB_S ": " PRI_S,
-           request->request_id, mDNSVal16(question->TargetQID), question->qname.c[0], &question->qname.c[1],
-           AddRecord ? "ADD" : "RMV", domain);
-
-    append_reply(request, reply);
-}
-
-mDNSlocal mStatus handle_enum_request(request_state *request)
-{
-    mStatus err;
-    DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-    DNSServiceFlags reg = flags & kDNSServiceFlagsRegistrationDomains;
-    mDNS_DomainType t_all     = reg ? mDNS_DomainTypeRegistration        : mDNS_DomainTypeBrowse;
-    mDNS_DomainType t_default = reg ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-    if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
-
-    if (!request->msgptr)
-    { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
-
-    request->flags = flags;
-    request->interfaceIndex = interfaceIndex;
-
-    // mark which kind of enumeration we're doing so that we know what domain enumeration queries to stop
-    request->u.enumeration.flags = reg;
-
-    // enumeration requires multiple questions, so we must link all the context pointers so that
-    // necessary context can be reached from the callbacks
-    request->u.enumeration.q_all.QuestionContext = request;
-    request->u.enumeration.q_default.QuestionContext = request;
-    if (!reg) request->u.enumeration.q_autoall.QuestionContext = request;
-
-    // if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
-    if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
-
-    // make the calls
-    LogOperation("%3d: DNSServiceEnumerateDomains(%X=%s)", request->sd, flags,
-                 (flags & kDNSServiceFlagsBrowseDomains      ) ? "kDNSServiceFlagsBrowseDomains" :
-                 (flags & kDNSServiceFlagsRegistrationDomains) ? "kDNSServiceFlagsRegistrationDomains" : "<<Unknown>>");
-    err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_all, t_all, NULL, InterfaceID, enum_result_callback, request);
-    if (!err)
-    {
-        err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
-        if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
-        else if (!reg)
-        {
-            err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_autoall, mDNS_DomainTypeBrowseAutomatic, NULL, InterfaceID, enum_result_callback, request);
-            if (err)
-            {
-                mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
-                mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
-            }
-        }
-        if (!err) request->terminate = enum_termination_callback;
-    }
-    if (!err)
-    {
-        // Start the domain enumeration queries to discover the WAB Browse/Registration domains
-        if (reg)
-        {
-            LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
-            uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
-        }
-        else
-        {
-            LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
-            uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
-        }
-    }
-
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceReconfirmRecord & Misc
-
-mDNSlocal mStatus handle_reconfirm_request(request_state *request)
-{
-    mStatus status = mStatus_BadParamErr;
-    AuthRecord *rr = read_rr_from_ipc_msg(request, 0, 0);
-    if (rr)
-    {
-        status = mDNS_ReconfirmByValue(&mDNSStorage, &rr->resrec);
-        LogOperation(
-            (status == mStatus_NoError) ?
-            "%3d: DNSServiceReconfirmRecord(%s) interface %d initiated PID[%d](%s)" :
-            "%3d: DNSServiceReconfirmRecord(%s) interface %d failed PID[%d](%s) status %d",
-            request->sd, RRDisplayString(&mDNSStorage, &rr->resrec),
-            mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, rr->resrec.InterfaceID, mDNSfalse),
-            request->process_id, request->pid_name, status);
-        freeL("AuthRecord/handle_reconfirm_request", rr);
-    }
-    return(status);
-}
-
-
-mDNSlocal mStatus handle_release_request(request_state *request)
-{
-    (void) request;
-    return mStatus_UnsupportedErr;
-}
-
-
-mDNSlocal mStatus handle_setdomain_request(request_state *request)
-{
-    char domainstr[MAX_ESCAPED_DOMAIN_NAME];
-    domainname domain;
-    DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-    (void)flags; // Unused
-    if (get_string(&request->msgptr, request->msgend, domainstr, sizeof(domainstr)) < 0 ||
-        !MakeDomainNameFromDNSNameString(&domain, domainstr))
-    { LogMsg("%3d: DNSServiceSetDefaultDomainForUser(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
-
-    LogOperation("%3d: DNSServiceSetDefaultDomainForUser(%##s)", request->sd, domain.c);
-    return(mStatus_NoError);
-}
-
-typedef packedstruct
-{
-    mStatus err;
-    mDNSu32 len;
-    mDNSu32 vers;
-} DaemonVersionReply;
-
-mDNSlocal void handle_getproperty_request(request_state *request)
-{
-    const mStatus BadParamErr = (mStatus)dnssd_htonl((mDNSu32)mStatus_BadParamErr);
-    char prop[256];
-    if (get_string(&request->msgptr, request->msgend, prop, sizeof(prop)) >= 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceGetProperty(" PUB_S ")", request->request_id, prop);
-        if (!strcmp(prop, kDNSServiceProperty_DaemonVersion))
-        {
-            DaemonVersionReply x = { 0, dnssd_htonl(4), dnssd_htonl(_DNS_SD_H) };
-            send_all(request->sd, (const char *)&x, sizeof(x));
-            return;
-        }
-    }
-
-    // If we didn't recogize the requested property name, return BadParamErr
-    send_all(request->sd, (const char *)&BadParamErr, sizeof(BadParamErr));
-}
-
-mDNSlocal void handle_connection_delegate_request(request_state *request)
-{
-    (void) request;
-}
-
-typedef packedstruct
-{
-    mStatus err;
-    mDNSs32 pid;
-} PIDInfo;
-
-// ***************************************************************************
-// MARK: - DNSServiceNATPortMappingCreate
-
-#define DNSServiceProtocol(X) ((X) == NATOp_AddrRequest ? 0 : (X) == NATOp_MapUDP ? kDNSServiceProtocol_UDP : kDNSServiceProtocol_TCP)
-
-mDNSlocal void port_mapping_termination_callback(request_state *request)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP PID[%d](" PUB_S ")",
-           request->request_id, DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
-           mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
-           request->process_id, request->pid_name);
-
-    mDNS_StopNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
-}
-
-// Called via function pointer when we get a NAT Traversal (address request or port mapping) response
-mDNSlocal void port_mapping_create_request_callback(mDNS *m, NATTraversalInfo *n)
-{
-    request_state *request = (request_state *)n->clientContext;
-    reply_state *rep;
-    size_t replyLen;
-    uint8_t *data;
-
-    if (!request) { LogMsg("port_mapping_create_request_callback called with unknown request_state object"); return; }
-
-    // calculate reply data length
-    replyLen = sizeof(DNSServiceFlags);
-    replyLen += 3 * sizeof(mDNSu32);  // if index + addr + ttl
-    replyLen += sizeof(DNSServiceErrorType);
-    replyLen += 2 * sizeof(mDNSu16);  // Internal Port + External Port
-    replyLen += sizeof(mDNSu8);       // protocol
-
-    rep = create_reply(port_mapping_reply_op, replyLen, request);
-
-    rep->rhdr->flags = dnssd_htonl(0);
-    rep->rhdr->ifi   = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, n->InterfaceID, mDNSfalse));
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)n->Result);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    *data++ = request->u.pm.NATinfo.ExternalAddress.b[0];
-    *data++ = request->u.pm.NATinfo.ExternalAddress.b[1];
-    *data++ = request->u.pm.NATinfo.ExternalAddress.b[2];
-    *data++ = request->u.pm.NATinfo.ExternalAddress.b[3];
-    *data++ = DNSServiceProtocol(request->u.pm.NATinfo.Protocol);
-    *data++ = request->u.pm.NATinfo.IntPort.b[0];
-    *data++ = request->u.pm.NATinfo.IntPort.b[1];
-    *data++ = request->u.pm.NATinfo.ExternalPort.b[0];
-    *data++ = request->u.pm.NATinfo.ExternalPort.b[1];
-    put_uint32(request->u.pm.NATinfo.Lifetime, &data);
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) RESULT " PRI_IPv4_ADDR ":%u TTL %u",
-           request->request_id, DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
-           mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
-           &request->u.pm.NATinfo.ExternalAddress, mDNSVal16(request->u.pm.NATinfo.ExternalPort),
-           request->u.pm.NATinfo.Lifetime);
-
-    append_reply(request, rep);
-}
-
-mDNSlocal mStatus handle_port_mapping_request(request_state *request)
-{
-    mDNSu32 ttl = 0;
-    mStatus err = mStatus_NoError;
-
-    DNSServiceFlags flags          = get_flags(&request->msgptr, request->msgend);
-    mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
-    mDNSInterfaceID InterfaceID    = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
-    mDNSu8 protocol       = (mDNSu8)get_uint32(&request->msgptr, request->msgend);
-    (void)flags; // Unused
-    if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr);
-    if (request->msgptr + 8 > request->msgend) request->msgptr = NULL;
-    else
-    {
-        request->u.pm.NATinfo.IntPort.b[0] = *request->msgptr++;
-        request->u.pm.NATinfo.IntPort.b[1] = *request->msgptr++;
-        request->u.pm.ReqExt.b[0]          = *request->msgptr++;
-        request->u.pm.ReqExt.b[1]          = *request->msgptr++;
-        ttl = get_uint32(&request->msgptr, request->msgend);
-    }
-
-    if (!request->msgptr)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%d] DNSServiceNATPortMappingCreate(unreadable parameters)", request->request_id);
-        return(mStatus_BadParamErr);
-    }
-
-    if (protocol == 0)  // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too
-    {
-        if (!mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort) || !mDNSIPPortIsZero(request->u.pm.ReqExt) || ttl) return(mStatus_BadParamErr);
-    }
-    else
-    {
-        if (mDNSIPPortIsZero(request->u.pm.NATinfo.IntPort)) return(mStatus_BadParamErr);
-        if (!(protocol & (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP))) return(mStatus_BadParamErr);
-    }
-
-    request->flags                       = flags;
-    request->interfaceIndex              = interfaceIndex;
-    request->u.pm.NATinfo.Protocol       = !protocol ? NATOp_AddrRequest : (protocol == kDNSServiceProtocol_UDP) ? NATOp_MapUDP : NATOp_MapTCP;
-    //       u.pm.NATinfo.IntPort        = already set above
-    request->u.pm.NATinfo.RequestedPort  = request->u.pm.ReqExt;
-    request->u.pm.NATinfo.NATLease       = ttl;
-    request->u.pm.NATinfo.clientCallback = port_mapping_create_request_callback;
-    request->u.pm.NATinfo.clientContext  = request;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%d] DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START PID[%d](" PUB_S ")",
-           request->request_id, protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt),
-           request->u.pm.NATinfo.NATLease, request->process_id, request->pid_name);
-    err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
-    if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
-    else request->terminate = port_mapping_termination_callback;
-
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - DNSServiceGetAddrInfo
-
-mDNSlocal void addrinfo_termination_callback(request_state *request)
-{
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-           "[R%u] DNSServiceGetAddrInfo(" PRI_DM_NAME ") STOP PID[%d](" PUB_S ")",
-           request->request_id, DM_NAME_PARAM(GetAddrInfoClientRequestGetQName(&request->u.addrinfo)),
-           request->process_id, request->pid_name);
-
-    GetAddrInfoClientRequestStop(&request->u.addrinfo);
-}
-
-typedef struct {
-    mDNSu32     protocols;
-    char        hostname[MAX_ESCAPED_DOMAIN_NAME];
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mDNSBool    require_privacy;
-#endif
-} _addrinfo_start_params_t;
-
-mDNSlocal mStatus _handle_addrinfo_request_start(request_state *request, const _addrinfo_start_params_t * const params)
-{
-    mStatus err;
-
-    request->terminate = addrinfo_termination_callback;
-
-    GetAddrInfoClientRequestParams gaiParams;
-    GetAddrInfoClientRequestParamsInit(&gaiParams);
-    gaiParams.requestID      = request->request_id;
-    gaiParams.hostnameStr    = params->hostname;
-    gaiParams.interfaceIndex = request->interfaceIndex;
-    gaiParams.flags          = request->flags;
-    gaiParams.protocols      = params->protocols;
-    gaiParams.effectivePID   = request->validUUID ? 0 : request->process_id;
-    gaiParams.effectiveUUID  = request->validUUID ? request->uuid : mDNSNULL;
-    gaiParams.peerUID        = request->uid;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    gaiParams.needEncryption = params->require_privacy ? mDNStrue : mDNSfalse;
-    gaiParams.customID       = request->custom_service_id;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    gaiParams.peerAuditToken = &request->audit_token;
-#endif
-    err = GetAddrInfoClientRequestStart(&request->u.addrinfo, &gaiParams, queryrecord_result_reply, request);
-
-    return err;
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-
-mDNSlocal void _return_addrinfo_request_error(request_state * request, mStatus error)
-{
-    _return_queryrecord_request_error(request, error);
-}
-
-mDNSlocal mStatus _handle_addrinfo_request_with_trust(request_state *request, const _addrinfo_start_params_t * const params)
-{
-    mStatus err;
-    if (audit_token_to_pid(request->audit_token) == 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_WARNING, "[R%u] _handle_addrinfo_request_with_trust: no audit token for pid(%s %d)", request->request_id, request->pid_name, request->process_id);
-        err = _handle_addrinfo_request_start(request, params);
-    }
-    else
-    {
-        mdns_trust_flags_t flags = mdns_trust_flags_none;
-        mdns_trust_status_t status = mdns_trust_check_getaddrinfo(request->audit_token, params->hostname, &flags);
-        switch (status)
-        {
-            case mdns_trust_status_denied:
-            case mdns_trust_status_pending:
-            {
-                mdns_trust_t trust = mdns_trust_create(request->audit_token, NULL, flags);
-                if (!trust )
-                {
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-
-                void * context = mallocL("context/_handle_addrinfo_request_with_trust", sizeof(_addrinfo_start_params_t));
-                if (!context)
-                {
-                    my_perror("ERROR: mallocL context/_handle_addrinfo_request_with_trust");
-                    mdns_release(trust);
-                    err = mStatus_NoMemoryErr;
-                    goto exit;
-                }
-                memcpy(context, params, sizeof(_addrinfo_start_params_t));
-                mdns_trust_set_context(trust, context);
-                mdns_trust_service_set_context_finalizer(trust, ^(void *ref)
-                {
-                    freeL("context/_handle_addrinfo_request_with_trust finalizer", ref);
-                });
-                mdns_trust_set_queue(trust, _get_trust_results_dispatch_queue());
-                mdns_trust_set_event_handler(trust, ^(mdns_trust_event_t event, mdns_trust_status_t update)
-                {
-                    if (event == mdns_trust_event_result)
-                    {
-                        mStatus error = (update != mdns_trust_status_granted) ? mStatus_PolicyDenied : mStatus_NoError;
-                        KQueueLock();
-                        _addrinfo_start_params_t * _params =  mdns_trust_get_context(trust);
-                        if (_params)
-                        {
-                            if (!error)
-                            {
-                                error = _handle_addrinfo_request_start(request, _params);
-                                // No context means the request was canceled before we got here
-                            }
-                            if (error) // (not else if) Always check for error result
-                            {
-                                _return_addrinfo_request_error(request, error);
-                            }
-                        }
-                        KQueueUnlock("_handle_addrinfo_request_with_trust");
-                    }
-                });
-                request->trust = trust;
-                mdns_trust_activate(trust);
-                err = mStatus_NoError;
-                break;
-            }
-
-            case mdns_trust_status_no_entitlement:
-                err = mStatus_NoAuth;
-                break;
-
-            case mdns_trust_status_granted:
-                err = _handle_addrinfo_request_start(request, params);
-                break;
-        }
-    }
-exit:
-    return err;
-}
-#endif // TRUST_ENFORCEMENT
-
-mDNSlocal mStatus handle_addrinfo_request(request_state *request)
-{
-    mStatus             err;
-    DNSServiceFlags     flags;
-    mDNSu32             interfaceIndex;
-    _addrinfo_start_params_t params;
-
-    flags               = get_flags(&request->msgptr, request->msgend);
-    interfaceIndex      = get_uint32(&request->msgptr, request->msgend);
-    params.protocols    = get_uint32(&request->msgptr, request->msgend);
-    if (get_string(&request->msgptr, request->msgend, params.hostname, sizeof(params.hostname)) < 0)
-    {
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-    if (!request->msgptr)
-    {
-        LogMsg("%3d: DNSServiceGetAddrInfo(unreadable parameters)", request->sd);
-        err = mStatus_BadParamErr;
-        goto exit;
-    }
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    params.require_privacy = mDNSfalse;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) && MDNSRESPONDER_SUPPORTS(APPLE, IPC_TLV)
-    if (request->msgptr && (request->hdr.ipc_flags & IPC_FLAGS_TRAILING_TLVS))
-    {
-        size_t len;
-        const mDNSu8 *const start = (const mDNSu8 *)request->msgptr;
-        const mDNSu8 *const end   = (const mDNSu8 *)request->msgend;
-        const mDNSu8 *const data = get_tlv(start, end, IPC_TLV_TYPE_RESOLVER_CONFIG_PLIST_DATA, &len);
-        if (data)
-        {
-            request->custom_service_id = Querier_RegisterCustomDNSServiceWithPListData(data, len);
-        }
-        const mDNSu32 u32 = get_tlv_uint32(start, end, IPC_TLV_TYPE_REQUIRE_PRIVACY, mDNSNULL);
-        params.require_privacy = (u32 != 0) ? mDNStrue : mDNSfalse;
-    }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    err = get_signed_resolve_tlvs(request);
-    if (err) { LogMsg("%3d: handle_addrinfo_request err reading Validation TLVS", request->sd); return(err); }
-#endif
-    request->flags          = flags;
-    request->interfaceIndex = interfaceIndex;
-
-    mDNSBool enablesDNSSEC = mDNSfalse;
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    enablesDNSSEC = dns_service_flags_enables_dnssec(request->flags);
-#endif
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-        "[R%u] DNSServiceGetAddrInfo(%X, %d, %u, " PRI_S PUB_S ") START PID[%d](" PUB_S ")",
-        request->request_id, request->flags, request->interfaceIndex, params.protocols, params.hostname,
-        enablesDNSSEC ? ", DNSSEC" : "", request->process_id, request->pid_name);
-
-    mDNSPlatformMemZero(&request->u.addrinfo, (mDNSu32)sizeof(request->u.addrinfo));
-    request->terminate = NULL;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    mDNSBool trust_check_done = mDNSfalse;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    if (request->signed_obj)
-    {
-        mdns_signed_resolve_result_t resolveResult = mdns_signed_resolve_result_downcast(request->signed_obj);
-        if (resolveResult &&
-            mdns_signed_resolve_result_contains(resolveResult, params.hostname, interfaceIndex))
-        {
-            if (mdns_system_is_signed_result_uuid_valid(mdns_signed_result_get_uuid(resolveResult)))
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                       "[R%d] DNSServiceGetAddrInfo: Allowing signed result",
-                          request->request_id);
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-                trust_check_done = mDNStrue;
-#endif
-            }
-            else
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                       "[R%d] DNSServiceGetAddrInfo: Signed result UUID revoked.",
-                          request->request_id);
-                return mStatus_PolicyDenied;
-            }
-        }
-        else
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                   "[R%d] DNSServiceGetAddrInfo: Signed result does not cover hostname: " PRI_S ", ifindex: %u.",
-                      request->request_id, params.hostname, request->interfaceIndex);
-            request->sign_result = mDNSfalse;
-            mdns_forget(&request->signed_obj);
-        }
-    }
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    if (!trust_check_done && os_feature_enabled(mDNSResponder, bonjour_privacy))
-    {
-        err = _handle_addrinfo_request_with_trust(request, &params);
-    }
-    else
-    {
-        err = _handle_addrinfo_request_start(request, &params);
-    }
-#else
-    err = _handle_addrinfo_request_start(request, &params);
-#endif
-
-exit:
-    return(err);
-}
-
-// ***************************************************************************
-// MARK: - Main Request Handler etc.
-
-mDNSlocal request_state *NewRequest(void)
-{
-    request_state *request;
-    request_state **p = &all_requests;
-    request = (request_state *) callocL("request_state", sizeof(*request));
-    if (!request) FatalError("ERROR: calloc");
-    while (*p) p = &(*p)->next;
-    *p = request;
-    return(request);
-}
-
-// read_msg may be called any time when the transfer state (req->ts) is t_morecoming.
-// if there is no data on the socket, the socket will be closed and t_terminated will be returned
-mDNSlocal void read_msg(request_state *req)
-{
-    if (req->ts == t_terminated || req->ts == t_error)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                  "[R%u] ERROR: read_msg called with transfer state terminated or error", req->request_id);
-        req->ts = t_error;
-        return;
-    }
-
-    if (req->ts == t_complete)  // this must be death or something is wrong
-    {
-        char buf[4];    // dummy for death notification
-        const ssize_t nread = udsSupportReadFD(req->sd, buf, 4, 0, req->platform_data);
-        if (!nread) { req->ts = t_terminated; return; }
-        if (nread < 0) goto rerror;
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                  "[R%u] ERROR: read data from a completed request", req->request_id);
-        req->ts = t_error;
-        return;
-    }
-
-    if (req->ts != t_morecoming)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                  "[R%u] ERROR: read_msg called with invalid transfer state (%d)", req->request_id, req->ts);
-        req->ts = t_error;
-        return;
-    }
-
-    if (req->hdr_bytes < sizeof(ipc_msg_hdr))
-    {
-        const mDNSu32 nleft = sizeof(ipc_msg_hdr) - req->hdr_bytes;
-        const ssize_t nread = udsSupportReadFD(req->sd, (char *)&req->hdr + req->hdr_bytes, nleft, 0, req->platform_data);
-        if (nread == 0) { req->ts = t_terminated; return; }
-        if (nread < 0) goto rerror;
-        req->hdr_bytes += (mDNSu32)nread;
-        if (req->hdr_bytes > sizeof(ipc_msg_hdr))
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                      "[R%u] ERROR: read_msg - read too many header bytes", req->request_id);
-            req->ts = t_error;
-            return;
-        }
-
-        // only read data if header is complete
-        if (req->hdr_bytes == sizeof(ipc_msg_hdr))
-        {
-            ConvertHeaderBytes(&req->hdr);
-            if (req->hdr.version != VERSION)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                          "[R%u] ERROR: client version 0x%08X daemon version 0x%08X", req->request_id, req->hdr.version, VERSION);
-                req->ts = t_error;
-                return;
-            }
-
-            // Largest conceivable single request is a DNSServiceRegisterRecord() or DNSServiceAddRecord()
-            // with 64kB of rdata. Adding 1009 byte for a maximal domain name, plus a safety margin
-            // for other overhead, this means any message above 70kB is definitely bogus.
-            if (req->hdr.datalen > 70000)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                          "[R%u] ERROR: read_msg: hdr.datalen %u (0x%X) > 70000", req->request_id, req->hdr.datalen, req->hdr.datalen);
-                req->ts = t_error;
-                return;
-            }
-            req->msgbuf = (uint8_t *)callocL("request_state msgbuf", req->hdr.datalen + MSG_PAD_BYTES);
-            if (!req->msgbuf) { my_perror("ERROR: calloc"); req->ts = t_error; return; }
-            req->msgptr = req->msgbuf;
-            req->msgend = req->msgbuf + req->hdr.datalen;
-        }
-    }
-
-    // If our header is complete, but we're still needing more body data, then try to read it now
-    // Note: For cancel_request req->hdr.datalen == 0, but there's no error return socket for cancel_request
-    // Any time we need to get the error return socket we know we'll have at least one data byte
-    // (even if only the one-byte empty C string placeholder for the old ctrl_path parameter)
-    if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes < req->hdr.datalen)
-    {
-        size_t nleft = req->hdr.datalen - req->data_bytes;
-        ssize_t nread;
-#if !defined(_WIN32)
-        struct iovec vec = { req->msgbuf + req->data_bytes, nleft };    // Tell recvmsg where we want the bytes put
-        struct msghdr msg;
-        struct cmsghdr *cmsg = NULL;
-        char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
-        msg.msg_name       = 0;
-        msg.msg_namelen    = 0;
-        msg.msg_iov        = &vec;
-        msg.msg_iovlen     = 1;
-        msg.msg_control    = cbuf;
-        msg.msg_controllen = sizeof(cbuf);
-        msg.msg_flags      = 0;
-        nread = recvmsg(req->sd, &msg, 0);
-#else
-        nread = udsSupportReadFD(req->sd, (char *)req->msgbuf + req->data_bytes, nleft, 0, req->platform_data);
-#endif
-        if (nread == 0) { req->ts = t_terminated; return; }
-        if (nread < 0) goto rerror;
-        req->data_bytes += (size_t)nread;
-        if (req->data_bytes > req->hdr.datalen)
-        {
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                      "[R%u] ERROR: read_msg - read too many data bytes", req->request_id);
-            req->ts = t_error;
-            return;
-        }
-#if !defined(_WIN32)
-        // There is no error sd if IPC_FLAGS_NOERRSD is set.
-        if (!(req->hdr.ipc_flags & IPC_FLAGS_NOERRSD))
-        {
-            cmsg = CMSG_FIRSTHDR(&msg);
-        }
-#if defined(DEBUG_64BIT_SCM_RIGHTS) && DEBUG_64BIT_SCM_RIGHTS
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%u] Expecting %d %d %d %d", req->request_id, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                  "[R%u] Got       %d %d %d %d", req->request_id, msg.msg_controllen, cmsg ? cmsg->cmsg_len : -1, cmsg ? cmsg->cmsg_level : -1, cmsg ? cmsg->cmsg_type : -1);
-#endif // DEBUG_64BIT_SCM_RIGHTS
-        if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
-        {
-            req->errsd = *(dnssd_sock_t *)CMSG_DATA(cmsg);
-#if defined(DEBUG_64BIT_SCM_RIGHTS) && DEBUG_64BIT_SCM_RIGHTS
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                      "[R%u] read req->errsd %d", req->request_id, req->errsd);
-#endif // DEBUG_64BIT_SCM_RIGHTS
-            if (req->data_bytes < req->hdr.datalen)
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG,
-                          "[R%u] Client(PID [%d](" PUB_S ")) sent result code socket %d via SCM_RIGHTS with req->data_bytes %lu < req->hdr.datalen %d",
-                          req->request_id, req->process_id, req->pid_name, req->errsd, (unsigned long)req->data_bytes, req->hdr.datalen);
-                req->ts = t_error;
-                return;
-            }
-        }
-#endif
-    }
-
-    // If our header and data are both complete, see if we need to make our separate error return socket
-    if (req->hdr_bytes == sizeof(ipc_msg_hdr) && req->data_bytes == req->hdr.datalen)
-    {
-        if (!(req->hdr.ipc_flags & IPC_FLAGS_NOERRSD) && req->terminate && req->hdr.op != cancel_request)
-        {
-            dnssd_sockaddr_t cliaddr;
-#if defined(USE_TCP_LOOPBACK)
-            mDNSOpaque16 port;
-            u_long opt = 1;
-            port.b[0] = req->msgptr[0];
-            port.b[1] = req->msgptr[1];
-            req->msgptr += 2;
-            cliaddr.sin_family      = AF_INET;
-            cliaddr.sin_port        = port.NotAnInteger;
-            cliaddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-#else
-            char ctrl_path[MAX_CTLPATH];
-            get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH);  // path is first element in message buffer
-            mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr));
-            cliaddr.sun_family = AF_LOCAL;
-            mDNSPlatformStrLCopy(cliaddr.sun_path, ctrl_path, sizeof(cliaddr.sun_path));
-            // If the error return path UDS name is empty string, that tells us
-            // that this is a new version of the library that's going to pass us
-            // the error return path socket via sendmsg/recvmsg
-            if (ctrl_path[0] == 0)
-            {
-                if (req->errsd == req->sd)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                              "[R%u] read_msg: ERROR failed to get errsd via SCM_RIGHTS", req->request_id);
-                    req->ts = t_error;
-                    return;
-                }
-                goto got_errfd;
-            }
-#endif
-
-            req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0);
-            if (!dnssd_SocketValid(req->errsd))
-            {
-                my_throttled_perror("ERROR: socket");
-                req->ts = t_error;
-                return;
-            }
-
-            if (connect(req->errsd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0)
-            {
-#if !defined(USE_TCP_LOOPBACK)
-                struct stat sb;
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                          "[R%u] read_msg: Couldn't connect to error return path socket " PUB_S " errno %d (" PUB_S ")",
-                          req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
-                if (stat(cliaddr.sun_path, &sb) < 0)
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                              "[R%u] read_msg: stat failed " PUB_S " errno %d (" PUB_S ")",
-                              req->request_id, cliaddr.sun_path, dnssd_errno, dnssd_strerror(dnssd_errno));
-                }
-                else
-                {
-                    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                              "[R%u] read_msg: file " PUB_S " mode %o (octal) uid %d gid %d",
-                              req->request_id, cliaddr.sun_path, sb.st_mode, sb.st_uid, sb.st_gid);
-                }
-#endif
-                req->ts = t_error;
-                return;
-            }
-
-#if !defined(USE_TCP_LOOPBACK)
-got_errfd:
-#endif
-
-#if defined(_WIN32)
-            if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0)
-#else
-            if (fcntl(req->errsd, F_SETFL, fcntl(req->errsd, F_GETFL, 0) | O_NONBLOCK) != 0)
-#endif
-            {
-                LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-                          "[R%u] ERROR: could not set control socket to non-blocking mode errno %d (" PUB_S ")",
-                          req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
-                req->ts = t_error;
-                return;
-            }
-        }
-
-        req->ts = t_complete;
-    }
-
-    return;
-
-rerror:
-    if (dnssd_errno == dnssd_EWOULDBLOCK || dnssd_errno == dnssd_EINTR) return;
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_ERROR,
-              "[R%u] ERROR: read_msg errno %d (" PUB_S ")", req->request_id, dnssd_errno, dnssd_strerror(dnssd_errno));
-    req->ts = t_error;
-}
-
-mDNSlocal void returnAsyncErrorCode(request_state *const request, const mStatus error)
-{
-    size_t len;
-    const char *const emptystr = "\0";
-    uint8_t *data;
-    reply_state *rep;
-
-    LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-       "[R%u] returnAsyncErrorCode: error code(%d)", request->request_id, error);
-
-    //Do not call callback when there is no error, refer to rdar://88599677
-    if (error == mStatus_NoError)
-    {
-        return;
-    }
-    // calculate reply length
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(mDNSu32);  // interface index
-    len += sizeof(DNSServiceErrorType);
-    len += 2 * (strlen(emptystr) + 1); // empty name, empty target
-    len += 2 * sizeof(mDNSu16);  // port, txtLen
-    len += 0; //req->u.resolve.txt->rdlength;
-
-    rep = create_reply(async_error_op, len, request);
-
-    rep->rhdr->flags = 0;
-    rep->rhdr->ifi   = 0;
-    rep->rhdr->error = (DNSServiceErrorType)dnssd_htonl((mDNSu32)error);
-
-    data = (uint8_t *)&rep->rhdr[1];
-
-    // write reply data to message
-    put_string(emptystr, &data); // name
-    put_string(emptystr, &data); // target
-    put_uint16(0,        &data); // port
-    put_uint16(0,        &data); // txtLen
-
-    append_reply(request, rep);
-}
-
-mDNSlocal mStatus handle_client_request(request_state *req)
-{
-    mStatus err = mStatus_NoError;
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    SetupAuditTokenForRequest(req);
-#endif
-    switch(req->hdr.op)
-    {
-            // These are all operations that have their own first-class request_state object
-        case connection_request:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                   "[R%d] DNSServiceCreateConnection START PID[%d](" PUB_S ")",
-                   req->request_id, req->process_id, req->pid_name);
-            req->terminate = connection_termination;
-            break;
-        case connection_delegate_request:
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-                   "[R%d] DNSServiceCreateDelegateConnection START PID[%d](" PRI_S ")",
-                   req->request_id, req->process_id, req->pid_name);
-            req->terminate = connection_termination;
-            handle_connection_delegate_request(req);
-            break;
-        case resolve_request:              err = handle_resolve_request     (req);  break;
-        case query_request:                err = handle_queryrecord_request (req);  break;
-        case browse_request:               err = handle_browse_request      (req);  break;
-        case reg_service_request:          err = handle_regservice_request  (req);  break;
-        case enumeration_request:          err = handle_enum_request        (req);  break;
-        case reconfirm_record_request:     err = handle_reconfirm_request   (req);  break;
-        case setdomain_request:            err = handle_setdomain_request   (req);  break;
-        case getproperty_request:                handle_getproperty_request (req);  break;
-        case port_mapping_request:         err = handle_port_mapping_request(req);  break;
-        case addrinfo_request:             err = handle_addrinfo_request    (req);  break;
-        case send_bpf:                     /* Do nothing for send_bpf */            break;
-
-            // These are all operations that work with an existing request_state object
-        case reg_record_request:           err = handle_regrecord_request   (req);  break;
-        case add_record_request:           err = handle_add_request         (req);  break;
-        case update_record_request:        err = handle_update_request      (req);  break;
-        case remove_record_request:        err = handle_removerecord_request(req);  break;
-        case cancel_request:                     handle_cancel_request      (req);  break;
-        case release_request:              err = handle_release_request     (req);  break;
-        default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]",
-                        req->sd, req->hdr.op, req->process_id, req->pid_name);
-            err = mStatus_BadParamErr;
-            break;
-    }
-
-    return err;
-}
-
-#define RecordOrientedOp(X) \
-    ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request)
-
-// The lightweight operations are the ones that don't need a dedicated request_state structure allocated for them
-#define LightweightOp(X) (RecordOrientedOp(X) || (X) == cancel_request)
-
-mDNSlocal void request_callback(int fd, void *info)
-{
-    request_state *req = info;
-    (void)fd; // Unused
-
-    for (;;)
-    {
-        mStatus err = mStatus_NoError;
-        mDNSs32 min_size = sizeof(DNSServiceFlags);
-
-        read_msg(req);
-        if (req->ts == t_morecoming)
-            return;
-        if (req->ts == t_terminated || req->ts == t_error)
-        {
-            AbortUnlinkAndFree(req);
-            return;
-        }
-        if (req->ts != t_complete)
-        {
-            LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name);
-            AbortUnlinkAndFree(req);
-            return;
-        }
-
-        switch(req->hdr.op)            //          Interface       + other data
-        {
-            case connection_request:       min_size = 0;                                                                           break;
-            case connection_delegate_request: min_size = 4; /* pid */                                                              break;
-            case reg_service_request:      min_size += sizeof(mDNSu32) + 4 /* name, type, domain, host */ + 4 /* port, textlen */; break;
-            case add_record_request:       min_size +=                   4 /* type, rdlen */              + 4 /* ttl */;           break;
-            case update_record_request:    min_size +=                   2 /* rdlen */                    + 4 /* ttl */;           break;
-            case remove_record_request:                                                                                            break;
-            case browse_request:           min_size += sizeof(mDNSu32) + 2 /* type, domain */;                                     break;
-            case resolve_request:          min_size += sizeof(mDNSu32) + 3 /* type, type, domain */;                               break;
-            case query_request:            min_size += sizeof(mDNSu32) + 1 /* name */                     + 4 /* type, class*/;    break;
-            case enumeration_request:      min_size += sizeof(mDNSu32);                                                            break;
-            case reg_record_request:       min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */ + 4 /* ttl */;  break;
-            case reconfirm_record_request: min_size += sizeof(mDNSu32) + 1 /* name */ + 6 /* type, class, rdlen */;                break;
-            case setdomain_request:        min_size +=                   1 /* domain */;                                           break;
-            case getproperty_request:      min_size = 2;                                                                           break;
-            case port_mapping_request:     min_size += sizeof(mDNSu32) + 4 /* udp/tcp */ + 4 /* int/ext port */    + 4 /* ttl */;  break;
-            case addrinfo_request:         min_size += sizeof(mDNSu32) + 4 /* v4/v6 */   + 1 /* hostname */;                       break;
-            case send_bpf:                 // Same as cancel_request below
-            case cancel_request:           min_size = 0;                                                                           break;
-            case release_request:          min_size += sizeof(mDNSu32) + 3 /* type, type, domain */;                               break;
-            default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]",
-                            req->hdr.op, req->process_id, req->pid_name);
-                     min_size = -1;                                                                                                break;
-        }
-
-        if ((mDNSs32)req->data_bytes < min_size)
-        {
-            LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]",
-                    req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name);
-            AbortUnlinkAndFree(req);
-            return;
-        }
-        if (LightweightOp(req->hdr.op) && !req->terminate)
-        {
-            LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]",
-                    req->hdr.op, req->process_id, req->pid_name);
-            AbortUnlinkAndFree(req);
-            return;
-        }
-
-        // If req->terminate is already set, this means this operation is sharing an existing connection
-        if (req->terminate && !LightweightOp(req->hdr.op))
-        {
-            request_state *newreq = NewRequest();
-            newreq->primary = req;
-            newreq->sd      = req->sd;
-            newreq->errsd   = req->errsd;
-            newreq->uid     = req->uid;
-            newreq->hdr     = req->hdr;
-            newreq->msgbuf  = req->msgbuf;
-            newreq->msgptr  = req->msgptr;
-            newreq->msgend  = req->msgend;
-            newreq->request_id = GetNewRequestID();
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-            newreq->audit_token = req->audit_token;
-#endif
-            // if the parent request is a delegate connection, copy the
-            // relevant bits
-            if (req->validUUID)
-            {
-                newreq->validUUID = mDNStrue;
-                mDNSPlatformMemCopy(newreq->uuid, req->uuid, UUID_SIZE);
-            }
-            else
-            {
-                if (req->process_id)
-                {
-                    newreq->process_id = req->process_id;
-                    mDNSPlatformStrLCopy(newreq->pid_name, req->pid_name, (mDNSu32)sizeof(newreq->pid_name));
-                }
-                else
-                {
-                    set_peer_pid(newreq);
-                }
-            }
-            req = newreq;
-        }
-
-        // Check if the request wants no asynchronous replies.
-        if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = 1;
-
-        // If we're shutting down, don't allow new client requests
-        // We do allow "cancel" and "getproperty" during shutdown
-        if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
-            err = mStatus_ServiceNotRunning;
-        else
-            err = handle_client_request(req);
-
-        // req->msgbuf may be NULL, e.g. for connection_request or remove_record_request
-        if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
-
-        // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
-        // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
-        if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request && req->hdr.op != send_bpf && req->hdr.op != getpid_request)
-        {
-            const mStatus err_netorder = (mStatus)dnssd_htonl((mDNSu32)err);
-            if ((req->hdr.ipc_flags & IPC_FLAGS_NOERRSD))
-            {
-                returnAsyncErrorCode(req, err);
-            }
-            else
-            {
-                send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder));
-            }
-            if (req->errsd != req->sd)
-            {
-                dnssd_close(req->errsd);
-                req->errsd = req->sd;
-                // Also need to reset the parent's errsd, if this is a subordinate operation
-                if (req->primary) req->primary->errsd = req->primary->sd;
-            }
-        }
-
-        // Reset ready to accept the next req on this pipe
-        if (req->primary) req = req->primary;
-        req->ts         = t_morecoming;
-        req->hdr_bytes  = 0;
-        req->data_bytes = 0;
-        req->msgbuf     = mDNSNULL;
-        req->msgptr     = mDNSNULL;
-        req->msgend     = 0;
-    }
-}
-
-mDNSlocal void connect_callback(int fd, void *info)
-{
-    dnssd_sockaddr_t cliaddr;
-    dnssd_socklen_t len = (dnssd_socklen_t) sizeof(cliaddr);
-    dnssd_sock_t sd = accept(fd, (struct sockaddr*) &cliaddr, &len);
-#if defined(SO_NOSIGPIPE) || defined(_WIN32)
-    unsigned long optval = 1;
-#endif
-
-    (void)info; // Unused
-
-    if (!dnssd_SocketValid(sd))
-    {
-        if (dnssd_errno != dnssd_EWOULDBLOCK)
-            my_throttled_perror("ERROR: accept");
-        return;
-    }
-
-#ifdef SO_NOSIGPIPE
-    // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
-    if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
-    {
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "%3d: WARNING: setsockopt - SO_NOSIGPIPE %d (" PUB_S ")", sd, dnssd_errno,
-            dnssd_strerror(dnssd_errno));
-    }
-
-#endif
-
-#if defined(_WIN32)
-    if (ioctlsocket(sd, FIONBIO, &optval) != 0)
-#else
-    if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK) != 0)
-#endif
-    {
-        my_perror("ERROR: fcntl(sd, F_SETFL, O_NONBLOCK) - aborting client");
-        dnssd_close(sd);
-        return;
-    }
-    else
-    {
-        request_state *request = NewRequest();
-        request->ts    = t_morecoming;
-        request->sd    = sd;
-        request->errsd = sd;
-        request->request_id = GetNewRequestID();
-        set_peer_pid(request);
-        LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "%3d: connect_callback: Adding FD for uid %u", request->sd, request->uid);
-        udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data);
-    }
-}
-
-mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
-{
-#if defined(SO_NP_EXTENSIONS)
-    struct      so_np_extensions sonpx;
-    socklen_t optlen = sizeof(struct so_np_extensions);
-    sonpx.npx_flags = SONPX_SETOPTSHUT;
-    sonpx.npx_mask  = SONPX_SETOPTSHUT;
-    if (setsockopt(skt, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, optlen) < 0)
-        my_perror("WARNING: could not set sockopt - SO_NP_EXTENSIONS");
-#endif
-#if defined(_WIN32)
-    // SEH: do we even need to do this on windows?
-    // This socket will be given to WSAEventSelect which will automatically set it to non-blocking
-    u_long opt = 1;
-    if (ioctlsocket(skt, FIONBIO, &opt) != 0)
-#else
-    if (fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK) != 0)
-#endif
-    {
-        my_perror("ERROR: could not set listen socket to non-blocking mode");
-        return mDNSfalse;
-    }
-
-    if (listen(skt, LISTENQ) != 0)
-    {
-        my_perror("ERROR: could not listen on listen socket");
-        return mDNSfalse;
-    }
-
-    if (mStatus_NoError != udsSupportAddFDToEventLoop(skt, connect_callback, (void *) NULL, (void **) NULL))
-    {
-        my_perror("ERROR: could not add listen socket to event loop");
-        return mDNSfalse;
-    }
-    else
-    {
-        LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
-        mDNSStorage.uds_listener_skt = skt;
-    }
-    return mDNStrue;
-}
-
-#if MDNS_MALLOC_DEBUGGING
-mDNSlocal void udsserver_validatelists(void *context);
-#endif
-
-mDNSexport int udsserver_init(dnssd_sock_t skts[], const size_t count)
-{
-    dnssd_sockaddr_t laddr;
-    int ret;
-
-#ifndef NO_PID_FILE
-    FILE *fp = fopen(PID_FILE, "w");
-    if (fp != NULL)
-    {
-        fprintf(fp, "%d\n", getpid());
-        fclose(fp);
-    }
-#endif
-
-#if MDNS_MALLOC_DEBUGGING
-	static mDNSListValidator validator;
-	mDNSPlatformAddListValidator(&validator, udsserver_validatelists, "udsserver_validatelists", NULL);
-#endif
-
-    if (skts)
-    {
-        size_t i;
-        for (i = 0; i < count; i++)
-            if (dnssd_SocketValid(skts[i]) && !uds_socket_setup(skts[i]))
-                goto error;
-    }
-    else
-    {
-        listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-        if (!dnssd_SocketValid(listenfd))
-        {
-            my_perror("ERROR: socket(AF_DNSSD, SOCK_STREAM, 0); failed");
-            goto error;
-        }
-
-        mDNSPlatformMemZero(&laddr, sizeof(laddr));
-
-        #if defined(USE_TCP_LOOPBACK)
-        {
-            laddr.sin_family = AF_INET;
-#ifdef WIN32_CENTENNIAL
-            // sin_port = 0, use the first available port from the dynamic client port range (49152-65535)
-            // (Used to be MDNS_TCP_SERVERPORT_CENTENNIAL)
-#else
-            laddr.sin_port = htons(MDNS_TCP_SERVERPORT);
-#endif
-            laddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-            ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
-            if (ret < 0)
-            {
-                my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
-                goto error;
-            }
-
-#ifdef WIN32_CENTENNIAL
-            // Retrieve the port number assigned to the socket
-            mDNSPlatformMemZero(&laddr, sizeof(laddr));
-            int len = sizeof(laddr);
-
-            ret = getsockname(listenfd, (struct sockaddr*)&laddr, &len);
-            if (ret < 0)
-            {
-                my_perror("ERROR: getsockname(listenfd, (struct sockaddr*)&laddr, &len); failed");
-                goto error;
-            }
-
-            char port[128];
-            if (0 != _ultoa_s(ntohs(laddr.sin_port), port, sizeof(port), 10))
-            {
-                my_perror("ERROR: _itoa_s(ntohs(laddr.sin_port), &port); failed");
-                goto error;
-            }
-            if (!SetEnvironmentVariableA("MDNS_TCP_SERVERPORT_CENTENNIAL", port))
-            {
-                my_perror("ERROR: SetEnvironmentVariableA(MDNS_TCP_SERVERPORT_CENTENNIAL, port); failed");
-                goto error;
-            }
-#endif
-        }
-        #else
-        {
-            mode_t mask = umask(0);
-            unlink(boundPath);  // OK if this fails
-            laddr.sun_family = AF_LOCAL;
-            #ifndef NOT_HAVE_SA_LEN
-            // According to Stevens (section 3.2), there is no portable way to
-            // determine whether sa_len is defined on a particular platform.
-            laddr.sun_len = sizeof(struct sockaddr_un);
-            #endif
-            if (strlen(boundPath) >= sizeof(laddr.sun_path))
-            {
-                LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
-                goto error;
-            }
-            mDNSPlatformStrLCopy(laddr.sun_path, boundPath, sizeof(laddr.sun_path));
-            ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
-            umask(mask);
-            if (ret < 0)
-            {
-                my_perror("ERROR: bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); failed");
-                goto error;
-            }
-        }
-        #endif
-
-        if (!uds_socket_setup(listenfd)) goto error;
-    }
-
-#if !defined(PLATFORM_NO_RLIMIT)
-    {
-        // Set maximum number of open file descriptors
-    #define MIN_OPENFILES 10240
-        struct rlimit maxfds, newfds;
-
-        // Due to bugs in OS X (<rdar://problem/2941095>, <rdar://problem/3342704>, <rdar://problem/3839173>)
-        // you have to get and set rlimits once before getrlimit will return sensible values
-        if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
-        if (setrlimit(RLIMIT_NOFILE, &maxfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
-
-        if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
-        newfds.rlim_max = (maxfds.rlim_max > MIN_OPENFILES) ? maxfds.rlim_max : MIN_OPENFILES;
-        newfds.rlim_cur = (maxfds.rlim_cur > MIN_OPENFILES) ? maxfds.rlim_cur : MIN_OPENFILES;
-        if (newfds.rlim_max != maxfds.rlim_max || newfds.rlim_cur != maxfds.rlim_cur)
-            if (setrlimit(RLIMIT_NOFILE, &newfds) < 0) my_perror("ERROR: Unable to set maximum file descriptor limit");
-
-        if (getrlimit(RLIMIT_NOFILE, &maxfds) < 0) { my_perror("ERROR: Unable to get file descriptor limit"); return 0; }
-        debugf("maxfds.rlim_max %d", (long)maxfds.rlim_max);
-        debugf("maxfds.rlim_cur %d", (long)maxfds.rlim_cur);
-    }
-#endif
-
-    // We start a "LocalOnly" query looking for Automatic Browse Domain records.
-    // When Domain Enumeration in uDNS.c finds an "lb" record from the network, its "FoundDomain" routine
-    // creates a "LocalOnly" record, which results in our AutomaticBrowseDomainChange callback being invoked
-    mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ_Internal, mDNS_DomainTypeBrowseAutomatic,
-        mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL);
-
-    // Add "local" as recommended registration domain ("dns-sd -E"), recommended browsing domain ("dns-sd -F"), and automatic browsing domain
-    RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration);
-    RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse);
-    AddAutoBrowseDomain(0, &localdomain);
-
-    udsserver_handle_configchange(&mDNSStorage);
-    return 0;
-
-error:
-
-    my_perror("ERROR: udsserver_init");
-    return -1;
-}
-
-mDNSexport int udsserver_exit(void)
-{
-    // Cancel all outstanding client requests
-    while (all_requests) AbortUnlinkAndFree(all_requests);
-
-    // Clean up any special mDNSInterface_LocalOnly records we created, both the entries for "local" we
-    // created in udsserver_init, and others we created as a result of reading local configuration data
-    while (LocalDomainEnumRecords)
-    {
-        ARListElem *rem = LocalDomainEnumRecords;
-        LocalDomainEnumRecords = LocalDomainEnumRecords->next;
-        mDNS_Deregister(&mDNSStorage, &rem->ar);
-    }
-
-    // If the launching environment created no listening socket,
-    // that means we created it ourselves, so we should clean it up on exit
-    if (dnssd_SocketValid(listenfd))
-    {
-        dnssd_close(listenfd);
-#if !defined(USE_TCP_LOOPBACK)
-        // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
-        // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
-        // It would be nice if we could find a solution to this problem
-        if (unlink(boundPath))
-            debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
-#endif
-    }
-
-#ifndef NO_PID_FILE
-    unlink(PID_FILE);
-#endif
-
-    return 0;
-}
-
-mDNSlocal void LogClientInfoToFD(int fd, request_state *req)
-{
-    char reqIDStr[14];
-    char prefix[18];
-
-    mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
-
-    mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
-
-    if (!req->terminate)
-        LogToFD(fd, "%s No operation yet on this socket", prefix);
-    else if (req->terminate == connection_termination)
-    {
-        int num_records = 0, num_ops = 0;
-        const registered_record_entry *p;
-        request_state *r;
-        for (p = req->u.reg_recs; p; p=p->next) num_records++;
-        for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
-        LogToFD(fd, "%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
-                  prefix, num_records, num_records != 1 ? "s" : "", num_ops,     num_ops     != 1 ? "s" : "",
-                  req->process_id, req->pid_name);
-        for (p = req->u.reg_recs; p; p=p->next)
-            LogToFD(fd, " ->  DNSServiceRegisterRecord   0x%08X %2d %3d %s PID[%d](%s)",
-                      req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
-        for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfoToFD(fd, r);
-    }
-    else if (req->terminate == regservice_termination_callback)
-    {
-        service_instance *ptr;
-        for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-            LogToFD(fd, "%-9s DNSServiceRegister         0x%08X %2d %##s %u/%u PID[%d](%s)",
-                      (ptr == req->u.servicereg.instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
-                      mDNSVal16(req->u.servicereg.port),
-                      SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
-    }
-    else if (req->terminate == browse_termination_callback)
-    {
-        browser_t *blist;
-        for (blist = req->u.browser.browsers; blist; blist = blist->next)
-            LogToFD(fd, "%-9s DNSServiceBrowse           0x%08X %2d %##s PID[%d](%s)",
-                      (blist == req->u.browser.browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
-                      req->process_id, req->pid_name);
-    }
-    else if (req->terminate == resolve_termination_callback)
-        LogToFD(fd, "%s DNSServiceResolve          0x%08X %2d %##s PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name);
-    else if (req->terminate == queryrecord_termination_callback)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-        const bool redacted = (req->u.queryrecord.op.q.logPrivacyLevel == dnssd_log_privacy_level_private);
-#endif
-
-        LogToFD(fd, "%s DNSServiceQueryRecord      0x%08X %2d %##s (%s) PID[%d](%s)", prefix, req->flags,
-            req->interfaceIndex,
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-            redacted ? PRIVATE_DOMAIN_NAME : QueryRecordClientRequestGetQName(&req->u.queryrecord),
-#else
-            QueryRecordClientRequestGetQName(&req->u.queryrecord),
-#endif
-            DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)),
-            req->process_id, req->pid_name);
-    }
-    else if (req->terminate == enum_termination_callback)
-        LogToFD(fd, "%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex, req->u.enumeration.q_all.qname.c, req->process_id, req->pid_name);
-    else if (req->terminate == port_mapping_termination_callback)
-        LogToFD(fd, "%s DNSServiceNATPortMapping   0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)",
-                  prefix,
-                  req->flags,
-                  req->interfaceIndex,
-                  req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : "   ",
-                  req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : "   ",
-                  mDNSVal16(req->u.pm.NATinfo.IntPort),
-                  mDNSVal16(req->u.pm.ReqExt),
-                  &req->u.pm.NATinfo.ExternalAddress,
-                  mDNSVal16(req->u.pm.NATinfo.ExternalPort),
-                  req->u.pm.NATinfo.NATLease,
-                  req->u.pm.NATinfo.Lifetime,
-                  req->process_id, req->pid_name);
-    else if (req->terminate == addrinfo_termination_callback)
-    {
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-        const GetAddrInfoClientRequest *const request = &req->u.addrinfo;
-        bool redacted = false;
-        if (request->op4)
-        {
-            redacted = (request->op4->q.logPrivacyLevel == dnssd_log_privacy_level_private);
-        }
-        else if (request->op6)
-        {
-            redacted = (request->op6->q.logPrivacyLevel == dnssd_log_privacy_level_private);
-        }
-#endif
-
-        LogToFD(fd, "%s DNSServiceGetAddrInfo      0x%08X %2d %s%s %##s PID[%d](%s)", prefix, req->flags,
-            req->interfaceIndex,
-            req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
-            req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-            redacted ? PRIVATE_DOMAIN_NAME : GetAddrInfoClientRequestGetQName(&req->u.addrinfo),
-#else
-            GetAddrInfoClientRequestGetQName(&req->u.addrinfo),
-#endif
-            req->process_id, req->pid_name);
-    }
-    else
-        LogToFD(fd, "%s Unrecognized operation %p", prefix, req->terminate);
-}
-
-mDNSlocal void LogClientInfo(request_state *req)
-{
-    char reqIDStr[14];
-    char prefix[18];
-
-    mDNS_snprintf(reqIDStr, sizeof(reqIDStr), "[R%u]", req->request_id);
-
-    mDNS_snprintf(prefix, sizeof(prefix), "%-6s %2s", reqIDStr, req->primary ? "->" : "");
-
-    if (!req->terminate)
-    LogMsgNoIdent("%s No operation yet on this socket", prefix);
-    else if (req->terminate == connection_termination)
-    {
-        int num_records = 0, num_ops = 0;
-        const registered_record_entry *p;
-        request_state *r;
-        for (p = req->u.reg_recs; p; p=p->next) num_records++;
-        for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
-        LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
-                      prefix, num_records, num_records != 1 ? "s" : "", num_ops,     num_ops     != 1 ? "s" : "",
-                      req->process_id, req->pid_name);
-        for (p = req->u.reg_recs; p; p=p->next)
-        LogMsgNoIdent(" ->  DNSServiceRegisterRecord   0x%08X %2d %3d %s PID[%d](%s)",
-                      req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name);
-        for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(r);
-    }
-    else if (req->terminate == regservice_termination_callback)
-    {
-        service_instance *ptr;
-        for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-        LogMsgNoIdent("%-9s DNSServiceRegister         0x%08X %2d %##s %u/%u PID[%d](%s)",
-                      (ptr == req->u.servicereg.instances) ? prefix : "", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c,
-                      mDNSVal16(req->u.servicereg.port),
-                      SRS_PORT(&ptr->srs), req->process_id, req->pid_name);
-    }
-    else if (req->terminate == browse_termination_callback)
-    {
-        browser_t *blist;
-        for (blist = req->u.browser.browsers; blist; blist = blist->next)
-        LogMsgNoIdent("%-9s DNSServiceBrowse           0x%08X %2d %##s PID[%d](%s)",
-                      (blist == req->u.browser.browsers) ? prefix : "", req->flags, req->interfaceIndex, blist->q.qname.c,
-                      req->process_id, req->pid_name);
-    }
-    else if (req->terminate == resolve_termination_callback)
-    LogMsgNoIdent("%s DNSServiceResolve          0x%08X %2d %##s PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name);
-    else if (req->terminate == queryrecord_termination_callback)
-    LogMsgNoIdent("%s DNSServiceQueryRecord      0x%08X %2d %##s (%s) PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex, QueryRecordClientRequestGetQName(&req->u.queryrecord), DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)), req->process_id, req->pid_name);
-    else if (req->terminate == enum_termination_callback)
-    LogMsgNoIdent("%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex, req->u.enumeration.q_all.qname.c, req->process_id, req->pid_name);
-    else if (req->terminate == port_mapping_termination_callback)
-    LogMsgNoIdent("%s DNSServiceNATPortMapping   0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)",
-                  prefix,
-                  req->flags,
-                  req->interfaceIndex,
-                  req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : "   ",
-                  req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : "   ",
-                  mDNSVal16(req->u.pm.NATinfo.IntPort),
-                  mDNSVal16(req->u.pm.ReqExt),
-                  &req->u.pm.NATinfo.ExternalAddress,
-                  mDNSVal16(req->u.pm.NATinfo.ExternalPort),
-                  req->u.pm.NATinfo.NATLease,
-                  req->u.pm.NATinfo.Lifetime,
-                  req->process_id, req->pid_name);
-    else if (req->terminate == addrinfo_termination_callback)
-    LogMsgNoIdent("%s DNSServiceGetAddrInfo      0x%08X %2d %s%s %##s PID[%d](%s)",
-                  prefix, req->flags, req->interfaceIndex,
-                  req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
-                  req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
-                  GetAddrInfoClientRequestGetQName(&req->u.addrinfo), req->process_id, req->pid_name);
-    else
-    LogMsgNoIdent("%s Unrecognized operation %p", prefix, req->terminate);
-}
-
-mDNSlocal void GetMcastClients(request_state *req)
-{
-    if (req->terminate == connection_termination)
-    {
-        int num_records = 0, num_ops = 0;
-        const registered_record_entry *p;
-        request_state *r;
-        for (p = req->u.reg_recs; p; p=p->next)
-            num_records++;
-        for (r = req->next; r; r=r->next)
-            if (r->primary == req)
-                num_ops++;
-        for (p = req->u.reg_recs; p; p=p->next)
-        {
-            if (!AuthRecord_uDNS(p->rr))
-                n_mrecords++;
-        }
-        for (r = req->next; r; r=r->next)
-            if (r->primary == req)
-                GetMcastClients(r);
-    }
-    else if (req->terminate == regservice_termination_callback)
-    {
-        service_instance *ptr;
-        for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-        {
-            if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
-                n_mrecords++;
-        }
-    }
-    else if (req->terminate == browse_termination_callback)
-    {
-        browser_t *blist;
-        for (blist = req->u.browser.browsers; blist; blist = blist->next)
-        {
-            if (mDNSOpaque16IsZero(blist->q.TargetQID))
-                n_mquests++;
-        }
-    }
-    else if (req->terminate == resolve_termination_callback)
-    {
-        if ((mDNSOpaque16IsZero(req->u.resolve.qsrv.TargetQID)) && (req->u.resolve.qsrv.ThisQInterval > 0))
-            n_mquests++;
-    }
-    else if (req->terminate == queryrecord_termination_callback)
-    {
-        if (QueryRecordClientRequestIsMulticast(&req->u.queryrecord))
-            n_mquests++;
-    }
-    else if (req->terminate == addrinfo_termination_callback)
-    {
-        if (GetAddrInfoClientRequestIsMulticast(&req->u.addrinfo))
-            n_mquests++;
-    }
-    else
-    {
-        return;
-    }
-}
-
-
-mDNSlocal void LogMcastClientInfo(request_state *req)
-{
-    if (!req->terminate)
-        LogMcastNoIdent("No operation yet on this socket");
-    else if (req->terminate == connection_termination)
-    {
-        int num_records = 0, num_ops = 0;
-        const registered_record_entry *p;
-        request_state *r;
-        for (p = req->u.reg_recs; p; p=p->next)
-            num_records++;
-        for (r = req->next; r; r=r->next)
-            if (r->primary == req)
-                num_ops++;
-        for (p = req->u.reg_recs; p; p=p->next)
-        {
-            if (!AuthRecord_uDNS(p->rr))
-                LogMcastNoIdent("R: ->  DNSServiceRegisterRecord:  %##s %s PID[%d](%s)", p->rr->resrec.name->c,
-                                DNSTypeName(p->rr->resrec.rrtype), req->process_id, req->pid_name, i_mcount++);
-        }
-        for (r = req->next; r; r=r->next)
-            if (r->primary == req)
-                LogMcastClientInfo(r);
-    }
-    else if (req->terminate == regservice_termination_callback)
-    {
-        service_instance *ptr;
-        for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
-        {
-            if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
-                LogMcastNoIdent("R: DNSServiceRegister:  %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port),
-                                SRS_PORT(&ptr->srs), req->process_id, req->pid_name, i_mcount++);
-        }
-    }
-    else if (req->terminate == browse_termination_callback)
-    {
-        browser_t *blist;
-        for (blist = req->u.browser.browsers; blist; blist = blist->next)
-        {
-            if (mDNSOpaque16IsZero(blist->q.TargetQID))
-                LogMcastNoIdent("Q: DNSServiceBrowse  %##s %s PID[%d](%s)", blist->q.qname.c, DNSTypeName(blist->q.qtype),
-                                req->process_id, req->pid_name, i_mcount++);
-        }
-    }
-    else if (req->terminate == resolve_termination_callback)
-    {
-        if ((mDNSOpaque16IsZero(req->u.resolve.qsrv.TargetQID)) && (req->u.resolve.qsrv.ThisQInterval > 0))
-            LogMcastNoIdent("Q: DNSServiceResolve  %##s %s PID[%d](%s)", req->u.resolve.qsrv.qname.c, DNSTypeName(req->u.resolve.qsrv.qtype),
-                            req->process_id, req->pid_name, i_mcount++);
-    }
-    else if (req->terminate == queryrecord_termination_callback)
-    {
-        if (QueryRecordClientRequestIsMulticast(&req->u.queryrecord))
-        {
-            LogMcastNoIdent("Q: DNSServiceQueryRecord  %##s %s PID[%d](%s)",
-                          QueryRecordClientRequestGetQName(&req->u.queryrecord),
-                          DNSTypeName(QueryRecordClientRequestGetType(&req->u.queryrecord)),
-                          req->process_id, req->pid_name, i_mcount++);
-        }
-    }
-    else if (req->terminate == addrinfo_termination_callback)
-    {
-        if (GetAddrInfoClientRequestIsMulticast(&req->u.addrinfo))
-        {
-            LogMcastNoIdent("Q: DNSServiceGetAddrInfo  %s%s %##s PID[%d](%s)",
-                          req->u.addrinfo.protocols & kDNSServiceProtocol_IPv4 ? "v4" : "  ",
-                          req->u.addrinfo.protocols & kDNSServiceProtocol_IPv6 ? "v6" : "  ",
-                          GetAddrInfoClientRequestGetQName(&req->u.addrinfo), req->process_id, req->pid_name, i_mcount++);
-        }
-    }
-}
-
-mDNSlocal char *RecordTypeName(mDNSu8 rtype)
-{
-    switch (rtype)
-    {
-    case kDNSRecordTypeUnregistered:  return ("Unregistered ");
-    case kDNSRecordTypeDeregistering: return ("Deregistering");
-    case kDNSRecordTypeUnique:        return ("Unique       ");
-    case kDNSRecordTypeAdvisory:      return ("Advisory     ");
-    case kDNSRecordTypeShared:        return ("Shared       ");
-    case kDNSRecordTypeVerified:      return ("Verified     ");
-    case kDNSRecordTypeKnownUnique:   return ("KnownUnique  ");
-    default: return("Unknown");
-    }
-}
-
-mDNSlocal int LogEtcHostsToFD(int fd, mDNS *const m)
-{
-    mDNSBool showheader = mDNStrue;
-    const AuthRecord *ar;
-    mDNSu32 slot;
-    AuthGroup *ag;
-    int count = 0;
-    int authslot = 0;
-    mDNSBool truncated = 0;
-
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-    {
-        if (m->rrauth.rrauth_hash[slot]) authslot++;
-        for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
-            for (ar = ag->members; ar; ar = ar->next)
-            {
-                if (ar->RecordCallback != FreeEtcHosts) continue;
-                if (showheader) { showheader = mDNSfalse; LogToFD(fd, "  State       Interface"); }
-
-                // Print a maximum of 50 records
-                if (count++ >= 50) { truncated = mDNStrue; continue; }
-                if (ar->ARType == AuthRecordLocalOnly)
-                {
-                    if (ar->resrec.InterfaceID == mDNSInterface_LocalOnly)
-                        LogToFD(fd, " %s   LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
-                    else
-                    {
-                        mDNSu32 scopeid  = (mDNSu32)(uintptr_t)ar->resrec.InterfaceID;
-                        LogToFD(fd, " %s   %u  %s", RecordTypeName(ar->resrec.RecordType), scopeid, ARDisplayString(m, ar));
-                    }
-                }
-            }
-    }
-
-    if (showheader) LogToFD(fd, "<None>");
-    else if (truncated) LogToFD(fd, "<Truncated: to 50 records, Total records %d, Total Auth Groups %d, Auth Slots %d>", count, m->rrauth.rrauth_totalused, authslot);
-    return count;
-}
-
-mDNSlocal void LogLocalOnlyAuthRecordsToFD(int fd, mDNS *const m)
-{
-    mDNSBool showheader = mDNStrue;
-    const AuthRecord *ar;
-    mDNSu32 slot;
-    AuthGroup *ag;
-
-    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)
-            {
-                if (ar->RecordCallback == FreeEtcHosts) continue;
-                if (showheader) { showheader = mDNSfalse; LogToFD(fd, "  State       Interface"); }
-
-                // Print a maximum of 400 records
-                if (ar->ARType == AuthRecordLocalOnly)
-                    LogToFD(fd, " %s   LO  %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
-                else if (ar->ARType == AuthRecordP2P)
-                {
-                    if (ar->resrec.InterfaceID == mDNSInterface_BLE)
-                        LogToFD(fd, " %s   BLE %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
-                    else
-                        LogToFD(fd, " %s   PP  %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
-                }
-            }
-    }
-
-    if (showheader) LogToFD(fd, "<None>");
-}
-
-mDNSlocal void LogOneAuthRecordToFD(int fd, const AuthRecord *ar, mDNSs32 now, const char *ifname)
-{
-    if (AuthRecord_uDNS(ar))
-    {
-        LogToFD(fd, "%7d %7d %7d %-7s %4d %s %s",
-                  ar->ThisAPInterval / mDNSPlatformOneSecond,
-                  (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
-                  ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
-                  "-U-",
-                  ar->state,
-                  ar->AllowRemoteQuery ? "☠" : " ",
-                  ARDisplayString(&mDNSStorage, ar));
-    }
-    else
-    {
-        LogToFD(fd, "%7d %7d %7d %-7s 0x%02X %s %s",
-                  ar->ThisAPInterval / mDNSPlatformOneSecond,
-                  ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
-                  ar->TimeExpire    ? (ar->TimeExpire                      - now) / mDNSPlatformOneSecond : 0,
-                  ifname ? ifname : "ALL",
-                  ar->resrec.RecordType,
-                  ar->AllowRemoteQuery ? "☠" : " ",
-                  ARDisplayString(&mDNSStorage, ar));
-    }
-}
-
-mDNSlocal void LogAuthRecordsToFD(int fd,
-                                    const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy)
-{
-    mDNSBool showheader = mDNStrue;
-    const AuthRecord *ar;
-    OwnerOptData owner = zeroOwner;
-    for (ar = ResourceRecords; ar; ar=ar->next)
-    {
-        const char *const ifname = InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID);
-        if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
-        {
-            if (showheader) { showheader = mDNSfalse; LogToFD(fd, "    Int    Next  Expire if     State"); }
-            if (proxy) (*proxy)++;
-            if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
-            {
-                owner = ar->WakeUp;
-                if (owner.password.l[0])
-                    LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
-                else if (!mDNSSameEthAddress(&owner.HMAC, &owner.IMAC))
-                    LogToFD(fd, "Proxying for H-MAC %.6a I-MAC %.6a seq %d",               &owner.HMAC, &owner.IMAC,                  owner.seq);
-                else
-                    LogToFD(fd, "Proxying for %.6a seq %d",                                &owner.HMAC,                               owner.seq);
-            }
-            if (AuthRecord_uDNS(ar))
-            {
-                LogOneAuthRecordToFD(fd, ar, now, ifname);
-            }
-            else if (ar->ARType == AuthRecordLocalOnly)
-            {
-                LogToFD(fd, "                             LO %s", ARDisplayString(&mDNSStorage, ar));
-            }
-            else if (ar->ARType == AuthRecordP2P)
-            {
-                if (ar->resrec.InterfaceID == mDNSInterface_BLE)
-                    LogToFD(fd, "                             BLE %s", ARDisplayString(&mDNSStorage, ar));
-                else
-                    LogToFD(fd, "                             PP %s", ARDisplayString(&mDNSStorage, ar));
-            }
-            else
-            {
-                LogOneAuthRecordToFD(fd, ar, now, ifname);
-            }
-        }
-    }
-    if (showheader) LogToFD(fd, "<None>");
-}
-
-mDNSlocal void PrintOneCacheRecordToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
-{
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    char *dnssec_description = dnssec_obj_resource_record_member_copy_state_dump_description(cr->resrec.dnssec, NULL);
-#endif
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-    const mDNSBool redacted = (cr->PrivacyLevel == CRLogPrivacyLevel_Private);
-#endif
-
-    LogToFD(fd, "%3d %s%8d %-7s%s %-6s"
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-              "   %-40s"
-#endif
-              "%s",
-              slot,
-              cr->CRActiveQuestion ? "*" : " ",
-              remain,
-              ifname ? ifname : "-U-",
-              (cr->resrec.RecordType == kDNSRecordTypePacketNegative)  ? "-" :
-              (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+",
-              DNSTypeName(cr->resrec.rrtype),
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-              dnssec_description,
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-              redacted ? "     " PRIVATE_RECORD_DESCRIPTION : CRDisplayString(&mDNSStorage, cr)
-#else
-              CRDisplayString(&mDNSStorage, cr)
-#endif
-            );
-    (*CacheUsed)++;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-    mdns_free(dnssec_description);
-#endif
-}
-
-mDNSlocal void PrintCachedRecordsToFD(int fd, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed)
-{
-    CacheRecord *soa;
-
-    soa = cr->soa;
-    if (soa)
-    {
-        PrintOneCacheRecordToFD(fd, soa, slot, remain, ifname, CacheUsed);
-    }
-}
-
-mDNSexport void LogMDNSStatisticsToFD(int fd, mDNS *const m)
-{
-    LogToFD(fd, "--- MDNS Statistics ---");
-
-    LogToFD(fd, "Name Conflicts                 %u", m->mDNSStats.NameConflicts);
-    LogToFD(fd, "KnownUnique Name Conflicts     %u", m->mDNSStats.KnownUniqueNameConflicts);
-    LogToFD(fd, "Duplicate Query Suppressions   %u", m->mDNSStats.DupQuerySuppressions);
-    LogToFD(fd, "KA Suppressions                %u", m->mDNSStats.KnownAnswerSuppressions);
-    LogToFD(fd, "KA Multiple Packets            %u", m->mDNSStats.KnownAnswerMultiplePkts);
-    LogToFD(fd, "Poof Cache Deletions           %u", m->mDNSStats.PoofCacheDeletions);
-    LogToFD(fd, "--------------------------------");
-
-    LogToFD(fd, "Multicast packets Sent         %u", m->MulticastPacketsSent);
-    LogToFD(fd, "Multicast packets Received     %u", m->MPktNum);
-    LogToFD(fd, "Remote Subnet packets          %u", m->RemoteSubnet);
-    LogToFD(fd, "QU questions  received         %u", m->mDNSStats.UnicastBitInQueries);
-    LogToFD(fd, "Normal multicast questions     %u", m->mDNSStats.NormalQueries);
-    LogToFD(fd, "Answers for questions          %u", m->mDNSStats.MatchingAnswersForQueries);
-    LogToFD(fd, "Unicast responses              %u", m->mDNSStats.UnicastResponses);
-    LogToFD(fd, "Multicast responses            %u", m->mDNSStats.MulticastResponses);
-    LogToFD(fd, "Unicast response Demotions     %u", m->mDNSStats.UnicastDemotedToMulticast);
-    LogToFD(fd, "--------------------------------");
-
-    LogToFD(fd, "Sleeps                         %u", m->mDNSStats.Sleeps);
-    LogToFD(fd, "Wakeups                        %u", m->mDNSStats.Wakes);
-    LogToFD(fd, "Interface UP events            %u", m->mDNSStats.InterfaceUp);
-    LogToFD(fd, "Interface UP Flap events       %u", m->mDNSStats.InterfaceUpFlap);
-    LogToFD(fd, "Interface Down events          %u", m->mDNSStats.InterfaceDown);
-    LogToFD(fd, "Interface DownFlap events      %u", m->mDNSStats.InterfaceDownFlap);
-    LogToFD(fd, "Cache refresh queries          %u", m->mDNSStats.CacheRefreshQueries);
-    LogToFD(fd, "Cache refreshed                %u", m->mDNSStats.CacheRefreshed);
-    LogToFD(fd, "Wakeup on Resolves             %u", m->mDNSStats.WakeOnResolves);
-}
-
-mDNSexport void udsserver_info_dump_to_fd(int fd)
-{
-    mDNS *const m = &mDNSStorage;
-    const mDNSs32 now = mDNS_TimeNow(m);
-    mDNSu32 CacheUsed = 0, CacheActive = 0, slot;
-    int ProxyA = 0, ProxyD = 0;
-    mDNSu32 groupCount = 0;
-    mDNSu32 mcastRecordCount = 0;
-    mDNSu32 ucastRecordCount = 0;
-    const CacheGroup *cg;
-    const CacheRecord *cr;
-    const DNSQuestion *q;
-    const DNameListElem *d;
-    const SearchListElem *s;
-
-    LogToFD(fd, "------------ Cache -------------");
-    LogToFD(fd, "Slt Q     TTL if     U Type     DNSSEC                                   rdlen");
-    for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-    {
-        for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
-        {
-            groupCount++;   // Count one cache entity for the CacheGroup object
-            for (cr = cg->members; cr; cr=cr->next)
-            {
-                const mDNSu32 remain = cr->resrec.rroriginalttl - (mDNSu32)((now - cr->TimeRcvd) / mDNSPlatformOneSecond);
-                const char *ifname;
-                mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
-                mDNSu32 *const countPtr = InterfaceID ? &mcastRecordCount : &ucastRecordCount;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                if (!InterfaceID && cr->resrec.dnsservice &&
-                    (mdns_dns_service_get_scope(cr->resrec.dnsservice) == mdns_dns_service_scope_interface))
-                {
-                    InterfaceID = (mDNSInterfaceID)(uintptr_t)mdns_dns_service_get_interface_index(cr->resrec.dnsservice);
-                }
-#else
-                if (!InterfaceID && cr->resrec.rDNSServer && cr->resrec.rDNSServer->scopeType)
-                    InterfaceID = cr->resrec.rDNSServer->interface;
-#endif
-                ifname = InterfaceNameForID(m, InterfaceID);
-                if (cr->CRActiveQuestion) CacheActive++;
-                PrintOneCacheRecordToFD(fd, cr, slot, remain, ifname, countPtr);
-                PrintCachedRecordsToFD(fd, cr, slot, remain, ifname, countPtr);
-            }
-        }
-    }
-
-    CacheUsed = groupCount + mcastRecordCount + ucastRecordCount;
-    if (m->rrcache_totalused != CacheUsed)
-        LogToFD(fd, "Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed);
-    if (m->rrcache_active != CacheActive)
-        LogToFD(fd, "Cache use mismatch: rrcache_active is %lu, true count %lu", m->rrcache_active, CacheActive);
-    LogToFD(fd, "Cache size %u entities; %u in use (%u group, %u multicast, %u unicast); %u referenced by active questions",
-              m->rrcache_size, CacheUsed, groupCount, mcastRecordCount, ucastRecordCount, CacheActive);
-
-    LogToFD(fd, "--------- Auth Records ---------");
-    LogAuthRecordsToFD(fd, now, m->ResourceRecords, mDNSNULL);
-
-    LogToFD(fd, "--------- LocalOnly, P2P Auth Records ---------");
-    LogLocalOnlyAuthRecordsToFD(fd, m);
-
-    LogToFD(fd, "--------- /etc/hosts ---------");
-    LogEtcHostsToFD(fd, m);
-
-    LogToFD(fd, "------ Duplicate Records -------");
-    LogAuthRecordsToFD(fd, now, m->DuplicateRecords, mDNSNULL);
-
-    LogToFD(fd, "----- Auth Records Proxied -----");
-    LogAuthRecordsToFD(fd, now, m->ResourceRecords, &ProxyA);
-
-    LogToFD(fd, "-- Duplicate Records Proxied ---");
-    LogAuthRecordsToFD(fd, now, m->DuplicateRecords, &ProxyD);
-
-    LogToFD(fd, "---------- Questions -----------");
-    if (!m->Questions) LogToFD(fd, "<None>");
-    else
-    {
-        CacheUsed = 0;
-        CacheActive = 0;
-        LogToFD(fd, "   Int  Next if     T NumAns "
-    #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                "VDNS                               "
-    #endif
-                "Qptr               DupOf              SU SQ "
-    #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                "DNSSEC "
-    #endif
-                "Type    Name");
-        for (q = m->Questions; q; q=q->next)
-        {
-            mDNSs32 i = q->ThisQInterval / mDNSPlatformOneSecond;
-            mDNSs32 n = (NextQSendTime(q) - now) / mDNSPlatformOneSecond;
-            char *ifname = InterfaceNameForID(m, q->InterfaceID);
-            CacheUsed++;
-            if (q->ThisQInterval) CacheActive++;
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-            const mDNSBool redacted = (q->logPrivacyLevel == dnssd_log_privacy_level_private);
-#endif
-
-            LogToFD(fd, "%6d%6d %-7s%s %6d "
-                #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                    "0x%08x%08x%08x%08x "
-                #endif
-                    "0x%p 0x%p %1d %2d  "
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                    "%-7s"
-                #endif
-                    "%-8s%##s%s",
-                      i, n,
-                      ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-",
-                      mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"),
-                      q->CurrentAnswers,
-                #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-                      q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0],
-                #endif
-                      q, q->DuplicateOf,
-                      q->SuppressUnusable, q->Suppressed,
-                #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-                      dns_question_is_dnssec_requestor(q) ? "YES" : "NO",
-                #endif
-                      DNSTypeName(q->qtype),
-                #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
-                      redacted ? PRIVATE_DOMAIN_NAME->c : q->qname.c,
-                #else
-                      q->qname.c,
-                #endif
-                      q->DuplicateOf ? " (dup)" : "");
-        }
-        LogToFD(fd, "%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
-    }
-
-    LogToFD(fd, "----- LocalOnly, P2P Questions -----");
-    if (!m->LocalOnlyQuestions) LogToFD(fd, "<None>");
-    else for (q = m->LocalOnlyQuestions; q; q=q->next)
-        LogToFD(fd, "                 %3s   %5d  %-6s%##s%s",
-                  q->InterfaceID == mDNSInterface_LocalOnly ? "LO ": q->InterfaceID == mDNSInterface_BLE ? "BLE": "P2P",
-                  q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
-
-    LogToFD(fd, "---- Active UDS Client Requests ----");
-    if (!all_requests) LogToFD(fd, "<None>");
-    else
-    {
-        request_state *req, *r;
-        for (req = all_requests; req; req=req->next)
-        {
-            if (req->primary)   // If this is a subbordinate operation, check that the parent is in the list
-            {
-                for (r = all_requests; r && r != req; r=r->next) if (r == req->primary) goto foundparent;
-                LogToFD(fd, "%3d: Orhpan operation %p; parent %p not found in request list", req->sd);
-            }
-            // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
-            LogClientInfoToFD(fd, req);
-        foundparent:;
-        }
-    }
-
-    LogToFD(fd, "-------- NAT Traversals --------");
-    LogToFD(fd, "ExtAddress %.4a Retry %d Interval %d",
-              &m->ExtAddress,
-              m->retryGetAddr ? (m->retryGetAddr - now) / mDNSPlatformOneSecond : 0,
-              m->retryIntervalGetAddr / mDNSPlatformOneSecond);
-    if (m->NATTraversals)
-    {
-        const NATTraversalInfo *nat;
-        for (nat = m->NATTraversals; nat; nat=nat->next)
-        {
-            LogToFD(fd, "%p %s Int %5d %s Err %d Retry %5d Interval %5d Expire %5d Req %.4a:%d Ext %.4a:%d",
-                      nat,
-                      nat->Protocol ? (nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP") : "ADD",
-                      mDNSVal16(nat->IntPort),
-                      (nat->lastSuccessfulProtocol == NATTProtocolNone    ? "None    " :
-                       nat->lastSuccessfulProtocol == NATTProtocolNATPMP  ? "NAT-PMP " :
-                       nat->lastSuccessfulProtocol == NATTProtocolUPNPIGD ? "UPnP/IGD" :
-                       nat->lastSuccessfulProtocol == NATTProtocolPCP     ? "PCP     " :
-                       /* else */                                           "Unknown " ),
-                      nat->Result,
-                      nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
-                      nat->retryInterval / mDNSPlatformOneSecond,
-                      nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
-                      &nat->NewAddress, mDNSVal16(nat->RequestedPort),
-                      &nat->ExternalAddress, mDNSVal16(nat->ExternalPort));
-        }
-    }
-
-    LogToFD(fd, "--------- AuthInfoList ---------");
-    if (!m->AuthInfoList) LogToFD(fd, "<None>");
-    else
-    {
-        const DomainAuthInfo *a;
-        for (a = m->AuthInfoList; a; a = a->next)
-        {
-            LogToFD(fd, "%##s %##s %##s %d %d",
-                      a->domain.c, a->keyname.c,
-                      a->hostname.c, (a->port.b[0] << 8 | a->port.b[1]),
-                      (a->deltime ? (a->deltime - now) : 0));
-        }
-    }
-
-    LogToFD(fd, "---------- Misc State ----------");
-
-    LogToFD(fd, "PrimaryMAC:   %.6a", &m->PrimaryMAC);
-
-    LogToFD(fd, "m->SleepState %d (%s) seq %d",
-              m->SleepState,
-              m->SleepState == SleepState_Awake        ? "Awake"        :
-              m->SleepState == SleepState_Transferring ? "Transferring" :
-              m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?",
-              m->SleepSeqNum);
-
-    if (!m->SPSSocket) LogToFD(fd, "Not offering Sleep Proxy Service");
-#ifndef SPC_DISABLED
-    else LogToFD(fd, "Offering Sleep Proxy Service: %#s", m->SPSRecords.RR_SRV.resrec.name->c);
-#endif
-    if (m->ProxyRecords == ProxyA + ProxyD) LogToFD(fd, "ProxyRecords: %d + %d = %d", ProxyA, ProxyD, ProxyA + ProxyD);
-    else LogToFD(fd, "ProxyRecords: MISMATCH %d + %d = %d ≠ %d", ProxyA, ProxyD, ProxyA + ProxyD, m->ProxyRecords);
-
-    LogToFD(fd, "------ Auto Browse Domains -----");
-    if (!AutoBrowseDomains) LogToFD(fd, "<None>");
-    else for (d=AutoBrowseDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
-
-    LogToFD(fd, "--- Auto Registration Domains --");
-    if (!AutoRegistrationDomains) LogToFD(fd, "<None>");
-    else for (d=AutoRegistrationDomains; d; d=d->next) LogToFD(fd, "%##s", d->name.c);
-
-    LogToFD(fd, "--- Search Domains --");
-    if (!SearchList) LogToFD(fd, "<None>");
-    else
-    {
-        for (s=SearchList; s; s=s->next)
-        {
-            char *ifname = InterfaceNameForID(m, s->InterfaceID);
-            LogToFD(fd, "%##s %s", s->domain.c, ifname ? ifname : "");
-        }
-    }
-    LogMDNSStatisticsToFD(fd, m);
-
-    LogToFD(fd, "---- Task Scheduling Timers ----");
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    LogToFD(fd, "BonjourEnabled %d", m->BonjourEnabled);
-#endif
-
-    if (!m->NewQuestions)
-        LogToFD(fd, "NewQuestion <NONE>");
-    else
-        LogToFD(fd, "NewQuestion DelayAnswering %d %d %##s (%s)",
-                  m->NewQuestions->DelayAnswering, m->NewQuestions->DelayAnswering-now,
-                  m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
-
-    if (!m->NewLocalOnlyQuestions)
-        LogToFD(fd, "NewLocalOnlyQuestions <NONE>");
-    else
-        LogToFD(fd, "NewLocalOnlyQuestions %##s (%s)",
-                  m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
-
-    if (!m->NewLocalRecords)
-        LogToFD(fd, "NewLocalRecords <NONE>");
-    else
-        LogToFD(fd, "NewLocalRecords %02X %s", m->NewLocalRecords->resrec.RecordType, ARDisplayString(m, m->NewLocalRecords));
-
-    LogToFD(fd, "SPSProxyListChanged%s", m->SPSProxyListChanged ? "" : " <NONE>");
-    LogToFD(fd, "LocalRemoveEvents%s",   m->LocalRemoveEvents   ? "" : " <NONE>");
-    LogToFD(fd, "m->WABBrowseQueriesCount %d", m->WABBrowseQueriesCount);
-    LogToFD(fd, "m->WABLBrowseQueriesCount %d", m->WABLBrowseQueriesCount);
-    LogToFD(fd, "m->WABRegQueriesCount %d", m->WABRegQueriesCount);
-    LogToFD(fd, "m->AutoTargetServices %u", m->AutoTargetServices);
-#if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
-    LogToFD(fd, "m->AutoTargetAWDLIncludedCount %u", m->AutoTargetAWDLIncludedCount);
-    LogToFD(fd, "m->AutoTargetAWDLOnlyCount     %u", m->AutoTargetAWDLOnlyCount);
-#endif
-
-    LogToFD(fd, "                         ABS (hex)  ABS (dec)  REL (hex)  REL (dec)");
-    LogToFD(fd, "m->timenow               %08X %11d", now, now);
-    LogToFD(fd, "m->timenow_adjust        %08X %11d", m->timenow_adjust, m->timenow_adjust);
-    LogTimerToFD(fd, "m->NextScheduledEvent   ", m->NextScheduledEvent);
-
-#ifndef UNICAST_DISABLED
-    LogTimerToFD(fd, "m->NextuDNSEvent        ", m->NextuDNSEvent);
-    LogTimerToFD(fd, "m->NextSRVUpdate        ", m->NextSRVUpdate);
-    LogTimerToFD(fd, "m->NextScheduledNATOp   ", m->NextScheduledNATOp);
-    LogTimerToFD(fd, "m->retryGetAddr         ", m->retryGetAddr);
-#endif
-
-    LogTimerToFD(fd, "m->NextCacheCheck       ", m->NextCacheCheck);
-    LogTimerToFD(fd, "m->NextScheduledSPS     ", m->NextScheduledSPS);
-    LogTimerToFD(fd, "m->NextScheduledKA      ", m->NextScheduledKA);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
-    LogTimerToFD(fd, "m->NextBonjourDisableTime ", m->NextBonjourDisableTime);
-#endif
-
-    LogTimerToFD(fd, "m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
-    LogTimerToFD(fd, "m->DelaySleep           ", m->DelaySleep);
-
-    LogTimerToFD(fd, "m->NextScheduledQuery   ", m->NextScheduledQuery);
-    LogTimerToFD(fd, "m->NextScheduledProbe   ", m->NextScheduledProbe);
-    LogTimerToFD(fd, "m->NextScheduledResponse", m->NextScheduledResponse);
-
-    LogTimerToFD(fd, "m->SuppressQueries      ", m->SuppressQueries);
-    LogTimerToFD(fd, "m->SuppressResponses    ", m->SuppressResponses);
-    LogTimerToFD(fd, "m->SuppressProbes       ", m->SuppressProbes);
-    LogTimerToFD(fd, "m->ProbeFailTime        ", m->ProbeFailTime);
-    LogTimerToFD(fd, "m->DelaySleep           ", m->DelaySleep);
-    LogTimerToFD(fd, "m->SleepLimit           ", m->SleepLimit);
-    LogTimerToFD(fd, "m->NextScheduledStopTime ", m->NextScheduledStopTime);
-}
-
-#if MDNS_MALLOC_DEBUGGING
-mDNSlocal void udsserver_validatelists(void *context)
-{
-    const request_state *req, *p;
-	(void)context; // unused
-    for (req = all_requests; req; req=req->next)
-    {
-        if (req->next == (request_state *)~0 || (req->sd < 0 && req->sd != -2))
-            LogMemCorruption("UDS request list: %p is garbage (%d)", req, req->sd);
-
-        if (req->primary == req)
-            LogMemCorruption("UDS request list: req->primary should not point to self %p/%d", req, req->sd);
-
-        if (req->primary && req->replies)
-            LogMemCorruption("UDS request list: Subordinate request %p/%d/%p should not have replies (%p)",
-                             req, req->sd, req->primary && req->replies);
-
-        p = req->primary;
-        if ((long)p & 3)
-            LogMemCorruption("UDS request list: req %p primary %p is misaligned (%d)", req, p, req->sd);
-        else if (p && (p->next == (request_state *)~0 || (p->sd < 0 && p->sd != -2)))
-            LogMemCorruption("UDS request list: req %p primary %p is garbage (%d)", req, p, p->sd);
-
-        reply_state *rep;
-        for (rep = req->replies; rep; rep=rep->next)
-            if (rep->next == (reply_state *)~0)
-                LogMemCorruption("UDS req->replies: %p is garbage", rep);
-
-        if (req->terminate == connection_termination)
-        {
-            registered_record_entry *r;
-            for (r = req->u.reg_recs; r; r=r->next)
-                if (r->next == (registered_record_entry *)~0)
-                    LogMemCorruption("UDS req->u.reg_recs: %p is garbage", r);
-        }
-        else if (req->terminate == regservice_termination_callback)
-        {
-            service_instance *s;
-            for (s = req->u.servicereg.instances; s; s=s->next)
-                if (s->next == (service_instance *)~0)
-                    LogMemCorruption("UDS req->u.servicereg.instances: %p is garbage", s);
-        }
-        else if (req->terminate == browse_termination_callback)
-        {
-            browser_t *b;
-            for (b = req->u.browser.browsers; b; b=b->next)
-                if (b->next == (browser_t *)~0)
-                    LogMemCorruption("UDS req->u.browser.browsers: %p is garbage", b);
-        }
-    }
-
-    DNameListElem *d;
-    for (d = SCPrefBrowseDomains; d; d=d->next)
-        if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
-            LogMemCorruption("SCPrefBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
-
-    ARListElem *b;
-    for (b = LocalDomainEnumRecords; b; b=b->next)
-        if (b->next == (ARListElem *)~0 || b->ar.resrec.name->c[0] > 63)
-            LogMemCorruption("LocalDomainEnumRecords: %p is garbage (%d)", b, b->ar.resrec.name->c[0]);
-
-    for (d = AutoBrowseDomains; d; d=d->next)
-        if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
-            LogMemCorruption("AutoBrowseDomains: %p is garbage (%d)", d, d->name.c[0]);
-
-    for (d = AutoRegistrationDomains; d; d=d->next)
-        if (d->next == (DNameListElem *)~0 || d->name.c[0] > 63)
-            LogMemCorruption("AutoRegistrationDomains: %p is garbage (%d)", d, d->name.c[0]);
-}
-#endif // MDNS_MALLOC_DEBUGGING
-
-mDNSlocal transfer_state send_msg(request_state *const req)
-{
-    reply_state *const rep = req->replies;      // Send the first waiting reply
-    ssize_t nwritten;
-    const mDNSu32 len = rep->totallen - rep->nwritten;
-
-    ConvertHeaderBytes(rep->mhdr);
-    nwritten = send(req->sd, (char *)&rep->mhdr + rep->nwritten, len, 0);
-    ConvertHeaderBytes(rep->mhdr);
-
-    if (nwritten < 0)
-    {
-        if (dnssd_errno == dnssd_EINTR || dnssd_errno == dnssd_EWOULDBLOCK) nwritten = 0;
-        else
-        {
-#if !defined(PLATFORM_NO_EPIPE)
-            if (dnssd_errno == EPIPE)
-                return(req->ts = t_terminated);
-            else
-#endif
-            {
-                LogMsg("send_msg ERROR: failed to write %u of %d bytes to fd %d errno %d (%s)",
-                       len, rep->totallen, req->sd, dnssd_errno, dnssd_strerror(dnssd_errno));
-                return(t_error);
-            }
-        }
-    }
-    rep->nwritten += (mDNSu32)nwritten;
-    return (rep->nwritten == rep->totallen) ? t_complete : t_morecoming;
-}
-
-mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
-{
-    mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
-    request_state **req = &all_requests;
-
-    while (*req)
-    {
-        request_state *r = *req;
-
-        if (r->terminate == resolve_termination_callback)
-            if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0)
-            {
-                r->u.resolve.ReportTime = 0;
-                // if client received results and resolve still active
-                if (r->u.resolve.txt && r->u.resolve.srv)
-                    LogMsgNoIdent("Client application PID[%d](%s) has received results for DNSServiceResolve(%##s) yet remains active over two minutes.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c);
-            }
-
-        // Note: Only primary req's have reply lists, not subordinate req's.
-        while (r->replies)      // Send queued replies
-        {
-            transfer_state result;
-            if (r->replies->next)
-                r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
-            result = send_msg(r);   // Returns t_morecoming if buffer full because client is not reading
-            if (result == t_complete)
-            {
-                reply_state *fptr = r->replies;
-                r->replies = r->replies->next;
-                freeL("reply_state/udsserver_idle", fptr);
-                r->time_blocked = 0; // reset failure counter after successful send
-                r->unresponsiveness_reports = 0;
-                continue;
-            }
-            else if (result == t_terminated)
-            {
-                LogInfo("%3d: Could not write data to client PID[%d](%s) because connection is terminated by the client", r->sd, r->process_id, r->pid_name);
-                abort_request(r);
-            }
-            else if (result == t_error)
-            {
-                LogMsg("%3d: Could not write data to client PID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name);
-                LogClientInfo(r);
-                abort_request(r);
-            }
-            break;
-        }
-
-        if (r->replies)     // If we failed to send everything, check our time_blocked timer
-        {
-            if (nextevent - now > mDNSPlatformOneSecond)
-                nextevent = now + mDNSPlatformOneSecond;
-
-            LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT,
-               "[R%u] Could not send all replies. Will try again in %d ticks.", r->request_id, nextevent - now);
-            if (mDNSStorage.SleepState != SleepState_Awake)
-                r->time_blocked = 0;
-            else if (!r->time_blocked)
-                r->time_blocked = NonZeroTime(now);
-            else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1))
-            {
-                int num = 0;
-                struct reply_state *x = r->replies;
-                while (x)
-                {
-                    num++;
-                    x=x->next;
-                }
-                LogMsg("%3d: Could not write data to client PID[%d](%s) after %ld seconds, %d repl%s waiting",
-                       r->sd, r->process_id, r->pid_name, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies");
-                if (++r->unresponsiveness_reports >= 60)
-                {
-                    LogMsg("%3d: Client PID[%d](%s) unresponsive; aborting connection", r->sd, r->process_id, r->pid_name);
-                    LogClientInfo(r);
-                    abort_request(r);
-                }
-            }
-        }
-
-        if (!dnssd_SocketValid(r->sd)) // If this request is finished, unlink it from the list and free the memory
-        {
-            // Since we're already doing a list traversal, we unlink the request directly instead of using AbortUnlinkAndFree()
-            *req = r->next;
-            freeL("request_state/udsserver_idle", r);
-        }
-        else
-            req = &r->next;
-    }
-    return nextevent;
-}
-
-struct CompileTimeAssertionChecks_uds_daemon
-{
-    // 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_request_state          [(sizeof(request_state)           <= 3888) ? 1 : -1];
-    char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <=   60) ? 1 : -1];
-    char sizecheck_service_instance       [(sizeof(service_instance)        <= 6552) ? 1 : -1];
-    char sizecheck_browser_t              [(sizeof(browser_t)               <= 1480) ? 1 : -1];
-    char sizecheck_reply_hdr              [(sizeof(reply_hdr)               <=   12) ? 1 : -1];
-    char sizecheck_reply_state            [(sizeof(reply_state)             <=   64) ? 1 : -1];
-};
-
-#ifdef UNIT_TEST
-#include "../unittests/uds_daemon_ut.c"
-#endif  //  UNIT_TEST
diff --git a/mDNSShared/uds_daemon.h b/mDNSShared/uds_daemon.h
deleted file mode 100644
index b3df614..0000000
--- a/mDNSShared/uds_daemon.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef UDS_DAEMON_H
-#define UDS_DAEMON_H
-
-#include "mDNSEmbeddedAPI.h"
-#include "dnssd_ipc.h"
-#include "ClientRequests.h"
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-#include "mdns_trust.h"
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-#include "signed_result.h"
-#endif
-
-/* Client request: */
-
-// ***************************************************************************
-// MARK: - Types and Data Structures
-
-typedef enum
-{
-	t_uninitialized,
-	t_morecoming,
-	t_complete,
-	t_error,
-	t_terminated
-} transfer_state;
-
-typedef struct request_state request_state;
-
-typedef void (*req_termination_fn)(request_state *request);
-
-typedef struct registered_record_entry
-{
-	struct registered_record_entry *next;
-	mDNSu32 key;
-	client_context_t regrec_client_context;
-	request_state *request;
-	mDNSBool external_advertise;
-	mDNSInterfaceID origInterfaceID;
-	AuthRecord *rr;             // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?)
-} registered_record_entry;
-
-// A single registered service: ServiceRecordSet + bookkeeping
-// Note that we duplicate some fields from parent service_info object
-// to facilitate cleanup, when instances and parent may be deallocated at different times.
-typedef struct service_instance
-{
-	struct service_instance *next;
-	request_state *request;
-	AuthRecord *subtypes;
-	mDNSBool renameonmemfree;       // Set on config change when we deregister original name
-	mDNSBool clientnotified;        // Has client been notified of successful registration yet?
-	mDNSBool default_local;         // is this the "local." from an empty-string registration?
-	mDNSBool external_advertise;    // is this is being advertised externally?
-	domainname domain;
-	ServiceRecordSet srs;           // note -- variable-sized object -- must be last field in struct
-} service_instance;
-
-// for multi-domain default browsing
-typedef struct browser_t
-{
-	struct browser_t *next;
-	domainname domain;
-	DNSQuestion q;
-} browser_t;
-
-#ifdef _WIN32
-# ifdef __MINGW32__
-typedef int pid_t;
-typedef int socklen_t;
-# else
-typedef unsigned int pid_t;
-typedef int socklen_t;
-# endif // __MINGW32__
-#endif //_WIN32
-
-#if (!defined(MAXCOMLEN))
-#define MAXCOMLEN 16
-#endif
-
-struct request_state
-{
-    request_state *next;            // For a shared connection, the next element in the list of subordinate
-                                    // requests on that connection. Otherwise null.
-    request_state *primary;         // For a subordinate request, the request that represents the shared
-                                    // connection to which this request is subordinate (must have been created
-                                    // by DNSServiceCreateConnection().
-	dnssd_sock_t sd;
-	pid_t process_id;               // Client's PID value
-	char  pid_name[MAXCOMLEN];      // Client's process name
-	mDNSu8 uuid[UUID_SIZE];
-	mDNSBool validUUID;
-	dnssd_sock_t errsd;
-#if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
-    audit_token_t audit_token;
-#endif
-	mDNSu32 uid;
-    mDNSu32 request_id;
-	void * platform_data;
-#if MDNSRESPONDER_SUPPORTS(APPLE, TRUST_ENFORCEMENT)
-    mdns_trust_t trust;
-#endif
-#if MDNSRESPONDER_SUPPORTS(APPLE, SIGNED_RESULTS)
-    mDNSBool sign_result;
-    mdns_signed_result_t signed_obj;
-#endif
-	// Note: On a shared connection these fields in the primary structure, including hdr, are re-used
-	// for each new request. This is because, until we've read the ipc_msg_hdr to find out what the
-	// operation is, we don't know if we're going to need to allocate a new request_state or not.
-	transfer_state ts;
-	mDNSu32 hdr_bytes;              // bytes of header already read
-	ipc_msg_hdr hdr;
-	size_t data_bytes;              // bytes of message data already read
-	uint8_t       *msgbuf;          // pointer to data storage to pass to free()
-	const uint8_t *msgptr;          // pointer to data to be read from (may be modified)
-	const uint8_t *msgend;          // pointer to byte after last byte of message
-
-	// reply, termination, error, and client context info
-	int no_reply;                   // don't send asynchronous replies to client
-	mDNSs32 time_blocked;           // record time of a blocked client
-	int unresponsiveness_reports;
-	struct reply_state *replies;    // corresponding (active) reply list
-	req_termination_fn terminate;
-	DNSServiceFlags flags;
-	mDNSu32 interfaceIndex;
-#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
-    mdns_dns_service_id_t custom_service_id;
-#endif
-	union
-	{
-		registered_record_entry *reg_recs;  // list of registrations for a connection-oriented request
-		struct
-		{
-			mDNSInterfaceID interface_id;
-			mDNSBool default_domain;
-			mDNSBool ForceMCast;
-			domainname regtype;
-			browser_t *browsers;
-		} browser;
-		struct
-		{
-			mDNSInterfaceID InterfaceID;
-			mDNSu16 txtlen;
-			void *txtdata;
-			mDNSIPPort port;
-			domainlabel name;
-			char type_as_string[MAX_ESCAPED_DOMAIN_NAME];
-			domainname type;
-			mDNSBool default_domain;
-			domainname host;
-			mDNSBool autoname;              // Set if this name is tied to the Computer Name
-			mDNSBool autorename;            // Set if this client wants us to automatically rename on conflict
-			mDNSBool allowremotequery;      // Respond to unicast queries from outside the local link?
-			mDNSu32 num_subtypes;
-			service_instance *instances;
-		} servicereg;
-		struct
-		{
-			mDNSIPPort ReqExt;              // External port we originally requested, for logging purposes
-			NATTraversalInfo NATinfo;
-		} pm;
-		struct
-		{
-			DNSServiceFlags flags;
-			DNSQuestion q_all;
-			DNSQuestion q_default;
-			DNSQuestion q_autoall;
-		} enumeration;
-		struct
-		{
-			DNSQuestion qtxt;
-			DNSQuestion qsrv;
-			const ResourceRecord *txt;
-			const ResourceRecord *srv;
-			mDNSs32 ReportTime;
-			mDNSBool external_advertise;
-		} resolve;
-        GetAddrInfoClientRequest addrinfo;
-        QueryRecordClientRequest queryrecord;
-	} u;
-};
-
-// struct physically sits between ipc message header and call-specific fields in the message buffer
-typedef struct
-{
-	DNSServiceFlags flags;          // Note: This field is in NETWORK byte order
-	mDNSu32 ifi;                    // Note: This field is in NETWORK byte order
-	DNSServiceErrorType error;      // Note: This field is in NETWORK byte order
-} reply_hdr;
-
-typedef struct reply_state
-{
-	struct reply_state *next;       // If there are multiple unsent replies
-	mDNSu32 totallen;
-	mDNSu32 nwritten;
-	ipc_msg_hdr mhdr[1];
-	reply_hdr rhdr[1];
-} reply_state;
-
-/* Client interface: */
-
-#define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port)
-
-#define LogTimerToFD(FILE_DESCRIPTOR, MSG, T) LogToFD((FILE_DESCRIPTOR), MSG " %08X %11d  %08X %11d", (T), (T), (T)-now, (T)-now)
-
-extern int udsserver_init(dnssd_sock_t skts[], size_t count);
-extern mDNSs32 udsserver_idle(mDNSs32 nextevent);
-extern void udsserver_info_dump_to_fd(int fd);
-extern void udsserver_handle_configchange(mDNS *const m);
-extern int udsserver_exit(void);    // should be called prior to app exit
-extern void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog);
-#define LogMcastQ       (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastQuestion
-#define LogMcastS       (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastService
-#define LogMcast        (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsg
-#define LogMcastNoIdent (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsgNoIdent
-
-/* Routines that uds_daemon expects to link against: */
-
-typedef void (*udsEventCallback)(int fd, void *context);
-extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data);
-extern ssize_t udsSupportReadFD(dnssd_sock_t fd, char* buf, mDNSu32 len, int flags, void *platform_data);
-extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well
-
-extern void RecordUpdatedNiceLabel(mDNSs32 delay);
-
-// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X
-
-extern mDNS mDNSStorage;
-extern DNameListElem *AutoRegistrationDomains;
-extern DNameListElem *AutoBrowseDomains;
-
-extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port);
-extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result);
-extern int CountPeerRegistrations(ServiceRecordSet *const srs);
-
-extern const char mDNSResponderVersionString_SCCS[];
-#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5)
-
-#if defined(DEBUG) && DEBUG
-extern void SetDebugBoundPath(void);
-extern int IsDebugSocketInUse(void);
-#endif
-
-#endif /* UDS_DAEMON_H */
diff --git a/mDNSShared/utilities/bsd_queue.h b/mDNSShared/utilities/bsd_queue.h
deleted file mode 100644
index b141139..0000000
--- a/mDNSShared/utilities/bsd_queue.h
+++ /dev/null
@@ -1,913 +0,0 @@
-/*
- * The following code is directly copied from <sys/queue.h>.
- * For the usage of <sys/queue.h>, see https://linux.die.net/man/3/queue.
- * =======================================================================================
- *
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_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. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * 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_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)queue.h	8.5 (Berkeley) 8/20/94
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-#ifndef __improbable
-#define __improbable(x) (x)             /* noop in userspace */
-#endif /* __improbable */
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * singly-linked tail queues, lists, tail queues, and circular queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- * Note that circle queues are deprecated, because, as the removal log
- * in FreeBSD states, "CIRCLEQs are a disgrace to everything Knuth taught
- * us in Volume 1 Chapter 2. [...] Use TAILQ instead, it provides the same
- * functionality." Code using them will continue to compile, but they
- * are no longer documented on the man page.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- *				SLIST	LIST	STAILQ	TAILQ	CIRCLEQ
- * _HEAD			+	+	+	+	+
- * _HEAD_INITIALIZER		+	+	+	+	-
- * _ENTRY			+	+	+	+	+
- * _INIT			+	+	+	+	+
- * _EMPTY			+	+	+	+	+
- * _FIRST			+	+	+	+	+
- * _NEXT			+	+	+	+	+
- * _PREV			-	-	-	+	+
- * _LAST			-	-	+	+	+
- * _FOREACH			+	+	+	+	+
- * _FOREACH_SAFE		+	+	+	+	-
- * _FOREACH_REVERSE		-	-	-	+	-
- * _FOREACH_REVERSE_SAFE	-	-	-	+	-
- * _INSERT_HEAD			+	+	+	+	+
- * _INSERT_BEFORE		-	+	-	+	+
- * _INSERT_AFTER		+	+	+	+	+
- * _INSERT_TAIL			-	-	+	+	+
- * _CONCAT			-	-	+	+	-
- * _REMOVE_AFTER		+	-	+	-	-
- * _REMOVE_HEAD			+	-	+	-	-
- * _REMOVE_HEAD_UNTIL		-	-	+	-	-
- * _REMOVE			+	+	+	+	+
- * _SWAP			-	+	+	+	-
- *
- */
-#ifdef QUEUE_MACRO_DEBUG
-/* Store the last 2 places the queue element or head was altered */
-struct qm_trace {
-	char * lastfile;
-	int lastline;
-	char * prevfile;
-	int prevline;
-};
-
-#define TRACEBUF        struct qm_trace trace;
-#define TRASHIT(x)      do {(x) = (void *)-1;} while (0)
-
-#define QMD_TRACE_HEAD(head) do {                                       \
-	(head)->trace.prevline = (head)->trace.lastline;                \
-	(head)->trace.prevfile = (head)->trace.lastfile;                \
-	(head)->trace.lastline = __LINE__;                              \
-	(head)->trace.lastfile = __FILE__;                              \
-} while (0)
-
-#define QMD_TRACE_ELEM(elem) do {                                       \
-	(elem)->trace.prevline = (elem)->trace.lastline;                \
-	(elem)->trace.prevfile = (elem)->trace.lastfile;                \
-	(elem)->trace.lastline = __LINE__;                              \
-	(elem)->trace.lastfile = __FILE__;                              \
-} while (0)
-
-#else
-#define QMD_TRACE_ELEM(elem)
-#define QMD_TRACE_HEAD(head)
-#define TRACEBUF
-#define TRASHIT(x)
-#endif  /* QUEUE_MACRO_DEBUG */
-
-/*
- * Horrible macros to enable use of code that was meant to be C-specific
- *   (and which push struct onto type) in C++; without these, C++ code
- *   that uses these macros in the context of a class will blow up
- *   due to "struct" being preprended to "type" by the macros, causing
- *   inconsistent use of tags.
- *
- * This approach is necessary because these are macros; we have to use
- *   these on a per-macro basis (because the queues are implemented as
- *   macros, disabling this warning in the scope of the header file is
- *   insufficient), whuch means we can't use #pragma, and have to use
- *   _Pragma.  We only need to use these for the queue macros that
- *   prepend "struct" to "type" and will cause C++ to blow up.
- */
-#if defined(__clang__) && defined(__cplusplus)
-#define __MISMATCH_TAGS_PUSH                                            \
-	_Pragma("clang diagnostic push")                                \
-	_Pragma("clang diagnostic ignored \"-Wmismatched-tags\"")
-#define __MISMATCH_TAGS_POP                                             \
-	_Pragma("clang diagnostic pop")
-#else
-#define __MISMATCH_TAGS_PUSH
-#define __MISMATCH_TAGS_POP
-#endif
-
-/*!
- * Ensures that these macros can safely be used in structs when compiling with
- * clang. The macros do not allow for nullability attributes to be specified due
- * to how they are expanded. For example:
- *
- *     SLIST_HEAD(, foo _Nullable) bar;
- *
- * expands to
- *
- *     struct {
- *         struct foo _Nullable *slh_first;
- *     }
- *
- * which is not valid because the nullability specifier has to apply to the
- * pointer. So just ignore nullability completeness in all the places where this
- * is an issue.
- */
-#if defined(__clang__)
-#define __NULLABILITY_COMPLETENESS_PUSH \
-	_Pragma("clang diagnostic push") \
-	_Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
-#define __NULLABILITY_COMPLETENESS_POP \
-	_Pragma("clang diagnostic pop")
-#else
-#define __NULLABILITY_COMPLETENESS_PUSH
-#define __NULLABILITY_COMPLETENESS_POP
-#endif
-
-/*
- * Singly-linked List declarations.
- */
-#define SLIST_HEAD(name, type)                                          \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct name {                                                           \
-	struct type *slh_first; /* first element */                     \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define SLIST_HEAD_INITIALIZER(head)                                    \
-	{ NULL }
-
-#define SLIST_ENTRY(type)                                               \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct {                                                                \
-	struct type *sle_next;  /* next element */                      \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_EMPTY(head)       ((head)->slh_first == NULL)
-
-#define SLIST_FIRST(head)       ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field)                                 \
-	for ((var) = SLIST_FIRST((head));                               \
-	    (var);                                                      \
-	    (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_SAFE(var, head, field, tvar)                      \
-	for ((var) = SLIST_FIRST((head));                               \
-	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);            \
-	    (var) = (tvar))
-
-#define SLIST_FOREACH_PREVPTR(var, varp, head, field)                   \
-	for ((varp) = &SLIST_FIRST((head));                             \
-	    ((var) = *(varp)) != NULL;                                  \
-	    (varp) = &SLIST_NEXT((var), field))
-
-#define SLIST_INIT(head) do {                                           \
-	SLIST_FIRST((head)) = NULL;                                     \
-} while (0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do {                   \
-	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);       \
-	SLIST_NEXT((slistelm), field) = (elm);                          \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do {                        \
-	SLIST_NEXT((elm), field) = SLIST_FIRST((head));                 \
-	SLIST_FIRST((head)) = (elm);                                    \
-} while (0)
-
-#define SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
-
-#define SLIST_REMOVE(head, elm, type, field)                            \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-do {                                                                    \
-	if (SLIST_FIRST((head)) == (elm)) {                             \
-	        SLIST_REMOVE_HEAD((head), field);                       \
-	}                                                               \
-	else {                                                          \
-	        struct type *curelm = SLIST_FIRST((head));              \
-	        while (SLIST_NEXT(curelm, field) != (elm))              \
-	                curelm = SLIST_NEXT(curelm, field);             \
-	        SLIST_REMOVE_AFTER(curelm, field);                      \
-	}                                                               \
-	TRASHIT((elm)->field.sle_next);                                 \
-} while (0)                                                             \
-__NULLABILITY_COMPLETENESS_POP                                      \
-__MISMATCH_TAGS_POP
-
-#define SLIST_REMOVE_AFTER(elm, field) do {                             \
-	SLIST_NEXT(elm, field) =                                        \
-	    SLIST_NEXT(SLIST_NEXT(elm, field), field);                  \
-} while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do {                             \
-	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);   \
-} while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type)                                         \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct name {                                                           \
-	struct type *stqh_first;/* first element */                     \
-	struct type **stqh_last;/* addr of last next element */         \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define STAILQ_HEAD_INITIALIZER(head)                                   \
-	{ NULL, &(head).stqh_first }
-
-#define STAILQ_ENTRY(type)                                              \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct {                                                                \
-	struct type *stqe_next; /* next element */                      \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                         \
-__MISMATCH_TAGS_POP
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_CONCAT(head1, head2) do {                                \
-	if (!STAILQ_EMPTY((head2))) {                                   \
-	        *(head1)->stqh_last = (head2)->stqh_first;              \
-	        (head1)->stqh_last = (head2)->stqh_last;                \
-	        STAILQ_INIT((head2));                                   \
-	}                                                               \
-} while (0)
-
-#define STAILQ_EMPTY(head)      ((head)->stqh_first == NULL)
-
-#define STAILQ_FIRST(head)      ((head)->stqh_first)
-
-#define STAILQ_FOREACH(var, head, field)                                \
-	for((var) = STAILQ_FIRST((head));                               \
-	   (var);                                                       \
-	   (var) = STAILQ_NEXT((var), field))
-
-
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar)                     \
-	for ((var) = STAILQ_FIRST((head));                              \
-	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);           \
-	    (var) = (tvar))
-
-#define STAILQ_INIT(head) do {                                          \
-	STAILQ_FIRST((head)) = NULL;                                    \
-	(head)->stqh_last = &STAILQ_FIRST((head));                      \
-} while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {               \
-	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
-	        (head)->stqh_last = &STAILQ_NEXT((elm), field);         \
-	STAILQ_NEXT((tqelm), field) = (elm);                            \
-} while (0)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do {                       \
-	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
-	        (head)->stqh_last = &STAILQ_NEXT((elm), field);         \
-	STAILQ_FIRST((head)) = (elm);                                   \
-} while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do {                       \
-	STAILQ_NEXT((elm), field) = NULL;                               \
-	*(head)->stqh_last = (elm);                                     \
-	(head)->stqh_last = &STAILQ_NEXT((elm), field);                 \
-} while (0)
-
-#define STAILQ_LAST(head, type, field)                                  \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-	(STAILQ_EMPTY((head)) ?                                         \
-	        NULL :                                                  \
-	        ((struct type *)(void *)                                \
-	        ((char *)((head)->stqh_last) - __offsetof(struct type, field))))\
-__NULLABILITY_COMPLETENESS_POP                                         \
-__MISMATCH_TAGS_POP
-
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define STAILQ_REMOVE(head, elm, type, field)                           \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-do {                                                                    \
-	if (STAILQ_FIRST((head)) == (elm)) {                            \
-	        STAILQ_REMOVE_HEAD((head), field);                      \
-	}                                                               \
-	else {                                                          \
-	        struct type *curelm = STAILQ_FIRST((head));             \
-	        while (STAILQ_NEXT(curelm, field) != (elm))             \
-	                curelm = STAILQ_NEXT(curelm, field);            \
-	        STAILQ_REMOVE_AFTER(head, curelm, field);               \
-	}                                                               \
-	TRASHIT((elm)->field.stqe_next);                                \
-} while (0)                                                             \
-__NULLABILITY_COMPLETENESS_POP                                      \
-__MISMATCH_TAGS_POP
-
-#define STAILQ_REMOVE_HEAD(head, field) do {                            \
-	if ((STAILQ_FIRST((head)) =                                     \
-	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)         \
-	        (head)->stqh_last = &STAILQ_FIRST((head));              \
-} while (0)
-
-#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {                 \
-       if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
-	       (head)->stqh_last = &STAILQ_FIRST((head));              \
-} while (0)
-
-#define STAILQ_REMOVE_AFTER(head, elm, field) do {                      \
-	if ((STAILQ_NEXT(elm, field) =                                  \
-	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)      \
-	        (head)->stqh_last = &STAILQ_NEXT((elm), field);         \
-} while (0)
-
-#define STAILQ_SWAP(head1, head2, type)                                 \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-do {                                                                    \
-	struct type *swap_first = STAILQ_FIRST(head1);                  \
-	struct type **swap_last = (head1)->stqh_last;                   \
-	STAILQ_FIRST(head1) = STAILQ_FIRST(head2);                      \
-	(head1)->stqh_last = (head2)->stqh_last;                        \
-	STAILQ_FIRST(head2) = swap_first;                               \
-	(head2)->stqh_last = swap_last;                                 \
-	if (STAILQ_EMPTY(head1))                                        \
-	        (head1)->stqh_last = &STAILQ_FIRST(head1);              \
-	if (STAILQ_EMPTY(head2))                                        \
-	        (head2)->stqh_last = &STAILQ_FIRST(head2);              \
-} while (0)                                                             \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type)                                           \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct name {                                                           \
-	struct type *lh_first;  /* first element */                     \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define LIST_HEAD_INITIALIZER(head)                                     \
-	{ NULL }
-
-#define LIST_ENTRY(type)                                                \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct {                                                                \
-	struct type *le_next;   /* next element */                      \
-	struct type **le_prev;  /* address of previous next element */  \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-/*
- * List functions.
- */
-
-#define LIST_CHECK_HEAD(head, field)
-#define LIST_CHECK_NEXT(elm, field)
-#define LIST_CHECK_PREV(elm, field)
-
-#define LIST_EMPTY(head)        ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head)        ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field)                                  \
-	for ((var) = LIST_FIRST((head));                                \
-	    (var);                                                      \
-	    (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_SAFE(var, head, field, tvar)                       \
-	for ((var) = LIST_FIRST((head));                                \
-	    (var) && ((tvar) = LIST_NEXT((var), field), 1);             \
-	    (var) = (tvar))
-
-#define LIST_INIT(head) do {                                            \
-	LIST_FIRST((head)) = NULL;                                      \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
-	LIST_CHECK_NEXT(listelm, field);                                \
-	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
-	        LIST_NEXT((listelm), field)->field.le_prev =            \
-	            &LIST_NEXT((elm), field);                           \
-	LIST_NEXT((listelm), field) = (elm);                            \
-	(elm)->field.le_prev = &LIST_NEXT((listelm), field);            \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
-	LIST_CHECK_PREV(listelm, field);                                \
-	(elm)->field.le_prev = (listelm)->field.le_prev;                \
-	LIST_NEXT((elm), field) = (listelm);                            \
-	*(listelm)->field.le_prev = (elm);                              \
-	(listelm)->field.le_prev = &LIST_NEXT((elm), field);            \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do {                         \
-	LIST_CHECK_HEAD((head), field);                         \
-	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)     \
-	        LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
-	LIST_FIRST((head)) = (elm);                                     \
-	(elm)->field.le_prev = &LIST_FIRST((head));                     \
-} while (0)
-
-#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do {                                    \
-	LIST_CHECK_NEXT(elm, field);                            \
-	LIST_CHECK_PREV(elm, field);                            \
-	if (LIST_NEXT((elm), field) != NULL)                            \
-	        LIST_NEXT((elm), field)->field.le_prev =                \
-	            (elm)->field.le_prev;                               \
-	*(elm)->field.le_prev = LIST_NEXT((elm), field);                \
-	TRASHIT((elm)->field.le_next);                                  \
-	TRASHIT((elm)->field.le_prev);                                  \
-} while (0)
-
-#define LIST_SWAP(head1, head2, type, field)                            \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-do {                                                                    \
-	struct type *swap_tmp = LIST_FIRST((head1));                    \
-	LIST_FIRST((head1)) = LIST_FIRST((head2));                      \
-	LIST_FIRST((head2)) = swap_tmp;                                 \
-	if ((swap_tmp = LIST_FIRST((head1))) != NULL)                   \
-	        swap_tmp->field.le_prev = &LIST_FIRST((head1));         \
-	if ((swap_tmp = LIST_FIRST((head2))) != NULL)                   \
-	        swap_tmp->field.le_prev = &LIST_FIRST((head2));         \
-} while (0)                                                             \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-/*
- * Tail queue declarations.
- */
-#define TAILQ_HEAD(name, type)                                          \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct name {                                                           \
-	struct type *tqh_first; /* first element */                     \
-	struct type **tqh_last; /* addr of last next element */         \
-	TRACEBUF                                                        \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define TAILQ_HEAD_INITIALIZER(head)                                    \
-	{ NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type)                                               \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct {                                                                \
-	struct type *tqe_next;  /* next element */                      \
-	struct type **tqe_prev; /* address of previous next element */  \
-	TRACEBUF                                                        \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_CHECK_HEAD(head, field)
-#define TAILQ_CHECK_NEXT(elm, field)
-#define TAILQ_CHECK_PREV(elm, field)
-
-#define TAILQ_CONCAT(head1, head2, field) do {                          \
-	if (!TAILQ_EMPTY(head2)) {                                      \
-	        *(head1)->tqh_last = (head2)->tqh_first;                \
-	        (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
-	        (head1)->tqh_last = (head2)->tqh_last;                  \
-	        TAILQ_INIT((head2));                                    \
-	        QMD_TRACE_HEAD(head1);                                  \
-	        QMD_TRACE_HEAD(head2);                                  \
-	}                                                               \
-} while (0)
-
-#define TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
-
-#define TAILQ_FIRST(head)       ((head)->tqh_first)
-
-#define TAILQ_FOREACH(var, head, field)                                 \
-	for ((var) = TAILQ_FIRST((head));                               \
-	    (var);                                                      \
-	    (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar)                      \
-	for ((var) = TAILQ_FIRST((head));                               \
-	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);            \
-	    (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
-	for ((var) = TAILQ_LAST((head), headname);                      \
-	    (var);                                                      \
-	    (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)    \
-	for ((var) = TAILQ_LAST((head), headname);                      \
-	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);  \
-	    (var) = (tvar))
-
-
-#define TAILQ_INIT(head) do {                                           \
-	TAILQ_FIRST((head)) = NULL;                                     \
-	(head)->tqh_last = &TAILQ_FIRST((head));                        \
-	QMD_TRACE_HEAD(head);                                           \
-} while (0)
-
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
-	TAILQ_CHECK_NEXT(listelm, field);                               \
-	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
-	        TAILQ_NEXT((elm), field)->field.tqe_prev =              \
-	            &TAILQ_NEXT((elm), field);                          \
-	else {                                                          \
-	        (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
-	        QMD_TRACE_HEAD(head);                                   \
-	}                                                               \
-	TAILQ_NEXT((listelm), field) = (elm);                           \
-	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);          \
-	QMD_TRACE_ELEM(&(elm)->field);                                  \
-	QMD_TRACE_ELEM(&listelm->field);                                \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
-	TAILQ_CHECK_PREV(listelm, field);                               \
-	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
-	TAILQ_NEXT((elm), field) = (listelm);                           \
-	*(listelm)->field.tqe_prev = (elm);                             \
-	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);          \
-	QMD_TRACE_ELEM(&(elm)->field);                                  \
-	QMD_TRACE_ELEM(&listelm->field);                                \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
-	TAILQ_CHECK_HEAD(head, field);                                  \
-	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   \
-	        TAILQ_FIRST((head))->field.tqe_prev =                   \
-	            &TAILQ_NEXT((elm), field);                          \
-	else                                                            \
-	        (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
-	TAILQ_FIRST((head)) = (elm);                                    \
-	(elm)->field.tqe_prev = &TAILQ_FIRST((head));                   \
-	QMD_TRACE_HEAD(head);                                           \
-	QMD_TRACE_ELEM(&(elm)->field);                                  \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
-	TAILQ_NEXT((elm), field) = NULL;                                \
-	(elm)->field.tqe_prev = (head)->tqh_last;                       \
-	*(head)->tqh_last = (elm);                                      \
-	(head)->tqh_last = &TAILQ_NEXT((elm), field);                   \
-	QMD_TRACE_HEAD(head);                                           \
-	QMD_TRACE_ELEM(&(elm)->field);                                  \
-} while (0)
-
-#define TAILQ_LAST(head, headname)                                      \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-	(*(((struct headname *)((head)->tqh_last))->tqh_last))          \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field)                                \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))     \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define TAILQ_REMOVE(head, elm, field) do {                             \
-	TAILQ_CHECK_NEXT(elm, field);                                   \
-	TAILQ_CHECK_PREV(elm, field);                                   \
-	if ((TAILQ_NEXT((elm), field)) != NULL)                         \
-	        TAILQ_NEXT((elm), field)->field.tqe_prev =              \
-	            (elm)->field.tqe_prev;                              \
-	else {                                                          \
-	        (head)->tqh_last = (elm)->field.tqe_prev;               \
-	        QMD_TRACE_HEAD(head);                                   \
-	}                                                               \
-	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);              \
-	TRASHIT((elm)->field.tqe_next);                                 \
-	TRASHIT((elm)->field.tqe_prev);                                 \
-	QMD_TRACE_ELEM(&(elm)->field);                                  \
-} while (0)
-
-/*
- * Why did they switch to spaces for this one macro?
- */
-#define TAILQ_SWAP(head1, head2, type, field)                           \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-do {                                                                    \
-	struct type *swap_first = (head1)->tqh_first;                   \
-	struct type **swap_last = (head1)->tqh_last;                    \
-	(head1)->tqh_first = (head2)->tqh_first;                        \
-	(head1)->tqh_last = (head2)->tqh_last;                          \
-	(head2)->tqh_first = swap_first;                                \
-	(head2)->tqh_last = swap_last;                                  \
-	if ((swap_first = (head1)->tqh_first) != NULL)                  \
-	        swap_first->field.tqe_prev = &(head1)->tqh_first;       \
-	else                                                            \
-	        (head1)->tqh_last = &(head1)->tqh_first;                \
-	if ((swap_first = (head2)->tqh_first) != NULL)                  \
-	        swap_first->field.tqe_prev = &(head2)->tqh_first;       \
-	else                                                            \
-	        (head2)->tqh_last = &(head2)->tqh_first;                \
-} while (0)                                                             \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type)                                        \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct name {                                                           \
-	struct type *cqh_first;         /* first element */             \
-	struct type *cqh_last;          /* last element */              \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                          \
-__MISMATCH_TAGS_POP
-
-#define CIRCLEQ_ENTRY(type)                                             \
-__MISMATCH_TAGS_PUSH                                                    \
-__NULLABILITY_COMPLETENESS_PUSH                                         \
-struct {                                                                \
-	struct type *cqe_next;          /* next element */              \
-	struct type *cqe_prev;          /* previous element */          \
-}                                                                       \
-__NULLABILITY_COMPLETENESS_POP                                         \
-__MISMATCH_TAGS_POP
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_CHECK_HEAD(head, field)
-#define CIRCLEQ_CHECK_NEXT(head, elm, field)
-#define CIRCLEQ_CHECK_PREV(head, elm, field)
-
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-
-#define CIRCLEQ_FOREACH(var, head, field)                               \
-	for((var) = (head)->cqh_first;                                  \
-	    (var) != (void *)(head);                                    \
-	    (var) = (var)->field.cqe_next)
-
-#define CIRCLEQ_INIT(head) do {                                         \
-	(head)->cqh_first = (void *)(head);                             \
-	(head)->cqh_last = (void *)(head);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {            \
-	CIRCLEQ_CHECK_NEXT(head, listelm, field);                       \
-	(elm)->field.cqe_next = (listelm)->field.cqe_next;              \
-	(elm)->field.cqe_prev = (listelm);                              \
-	if ((listelm)->field.cqe_next == (void *)(head))                \
-	        (head)->cqh_last = (elm);                               \
-	else                                                            \
-	        (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
-	(listelm)->field.cqe_next = (elm);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {           \
-	CIRCLEQ_CHECK_PREV(head, listelm, field);                       \
-	(elm)->field.cqe_next = (listelm);                              \
-	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
-	if ((listelm)->field.cqe_prev == (void *)(head))                \
-	        (head)->cqh_first = (elm);                              \
-	else                                                            \
-	        (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
-	(listelm)->field.cqe_prev = (elm);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                      \
-	CIRCLEQ_CHECK_HEAD(head, field);                                \
-	(elm)->field.cqe_next = (head)->cqh_first;                      \
-	(elm)->field.cqe_prev = (void *)(head);                         \
-	if ((head)->cqh_last == (void *)(head))                         \
-	        (head)->cqh_last = (elm);                               \
-	else                                                            \
-	        (head)->cqh_first->field.cqe_prev = (elm);              \
-	(head)->cqh_first = (elm);                                      \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                      \
-	(elm)->field.cqe_next = (void *)(head);                         \
-	(elm)->field.cqe_prev = (head)->cqh_last;                       \
-	if ((head)->cqh_first == (void *)(head))                        \
-	        (head)->cqh_first = (elm);                              \
-	else                                                            \
-	        (head)->cqh_last->field.cqe_next = (elm);               \
-	(head)->cqh_last = (elm);                                       \
-} while (0)
-
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do {                           \
-	CIRCLEQ_CHECK_NEXT(head, elm, field);                           \
-	CIRCLEQ_CHECK_PREV(head, elm, field);                           \
-	if ((elm)->field.cqe_next == (void *)(head))                    \
-	        (head)->cqh_last = (elm)->field.cqe_prev;               \
-	else                                                            \
-	        (elm)->field.cqe_next->field.cqe_prev =                 \
-	            (elm)->field.cqe_prev;                              \
-	if ((elm)->field.cqe_prev == (void *)(head))                    \
-	        (head)->cqh_first = (elm)->field.cqe_next;              \
-	else                                                            \
-	        (elm)->field.cqe_prev->field.cqe_next =                 \
-	            (elm)->field.cqe_next;                              \
-} while (0)
-
-#ifdef _KERNEL
-
-#if NOTFB31
-
-/*
- * XXX insque() and remque() are an old way of handling certain queues.
- * They bogusly assumes that all queue heads look alike.
- */
-
-struct quehead {
-	struct quehead *qh_link;
-	struct quehead *qh_rlink;
-};
-
-#ifdef __GNUC__
-#define chkquenext(a)
-#define chkqueprev(a)
-
-static __inline void
-insque(void *a, void *b)
-{
-	struct quehead *element = (struct quehead *)a,
-	    *head = (struct quehead *)b;
-	chkquenext(head);
-
-	element->qh_link = head->qh_link;
-	element->qh_rlink = head;
-	head->qh_link = element;
-	element->qh_link->qh_rlink = element;
-}
-
-static __inline void
-remque(void *a)
-{
-	struct quehead *element = (struct quehead *)a;
-	chkquenext(element);
-	chkqueprev(element);
-
-	element->qh_link->qh_rlink = element->qh_rlink;
-	element->qh_rlink->qh_link = element->qh_link;
-	element->qh_rlink = 0;
-}
-
-#else /* !__GNUC__ */
-
-void    insque(void *a, void *b);
-void    remque(void *a);
-
-#endif /* __GNUC__ */
-
-#endif /* NOTFB31 */
-#endif /* _KERNEL */
-
-#endif /* !_SYS_QUEUE_H_ */
diff --git a/mDNSShared/utilities/mdns_addr_tailq.c b/mDNSShared/utilities/mdns_addr_tailq.c
deleted file mode 100644
index 4990d87..0000000
--- a/mDNSShared/utilities/mdns_addr_tailq.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "mdns_addr_tailq.h"
-
-#ifdef __APPLE__
-#include <AssertMacros.h>
-#endif // __APPLE__
-
-#include "mdns_strict.h"
-
-//======================================================================================================================
-// MARK: - Functions
-
-mdns_addr_tailq_t *
-mdns_addr_tailq_create(void)
-{
-	mdns_addr_tailq_t * const me = mdns_calloc(1, sizeof(*me));
-	require(me != NULL, exit);
-
-	STAILQ_INIT(me);
-exit:
-	return me;
-}
-//======================================================================================================================
-
-void
-mdns_addr_tailq_dispose(mdns_addr_tailq_t * NONNULL me)
-{
-	mdns_addr_with_port_t * n1 = STAILQ_FIRST(me);
-	mdns_addr_with_port_t * n2;
-	while (n1 != NULL) {
-		n2 = STAILQ_NEXT(n1, __entries);
-		mdns_free(n1);
-		n1 = n2;
-	}
-	mdns_addr_tailq_t * me_temp = me;
-	mdns_free(me_temp);
-}
-
-//======================================================================================================================
-
-bool
-mdns_addr_tailq_empty(const mdns_addr_tailq_t * const NONNULL me)
-{
-	return STAILQ_EMPTY(me);
-}
-
-//======================================================================================================================
-
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_add_front(mdns_addr_tailq_t * const NONNULL me, const mDNSAddr * const NONNULL address,
-						  const mDNSIPPort port)
-{
-	mdns_addr_with_port_t * const addr_with_port = mdns_calloc(1, sizeof(*addr_with_port));
-	require(addr_with_port != NULL, exit);
-
-	addr_with_port->address = *address;
-	addr_with_port->port = port;
-
-	STAILQ_INSERT_HEAD(me, addr_with_port, __entries);
-
-exit:
-	return addr_with_port;
-}
-
-//======================================================================================================================
-
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_add_back(mdns_addr_tailq_t * const NONNULL me, const mDNSAddr * const NONNULL address,
-						 const mDNSIPPort port)
-{
-	mdns_addr_with_port_t * const addr_with_port = mdns_calloc(1, sizeof(*addr_with_port));
-	require(addr_with_port != NULL, exit);
-
-	addr_with_port->address = *address;
-	addr_with_port->port = port;
-
-	STAILQ_INSERT_TAIL(me, addr_with_port, __entries);
-
-exit:
-	return addr_with_port;
-}
-
-//======================================================================================================================
-
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_get_front(const mdns_addr_tailq_t * const NONNULL me)
-{
-	return STAILQ_FIRST(me);
-}
-
-//======================================================================================================================
-
-void
-mdns_addr_tailq_remove_front(mdns_addr_tailq_t * const NONNULL me)
-{
-	mdns_addr_with_port_t * n = STAILQ_FIRST(me);
-	STAILQ_REMOVE_HEAD(me, __entries);
-	mdns_free(n);
-}
-
-//======================================================================================================================
-
-bool
-mdns_addr_tailq_remove(mdns_addr_tailq_t * const NONNULL me, const mDNSAddr * const NONNULL address,
-					   const mDNSIPPort port)
-{
-	bool found;
-	require_action(!mdns_addr_tailq_empty(me), exit, found = false);
-
-	mdns_addr_with_port_t * addr_with_port;
-	mdns_addr_with_port_t * addr_with_port_temp;
-	found = false;
-	STAILQ_FOREACH_SAFE(addr_with_port, me, __entries, addr_with_port_temp) {
-		if (mDNSVal16(port) != mDNSVal16(addr_with_port->port)) {
-			continue;
-		}
-		if (!mDNSSameAddress(address, &addr_with_port->address)) {
-			continue;
-		}
-		found = true;
-
-		STAILQ_REMOVE(me, addr_with_port, mdns_addr_with_port, __entries);
-		mdns_free(addr_with_port);
-		break;
-	}
-
-exit:
-	return found;
-}
-
-//======================================================================================================================
-
-bool
-mdns_addr_with_port_equal(const mdns_addr_with_port_t * const NONNULL addr_1,
-						  const mdns_addr_with_port_t * const NONNULL addr_2)
-{
-	bool equal;
-
-	if (addr_1 == addr_2) {
-		equal = true;
-		goto exit;
-	}
-
-	if (mDNSVal16(addr_1->port) != mDNSVal16(addr_2->port)) {
-		equal = false;
-		goto exit;
-	}
-
-	if (!mDNSSameAddress(&addr_1->address, &addr_2->address)) {
-		equal = false;
-		goto exit;
-	}
-
-	equal = true;
-exit:
-	return equal;
-}
diff --git a/mDNSShared/utilities/mdns_addr_tailq.h b/mDNSShared/utilities/mdns_addr_tailq.h
deleted file mode 100644
index e942483..0000000
--- a/mDNSShared/utilities/mdns_addr_tailq.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MDNS_ADDR_TAIL_QUEUE_H
-#define MDNS_ADDR_TAIL_QUEUE_H
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include "nullability.h"		// For NULLABLE and NONNULL.
-#include "bsd_queue.h"			// For STAILQ.
-#include <stdlib.h>
-#include <stdbool.h>			// For bool.
-#include "mDNSEmbeddedAPI.h"	// For mDNSAddr, mDNSIPPort and mStatus.
-#if defined(POSIX_BUILD)
-#include "DebugServices.h"
-#endif // defined(POSIX_BUILD)
-
-//======================================================================================================================
-// MARK: - Structures
-
-typedef struct mdns_addr_with_port mdns_addr_with_port_t;
-struct mdns_addr_with_port {
-	STAILQ_ENTRY(mdns_addr_with_port) __entries;	// The entry used by STAILQ to form the linked list.
-	mDNSAddr address;								// IPv4 or IPv6 address.
-	mDNSIPPort port;								// The port number that is associated with the address above.
-};
-
-typedef struct mdns_addr_tailq mdns_addr_tailq_t;
-// The tail queue struct mdns_addr_tailq that contains struct mdns_addr_with_port.
-STAILQ_HEAD(mdns_addr_tailq, mdns_addr_with_port);
-
-//======================================================================================================================
-// MARK: - Function Declarations
-
-/*!
- *	@brief
- *		Creates a tail queue that contains IP address and port number.
- *
- *	@result
- *		A pointer to the tail queue or NULL if the system was out of memory.
- */
-mdns_addr_tailq_t * NULLABLE
-mdns_addr_tailq_create(void);
-
-/*!
- *	@brief
- * 		Disposes a tail queue that is created by <code>mdns_addr_tailq_create()</code>.
- *
- *	@param me
- *		The tail queue that will be disposed.
- *
- *	@discussion
- *		Use <code>MDNS_DISPOSE_MDNS_ADDR_TAILQ()</code> to dispose a tail queue safely.
- */
-void
-mdns_addr_tailq_dispose(mdns_addr_tailq_t * NONNULL me);
-#define MDNS_DISPOSE_MDNS_ADDR_TAILQ(obj) _MDNS_STRICT_DISPOSE_TEMPLATE(obj, mdns_addr_tailq_dispose)
-
-/*!
- *	@brief
- *		Checks if the current tail queue is empty.
- *
- *	@param me
- *		The tail queue to be checked.
- *
- *	@result
- *		True if the tail queue does not contain any element. Otherwise, false.
- */
-bool
-mdns_addr_tailq_empty(const mdns_addr_tailq_t * NONNULL me);
-
-/*!
- *	@brief
- *		Adds an IP address with its corresponding port number into the front of the tail queue.
- *
- *	@param me
- *		The tail queue where the address and port number to be added into.
- *
- *	@param address
- *		The IP address to be added.
- *
- *	@param port
- *		The corresponding port number of the added address to be added.
- *
- *	@result
- *		The added address with its port number in the front of the tail queue, or NULL if the system was out of memory.
- */
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_add_front(mdns_addr_tailq_t * NONNULL me, const mDNSAddr * NONNULL address, mDNSIPPort port);
-
-/*!
- *	@brief
- *		Adds an IP address with its corresponding port number into the back of the tail queue.
- *
- *	@param me
- *		The tail queue where the address and port number to be added into.
- *
- *	@param address
- *		The IP address to be added.
- *
- *	@param port
- *		The corresponding port number of the added address to be added.
- *
- *	@result
- *		The added address with its port number in the back of the tail queue, or NULL if the system was out of memory.
- */
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_add_back(mdns_addr_tailq_t * NONNULL me, const mDNSAddr * NONNULL address, mDNSIPPort port);
-
-/*!
- *	@brief
- *		Gets the pointer to mdns_addr_with_port_t (which contains the IP address and port number added before) in the front of the tail queue.
- *
- *	@param me
- *		The tail queue where the mdns_addr_with_port_t to be get from.
- *
- *	@result
- *		The pointer to the mdns_addr_with_port_t in the front of the tail queue, or NULL if the tail queue is empty.
- */
-const mdns_addr_with_port_t * NULLABLE
-mdns_addr_tailq_get_front(const mdns_addr_tailq_t * NONNULL me);
-
-/*!
- *	@brief
- *		Removes the first IP address and its port number in the front of the tail queue.
- *
- *	@param me
- *		The tail queue where the IP address and its port number to be removed.
- */
-void
-mdns_addr_tailq_remove_front(mdns_addr_tailq_t * NONNULL me);
-
-/*!
- *	@brief
- *		Removes mdns_addr_with_port_t object in the tail queue with the IP address and port number specified in the parameters.
- *
- *	@param me
- *		The tail queue where the IP address and its port number to be removed.
- *
- *	@param address
- *		The IP address to be matched.
- *
- *	@param port
- *		The corresponding port number of the IP address to be matched.
- *
- *	@result
- *		True if the mdns_addr_with_port_t object is found and removed from the tail queue, for the IP address and port number specified in the parameters.
- *		False if such mdns_addr_with_port_t object does not exist in the tail queue.
- */
-bool
-mdns_addr_tailq_remove(mdns_addr_tailq_t * NONNULL me, const mDNSAddr * NONNULL address, mDNSIPPort port);
-
-/*!
- *	@brief
- *		Checks if two mdns_addr_with_port_t object are equal in value.
- *
- *	@param addr_1
- *		mdns_addr_with_port_t object to be compared.
- *
- *	@param addr_2
- *		mdns_addr_with_port_t object to be compared.
- *
- *	@result
- *		True if two mdns_addr_with_port_t are equal in value, otherwise, false.
- */
-bool
-mdns_addr_with_port_equal(const mdns_addr_with_port_t * NONNULL addr_1, const mdns_addr_with_port_t * NONNULL addr_2);
-
-#endif // MDNS_ADDR_TAIL_QUEUE_H
diff --git a/mDNSShared/utilities/misc_utilities.c b/mDNSShared/utilities/misc_utilities.c
deleted file mode 100644
index e25cbd4..0000000
--- a/mDNSShared/utilities/misc_utilities.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include "misc_utilities.h"
-
-#include <string.h>						// For memset().
-#include "mdns_strict.h"
-#include "DebugServices.h"				// For check_compile_time_code().
-
-//======================================================================================================================
-// MARK: - Functions
-
-mDNSAddr
-mDNSAddr_from_in_addr(const struct in_addr * const NONNULL v4)
-{
-	mDNSAddr mdns_addr; // NOLINT(misc-uninitialized-record-variable): No need to initialize mdns_addr here.
-	check_compile_time_code(sizeof(mdns_addr.ip.v4) == sizeof(v4->s_addr));
-
-	mdns_addr.type = mDNSAddrType_IPv4;
-	mDNSPlatformMemCopy(&mdns_addr.ip.v4, &v4->s_addr, sizeof(v4->s_addr));
-
-	return mdns_addr;
-}
-
-//======================================================================================================================
-
-mDNSAddr
-mDNSAddr_from_in6_addr(const struct in6_addr * const NONNULL v6)
-{
-	mDNSAddr mdns_addr; // NOLINT(misc-uninitialized-record-variable): No need to initialize mdns_addr here.
-	check_compile_time_code(sizeof(mdns_addr.ip.v6) == sizeof(v6->s6_addr));
-
-	mdns_addr.type = mDNSAddrType_IPv6;
-	mDNSPlatformMemCopy(&mdns_addr.ip.v6, v6->s6_addr, sizeof(v6->s6_addr));
-
-	return mdns_addr;
-}
-
-//======================================================================================================================
-
-mDNSAddr
-mDNSAddr_from_sockaddr(const struct sockaddr * const NONNULL sa)
-{
-	mDNSAddr mdns_addr; // NOLINT(misc-uninitialized-record-variable): No need to initialize mdns_addr here.
-
-	if (sa->sa_family == AF_INET) {
-		const struct in_addr *const v4_addr = &((const struct sockaddr_in *)sa)->sin_addr;
-		mdns_addr = mDNSAddr_from_in_addr(v4_addr);
-
-	} else if (sa->sa_family == AF_INET6) {
-		const struct in6_addr *const v6_addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
-		mdns_addr = mDNSAddr_from_in6_addr(v6_addr);
-
-	} else {
-		memset(&mdns_addr, 0, sizeof(mdns_addr));
-	}
-
-	return mdns_addr;
-}
-
-//======================================================================================================================
-
-const char *
-get_address_string_from_mDNSAddr(const mDNSAddr * const NONNULL addr,
-								 char out_string_buf[static NONNULL INET6_ADDRSTRLEN + 1])
-{
-	if (addr->type == mDNSAddrType_IPv4) {
-		inet_ntop(AF_INET, addr->ip.v4.b, out_string_buf, INET6_ADDRSTRLEN + 1);
-	} else if (addr->type == mDNSAddrType_IPv6) {
-		inet_ntop(AF_INET6, addr->ip.v6.b, out_string_buf, INET6_ADDRSTRLEN + 1);
-	} else {
-		out_string_buf[0] = '\0';
-	}
-
-	return out_string_buf;
-}
diff --git a/mDNSShared/utilities/misc_utilities.h b/mDNSShared/utilities/misc_utilities.h
deleted file mode 100644
index bd019e8..0000000
--- a/mDNSShared/utilities/misc_utilities.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef MISC_UTILITIES_H
-#define MISC_UTILITIES_H
-
-//======================================================================================================================
-// MARK: - Headers
-
-#include <netinet/in.h>			// For sockaddr.
-#include "nullability.h"		// For NULLABLE and NONNULL.
-#include "mDNSEmbeddedAPI.h"	// For mDNSAddr.
-
-//======================================================================================================================
-// MARK: - Macros
-
-#ifndef __APPLE__
-
-#ifndef require
-	#define require(assertion, exception_label)			\
-		do {											\
-			if (__builtin_expect(!(assertion), 0)) {	\
-				goto exception_label;					\
-			}											\
-		} while (false)
-#endif // require
-
-#ifndef require_action
-	#define require_action(assertion, exception_label, action)	\
-		do {													\
-			if (__builtin_expect(!(assertion), 0)) {			\
-				{												\
-					action;										\
-				}												\
-				goto exception_label;							\
-			}													\
-		} while (false)
-#endif // require_action
-
-#endif // __APPLE__
-
-//======================================================================================================================
-// MARK: - Function Declarations
-
-/*!
- *	@brief
- *		Convert struct in_addr to mDNSAddr.
- *
- *	@param v4
- *		The IPv4 struct in_addr to be converted.
- *
- *	@result
- *		The converted mDNSAddr.
- */
-mDNSAddr
-mDNSAddr_from_in_addr(const struct in_addr * NONNULL v4);
-
-/*!
- *	@brief
- *		Convert struct in6_addr to mDNSAddr.
- *
- *	@param v6
- *		The IPv6 struct in6_addr to be converted.
- *
- *	@result
- *		The converted mDNSAddr.
- */
-mDNSAddr
-mDNSAddr_from_in6_addr(const struct in6_addr * NONNULL v6);
-
-/*!
- *	@brief
- *		Convert struct sockaddr to mDNSAddr.
- *
- *	@param sa
- *		The struct sockaddr to be converted.
- *
- *	@result
- *		The converted mDNSAddr.
- */
-mDNSAddr
-mDNSAddr_from_sockaddr(const struct sockaddr * NONNULL sa);
-
-
-const char * NONNULL
-get_address_string_from_mDNSAddr(const mDNSAddr * const NONNULL addr,
-								 char out_string_buf[static NONNULL INET6_ADDRSTRLEN + 1]);
-
-#endif // MISC_UTILITIES_H
diff --git a/mDNSShared/utilities/nullability.h b/mDNSShared/utilities/nullability.h
deleted file mode 100644
index 75e37ba..0000000
--- a/mDNSShared/utilities/nullability.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple 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
- *
- *     https://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.
- */
-
-#ifndef NULLABILITY_H
-#define NULLABILITY_H
-
-//======================================================================================================================
-// MARK: - Macros
-
-#ifndef NULLABLE
-	#ifdef __clang__
-		#define NULLABLE			_Nullable
-		#define NONNULL				_Nonnull
-		#define NULL_UNSPECIFIED	_Null_unspecified
-		#define UNUSED				__unused
-	#else
-		#define NULLABLE
-		#define NONNULL
-		#define NULL_UNSPECIFIED
-		#define UNUSED				__attribute__((unused))
-	#endif
-#endif
-
-#endif // NULLABILITY_H
diff --git a/mDNSWindows/ControlPanel/BrowsingPage.cpp b/mDNSWindows/ControlPanel/BrowsingPage.cpp
deleted file mode 100644
index 084cf1b..0000000
--- a/mDNSWindows/ControlPanel/BrowsingPage.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "BrowsingPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-
-#include <WinServices.h>
-    
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CBrowsingPage, CPropertyPage)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::CBrowsingPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CBrowsingPage::CBrowsingPage()
-:
-	CPropertyPage(CBrowsingPage::IDD)
-{
-	//{{AFX_DATA_INIT(CBrowsingPage)
-	//}}AFX_DATA_INIT
-
-	m_firstTime = true;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::~CBrowsingPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CBrowsingPage::~CBrowsingPage()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CBrowsingPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CBrowsingPage)
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_BROWSE_LIST, m_browseListCtrl);
-	DDX_Control(pDX, IDC_REMOVE_BROWSE_DOMAIN, m_removeButton);
-}
-
-BEGIN_MESSAGE_MAP(CBrowsingPage, CPropertyPage)
-	//{{AFX_MSG_MAP(CBrowsingPage)
-	//}}AFX_MSG_MAP
-	ON_BN_CLICKED(IDC_ADD_BROWSE_DOMAIN, OnBnClickedAddBrowseDomain)
-	ON_BN_CLICKED(IDC_REMOVE_BROWSE_DOMAIN, OnBnClickedRemoveBrowseDomain)
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_BROWSE_LIST, OnLvnItemchangedBrowseList)
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CBrowsingPage::SetModified( BOOL bChanged )
-{
-	m_modified = bChanged;
-
-	CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CBrowsingPage::OnSetActive()
-{
-	CConfigPropertySheet	*	psheet;
-	HKEY						key = NULL;
-	HKEY						subKey = NULL;
-	DWORD						dwSize;
-	DWORD						enabled;
-	DWORD						err;
-	TCHAR						subKeyName[MAX_KEY_LENGTH];
-	DWORD						cSubKeys = 0;
-	DWORD						cbMaxSubKey;
-	DWORD						cchMaxClass;
-	int							nIndex;
-    DWORD						i; 
-	BOOL						b = CPropertyPage::OnSetActive();
-
-	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-	require_quiet( psheet, exit );
-	
-	m_modified = FALSE;
-
-	if ( m_firstTime )
-	{
-		m_browseListCtrl.SetExtendedStyle((m_browseListCtrl.GetStyle() & (~LVS_EX_GRIDLINES))|LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
-
-		m_browseListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, 20 );
-		m_browseListCtrl.InsertColumn(1, L"", LVCFMT_LEFT, 345);
-
-		m_firstTime = false;
-	}
-
-	m_initialized = false;
-
-	// Clear out what's there
-
-	m_browseListCtrl.DeleteAllItems();
-
-	// Now populate the browse domain box
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	// Get information about this node
-
-    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	for ( i = 0; i < cSubKeys; i++)
-	{	
-		dwSize = MAX_KEY_LENGTH;
-            
-		err = RegEnumKeyEx( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-		require_noerr( err, exit );
-
-		err = RegOpenKey( key, subKeyName, &subKey );
-		require_noerr( err, exit );
-
-		dwSize = sizeof( DWORD );
-		err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-		require_noerr( err, exit );
-
-		nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
-		m_browseListCtrl.SetItemText( nIndex, 1, subKeyName );
-		m_browseListCtrl.SetCheck( nIndex, enabled );
-
-		RegCloseKey( subKey );
-		subKey = NULL;
-    }
-
-	m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
-
-	m_removeButton.EnableWindow( FALSE );
- 
-exit:
-
-	if ( subKey )
-	{
-		RegCloseKey( subKey );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	m_initialized = true;
-
-	return b;
-}
-
- 
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CBrowsingPage::OnOK()
-{
-	if ( m_modified )
-	{
-		Commit();
-	}
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CBrowsingPage::Commit()
-{
-	HKEY		key		= NULL;
-	HKEY		subKey	= NULL;
-	TCHAR		subKeyName[MAX_KEY_LENGTH];
-	DWORD		cSubKeys = 0;
-	DWORD		cbMaxSubKey;
-	DWORD		cchMaxClass;
-	DWORD		dwSize;
-	int			i;
-	DWORD		err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSBrowseDomains, 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	// First, remove all the entries that are there
-
-    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	for ( i = 0; i < (int) cSubKeys; i++ )
-	{	
-		dwSize = MAX_KEY_LENGTH;
-            
-		err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-		require_noerr( err, exit );
-			
-		err = RegDeleteKey( key, subKeyName );
-		require_noerr( err, exit );
-	}
-
-	// Now re-populate
-
-	for ( i = 0; i < m_browseListCtrl.GetItemCount(); i++ )
-	{
-		DWORD enabled = (DWORD) m_browseListCtrl.GetCheck( i );
-
-		err = RegCreateKeyEx( key, m_browseListCtrl.GetItemText( i, 1 ), 0,
-		                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &subKey, NULL );
-		require_noerr( err, exit );
-
-		err = RegSetValueEx( subKey, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
-		require_noerr( err, exit );
-
-		RegCloseKey( subKey );
-		subKey = NULL;
-	}
-	
-exit:
-
-	if ( subKey )
-	{
-		RegCloseKey( subKey );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::OnBnClickedAddBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CBrowsingPage::OnBnClickedAddBrowseDomain()
-{
-	CAddBrowseDomain dlg( GetParent() );
-
-	if ( ( dlg.DoModal() == IDOK ) && ( dlg.m_text.GetLength() > 0 ) )
-	{
-		int nIndex;
-
-		nIndex = m_browseListCtrl.InsertItem( m_browseListCtrl.GetItemCount(), L"");
-		m_browseListCtrl.SetItemText( nIndex, 1, dlg.m_text );
-		m_browseListCtrl.SetCheck( nIndex, 1 );
-
-		m_browseListCtrl.SortItems( SortFunc, (DWORD_PTR) this );
-
-		m_browseListCtrl.Invalidate();
-
-		SetModified( TRUE );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage::OnBnClickedRemoveBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CBrowsingPage::OnBnClickedRemoveBrowseDomain()
-{
-	UINT	selectedCount = m_browseListCtrl.GetSelectedCount();
-	int		nItem = -1;
-	UINT	i;
-
-	// Update all of the selected items.
-
-	for ( i = 0; i < selectedCount; i++ )
-	{
-		nItem = m_browseListCtrl.GetNextItem( -1, LVNI_SELECTED );
-		check( nItem != -1 );
-
-		m_browseListCtrl.DeleteItem( nItem );
-
-		SetModified( TRUE );
-	}
-
-	m_removeButton.EnableWindow( FALSE );
-}
-
-
-void
-CBrowsingPage::OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
-{
-	if ( m_browseListCtrl.GetSelectedCount() )
-	{
-		m_removeButton.EnableWindow( TRUE );
-	}
-
-	if ( m_initialized )
-	{
-		NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; 
-	 
-		BOOL bPrevState = (BOOL) ( ( ( pNMListView->uOldState & LVIS_STATEIMAGEMASK ) >> 12 ) - 1 ); 
-	 
-		if ( bPrevState < 0 )
-		{
-			bPrevState = 0;
-		}
-
-
-		BOOL bChecked = ( BOOL ) ( ( ( pNMListView->uNewState & LVIS_STATEIMAGEMASK ) >> 12) - 1 ); 
-	 
-		if ( bChecked < 0 )
-		{
-			bChecked = 0;
-		}
-
-		if ( bPrevState != bChecked )
-		{
-			SetModified( TRUE );
-		}
-	}
-
-	*pResult = 0;
-}
-
-
-
-int CALLBACK 
-CBrowsingPage::SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
-{
-	CString str1;
-	CString	str2;
-	int		ret = 0;
-
-	CBrowsingPage * self = reinterpret_cast<CBrowsingPage*>( lParamSort );
-	require_quiet( self, exit );
-
-	str1 = self->m_browseListCtrl.GetItemText( (int) lParam1, 1 );
-	str2 = self->m_browseListCtrl.GetItemText( (int) lParam2, 1 );
-
-	ret = str1.Compare( str2 );
-
-exit:
-
-	return ret;
-}
-
-
-// CAddBrowseDomain dialog
-
-IMPLEMENT_DYNAMIC(CAddBrowseDomain, CDialog)
-CAddBrowseDomain::CAddBrowseDomain(CWnd* pParent /*=NULL*/)
-	: CDialog(CAddBrowseDomain::IDD, pParent)
-{
-}
-
-CAddBrowseDomain::~CAddBrowseDomain()
-{
-}
-
-void CAddBrowseDomain::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_COMBO1, m_comboBox);
-}
-
-
-BOOL
-CAddBrowseDomain::OnInitDialog()
-{
-	CConfigPropertySheet	*	psheet;
-	CConfigPropertySheet::StringList::iterator		it;
-	
-	BOOL b = CDialog::OnInitDialog();
-
-	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	for ( it = psheet->m_browseDomains.begin(); it != psheet->m_browseDomains.end(); it++ )
-	{
-		CString text = *it;
-
-		if ( m_comboBox.FindStringExact( -1, *it ) == CB_ERR )
-		{
-			m_comboBox.AddString( *it );
-		}
-	}
-
-exit:
-
-	return b;
-}
-
-
-void
-CAddBrowseDomain::OnOK()
-{
-	m_comboBox.GetWindowText( m_text );
-
-	CDialog::OnOK();
-}
-
-
-
-BEGIN_MESSAGE_MAP(CAddBrowseDomain, CDialog)
-END_MESSAGE_MAP()
-
diff --git a/mDNSWindows/ControlPanel/BrowsingPage.h b/mDNSWindows/ControlPanel/BrowsingPage.h
deleted file mode 100644
index 4711b36..0000000
--- a/mDNSWindows/ControlPanel/BrowsingPage.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include <list>
-#include "afxcmn.h"
-
-#include "afxwin.h"
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CBrowsingPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CBrowsingPage : public CPropertyPage
-{
-public:
-	CBrowsingPage();
-	~CBrowsingPage();
-
-protected:
-
-	//{{AFX_DATA(CBrowsingPage)
-	enum { IDD = IDR_APPLET_PAGE3 };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CBrowsingPage)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CBrowsingPage)
-
-	//{{AFX_MSG(CBrowsingPage)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-	
-private:
-	
-	typedef std::list<CString> StringList;
-
-	afx_msg BOOL
-	OnSetActive();
-	
-	afx_msg void
-	OnOK();
-	
-	void
-	SetModified( BOOL bChanged = TRUE );
-	
-	void
-	Commit();
-
-	BOOL			m_modified;
-
-public:
-private:
-
-	static int CALLBACK 
-
-	SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
-
-
-
-	CListCtrl	m_browseListCtrl;
-
-	bool		m_initialized;
-
-	bool		m_firstTime;
-
-
-
-public:
-
-
-
-	afx_msg void OnBnClickedAddBrowseDomain();
-
-	afx_msg void OnBnClickedRemoveBrowseDomain();
-
-	afx_msg void OnLvnItemchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult);
-
-	CButton m_removeButton;
-
-};
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CAddBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-
-class CAddBrowseDomain : public CDialog
-
-{
-
-	DECLARE_DYNAMIC(CAddBrowseDomain)
-
-
-
-public:
-
-	CAddBrowseDomain(CWnd* pParent = NULL);   // standard constructor
-
-	virtual ~CAddBrowseDomain();
-
-
-
-// Dialog Data
-
-	enum { IDD = IDR_ADD_BROWSE_DOMAIN };
-
-
-
-protected:
-
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-
-	virtual BOOL OnInitDialog();
-
-	virtual void OnOK();
-
-	DECLARE_MESSAGE_MAP()
-
-public:
-
-	CComboBox	m_comboBox;
-
-	CString		m_text;
-
-};
-
diff --git a/mDNSWindows/ControlPanel/ConfigDialog.cpp b/mDNSWindows/ControlPanel/ConfigDialog.cpp
deleted file mode 100644
index ad59066..0000000
--- a/mDNSWindows/ControlPanel/ConfigDialog.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-
-#include "ConfigDialog.h"
-#include "ControlPanel.h"
-
-
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-IMPLEMENT_DYNCREATE(CConfigDialog, CDialog)
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigDialog::CConfigDialog
-//---------------------------------------------------------------------------------------------------------------------------
-
-CConfigDialog::CConfigDialog()
-	: CDialog(CConfigDialog::IDD, NULL)
-{
-	//{{AFX_DATA_INIT(CConfigDialog)
-	//}}AFX_DATA_INIT
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigDialog::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CConfigDialog::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CConfigDialog)
-	//}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CConfigDialog, CDialog)
-	//{{AFX_MSG_MAP(CConfigDialog)
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
diff --git a/mDNSWindows/ControlPanel/ConfigDialog.h b/mDNSWindows/ControlPanel/ConfigDialog.h
deleted file mode 100644
index fa8df5f..0000000
--- a/mDNSWindows/ControlPanel/ConfigDialog.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigDialog
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CConfigDialog : public CDialog
-{
-public:
-
-	CConfigDialog();
-
-protected:
-
-	//{{AFX_DATA(CConfigDialog)
-	enum { IDD = IDR_APPLET };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CConfigDialog)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	//{{AFX_MSG(CConfigDialog)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-
-	DECLARE_DYNCREATE(CConfigDialog)
-};
diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp b/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
deleted file mode 100644
index 34c418e..0000000
--- a/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "ConfigPropertySheet.h"
-#include <WinServices.h>
-extern "C"
-{
-#include <ClientCommon.h>
-}
-#include <process.h>
-
-// Custom events
-
-#define WM_DATAREADY		( WM_USER + 0x100 )
-
-
-IMPLEMENT_DYNCREATE(CConfigPropertySheet, CPropertySheet)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::CConfigPropertySheet
-//---------------------------------------------------------------------------------------------------------------------------
-
-CConfigPropertySheet::CConfigPropertySheet()
-:
-	CPropertySheet(),
-	m_browseDomainsRef( NULL ),
-	m_thread( NULL ),
-	m_threadExited( NULL )
-{
-	AddPage(&m_firstPage );
-	AddPage(&m_secondPage);
-	AddPage(&m_thirdPage);
-
-	InitializeCriticalSection( &m_lock );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::~CConfigPropertySheet
-//---------------------------------------------------------------------------------------------------------------------------
-
-CConfigPropertySheet::~CConfigPropertySheet()
-{
-	DeleteCriticalSection( &m_lock );
-}
-
-
-BEGIN_MESSAGE_MAP(CConfigPropertySheet, CPropertySheet)
-	//{{AFX_MSG_MAP(CConfigPropertySheet)
-	//}}AFX_MSG_MAP
-	ON_MESSAGE( WM_DATAREADY, OnDataReady )
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::OnInitDialog
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CConfigPropertySheet::OnInitDialog()
-{
-	OSStatus err;
-
-	BOOL b = CPropertySheet::OnInitDialog();
-
-	err = SetupBrowsing();
-	require_noerr( err, exit );
-
-exit:
-
-	return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::OnCommand
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CConfigPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
-{
-   // Check if OK or Cancel was hit
-
-   if ( ( wParam == ID_WIZFINISH ) || ( wParam == IDOK ) || ( wParam == IDCANCEL ) ) 
-   {
-      OnEndDialog();
-   }
-
-   return CPropertySheet::OnCommand(wParam, lParam);
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::OnDataReady
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CConfigPropertySheet::OnDataReady(WPARAM inWParam, LPARAM inLParam)
-{
-	if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
-	{
-		dlog( kDebugLevelError, "OnSocket: window error\n" );
-	}
-	else
-	{
-		SOCKET sock = (SOCKET) inWParam;
-
-		if ( m_browseDomainsRef && DNSServiceRefSockFD( m_browseDomainsRef ) == (int) sock )
-		{
-			DNSServiceProcessResult( m_browseDomainsRef );
-		}
-	}
-
-	return 0;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::OnEndDialog
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CConfigPropertySheet::OnEndDialog()
-{
-	OSStatus err;
-
-	err = TearDownBrowsing();
-	check_noerr( err );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::SetupBrowsing
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CConfigPropertySheet::SetupBrowsing()
-{
-	OSStatus err;
-
-	// Start browsing for browse domains
-
-	err = DNSServiceEnumerateDomains( &m_browseDomainsRef, kDNSServiceFlagsBrowseDomains, 0, BrowseDomainsReply, this );
-	require_noerr( err, exit );
-
-	err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, WM_DATAREADY, FD_READ|FD_CLOSE );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( err )
-	{
-		TearDownBrowsing();
-	}
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::TearDownBrowsing
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CConfigPropertySheet::TearDownBrowsing()
-{
-	OSStatus err = kNoErr;
-
-	if ( m_browseDomainsRef )
-	{
-		err = WSAAsyncSelect( DNSServiceRefSockFD( m_browseDomainsRef ), m_hWnd, 0, 0 );
-		check_noerr( err );
-
-		DNSServiceRefDeallocate( m_browseDomainsRef );
-	
-		m_browseDomainsRef = NULL;
-	}
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::DecodeDomainName
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded )
-{
-	char nextLabel[128] = "\0";
-	char decodedDomainString[kDNSServiceMaxDomainName];
-    char * buffer = (char *) raw;
-    int labels = 0, i;
-    char text[64];
-	const char *label[128];
-	OSStatus	err;
-    
-	// Initialize
-
-	decodedDomainString[0] = '\0';
-
-    // Count the labels
-
-	while ( *buffer )
-	{
-		label[labels++] = buffer;
-		buffer = (char *) GetNextLabel(buffer, text);
-    }
-        
-    buffer = (char*) raw;
-
-    for (i = 0; i < labels; i++)
-	{
-		buffer = (char *)GetNextLabel(buffer, nextLabel);
-        strcat_s(decodedDomainString, sizeof(decodedDomainString), nextLabel);
-        strcat_s(decodedDomainString, sizeof(decodedDomainString), ".");
-    }
-    
-    // Remove trailing dot from domain name.
-    
-	decodedDomainString[ strlen( decodedDomainString ) - 1 ] = '\0';
-
-	// Convert to Unicode
-
-	err = UTF8StringToStringObject( decodedDomainString, decoded );
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet::BrowseDomainsReply
-//---------------------------------------------------------------------------------------------------------------------------
-
-void DNSSD_API
-CConfigPropertySheet::BrowseDomainsReply
-							(
-							DNSServiceRef			sdRef,
-							DNSServiceFlags			flags,
-							uint32_t				interfaceIndex,
-							DNSServiceErrorType		errorCode,
-							const char			*	replyDomain,
-							void				*	context
-							)
-{
-	CConfigPropertySheet	*	self = reinterpret_cast<CConfigPropertySheet*>(context);
-	CString						decoded;
-	OSStatus					err;
-
-	DEBUG_UNUSED( sdRef );
-	DEBUG_UNUSED( interfaceIndex );
-
-	if ( errorCode )
-	{
-		goto exit;
-	}
-
-	check( replyDomain );
-	
-	// Ignore local domains
-
-	if ( strcmp( replyDomain, "local." ) == 0 )
-	{
-		goto exit;
-	}
-
-	err = self->DecodeDomainName( replyDomain, decoded );
-	require_noerr( err, exit );
-
-	// Remove trailing '.'
-
-	decoded.TrimRight( '.' );
-
-	if ( flags & kDNSServiceFlagsAdd )
-	{
-		self->m_browseDomains.push_back( decoded );
-	}
-	else
-	{
-		self->m_browseDomains.remove( decoded );
-	}
-
-exit:
-
-	return;
-}
diff --git a/mDNSWindows/ControlPanel/ConfigPropertySheet.h b/mDNSWindows/ControlPanel/ConfigPropertySheet.h
deleted file mode 100644
index 9e4fda8..0000000
--- a/mDNSWindows/ControlPanel/ConfigPropertySheet.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#ifndef _ConfigPropertySheet_h
-#define _ConfigPropertySheet_h
-
-#include "stdafx.h"
-#include "ServicesPage.h"
-#include "RegistrationPage.h"
-#include "BrowsingPage.h"
-
-#include <RegNames.h>
-#include <dns_sd.h>
-#include <list>
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CConfigPropertySheet
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CConfigPropertySheet : public CPropertySheet
-{
-public:
-
-	CConfigPropertySheet();
-	virtual ~CConfigPropertySheet();
-
-	typedef std::list<CString> StringList;
-
-	StringList	m_browseDomains;
-
-protected:
-
-	CServicesPage		m_firstPage;
-	CRegistrationPage	m_secondPage;
-	CBrowsingPage		m_thirdPage;
-
-	//{{AFX_VIRTUAL(CConfigPropertySheet)
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CConfigPropertySheet)
-
-	//{{AFX_MSG(CConfigPropertySheet)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-
-	afx_msg BOOL	OnInitDialog();
-	afx_msg BOOL	OnCommand( WPARAM wParam, LPARAM lParam );
-	afx_msg LRESULT	OnDataReady( WPARAM inWParam, LPARAM inLParam );
-	afx_msg LRESULT	OnRegistryChanged( WPARAM inWParam, LPARAM inLParam );
-	void			OnEndDialog();
-
-private:
-
-	OSStatus
-	SetupBrowsing();
-
-	OSStatus
-	TearDownBrowsing();
-
-	OSStatus
-	DecodeDomainName( const char * raw, CString & decoded );
-
-	static void DNSSD_API
-	BrowseDomainsReply
-				(
-				DNSServiceRef			sdRef,
-				DNSServiceFlags			flags,
-				uint32_t				interfaceIndex,
-				DNSServiceErrorType		errorCode,
-				const char			*	replyDomain,
-				void				*	context
-				);
-
-	// This thread will watch for registry changes
-
-	static unsigned WINAPI
-	WatchRegistry
-				(
-				LPVOID inParam
-				);
-
-	HKEY				m_statusKey;
-	HANDLE				m_thread;
-	HANDLE				m_threadExited;
-	DNSServiceRef		m_browseDomainsRef;
-	CRITICAL_SECTION	m_lock;
-};
-
-
-#endif
diff --git a/mDNSWindows/ControlPanel/ControlPanel.cpp b/mDNSWindows/ControlPanel/ControlPanel.cpp
deleted file mode 100644
index 4bf5df3..0000000
--- a/mDNSWindows/ControlPanel/ControlPanel.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-    
-#include "ControlPanel.h"
-#include "ConfigDialog.h"
-#include "ConfigPropertySheet.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-
-static CCPApp theApp;
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	GetControlPanelApp
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApp*
-GetControlPanelApp()
-{
-	CCPApp * pApp = (CCPApp*) AfxGetApp();
-
-	check( pApp );
-	check( pApp->IsKindOf( RUNTIME_CLASS( CCPApp ) ) );
-
-	return pApp;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CPlApplet
-//---------------------------------------------------------------------------------------------------------------------------
-
-LONG APIENTRY
-CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2)
-{
-	AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
-	CCPApp * pApp = GetControlPanelApp();
-
-	return ( LONG ) pApp->OnCplMsg(hWndCPl, uMsg, lParam1, lParam2);
-}
-
-
-IMPLEMENT_DYNAMIC(CCPApplet, CCmdTarget);
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::CCPApplet
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApplet::CCPApplet(UINT resourceId, UINT descId, CRuntimeClass * uiClass)
-:
-	m_resourceId(resourceId),
-	m_descId(descId),
-	m_uiClass(uiClass),
-	m_pageNumber(0)
-{
-	check( uiClass );
-	check( uiClass->IsDerivedFrom( RUNTIME_CLASS( CDialog ) ) || 
-	       uiClass->IsDerivedFrom( RUNTIME_CLASS( CPropertySheet ) ) );
-
-	m_name.LoadString(resourceId);
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::~CCPApplet
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApplet::~CCPApplet()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnStartParms
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnStartParms(CWnd * pParentWnd, LPCTSTR extra)
-{
-	DEBUG_UNUSED( pParentWnd );
-
-	if ( extra )
-	{
-		m_pageNumber = ::_ttoi( extra ) - 1;
-	}
-
-	return 0;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnRun
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnRun(CWnd* pParentWnd)
-{
-	LRESULT		lResult = 1;
-	CWnd	*	pWnd;
-
-	InitCommonControls();
-
-	pWnd = (CWnd*) m_uiClass->CreateObject(); 
-
-	if ( pWnd )
-	{
-		lResult = ERROR_SUCCESS;
-
-		if ( pWnd->IsKindOf( RUNTIME_CLASS( CPropertySheet ) ) )
-		{
-			CPropertySheet * pSheet = (CPropertySheet*) pWnd;
-
-			pSheet->Construct(m_name, pParentWnd, m_pageNumber);
-
-			pSheet->DoModal();
-		}
-		else
-		{
-			check( pWnd->IsKindOf( RUNTIME_CLASS( CDialog ) ) );
-
-			CDialog * pDialog = (CDialog*) pWnd;
-
-      		pDialog->DoModal();
-    	}
-
-		delete pWnd;
-  	}
-
-	return lResult;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnInquire
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnInquire(CPLINFO* pInfo)
-{
-	pInfo->idIcon = m_resourceId;
-	pInfo->idName = m_resourceId;
-	pInfo->idInfo = m_descId;
-	pInfo->lData  = reinterpret_cast<LONG>(this);
-
-	return 0;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnNewInquire
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnNewInquire(NEWCPLINFO* pInfo)
-{
-	DEBUG_UNUSED( pInfo );
-
-	return 1;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnSelect
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnSelect()
-{
-	return 0;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet::OnStop
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApplet::OnStop()
-{
-	return 0;
-}
-
-
-IMPLEMENT_DYNAMIC(CCPApp, CWinApp);
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::CCPApp
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApp::CCPApp()
-{
-	debug_initialize( kDebugOutputTypeWindowsEventLog, "DNS-SD Control Panel", GetModuleHandle( NULL ) );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::~CCPApp
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApp::~CCPApp()
-{
-	while ( !m_applets.IsEmpty() )
-	{
-    	delete m_applets.RemoveHead();
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::AddApplet
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CCPApp::AddApplet( CCPApplet * applet )
-{
-	check( applet );
-
-	m_applets.AddTail( applet );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::OnInit
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApp::OnInit()
-{
-	CCPApplet * applet;
-
-	try
-	{
-		applet = new CCPApplet( IDR_APPLET, IDS_APPLET_DESCRIPTION, RUNTIME_CLASS( CConfigPropertySheet ) );
-	}
-	catch (...)
-	{
-		applet = NULL;
-	}
-   
-	require_action( applet, exit, kNoMemoryErr );
-	
-	AddApplet( applet );
-
-exit:
-
-	return m_applets.GetCount();
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::OnExit
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApp::OnExit()
-{
-  return 1;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::OnCplMsg
-//---------------------------------------------------------------------------------------------------------------------------
-
-LRESULT
-CCPApp::OnCplMsg(HWND hWndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
-{
-	LRESULT lResult = 1;
-
-	switch ( uMsg )
-	{
-		case CPL_INIT:
-		{
-			lResult = OnInit();
-		}
-		break;
-
-		case CPL_EXIT:
-		{
-			lResult = OnExit();
-		}
-		break;
-
-		case CPL_GETCOUNT:
-		{      
-    		lResult = m_applets.GetCount();
-  		}
-		break;
-
-		default:
-  		{
-    		POSITION pos = m_applets.FindIndex( lParam1 );
-			check( pos );
-
-			CCPApplet * applet = m_applets.GetAt( pos );  
-			check( applet );
-
-    		switch (uMsg)
-    		{
-      			case CPL_INQUIRE:
-      			{
-					LPCPLINFO pInfo = reinterpret_cast<LPCPLINFO>(lParam2);
-        			lResult = applet->OnInquire(pInfo);
-				}  
-        		break;
-
-				case CPL_NEWINQUIRE:
-      			{
-        			LPNEWCPLINFO pInfo = reinterpret_cast<LPNEWCPLINFO>(lParam2);
-					lResult = applet->OnNewInquire(pInfo);
-				}  
-        		break;
-
-				case CPL_STARTWPARMS:
-      			{
-        			CWnd * pParentWnd = CWnd::FromHandle(hWndCPl);
-        			LPCTSTR lpszExtra = reinterpret_cast<LPCTSTR>(lParam2);
-        			lResult = applet->OnStartParms(pParentWnd, lpszExtra);
-				}
-				break;
-
-				case CPL_DBLCLK:
-				{
-        			CWnd* pParentWnd = CWnd::FromHandle(hWndCPl);
-        			lResult = applet->OnRun(pParentWnd);
-				}
-        		break;
-
-				case CPL_SELECT:
-				{
-        			lResult = applet->OnSelect();
-				}
-				break;
-
-				case CPL_STOP:
-				{
-					lResult = applet->OnStop();
-				}
-				break;
-
-				default:
-				{
-					// TRACE(_T("Warning, Received an unknown control panel message:%d\n"), uMsg);
-					lResult = 1;
-				}
-				break;
-    		}
-  		}
-		break;
-	}
-
-	return lResult;
-}
diff --git a/mDNSWindows/ControlPanel/ControlPanel.h b/mDNSWindows/ControlPanel/ControlPanel.h
deleted file mode 100644
index dec5e58..0000000
--- a/mDNSWindows/ControlPanel/ControlPanel.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-    
-#pragma once
-
-#include "stdafx.h"
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApplet
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CCPApplet : public CCmdTarget
-{
-public:
-
-	CCPApplet( UINT nResourceID, UINT nDescriptionID, CRuntimeClass* pUIClass );
-
-	virtual ~CCPApplet();
-
-protected:
-
-	virtual LRESULT OnRun(CWnd* pParentWnd);
-	virtual LRESULT OnStartParms(CWnd* pParentWnd, LPCTSTR lpszExtra);
-	virtual LRESULT OnInquire(CPLINFO* pInfo);
-	virtual LRESULT OnNewInquire(NEWCPLINFO* pInfo);
-	virtual LRESULT OnSelect();
-	virtual LRESULT OnStop();
-
-	CRuntimeClass	*	m_uiClass;
-	UINT				m_resourceId;
-	UINT				m_descId;
-	CString				m_name;
-	int					m_pageNumber;
-  
-	friend class CCPApp;
-
-	DECLARE_DYNAMIC(CCPApplet);
-};
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CCPApp : public CWinApp
-{
-public:
-
-	CCPApp();
-	virtual ~CCPApp();
-
-	void AddApplet( CCPApplet* pApplet );
-
-protected:
-
-	CList<CCPApplet*, CCPApplet*&> m_applets;
-
-	friend LONG APIENTRY
-	CPlApplet(HWND hWndCPl, UINT uMsg, LONG lParam1, LONG lParam2);
-
-	virtual LRESULT OnCplMsg(HWND hWndCPl, UINT msg, LPARAM lp1, LPARAM lp2);
-	virtual LRESULT OnInit();
-	virtual LRESULT OnExit();
-
-	DECLARE_DYNAMIC(CCPApp);
-};
-
-
-CCPApp * GetControlPanelApp();
diff --git a/mDNSWindows/ControlPanel/ControlPanelExe.cpp b/mDNSWindows/ControlPanel/ControlPanelExe.cpp
deleted file mode 100644
index 94de794..0000000
--- a/mDNSWindows/ControlPanel/ControlPanelExe.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2007 Apple 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.
- */
-
-    
-#include "ControlPanelExe.h"
-#include "ConfigDialog.h"
-#include "ConfigPropertySheet.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include "loclibrary.h"
-#include <strsafe.h>
-
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#ifndef HeapEnableTerminationOnCorruption
-#	define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS) 1
-#endif
-
-
-// Stash away pointers to our resource DLLs
-
-static HINSTANCE g_nonLocalizedResources	= NULL;
-static HINSTANCE g_localizedResources		= NULL;
-
-
-HINSTANCE	GetNonLocalizedResources()
-{
-	return g_nonLocalizedResources;
-}
-
-
-HINSTANCE	GetLocalizedResources()
-{
-	return g_localizedResources;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	Static Declarations
-//---------------------------------------------------------------------------------------------------------------------------
-DEFINE_GUID(CLSID_ControlPanel, 
-
-0x1207552c, 0xe59, 0x4d9f, 0x85, 0x54, 0xf1, 0xf8, 0x6, 0xcd, 0x7f, 0xa9);
-
-static LPCTSTR g_controlPanelGUID			=	TEXT( "{1207552C-0E59-4d9f-8554-F1F806CD7FA9}" );
-static LPCTSTR g_controlPanelName			=	TEXT( "Bonjour" );
-static LPCTSTR g_controlPanelCanonicalName	=	TEXT( "Apple.Bonjour" );
-static LPCTSTR g_controlPanelCategory		=	TEXT( "3,8" );
-
-static CCPApp theApp;
-
-//===========================================================================================================================
-//	MyRegDeleteKey
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus MyRegDeleteKey( HKEY hKeyRoot, LPTSTR lpSubKey )
-{
-    LPTSTR lpEnd;
-    OSStatus err;
-    DWORD dwSize;
-    TCHAR szName[MAX_PATH];
-    HKEY hKey;
-    FILETIME ftWrite;
-
-    // First, see if we can delete the key without having to recurse.
-
-    err = RegDeleteKey( hKeyRoot, lpSubKey );
-
-    if ( !err )
-	{
-		goto exit;
-	}
-
-    err = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
-	require_noerr( err, exit );
-
-    // Check for an ending slash and add one if it is missing.
-
-    lpEnd = lpSubKey + lstrlen(lpSubKey);
-
-    if ( *( lpEnd - 1 ) != TEXT( '\\' ) ) 
-    {
-        *lpEnd =  TEXT('\\');
-        lpEnd++;
-        *lpEnd =  TEXT('\0');
-    }
-
-    // Enumerate the keys
-
-    dwSize = MAX_PATH;
-    err = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
-
-    if ( !err ) 
-    {
-        do
-		{
-            lstrcpy (lpEnd, szName);
-
-            if ( !MyRegDeleteKey( hKeyRoot, lpSubKey ) )
-			{
-                break;
-            }
-
-            dwSize = MAX_PATH;
-
-            err = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
-
-        }
-		while ( !err );
-    }
-
-    lpEnd--;
-    *lpEnd = TEXT('\0');
-
-    RegCloseKey( hKey );
-
-    // Try again to delete the key.
-
-    err = RegDeleteKey(hKeyRoot, lpSubKey);
-	require_noerr( err, exit );
-
-exit:
-
-	return err;
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::CCPApp
-//---------------------------------------------------------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC(CCPApp, CWinApp);
-
-CCPApp::CCPApp()
-{
-	debug_initialize( kDebugOutputTypeWindowsEventLog, "DNS-SD Control Panel", GetModuleHandle( NULL ) );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelInfo );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CCPApp::~CCPApp
-//---------------------------------------------------------------------------------------------------------------------------
-
-CCPApp::~CCPApp()
-{
-}
-
-
-void
-CCPApp::Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath )
-{
-	typedef struct	RegistryBuilder		RegistryBuilder;
-	
-	struct	RegistryBuilder
-	{
-		HKEY		rootKey;
-		LPCTSTR		subKey;
-		LPCTSTR		valueName;
-		DWORD		valueType;
-		LPCTSTR		data;
-	};
-	
-	OSStatus			err;
-	size_t				n;
-	size_t				i;
-	HKEY				key;
-	TCHAR				keyName[ MAX_PATH ];
-	RegistryBuilder		entries[] = 
-	{
-		{ HKEY_LOCAL_MACHINE,	TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s" ),	NULL,									REG_SZ,		inName },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			NULL,									NULL,		NULL },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "System.ApplicationName" ),		REG_SZ,		inCanonicalName },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "System.ControlPanel.Category" ),	REG_SZ,		inCategory },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "LocalizedString" ),				REG_SZ,		inLocalizedName },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s" ),																			TEXT( "InfoTip" ),						REG_SZ,		inInfoTip },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\DefaultIcon" ),																NULL,									REG_SZ,		inIconPath },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell" ),																		NULL,									NULL,		NULL },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell\\Open" ),																NULL,									NULL,		NULL },
-		{ HKEY_CLASSES_ROOT,	TEXT( "CLSID\\%s\\Shell\\Open\\Command" ),														NULL,									REG_SZ,		inExePath }
-	};
-	DWORD				size;
-	
-	// Register the registry entries.
-
-	n = sizeof_array( entries );
-	for( i = 0; i < n; ++i )
-	{
-		StringCbPrintf( keyName, sizeof( keyName ), entries[ i ].subKey, inClsidString );
-		err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
-		require_noerr( err, exit );
-		
-		if ( entries[ i ].data )
-		{
-			size = (DWORD)( ( lstrlen( entries[ i ].data ) + 1 ) * sizeof( TCHAR ) );
-			err = RegSetValueEx( key, entries[ i ].valueName, 0, entries[ i ].valueType, (LPBYTE) entries[ i ].data, size );
-			require_noerr( err, exit );
-		}
-
-		RegCloseKey( key );
-	}
-	
-exit:
-	return;
-}
-
-
-//-----------------------------------------------------------
-//	CCPApp::Unregister
-//-----------------------------------------------------------
-void
-CCPApp::Unregister( LPCTSTR clsidString )
-{
-	TCHAR keyName[ MAX_PATH * 2 ];
-
-	StringCbPrintf( keyName, sizeof( keyName ), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s", clsidString );
-	MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
-
-	StringCbPrintf( keyName, sizeof( keyName ), L"CLSID\\%s", clsidString );
-	MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
-}
-
-
-
-//-----------------------------------------------------------
-//	CCPApp::InitInstance
-//-----------------------------------------------------------
-
-BOOL
-CCPApp::InitInstance()
-{
-	CCommandLineInfo	commandLine;
-	wchar_t				resource[MAX_PATH];
-	CString				errorMessage;
-	CString				errorCaption;
-	int					res;
-	OSStatus			err = kNoErr;
-
-	HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
-
-	//
-	// initialize the debugging framework
-	//
-	debug_initialize( kDebugOutputTypeWindowsDebugger, "ControlPanel", NULL );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelTrace );
-
-	// Before we load the resources, let's load the error string
-
-	errorMessage.LoadString( IDS_REINSTALL );
-	errorCaption.LoadString( IDS_REINSTALL_CAPTION );
-
-	res = PathForResource( NULL, L"ControlPanelResources.dll", resource, MAX_PATH );
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_nonLocalizedResources = LoadLibrary( resource );
-	translate_errno( g_nonLocalizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	res = PathForResource( NULL, L"ControlPanelLocalized.dll", resource, MAX_PATH );
-	err = translate_errno( res != 0, kUnknownErr, kUnknownErr );
-	require_noerr( err, exit );
-
-	g_localizedResources = LoadLibrary( resource );
-	translate_errno( g_localizedResources, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	AfxSetResourceHandle( g_localizedResources );
-
-	// InitCommonControls() is required on Windows XP if an application
-	// manifest specifies use of ComCtl32.dll version 6 or later to enable
-	// visual styles.  Otherwise, any window creation will fail.
-
-	InitCommonControls();
-
-	CWinApp::InitInstance();
-
-	AfxEnableControlContainer();
-
-	ParseCommandLine( commandLine );
-
-	if ( commandLine.m_nShellCommand == CCommandLineInfo::AppRegister )
-	{
-		CString		localizedName;
-		CString		toolTip;
-		TCHAR		iconPath[ MAX_PATH + 12 ]	= TEXT( "" );
-		TCHAR		exePath[ MAX_PATH ]			= TEXT( "" );
-		DWORD		nChars;
-		OSStatus	err;
-
-		nChars = GetModuleFileName( NULL, exePath, sizeof_array( exePath ) );
-
-		err = translate_errno( nChars > 0, (OSStatus) GetLastError(), kUnknownErr );
-
-		require_noerr( err, exit );
-
-		StringCbPrintf( iconPath, sizeof( iconPath ), L"%s,-%d", exePath, IDR_APPLET );
-
-		localizedName.LoadString( IDS_APPLET_NAME );
-		toolTip.LoadString( IDS_APPLET_TOOLTIP );
-
-		Register( g_controlPanelGUID, g_controlPanelName, g_controlPanelCanonicalName, g_controlPanelCategory, localizedName, toolTip, iconPath, exePath );
-	}
-	else if ( commandLine.m_nShellCommand == CCommandLineInfo::AppUnregister )
-	{
-		Unregister( g_controlPanelGUID );
-	}
-	else
-	{
-		CString					name;
-		CConfigPropertySheet	dlg;
-		
-		name.LoadString( IDR_APPLET );
-		dlg.Construct( name, NULL, 0 );
-
-		m_pMainWnd = &dlg;
-
-		try
-		{
-			INT_PTR nResponse = dlg.DoModal();
-		
-			if (nResponse == IDOK)
-			{
-				// TODO: Place code here to handle when the dialog is
-				//  dismissed with OK
-			}
-			else if (nResponse == IDCANCEL)
-			{
-				// TODO: Place code here to handle when the dialog is
-				//  dismissed with Cancel
-			}
-		}
-		catch (...)
-		{
-			MessageBox(NULL, L"", L"", MB_OK|MB_ICONEXCLAMATION);
-		}
-	}
-
-	if ( err )
-	{
-		MessageBox( NULL, L"", L"", MB_ICONERROR | MB_OK );
-	}
-
-exit:
-
-	if ( err )
-	{
-		MessageBox( NULL, errorMessage, errorCaption, MB_ICONERROR | MB_OK );
-	}
-
-	// Since the dialog has been closed, return FALSE so that we exit the
-	//  application, rather than start the application's message pump.
-	return FALSE;
-}
diff --git a/mDNSWindows/ControlPanel/ControlPanelExe.h b/mDNSWindows/ControlPanel/ControlPanelExe.h
deleted file mode 100644
index 865ebc1..0000000
--- a/mDNSWindows/ControlPanel/ControlPanelExe.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2007 Apple 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.
- */
-
-    
-#pragma once
-
-#include "stdafx.h"
-
-extern HINSTANCE	GetNonLocalizedResources();
-extern HINSTANCE	GetLocalizedResources();
-
-//-------------------------------------------------
-//	CCPApp
-//-------------------------------------------------
-
-class CCPApp : public CWinApp
-{
-public:
-
-	CCPApp();
-	virtual ~CCPApp();
-
-protected:
-
-	virtual BOOL    InitInstance();
-
-	void
-	Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName, LPCTSTR inCategory, LPCTSTR inLocalizedName, LPCTSTR inInfoTip, LPCTSTR inIconPath, LPCTSTR inExePath );
-
-	void
-	Unregister( LPCTSTR clsidString );
-
-	DECLARE_DYNAMIC(CCPApp);
-};
diff --git a/mDNSWindows/ControlPanel/FourthPage.cpp b/mDNSWindows/ControlPanel/FourthPage.cpp
deleted file mode 100644
index 7ded08f..0000000
--- a/mDNSWindows/ControlPanel/FourthPage.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "FourthPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-#include "SharedSecret.h"
-
-#include <WinServices.h>
-    
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CFourthPage, CPropertyPage)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::CFourthPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CFourthPage::CFourthPage()
-:
-	CPropertyPage(CFourthPage::IDD)
-{
-	//{{AFX_DATA_INIT(CFourthPage)
-	//}}AFX_DATA_INIT
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::~CFourthPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CFourthPage::~CFourthPage()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFourthPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CFourthPage)
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_POWER_MANAGEMENT, m_checkBox);
-}
-
-BEGIN_MESSAGE_MAP(CFourthPage, CPropertyPage)
-	//{{AFX_MSG_MAP(CFourthPage)
-	//}}AFX_MSG_MAP
-
-	ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CFourthPage::OnBnClickedPowerManagement)
-
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CFourthPage::SetModified( BOOL bChanged )
-{
-	m_modified = bChanged;
-
-	CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CFourthPage::OnSetActive()
-{
-	CConfigPropertySheet	*	psheet;
-	HKEY						key = NULL;
-	DWORD						dwSize;
-	DWORD						enabled;
-	DWORD						err;
-	BOOL						b = CPropertyPage::OnSetActive();
-
-	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	m_checkBox.SetCheck( 0 );
-
-	// Now populate the browse domain box
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	dwSize = sizeof( DWORD );
-	err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-	require_noerr( err, exit );
-
-	m_checkBox.SetCheck( enabled );
- 
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFourthPage::OnOK()
-{
-	if ( m_modified )
-	{
-		Commit();
-	}
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CFourthPage::Commit()
-{
-	HKEY		key		= NULL;
-	DWORD		enabled;
-	DWORD		err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	enabled = m_checkBox.GetCheck();
-	err = RegSetValueEx( key, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
-	require_noerr( err, exit );
-	
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage::OnBnClickedRemoveBrowseDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-
-
-void CFourthPage::OnBnClickedPowerManagement()
-
-{
-
-	char buf[ 256 ];
-
-
-
-	snprintf( buf, sizeof( buf ), "check box: %d", m_checkBox.GetCheck() );
-
-	OutputDebugStringA( buf );
-
-	// TODO: Add your control notification handler code here
-
-
-
-	SetModified( TRUE );
-
-}
-
diff --git a/mDNSWindows/ControlPanel/FourthPage.h b/mDNSWindows/ControlPanel/FourthPage.h
deleted file mode 100644
index d595291..0000000
--- a/mDNSWindows/ControlPanel/FourthPage.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include <list>
-#include "afxcmn.h"
-
-#include "afxwin.h"
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CFourthPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CFourthPage : public CPropertyPage
-{
-public:
-	CFourthPage();
-	~CFourthPage();
-
-protected:
-
-	//{{AFX_DATA(CFourthPage)
-	enum { IDD = IDR_APPLET_PAGE4 };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CFourthPage)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CFourthPage)
-
-	//{{AFX_MSG(CFourthPage)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-	
-private:
-	
-	typedef std::list<CString> StringList;
-
-	afx_msg BOOL
-	OnSetActive();
-	
-	afx_msg void
-	OnOK();
-	
-	void
-	SetModified( BOOL bChanged = TRUE );
-	
-	void
-	Commit();
-
-	BOOL			m_modified;
-
-public:
-private:
-
-	CButton m_checkBox;
-
-public:
-
-
-	afx_msg void OnBnClickedPowerManagement();
-
-};
diff --git a/mDNSWindows/ControlPanel/RegistrationPage.cpp b/mDNSWindows/ControlPanel/RegistrationPage.cpp
deleted file mode 100644
index 55755f0..0000000
--- a/mDNSWindows/ControlPanel/RegistrationPage.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include <Secret.h>
-#include "RegistrationPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-extern "C"
-{
-#include <ClientCommon.h>
-}
-#include <WinServices.h>
-
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CRegistrationPage, CPropertyPage)
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::CRegistrationPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CRegistrationPage::CRegistrationPage()
-:
-	CPropertyPage(CRegistrationPage::IDD),
-	m_ignoreChanges( false ),
-	m_hostnameSetupKey( NULL ),
-	m_registrationSetupKey( NULL ),
-	m_statusKey( NULL )
-{
-	//{{AFX_DATA_INIT(CRegistrationPage)
-	//}}AFX_DATA_INIT
-
-	OSStatus err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\Hostnames", 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_hostnameSetupKey, NULL );
-	check_noerr( err );
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_registrationSetupKey, NULL );
-	check_noerr( err );
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_statusKey, NULL );
-	check_noerr( err );
-
-	
-}
-
-CRegistrationPage::~CRegistrationPage()
-{
-	if ( m_hostnameSetupKey )
-	{
-		RegCloseKey( m_hostnameSetupKey );
-		m_hostnameSetupKey = NULL;
-	}
-
-	if ( m_registrationSetupKey )
-	{
-		RegCloseKey( m_registrationSetupKey );
-		m_registrationSetupKey = NULL;
-	}
-
-	if ( m_statusKey )
-	{
-		RegCloseKey( m_statusKey );
-		m_statusKey = NULL;
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CRegistrationPage)
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_HOSTNAME, m_hostnameControl);
-	DDX_Control(pDX, IDC_USERNAME, m_usernameControl);
-	DDX_Control(pDX, IDC_PASSWORD, m_passwordControl);
-	DDX_Control(pDX, IDC_ADVERTISE_SERVICES, m_advertiseServices);
-}
-
-BEGIN_MESSAGE_MAP(CRegistrationPage, CPropertyPage)
-	//{{AFX_MSG_MAP(CRegistrationPage)
-	//}}AFX_MSG_MAP
-	ON_EN_CHANGE(IDC_HOSTNAME, OnEnChangeHostname)
-	ON_EN_CHANGE(IDC_USERNAME, OnEnChangeUsername)
-	ON_EN_CHANGE(IDC_PASSWORD, OnEnChangePassword)
-	ON_BN_CLICKED(IDC_ADVERTISE_SERVICES, OnBnClickedAdvertiseServices)
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnEnChangedHostname
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::OnEnChangeHostname()
-{
-	if ( !m_ignoreChanges )
-	{
-		SetModified( TRUE );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnEnChangedUsername
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::OnEnChangeUsername()
-{
-	if ( !m_ignoreChanges )
-	{
-		SetModified( TRUE );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnEnChangedPassword
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::OnEnChangePassword()
-{
-	if ( !m_ignoreChanges )
-	{
-		SetModified( TRUE );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnBnClickedAdvertiseServices
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::OnBnClickedAdvertiseServices()
-{
-	if ( !m_ignoreChanges )
-	{
-		SetModified( TRUE );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CRegistrationPage::SetModified( BOOL bChanged )
-{
-	m_modified = bChanged ? true : false;
-
-	CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CRegistrationPage::OnSetActive()
-{
-	TCHAR	name[kDNSServiceMaxDomainName + 1];
-	DWORD	nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR );
-	DWORD	err;
-
-	BOOL b = CPropertyPage::OnSetActive();
-
-	m_ignoreChanges = true;
-	m_modified = FALSE;
-	
-	if ( m_hostnameSetupKey )
-	{
-		err = RegQueryValueEx( m_hostnameSetupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen );
-
-		if ( !err )
-		{
-			char	hostnameUTF8[ 256 ];
-			char	outDomain[ 256 ];
-			char	outUsername[ 256 ];
-			char	outPassword[ 256 ];
-			CString hostname = name;
-			CString username;
-			CString password;
-
-			m_hostnameControl.SetWindowText( hostname );
-
-			StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );
-
-			if ( LsaGetSecret( hostnameUTF8, outDomain, sizeof( outDomain ) / sizeof( TCHAR ), outUsername, sizeof( outUsername ) / sizeof( TCHAR ), outPassword, sizeof( outPassword ) / sizeof( TCHAR ) ) )
-			{
-				username = outUsername;
-				m_usernameControl.SetWindowText( username );
-
-				password = outPassword;
-				m_passwordControl.SetWindowText( password );
-			}
-		}
-	}
-
-	m_advertiseServices.SetCheck( 0 );
-
-	if ( m_registrationSetupKey )
-	{
-		HKEY		subKey = NULL;
-		DWORD		dwSize;
-		DWORD		enabled = 0;
-		TCHAR		subKeyName[MAX_KEY_LENGTH];
-		DWORD		cSubKeys = 0;
-		DWORD		cbMaxSubKey;
-		DWORD		cchMaxClass;
-		OSStatus	err;
-
-		err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-		if ( !err )
-		{
-			if ( cSubKeys > 0 )
-			{	
-				dwSize = MAX_KEY_LENGTH;
-	            
-				err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-				if ( !err )
-				{
-					err = RegOpenKey( m_registrationSetupKey, subKeyName, &subKey );
-					if ( !err )
-					{
-						dwSize = sizeof( DWORD );
-						err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-						if ( !err && enabled )
-						{
-							m_advertiseServices.SetCheck( enabled );
-						}
-
-						RegCloseKey( subKey );
-						subKey = NULL;
-					}
-				}
-			}
-		}
-	}
-
-	m_ignoreChanges = false;
-
-	return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CRegistrationPage::OnOK()
-{
-	if ( m_modified )
-	{
-		Commit();
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CRegistrationPage::Commit()
-{
-	CString	hostname;
-	char	hostnameUTF8[ 256 ];
-	CString username;
-	char	usernameUTF8[ 256 ];
-	CString password;
-	char	passwordUTF8[ 256 ];
-	DWORD	enabled = 1;
-	BOOL	secret = FALSE;
-	DWORD	err;
-
-	m_hostnameControl.GetWindowText( hostname );
-	hostname.MakeLower();
-	hostname.TrimRight( '.' );
-	StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );
-	
-	m_usernameControl.GetWindowText( username );
-	m_passwordControl.GetWindowText( password );
-	
-	if ( username.GetLength() && password.GetLength() )
-	{
-		StringObjectToUTF8String( username, usernameUTF8, sizeof( usernameUTF8 ) );	
-		StringObjectToUTF8String( password, passwordUTF8, sizeof( passwordUTF8 ) );
-		secret = TRUE;
-	}
-
-	if ( m_hostnameSetupKey != NULL )
-	{
-		err = RegSetValueEx( m_hostnameSetupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) hostname, ( hostname.GetLength() + 1 ) * sizeof( TCHAR ) );
-		require_noerr( err, exit );
-		
-		err = RegSetValueEx( m_hostnameSetupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
-		require_noerr( err, exit );
-
-		if ( secret )
-		{
-			LsaSetSecret( hostnameUTF8, usernameUTF8, passwordUTF8 );
-		}
-	}
-
-	if ( m_registrationSetupKey != NULL )
-	{
-		TCHAR		subKeyName[MAX_KEY_LENGTH];
-		DWORD		cSubKeys = 0;
-		DWORD		cbMaxSubKey;
-		DWORD		cchMaxClass;
-		DWORD		dwSize;
-		int			i;
-		OSStatus	err = kNoErr;
-
-		// First, remove all the entries that are there
-
-		err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-		if ( !err )
-		{
-			for ( i = 0; i < (int) cSubKeys; i++ )
-			{	
-				dwSize = MAX_KEY_LENGTH;
-		            
-				err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-				require_noerr( err, exit );
-					
-				err = RegDeleteKey( m_registrationSetupKey, subKeyName );
-				require_noerr( err, exit );
-			}
-		}
-
-		if ( m_advertiseServices.GetCheck() )
-		{
-			const char	* domainUTF8;
-			CString		  domain;
-			char		  label[ 64 ];
-			HKEY		  subKey = NULL;
-
-			domainUTF8	= GetNextLabel( hostnameUTF8, label );
-			domain		= domainUTF8;
-
-			err = RegCreateKeyEx( m_registrationSetupKey, domain, 0,
-									 NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &subKey, NULL );
-			if ( !err )
-			{
-				err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
-				check_noerr( err );
-
-				RegCloseKey( subKey );
-				subKey = NULL;
-			}
-
-			if ( secret )
-			{
-				LsaSetSecret( domainUTF8, usernameUTF8, passwordUTF8 );
-			}
-		}
-	}
-
-exit:
-
-	return;
-}
diff --git a/mDNSWindows/ControlPanel/RegistrationPage.h b/mDNSWindows/ControlPanel/RegistrationPage.h
deleted file mode 100644
index 935a418..0000000
--- a/mDNSWindows/ControlPanel/RegistrationPage.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-#include <DebugServices.h>
-#include "afxwin.h"
-
-    
-//---------------------------------------------------------------------------------------------------------------------------
-//	CRegistrationPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CRegistrationPage : public CPropertyPage
-{
-public:
-	CRegistrationPage();
-	~CRegistrationPage();
-
-protected:
-	//{{AFX_DATA(CRegistrationPage)
-	enum { IDD = IDR_APPLET_PAGE1 };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CRegistrationPage)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CRegistrationPage)
-
-	//{{AFX_MSG(CRegistrationPage)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-
-private:
-
-	afx_msg BOOL	OnSetActive();
-	afx_msg void	OnOK();
-
-	void			SetModified( BOOL bChanged = TRUE );
-	void			Commit();
-
-	CEdit			m_hostnameControl;
-	CEdit			m_usernameControl;
-	CEdit			m_passwordControl;
-	CButton			m_advertiseServices;
-	bool			m_ignoreChanges;
-	bool			m_modified;
-	HKEY			m_hostnameSetupKey;
-	HKEY			m_registrationSetupKey;
-	HKEY			m_statusKey;
-	
-public:
-	
-	afx_msg void OnEnChangeHostname();
-	afx_msg void OnEnChangeUsername();
-	afx_msg void OnEnChangePassword();
-	afx_msg void OnBnClickedAdvertiseServices();
-};
diff --git a/mDNSWindows/ControlPanel/SecondPage.cpp b/mDNSWindows/ControlPanel/SecondPage.cpp
deleted file mode 100644
index b6cf4ff..0000000
--- a/mDNSWindows/ControlPanel/SecondPage.cpp
+++ /dev/null
@@ -1,544 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "SecondPage.h"
-#include "resource.h"
-
-#include "ConfigPropertySheet.h"
-#include "SharedSecret.h"
-
-#include <WinServices.h>
-    
-#define MAX_KEY_LENGTH 255
-
-IMPLEMENT_DYNCREATE(CSecondPage, CPropertyPage)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::CSecondPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CSecondPage::CSecondPage()
-:
-	CPropertyPage(CSecondPage::IDD),
-	m_setupKey( NULL )
-{
-	//{{AFX_DATA_INIT(CSecondPage)
-	//}}AFX_DATA_INIT
-
-	OSStatus err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_setupKey, NULL );
-	check_noerr( err );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::~CSecondPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CSecondPage::~CSecondPage()
-{
-	if ( m_setupKey )
-	{
-		RegCloseKey( m_setupKey );
-		m_setupKey = NULL;
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CSecondPage)
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_CHECK1, m_advertiseServicesButton);
-	DDX_Control(pDX, IDC_BUTTON1, m_sharedSecretButton);
-	DDX_Control(pDX, IDC_COMBO2, m_regDomainsBox);
-}
-
-BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
-	//{{AFX_MSG_MAP(CSecondPage)
-	//}}AFX_MSG_MAP
-	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedSharedSecret)
-	ON_BN_CLICKED(IDC_CHECK1, OnBnClickedAdvertise)
-	ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelChange)
-	ON_CBN_EDITCHANGE(IDC_COMBO1, OnCbnEditChange)
-	ON_CBN_EDITCHANGE(IDC_COMBO2, OnCbnEditChange)
-	ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelChange)
-	
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::SetModified( BOOL bChanged )
-{
-	m_modified = bChanged;
-
-	CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CSecondPage::OnSetActive()
-{
-	CConfigPropertySheet	*	psheet;
-	DWORD						err;
-	BOOL						b = CPropertyPage::OnSetActive();
-
-	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-	require_quiet( psheet, exit );
-	
-	m_modified = FALSE;
-
-	// Clear out what's there
-
-	EmptyComboBox( m_regDomainsBox );
-
-	// Now populate the registration domain box
-
-	err = Populate( m_regDomainsBox, m_setupKey, psheet->m_regDomains );
-	check_noerr( err );
-
-exit:
-
-	return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSecondPage::OnOK()
-{
-	if ( m_modified )
-	{
-		Commit();
-	}
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSecondPage::Commit()
-{
-	DWORD err;
-
-	if ( m_setupKey != NULL )
-	{
-		err = Commit( m_regDomainsBox, m_setupKey, m_advertiseServicesButton.GetCheck() == BST_CHECKED );
-		check_noerr( err );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CSecondPage::Commit( CComboBox & box, HKEY key, DWORD enabled )
-{
-	CString		selected;
-	HKEY		subKey	= NULL;
-	TCHAR		subKeyName[MAX_KEY_LENGTH];
-	DWORD		cSubKeys = 0;
-	DWORD		cbMaxSubKey;
-	DWORD		cchMaxClass;
-	DWORD		dwSize;
-	int			i;
-	OSStatus	err = kNoErr;
-
-	// First, remove all the entries that are there
-
-    err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	for ( i = 0; i < (int) cSubKeys; i++ )
-	{	
-		dwSize = MAX_KEY_LENGTH;
-            
-		err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-		require_noerr( err, exit );
-			
-		err = RegDeleteKey( key, subKeyName );
-		require_noerr( err, exit );
-	}
-
-	// Get selected text
-	
-	box.GetWindowText( selected );
-	
-	// If we haven't seen this string before, add the string to the box and
-	// the registry
-	
-	if ( ( selected.GetLength() > 0 ) && ( box.FindStringExact( -1, selected ) == CB_ERR ) )
-	{
-		CString string;
-
-		box.AddString( selected );
-
-		err = RegQueryString( key, L"UserDefined", string );
-		check_noerr( err );
-
-		if ( string.GetLength() )
-		{
-			string += L"," + selected;
-		}
-		else
-		{
-			string = selected;
-		}
-
-		err = RegSetValueEx( key, L"UserDefined", 0, REG_SZ, (LPBYTE) (LPCTSTR) string, ( string.GetLength() + 1) * sizeof( TCHAR ) );
-		check_noerr ( err );
-	}
-
-	// Save selected text in registry.  This will trigger mDNSResponder to setup
-	// DynDNS config again
-
-	err = RegCreateKeyEx( key, selected, 0,
-	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &subKey, NULL );
-	require_noerr( err, exit );
-
-	err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
-	check_noerr( err );
-
-exit:
-
-	if ( subKey )
-	{
-		RegCloseKey( subKey );
-		subKey = NULL;
-	}
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnBnClickedSharedSecret
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::OnBnClickedSharedSecret()
-{
-	CString name;
-
-	m_regDomainsBox.GetWindowText( name );
-
-	CSharedSecret dlg;
-
-	dlg.Load( name );
-
-	if ( dlg.DoModal() == IDOK )
-	{
-		DWORD		wakeup = 0;
-		DWORD		dwSize = sizeof( DWORD );
-		OSStatus	err;
-
-		dlg.Commit( name );
-
-		// We have now updated the secret, however the system service
-		// doesn't know about it yet.  So we're going to update the
-		// registry with a dummy value which will cause the system
-		// service to re-initialize it's DynDNS setup
-		//
-
-		RegQueryValueEx( m_setupKey, L"Wakeup", NULL, NULL, (LPBYTE) &wakeup, &dwSize );      
-
-		wakeup++;
-		
-		err = RegSetValueEx( m_setupKey, L"Wakeup", 0, REG_DWORD, (LPBYTE) &wakeup, sizeof( DWORD ) );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnBnClickedAdvertise
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::OnBnClickedAdvertise()
-{
-	int state;
-
-	state = m_advertiseServicesButton.GetCheck();
-
-	m_regDomainsBox.EnableWindow( state );
-	m_sharedSecretButton.EnableWindow( state );
-
-	SetModified( TRUE );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnCbnSelChange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::OnCbnSelChange()
-{
-	SetModified( TRUE );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnCbnEditChange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSecondPage::OnCbnEditChange()
-{
-	SetModified( TRUE );
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnAddRegistrationDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSecondPage::OnAddRegistrationDomain( CString & domain )
-{
-	int index = m_regDomainsBox.FindStringExact( -1, domain );
-
-	if ( index == CB_ERR )
-	{
-		m_regDomainsBox.AddString( domain );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::OnRemoveRegistrationDomain
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSecondPage::OnRemoveRegistrationDomain( CString & domain )
-{
-	int index = m_regDomainsBox.FindStringExact( -1, domain );
-
-	if ( index != CB_ERR )
-	{
-		m_regDomainsBox.DeleteString( index );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::EmptyComboBox
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSecondPage::EmptyComboBox( CComboBox & box )
-{
-	while ( box.GetCount() > 0 )
-	{
-		box.DeleteString( 0 );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::Populate
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CSecondPage::Populate( CComboBox & box, HKEY key, StringList & l )
-{
-	CString		string;
-	HKEY		subKey = NULL;
-	DWORD		dwSize;
-	DWORD		enabled = 0;
-	TCHAR		subKeyName[MAX_KEY_LENGTH];
-	DWORD		cSubKeys = 0;
-	DWORD		cbMaxSubKey;
-	DWORD		cchMaxClass;
-	OSStatus	err;
-
-	err = RegQueryString( key, L"UserDefined", string );
-
-	if ( !err && string.GetLength() )
-	{
-		bool done = false;
-
-		while ( !done )
-		{
-			CString tok;
-
-			tok = string.SpanExcluding( L"," );
-
-			box.AddString( tok );
-
-			if ( tok != string )
-			{
-				// Get rid of that string and comma
-
-				string = string.Right( string.GetLength() - tok.GetLength() - 1 );
-			}
-			else
-			{
-				done = true;
-			}
-		}
-	}
-
-	StringList::iterator it;
-
-	for ( it = l.begin(); it != l.end(); it++ )
-	{
-		if ( box.FindStringExact( -1, *it ) == CB_ERR )
-		{
-			box.AddString( *it );
-		}
-	}
-
-	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	if ( cSubKeys > 0 )
-	{	
-		dwSize = MAX_KEY_LENGTH;
-            
-		err = RegEnumKeyEx( key, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-		require_noerr( err, exit );
-
-		err = RegOpenKey( key, subKeyName, &subKey );
-		require_noerr( err, exit );
-
-		dwSize = sizeof( DWORD );
-		err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-		require_noerr( err, exit );
-
-		// See if it's there
-
-		if ( box.SelectString( -1, subKeyName ) == CB_ERR )
-		{
-			// If not, add it
-
-			box.AddString( subKeyName );
-		}
-
-		box.SelectString( -1, subKeyName );
-
-		RegCloseKey( subKey );
-		subKey = NULL;
-	}
-
-exit:
-
-	m_advertiseServicesButton.SetCheck( ( !err && enabled ) ? BST_CHECKED : BST_UNCHECKED );
-	m_regDomainsBox.EnableWindow( ( !err && enabled ) );
-	m_sharedSecretButton.EnableWindow( (!err && enabled ) );
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::CreateKey
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CSecondPage::CreateKey( CString & name, DWORD enabled )
-{
-	HKEY		key = NULL;
-	OSStatus	err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR) name, 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	err = RegSetValueEx( key, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
-	check_noerr( err );
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return err;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage::RegQueryString
-//---------------------------------------------------------------------------------------------------------------------------
-
-OSStatus
-CSecondPage::RegQueryString( HKEY key, CString valueName, CString & value )
-{
-	TCHAR	*	string;
-	DWORD		stringLen;
-	int			i;
-	OSStatus	err;
-
-	stringLen	= 1024;
-	string		= NULL;
-	i			= 0;
-
-	do
-	{
-		if ( string )
-		{
-			free( string );
-		}
-
-		string = (TCHAR*) malloc( stringLen );
-		require_action( string, exit, err = kUnknownErr );
-		*string = '\0';
-
-		err = RegQueryValueEx( key, valueName, 0, NULL, (LPBYTE) string, &stringLen );
-
-		i++;
-	}
-	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
-
-	value = string;
-
-exit:
-
-	if ( string )
-	{
-		free( string );
-	}
-
-	return err;
-}
diff --git a/mDNSWindows/ControlPanel/SecondPage.h b/mDNSWindows/ControlPanel/SecondPage.h
deleted file mode 100644
index 3bd9e74..0000000
--- a/mDNSWindows/ControlPanel/SecondPage.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include <list>
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSecondPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CSecondPage : public CPropertyPage
-{
-public:
-	CSecondPage();
-	~CSecondPage();
-
-protected:
-
-	//{{AFX_DATA(CSecondPage)
-	enum { IDD = IDR_APPLET_PAGE2 };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CSecondPage)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CSecondPage)
-
-	//{{AFX_MSG(CSecondPage)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-public:
-	
-	afx_msg void	OnBnClickedSharedSecret();
-	afx_msg void	OnBnClickedAdvertise();
-
-	void			OnAddRegistrationDomain( CString & domain );
-	void			OnRemoveRegistrationDomain( CString & domain );
-	
-private:
-	
-	typedef std::list<CString> StringList;
-
-	afx_msg BOOL
-	OnSetActive();
-	
-	afx_msg void
-	OnOK();
-
-	void
-	EmptyComboBox
-			(
-			CComboBox	&	box
-			);
-
-	OSStatus
-	Populate(
-			CComboBox	&	box,
-			HKEY			key,
-			StringList	&	l
-			);
-	
-	void
-	SetModified( BOOL bChanged = TRUE );
-	
-	void
-	Commit();
-
-	OSStatus
-	Commit( CComboBox & box, HKEY key, DWORD enabled );
-
-	OSStatus
-	CreateKey( CString & name, DWORD enabled );
-
-	OSStatus
-	RegQueryString( HKEY key, CString valueName, CString & value );
-
-	CComboBox		m_regDomainsBox;
-	CButton			m_advertiseServicesButton;
-	CButton			m_sharedSecretButton;
-	BOOL			m_modified;
-	HKEY			m_setupKey;
-
-public:
-	afx_msg void OnCbnSelChange();
-	afx_msg void OnCbnEditChange();
-}; 
diff --git a/mDNSWindows/ControlPanel/ServicesPage.cpp b/mDNSWindows/ControlPanel/ServicesPage.cpp
deleted file mode 100644
index 4269fa6..0000000
--- a/mDNSWindows/ControlPanel/ServicesPage.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "ServicesPage.h"
-#include "resource.h"
-
-#include "ControlPanelExe.h"
-#include "ConfigPropertySheet.h"
-
-#include <WinServices.h>
-    
-#define MAX_KEY_LENGTH 255
-
-
-IMPLEMENT_DYNCREATE(CServicesPage, CPropertyPage)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::CServicesPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CServicesPage::CServicesPage()
-:
-	CPropertyPage(CServicesPage::IDD)
-{
-	//{{AFX_DATA_INIT(CServicesPage)
-	//}}AFX_DATA_INIT
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::~CServicesPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-CServicesPage::~CServicesPage()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CServicesPage::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(CServicesPage)
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_ADVERTISE_SMB, m_SMBCheckBox);
-	DDX_Control(pDX, IDC_POWER_MANAGEMENT, m_powerManagementCheckBox);
-}
-
-BEGIN_MESSAGE_MAP(CServicesPage, CPropertyPage)
-	//{{AFX_MSG_MAP(CServicesPage)
-	//}}AFX_MSG_MAP
-
-	ON_BN_CLICKED(IDC_ADVERTISE_SMB, &CServicesPage::OnBnClickedAdvertiseSMB)
-	ON_BN_CLICKED(IDC_POWER_MANAGEMENT, &CServicesPage::OnBnClickedPowerManagement)
-
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::SetModified
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CServicesPage::SetModified( BOOL bChanged )
-{
-	m_modified = bChanged;
-
-	CPropertyPage::SetModified( bChanged );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::OnSetActive
-//---------------------------------------------------------------------------------------------------------------------------
-
-BOOL
-CServicesPage::OnSetActive()
-{
-	CConfigPropertySheet	*	psheet;
-	HKEY						key = NULL;
-	DWORD						dwSize;
-	DWORD						enabled;
-	DWORD						err;
-	BOOL						b = CPropertyPage::OnSetActive();
-
-	psheet = reinterpret_cast<CConfigPropertySheet*>(GetParent());
-	require_quiet( psheet, exit );
-
-	m_SMBCheckBox.SetCheck( 0 );
-
-	// Now populate the browse domain box
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	dwSize = sizeof( DWORD );
-	err = RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-	require_noerr( err, exit );
-
-	m_SMBCheckBox.SetCheck( enabled );
-
-	RegCloseKey( key );
-	key = NULL;
-
-	m_powerManagementCheckBox.SetCheck( 0 );
-
-	// Now populate the browse domain box
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	dwSize = sizeof( DWORD );
-	err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-	require_noerr( err, exit );
-
-	m_powerManagementCheckBox.SetCheck( enabled );
- 
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return b;
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::OnOK
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CServicesPage::OnOK()
-{
-	if ( m_modified )
-	{
-		Commit();
-	}
-}
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CServicesPage::Commit()
-{
-	HKEY		key		= NULL;
-	DWORD		enabled;
-	DWORD		err;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", 0,
-	                   	NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	enabled = m_SMBCheckBox.GetCheck();
-	err = RegSetValueEx( key, L"Advertise", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
-	require_noerr( err, exit );
-
-	RegCloseKey( key );
-	key = NULL;
-
-	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Power Management", 0,
-		                  NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &key, NULL );
-	require_noerr( err, exit );
-
-	enabled = m_powerManagementCheckBox.GetCheck();
-	err = RegSetValueEx( key, L"Enabled", NULL, REG_DWORD, (LPBYTE) &enabled, sizeof( enabled ) );
-	require_noerr( err, exit );
-	
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::OnBnClickedAdvertiseSMB
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CServicesPage::OnBnClickedAdvertiseSMB()
-{
-	SetModified( TRUE );
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage::OnBnClickedPowerManagement
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CServicesPage::OnBnClickedPowerManagement()
-{
-	SetModified( TRUE );
-
-	if ( m_powerManagementCheckBox.GetCheck() )
-	{
-		CPowerManagementWarning dlg( GetParent() );
-
-		dlg.DoModal();
-	}
-}
-
-
-// CPowerManagementWarning dialog
-
-IMPLEMENT_DYNAMIC(CPowerManagementWarning, CDialog)
-CPowerManagementWarning::CPowerManagementWarning(CWnd* pParent /*=NULL*/)
-	: CDialog(CPowerManagementWarning::IDD, pParent)
-{
-}
-
-CPowerManagementWarning::~CPowerManagementWarning()
-{
-}
-
-void CPowerManagementWarning::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_ENERGY_SAVER, m_energySaverIcon);
-}
-
-
-BOOL
-CPowerManagementWarning::OnInitDialog()
-{	
-	BOOL b = CDialog::OnInitDialog();
-
-	const HICON hIcon = ( HICON ) ::LoadImage( GetNonLocalizedResources(), MAKEINTRESOURCE( IDI_ENERGY_SAVER ), IMAGE_ICON, 0, 0, 0);
-	
-	if ( hIcon )
-	{
-		m_energySaverIcon.SetIcon( hIcon );
-	}
-
-	return b;
-}
-
-
-void
-CPowerManagementWarning::OnOK()
-{
-	CDialog::OnOK();
-}
-
-
-BEGIN_MESSAGE_MAP(CPowerManagementWarning, CDialog)
-END_MESSAGE_MAP()
-
diff --git a/mDNSWindows/ControlPanel/ServicesPage.h b/mDNSWindows/ControlPanel/ServicesPage.h
deleted file mode 100644
index d593a72..0000000
--- a/mDNSWindows/ControlPanel/ServicesPage.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include "stdafx.h"
-#include "resource.h"
-
-#include <DebugServices.h>
-#include <list>
-#include "afxcmn.h"
-
-#include "afxwin.h"
-
-
-
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CServicesPage
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CServicesPage : public CPropertyPage
-{
-public:
-	CServicesPage();
-	~CServicesPage();
-
-protected:
-
-	//{{AFX_DATA(CServicesPage)
-	enum { IDD = IDR_APPLET_PAGE5 };
-	//}}AFX_DATA
-
-	//{{AFX_VIRTUAL(CServicesPage)
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-	DECLARE_DYNCREATE(CServicesPage)
-
-	//{{AFX_MSG(CServicesPage)
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-	
-private:
-	
-	typedef std::list<CString> StringList;
-
-	afx_msg BOOL
-	OnSetActive();
-	
-	afx_msg void
-	OnOK();
-	
-	void
-	SetModified( BOOL bChanged = TRUE );
-	
-	void
-	Commit();
-
-	BOOL			m_modified;
-
-public:
-private:
-
-	CButton m_SMBCheckBox;
-	CButton m_powerManagementCheckBox;
-
-public:
-
-
-	afx_msg void OnBnClickedAdvertiseSMB();
-	afx_msg void OnBnClickedPowerManagement();
-};
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CPowerManagementWarning
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CPowerManagementWarning : public CDialog
-{
-	DECLARE_DYNAMIC(CPowerManagementWarning)
-
-public:
-
-	CPowerManagementWarning(CWnd* pParent = NULL);   // standard constructor
-
-	virtual ~CPowerManagementWarning();
-
-// Dialog Data
-
-	enum { IDD = IDR_POWER_MANAGEMENT_WARNING };
-
-protected:
-
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-
-	virtual BOOL OnInitDialog();
-
-	virtual void OnOK();
-
-	DECLARE_MESSAGE_MAP()
-
-public:
-
-	CStatic m_energySaverIcon;
-};
-
diff --git a/mDNSWindows/ControlPanel/SharedSecret.cpp b/mDNSWindows/ControlPanel/SharedSecret.cpp
deleted file mode 100644
index 3d19295..0000000
--- a/mDNSWindows/ControlPanel/SharedSecret.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-    
-// SharedSecret.cpp : implementation file
-//
-
-
-#include <Secret.h>
-#include "stdafx.h"
-#include "SharedSecret.h"
-#include <WinServices.h>
-
-#include <DebugServices.h>
-
-
-// SharedSecret dialog
-
-IMPLEMENT_DYNAMIC(CSharedSecret, CDialog)
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret::CSharedSecret
-//---------------------------------------------------------------------------------------------------------------------------
-
-CSharedSecret::CSharedSecret(CWnd* pParent /*=NULL*/)
-	: CDialog(CSharedSecret::IDD, pParent)
-	, m_key(_T(""))
-	, m_secret(_T(""))
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret::~CSharedSecret
-//---------------------------------------------------------------------------------------------------------------------------
-
-CSharedSecret::~CSharedSecret()
-{
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret::DoDataExchange
-//---------------------------------------------------------------------------------------------------------------------------
-
-void CSharedSecret::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	DDX_Text(pDX, IDC_KEY, m_key );
-	DDX_Text(pDX, IDC_SECRET, m_secret );
-}
-
-
-BEGIN_MESSAGE_MAP(CSharedSecret, CDialog)
-END_MESSAGE_MAP()
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret::Load
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSharedSecret::Load( CString zone )
-{
-	char	zoneUTF8[ 256 ];
-	char	outDomain[ 256 ];
-	char	outKey[ 256 ];
-	char	outSecret[ 256 ];
-
-	StringObjectToUTF8String( zone, zoneUTF8, sizeof( zoneUTF8 ) );
-
-	if ( LsaGetSecret( zoneUTF8, outDomain, sizeof( outDomain ) / sizeof( TCHAR ), outKey, sizeof( outKey ) / sizeof( TCHAR ), outSecret, sizeof( outSecret ) / sizeof( TCHAR ) ) )
-	{
-		m_key		= outKey;
-		m_secret	= outSecret;
-	}
-	else
-	{
-		m_key = zone;
-	}
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret::Commit
-//---------------------------------------------------------------------------------------------------------------------------
-
-void
-CSharedSecret::Commit( CString zone )
-{
-	char	zoneUTF8[ 256 ];
-	char	keyUTF8[ 256 ];
-	char	secretUTF8[ 256 ];
-
-	StringObjectToUTF8String( zone, zoneUTF8, sizeof( zoneUTF8 ) );
-	StringObjectToUTF8String( m_key, keyUTF8, sizeof( keyUTF8 ) );
-	StringObjectToUTF8String( m_secret, secretUTF8, sizeof( secretUTF8 ) );
-
-	LsaSetSecret( zoneUTF8, keyUTF8, secretUTF8 );
-}
diff --git a/mDNSWindows/ControlPanel/SharedSecret.h b/mDNSWindows/ControlPanel/SharedSecret.h
deleted file mode 100644
index be82d8b..0000000
--- a/mDNSWindows/ControlPanel/SharedSecret.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-    
-#pragma once
-
-#include "resource.h"
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-//	CSharedSecret
-//---------------------------------------------------------------------------------------------------------------------------
-
-class CSharedSecret : public CDialog
-{
-	DECLARE_DYNAMIC(CSharedSecret)
-
-public:
-	CSharedSecret(CWnd* pParent = NULL);   // standard constructor
-	virtual ~CSharedSecret();
-
-// Dialog Data
-	enum { IDD = IDR_SECRET };
-
-	void
-	Load( CString zone );
-
-	void
-	Commit( CString zone );
-
-protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-
-	DECLARE_MESSAGE_MAP()
-
-public:
-
-	CString m_key;
-	CString m_secret;
-};
diff --git a/mDNSWindows/ControlPanel/resource.h b/mDNSWindows/ControlPanel/resource.h
deleted file mode 100644
index fec673f..0000000
--- a/mDNSWindows/ControlPanel/resource.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by ControlPanel.rc
-//
-#define IDR_APPLET                      131
-#define IDR_APPLET_PAGE1                131
-#define IDS_APPLET_DESCRIPTION          132
-#define IDR_APPLET_PAGE2                132
-#define IDR_SECRET                      133
-#define IDR_APPLET_PAGE3                134
-#define IDR_APPLET_PAGE4                135
-#define IDR_APPLET_PAGE5                136
-#define IDI_FAILURE                     140
-#define IDI_SUCCESS                     141
-#define IDI_ENERGY_SAVER				142
-#define IDR_ADD_BROWSE_DOMAIN           143
-#define IDR_POWER_MANAGEMENT_WARNING	144
-#define IDS_REINSTALL					145
-#define IDS_REINSTALL_CAPTION			146
-#define IDS_APPLET_NAME					147
-#define IDS_APPLET_TOOLTIP				148
-#define IDC_HOSTNAME                    1000
-#define IDC_USERNAME					1001
-#define IDC_PASSWORD					1002
-#define IDC_ADVERTISE_SERVICES			1003
-#define IDC_BUTTON1                     1004
-#define IDC_COMBO1                      1005
-#define IDC_CHECK1                      1006
-#define IDC_COMBO2                      1007
-#define IDC_EDIT2                       1008
-#define IDC_SECRET                      1009
-#define IDC_COMBO3                      1010
-#define IDC_FAILURE                     1011
-#define IDC_SUCCESS                     1012
-#define IDC_SECRET_NAME                 1013
-#define IDC_NAME                        1014
-#define IDC_KEY                         1015
-#define IDC_LIST1                       1016
-#define IDC_BROWSE_LIST                 1017
-#define IDC_BUTTON2                     1018
-#define IDC_REMOVE_BROWSE_DOMAIN        1019
-#define IDC_ADD_BROWSE_DOMAIN           1020
-#define IDC_POWER_MANAGEMENT            1021
-#define IDC_ADVERTISE_SMB	            1022
-#define IDC_ENERGY_SAVER				1023
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        149
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1024
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/ControlPanel/stdafx.cpp b/mDNSWindows/ControlPanel/stdafx.cpp
deleted file mode 100644
index e05ec3d..0000000
--- a/mDNSWindows/ControlPanel/stdafx.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "stdafx.h"
-
-
diff --git a/mDNSWindows/ControlPanel/stdafx.h b/mDNSWindows/ControlPanel/stdafx.h
deleted file mode 100644
index 246752e..0000000
--- a/mDNSWindows/ControlPanel/stdafx.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#ifndef VC_EXTRALEAN
-#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
-#endif
-
-// Modify the following defines if you have to target a platform prior to the ones specified below.
-// Refer to MSDN for the latest info on corresponding values for different platforms.
-#ifndef WINVER				// Allow use of features specific to Windows 95 and Windows NT 4 or later.
-#define WINVER 0x0400		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
-#endif
-
-#ifndef _WIN32_WINNT		// Allow use of features specific to Windows NT 4 or later.
-#define _WIN32_WINNT 0x0400	// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
-#endif						
-
-#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
-#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
-#endif
-
-// Step 3: We want to see one image, but not a tile
-#ifndef _WIN32_IE			// Allow use of features specific to IE 4.0 or later.
-#define _WIN32_IE 0x0500	// Change this to the appropriate value to target IE 5.0 or later.
-#endif
-
-#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
-
-// turns off MFC's hiding of some common and often safely ignored warning messages
-#define _AFX_ALL_WARNINGS
-
-#if !defined(_WSPIAPI_COUNTOF)
-#	define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-#endif
-
-#include <afxwin.h>         // MFC core and standard components
-#include <afxext.h>         // MFC extensions
-#include <afxdisp.h>        // MFC Automation classes
-
-#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-#include <afxcmn.h>			// MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
-#include <afxdlgs.h>
-
-#include <cpl.h>            // Control Panel Applet functions and defines
-
-#include <afxtempl.h>       // MFC Template support
diff --git a/mDNSWindows/DLL.NET/AssemblyInfo.cpp b/mDNSWindows/DLL.NET/AssemblyInfo.cpp
deleted file mode 100644
index 40f0b5d..0000000
--- a/mDNSWindows/DLL.NET/AssemblyInfo.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-    
-#include "stdafx.h"
-#include "WinVersRes.h"
-
-using namespace System;
-using namespace System::Reflection;
-using namespace System::Runtime::CompilerServices;
-using namespace System::Runtime::InteropServices;
-using namespace System::Security::Permissions;
-
-//
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-//
-[assembly:AssemblyTitleAttribute("dnssd.NET")];
-[assembly:AssemblyDescriptionAttribute(".NET wrapper for DNS-SD services")];
-[assembly:AssemblyConfigurationAttribute("")];
-[assembly:AssemblyCompanyAttribute("Apple Inc.")];
-[assembly:AssemblyProductAttribute("")];
-[assembly:AssemblyCopyrightAttribute("Apple Inc.")];
-[assembly:AssemblyTrademarkAttribute("")];
-[assembly:AssemblyCultureAttribute("")];		
-
-//
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the value or you can default the Revision and Build Numbers 
-// by using the '*' as shown below:
-
-[assembly:AssemblyVersionAttribute(MASTER_PROD_VERS_STR2)];
-
-//
-// In order to sign your assembly you must specify a key to use. Refer to the
-// Microsoft .NET Framework documentation for more information on assembly
-// signing.
-//
-// Use the attributes below to control which key is used for signing.
-//
-// Notes:
-//   (*) If no key is specified, the assembly is not signed.
-//   (*) KeyName refers to a key that has been installed in the Crypto Service
-//       Provider (CSP) on your machine. KeyFile refers to a file which contains
-//       a key.
-//   (*) If the KeyFile and the KeyName values are both specified, the
-//       following processing occurs:
-//       (1) If the KeyName can be found in the CSP, that key is used.
-//       (2) If the KeyName does not exist and the KeyFile does exist, the key
-//           in the KeyFile is installed into the CSP and used.
-//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name)
-//       utility
-//        When specifying the KeyFile, the location of the KeyFile should be
-//        relative to the project directory.
-//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
-//       documentation for more information on this.
-//
-[assembly:AssemblyDelaySignAttribute(false)];
-[assembly:AssemblyKeyFileAttribute("dnssd_NET.snk")];
-[assembly:AssemblyKeyNameAttribute("")];
-
-[assembly:ComVisible(false)];
-[assembly:CLSCompliantAttribute(true)];
-[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
diff --git a/mDNSWindows/DLL.NET/PString.h b/mDNSWindows/DLL.NET/PString.h
deleted file mode 100644
index 0249c05..0000000
--- a/mDNSWindows/DLL.NET/PString.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-    
-#pragma once
-
-using namespace System;
-using namespace System::Text;
-
-namespace Apple
-{
-	__gc class PString
-	{
-	public:
-
-		PString(String* string)
-		{
-			if (string != NULL)
-			{
-				Byte unicodeBytes[] = Encoding::Unicode->GetBytes(string);
-				Byte utf8Bytes[] = Encoding::Convert(Encoding::Unicode, Encoding::UTF8, unicodeBytes);
-				m_p = Marshal::AllocHGlobal(utf8Bytes->Length + 1);
-
-				Byte __pin * p = &utf8Bytes[0];
-				char * hBytes = static_cast<char*>(m_p.ToPointer());
-				memcpy(hBytes, p, utf8Bytes->Length);
-				hBytes[utf8Bytes->Length] = '\0';
-			}
-			else
-			{
-				m_p = NULL;
-			}
-		}
-
-		~PString()
-		{
-			Marshal::FreeHGlobal(m_p);
-		}
-
-		const char*
-		c_str()
-		{
-			if (m_p != NULL)
-			{
-				return static_cast<const char*>(m_p.ToPointer());
-			}
-			else
-			{
-				return NULL;
-			}
-		}
-		
-	protected:
-
-		IntPtr m_p;
-	};
-}
diff --git a/mDNSWindows/DLL.NET/Stdafx.cpp b/mDNSWindows/DLL.NET/Stdafx.cpp
deleted file mode 100644
index ef03e21..0000000
--- a/mDNSWindows/DLL.NET/Stdafx.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-    
-// stdafx.cpp : source file that includes just the standard includes
-// dotNET.pch will be the pre-compiled header
-// stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
diff --git a/mDNSWindows/DLL.NET/Stdafx.h b/mDNSWindows/DLL.NET/Stdafx.h
deleted file mode 100644
index d2e5c1a..0000000
--- a/mDNSWindows/DLL.NET/Stdafx.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-    
-// stdafx.h : include file for standard system include files,
-// or project specific include files that are used frequently,
-// but are changed infrequently
-
-#pragma once
-
-#if !defined(_WSPIAPI_COUNTOF)
-#	define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
-#endif
-
-#using <mscorlib.dll>
-#using <System.dll>
-
-struct _DNSServiceRef_t {};
-struct _DNSRecordRef_t {};
-
diff --git a/mDNSWindows/DLL.NET/dnssd_NET.cpp b/mDNSWindows/DLL.NET/dnssd_NET.cpp
deleted file mode 100644
index 3e22146..0000000
--- a/mDNSWindows/DLL.NET/dnssd_NET.cpp
+++ /dev/null
@@ -1,1234 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-    
-// This is the main DLL file.
-
-#include "stdafx.h"
-
-#include "dnssd_NET.h"
-#include "DebugServices.h"
-#include "PString.h"
-
-
-using namespace System::Net::Sockets;
-using namespace System::Diagnostics;
-using namespace Apple;
-using namespace Apple::DNSSD;
-
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#define	DEBUG_NAME	"[dnssd.NET] "
-
-//
-// ConvertToString
-//
-static String*
-ConvertToString(const char * utf8String)
-{
-	return __gc new String(utf8String, 0, strlen(utf8String), __gc new UTF8Encoding(true, true));
-}
-
-
-//
-// class ServiceRef
-//
-// ServiceRef serves as the base class for all DNSService operations.
-//
-// It manages the DNSServiceRef, and implements processing the
-// result
-//
-ServiceRef::ServiceRef(Object * callback)
-:
-	m_bDisposed(false),
-	m_callback(callback),
-	m_thread(NULL)
-{
-	m_impl = new ServiceRefImpl(this);
-}
-
-
-ServiceRef::~ServiceRef()
-{
-}
-
-
-//
-// StartThread
-//
-// Starts the main processing thread
-//
-void
-ServiceRef::StartThread()
-{
-	check( m_impl != NULL );
-
-	m_impl->SetupEvents();
-
-	m_thread		=	new Thread(new ThreadStart(this, &Apple::DNSSD::ServiceRef::ProcessingThread));
-	m_thread->Name	=	S"DNSService Thread";
-	m_thread->IsBackground = true;
-	
-	m_thread->Start();
-}
-
-
-//
-// ProcessingThread
-//
-// The Thread class can only invoke methods in MC++ types.  So we
-// make a ProcessingThread method that forwards to the impl
-//
-void
-ServiceRef::ProcessingThread()
-{
-	m_impl->ProcessingThread();
-}
-
-
-//
-// Dispose
-//
-// Calls impl-Dispose().  This ultimately will call DNSServiceRefDeallocate()
-//
-void
-ServiceRef::Dispose()
-{
-	check(m_impl != NULL);
-	check(m_bDisposed == false);
-
-	if (!m_bDisposed)
-	{
-		m_bDisposed = true;
-
-		//
-		// Call Dispose.  This won't call DNSServiceRefDeallocate()
-		// necessarily. It depends on what thread this is being
-		// called in.
-		//
-		m_impl->Dispose();
-		m_impl = NULL;
-
-		m_thread = NULL;
-
-		GC::SuppressFinalize(this);  
-	}
-}
-
-
-//
-// EnumerateDomainsDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::EnumerateDomainsDispatch
-						(
-						ServiceFlags	flags,
-						int				interfaceIndex,
-						ErrorCode		errorCode,
-						String		*	replyDomain
-						)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::EnumerateDomainsReply * OnEnumerateDomainsReply = static_cast<DNSService::EnumerateDomainsReply*>(m_callback);
-		OnEnumerateDomainsReply(this, flags, interfaceIndex, errorCode, replyDomain);
-	}
-}
-
-
-//
-// RegisterDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::RegisterDispatch
-				(
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
- 				String		*	name,
-				String		*	regtype,
-				String		*	domain
-				)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::RegisterReply * OnRegisterReply = static_cast<DNSService::RegisterReply*>(m_callback);
-		OnRegisterReply(this, flags, errorCode, name, regtype, domain);
-	}
-}
-
-
-//
-// BrowseDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::BrowseDispatch
-			(
-			ServiceFlags	flags,
-			int				interfaceIndex,
-			ErrorCode		errorCode,
-			String		*	serviceName,
-			String		*	regtype,
-			String		*	replyDomain
-			)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::BrowseReply * OnBrowseReply = static_cast<DNSService::BrowseReply*>(m_callback);
-		OnBrowseReply(this, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
-	}
-}
-
-
-//
-// ResolveDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::ResolveDispatch
-			(
-			ServiceFlags	flags,
-			int				interfaceIndex,
-			ErrorCode		errorCode,
-			String		*	fullname,
-			String		*	hosttarget,
-			int				port,
-			Byte			txtRecord[]
-			)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::ResolveReply * OnResolveReply = static_cast<DNSService::ResolveReply*>(m_callback);
-		OnResolveReply(this, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtRecord);
-	}
-}
-
-
-//
-// RegisterRecordDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::RegisterRecordDispatch
-				(
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
-				RecordRef	*	record
-				)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::RegisterRecordReply * OnRegisterRecordReply = static_cast<DNSService::RegisterRecordReply*>(m_callback);
-		OnRegisterRecordReply(this, flags, errorCode, record);
-	}
-}
-
-
-//
-// QueryRecordDispatch
-//
-// Dispatch a reply to the delegate.
-//
-void
-ServiceRef::QueryRecordDispatch
-					(
-					ServiceFlags	flags,
-					int				interfaceIndex,
-					ErrorCode		errorCode,
-					String		*	fullname,
-					int				rrtype,
-					int				rrclass,
-					Byte			rdata[],
-					int				ttl
-					)
-{
-	if ((m_callback != NULL) && (m_impl != NULL))
-	{
-		DNSService::QueryRecordReply * OnQueryRecordReply = static_cast<DNSService::QueryRecordReply*>(m_callback);
-		OnQueryRecordReply(this, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdata, ttl);
-	}
-}
-
-
-//
-// ServiceRefImpl::ServiceRefImpl()
-//
-// Constructs a new ServiceRefImpl.  We save the pointer to our enclosing
-// class in a gcroot handle.  This satisfies the garbage collector as
-// the outer class is a managed type
-//
-ServiceRef::ServiceRefImpl::ServiceRefImpl(ServiceRef * outer)
-:
-	m_socketEvent(NULL),
-	m_stopEvent(NULL),
-	m_disposed(false),
-	m_outer(outer),
-	m_ref(NULL)
-{
-	m_threadId = GetCurrentThreadId();
-}
-
-
-//
-// ServiceRefImpl::~ServiceRefImpl()
-//
-// Deallocate all resources associated with the ServiceRefImpl
-//
-ServiceRef::ServiceRefImpl::~ServiceRefImpl()
-{
-	if (m_socketEvent != NULL)
-	{
-		CloseHandle(m_socketEvent);
-		m_socketEvent = NULL;
-	}
-
-	if (m_stopEvent != NULL)
-	{
-		CloseHandle(m_stopEvent);
-		m_stopEvent = NULL;
-	}
-
-	if (m_ref != NULL)
-	{
-		DNSServiceRefDeallocate(m_ref);
-		m_ref = NULL;
-	}
-}
-
-
-//
-// ServiceRefImpl::SetupEvents()
-//
-// Setup the events necessary to manage multi-threaded dispatch
-// of DNSService Events
-//
-void
-ServiceRef::ServiceRefImpl::SetupEvents()
-{
-	check(m_ref != NULL);
-
-	m_socket		=	(SOCKET) DNSServiceRefSockFD(m_ref);
-	check(m_socket != INVALID_SOCKET);
-
-	m_socketEvent	=	CreateEvent(NULL, 0, 0, NULL);
-
-	if (m_socketEvent == NULL)
-	{
-		throw new DNSServiceException(Unknown);
-	}
-
-	int err = WSAEventSelect(m_socket, m_socketEvent, FD_READ|FD_CLOSE);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(Unknown);
-	}
-
-	m_stopEvent = CreateEvent(NULL, 0, 0, NULL);
-
-	if (m_stopEvent == NULL)
-	{
-		throw new DNSServiceException(Unknown);
-	}
-}
-
-
-//
-// ServiceRefImpl::ProcessingThread()
-//
-// Wait for socket events on the DNSServiceRefSockFD().  Also wait
-// for stop events
-//
-void
-ServiceRef::ServiceRefImpl::ProcessingThread()
-{
-	check( m_socketEvent != NULL );
-	check( m_stopEvent != NULL );
-	check( m_ref != NULL );
-	
-	HANDLE handles[2];
-
-	handles[0] = m_socketEvent;
-	handles[1] = m_stopEvent;
-
-	while (m_disposed == false)
-	{
-		int ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-
-		//
-		// it's a socket event
-		//
-		if (ret == WAIT_OBJECT_0)
-		{
-			DNSServiceProcessResult(m_ref);
-		}
-		//
-		// else it's a stop event
-		//
-		else if (ret == WAIT_OBJECT_0 + 1)
-		{
-			break;
-		}
-		else
-		{
-			//
-			// unexpected wait result
-			//
-			dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, ret );
-		}
-	}
-
-	delete this;
-}
-
-
-//
-// ServiceRefImpl::Dispose()
-//
-// Calls DNSServiceRefDeallocate()
-//
-void
-ServiceRef::ServiceRefImpl::Dispose()
-{
-	OSStatus	err;
-	BOOL		ok;
-
-	check(m_disposed == false);
-
-	m_disposed = true;
-
-	ok = SetEvent(m_stopEvent);
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-
-	return;
-}
-
-
-//
-// ServiceRefImpl::EnumerateDomainsCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::EnumerateDomainsCallback
-											(
-											DNSServiceRef			sdRef,
-											DNSServiceFlags			flags,
-											uint32_t				interfaceIndex,
-											DNSServiceErrorType		errorCode,
-											const char			*	replyDomain,
-											void				*	context
-											)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-
-	if (self->m_disposed == false)
-	{
-		self->m_outer->EnumerateDomainsDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(replyDomain));
-	}
-}
-
-
-//
-// ServiceRefImpl::RegisterCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::RegisterCallback
-							(
-							DNSServiceRef			sdRef,
-							DNSServiceFlags			flags,
-							DNSServiceErrorType		errorCode,
-							const char			*	name,
-							const char			*	regtype,
-							const char			*	domain,
-							void				*	context
-							)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-	
-	if (self->m_disposed == false)
-	{
-		self->m_outer->RegisterDispatch((ServiceFlags) flags, (ErrorCode) errorCode, ConvertToString(name), ConvertToString(regtype), ConvertToString(domain));
-	}
-}
-
-
-//
-// ServiceRefImpl::BrowseCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::BrowseCallback
-							(
-							DNSServiceRef			sdRef,
-   							DNSServiceFlags			flags,
-							uint32_t				interfaceIndex,
-							DNSServiceErrorType		errorCode,
-							const char			*	serviceName,
-							const char			*	regtype,
-							const char			*	replyDomain,
-							void				*	context
-							)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-	
-	if (self->m_disposed == false)
-	{
-		self->m_outer->BrowseDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(serviceName), ConvertToString(regtype), ConvertToString(replyDomain));
-	}
-}
-
-
-//
-// ServiceRefImpl::ResolveCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::ResolveCallback
-							(
-							DNSServiceRef			sdRef,
-							DNSServiceFlags			flags,
-							uint32_t				interfaceIndex,
-							DNSServiceErrorType		errorCode,
-							const char			*	fullname,
-							const char			*	hosttarget,
-							uint16_t				notAnIntPort,
-							uint16_t				txtLen,
-							const char			*	txtRecord,
-							void				*	context
-							)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-	
-	if (self->m_disposed == false)
-	{
-		Byte txtRecordBytes[];
-
-		txtRecordBytes = NULL;
-
-		if (txtLen > 0)
-		{
-			//
-			// copy raw memory into managed byte array
-			//
-			txtRecordBytes		=	new Byte[txtLen];
-			Byte __pin	*	p	=	&txtRecordBytes[0];
-			memcpy(p, txtRecord, txtLen);
-		}
-
-		self->m_outer->ResolveDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), ConvertToString(hosttarget), ntohs(notAnIntPort), txtRecordBytes);
-	}	
-}
-
-
-//
-// ServiceRefImpl::RegisterRecordCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::RegisterRecordCallback
-								(
-								DNSServiceRef		sdRef,
-								DNSRecordRef		rrRef,
-								DNSServiceFlags		flags,
-								DNSServiceErrorType	errorCode,
-								void			*	context
-								)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-	
-	if (self->m_disposed == false)
-	{
-		RecordRef * record = NULL;
-
-		if (errorCode == 0)
-		{
-			record = new RecordRef;
-
-			record->m_impl->m_ref = rrRef;
-		}
-
-		self->m_outer->RegisterRecordDispatch((ServiceFlags) flags, (ErrorCode) errorCode, record);
-	}
-}
-
-
-//
-// ServiceRefImpl::QueryRecordCallback()
-//
-// This is the callback from dnssd.dll.  We pass this up to our outer, managed type
-//
-void DNSSD_API
-ServiceRef::ServiceRefImpl::QueryRecordCallback
-								(
-								DNSServiceRef			DNSServiceRef,
-								DNSServiceFlags			flags,
-								uint32_t				interfaceIndex,
-								DNSServiceErrorType		errorCode,
-								const char			*	fullname,
-								uint16_t				rrtype,
-								uint16_t				rrclass,
-								uint16_t				rdlen,
-								const void			*	rdata,
-								uint32_t				ttl,
-								void				*	context
-								)
-{
-	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
-
-	check( self != NULL );
-	check( self->m_outer != NULL );
-	
-	if (self->m_disposed == false)
-	{
-		Byte rdataBytes[];
-
-		if (rdlen)
-		{
-			rdataBytes			=	new Byte[rdlen];
-			Byte __pin * p		=	&rdataBytes[0];
-			memcpy(p, rdata, rdlen);
-		}
-
-		self->m_outer->QueryRecordDispatch((ServiceFlags) flags, (int) interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), rrtype, rrclass, rdataBytes, ttl);
-	}
-}
-
-
-/*
- * EnumerateDomains()
- *
- * This maps to DNSServiceEnumerateDomains().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::EnumerateDomains
-		(
-		int							flags,
-		int							interfaceIndex,
-		EnumerateDomainsReply	*	callback
-		)
-{
-	ServiceRef * sdRef = new ServiceRef(callback);
-	int			 err;
-
-	err = DNSServiceEnumerateDomains(&sdRef->m_impl->m_ref, flags, interfaceIndex, ServiceRef::ServiceRefImpl::EnumerateDomainsCallback, sdRef->m_impl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * Register()
- *
- * This maps to DNSServiceRegister().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::Register
-				(
-				int					flags,
-				int					interfaceIndex,
-				String			*	name,
-				String			*	regtype,
-				String			*	domain,
-				String			*	host,
-				int					port,
-				Byte				txtRecord[],
-				RegisterReply	*	callback
-				)
-{
-	ServiceRef	*	sdRef	=	new ServiceRef(callback);
-	PString		*	pName	=	new PString(name);
-	PString		*	pType	=	new PString(regtype);
-	PString		*	pDomain =	new PString(domain);
-	PString		*	pHost	=	new PString(host);
-	int				len		=	0;
-	Byte __pin	*	p		=	NULL;
-	void		*	v		=	NULL;
-
-	if ((txtRecord != NULL) && (txtRecord->Length > 0))
-	{
-		len		= txtRecord->Length;
-		p		= &txtRecord[0];
-		v		= (void*) p;
-	}
-
-	int err = DNSServiceRegister(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(), pHost->c_str(), htons(port), len, v, ServiceRef::ServiceRefImpl::RegisterCallback, sdRef->m_impl );
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * AddRecord()
- *
- * This maps to DNSServiceAddRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-RecordRef*
-DNSService::AddRecord
-				(
-				ServiceRef	*	sdRef,
-				int				flags,
-				int				rrtype,
-				Byte			rdata[],
-				int				ttl
-				)
-{
-	int				len		=	0;
-	Byte __pin	*	p		=	NULL;
-	void		*	v		=	NULL;
-
-	if ((rdata != NULL) && (rdata->Length > 0))
-	{
-		len = rdata->Length;
-		p	= &rdata[0];
-		v	= (void*) p;
-	}
-
-	RecordRef * record = new RecordRef;
-
-	int err = DNSServiceAddRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, rrtype, len, v, ttl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	return record;
-}
-
-
-/*
- * UpdateRecord()
- *
- * This maps to DNSServiceUpdateRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-void
-DNSService::UpdateRecord
-				(
-				ServiceRef	*	sdRef,
-				RecordRef	*	record,
-				int				flags,
-				Byte			rdata[],
-				int				ttl
-				)
-{
-	int				len		=	0;
-	Byte __pin	*	p		=	NULL;
-	void		*	v		=	NULL;
-
-	if ((rdata != NULL) && (rdata->Length > 0))
-	{
-		len	= rdata->Length;
-		p	= &rdata[0];
-		v	= (void*) p;
-	}
-
-	int err = DNSServiceUpdateRecord(sdRef->m_impl->m_ref, record ? record->m_impl->m_ref : NULL, flags, len, v, ttl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-}
-
-
-/*
- * RemoveRecord()
- *
- * This maps to DNSServiceRemoveRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-void
-DNSService::RemoveRecord
-		(
-		ServiceRef	*	sdRef,
-		RecordRef	*	record,
-		int				flags
-		)
-{
-	int err = DNSServiceRemoveRecord(sdRef->m_impl->m_ref, record->m_impl->m_ref, flags);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-}	
-
-
-/*
- * Browse()
- *
- * This maps to DNSServiceBrowse().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::Browse
-	(
-	int				flags,
-	int				interfaceIndex,
-	String		*	regtype,
-	String		*	domain,
-	BrowseReply	*	callback
-	)
-{
-	ServiceRef	*	sdRef	= new ServiceRef(callback);
-	PString		*	pType	= new PString(regtype);
-	PString		*	pDomain	= new PString(domain);
-
-	int err = DNSServiceBrowse(&sdRef->m_impl->m_ref, flags, interfaceIndex, pType->c_str(), pDomain->c_str(),(DNSServiceBrowseReply) ServiceRef::ServiceRefImpl::BrowseCallback, sdRef->m_impl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * Resolve()
- *
- * This maps to DNSServiceResolve().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::Resolve
-	(
-	int					flags,
-	int					interfaceIndex,
-	String			*	name,
-	String			*	regtype,
-	String			*	domain,
-	ResolveReply	*	callback	
-	)
-{
-	ServiceRef	*	sdRef	= new ServiceRef(callback);
-	PString		*	pName	= new PString(name);
-	PString		*	pType	= new PString(regtype);
-	PString		*	pDomain	= new PString(domain);
-
-	int err = DNSServiceResolve(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(),(DNSServiceResolveReply) ServiceRef::ServiceRefImpl::ResolveCallback, sdRef->m_impl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * CreateConnection()
- *
- * This maps to DNSServiceCreateConnection().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::CreateConnection
-			(
-			RegisterRecordReply * callback
-			)
-{
-	ServiceRef * sdRef = new ServiceRef(callback);
-
-	int err = DNSServiceCreateConnection(&sdRef->m_impl->m_ref);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * RegisterRecord()
- *
- * This maps to DNSServiceRegisterRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-
-RecordRef*
-DNSService::RegisterRecord
-			(
-			ServiceRef			*	sdRef,
-			ServiceFlags			flags,
-			int						interfaceIndex,
-			String				*	fullname,
-			int						rrtype,
-			int						rrclass,
-			Byte					rdata[],
-			int						ttl
-			)
-{
-	RecordRef	*	record	= new RecordRef;
-	int				len		= 0;
-	Byte __pin	*	p		= NULL;
-	void		*	v		= NULL;
-
-	PString * pFullname = new PString(fullname);
-
-	if ((rdata != NULL) && (rdata->Length > 0))
-	{
-		len		= rdata->Length;
-		p		= &rdata[0];
-		v		= (void*) p;
-	}
-
-	int err = DNSServiceRegisterRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v, ttl, (DNSServiceRegisterRecordReply) ServiceRef::ServiceRefImpl::RegisterRecordCallback, sdRef->m_impl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	return record;
-}
-
-/*
- * QueryRecord()
- *
- * This maps to DNSServiceQueryRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-ServiceRef*
-DNSService::QueryRecord
-		(
-		ServiceFlags			flags,
-		int						interfaceIndex,
-		String				*	fullname,
-		int						rrtype,
-		int						rrclass,
-		QueryRecordReply	*	callback
-		)
-{
-	ServiceRef	*	sdRef		= new ServiceRef(callback);
-	PString		*	pFullname	= new PString(fullname);
-
-	int err = DNSServiceQueryRecord(&sdRef->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, (DNSServiceQueryRecordReply) ServiceRef::ServiceRefImpl::QueryRecordCallback, sdRef->m_impl);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	sdRef->StartThread();
-
-	return sdRef;
-}
-
-
-/*
- * ReconfirmRecord()
- *
- * This maps to DNSServiceReconfirmRecord().  Returns an
- * initialized ServiceRef on success, throws an exception
- * on failure.
- */
-void
-DNSService::ReconfirmRecord
-		(
-		ServiceFlags	flags,
-		int				interfaceIndex,
-		String		*	fullname,
-		int				rrtype,
-		int				rrclass,
-		Byte			rdata[]
-		)
-{
-	int				len	= 0;
-	Byte __pin	*	p	= NULL;
-	void		*	v	= NULL;
-
-	PString * pFullname = new PString(fullname);
-
-	if ((rdata != NULL) && (rdata->Length > 0))
-	{
-		len	= rdata->Length;
-		p	= &rdata[0];
-		v	= (void*) p;
-	}
-
-	DNSServiceReconfirmRecord(flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v);
-}
-
-
-void
-TextRecord::SetValue
-		(
-		String	*	key,
-		Byte		value[]            /* may be NULL */
-		)
-{
-	PString			*	pKey = new PString(key);
-	int					len		=	0;
-	Byte __pin		*	p		=	NULL;
-	void			*	v		=	NULL;
-	DNSServiceErrorType	err;
-
-	if (value && (value->Length > 0))
-	{
-		len	=	value->Length;
-		p	=	&value[0];
-		v	=	(void*) p;
-	}
-
-	err = TXTRecordSetValue(&m_impl->m_ref, pKey->c_str(), len, v);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-}
-
-
-void
-TextRecord::RemoveValue
-		(
-		String	*	key
-		)
-{
-	PString			*	pKey = new PString(key);
-	DNSServiceErrorType	err;
-
-	err = TXTRecordRemoveValue(&m_impl->m_ref, pKey->c_str());
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-}
-
-
-int
-TextRecord::GetLength
-		(
-		)
-{
-	return TXTRecordGetLength(&m_impl->m_ref);
-}
-
-
-Byte
-TextRecord::GetBytes
-		(
-		) __gc[]
-{
-	const void	*	noGCBytes = NULL;
-	Byte			gcBytes[] = NULL;		
-
-	noGCBytes		=	TXTRecordGetBytesPtr(&m_impl->m_ref);
-	int			len	=	GetLength();
-
-	if (noGCBytes && len)
-	{
-		gcBytes				=	new Byte[len];
-		Byte __pin	*	p	=	&gcBytes[0];
-		memcpy(p, noGCBytes, len);
-	}
-
-	return gcBytes;
-}
-
-
-bool
-TextRecord::ContainsKey
-		(
-		Byte		txtRecord[],
-		String	*	key
-		)
-{
-	PString		*	pKey	= new PString(key);
-	Byte __pin	*	p		= &txtRecord[0];
-	
-	return (TXTRecordContainsKey(txtRecord->Length, p, pKey->c_str()) > 0) ? true : false;
-}
-
-
-Byte
-TextRecord::GetValueBytes
-		(
-		Byte		txtRecord[],
-		String	*	key
-		) __gc[]
-{
-	uint8_t			valueLen;
-	Byte			ret[]	= NULL;
-	PString		*	pKey	= new PString(key);
-	Byte __pin	*	p1		= &txtRecord[0];
-	const void	*	v;
-
-	v = TXTRecordGetValuePtr(txtRecord->Length, p1, pKey->c_str(), &valueLen);
-
-	if (v != NULL)
-	{
-		ret					= new Byte[valueLen];
-		Byte __pin	*	p2	= &ret[0];
-
-		memcpy(p2, v, valueLen);
-	}
-
-	return ret;
-}
-
-
-int
-TextRecord::GetCount
-		(
-		Byte txtRecord[]
-		)
-{
-	Byte __pin	*	p	= &txtRecord[0];
-
-	return TXTRecordGetCount(txtRecord->Length, p);
-}
-
-
-Byte
-TextRecord::GetItemAtIndex
-		(
-		Byte				txtRecord[],
-		int					index,
-		[Out] String	**	key
-		) __gc[]
-{
-	char				keyBuf[255];
-	uint8_t				keyBufLen = 255;
-	uint8_t				valueLen;
-	void			*	value;
-	Byte				ret[]	= NULL;
-	DNSServiceErrorType	err;
-	Byte __pin		*	p1		= &txtRecord[0];
-	
-
-	err = TXTRecordGetItemAtIndex(txtRecord->Length, p1, index, keyBufLen, keyBuf, &valueLen, (const void**) &value);
-
-	if (err != 0)
-	{
-		throw new DNSServiceException(err);
-	}
-
-	*key = ConvertToString(keyBuf);
-
-	if (valueLen)
-	{
-		ret					= new Byte[valueLen];
-		Byte __pin	*	p2	= &ret[0];
-
-		memcpy(p2, value, valueLen);
-	}
-
-	return ret;
-}
-
-
-//
-// DNSServiceException::DNSServiceException()
-//
-// Constructs an exception with an error code
-//
-DNSServiceException::DNSServiceException
-				(
-				int _err
-				)
-:
-	err(_err)
-{
-}
-
-
-//
-// This version of the constructor is useful for instances in which
-// an inner exception is thrown, caught, and then a new exception
-// is thrown in it's place
-//
-DNSServiceException::DNSServiceException
-				(	
-				String				*	message,
-				System::Exception	*	innerException
-				)
-{
-}
diff --git a/mDNSWindows/DLL.NET/dnssd_NET.h b/mDNSWindows/DLL.NET/dnssd_NET.h
deleted file mode 100644
index 3e0196d..0000000
--- a/mDNSWindows/DLL.NET/dnssd_NET.h
+++ /dev/null
@@ -1,1392 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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:
- * 
- * These .Net APIs are a work in progress, currently being discussed and refined.
- * If you plan to build an application based on these APIs, you may wish to
- * statically link this code into your application, or otherwise distribute
- * the DLL so that it installs into the same folder as your application
- * (not into any common system area where it might interfere with other
- * applications using a future completed version of these APIs).
- * If you plan to do this, please be sure to inform us by sending email
- * to bonjour@apple.com to let us know.
- * You may want to discuss what you're doing on the Bonjour mailing
- * list to see if others in similar positions have any suggestions for you:
- * 
- * <http://lists.apple.com/bonjour-dev/>
- * 
- */
-    
-#pragma once
-
-#include <dns_sd.h>
-#include <vcclr.h>
-#include <memory>
-#include <winsock2.h>
-
-using namespace System;
-using namespace System::Net;
-using namespace System::Runtime::InteropServices;
-using namespace System::Threading;
-using namespace System::Collections;
-
-
-namespace Apple
-{
-	namespace DNSSD
-	{
-		public __gc class ServiceRef;
-
-		public __value enum ServiceFlags : int
-		{
-			MoreComing			=	1,
-			/* MoreComing indicates to a callback that at least one more result is
-				* queued and will be delivered following immediately after this one.
-				* Applications should not update their UI to display browse
-				* results when the MoreComing flag is set, because this would
-				* result in a great deal of ugly flickering on the screen.
-				* Applications should instead wait until until MoreComing is not set,
-				* and then update their UI.
-				* When MoreComing is not set, that doesn't mean there will be no more
-				* answers EVER, just that there are no more answers immediately
-				* available right now at this instant. If more answers become available
-				* in the future they will be delivered as usual.
-				*/
-
-			Add					=	2,
-			Default				=	4,
-			/* Flags for domain enumeration and browse/query reply callbacks.
-				* "Default" applies only to enumeration and is only valid in
-				* conjuction with "Add".  An enumeration callback with the "Add"
-				* flag NOT set indicates a "Remove", i.e. the domain is no longer
-				* valid.
-				*/
-
-			NoAutoRename		=	8,
-			/* Flag for specifying renaming behavior on name conflict when registering
-				* non-shared records. By default, name conflicts are automatically handled
-				* by renaming the service.  NoAutoRename overrides this behavior - with this
-				* flag set, name conflicts will result in a callback.  The NoAutorename flag
-				* is only valid if a name is explicitly specified when registering a service
-				* (i.e. the default name is not used.)
-				*/
-
-			Shared				=	16,
-			Unique				=	32,
-			/* Flag for registering individual records on a connected
-				* DNSServiceRef.  Shared indicates that there may be multiple records
-				* with this name on the network (e.g. PTR records).  Unique indicates that
-	the
-				* record's name is to be unique on the network (e.g. SRV records).
-				*/
-
-			BrowseDomains		=	64,
-			RegistrationDomains	=	128,
-			/* Flags for specifying domain enumeration type in DNSServiceEnumerateDomain
-	s.
-				* BrowseDomains enumerates domains recommended for browsing, RegistrationDo
-	mains
-				* enumerates domains recommended for registration.
-				*/
-		};
-
-
-		public __value enum ErrorCode : int
-		{
-			NoError				=	0,
-			Unknown				=	-65537,
-			NoSuchName			=	-65538,
-			NoMemory			=	-65539,
-			BadParam			=	-65540,
-			BadReference		=	-65541,
-			BadState			=	-65542,
-			BadFlags			=	-65543,
-			Unsupported			=	-65544,
-			AlreadyRegistered	=	-65547,
-			NameConflict		=	-65548,
-			Invalid				=	-65549,
-			Incompatible		=	-65551,
-			BadinterfaceIndex	=	-65552
-
-			/*
-				* mDNS Error codes are in the range
-				* FFFE FF00 (-65792) to FFFE FFFF (-65537)
-				*/
-		};
-
-		public __gc class DNSServiceException
-		:
-			public Exception
-		{
-		public:
-
-			DNSServiceException
-				(
-				int err
-				);
-
-			DNSServiceException
-				(	
-				String				*	message,
-				System::Exception	*	innerException
-				);
-
-			int err;
-		};
-
-
-		/*
-		* class RecordRef
-		*
-		* This is a thin MC++ class facade on top of a DNSRecordRef
-		*/
-		public __gc class RecordRef
-		{
-		public:
-
-			RecordRef()
-			{
-				m_impl = new RecordRefImpl;
-				m_impl->m_ref = NULL;
-			}
-
-			~RecordRef()
-			{
-				delete m_impl;
-			}
-
-			__nogc class RecordRefImpl
-			{
-			public:
-
-				DNSRecordRef m_ref;
-			};
-
-			RecordRefImpl * m_impl;
-		};			
-
-
-		/*
-		* class ServiceRef
-		*
-		* This is a thin MC++ class facade on top of a DNSServiceRef
-		*/
-		public __gc class ServiceRef : public IDisposable
-		{
-		public:
-
-			ServiceRef(Object * callback);
-
-			~ServiceRef();
-
-			/*
-			* This does an underlying DNSServiceRefDeallocate().  After
-			* calling Dispose, the ServiceRef is no longer usable.
-			*/
-			void
-			Dispose();
-
-			/*
-			* Internal - Dispatch an EnumerateDomains callback
-			*/
-			void
-			EnumerateDomainsDispatch
-				(
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	replyDomain
-				);
-
-			/*
-			* Internal - Dispatch a Register callback
-			*/
-			void
-			RegisterDispatch
-				(
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
- 				String		*	name,
-				String		*	regtype,
-				String		*	domain
-				);
-
-			/*
-			* Internal - Dispatch a Browse callback
-			*/
-			void
-			BrowseDispatch
-				(
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	serviceName,
-				String		*	regtype,
-				String		*	replyDomain
-				);
-
-			/*
-			* Internal - Dispatch a Resolve callback
-			*/
-			void
-			ResolveDispatch
-				(
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	fullname,
-				String		*	hosttarget,
-				int				port,
-				Byte			txtRecord[]
-				);
-			
-			/*
-			* Internal - Dispatch a RegisterRecord callback
-			*/
-			void
-			RegisterRecordDispatch
-				(
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
-				RecordRef	*	record
-				);
-
-			/*
-			* Internal - Dispatch a QueryRecord callback
-			*/
-			void
-			QueryRecordDispatch
-				(
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	fullname,
-				int				rrtype,
-				int				rrclass,
-				Byte			rdata[],
-				int				ttl
-				);
-
-			/*
-			* Internal - A non managed class to wrap a DNSServiceRef
-			*/
-			__nogc class ServiceRefImpl
-			{
-			public:
-
-				ServiceRefImpl
-					(
-					ServiceRef * outer
-					);
-
-				~ServiceRefImpl();
-
-				/*
-				* Sets up events for threaded operation
-				*/
-				void
-				SetupEvents();
-
-				/*
-				* Main processing thread
-				*/
-				void
-				ProcessingThread();
-
-				/*
-				* Calls DNSServiceRefDeallocate()
-				*/
-				void
-				Dispose();
-
-				/*
-				* Called from dnssd.dll
-				*/
-				static void DNSSD_API
-				EnumerateDomainsCallback
-					(
-					DNSServiceRef			sdRef,
-					DNSServiceFlags			flags,
-					uint32_t				interfaceIndex,
-					DNSServiceErrorType		errorCode,
-					const char			*	replyDomain,
-					void				*	context
-					);
-
-				static void DNSSD_API
-				RegisterCallback
-					(
-					DNSServiceRef			ref,
-					DNSServiceFlags			flags,
-					DNSServiceErrorType		errorCode,
- 					const char			*	name,
-					const char			*	regtype,
-					const char			*	domain,
-					void				*	context
-					);
-
-				static void DNSSD_API
-				BrowseCallback
-					(
-					DNSServiceRef			sdRef,
-   					DNSServiceFlags			flags,
-					uint32_t				interfaceIndex,
-					DNSServiceErrorType		errorCode,
-					const char			*	serviceName,
-					const char			*	regtype,
-					const char			*	replyDomain,
-					void				*	context
-					);
-
-				static void DNSSD_API
-				ResolveCallback
-					(
-					DNSServiceRef			sdRef,
-					DNSServiceFlags			flags,
-					uint32_t				interfaceIndex,
-					DNSServiceErrorType		errorCode,
-					const char			*	fullname,
-					const char			*	hosttarget,
-					uint16_t				notAnIntPort,
-					uint16_t				txtLen,
-					const char			*	txtRecord,
-					void				*	context
-					);
-
-				static void DNSSD_API
-				RegisterRecordCallback
-					( 
-					DNSServiceRef		sdRef,
-					DNSRecordRef		RecordRef,
-					DNSServiceFlags		flags,
-					DNSServiceErrorType	errorCode,
-					void			*	context
-					);
-
-				static void DNSSD_API
-				QueryRecordCallback
-					(
-					DNSServiceRef			DNSServiceRef,
-					DNSServiceFlags			flags,
-					uint32_t				interfaceIndex,
-					DNSServiceErrorType		errorCode,
-					const char			*	fullname,
-					uint16_t				rrtype,
-					uint16_t				rrclass,
-					uint16_t				rdlen,
-					const void			*	rdata,
-					uint32_t				ttl,
-					void				*	context
-					);
-
-				SOCKET				m_socket;
-				HANDLE				m_socketEvent;
-				HANDLE				m_stopEvent;
-				DWORD				m_threadId;
-				bool				m_disposed;
-				DNSServiceRef		m_ref;
-				gcroot<ServiceRef*> m_outer;
-			};
-
-			void
-			StartThread();
-
-			void
-			ProcessingThread();
-
-			bool				m_bDisposed;
-			Object			*	m_callback;
-			Thread			*	m_thread;
-			ServiceRefImpl	*	m_impl;
-		};
-			
-		/*********************************************************************************************
-		*
-		*   TXT Record Construction Functions
-		*
-		*********************************************************************************************/
-
-		/*
-		* A typical calling sequence for TXT record construction is something like:
-		*
-		* DNSService.TextRecord tr = new DNSService.TextRecord(1024);
-		* tr.SetValue();
-		* tr.SetValue();
-		* tr.SetValue();
-		* ...
-		* DNSServiceRegister( ... tr.GetLength(), tr.GetBytes() ... );
-		*/
-
-
-		/* TextRecord
-		*
-		* Opaque internal data type.
-		* Note: Represents a DNS-SD TXT record.
-		*/
-
-
-		/* TextRecord::TextRecord()
-		*
-		* Creates a new empty TextRecord .
-		*
-		*/
-
-		public __gc class TextRecord
-		{
-		public:
-
-			TextRecord()
-			{
-				m_impl = new TextRecordImpl();
-				TXTRecordCreate(&m_impl->m_ref, 0, NULL);
-			}
-
-			~TextRecord()
-			{
-				TXTRecordDeallocate(&m_impl->m_ref);
-				delete m_impl;
-			}
-
-			__nogc class TextRecordImpl
-			{
-			public:
-
-				TXTRecordRef m_ref;
-			};
-
-			TextRecordImpl * m_impl;
-
-
-			/* SetValue()
-			*
-			* Adds a key (optionally with value) to a TextRecord. If the "key" already
-			* exists in the TextRecord, then the current value will be replaced with
-			* the new value.
-			* Keys may exist in four states with respect to a given TXT record:
-			*  - Absent (key does not appear at all)
-			*  - Present with no value ("key" appears alone)
-			*  - Present with empty value ("key=" appears in TXT record)
-			*  - Present with non-empty value ("key=value" appears in TXT record)
-			* For more details refer to "Data Syntax for DNS-SD TXT Records" in
-			* <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
-			*
-			* key:             A null-terminated string which only contains printable ASCII
-			*                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
-			*                  14 characters or less (not counting the terminating null).
-			*
-			* value:           Any binary value. For values that represent
-			*                  textual data, UTF-8 is STRONGLY recommended.
-			*                  For values that represent textual data, valueSize
-			*                  should NOT include the terminating null (if any)
-			*                  at the end of the string.
-			*                  If NULL, then "key" will be added with no value.
-			*                  If non-NULL but valueSize is zero, then "key=" will be
-			*                  added with empty value.
-			*
-			* exceptions:      Throws kDNSServiceErr_Invalid if the "key" string contains
-			*                  illegal characters.
-			*                  Throws kDNSServiceErr_NoMemory if adding this key would
-			*                  exceed the available storage.
-			*/
-
-			void
-			SetValue
-				(
-				String	*	key,
-				Byte		value[]  /* may be NULL */
-				);
-
-
-			/* RemoveValue()
-			*
-			* Removes a key from a TextRecord.  The "key" must be an
-			* ASCII string which exists in the TextRecord.
-			*
-			* key:             A key name which exists in the TextRecord.
-			*
-			* exceptions:      Throws kDNSServiceErr_NoSuchKey if the "key" does not
-			*                  exist in the TextRecord.
-			*
-			*/
-
-			void
-			RemoveValue
-				(
-				String	*	key
-				);
-
-
-			/* GetLength()
-			*
-			* Allows you to determine the length of the raw bytes within a TextRecord.
-			*
-			* return value :     Returns the size of the raw bytes inside a TextRecord
-			*                  which you can pass directly to DNSServiceRegister() or
-			*                  to DNSServiceUpdateRecord().
-			*                  Returns 0 if the TextRecord is empty.
-			*
-			*/
-
-			int
-			GetLength
-				(
-				);
-
-
-			/* GetBytes()
-			*
-			* Allows you to retrieve a pointer to the raw bytes within a TextRecord.
-			*
-			* return value:    Returns a pointer to the bytes inside the TextRecord
-			*                  which you can pass directly to DNSServiceRegister() or
-			*                  to DNSServiceUpdateRecord().
-			*
-			*/
-
-			Byte
-			GetBytes
-				(
-				) __gc[];
-
-
-			/*********************************************************************************************
-			*
-			*   TXT Record Parsing Functions
-			*
-			*********************************************************************************************/
-
-			/*
-			* A typical calling sequence for TXT record parsing is something like:
-			*
-			* Receive TXT record data in DNSServiceResolve() callback
-			* if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
-			* val1ptr = DNSService.TextService.GetValue(txtRecord, "key1", &len1);
-			* val2ptr = DNSService.TextService.GetValue(txtRecord, "key2", &len2);
-			* ...
-			* return;
-			*
-			*/
-
-			/* ContainsKey()
-			*
-			* Allows you to determine if a given TXT Record contains a specified key.
-			*
-			* txtRecord:       Pointer to the received TXT Record bytes.
-			*
-			* key:             A null-terminated ASCII string containing the key name.
-			*
-			* return value:    Returns 1 if the TXT Record contains the specified key.
-			*                  Otherwise, it returns 0.
-			*
-			*/
-
-			static public bool
-			ContainsKey
-				(
-				Byte		txtRecord[],
-				String	*	key
-				);
-
-
-			/* GetValueBytes()
-			*
-			* Allows you to retrieve the value for a given key from a TXT Record.
-			*
-			* txtRecord:       Pointer to the received TXT Record bytes.
-			*
-			* key:             A null-terminated ASCII string containing the key name.
-			*
-			* return value:    Returns NULL if the key does not exist in this TXT record,
-			*                  or exists with no value (to differentiate between
-			*                  these two cases use ContainsKey()).
-			*                  Returns byte array 
-			*                  if the key exists with empty or non-empty value.
-			*                  For empty value, length of byte array will be zero.
-			*                  For non-empty value, it will be the length of value data.
-			*/
-
-			static public Byte
-			GetValueBytes
-				(
-				Byte		txtRecord[],
-				String	*	key
-				) __gc[];
-
-
-			/* GetCount()
-			*
-			* Returns the number of keys stored in the TXT Record.  The count
-			* can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
-			*
-			* txtRecord:       Pointer to the received TXT Record bytes.
-			*
-			* return value:    Returns the total number of keys in the TXT Record.
-			*
-			*/
-
-			static public int
-			GetCount
-				(
-				Byte	txtRecord[]
-				);
-
-
-			/* GetItemAtIndex()
-			*
-			* Allows you to retrieve a key name and value pointer, given an index into
-			* a TXT Record.  Legal index values range from zero to TXTRecordGetCount()-1.
-			* It's also possible to iterate through keys in a TXT record by simply
-			* calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
-			* and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
-			*
-			* On return:
-			* For keys with no value, *value is set to NULL and *valueLen is zero.
-			* For keys with empty value, *value is non-NULL and *valueLen is zero.
-			* For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
-			*
-			* txtRecord:       Pointer to the received TXT Record bytes.
-			*
-			* index:           An index into the TXT Record.
-			*
-			* key:             A string buffer used to store the key name.
-			*                  On return, the buffer contains a string
-			*                  giving the key name. DNS-SD TXT keys are usually
-			*                  14 characters or less. 
-			*
-			* return value:    Record bytes that holds the value data.
-			*
-			* exceptions:      Throws kDNSServiceErr_Invalid if index is greater than
-			*                  GetCount()-1.
-			*/
-
-			static public Byte
-			GetItemAtIndex
-				(
-				Byte				txtRecord[],
-				int					index,
-				[Out] String	**	key
-				) __gc[];
-		};
-
-
-		public __abstract __gc class DNSService
-		{
-		public:
-
-			/*********************************************************************************************
-			*
-			* Domain Enumeration
-			*
-			*********************************************************************************************/
-
-			/* DNSServiceEnumerateDomains()
-			*
-			* Asynchronously enumerate domains available for browsing and registration.
-			* Currently, the only domain returned is "local.", but other domains will be returned in future.
-			*
-			* The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
-			* are to be found.
-			*
-			*
-			* EnumerateDomainsReply Delegate
-			*
-			* This Delegate is invoked upon a reply from an EnumerateDomains call.
-			*
-			* sdRef:           The DNSServiceRef initialized by DNSServiceEnumerateDomains().
-			*
-			* flags:           Possible values are:
-			*                  MoreComing
-			*                  Add
-			*                  Default
-			*
-			* interfaceIndex:  Specifies the interface on which the domain exists.  (The index for a given
-			*                  interface is determined via the if_nametoindex() family of calls.)
-			*
-			* errorCode:       Will be NoError (0) on success, otherwise indicates
-			*                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
-			*
-			* replyDomain:     The name of the domain.
-			*
-			*/
-
-			__delegate void
-			EnumerateDomainsReply
-				(
-				ServiceRef	*	sdRef,
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	replyDomain
-				);
-
-			/* DNSServiceEnumerateDomains() Parameters:
-			*
-			*
-			* flags:           Possible values are:
-			*                  BrowseDomains to enumerate domains recommended for browsing.
-			*                  RegistrationDomains to enumerate domains recommended
-			*                  for registration.
-			*
-			* interfaceIndex:  If non-zero, specifies the interface on which to look for domains.
-			*                  (the index for a given interface is determined via the if_nametoindex()
-			*                  family of calls.)  Most applications will pass 0 to enumerate domains on
-			*                  all interfaces.
-			*
-			* callback:        The delegate to be called when a domain is found or the call asynchronously
-			*                  fails.
-			*
-			*
-			* return value:    Returns initialize ServiceRef on succeses (any subsequent, asynchronous
-			*                  errors are delivered to the delegate), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is not invoked and the ServiceRef
-			*                  is not initialized.)
-			*/
-
-			static public ServiceRef*
-			EnumerateDomains
-				(
-				int							flags,
-				int							interfaceIndex,
-				EnumerateDomainsReply	*	callback
-				);
-
-			/*********************************************************************************************
-			*
-			*  Service Registration
-			*
-			*********************************************************************************************/
-
-			/* Register a service that is discovered via Browse() and Resolve() calls.
-			* 
-			* RegisterReply() Callback Parameters:
-			*
-			* sdRef:           The ServiceRef initialized by Register().
-			*
-			* flags:           Currently unused, reserved for future use.
-			*
-			* errorCode:       Will be NoError on success, otherwise will
-			*                  indicate the failure that occurred (including name conflicts, if the
-			*                  NoAutoRename flag was passed to the
-			*                  callout.)  Other parameters are undefined if errorCode is nonzero.
-			*
-			* name:            The service name registered (if the application did not specify a name in
-			*                  DNSServiceRegister(), this indicates what name was automatically chosen).
-			*
-			* regtype:         The type of service registered, as it was passed to the callout.
-			*
-			* domain:          The domain on which the service was registered (if the application did not
-			*                  specify a domain in Register(), this indicates the default domain
-			*                  on which the service was registered).
-			*
-			*/
-
-			__delegate void
-			RegisterReply
-				(
-				ServiceRef	*	sdRef,
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
-				String		*	name,
-				String		*	regtype,
-				String		*	domain
-				);
-
-			/* Register()  Parameters:
-			*
-			* flags:           Indicates the renaming behavior on name conflict (most applications
-			*                  will pass 0).  See flag definitions above for details.
-			*
-			* interfaceIndex:  If non-zero, specifies the interface on which to register the service
-			*                  (the index for a given interface is determined via the if_nametoindex()
-			*                  family of calls.)  Most applications will pass 0 to register on all
-			*                  available interfaces.  Pass -1 to register a service only on the local
-			*                  machine (service will not be visible to remote hosts.)
-			*
-			* name:            If non-NULL, specifies the service name to be registered.
-			*                  Most applications will not specify a name, in which case the
-			*                  computer name is used (this name is communicated to the client via
-			*                  the callback).
-			*
-			* regtype:         The service type followed by the protocol, separated by a dot
-			*                  (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
-			*                  New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html.
-			*
-			* domain:          If non-NULL, specifies the domain on which to advertise the service.
-			*                  Most applications will not specify a domain, instead automatically
-			*                  registering in the default domain(s).
-			*
-			* host:            If non-NULL, specifies the SRV target host name.  Most applications
-			*                  will not specify a host, instead automatically using the machine's
-			*                  default host name(s).  Note that specifying a non-NULL host does NOT
-			*                  create an address record for that host - the application is responsible
-			*                  for ensuring that the appropriate address record exists, or creating it
-			*                  via DNSServiceRegisterRecord().
-			*
-			* port:            The port, in host byte order, on which the service accepts connections.
-			*                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
-			*                  by browsing, but will cause a name conflict if another client tries to
-			*                  register that same name).  Most clients will not use placeholder services.
-			*
-			* txtRecord:       The txt record rdata.  May be NULL.  Note that a non-NULL txtRecord
-			*                  MUST be a properly formatted DNS TXT record, i.e. <length byte> <data>
-			*                  <length byte> <data> ...
-			*
-			* callback:        The delegate to be called when the registration completes or asynchronously
-			*                  fails.  The client MAY pass NULL for the callback -  The client will NOT be notified
-			*                  of the default values picked on its behalf, and the client will NOT be notified of any
-			*                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
-			*                  of the service.  The client may NOT pass the NoAutoRename flag if the callback is NULL.
-			*                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
-			*
-			* return value:    Returns initialize ServiceRef (any subsequent, asynchronous
-			*                  errors are delivered to the callback), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is never invoked and the DNSServiceRef
-			*                  is not initialized.)
-			*
-			*/
-			static public ServiceRef*
-			Register
-				(
-				int					flags,
-				int					interfaceIndex,
-				String			*	name,
-				String			*	regtype,
-				String			*	domain,
-				String			*	host,
-				int					port,
-				Byte				txtRecord[],
-				RegisterReply	*	callback
-				);
-
-			/* AddRecord()
-			*
-			* Add a record to a registered service.  The name of the record will be the same as the
-			* registered service's name.
-			* The record can later be updated or deregistered by passing the RecordRef initialized
-			* by this function to UpdateRecord() or RemoveRecord().
-			*
-			*
-			* Parameters;
-			*
-			* sdRef:           A ServiceRef initialized by Register().
-			*
-			* RecordRef:       A pointer to an uninitialized RecordRef.  Upon succesfull completion of this
-			*                  call, this ref may be passed to UpdateRecord() or RemoveRecord().
-			*                  If the above ServiceRef is disposed, RecordRef is also
-			*                  invalidated and may not be used further.
-			*
-			* flags:           Currently ignored, reserved for future use.
-			*
-			* rrtype:          The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h.
-			*
-			* rdata:           The raw rdata to be contained in the added resource record.
-			*
-			* ttl:             The time to live of the resource record, in seconds.
-			*
-			* return value:    Returns initialized RecordRef, otherwise throws
-			*                  an exception indicating the error that occurred (the RecordRef is not initialized).
-			*/
-
-			static public RecordRef*
-			AddRecord
-				(
-				ServiceRef	*	sref,
-				int				flags,
-				int				rrtype,
-				Byte			rdata[],
-				int				ttl
-				);
-
-			/* UpdateRecord
-			*
-			* Update a registered resource record.  The record must either be:
-			*   - The primary txt record of a service registered via Register()
-			*   - A record added to a registered service via AddRecord()
-			*   - An individual record registered by RegisterRecord()
-			*
-			*
-			* Parameters:
-			*
-			* sdRef:           A ServiceRef that was initialized by Register()
-			*                  or CreateConnection().
-			*
-			* RecordRef:       A RecordRef initialized by AddRecord, or NULL to update the
-			*                  service's primary txt record.
-			*
-			* flags:           Currently ignored, reserved for future use.
-			*
-			* rdata:           The new rdata to be contained in the updated resource record.
-			*
-			* ttl:             The time to live of the updated resource record, in seconds.
-			*
-			* return value:    No return value on success, otherwise throws an exception
-			*                  indicating the error that occurred.
-			*/
-			static public void
-			UpdateRecord
-				(
-				ServiceRef	*	sref,
-				RecordRef	*	record,
-				int				flags,
-				Byte			rdata[],
-				int				ttl
-				);
-
-			/* RemoveRecord
-			*
-			* Remove a record previously added to a service record set via AddRecord(), or deregister
-			* an record registered individually via RegisterRecord().
-			*
-			* Parameters:
-			*
-			* sdRef:           A ServiceRef initialized by Register() (if the
-			*                  record being removed was registered via AddRecord()) or by
-			*                  CreateConnection() (if the record being removed was registered via
-			*                  RegisterRecord()).
-			*
-			* recordRef:       A RecordRef initialized by a successful call to AddRecord()
-			*                  or RegisterRecord().
-			*
-			* flags:           Currently ignored, reserved for future use.
-			*
-			* return value:    Nothing on success, otherwise throws an
-			*                  exception indicating the error that occurred.
-			*/
-
-			static public void
-			RemoveRecord
-							(
-							ServiceRef	*	sref,
-							RecordRef	*	record,	
-							int				flags
-							);
-
-			/*********************************************************************************************
-			*
-			*  Service Discovery
-			*
-			*********************************************************************************************/
-
-			/* Browse for instances of a service.
-			*
-			*
-			* BrowseReply() Parameters:
-			*
-			* sdRef:           The DNSServiceRef initialized by Browse().
-			*
-			* flags:           Possible values are MoreComing and Add.
-			*                  See flag definitions for details.
-			*
-			* interfaceIndex:  The interface on which the service is advertised.  This index should
-			*                  be passed to Resolve() when resolving the service.
-			*
-			* errorCode:       Will be NoError (0) on success, otherwise will
-			*                  indicate the failure that occurred.  Other parameters are undefined if
-			*                  the errorCode is nonzero.
-			*
-			* serviceName:     The service name discovered.
-			*
-			* regtype:         The service type, as passed in to Browse().
-			* 
-			* domain:          The domain on which the service was discovered (if the application did not
-			*                  specify a domain in Browse(), this indicates the domain on which the
-			*                  service was discovered.)
-			*
-			*/
-
-			__delegate void
-			BrowseReply
-				(
-				ServiceRef	*	sdRef,
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	name,
-				String		*	type,
-				String		*	domain
-				);
-
-			/* DNSServiceBrowse() Parameters:
-			*
-			* sdRef:           A pointer to an uninitialized ServiceRef.  Call ServiceRef.Dispose()
-			*                  to terminate the browse.
-			*
-			* flags:           Currently ignored, reserved for future use.
-			*
-			* interfaceIndex:  If non-zero, specifies the interface on which to browse for services
-			*                  (the index for a given interface is determined via the if_nametoindex()
-			*                  family of calls.)  Most applications will pass 0 to browse on all available
-			*                  interfaces.  Pass -1 to only browse for services provided on the local host.
-			*
-			* regtype:         The service type being browsed for followed by the protocol, separated by a
-			*                  dot (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
-			*
-			* domain:          If non-NULL, specifies the domain on which to browse for services.
-			*                  Most applications will not specify a domain, instead browsing on the
-			*                  default domain(s).
-			*
-			* callback:        The delegate to be called when an instance of the service being browsed for
-			*                  is found, or if the call asynchronously fails.
-			*
-			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
-			*                  errors are delivered to the callback), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is not invoked and the ServiceRef
-			*                  is not initialized.)
-			*/
-
-			static public ServiceRef*
-			Browse
-				(
-				int				flags,
-				int				interfaceIndex,
-				String		*	regtype,
-				String		*	domain,
-				BrowseReply	*	callback
-				);
-
-			/* ResolveReply() Parameters:
-			*
-			* Resolve a service name discovered via Browse() to a target host name, port number, and
-			* txt record.
-			*
-			* Note: Applications should NOT use Resolve() solely for txt record monitoring - use
-			* QueryRecord() instead, as it is more efficient for this task.
-			*
-			* Note: When the desired results have been returned, the client MUST terminate the resolve by calling
-			* ServiceRef.Dispose().
-			*
-			* Note: Resolve() behaves correctly for typical services that have a single SRV record and
-			* a single TXT record (the TXT record may be empty.)  To resolve non-standard services with multiple
-			* SRV or TXT records, QueryRecord() should be used.
-			*
-			* ResolveReply Callback Parameters:
-			*
-			* sdRef:           The DNSServiceRef initialized by Resolve().
-			*
-			* flags:           Currently unused, reserved for future use.
-			*
-			* interfaceIndex:  The interface on which the service was resolved.
-			*
-			* errorCode:       Will be NoError (0) on success, otherwise will
-			*                  indicate the failure that occurred.  Other parameters are undefined if
-			*                  the errorCode is nonzero.
-			*
-			* fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
-			*                  (Any literal dots (".") are escaped with a backslash ("\."), and literal
-			*                  backslashes are escaped with a second backslash ("\\"), e.g. a web server
-			*                  named "Dr. Pepper" would have the fullname  "Dr\.\032Pepper._http._tcp.local.").
-			*                  This is the appropriate format to pass to standard system DNS APIs such as
-			*                  res_query(), or to the special-purpose functions included in this API that
-			*                  take fullname parameters.
-			*
-			* hosttarget:      The target hostname of the machine providing the service.  This name can
-			*                  be passed to functions like gethostbyname() to identify the host's IP address.
-			*
-			* port:            The port, in host byte order, on which connections are accepted for this service.
-			*
-			* txtRecord:       The service's primary txt record, in standard txt record format.
-			*
-			*/
-
-			__delegate void
-			ResolveReply
-				(	
-				ServiceRef	*	sdRef,  
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,
-				String		*	fullName,
-				String		*	hostName,
-				int				port,
-				Byte			txtRecord[]
-				);
-
-			/* Resolve() Parameters
-			*
-			* flags:           Currently ignored, reserved for future use.
-			*
-			* interfaceIndex:  The interface on which to resolve the service.  The client should
-			*                  pass the interface on which the servicename was discovered, i.e.
-			*                  the interfaceIndex passed to the DNSServiceBrowseReply callback,
-			*                  or 0 to resolve the named service on all available interfaces.
-			*
-			* name:            The servicename to be resolved.
-			*
-			* regtype:         The service type being resolved followed by the protocol, separated by a
-			*                  dot (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
-			*
-			* domain:          The domain on which the service is registered, i.e. the domain passed
-			*                  to the DNSServiceBrowseReply callback.
-			*
-			* callback:        The delegate to be called when a result is found, or if the call
-			*                  asynchronously fails.
-			*
-			*
-			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
-			*                  errors are delivered to the callback), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is never invoked and the DNSServiceRef
-			*                  is not initialized.)
-			*/
-
-			static public ServiceRef*
-			Resolve
-				(
-				int					flags,
-				int					interfaceIndex,
-				String			*	name,
-				String			*	regtype,
-				String			*	domain,
-				ResolveReply	*	callback
-				);
-
-			/*********************************************************************************************
-			*
-			*  Special Purpose Calls (most applications will not use these)
-			*
-			*********************************************************************************************/
-
-			/* CreateConnection/RegisterRecord
-			*
-			* Register an individual resource record on a connected ServiceRef.
-			*
-			* Note that name conflicts occurring for records registered via this call must be handled
-			* by the client in the callback.
-			*
-			*
-			* RecordReply() parameters:
-			*
-			* sdRef:           The connected ServiceRef initialized by
-			*                  CreateConnection().
-			*
-			* RecordRef:       The RecordRef initialized by RegisterRecord().  If the above
-			*                  ServiceRef.Dispose is called, this RecordRef is
-			*                  invalidated, and may not be used further.
-			*
-			* flags:           Currently unused, reserved for future use.
-			*
-			* errorCode:       Will be NoError on success, otherwise will
-			*                  indicate the failure that occurred (including name conflicts.)
-			*                  Other parameters are undefined if errorCode is nonzero.
-			*
-			*/
-
-			__delegate void
-			RegisterRecordReply
-				(
-				ServiceRef	*	sdRef,
-				ServiceFlags	flags,
-				ErrorCode		errorCode,
-				RecordRef	*	record
-				);
-
-			/* CreateConnection()
-			*
-			* Create a connection to the daemon allowing efficient registration of
-			* multiple individual records.
-			*
-			*
-			* Parameters:
-			*
-			* callback:        The delegate to be called when a result is found, or if the call
-			*                  asynchronously fails (e.g. because of a name conflict.)
-			*
-			* return value:    Returns initialize ServiceRef on success, otherwise throws
-			*                  an exception indicating the specific failure that occurred (in which
-			*                  case the ServiceRef is not initialized).
-			*/
-
-			static public ServiceRef*
-			CreateConnection
-				(
-				RegisterRecordReply * callback
-				);
-
-
-			/* RegisterRecord() Parameters:
-			*
-			* sdRef:           A ServiceRef initialized by CreateConnection().
-			*
-			* RecordRef:       A pointer to an uninitialized RecordRef.  Upon succesfull completion of this
-			*                  call, this ref may be passed to UpdateRecord() or RemoveRecord().
-			*                  (To deregister ALL records registered on a single connected ServiceRef
-			*                  and deallocate each of their corresponding RecordRefs, call
-			*                  ServiceRef.Dispose()).
-			*
-			* flags:           Possible values are Shared or Unique
-			*                  (see flag type definitions for details).
-			*
-			* interfaceIndex:  If non-zero, specifies the interface on which to register the record
-			*                  (the index for a given interface is determined via the if_nametoindex()
-			*                  family of calls.)  Passing 0 causes the record to be registered on all interfaces.
-			*                  Passing -1 causes the record to only be visible on the local host.
-			*
-			* fullname:        The full domain name of the resource record.
-			*
-			* rrtype:          The numerical type of the resource record (e.g. PTR, SRV, etc), as defined
-			*                  in nameser.h.
-			*
-			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1 for the
-			*                  Internet class).
-			*
-			* rdata:           A pointer to the raw rdata, as it is to appear in the DNS record.
-			*
-			* ttl:             The time to live of the resource record, in seconds.
-			*
-			*
-			* return value:    Returns initialize RecordRef on succeses (any subsequent, asynchronous
-			*                  errors are delivered to the callback), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is never invoked and the RecordRef is
-			*                  not initialized.)
-			*/
-			static public RecordRef*
-			RegisterRecord
-				(
-				ServiceRef			*	sdRef,
-				ServiceFlags			flags,
-				int						interfaceIndex,
-				String				*	fullname,
-				int						rrtype,
-				int						rrclass,
-				Byte					rdata[],
-				int						ttl
-				);
-
-
-			/* DNSServiceQueryRecord
-			*
-			* Query for an arbitrary DNS record.
-			*
-			*
-			* QueryRecordReply() Delegate Parameters:
-			*
-			* sdRef:           The ServiceRef initialized by QueryRecord().
-			*
-			* flags:           Possible values are MoreComing and
-			*                  Add.  The Add flag is NOT set for PTR records
-			*                  with a ttl of 0, i.e. "Remove" events.
-			*
-			* interfaceIndex:  The interface on which the query was resolved (the index for a given
-			*                  interface is determined via the if_nametoindex() family of calls).
-			*
-			* errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
-			*                  indicate the failure that occurred.  Other parameters are undefined if
-			*                  errorCode is nonzero.
-			*
-			* fullname:        The resource record's full domain name.
-			*
-			* rrtype:          The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
-			*
-			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1).
-			*
-			* rdata:           The raw rdata of the resource record.
-			*
-			* ttl:             The resource record's time to live, in seconds.
-			*
-			*/
-
-			__delegate void
-			QueryRecordReply
-				(
-				ServiceRef	*	sdRef,
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				ErrorCode		errorCode,	
-				String		*	fullName,
-				int				rrtype,
-				int				rrclass,
-				Byte			rdata[],
-				int				ttl
-				);
-
-			/* QueryRecord() Parameters:
-			*
-			* flags:           Pass LongLivedQuery to create a "long-lived" unicast
-			*                  query in a non-local domain.  Without setting this flag, unicast queries
-			*                  will be one-shot - that is, only answers available at the time of the call
-			*                  will be returned.  By setting this flag, answers (including Add and Remove
-			*                  events) that become available after the initial call is made will generate
-			*                  callbacks.  This flag has no effect on link-local multicast queries.
-			*
-			* interfaceIndex:  If non-zero, specifies the interface on which to issue the query
-			*                  (the index for a given interface is determined via the if_nametoindex()
-			*                  family of calls.)  Passing 0 causes the name to be queried for on all
-			*                  interfaces.  Passing -1 causes the name to be queried for only on the
-			*                  local host.
-			*
-			* fullname:        The full domain name of the resource record to be queried for.
-			*
-			* rrtype:          The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc)
-			*                  as defined in nameser.h.
-			*
-			* rrclass:         The class of the resource record, as defined in nameser.h
-			*                  (usually 1 for the Internet class).
-			*
-			* callback:        The delegate to be called when a result is found, or if the call
-			*                  asynchronously fails.
-			*
-			*
-			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
-			*                  errors are delivered to the callback), otherwise throws an exception indicating
-			*                  the error that occurred (the callback is never invoked and the ServiceRef
-			*                  is not initialized.)
-			*/
-
-			static public ServiceRef*
-			QueryRecord
-				(
-				ServiceFlags			flags,
-				int						interfaceIndex,
-				String				*	fullname,
-				int						rrtype,
-				int						rrclass,
-				QueryRecordReply	*	callback
-				);
-
-			/* ReconfirmRecord
-			*
-			* Instruct the daemon to verify the validity of a resource record that appears to
-			* be out of date (e.g. because tcp connection to a service's target failed.)
-			* Causes the record to be flushed from the daemon's cache (as well as all other
-			* daemons' caches on the network) if the record is determined to be invalid.
-			*
-			* Parameters:
-			*
-			* flags:           Currently unused, reserved for future use.
-			*
-			* fullname:        The resource record's full domain name.
-			*
-			* rrtype:          The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
-			*
-			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1).
-			*
-			* rdata:           The raw rdata of the resource record.
-			*
-			*/
-			static public void
-			ReconfirmRecord
-				(
-				ServiceFlags	flags,
-				int				interfaceIndex,
-				String		*	fullname,
-				int				rrtype,
-				int				rrclass,
-				Byte			rdata[]
-				);
-		};
-	}
-}
diff --git a/mDNSWindows/DLL.NET/resource.h b/mDNSWindows/DLL.NET/resource.h
deleted file mode 100644
index 9a14836..0000000
--- a/mDNSWindows/DLL.NET/resource.h
+++ /dev/null
@@ -1,3 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by dnssd_NET.rc
diff --git a/mDNSWindows/DLL/dllmain.c b/mDNSWindows/DLL/dllmain.c
deleted file mode 100644
index 7aadae8..0000000
--- a/mDNSWindows/DLL/dllmain.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2004-2021 Apple 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
- * 
- *     https://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.
- */
-
-#include <windows.h>
-#include <DebugServices.h>
-#include <stdlib.h>
-
-BOOL APIENTRY	DllMain( HANDLE inModule, DWORD inReason, LPVOID inReserved )
-{
-	(void) inModule;
-	(void) inReserved;
-	
-	switch( inReason )
-	{
-		case DLL_PROCESS_ATTACH:
-		case DLL_THREAD_ATTACH:
-		case DLL_THREAD_DETACH:
-		case DLL_PROCESS_DETACH:
-			break;
-	}
-	return( TRUE );
-}
-
-
-BOOL
-IsSystemServiceDisabled()
-{
-	ENUM_SERVICE_STATUS	*	lpService = NULL;
-	SC_HANDLE				sc;
-	BOOL					installed = FALSE;
-	BOOL					ret = FALSE;
-	BOOL					ok;
-	DWORD					bytesNeeded = 0;
-	DWORD					srvCount;
-	DWORD					resumeHandle = 0;
-	DWORD					srvType;
-	DWORD					srvState;
-	DWORD					dwBytes = 0;
-	DWORD					i;
-	OSStatus				err;
-
-	sc = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
-	err = translate_errno( sc, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	srvType		=	SERVICE_WIN32;
-	srvState		=	SERVICE_STATE_ALL;
-
-	for ( ;; )
-	{
-		// Call EnumServicesStatus using the handle returned by OpenSCManager
-
-		ok = EnumServicesStatus ( sc, srvType, srvState, lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle );
-
-		if ( ok || ( GetLastError() != ERROR_MORE_DATA ) )
-		{
-			break;
-		}
-
-		if ( lpService )
-		{
-			free( lpService );
-		}
-
-		dwBytes = bytesNeeded;
-
-		lpService = ( ENUM_SERVICE_STATUS* ) malloc( dwBytes );
-		require_action( lpService, exit, ret = FALSE );
-	}
-
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	for ( i = 0; i < srvCount; i++ )
-	{
-		if ( strcmp( lpService[i].lpServiceName, "Bonjour Service" ) == 0 )
-		{
-			installed = TRUE;
-
-			if ( ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_PAUSED ) || ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_STOPPED ) )
-			{
-				ret = TRUE;
-			}
-
-			break;
-		}
-	}
-
-exit:
-
-	if ( lpService )
-	{
-		free( lpService );
-	}
-
-	if ( sc )
-	{
-		CloseServiceHandle ( sc );
-	}
-
-	return (ret || installed == FALSE);
-}
diff --git a/mDNSWindows/DLL/resource.h b/mDNSWindows/DLL/resource.h
deleted file mode 100644
index bdea251..0000000
--- a/mDNSWindows/DLL/resource.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by dll.rc
-//
-#define IDS_PROJNAME                    100
-#define IDR_WMDMLOGGER                  101
-#define IDS_LOG_SEV_INFO                201
-#define IDS_LOG_SEV_WARN                202
-#define IDS_LOG_SEV_ERROR               203
-#define IDS_LOG_DATETIME                204
-#define IDS_LOG_SRCNAME                 205
-#define IDS_DEF_LOGFILE                 301
-#define IDS_DEF_MAXSIZE                 302
-#define IDS_DEF_SHRINKTOSIZE            303
-#define IDS_DEF_LOGENABLED              304
-#define IDS_MUTEX_TIMEOUT               401
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        201
-#define _APS_NEXT_COMMAND_VALUE         32768
-#define _APS_NEXT_CONTROL_VALUE         201
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/DLLStub/DLLStub.cpp b/mDNSWindows/DLLStub/DLLStub.cpp
deleted file mode 100644
index 38fd5e0..0000000
--- a/mDNSWindows/DLLStub/DLLStub.cpp
+++ /dev/null
@@ -1,693 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009, Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "DLLStub.h"
-
-static int		g_defaultErrorCode = kDNSServiceErr_ServiceNotRunning;
-static DLLStub	g_glueLayer;
-
-
-// ------------------------------------------
-// DLLStub implementation
-// ------------------------------------------
-DLLStub * DLLStub::m_instance;
-
-DLLStub::DLLStub()
-:
-	m_library( LoadLibrary( TEXT( "dnssd.dll" ) ) )
-{
-	m_instance = this;
-}
-
-
-DLLStub::~DLLStub()
-{
-	if ( m_library != NULL )
-	{
-		FreeLibrary( m_library );
-		m_library = NULL;
-	}
-
-	m_instance = NULL;
-}
-
-
-bool
-DLLStub::GetProcAddress( FARPROC * func, LPCSTR lpProcName )
-{ 
-	if ( m_instance && m_instance->m_library )
-	{
-		// Only call ::GetProcAddress if *func is NULL. This allows
-		// the calling code to cache the funcptr value, and we get
-		// some performance benefit.
-
-		if ( *func == NULL )
-		{
-			*func = ::GetProcAddress( m_instance->m_library, lpProcName );
-		}
-	}
-	else
-	{
-		*func = NULL;
-	}
-
-	return ( *func != NULL );
-}
-
-
-dnssd_sock_t DNSSD_API
-DNSServiceRefSockFD(DNSServiceRef sdRef)
-{
-	typedef int (DNSSD_API * Func)(DNSServiceRef sdRef);
-	static Func func = NULL;
-	int ret = INVALID_SOCKET;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceProcessResult(DNSServiceRef sdRef)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef sdRef);
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef );
-	}
-	
-	return ret;
-}
-
-
-void DNSSD_API
-DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-	typedef void (DNSSD_API * Func)(DNSServiceRef sdRef);
-	static Func func = NULL;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		func( sdRef );
-	}
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceEnumerateDomains
-		(
-		DNSServiceRef                       *sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		DNSServiceDomainEnumReply           callBack,
-		void                                *context
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceDomainEnumReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceRegister
-		(
-		DNSServiceRef                       *sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		const char                          *name,
-		const char                          *regtype,
-		const char                          *domain,
-		const char                          *host,
-		uint16_t                            port,
-		uint16_t                            txtLen,
-		const void                          *txtRecord,
-		DNSServiceRegisterReply             callBack,
-		void                                *context
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, const char*, const char*, uint16_t, uint16_t, const void*, DNSServiceRegisterReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceAddRecord
-		(
-		DNSServiceRef                       sdRef,
-		DNSRecordRef                        *RecordRef,
-		DNSServiceFlags                     flags,
-		uint16_t                            rrtype,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef*, DNSServiceFlags, uint16_t, uint16_t, const void*, uint32_t );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, RecordRef, flags, rrtype, rdlen, rdata, ttl );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceUpdateRecord
-		(
-		DNSServiceRef                       sdRef,
-		DNSRecordRef                        RecordRef,     /* may be NULL */
-		DNSServiceFlags                     flags,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef, DNSServiceFlags, uint16_t, const void*, uint32_t );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, RecordRef, flags, rdlen, rdata, ttl );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceRemoveRecord
-		(
-		DNSServiceRef                 sdRef,
-		DNSRecordRef                  RecordRef,
-		DNSServiceFlags               flags
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef, DNSServiceFlags );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, RecordRef, flags );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceBrowse
-		(
-		DNSServiceRef                       *sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		const char                          *regtype,
-		const char                          *domain,    /* may be NULL */
-		DNSServiceBrowseReply               callBack,
-		void                                *context    /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, DNSServiceBrowseReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, regtype, domain, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceResolve
-		(
-		DNSServiceRef                       *sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		const char                          *name,
-		const char                          *regtype,
-		const char                          *domain,
-		DNSServiceResolveReply              callBack,
-		void                                *context  /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, const char*, const char*, DNSServiceResolveReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceConstructFullName
-		(
-		char                            *fullName,
-		const char                      *service,      /* may be NULL */
-		const char                      *regtype,
-		const char                      *domain
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( char*, const char*, const char*, const char* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( fullName, service, regtype, domain );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceCreateConnection(DNSServiceRef *sdRef)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( DNSServiceRef* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceRegisterRecord
-		(
-		DNSServiceRef                       sdRef,
-		DNSRecordRef                        *RecordRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		const char                          *fullname,
-		uint16_t                            rrtype,
-		uint16_t                            rrclass,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl,
-		DNSServiceRegisterRecordReply       callBack,
-		void                                *context    /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef, DNSRecordRef*, DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, uint16_t, const void*, uint16_t, DNSServiceRegisterRecordReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceQueryRecord
-		(
-		DNSServiceRef                       *sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		const char                          *fullname,
-		uint16_t                            rrtype,
-		uint16_t                            rrclass,
-		DNSServiceQueryRecordReply          callBack,
-		void                                *context  /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, DNSServiceQueryRecordReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceReconfirmRecord
-		(
-		DNSServiceFlags                    flags,
-		uint32_t                           interfaceIndex,
-		const char                         *fullname,
-		uint16_t                           rrtype,
-		uint16_t                           rrclass,
-		uint16_t                           rdlen,
-		const void                         *rdata
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( DNSServiceFlags, uint32_t, const char*, uint16_t, uint16_t, uint16_t, const void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceNATPortMappingCreate
-		(
-		DNSServiceRef                    *sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         interfaceIndex,
-		DNSServiceProtocol               protocol,          /* TCP and/or UDP          */
-		uint16_t                         internalPort,      /* network byte order      */
-		uint16_t                         externalPort,      /* network byte order      */
-		uint32_t                         ttl,               /* time to live in seconds */
-		DNSServiceNATPortMappingReply    callBack,
-		void                             *context           /* may be NULL             */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceProtocol, uint16_t, uint16_t, uint16_t, DNSServiceNATPortMappingReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, protocol, internalPort, externalPort, ttl, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceGetAddrInfo
-		(
-		DNSServiceRef                    *sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         interfaceIndex,
-		DNSServiceProtocol               protocol,
-		const char                       *hostname,
-		DNSServiceGetAddrInfoReply       callBack,
-		void                             *context          /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)(DNSServiceRef*, DNSServiceFlags, uint32_t, DNSServiceProtocol, const char*, DNSServiceGetAddrInfoReply, void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( sdRef, flags, interfaceIndex, protocol, hostname, callBack, context );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-DNSServiceGetProperty
-		(
-		const char *property,  /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
-		void       *result,    /* Pointer to place to store result */
-		uint32_t   *size       /* size of result location */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( const char*, void*, uint32_t* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( property, result, size );
-	}
-	
-	return ret;
-}
-
-
-void DNSSD_API
-TXTRecordCreate
-		(
-		TXTRecordRef     *txtRecord,
-		uint16_t         bufferLen,
-		void             *buffer
-		)
-{
-	typedef void (DNSSD_API * Func)( TXTRecordRef*, uint16_t, void* );
-	static Func func = NULL;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		func( txtRecord, bufferLen, buffer );
-	}
-}
-
-
-void DNSSD_API
-TXTRecordDeallocate
-		(
-		TXTRecordRef     *txtRecord
-		)
-{
-	typedef void (DNSSD_API * Func)( TXTRecordRef* );
-	static Func func = NULL;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		func( txtRecord );
-	}
-}
-
-
-DNSServiceErrorType DNSSD_API
-TXTRecordSetValue
-		(
-		TXTRecordRef     *txtRecord,
-		const char       *key,
-		uint8_t          valueSize,        /* may be zero */
-		const void       *value            /* may be NULL */
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( TXTRecordRef*, const char*, uint8_t, const void* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtRecord, key, valueSize, value );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-TXTRecordRemoveValue
-		(
-		TXTRecordRef     *txtRecord,
-		const char       *key
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( TXTRecordRef*, const char* );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtRecord, key );
-	}
-	
-	return ret;
-}
-
-
-int DNSSD_API
-TXTRecordContainsKey
-		(
-		uint16_t         txtLen,
-		const void       *txtRecord,
-		const char       *key
-		)
-{
-	typedef int (DNSSD_API * Func)( uint16_t, const void*, const char* );
-	static Func func = NULL;
-	int ret = 0;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtLen, txtRecord, key );
-	}
-	
-	return ret;
-}
-
-
-uint16_t DNSSD_API
-TXTRecordGetCount
-		(
-		uint16_t         txtLen,
-		const void       *txtRecord
-		)
-{
-	typedef uint16_t (DNSSD_API * Func)( uint16_t, const void* );
-	static Func func = NULL;
-	uint16_t ret = 0;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtLen, txtRecord );
-	}
-	
-	return ret;
-}
-
-
-uint16_t DNSSD_API
-TXTRecordGetLength
-		(
-		const TXTRecordRef *txtRecord
-		)
-{
-	typedef uint16_t (DNSSD_API * Func)( const TXTRecordRef* );
-	static Func func = NULL;
-	uint16_t ret = 0;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtRecord );
-	}
-	
-	return ret;
-}
-
-
-const void * DNSSD_API
-TXTRecordGetBytesPtr
-		(
-		const TXTRecordRef *txtRecord
-		)
-{
-	typedef const void* (DNSSD_API * Func)( const TXTRecordRef* );
-	static Func func = NULL;
-	const void* ret = NULL;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtRecord );
-	}
-	
-	return ret;
-}
-
-
-const void * DNSSD_API
-TXTRecordGetValuePtr
-		(
-		uint16_t         txtLen,
-		const void       *txtRecord,
-		const char       *key,
-		uint8_t          *valueLen
-		)
-{
-	typedef const void* (DNSSD_API * Func)( uint16_t, const void*, const char*, uint8_t* );
-	static Func func = NULL;
-	const void* ret = NULL;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtLen, txtRecord, key, valueLen );
-	}
-	
-	return ret;
-}
-
-
-DNSServiceErrorType DNSSD_API
-TXTRecordGetItemAtIndex
-		(
-		uint16_t         txtLen,
-		const void       *txtRecord,
-		uint16_t         itemIndex,
-		uint16_t         keyBufLen,
-		char             *key,
-		uint8_t          *valueLen,
-		const void       **value
-		)
-{
-	typedef DNSServiceErrorType (DNSSD_API * Func)( uint16_t, const void*, uint16_t, uint16_t, char*, uint8_t*, const void** );
-	static Func func = NULL;
-	DNSServiceErrorType ret = g_defaultErrorCode;
-
-	if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
-	{
-		ret = func( txtLen, txtRecord, itemIndex, keyBufLen, key, valueLen, value );
-	}
-	
-	return ret;
-}
diff --git a/mDNSWindows/DLLStub/DLLStub.h b/mDNSWindows/DLLStub/DLLStub.h
deleted file mode 100644
index 481298d..0000000
--- a/mDNSWindows/DLLStub/DLLStub.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009, Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _DLLStub_h
-#define _DLLStub_h
-
-#include <windows.h>
-#include <dns_sd.h>
-
-class DLLStub
-{
-public:
-
-	DLLStub();
-	~DLLStub();
-
-	static bool
-	GetProcAddress( FARPROC * func, LPCSTR lpProcName );
-
-private:
-
-	static DLLStub	*	m_instance;
-	HMODULE				m_library;
-};
-
-
-#endif
diff --git a/mDNSWindows/DLLX/DLLX.cpp b/mDNSWindows/DLLX/DLLX.cpp
deleted file mode 100644
index 77883cc..0000000
--- a/mDNSWindows/DLLX/DLLX.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-
-
-#include "stdafx.h"
-
-#include "resource.h"
-
-#include "DLLX.h"
-
-#include "dlldatax.h"
-
-#include <DebugServices.h>
-
-
-
-
-
-class CDLLComponentModule : public CAtlDllModuleT< CDLLComponentModule >
-
-{
-
-public :
-
-	DECLARE_LIBID(LIBID_Bonjour)
-
-	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DLLX, "{56608F9C-223B-4CB6-813D-85EDCCADFB4B}")
-
-};
-
-
-
-CDLLComponentModule _AtlModule;
-
-
-
-
-
-#ifdef _MANAGED
-
-#pragma managed(push, off)
-
-#endif
-
-
-
-// DLL Entry Point
-
-extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
-
-{
-
-	debug_initialize( kDebugOutputTypeWindowsDebugger );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
-
-
-
-#ifdef _MERGE_PROXYSTUB
-
-    if (!PrxDllMain(hInstance, dwReason, lpReserved))
-
-        return FALSE;
-
-#endif
-
-	hInstance;
-
-    return _AtlModule.DllMain(dwReason, lpReserved); 
-
-}
-
-
-
-#ifdef _MANAGED
-
-#pragma managed(pop)
-
-#endif
-
-
-
-
-
-
-
-
-
-// Used to determine whether the DLL can be unloaded by OLE
-
-STDAPI DllCanUnloadNow(void)
-
-{
-
-#ifdef _MERGE_PROXYSTUB
-
-    HRESULT hr = PrxDllCanUnloadNow();
-
-    if (hr != S_OK)
-
-        return hr;
-
-#endif
-
-    return _AtlModule.DllCanUnloadNow();
-
-}
-
-
-
-
-
-// Returns a class factory to create an object of the requested type
-
-STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
-
-{
-
-#ifdef _MERGE_PROXYSTUB
-
-    if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
-
-        return S_OK;
-
-#endif
-
-    return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
-
-}
-
-
-
-
-
-// DllRegisterServer - Adds entries to the system registry
-
-STDAPI DllRegisterServer(void)
-
-{
-
-    // registers object, typelib and all interfaces in typelib
-
-    HRESULT hr = _AtlModule.DllRegisterServer();
-
-#ifdef _MERGE_PROXYSTUB
-
-    if (FAILED(hr))
-
-        return hr;
-
-    hr = PrxDllRegisterServer();
-
-#endif
-
-	return hr;
-
-}
-
-
-
-
-
-// DllUnregisterServer - Removes entries from the system registry
-
-STDAPI DllUnregisterServer(void)
-
-{
-
-	HRESULT hr = _AtlModule.DllUnregisterServer();
-
-#ifdef _MERGE_PROXYSTUB
-
-    if (FAILED(hr))
-
-        return hr;
-
-    hr = PrxDllRegisterServer();
-
-    if (FAILED(hr))
-
-        return hr;
-
-    hr = PrxDllUnregisterServer();
-
-#endif
-
-	return hr;
-
-}
-
-
-
diff --git a/mDNSWindows/DLLX/DNSSD.cpp b/mDNSWindows/DLLX/DNSSD.cpp
deleted file mode 100644
index f011dd1..0000000
--- a/mDNSWindows/DLLX/DNSSD.cpp
+++ /dev/null
@@ -1,892 +0,0 @@
-// DNSSD.cpp : Implementation of CDNSSD
-
-#include "stdafx.h"
-#include "DNSSD.h"
-#include "DNSSDService.h"
-#include "TXTRecord.h"
-#include <dns_sd.h>
-#include <CommonServices.h>
-#include <DebugServices.h>
-#include "StringServices.h"
-
-
-// CDNSSD
-
-STDMETHODIMP CDNSSD::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IBrowseListener* listener, IDNSSDService** browser )
-{
-	CComObject<CDNSSDService>	*	object		= NULL;
-	std::string						regtypeUTF8;
-	std::string						domainUTF8;
-	DNSServiceRef					sref		= NULL;
-	DNSServiceErrorType				err			= 0;
-	HRESULT							hr			= 0;
-	BOOL							ok;
-
-	// Initialize
-	*browser = NULL;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( regtype, regtypeUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( domain, domainUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceBrowse( &sref, flags, ifIndex, regtypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceBrowseReply ) &BrowseReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*browser = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IResolveListener* listener, IDNSSDService** service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	std::string						serviceNameUTF8;
-	std::string						regTypeUTF8;
-	std::string						domainUTF8;
-	DNSServiceRef					sref			= NULL;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-	BOOL							ok;
-
-	// Initialize
-	*service = NULL;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( regType, regTypeUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( domain, domainUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceResolve( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDomainListener *listener, IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	DNSServiceRef					sref			= NULL;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-
-	// Initialize
-	*service = NULL;
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceEnumerateDomains( &sref, flags, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IRegisterListener *listener, IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	std::string						serviceNameUTF8;
-	std::string						regTypeUTF8;
-	std::string						domainUTF8;
-	std::string						hostUTF8;
-	const void					*	txtRecord		= NULL;
-	uint16_t						txtLen			= 0;
-	DNSServiceRef					sref			= NULL;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-	BOOL							ok;
-
-	// Initialize
-	*service = NULL;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( regType, regTypeUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( domain, domainUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-	ok = BSTRToUTF8( host, hostUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	if ( record )
-	{
-		CComObject< CTXTRecord > * realTXTRecord;
-
-		realTXTRecord = ( CComObject< CTXTRecord >* ) record;
-
-		txtRecord	= realTXTRecord->GetBytes();
-		txtLen		= realTXTRecord->GetLen();
-	}
-
-	err = DNSServiceRegister( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), hostUTF8.c_str(), port, txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IQueryRecordListener *listener, IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	DNSServiceRef					sref			= NULL;
-	std::string						fullNameUTF8;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-	BOOL							ok;
-
-	// Initialize
-	*service = NULL;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( fullname, fullNameUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceQueryRecord( &sref, flags, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IGetAddrInfoListener *listener, IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	DNSServiceRef					sref			= NULL;
-	std::string						hostNameUTF8;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-	BOOL							ok;
-
-	// Initialize
-	*service = NULL;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( hostName, hostNameUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceGetAddrInfo( &sref, flags, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::CreateConnection(IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object	= NULL;
-	DNSServiceRef					sref	= NULL;
-	DNSServiceErrorType				err		= 0;
-	HRESULT							hr		= 0;
-
-	// Initialize
-	*service = NULL;
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	err = DNSServiceCreateConnection( &sref );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, INATPortMappingListener *listener, IDNSSDService **service)
-{
-	CComObject<CDNSSDService>	*	object			= NULL;
-	DNSServiceRef					sref			= NULL;
-	DNSServiceProtocol				prot			= 0;
-	DNSServiceErrorType				err				= 0;
-	HRESULT							hr				= 0;
-
-	// Initialize
-	*service = NULL;
-
-	try
-	{
-		object = new CComObject<CDNSSDService>();
-	}
-	catch ( ... )
-	{
-		object = NULL;
-	}
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-	hr = object->FinalConstruct();
-	require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown );
-	object->AddRef();
-
-	prot = ( addressFamily | protocol );
-
-	err = DNSServiceNATPortMappingCreate( &sref, flags, ifIndex, prot, internalPort, externalPort, ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
-	require_noerr( err, exit );
-
-	object->SetServiceRef( sref );
-	object->SetListener( listener );
-
-	err = object->Run();
-	require_noerr( err, exit );
-
-	*service = object;
-
-exit:
-
-	if ( err && object )
-	{
-		object->Release();
-	}
-
-	return err;
-}
-
-
-STDMETHODIMP CDNSSD::GetProperty(BSTR prop, VARIANT * value )
-{
-	std::string			propUTF8;
-	std::vector< BYTE >	byteArray;
-	SAFEARRAY		*	psa			= NULL;
-	BYTE			*	pData		= NULL;
-	uint32_t			elems		= 0;
-	DNSServiceErrorType	err			= 0;
-	BOOL				ok = TRUE;
-
-	// Convert BSTR params to utf8
-	ok = BSTRToUTF8( prop, propUTF8 );
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	// Setup the byte array
-	require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
-	psa = V_ARRAY( value );
-	require_action( psa, exit, err = kDNSServiceErr_Unknown );
-	require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
-	byteArray.reserve( psa->rgsabound[0].cElements );
-	byteArray.assign( byteArray.capacity(), 0 );
-	elems = ( uint32_t ) byteArray.capacity();
-
-	// Call the function and package the return value in the Variant
-	err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
-	require_noerr( err, exit );
-	ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
-	require_action( ok, exit, err = kDNSSDError_Unknown );
-
-exit:
-
-	if ( psa )
-	{
-		SafeArrayUnaccessData( psa );
-		psa = NULL;
-	}
-
-	return err;
-}
-
-
-void DNSSD_API
-CDNSSD::DomainEnumReply
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            ifIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *replyDomainUTF8,
-    void                                *context
-    )
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IDomainListener	* listener;
-
-		listener = ( IDomainListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR replyDomain;
-		
-			UTF8ToBSTR( replyDomainUTF8, replyDomain );
-
-			if ( flags & kDNSServiceFlagsAdd )
-			{
-				listener->DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
-			}
-			else
-			{
-				listener->DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
-			}
-		}
-		else
-		{
-			listener->EnumDomainsFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::BrowseReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *serviceNameUTF8,
-		const char                          *regTypeUTF8,
-		const char                          *replyDomainUTF8,
-		void                                *context
-		)
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IBrowseListener	* listener;
-
-		listener = ( IBrowseListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR	serviceName;
-			CComBSTR	regType;
-			CComBSTR	replyDomain;
-		
-			UTF8ToBSTR( serviceNameUTF8, serviceName );
-			UTF8ToBSTR( regTypeUTF8, regType );
-			UTF8ToBSTR( replyDomainUTF8, replyDomain );
-
-			if ( flags & kDNSServiceFlagsAdd )
-			{
-				listener->ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
-			}
-			else
-			{
-				listener->ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
-			}
-		}
-		else
-		{
-			listener->BrowseFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::ResolveReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullNameUTF8,
-		const char                          *hostNameUTF8,
-		uint16_t                            port,
-		uint16_t                            txtLen,
-		const unsigned char                 *txtRecord,
-		void                                *context
-		)
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IResolveListener * listener;
-
-		listener = ( IResolveListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR					fullName;
-			CComBSTR					hostName;
-			CComBSTR					regType;
-			CComBSTR					replyDomain;
-			CComObject< CTXTRecord >*	record;
-			BOOL						ok;
-
-			ok = UTF8ToBSTR( fullNameUTF8, fullName );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-			ok = UTF8ToBSTR( hostNameUTF8, hostName );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-			try
-			{
-				record = new CComObject<CTXTRecord>();
-			}
-			catch ( ... )
-			{
-				record = NULL;
-			}
-
-			require_action( record, exit, err = kDNSServiceErr_NoMemory );
-			record->AddRef();
-
-			char buf[ 64 ];
-			snprintf( buf, sizeof( buf ), "txtLen = %d", txtLen );
-			OutputDebugStringA( buf );
-
-			if ( txtLen > 0 )
-			{
-				record->SetBytes( txtRecord, txtLen );
-			}
-
-			listener->ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, port, record );
-		}
-		else
-		{
-			listener->ResolveFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::RegisterReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		DNSServiceErrorType                 errorCode,
-		const char                          *serviceNameUTF8,
-		const char                          *regTypeUTF8,
-		const char                          *domainUTF8,
-		void                                *context
-		)
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IRegisterListener * listener;
-
-		listener = ( IRegisterListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR					serviceName;
-			CComBSTR					regType;
-			CComBSTR					domain;
-			BOOL						ok;
-
-			ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-			ok = UTF8ToBSTR( regTypeUTF8, regType );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-			ok = UTF8ToBSTR( domainUTF8, domain );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-			listener->ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
-		}
-		else
-		{
-			listener->ServiceRegisterFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::QueryRecordReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullNameUTF8,
-		uint16_t                            rrtype,
-		uint16_t                            rrclass,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl,
-		void                                *context
-		)
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IQueryRecordListener * listener;
-
-		listener = ( IQueryRecordListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR	fullName;
-			VARIANT		var;
-			BOOL		ok;
-
-			ok = UTF8ToBSTR( fullNameUTF8, fullName );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-			ok = ByteArrayToVariant( rdata, rdlen, &var );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-			listener->QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
-		}
-		else
-		{
-			listener->QueryRecordFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::GetAddrInfoReply
-		(
-		DNSServiceRef                    sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         ifIndex,
-		DNSServiceErrorType              errorCode,
-		const char                       *hostNameUTF8,
-		const struct sockaddr            *rawAddress,
-		uint32_t                         ttl,
-		void                             *context
-		)
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		IGetAddrInfoListener * listener;
-
-		listener = ( IGetAddrInfoListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			CComBSTR			hostName;
-			DWORD				sockaddrLen;
-			DNSSDAddressFamily	addressFamily;
-			char				addressUTF8[INET6_ADDRSTRLEN];
-			DWORD				addressLen = sizeof( addressUTF8 );
-			CComBSTR			address;
-			BOOL				ok;
-
-			ok = UTF8ToBSTR( hostNameUTF8, hostName );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-			switch ( rawAddress->sa_family )
-			{
-				case AF_INET:
-				{
-					addressFamily	= kDNSSDAddressFamily_IPv4;
-					sockaddrLen		= sizeof( sockaddr_in );
-				}
-				break;
-
-				case AF_INET6:
-				{
-					addressFamily	= kDNSSDAddressFamily_IPv6;
-					sockaddrLen		= sizeof( sockaddr_in6 );
-				}
-				break;
-			}
-
-			err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
-			require_noerr( err, exit );
-			ok = UTF8ToBSTR( addressUTF8, address );
-			require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-			listener->GetAddrInfoReply( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
-		}
-		else
-		{
-			listener->GetAddrInfoFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-void DNSSD_API
-CDNSSD::NATPortMappingReply
-    (
-    DNSServiceRef                    sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         ifIndex,
-    DNSServiceErrorType              errorCode,
-    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
-    DNSServiceProtocol               protocol,
-    uint16_t                         internalPort,
-    uint16_t                         externalPort,      /* may be different than the requested port     */
-    uint32_t                         ttl,               /* may be different than the requested ttl      */
-    void                             *context
-    )
-{
-	CComObject<CDNSSDService> * service;
-	int err;
-	
-	service = ( CComObject< CDNSSDService>* ) context;
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-	if ( !service->Stopped() )
-	{
-		INATPortMappingListener * listener;
-
-		listener = ( INATPortMappingListener* ) service->GetListener();
-		require_action( listener, exit, err = kDNSServiceErr_Unknown );
-
-		if ( !errorCode )
-		{
-			listener->MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), internalPort, externalPort, ttl  );
-		}
-		else
-		{
-			listener->MappingFailed( service, ( DNSSDError ) errorCode );
-		}
-	}
-
-exit:
-
-	return;
-}
-
diff --git a/mDNSWindows/DLLX/DNSSDEventManager.cpp b/mDNSWindows/DLLX/DNSSDEventManager.cpp
deleted file mode 100644
index 310ced0..0000000
--- a/mDNSWindows/DLLX/DNSSDEventManager.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#include "stdafx.h"
-
-#include "DNSSDEventManager.h"
-
-
-
-
-
-// CDNSSDEventManager
-
-
-
diff --git a/mDNSWindows/DLLX/DNSSDEventManager.h b/mDNSWindows/DLLX/DNSSDEventManager.h
deleted file mode 100644
index 70aedfc..0000000
--- a/mDNSWindows/DLLX/DNSSDEventManager.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma once
-
-#include "resource.h"       // main symbols
-
-
-
-#include "DLLX.h"
-
-#include "_IDNSSDEvents_CP.H"
-
-
-
-
-
-#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
-
-#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
-
-#endif
-
-
-
-
-
-
-
-// CDNSSDEventManager
-
-
-
-class ATL_NO_VTABLE CDNSSDEventManager :
-
-	public CComObjectRootEx<CComSingleThreadModel>,
-
-	public CComCoClass<CDNSSDEventManager, &CLSID_DNSSDEventManager>,
-
-	public IConnectionPointContainerImpl<CDNSSDEventManager>,
-
-	public CProxy_IDNSSDEvents<CDNSSDEventManager>,
-
-	public IDispatchImpl<IDNSSDEventManager, &IID_IDNSSDEventManager, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
-
-{
-
-public:
-
-	CDNSSDEventManager()
-
-	{
-
-	}
-
-
-
-DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDEVENTMANAGER)
-
-
-
-
-
-BEGIN_COM_MAP(CDNSSDEventManager)
-
-	COM_INTERFACE_ENTRY(IDNSSDEventManager)
-
-	COM_INTERFACE_ENTRY(IDispatch)
-
-	COM_INTERFACE_ENTRY(IConnectionPointContainer)
-
-END_COM_MAP()
-
-
-
-BEGIN_CONNECTION_POINT_MAP(CDNSSDEventManager)
-
-	CONNECTION_POINT_ENTRY(__uuidof(_IDNSSDEvents))
-
-END_CONNECTION_POINT_MAP()
-
-
-
-
-
-	DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-
-
-	HRESULT FinalConstruct()
-
-	{
-
-		return S_OK;
-
-	}
-
-
-
-	void FinalRelease()
-
-	{
-
-	}
-
-
-
-public:
-
-
-
-};
-
-
-
-OBJECT_ENTRY_AUTO(__uuidof(DNSSDEventManager), CDNSSDEventManager)
-
diff --git a/mDNSWindows/DLLX/DNSSDRecord.cpp b/mDNSWindows/DLLX/DNSSDRecord.cpp
deleted file mode 100644
index a272720..0000000
--- a/mDNSWindows/DLLX/DNSSDRecord.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#include "stdafx.h"
-
-#include "DNSSDRecord.h"
-
-#include "StringServices.h"
-
-#include <DebugServices.h>
-
-
-
-
-
-// CDNSSDRecord
-
-
-
-STDMETHODIMP CDNSSDRecord::Update(DNSSDFlags flags, VARIANT rdata, ULONG ttl)
-
-{
-
-	std::vector< BYTE >	byteArray;
-
-	const void		*	byteArrayPtr	= NULL;
-
-	DNSServiceErrorType	err				= 0;
-
-	HRESULT				hr				= 0;
-
-	BOOL				ok;
-
-
-
-	// Convert the VARIANT
-
-	ok = VariantToByteArray( &rdata, byteArray );
-
-	require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	err = DNSServiceUpdateRecord( m_serviceObject->GetSubordRef(), m_rref, flags, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
-
-	require_noerr( err, exit );
-
-
-
-exit:
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDRecord::Remove(DNSSDFlags flags)
-
-{
-
-	DNSServiceErrorType	err = 0;
-
-
-
-	err = DNSServiceRemoveRecord( m_serviceObject->GetSubordRef(), m_rref, flags );
-
-	require_noerr( err, exit );
-
-
-
-exit:
-
-
-
-	return err;
-
-}
-
-
-
diff --git a/mDNSWindows/DLLX/DNSSDRecord.h b/mDNSWindows/DLLX/DNSSDRecord.h
deleted file mode 100644
index bdedda5..0000000
--- a/mDNSWindows/DLLX/DNSSDRecord.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma once
-
-#include "resource.h"       // main symbols
-
-
-
-#include "DLLX.h"
-
-#include "DNSSDService.h"
-
-#include <dns_sd.h>
-
-
-
-
-
-#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
-
-#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
-
-#endif
-
-
-
-
-
-
-
-// CDNSSDRecord
-
-
-
-class ATL_NO_VTABLE CDNSSDRecord :
-
-	public CComObjectRootEx<CComSingleThreadModel>,
-
-	public CComCoClass<CDNSSDRecord, &CLSID_DNSSDRecord>,
-
-	public IDispatchImpl<IDNSSDRecord, &IID_IDNSSDRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
-
-{
-
-public:
-
-	CDNSSDRecord()
-
-	{
-
-	}
-
-
-
-DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDRECORD)
-
-
-
-
-
-BEGIN_COM_MAP(CDNSSDRecord)
-
-	COM_INTERFACE_ENTRY(IDNSSDRecord)
-
-	COM_INTERFACE_ENTRY(IDispatch)
-
-END_COM_MAP()
-
-
-
-
-
-
-
-	DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-
-
-	HRESULT FinalConstruct()
-
-	{
-
-		return S_OK;
-
-	}
-
-
-
-	void FinalRelease()
-
-	{
-
-	}
-
-
-
-	inline CDNSSDService*
-
-	GetServiceObject()
-
-	{
-
-		return m_serviceObject;
-
-	}
-
-
-
-	inline void
-
-	SetServiceObject( CDNSSDService * serviceObject )
-
-	{
-
-		m_serviceObject = serviceObject;
-
-	}
-
-
-
-	inline DNSRecordRef
-
-	GetRecordRef()
-
-	{
-
-		return m_rref;
-
-	}
-
-
-
-	inline void
-
-	SetRecordRef( DNSRecordRef rref )
-
-	{
-
-		m_rref = rref;
-
-	}
-
-
-
-public:
-
-
-
-	STDMETHOD(Update)(DNSSDFlags flags, VARIANT rdata, ULONG ttl);
-
-	STDMETHOD(Remove)(DNSSDFlags flags);
-
-
-
-private:
-
-
-
-	CDNSSDService *	m_serviceObject;
-
-	DNSRecordRef	m_rref;
-
-};
-
-
-
-OBJECT_ENTRY_AUTO(__uuidof(DNSSDRecord), CDNSSDRecord)
-
diff --git a/mDNSWindows/DLLX/DNSSDService.cpp b/mDNSWindows/DLLX/DNSSDService.cpp
deleted file mode 100644
index b8ce49b..0000000
--- a/mDNSWindows/DLLX/DNSSDService.cpp
+++ /dev/null
@@ -1,2095 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma warning(disable:4995)
-
-
-
-#include "stdafx.h"
-
-#include <strsafe.h>
-
-#include "DNSSDService.h"
-
-#include "DNSSDEventManager.h"
-
-#include "DNSSDRecord.h"
-
-#include "TXTRecord.h"
-
-#include "StringServices.h"
-
-#include <DebugServices.h>
-
-
-
-
-
-#define WM_SOCKET (WM_APP + 100)
-
-
-
-
-
-// CDNSSDService
-
-
-
-BOOL						CDNSSDService::m_registeredWindowClass	= FALSE;
-
-HWND						CDNSSDService::m_hiddenWindow			= NULL;
-
-CDNSSDService::SocketMap	CDNSSDService::m_socketMap;
-
-
-
-
-
-HRESULT CDNSSDService::FinalConstruct()
-
-{
-
-	DNSServiceErrorType	err	= 0;
-
-	HRESULT				hr	= S_OK;
-
-
-
-	m_isPrimary = TRUE;
-
-	err = DNSServiceCreateConnection( &m_primary );
-
-	require_action( !err, exit, hr = E_FAIL );
-
-
-
-	if ( !m_hiddenWindow )
-
-	{
-
-		TCHAR windowClassName[ 256 ];
-
-
-
-		StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );
-
-
-
-		if ( !m_registeredWindowClass )
-
-		{
-
-			WNDCLASS	wc;
-
-			ATOM		atom;
-
-
-
-			wc.style			= 0;
-
-			wc.lpfnWndProc		= WndProc;
-
-			wc.cbClsExtra		= 0;
-
-			wc.cbWndExtra		= 0;
-
-			wc.hInstance		= NULL;
-
-			wc.hIcon			= NULL;
-
-			wc.hCursor			= NULL;
-
-			wc.hbrBackground	= NULL;
-
-			wc.lpszMenuName		= NULL;
-
-			wc.lpszClassName	= windowClassName;
-
-
-
-			atom = RegisterClass(&wc);
-
-			require_action( atom != NULL, exit, hr = E_FAIL );
-
-
-
-			m_registeredWindowClass = TRUE;
-
-		}
-
-
-
-		m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );
-
-		require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );
-
-	}
-
-
-
-	err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );
-
-	require_action( !err, exit, hr = E_FAIL );
-
-
-
-	m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-
-
-void CDNSSDService::FinalRelease()
-
-{
-
-	dlog( kDebugLevelTrace, "FinalRelease()\n" ); 
-
-	Stop();
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)
-
-{
-
-	CComObject<CDNSSDService>	*	object	= NULL;
-
-	DNSServiceRef					subord	= NULL;
-
-	DNSServiceErrorType				err		= 0;
-
-	HRESULT							hr		= 0;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )
-
-{
-
-	CComObject<CDNSSDService>	*	object		= NULL;
-
-	std::string						regtypeUTF8;
-
-	std::string						domainUTF8;
-
-	DNSServiceRef					subord		= NULL;
-
-	DNSServiceErrorType				err			= 0;
-
-	HRESULT							hr			= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( regtype, regtypeUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( domain, domainUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)
-
-{
-
-	CComObject<CDNSSDService>	*	object			= NULL;
-
-	std::string						serviceNameUTF8;
-
-	std::string						regTypeUTF8;
-
-	std::string						domainUTF8;
-
-	DNSServiceRef					subord			= NULL;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( regType, regTypeUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( domain, domainUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)
-
-{
-
-	CComObject<CDNSSDService>	*	object			= NULL;
-
-	std::string						serviceNameUTF8;
-
-	std::string						regTypeUTF8;
-
-	std::string						domainUTF8;
-
-	std::string						hostUTF8;
-
-	const void					*	txtRecord		= NULL;
-
-	uint16_t						txtLen			= 0;
-
-	DNSServiceRef					subord			= NULL;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( regType, regTypeUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( domain, domainUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-	ok = BSTRToUTF8( host, hostUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	if ( record )
-
-	{
-
-		CComObject< CTXTRecord > * realTXTRecord;
-
-
-
-		realTXTRecord = ( CComObject< CTXTRecord >* ) record;
-
-
-
-		txtRecord	= realTXTRecord->GetBytes();
-
-		txtLen		= realTXTRecord->GetLen();
-
-	}
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceRegister( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, hostUTF8.c_str(), htons( port ), txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)
-
-{
-
-	CComObject<CDNSSDService>	*	object			= NULL;
-
-	DNSServiceRef					subord			= NULL;
-
-	std::string						fullNameUTF8;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( fullname, fullNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)
-
-{
-
-	CComObject<CDNSSDRecord>	*	object			= NULL;
-
-	DNSRecordRef					rref			= NULL;
-
-	std::string						fullNameUTF8;
-
-	std::vector< BYTE >				byteArray;
-
-	const void					*	byteArrayPtr	= NULL;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*object = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( fullName, fullNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	// Convert the VARIANT
-
-	ok = VariantToByteArray( &rdata, byteArray );
-
-	require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDRecord>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	err = DNSServiceRegisterRecord( m_primary, &rref, flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl, &RegisterRecordReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetServiceObject( this );
-
-	object->SetRecordRef( rref );
-
-	this->SetEventManager( eventManager );
-
-
-
-	*record = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)
-
-{
-
-	CComObject<CDNSSDRecord>	*	object			= NULL;
-
-	DNSRecordRef					rref			= NULL;
-
-	std::vector< BYTE >				byteArray;
-
-	const void					*	byteArrayPtr	= NULL;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*object = NULL;
-
-
-
-	// Convert the VARIANT
-
-	ok = VariantToByteArray( &rdata, byteArray );
-
-	require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDRecord>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetServiceObject( this );
-
-	object->SetRecordRef( rref );
-
-
-
-	*record = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)
-
-{
-
-	std::string						fullNameUTF8;
-
-	std::vector< BYTE >				byteArray;
-
-	const void					*	byteArrayPtr	= NULL;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( fullName, fullNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	// Convert the VARIANT
-
-	ok = VariantToByteArray( &rdata, byteArray );
-
-	require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );
-
-	require_noerr( err, exit );
-
-
-
-exit:
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )
-
-{
-
-	std::string			propUTF8;
-
-	std::vector< BYTE >	byteArray;
-
-	SAFEARRAY		*	psa			= NULL;
-
-	BYTE			*	pData		= NULL;
-
-	uint32_t			elems		= 0;
-
-	DNSServiceErrorType	err			= 0;
-
-	BOOL				ok = TRUE;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( prop, propUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	// Setup the byte array
-
-	require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
-
-	psa = V_ARRAY( value );
-
-	require_action( psa, exit, err = kDNSServiceErr_Unknown );
-
-	require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
-
-	byteArray.reserve( psa->rgsabound[0].cElements );
-
-	byteArray.assign( byteArray.capacity(), 0 );
-
-	elems = ( uint32_t ) byteArray.capacity();
-
-
-
-	// Call the function and package the return value in the Variant
-
-	err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
-
-	require_noerr( err, exit );
-
-	ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
-
-	require_action( ok, exit, err = kDNSSDError_Unknown );
-
-
-
-exit:
-
-
-
-	if ( psa )
-
-	{
-
-		SafeArrayUnaccessData( psa );
-
-		psa = NULL;
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)
-
-{
-
-	CComObject<CDNSSDService>	*	object			= NULL;
-
-	DNSServiceRef					subord			= NULL;
-
-	std::string						hostNameUTF8;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-	BOOL							ok;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	// Convert BSTR params to utf8
-
-	ok = BSTRToUTF8( hostName, hostNameUTF8 );
-
-	require_action( ok, exit, err = kDNSServiceErr_BadParam );
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)
-
-{
-
-	CComObject<CDNSSDService>	*	object			= NULL;
-
-	DNSServiceRef					subord			= NULL;
-
-	DNSServiceProtocol				prot			= 0;
-
-	DNSServiceErrorType				err				= 0;
-
-	HRESULT							hr				= 0;
-
-
-
-	check( m_primary );
-
-
-
-	// Initialize
-
-	*service = NULL;
-
-
-
-	try
-
-	{
-
-		object = new CComObject<CDNSSDService>();
-
-	}
-
-	catch ( ... )
-
-	{
-
-		object = NULL;
-
-	}
-
-
-
-	require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
-
-	object->AddRef();
-
-
-
-	prot = ( addressFamily | protocol );
-
-
-
-	subord = m_primary;
-
-	err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
-
-	require_noerr( err, exit );
-
-
-
-	object->SetPrimaryRef( m_primary );
-
-	object->SetSubordRef( subord );
-
-	object->SetEventManager( eventManager );
-
-
-
-	*service = object;
-
-
-
-exit:
-
-
-
-	if ( err && object )
-
-	{
-
-		object->Release();
-
-	}
-
-
-
-	return err;
-
-}
-
-
-
-
-
-STDMETHODIMP CDNSSDService::Stop(void)
-
-{
-
-	if ( !m_stopped )
-
-	{
-
-		m_stopped = TRUE;
-
-
-
-		dlog( kDebugLevelTrace, "Stop()\n" );
-
-
-
-		if ( m_isPrimary && m_primary )
-
-		{
-
-			SocketMap::iterator it;
-
-
-
-			if ( m_hiddenWindow )
-
-			{
-
-				WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );
-
-			}
-
-
-
-			it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );
-
-
-
-			if ( it != m_socketMap.end() )
-
-			{
-
-				m_socketMap.erase( it );
-
-			}
-
-
-
-			DNSServiceRefDeallocate( m_primary );
-
-			m_primary = NULL;
-
-		}
-
-		else if ( m_subord )
-
-		{
-
-			DNSServiceRefDeallocate( m_subord );
-
-			m_subord = NULL;
-
-		}
-
-
-
-		if ( m_eventManager != NULL )
-
-		{
-
-			m_eventManager->Release();
-
-			m_eventManager = NULL;
-
-		}
-
-	}
-
-
-
-	return S_OK;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::DomainEnumReply
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            ifIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *replyDomainUTF8,
-    void                                *context
-    )
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR replyDomain;
-
-		BOOL ok;
-
-		
-
-		ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		if ( flags & kDNSServiceFlagsAdd )
-
-		{
-
-			eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
-
-		}
-
-		else
-
-		{
-
-			eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
-
-		}
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::BrowseReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *serviceNameUTF8,
-		const char                          *regTypeUTF8,
-		const char                          *replyDomainUTF8,
-		void                                *context
-		)
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR	serviceName;
-
-		CComBSTR	regType;
-
-		CComBSTR	replyDomain;
-
-	
-
-		UTF8ToBSTR( serviceNameUTF8, serviceName );
-
-		UTF8ToBSTR( regTypeUTF8, regType );
-
-		UTF8ToBSTR( replyDomainUTF8, replyDomain );
-
-
-
-		if ( flags & kDNSServiceFlagsAdd )
-
-		{
-
-			eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
-
-		}
-
-		else
-
-		{
-
-			eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
-
-		}
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-
-CDNSSDService::ResolveReply
-
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullNameUTF8,
-		const char                          *hostNameUTF8,
-		uint16_t                            port,
-		uint16_t                            txtLen,
-		const unsigned char                 *txtRecord,
-		void                                *context
-
-		)
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR					fullName;
-
-		CComBSTR					hostName;
-
-		CComBSTR					regType;
-
-		CComBSTR					replyDomain;
-
-		CComObject< CTXTRecord >*	record;
-
-		BOOL						ok;
-
-
-
-		ok = UTF8ToBSTR( fullNameUTF8, fullName );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-		ok = UTF8ToBSTR( hostNameUTF8, hostName );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		try
-
-		{
-
-			record = new CComObject<CTXTRecord>();
-
-		}
-
-		catch ( ... )
-
-		{
-
-			record = NULL;
-
-		}
-
-
-
-		require_action( record, exit, err = kDNSServiceErr_NoMemory );
-
-		record->AddRef();
-
-
-
-		if ( txtLen > 0 )
-
-		{
-
-			record->SetBytes( txtRecord, txtLen );
-
-		}
-
-
-
-		eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::RegisterReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		DNSServiceErrorType                 errorCode,
-		const char                          *serviceNameUTF8,
-		const char                          *regTypeUTF8,
-		const char                          *domainUTF8,
-		void                                *context
-		)
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR					serviceName;
-
-		CComBSTR					regType;
-
-		CComBSTR					domain;
-
-		BOOL						ok;
-
-
-
-		ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-		ok = UTF8ToBSTR( regTypeUTF8, regType );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-		ok = UTF8ToBSTR( domainUTF8, domain );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::QueryRecordReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullNameUTF8,
-		uint16_t                            rrtype,
-		uint16_t                            rrclass,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl,
-		void                                *context
-		)
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR	fullName;
-
-		VARIANT		var;
-
-		BOOL		ok;
-
-
-
-		ok = UTF8ToBSTR( fullNameUTF8, fullName );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-		ok = ByteArrayToVariant( rdata, rdlen, &var );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::GetAddrInfoReply
-		(
-		DNSServiceRef                    sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         ifIndex,
-		DNSServiceErrorType              errorCode,
-		const char                       *hostNameUTF8,
-		const struct sockaddr            *rawAddress,
-		uint32_t                         ttl,
-		void                             *context
-		)
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		CComBSTR			hostName;
-
-		DWORD				sockaddrLen;
-
-		DNSSDAddressFamily	addressFamily;
-
-		char				addressUTF8[INET6_ADDRSTRLEN];
-
-		DWORD				addressLen = sizeof( addressUTF8 );
-
-		CComBSTR			address;
-
-		BOOL				ok;
-
-
-
-		ok = UTF8ToBSTR( hostNameUTF8, hostName );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		switch ( rawAddress->sa_family )
-
-		{
-
-			case AF_INET:
-
-			{
-
-				addressFamily	= kDNSSDAddressFamily_IPv4;
-
-				sockaddrLen		= sizeof( sockaddr_in );
-
-			}
-
-			break;
-
-
-
-			case AF_INET6:
-
-			{
-
-				addressFamily	= kDNSSDAddressFamily_IPv6;
-
-				sockaddrLen		= sizeof( sockaddr_in6 );
-
-			}
-
-			break;
-
-		}
-
-
-
-		err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
-
-		require_noerr( err, exit );
-
-		ok = UTF8ToBSTR( addressUTF8, address );
-
-		require_action( ok, exit, err = kDNSServiceErr_Unknown );
-
-
-
-		eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::NATPortMappingReply
-    (
-    DNSServiceRef                    sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         ifIndex,
-    DNSServiceErrorType              errorCode,
-    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
-    DNSServiceProtocol               protocol,
-    uint16_t                         internalPort,
-    uint16_t                         externalPort,      /* may be different than the requested port     */
-    uint32_t                         ttl,               /* may be different than the requested ttl      */
-    void                             *context
-    )
-
-{
-
-	CComObject<CDNSSDService>	* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	service = ( CComObject< CDNSSDService>* ) context;
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl  );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-void DNSSD_API
-CDNSSDService::RegisterRecordReply
-		(
-		DNSServiceRef		sdRef,
-		DNSRecordRef		RecordRef,
-		DNSServiceFlags		flags,
-		DNSServiceErrorType	errorCode,
-		void				*context
-		)
-
-{
-
-	CComObject<CDNSSDRecord>	* record		= NULL;
-
-	CDNSSDService				* service		= NULL;
-
-	CDNSSDEventManager			* eventManager	= NULL;
-
-	int err = 0;
-
-	
-
-	record = ( CComObject< CDNSSDRecord >* ) context;
-
-	require_action( record, exit, err = kDNSServiceErr_Unknown );
-
-	service = record->GetServiceObject();
-
-	require_action( service, exit, err = kDNSServiceErr_Unknown );
-
-
-
-	if ( service->ShouldHandleReply( errorCode, eventManager ) )
-
-	{
-
-		eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );
-
-	}
-
-
-
-exit:
-
-
-
-	return;
-
-}
-
-
-
-
-
-BOOL
-
-CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )
-
-{
-
-	BOOL ok = FALSE;
-
-
-
-	if ( !this->Stopped() )
-
-	{
-
-		eventManager = this->GetEventManager();
-
-		require_action( eventManager, exit, ok = FALSE );
-
-
-
-		if ( !errorCode )
-
-		{
-
-			ok = TRUE;
-
-		}
-
-		else
-
-		{
-
-			eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );
-
-		}
-
-	}
-
-
-
-exit:
-
-
-
-	return ok;
-
-}
-
-
-
-
-
-LRESULT CALLBACK
-
-CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
-
-{
-
-	if ( msg == WM_SOCKET )
-
-	{
-
-		SocketMap::iterator it;
-
-			
-
-		it = m_socketMap.find( ( SOCKET ) wParam );
-
-		check( it != m_socketMap.end() );
-
-
-
-		if ( it != m_socketMap.end() )
-
-		{
-
-			DNSServiceProcessResult( it->second->m_primary );
-
-		}
-
-	}
-
-
-
-	return DefWindowProc(hWnd, msg, wParam, lParam);;
-
-}
-
diff --git a/mDNSWindows/DLLX/DNSSDService.h b/mDNSWindows/DLLX/DNSSDService.h
deleted file mode 100644
index 5eb8dcb..0000000
--- a/mDNSWindows/DLLX/DNSSDService.h
+++ /dev/null
@@ -1,429 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma once
-
-#include "resource.h"       // main symbols
-
-
-
-#include "DLLX.h"
-
-#include "DNSSDEventManager.h"
-
-#include <CommonServices.h>
-
-#include <DebugServices.h>
-
-#include <dns_sd.h>
-
-#include <map>
-
-
-
-
-
-#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
-
-#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
-
-#endif
-
-
-
-
-
-
-
-// CDNSSDService
-
-
-
-class ATL_NO_VTABLE CDNSSDService :
-
-	public CComObjectRootEx<CComSingleThreadModel>,
-
-	public CComCoClass<CDNSSDService, &CLSID_DNSSDService>,
-
-	public IDispatchImpl<IDNSSDService, &IID_IDNSSDService, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
-
-{
-
-public:
-
-
-
-	typedef CComObjectRootEx<CComSingleThreadModel> Super;
-
-
-
-	CDNSSDService()
-
-	:
-
-		m_isPrimary( FALSE ),
-
-		m_eventManager( NULL ),
-
-		m_stopped( FALSE ),
-
-		m_primary( NULL ),
-
-		m_subord( NULL )
-
-	{
-
-	}
-
-
-
-DECLARE_REGISTRY_RESOURCEID(IDR_DNSSDSERVICE)
-
-
-
-
-
-BEGIN_COM_MAP(CDNSSDService)
-
-	COM_INTERFACE_ENTRY(IDNSSDService)
-
-	COM_INTERFACE_ENTRY(IDispatch)
-
-END_COM_MAP()
-
-
-
-	DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-
-
-	HRESULT
-
-	FinalConstruct();
-
-
-
-	void 
-
-	FinalRelease();
-
-
-
-public:
-
-
-
-	inline DNSServiceRef
-
-	GetPrimaryRef()
-
-	{
-
-		return m_primary;
-
-	}
-
-
-
-	inline void
-
-	SetPrimaryRef( DNSServiceRef primary )
-
-	{
-
-		m_primary = primary;
-
-	}
-
-
-
-	inline DNSServiceRef
-
-	GetSubordRef()
-
-	{
-
-		return m_subord;
-
-	}
-
-
-
-	inline void
-
-	SetSubordRef( DNSServiceRef subord )
-
-	{
-
-		m_subord = subord;
-
-	}
-
-
-
-	inline CDNSSDEventManager*
-
-	GetEventManager()
-
-	{
-
-		return m_eventManager;
-
-	}
-
-
-
-	inline void
-
-	SetEventManager( IDNSSDEventManager * eventManager )
-
-	{
-
-		if ( m_eventManager )
-
-		{
-
-			m_eventManager->Release();
-
-			m_eventManager = NULL;
-
-		}
-
-
-
-		if ( eventManager )
-
-		{
-
-			m_eventManager = dynamic_cast< CDNSSDEventManager* >( eventManager );
-
-			check( m_eventManager );
-
-			m_eventManager->AddRef();
-
-		}
-
-	}
-
-
-
-	inline BOOL
-
-	Stopped()
-
-	{
-
-		return m_stopped;
-
-	}
-
-
-
-private:
-
-
-
-	static void DNSSD_API
-	DomainEnumReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            ifIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *replyDomain,
-		void                                *context
-		);
-
-
-
-	static void DNSSD_API
-	BrowseReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *serviceName,
-		const char                          *regtype,
-		const char                          *replyDomain,
-		void                                *context
-		);
-
-
-
-	static void DNSSD_API
-
-	ResolveReply
-
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullname,
-		const char                          *hosttarget,
-		uint16_t                            port,
-		uint16_t                            txtLen,
-		const unsigned char                 *txtRecord,
-		void                                *context
-
-		);
-
-
-
-	static void DNSSD_API
-	RegisterReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		DNSServiceErrorType                 errorCode,
-		const char                          *name,
-		const char                          *regtype,
-		const char                          *domain,
-		void                                *context
-		);
-
-
-
-	static void DNSSD_API
-	QueryRecordReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSServiceFlags                     flags,
-		uint32_t                            interfaceIndex,
-		DNSServiceErrorType                 errorCode,
-		const char                          *fullname,
-		uint16_t                            rrtype,
-		uint16_t                            rrclass,
-		uint16_t                            rdlen,
-		const void                          *rdata,
-		uint32_t                            ttl,
-		void                                *context
-		);
-
-
-
-	static void DNSSD_API
-    GetAddrInfoReply
-		(
-		DNSServiceRef                    sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         interfaceIndex,
-		DNSServiceErrorType              errorCode,
-		const char                       *hostname,
-		const struct sockaddr            *address,
-		uint32_t                         ttl,
-		void                             *context
-		);
-
-
-
-	static void DNSSD_API
-	NATPortMappingReply
-		(
-		DNSServiceRef                    sdRef,
-		DNSServiceFlags                  flags,
-		uint32_t                         interfaceIndex,
-		DNSServiceErrorType              errorCode,
-		uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
-		DNSServiceProtocol               protocol,
-		uint16_t                         internalPort,
-		uint16_t                         externalPort,      /* may be different than the requested port     */
-		uint32_t                         ttl,               /* may be different than the requested ttl      */
-		void                             *context
-		);
-
-
-
-	static void DNSSD_API
-	RegisterRecordReply
-		(
-		DNSServiceRef                       sdRef,
-		DNSRecordRef                        RecordRef,
-		DNSServiceFlags                     flags,
-		DNSServiceErrorType                 errorCode,
-		void                                *context
-		);
-
-
-
-	inline BOOL
-
-	ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager );
-
-	
-
-	static LRESULT CALLBACK
-
-	WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
-
-
-
-	typedef std::map< SOCKET, CDNSSDService* > SocketMap;
-
-
-
-	static BOOL				m_registeredWindowClass;
-
-	static HWND				m_hiddenWindow;
-
-	static SocketMap		m_socketMap;
-
-	CDNSSDEventManager	*	m_eventManager;
-
-	BOOL					m_stopped;
-
-	BOOL					m_isPrimary;
-
-	DNSServiceRef			m_primary;
-
-	DNSServiceRef			m_subord;
-
-public:
-
-	STDMETHOD(EnumerateDomains)(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service);  
-
-	STDMETHOD(Browse)(DNSSDFlags flags, ULONG interfaceIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** sdref);
-
-	STDMETHOD(Resolve)(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service);
-
-	STDMETHOD(Register)(DNSSDFlags flags, ULONG ifIndex, BSTR name, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service);
-
-	STDMETHOD(QueryRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service);      
-
-	STDMETHOD(RegisterRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record);
-
-	STDMETHOD(AddRecord)(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record);
-
-	STDMETHOD(ReconfirmRecord)(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata);
-
-	STDMETHOD(GetProperty)(BSTR prop, VARIANT * value);
-
-	STDMETHOD(GetAddrInfo)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostname, IDNSSDEventManager *eventManager, IDNSSDService **service);      
-
-	STDMETHOD(NATPortMappingCreate)(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service);
-
-	STDMETHOD(Stop)(void);
-
-};
-
-
-
-OBJECT_ENTRY_AUTO(__uuidof(DNSSDService), CDNSSDService)
-
diff --git a/mDNSWindows/DLLX/StringServices.cpp b/mDNSWindows/DLLX/StringServices.cpp
deleted file mode 100644
index 87f7aa9..0000000
--- a/mDNSWindows/DLLX/StringServices.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#include "StringServices.h"
-
-#include <DebugServices.h>
-
-
-
-
-
-extern BOOL
-
-BSTRToUTF8
-
-	(
-
-	BSTR			inString,
-
-	std::string	&	outString
-
-	)
-
-{
-
-	USES_CONVERSION;
-
-	
-
-	char	*	utf8String	= NULL;
-
-	OSStatus    err			= kNoErr;
-
-
-
-	outString = "";
-
-	if ( inString )
-
-	{
-		TCHAR	*	utf16String	= NULL;
-		size_t      size		= 0;
-
-
-		utf16String = OLE2T( inString );
-
-		require_action( utf16String != NULL, exit, err = kUnknownErr );
-
-
-
-		if ( wcslen( utf16String ) > 0 )
-
-		{
-
-			size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL );
-
-			err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-
-			require_noerr( err, exit );
-
-
-
-			try
-
-			{
-
-				utf8String = new char[ size + 1 ];
-
-			}
-
-			catch ( ... )
-
-			{
-
-				utf8String = NULL;
-
-			}
-
-
-
-			require_action( utf8String != NULL, exit, err = kNoMemoryErr );
-
-			size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (int) size, NULL, NULL);
-
-			err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-
-			require_noerr( err, exit );
-
-
-
-			// have to add the trailing 0 because WideCharToMultiByte doesn't do it,
-
-			// although it does return the correct size
-
-
-
-			utf8String[size] = '\0';
-
-			outString = utf8String;
-
-		}
-	}
-
-
-
-exit:
-
-
-
-	if ( utf8String != NULL )
-
-	{
-
-		delete [] utf8String;
-
-	}
-
-
-
-	return ( !err ) ? TRUE : FALSE;
-
-}
-
-
-
-
-
-extern BOOL
-
-UTF8ToBSTR
-
-	(
-
-	const char	*	inString,
-
-	CComBSTR	&	outString
-
-	)
-
-{
-
-	wchar_t	*	unicode	= NULL;
-
-	OSStatus	err		= 0;
-
-
-
-	if ( inString )
-
-	{
-		int n;
-
-		n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 );
-
-	    
-
-		if ( n > 0 )
-
-		{
-
-			try
-
-			{
-
-				unicode = new wchar_t[ n ];
-
-			}
-
-			catch ( ... )
-
-			{
-
-				unicode = NULL;
-
-			}
-
-
-
-			require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER );
-
-
-
-			n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n );
-
-		}
-
-
-
-		outString = unicode;
-
-	}
-
-
-exit:
-
-
-
-    if ( unicode != NULL )
-
-    {
-
-        delete [] unicode;
-
-	}
-
-
-
-	return ( !err ) ? TRUE : FALSE;
-
-}
-
-
-
-
-
-BOOL
-
-ByteArrayToVariant
-
-	(
-
-	const void	*	inArray,
-
-	size_t			inArrayLen,
-
-	VARIANT		*	outVariant
-
-	)
-
-{
-
-	LPBYTE			buf	= NULL;
-
-	HRESULT			hr	= 0;
-
-	BOOL			ok	= TRUE;
-
-
-
-	VariantClear( outVariant );
-
-	outVariant->vt		= VT_ARRAY|VT_UI1;
-
-	outVariant->parray	= SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen );
-
-	require_action( outVariant->parray, exit, ok = FALSE );
-
-	hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf );
-
-	require_action( hr == S_OK, exit, ok = FALSE );
-
-	memcpy( buf, inArray, inArrayLen );
-
-	hr = SafeArrayUnaccessData( outVariant->parray );
-
-	require_action( hr == S_OK, exit, ok = FALSE );
-
-
-
-exit:
-
-
-
-	return ok;
-
-}
-
-
-
-
-
-extern BOOL
-
-VariantToByteArray
-	(
-	VARIANT				*	inVariant,
-	std::vector< BYTE >	&	outArray
-	)
-{
-	BOOL ok = TRUE;
-
-	if ( V_VT( inVariant ) == VT_BSTR )
-	{
-		BSTR bstr = V_BSTR( inVariant );
-		std::string utf8;
-
-		BSTRToUTF8( bstr, utf8 );
-
-		outArray.reserve( utf8.size() );
-		outArray.assign( utf8.begin(), utf8.end() );
-	}
-	else if ( V_VT( inVariant ) == VT_ARRAY )
-	{
-		SAFEARRAY	*	psa			= NULL;
-		BYTE		*	pData		= NULL;
-		ULONG			cElements	= 0;
-		HRESULT			hr;
-		
-		psa = V_ARRAY( inVariant );
-
-		require_action( psa, exit, ok = FALSE );
-
-		require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE );
-
-		hr = SafeArrayAccessData( psa, ( LPVOID* )&pData );
-
-		require_action( hr == S_OK, exit, ok = FALSE );
-
-		cElements = psa->rgsabound[0].cElements;
-
-		outArray.reserve( cElements );
-
-		outArray.assign( cElements, 0 );
-
-		memcpy( &outArray[ 0 ], pData, cElements );
-
-		SafeArrayUnaccessData( psa );
-	}
-	else
-	{
-		ok = FALSE;
-	}
-
-exit:
-
-	return ok;
-
-}
\ No newline at end of file
diff --git a/mDNSWindows/DLLX/StringServices.h b/mDNSWindows/DLLX/StringServices.h
deleted file mode 100644
index 71ba286..0000000
--- a/mDNSWindows/DLLX/StringServices.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#ifndef _StringServices_h
-
-#define _StringServices_h
-
-
-
-#include <atlbase.h>
-
-#include <vector>
-
-#include <string>
-
-
-
-
-
-extern BOOL
-
-BSTRToUTF8
-
-	(
-
-	BSTR			inString,
-
-	std::string	&	outString
-
-	);
-
-
-
-
-
-extern BOOL
-
-UTF8ToBSTR
-
-	(
-
-	const char	*	inString,
-
-	CComBSTR	&	outString
-
-	);
-
-
-
-
-
-extern BOOL
-
-ByteArrayToVariant
-
-	(
-
-	const void	*	inArray,
-
-	size_t			inArrayLen,
-
-	VARIANT		*	outVariant
-
-	);
-
-
-
-
-
-extern BOOL
-
-VariantToByteArray
-
-	(
-
-	VARIANT				*	inVariant,
-
-	std::vector< BYTE >	&	outArray
-
-	);
-
-
-
-
-
-#endif
diff --git a/mDNSWindows/DLLX/TXTRecord.cpp b/mDNSWindows/DLLX/TXTRecord.cpp
deleted file mode 100644
index 2ebb67e..0000000
--- a/mDNSWindows/DLLX/TXTRecord.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#include "stdafx.h"
-
-#include "TXTRecord.h"
-
-#include "StringServices.h"
-
-#include <DebugServices.h>
-
-
-
-
-
-// CTXTRecord
-
-
-
-
-
-STDMETHODIMP CTXTRecord::SetValue(BSTR key, VARIANT value)
-
-{
-
-	std::string			keyUTF8;
-
-	ByteArray			valueArray;
-
-	BOOL				ok;
-
-	DNSServiceErrorType	err;
-
-	HRESULT				hr = S_OK;
-
-
-
-	if ( !m_allocated )
-
-	{
-
-		TXTRecordCreate( &m_tref, 0, NULL );
-
-		m_allocated = TRUE;
-
-	}
-
-
-
-	ok = BSTRToUTF8( key, keyUTF8 );
-
-	require_action( ok, exit, hr = S_FALSE );
-
-
-
-	ok = VariantToByteArray( &value, valueArray );
-
-	require_action( ok, exit, hr = S_FALSE );
-
-
-
-	err = TXTRecordSetValue( &m_tref, keyUTF8.c_str(), ( uint8_t ) valueArray.size(), &valueArray[ 0 ] );
-
-	require_action( !err, exit, hr = S_FALSE );
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::RemoveValue(BSTR key)
-
-{
-
-	HRESULT hr = S_OK;
-
-
-
-	if ( m_allocated )
-
-	{
-
-		std::string			keyUTF8;
-
-		BOOL				ok;
-
-		DNSServiceErrorType	err;
-
-
-
-		ok = BSTRToUTF8( key, keyUTF8 );
-
-		require_action( ok, exit, hr = S_FALSE );
-
-
-
-		err = TXTRecordRemoveValue( &m_tref, keyUTF8.c_str() );
-
-		require_action( !err, exit, hr = S_FALSE );
-
-	}
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::ContainsKey(BSTR key, VARIANT_BOOL* retval)
-
-{
-
-	std::string keyUTF8;
-
-	int			ret	= 0;
-
-	HRESULT		err	= S_OK;
-
-
-
-	if ( m_byteArray.size() > 0 )
-
-	{
-
-		BOOL ok;
-
-
-
-		ok = BSTRToUTF8( key, keyUTF8 );
-
-		require_action( ok, exit, err = S_FALSE );
-
-
-
-		ret = TXTRecordContainsKey( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str() );
-
-	}
-
-
-
-	*retval = ( ret ) ? VARIANT_TRUE : VARIANT_FALSE;
-
-
-
-exit:
-
-
-
-	return err;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::GetValueForKey(BSTR key, VARIANT* value)
-
-{
-
-	std::string		keyUTF8;
-
-	const void	*	rawValue;
-
-	uint8_t			rawValueLen;
-
-	BOOL			ok	= TRUE;
-
-	HRESULT			hr	= S_OK;
-
-
-
-	VariantClear( value );
-
-
-
-	if ( m_byteArray.size() > 0 )
-
-	{
-
-		ok = BSTRToUTF8( key, keyUTF8 );
-
-		require_action( ok, exit, hr = S_FALSE );
-
-
-
-		rawValue = TXTRecordGetValuePtr( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], keyUTF8.c_str(), &rawValueLen );
-
-
-
-		if ( rawValue )
-
-		{
-
-			ok = ByteArrayToVariant( rawValue, rawValueLen, value );
-
-			require_action( ok, exit, hr = S_FALSE );
-
-		}
-
-	}
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::GetCount(ULONG* count)
-
-{
-
-	*count = 0;
-
-	if ( m_allocated )
-	{
-		*count = TXTRecordGetCount( TXTRecordGetLength( &m_tref ), TXTRecordGetBytesPtr( &m_tref ) );
-	}
-	else if ( m_byteArray.size() > 0 )
-	{
-
-		*count = TXTRecordGetCount( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ] );
-
-	}
-
-
-
-	return S_OK;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::GetKeyAtIndex(ULONG index, BSTR* retval)
-
-{
-
-	char				keyBuf[ 64 ];
-
-	uint8_t				rawValueLen;
-
-	const void		*	rawValue;
-
-	CComBSTR			temp;
-
-	DNSServiceErrorType	err;
-
-	BOOL				ok;
-
-	HRESULT				hr = S_OK;
-
-
-
-	err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );
-
-	require_action( !err, exit, hr = S_FALSE );
-
-
-
-	ok = UTF8ToBSTR( keyBuf, temp );
-
-	require_action( ok, exit, hr = S_FALSE );
-
-
-
-	*retval = temp;
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-STDMETHODIMP CTXTRecord::GetValueAtIndex(ULONG index, VARIANT* retval)
-
-{
-
-	char				keyBuf[ 64 ];
-
-	uint8_t				rawValueLen;
-
-	const void		*	rawValue;
-
-	CComBSTR			temp;
-
-	DNSServiceErrorType	err;
-
-	BOOL				ok;
-
-	HRESULT				hr = S_OK;
-
-
-
-	err = TXTRecordGetItemAtIndex( ( uint16_t ) m_byteArray.size(), &m_byteArray[ 0 ], ( uint16_t ) index, sizeof( keyBuf ), keyBuf, &rawValueLen, &rawValue );
-
-	require_action( !err, exit, hr = S_FALSE );
-
-
-
-	ok = ByteArrayToVariant( rawValue, rawValueLen, retval );
-
-	require_action( ok, exit, hr = S_FALSE );
-
-
-
-exit:
-
-
-
-	return hr;
-
-}
-
-
-
-
-
-void
-
-CTXTRecord::SetBytes
-
-	(
-
-	const unsigned char	*	bytes,
-
-	uint16_t				len
-
-	)
-
-{
-
-	check ( bytes != NULL );
-
-	check( len );
-
-
-
-	m_byteArray.reserve( len );
-
-	m_byteArray.assign( bytes, bytes + len );
-
-}
-
diff --git a/mDNSWindows/DLLX/TXTRecord.h b/mDNSWindows/DLLX/TXTRecord.h
deleted file mode 100644
index 67f3bdc..0000000
--- a/mDNSWindows/DLLX/TXTRecord.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma once
-
-#include "resource.h"       // main symbols
-
-#include "DLLX.h"
-
-#include <vector>
-
-#include <dns_sd.h>
-
-
-
-
-
-#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
-
-#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
-
-#endif
-
-
-
-
-
-
-
-// CTXTRecord
-
-
-
-class ATL_NO_VTABLE CTXTRecord :
-
-	public CComObjectRootEx<CComSingleThreadModel>,
-
-	public CComCoClass<CTXTRecord, &CLSID_TXTRecord>,
-
-	public IDispatchImpl<ITXTRecord, &IID_ITXTRecord, &LIBID_Bonjour, /*wMajor =*/ 1, /*wMinor =*/ 0>
-
-{
-
-public:
-
-	CTXTRecord()
-
-	:
-
-		m_allocated( FALSE )
-
-	{
-
-	}
-
-
-
-DECLARE_REGISTRY_RESOURCEID(IDR_TXTRECORD)
-
-
-
-
-
-BEGIN_COM_MAP(CTXTRecord)
-
-	COM_INTERFACE_ENTRY(ITXTRecord)
-
-	COM_INTERFACE_ENTRY(IDispatch)
-
-END_COM_MAP()
-
-
-
-
-
-
-
-	DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-
-
-	HRESULT FinalConstruct()
-
-	{
-
-		return S_OK;
-
-	}
-
-
-
-	void FinalRelease()
-
-	{
-
-		if ( m_allocated )
-
-		{
-
-			TXTRecordDeallocate( &m_tref );
-
-		}
-
-	}
-
-
-
-public:
-
-
-
-	STDMETHOD(SetValue)(BSTR key, VARIANT value);
-
-	STDMETHOD(RemoveValue)(BSTR key);
-
-	STDMETHOD(ContainsKey)(BSTR key, VARIANT_BOOL* retval);
-
-	STDMETHOD(GetValueForKey)(BSTR key, VARIANT* value);
-
-	STDMETHOD(GetCount)(ULONG* count);
-
-	STDMETHOD(GetKeyAtIndex)(ULONG index, BSTR* retval);
-
-	STDMETHOD(GetValueAtIndex)(ULONG index, VARIANT* retval);
-
-
-
-private:
-
-
-
-	typedef std::vector< BYTE > ByteArray;
-
-	ByteArray		m_byteArray;
-
-	BOOL			m_allocated;
-
-	TXTRecordRef	m_tref;
-
-
-
-public:
-
-
-
-	uint16_t
-
-	GetLen()
-
-	{
-
-		return TXTRecordGetLength( &m_tref );
-
-	}
-
-
-
-	const void*
-
-	GetBytes()
-
-	{
-
-		return TXTRecordGetBytesPtr( &m_tref );
-
-	}
-
-
-
-	void
-
-	SetBytes
-
-		(
-
-		const unsigned char	*	bytes,
-
-		uint16_t				len
-
-		);
-
-};
-
-
-
-OBJECT_ENTRY_AUTO(__uuidof(TXTRecord), CTXTRecord)
-
diff --git a/mDNSWindows/DLLX/_IDNSSDEvents_CP.h b/mDNSWindows/DLLX/_IDNSSDEvents_CP.h
deleted file mode 100644
index 90d778f..0000000
--- a/mDNSWindows/DLLX/_IDNSSDEvents_CP.h
+++ /dev/null
@@ -1,358 +0,0 @@
-
-// Wizard-generated connection point proxy class
-// WARNING: This file may be regenerated by the wizard
-
-
-#pragma once
-
-template<class T>
-class CProxy_IDNSSDEvents :
-	public IConnectionPointImpl<T, &__uuidof(_IDNSSDEvents)>
-{
-public:
-	HRESULT Fire_DomainFound( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR domain)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[4];
-				avarParams[3] = service;
-				avarParams[2] = flags;
-				avarParams[1] = ifIndex;
-				avarParams[1].vt = VT_UI4;
-				avarParams[0] = domain;
-				avarParams[0].vt = VT_BSTR;
-				DISPPARAMS params = { avarParams, NULL, 4, 0 };
-				hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_DomainLost( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR domain)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[4];
-				avarParams[3] = service;
-				avarParams[2] = flags;
-				avarParams[1] = ifIndex;
-				avarParams[1].vt = VT_UI4;
-				avarParams[0] = domain;
-				avarParams[0].vt = VT_BSTR;
-				DISPPARAMS params = { avarParams, NULL, 4, 0 };
-				hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_ServiceFound( IDNSSDService * browser,  DNSSDFlags flags,  ULONG ifIndex,  BSTR serviceName,  BSTR regType,  BSTR domain)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[6];
-				avarParams[5] = browser;
-				avarParams[4] = flags;
-				avarParams[3] = ifIndex;
-				avarParams[3].vt = VT_UI4;
-				avarParams[2] = serviceName;
-				avarParams[2].vt = VT_BSTR;
-				avarParams[1] = regType;
-				avarParams[1].vt = VT_BSTR;
-				avarParams[0] = domain;
-				avarParams[0].vt = VT_BSTR;
-				DISPPARAMS params = { avarParams, NULL, 6, 0 };
-				hr = pConnection->Invoke(3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_ServiceLost( IDNSSDService * browser,  DNSSDFlags flags,  ULONG ifIndex,  BSTR serviceName,  BSTR regType,  BSTR domain)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[6];
-				avarParams[5] = browser;
-				avarParams[4] = flags;
-				avarParams[3] = ifIndex;
-				avarParams[3].vt = VT_UI4;
-				avarParams[2] = serviceName;
-				avarParams[2].vt = VT_BSTR;
-				avarParams[1] = regType;
-				avarParams[1].vt = VT_BSTR;
-				avarParams[0] = domain;
-				avarParams[0].vt = VT_BSTR;
-				DISPPARAMS params = { avarParams, NULL, 6, 0 };
-				hr = pConnection->Invoke(4, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_ServiceResolved( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR fullName,  BSTR hostName,  USHORT port,  ITXTRecord * record)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[7];
-				avarParams[6] = service;
-				avarParams[5] = flags;
-				avarParams[4] = ifIndex;
-				avarParams[4].vt = VT_UI4;
-				avarParams[3] = fullName;
-				avarParams[3].vt = VT_BSTR;
-				avarParams[2] = hostName;
-				avarParams[2].vt = VT_BSTR;
-				avarParams[1] = port;
-				avarParams[1].vt = VT_UI2;
-				avarParams[0] = record;
-				DISPPARAMS params = { avarParams, NULL, 7, 0 };
-				hr = pConnection->Invoke(5, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_ServiceRegistered( IDNSSDService * service,  DNSSDFlags flags,  BSTR name,  BSTR regType,  BSTR domain)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[5];
-				avarParams[4] = service;
-				avarParams[3] = flags;
-				avarParams[2] = name;
-				avarParams[2].vt = VT_BSTR;
-				avarParams[1] = regType;
-				avarParams[1].vt = VT_BSTR;
-				avarParams[0] = domain;
-				avarParams[0].vt = VT_BSTR;
-				DISPPARAMS params = { avarParams, NULL, 5, 0 };
-				hr = pConnection->Invoke(6, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_QueryRecordAnswered( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR fullName,  DNSSDRRType rrtype,  DNSSDRRClass rrclass,  VARIANT rdata,  ULONG ttl)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[8];
-				avarParams[7] = service;
-				avarParams[6] = flags;
-				avarParams[5] = ifIndex;
-				avarParams[5].vt = VT_UI4;
-				avarParams[4] = fullName;
-				avarParams[4].vt = VT_BSTR;
-				avarParams[3] = rrtype;
-				avarParams[2] = rrclass;
-				avarParams[1] = rdata;
-				avarParams[0] = ttl;
-				avarParams[0].vt = VT_UI4;
-				DISPPARAMS params = { avarParams, NULL, 8, 0 };
-				hr = pConnection->Invoke(7, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_RecordRegistered( IDNSSDRecord * record,  DNSSDFlags flags)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[2];
-				avarParams[1] = record;
-				avarParams[0] = flags;
-				DISPPARAMS params = { avarParams, NULL, 2, 0 };
-				hr = pConnection->Invoke(8, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_AddressFound( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  BSTR hostname,  DNSSDAddressFamily addressFamily,  BSTR address,  ULONG ttl)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[7];
-				avarParams[6] = service;
-				avarParams[5] = flags;
-				avarParams[4] = ifIndex;
-				avarParams[4].vt = VT_UI4;
-				avarParams[3] = hostname;
-				avarParams[3].vt = VT_BSTR;
-				avarParams[2] = addressFamily;
-				avarParams[1] = address;
-				avarParams[1].vt = VT_BSTR;
-				avarParams[0] = ttl;
-				avarParams[0].vt = VT_UI4;
-				DISPPARAMS params = { avarParams, NULL, 7, 0 };
-				hr = pConnection->Invoke(9, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_MappingCreated( IDNSSDService * service,  DNSSDFlags flags,  ULONG ifIndex,  ULONG externalAddress,  DNSSDAddressFamily addressFamily,  DNSSDProtocol protocol,  USHORT internalPort,  USHORT externalPort,  ULONG ttl)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[9];
-				avarParams[8] = service;
-				avarParams[7] = flags;
-				avarParams[6] = ifIndex;
-				avarParams[6].vt = VT_UI4;
-				avarParams[5] = externalAddress;
-				avarParams[5].vt = VT_UI4;
-				avarParams[4] = addressFamily;
-				avarParams[3] = protocol;
-				avarParams[2] = internalPort;
-				avarParams[2].vt = VT_UI2;
-				avarParams[1] = externalPort;
-				avarParams[1].vt = VT_UI2;
-				avarParams[0] = ttl;
-				avarParams[0].vt = VT_UI4;
-				DISPPARAMS params = { avarParams, NULL, 9, 0 };
-				hr = pConnection->Invoke(10, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-	HRESULT Fire_OperationFailed( IDNSSDService * service,  DNSSDError error)
-	{
-		HRESULT hr = S_OK;
-		T * pThis = static_cast<T *>(this);
-		int cConnections = m_vec.GetSize();
-
-		for (int iConnection = 0; iConnection < cConnections; iConnection++)
-		{
-			pThis->Lock();
-			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
-			pThis->Unlock();
-
-			IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);
-
-			if (pConnection)
-			{
-				CComVariant avarParams[2];
-				avarParams[1] = service;
-				avarParams[0] = error;
-				DISPPARAMS params = { avarParams, NULL, 2, 0 };
-				hr = pConnection->Invoke(11, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
-			}
-		}
-		return hr;
-	}
-};
-
diff --git a/mDNSWindows/DLLX/dlldatax.c b/mDNSWindows/DLLX/dlldatax.c
deleted file mode 100644
index a581532..0000000
--- a/mDNSWindows/DLLX/dlldatax.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-
-
-#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL
-
-
-
-#define REGISTER_PROXY_DLL //DllRegisterServer, etc.
-
-
-
-#define _WIN32_WINNT 0x0500	//for WinNT 4.0 or Win95 with DCOM
-
-#define USE_STUBLESS_PROXY	//defined only with MIDL switch /Oicf
-
-
-
-#pragma comment(lib, "rpcns4.lib")
-
-#pragma comment(lib, "rpcrt4.lib")
-
-
-
-#define ENTRY_PREFIX	Prx
-
-
-
-#include "dlldata.c"
-
-#include "DLLX_p.c"
-
-
-
-#endif //_MERGE_PROXYSTUB
-
diff --git a/mDNSWindows/DLLX/dlldatax.h b/mDNSWindows/DLLX/dlldatax.h
deleted file mode 100644
index f8816a3..0000000
--- a/mDNSWindows/DLLX/dlldatax.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-
-
-#pragma once
-
-
-
-#ifdef _MERGE_PROXYSTUB
-
-
-
-extern "C" 
-
-{
-
-BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason, 
-
-	LPVOID lpReserved);
-
-STDAPI PrxDllCanUnloadNow(void);
-
-STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
-
-STDAPI PrxDllRegisterServer(void);
-
-STDAPI PrxDllUnregisterServer(void);
-
-}
-
-
-
-#endif
-
diff --git a/mDNSWindows/DLLX/resource.h b/mDNSWindows/DLLX/resource.h
deleted file mode 100644
index d8a0cbc..0000000
--- a/mDNSWindows/DLLX/resource.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by DLLX.rc
-//
-#define IDS_PROJNAME                    100
-#define IDR_DLLX		                101
-#define IDR_DNSSD                       102
-#define IDR_DNSSDSERVICE                103
-#define IDR_BROWSELISTENER              104
-#define IDR_RESOLVELISTENER             105
-#define IDR_TXTRECORD                   106
-#define IDR_ENUMERATEDOMAINSLISTENER    107
-#define IDR_REGISTERLISTENER            108
-#define IDR_QUERYRECORDLISTENER         109
-#define IDR_GETADDRINFOLISTENER         110
-#define IDR_DNSSDRECORD                 111
-#define IDR_REGISTERRECORDLISTENER      112
-#define IDR_NATPORTMAPPINGLISTENER      113
-#define IDR_DNSSDEVENTMANAGER           114
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        201
-#define _APS_NEXT_COMMAND_VALUE         32768
-#define _APS_NEXT_CONTROL_VALUE         201
-#define _APS_NEXT_SYMED_VALUE           115
-#endif
-#endif
diff --git a/mDNSWindows/DLLX/stdafx.h b/mDNSWindows/DLLX/stdafx.h
deleted file mode 100644
index 66fb37b..0000000
--- a/mDNSWindows/DLLX/stdafx.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2009 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.
- */
-
-
-
-#pragma once
-
-
-
-#ifndef STRICT
-
-#define STRICT
-
-#endif
-
-
-
-// Modify the following defines if you have to target a platform prior to the ones specified below.
-
-// Refer to MSDN for the latest info on corresponding values for different platforms.
-
-#ifndef WINVER				// Allow use of features specific to Windows XP or later.
-
-#define WINVER 0x0501		// Change this to the appropriate value to target other versions of Windows.
-
-#endif
-
-
-
-#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
-
-#define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.
-
-#endif						
-
-
-
-#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
-
-#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
-
-#endif
-
-
-
-#ifndef _WIN32_IE			// Allow use of features specific to IE 6.0 or later.
-
-#define _WIN32_IE 0x0600	// Change this to the appropriate value to target other versions of IE.
-
-#endif
-
-
-
-#define _ATL_APARTMENT_THREADED
-
-#define _ATL_NO_AUTOMATIC_NAMESPACE
-
-
-
-#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
-
-
-
-
-
-#include "resource.h"
-
-#include <atlbase.h>
-
-#include <atlcom.h>
-
-
-
-using namespace ATL;
\ No newline at end of file
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Resources/Resource.h b/mDNSWindows/DNSServiceBrowser/Windows/Resources/Resource.h
deleted file mode 100644
index 62602a4..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Resources/Resource.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by Application.rc
-//
-#define IDS_ABOUTBOX                    101
-#define IDS_CHOOSER_DOMAIN_COLUMN_NAME  102
-#define IDP_SOCKETS_INIT_FAILED         103
-#define IDS_CHOOSER_SERVICE_COLUMN_NAME 104
-#define IDS_CHOOSER_SERVICE_COLUMN_TYPE 104
-#define IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME 105
-#define IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME 106
-#define IDS_CHOOSER_SERVICE_COLUMN_DESC 107
-#define IDC_NAME_TEXT2                  124
-#define IDC_INFO_NAME_TEXT              124
-#define IDC_DESCRIPTION_TEXT2           125
-#define IDC_INFO_TEXT_TEXT              125
-#define IDC_IP_TEXT2                    126
-#define IDC_INFO_IP_TEXT                126
-#define IDC_IP_TEXT3                    127
-#define IDC_INFO_INTERFACE_TEXT         127
-#define IDR_MAIN_ICON                   128
-#define IDC_INFO_INTERFACE_TEXT2        128
-#define IDC_INFO_HOST_NAME_TEXT         128
-#define IDR_CHOOSER_DIALOG_MENU         136
-#define IDD_CHOOSER_DIALOG              143
-#define IDD_ABOUT_DIALOG                144
-#define IDD_LOGIN                       145
-#define IDR_CHOOSER_DIALOG_MENU_ACCELERATORS 146
-#define IDC_CHOOSER_LIST                1000
-#define IDC_SERVICE_LIST2               1001
-#define IDC_SERVICE_LIST                1001
-#define IDC_SERVICE_LIST3               1002
-#define IDC_DOMAIN_LIST                 1002
-#define IDC_ABOUT_APP_NAME_TEXT         1105
-#define IDC_ABOUT_APP_VERSION_TEXT      1106
-#define IDC_ABOUT_COPYRIGHT_TEXT        1107
-#define IDC_ABOUT_APP_ICON              1108
-#define IDC_LOGIN_USERNAME_TEXT         1182
-#define IDC_EDIT2                       1183
-#define IDC_LOGIN_PASSWORD_TEXT         1183
-#define ID_FILE_EXIT                    32771
-#define ID_HELP_ABOUT                   32806
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        164
-#define _APS_NEXT_COMMAND_VALUE         32809
-#define _APS_NEXT_CONTROL_VALUE         1185
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp
deleted file mode 100644
index 8dd6b09..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	<stdlib.h>
-
-#include	"stdafx.h"
-
-#include	"AboutDialog.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(AboutDialog, CDialog)
-	//{{AFX_MSG_MAP(AboutDialog)
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-//===========================================================================================================================
-//	AboutDialog
-//===========================================================================================================================
-
-AboutDialog::AboutDialog(CWnd* pParent /*=NULL*/)
-	: CDialog(AboutDialog::IDD, pParent)
-{
-	//{{AFX_DATA_INIT(AboutDialog)
-		// Note: the ClassWizard will add member initialization here
-	//}}AFX_DATA_INIT
-}
-
-//===========================================================================================================================
-//	OnInitDialog
-//===========================================================================================================================
-
-BOOL	AboutDialog::OnInitDialog() 
-{
-	CDialog::OnInitDialog();
-	return( true );
-}
-
-//===========================================================================================================================
-//	DoDataExchange
-//===========================================================================================================================
-
-void	AboutDialog::DoDataExchange(CDataExchange* pDX)
-{
-	CDialog::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(AboutDialog)
-		// Note: the ClassWizard will add DDX and DDV calls here
-	//}}AFX_DATA_MAP
-}
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h b/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h
deleted file mode 100644
index cdd257c..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/AboutDialog.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_)
-#define AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include	"Resource.h"
-
-//===========================================================================================================================
-//	AboutDialog
-//===========================================================================================================================
-
-class	AboutDialog : public CDialog
-{
-	public:
-		
-		// Creation/Deletion
-		
-		AboutDialog(CWnd* pParent = NULL);   // standard constructor
-		
-		//{{AFX_DATA(AboutDialog)
-		enum { IDD = IDD_ABOUT_DIALOG };
-			// Note: the ClassWizard will add data members here
-		//}}AFX_DATA
-		
-		// ClassWizard generated virtual function overrides
-		//{{AFX_VIRTUAL(AboutDialog)
-		protected:
-		virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-		//}}AFX_VIRTUAL
-
-	protected:
-
-		// Generated message map functions
-		//{{AFX_MSG(AboutDialog)
-		virtual BOOL OnInitDialog();
-		//}}AFX_MSG
-		DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.cpp
deleted file mode 100644
index f7f4b03..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	<assert.h>
-
-#include	"StdAfx.h"
-
-#include	"DNSServices.h"
-
-#include	"Application.h"
-
-#include	"ChooserDialog.h"
-
-#include	"stdafx.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(Application, CWinApp)
-	//{{AFX_MSG_MAP(Application)
-		// NOTE - the ClassWizard will add and remove mapping macros here.
-		//    DO NOT EDIT what you see in these blocks of generated code!
-	//}}AFX_MSG
-	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
-END_MESSAGE_MAP()
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-Application		gApp;
-
-//===========================================================================================================================
-//	Application
-//===========================================================================================================================
-
-Application::Application( void )
-{
-	//
-}
-
-//===========================================================================================================================
-//	InitInstance
-//===========================================================================================================================
-
-BOOL	Application::InitInstance()
-{
-	DNSStatus		err;
-	
-	// Standard MFC initialization.
-
-#if( !defined( AFX_DEPRECATED ) )
-	#ifdef _AFXDLL
-		Enable3dControls();			// Call this when using MFC in a shared DLL
-	#else
-		Enable3dControlsStatic();	// Call this when linking to MFC statically
-	#endif
-#endif
-
-	InitCommonControls();
-	
-	// Set up DNS Services.
-	
-	err = DNSServicesInitialize( 0, 512 );
-	assert( err == kDNSNoErr );
-	
-	// Create the chooser dialog.
-	
-	ChooserDialog *		dialog;
-	
-	m_pMainWnd = NULL;
-	dialog = new ChooserDialog;
-	dialog->Create( IDD_CHOOSER_DIALOG );
-	m_pMainWnd = dialog;
-	dialog->ShowWindow( SW_SHOW );
-	
-	return( true );
-}
-
-//===========================================================================================================================
-//	ExitInstance
-//===========================================================================================================================
-
-int	Application::ExitInstance( void )
-{
-	// Clean up DNS Services.
-	
-	DNSServicesFinalize();
-	return( 0 );
-}
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.h b/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.h
deleted file mode 100644
index 8368a49..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/Application.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_)
-#define AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include	"stdafx.h"
-
-#ifndef __AFXWIN_H__
-	#error include 'stdafx.h' before including this file for PCH
-#endif
-
-#include	"Resource.h"
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-extern class Application		gApp;
-
-//===========================================================================================================================
-//	Application
-//===========================================================================================================================
-
-class	Application : public CWinApp
-{
-	public:
-		
-		// Creation/Deletion
-		
-		Application();
-		
-		// ClassWizard generated virtual function overrides
-		//{{AFX_VIRTUAL(Application)
-		public:
-		virtual BOOL InitInstance();
-		virtual int ExitInstance( void );
-		//}}AFX_VIRTUAL
-		
-		//{{AFX_MSG(Application)
-			// NOTE - the ClassWizard will add and remove member functions here.
-			//    DO NOT EDIT what you see in these blocks of generated code !
-		//}}AFX_MSG
-		DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
deleted file mode 100644
index fe46be0..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
+++ /dev/null
@@ -1,1426 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	<assert.h>
-#include	<stdio.h>
-#include	<stdlib.h>
-#include	<string.h>
-#include	<time.h>
-
-#include	<algorithm>
-#include	<memory>
-
-#include	"stdafx.h"
-
-#include	"DNSServices.h"
-
-#include	"Application.h"
-#include	"AboutDialog.h"
-#include	"LoginDialog.h"
-#include	"Resource.h"
-
-#include	"ChooserDialog.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-// Menus
-
-enum
-{
-	kChooserMenuIndexFile	= 0, 
-	kChooserMenuIndexHelp	= 1 
-};
-
-// Domain List
-	
-#define kDomainListDefaultDomainColumnWidth		 		164 
-	
-// Service List
-
-#define kServiceListDefaultServiceColumnTypeWidth		146
-#define kServiceListDefaultServiceColumnDescWidth		230
-	
-// Chooser List
-	
-#define kChooserListDefaultNameColumnWidth				190
-#define kChooserListDefaultIPColumnWidth				120
-
-// Windows User Messages
-
-#define	WM_USER_DOMAIN_ADD								( WM_USER + 0x100 )
-#define	WM_USER_DOMAIN_REMOVE							( WM_USER + 0x101 )
-#define	WM_USER_SERVICE_ADD								( WM_USER + 0x102 )
-#define	WM_USER_SERVICE_REMOVE							( WM_USER + 0x103 )
-#define	WM_USER_RESOLVE									( WM_USER + 0x104 )
-
-#if 0
-#pragma mark == Constants - Service Table ==
-#endif
-
-//===========================================================================================================================
-//	Constants - Service Table
-//===========================================================================================================================
-
-struct	KnownServiceEntry
-{
-	const char *		serviceType;
-	const char *		description;
-	const char *		urlScheme;
-	bool				useText;
-};
-
-static const KnownServiceEntry		kKnownServiceTable[] =
-{
-	{ "_accountedge._tcp.",	 		"MYOB AccountEdge", 										"", 			false },
-	{ "_aecoretech._tcp.", 			"Apple Application Engineering Services",					"", 			false },
-	{ "_afpovertcp._tcp.", 			"Apple File Sharing (AFP)", 								"afp://", 		false },
-	{ "_airport._tcp.", 			"AirPort Base Station",										"", 			false }, 
-	{ "_apple-sasl._tcp.", 			"Apple Password Server", 									"", 			false },
-	{ "_aquamon._tcp.", 			"AquaMon", 													"", 			false },
-	{ "_async._tcp", 				"address-o-sync", 											"", 			false },
-	{ "_auth._tcp.", 				"Authentication Service",									"", 			false },
-	{ "_bootps._tcp.", 				"Bootstrap Protocol Server",								"", 			false },
-	{ "_bousg._tcp.", 				"Bag Of Unusual Strategy Games",							"", 			false },
-	{ "_browse._udp.", 				"DNS Service Discovery",									"", 			false },
-	{ "_cheat._tcp.", 				"The Cheat",												"", 			false },
-	{ "_chess._tcp", 				"Project Gridlock", 										"", 			false },
-	{ "_chfts._tcp", 				"Fluid Theme Server", 										"", 			false },
-	{ "_clipboard._tcp", 			"Clipboard Sharing", 										"", 			false },
-	{ "_contactserver._tcp.", 		"Now Up-to-Date & Contact",									"", 			false },
-	{ "_cvspserver._tcp", 			"CVS PServer", 												"", 			false },
-	{ "_cytv._tcp.", 				"CyTV Network streaming for Elgato EyeTV",					"", 			false },
-	{ "_daap._tcp.", 				"Digital Audio Access Protocol (iTunes)",					"daap://",		false }, 
-	{ "_distcc._tcp", 				"Distributed Compiler", 									"", 			false },
-	{ "_dns-sd._udp", 				"DNS Service Discovery", 									"", 			false },
-	{ "_dpap._tcp.", 				"Digital Picture Access Protocol (iPhoto)",					"", 			false },
-	{ "_earphoria._tcp.", 			"Earphoria",												"", 			false },
-	{ "_ecbyesfsgksc._tcp.", 		"Net Monitor Anti-Piracy Service",							"",				false },
-	{ "_eheap._tcp.", 				"Interactive Room Software",								"",				false },
-	{ "_embrace._tcp.", 			"DataEnvoy",												"",				false },
-	{ "_eppc._tcp.", 				"Remote AppleEvents", 										"eppc://", 		false }, 
-	{ "_exec._tcp.", 				"Remote Process Execution",									"",				false },
-	{ "_facespan._tcp.", 			"FaceSpan",													"",				false },
-	{ "_fjork._tcp.", 				"Fjork",													"",				false },
-	{ "_ftp._tcp.", 				"File Transfer (FTP)", 										"ftp://", 		false }, 
-	{ "_ftpcroco._tcp.", 			"Crocodile FTP Server",										"",				false },
-	{ "_gbs-smp._tcp.", 			"SnapMail",													"",				false },
-	{ "_gbs-stp._tcp.", 			"SnapTalk",													"",				false },
-	{ "_grillezvous._tcp.", 		"Roxio ToastAnywhere(tm) Recorder Sharing",					"",				false },
-	{ "_h323._tcp.", 				"H.323",													"",				false },
-	{ "_hotwayd._tcp", 				"Hotwayd", 													"", 			false },
-	{ "_http._tcp.", 				"Web Server (HTTP)", 										"http://", 		true  }, 
-	{ "_hydra._tcp", 				"SubEthaEdit", 												"", 			false },
-	{ "_ica-networking._tcp.", 		"Image Capture Networking",									"", 			false }, 
-	{ "_ichalkboard._tcp.", 		"iChalk",													"", 			false }, 
-	{ "_ichat._tcp.", 				"iChat",				 									"ichat://",		false }, 
-	{ "_iconquer._tcp.",	 		"iConquer",													"", 			false }, 
-	{ "_imap._tcp.", 				"Internet Message Access Protocol",							"",				false },
-	{ "_imidi._tcp.", 				"iMidi",													"",				false },
-	{ "_ipp._tcp.", 				"Printer (IPP)", 											"ipp://", 		false },
-	{ "_ishare._tcp.", 				"iShare",													"",				false },
-	{ "_isparx._tcp.", 				"iSparx",													"",				false },
-	{ "_istorm._tcp", 				"iStorm", 													"", 			false },
-	{ "_iwork._tcp.", 				"iWork Server",												"",				false },
-	{ "_liaison._tcp.", 			"Liaison",													"",				false },
-	{ "_login._tcp.", 				"Remote Login a la Telnet",									"",				false },
-	{ "_lontalk._tcp.", 			"LonTalk over IP (ANSI 852)",								"",				false },
-	{ "_lonworks._tcp.", 			"Echelon LNS Remote Client",								"",				false },
-	{ "_macfoh-remote._tcp.", 		"MacFOH Remote",											"",				false },
-	{ "_moneyworks._tcp.", 			"MoneyWorks",												"",				false },
-	{ "_mp3sushi._tcp", 			"MP3 Sushi", 												"", 			false },
-	{ "_mttp._tcp.", 				"MenuTunes Sharing",										"",				false },
-	{ "_ncbroadcast._tcp.", 		"Network Clipboard Broadcasts",								"",				false },
-	{ "_ncdirect._tcp.", 			"Network Clipboard Direct Transfers",						"",				false },
-	{ "_ncsyncserver._tcp.", 		"Network Clipboard Sync Server",							"",				false },
-	{ "_newton-dock._tcp.", 		"Escale",													"",				false },
-	{ "_nfs._tcp", 					"NFS", 														"", 			false },
-	{ "_nssocketport._tcp.", 		"DO over NSSocketPort",										"",				false },
-	{ "_omni-bookmark._tcp.", 		"OmniWeb",													"",				false },
-	{ "_openbase._tcp.", 			"OpenBase SQL",												"",				false },
-	{ "_p2pchat._tcp.", 			"Peer-to-Peer Chat",										"",				false },
-	{ "_pdl-datastream._tcp.", 		"Printer (PDL)", 											"pdl://", 		false }, 
-	{ "_poch._tcp.", 				"Parallel OperatiOn and Control Heuristic",					"",				false },
-	{ "_pop_2_ambrosia._tcp.",		"Pop-Pop",													"",				false },
-	{ "_pop3._tcp", 				"POP3 Server", 												"", 			false },
-	{ "_postgresql._tcp", 			"PostgreSQL Server", 										"", 			false },
-	{ "_presence._tcp", 			"iChat AV", 												"", 			false },
-	{ "_printer._tcp.", 			"Printer (LPR)", 											"lpr://", 		false }, 
-	{ "_ptp._tcp.", 				"Picture Transfer (PTP)", 									"ptp://", 		false },
-	{ "_register._tcp", 			"DNS Service Discovery", 									"", 			false },
-	{ "_rfb._tcp.", 				"Remote Frame Buffer",										"",				false },
-	{ "_riousbprint._tcp.", 		"Remote I/O USB Printer Protocol",							"",				false },
-	{ "_rtsp._tcp.", 				"Real Time Stream Control Protocol",						"",				false },
-	{ "_safarimenu._tcp", 			"Safari Menu", 												"", 			false },
-	{ "_scone._tcp", 				"Scone", 													"", 			false },
-	{ "_sdsharing._tcp.", 			"Speed Download",											"",				false },
-	{ "_seeCard._tcp.", 			"seeCard",													"",				false },
-	{ "_services._udp.", 			"DNS Service Discovery",									"",				false },
-	{ "_shell._tcp.", 				"like exec, but automatic authentication",					"",				false },
-	{ "_shout._tcp.", 				"Shout",													"",				false },
-	{ "_shoutcast._tcp", 			"Nicecast", 												"", 			false },
-	{ "_smb._tcp.", 				"Windows File Sharing (SMB)", 								"smb://", 		false }, 
-	{ "_soap._tcp.", 				"Simple Object Access Protocol", 							"", 			false }, 
-	{ "_spincrisis._tcp.", 			"Spin Crisis",												"",				false },
-	{ "_spl-itunes._tcp.", 			"launchTunes",												"",				false },
-	{ "_spr-itunes._tcp.", 			"netTunes",													"",				false },
-	{ "_ssh._tcp.", 				"Secure Shell (SSH)", 										"ssh://", 		false }, 
-	{ "_ssscreenshare._tcp", 		"Screen Sharing", 											"", 			false },
-	{ "_sge-exec._tcp", 			"Sun Grid Engine (Execution Host)", 						"", 			false },
-	{ "_sge-qmaster._tcp", 			"Sun Grid Engine (Master)", 								"", 			false },
-	{ "_stickynotes._tcp", 			"Sticky Notes", 											"", 			false },
-	{ "_strateges._tcp", 			"Strateges", 												"", 			false },
-	{ "_sxqdea._tcp", 				"Synchronize! Pro X", 										"", 			false },
-	{ "_sybase-tds._tcp", 			"Sybase Server", 											"", 			false },
-	{ "_tce._tcp", 					"Power Card", 												"", 			false },
-	{ "_teamlist._tcp", 			"ARTIS Team Task",											"", 			false },
-	{ "_teleport._tcp", 			"teleport",													"", 			false },
-	{ "_telnet._tcp.", 				"Telnet", 													"telnet://", 	false }, 
-	{ "_tftp._tcp.", 				"Trivial File Transfer (TFTP)", 							"tftp://", 		false }, 
-	{ "_tinavigator._tcp.", 		"TI Navigator", 											"", 			false }, 
-	{ "_tivo_servemedia._tcp", 		"TiVo",														"", 			false },
-	{ "_upnp._tcp.", 				"Universal Plug and Play", 									"", 			false }, 
-	{ "_utest._tcp.", 				"uTest", 													"", 			false }, 
-	{ "_vue4rendercow._tcp",		"VueProRenderCow",											"", 			false },
-	{ "_webdav._tcp.", 				"WebDAV", 													"webdav://",	false }, 
-	{ "_whamb._tcp.", 				"Whamb", 													"",				false }, 
-	{ "_workstation._tcp", 			"Macintosh Manager",										"", 			false },
-	{ "_ws._tcp", 					"Web Services",												"", 			false },
-	{ "_xserveraid._tcp.", 			"Xserve RAID",												"xsr://", 		false }, 
-	{ "_xsync._tcp.",	 			"Xserve RAID Synchronization",								"",		 		false }, 
-	
-	{ "",	 						"",															"",		 		false }, 
-	
-	// Unofficial and invalid service types that will be phased out:
-	
-	{ "_clipboardsharing._tcp.",			"ClipboardSharing",									"",		 		false }, 
-	{ "_MacOSXDupSuppress._tcp.",			"Mac OS X Duplicate Suppression",					"",		 		false }, 
-	{ "_netmonitorserver._tcp.",			"Net Monitor Server",								"",		 		false }, 
-	{ "_networkclipboard._tcp.",			"Network Clipboard",								"",		 		false }, 
-	{ "_slimdevices_slimp3_cli._tcp.",		"SliMP3 Server Command-Line Interface",				"",		 		false }, 
-	{ "_slimdevices_slimp3_http._tcp.",		"SliMP3 Server Web Interface",						"",		 		false }, 
-	{ "_tieducationalhandhelddevice._tcp.",	"TI Connect Manager",								"",		 		false }, 
-	{ "_tivo_servemedia._tcp.",				"TiVo",												"",		 		false }, 
-	
-	{ NULL,							NULL,														NULL,			false }, 
-};
-
-#if 0
-#pragma mark == Structures ==
-#endif
-
-//===========================================================================================================================
-//	Structures
-//===========================================================================================================================
-
-struct	DomainEventInfo
-{
-	DNSBrowserEventType		eventType;
-	CString					domain;
-	DNSNetworkAddress		ifIP;
-};
-
-struct	ServiceEventInfo
-{
-	DNSBrowserEventType		eventType;
-	std::string				name;
-	std::string				type;
-	std::string				domain;
-	DNSNetworkAddress		ifIP;
-};
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-static void
-	BrowserCallBack( 
-		void *					inContext, 
-		DNSBrowserRef			inRef, 
-		DNSStatus				inStatusCode,
-		const DNSBrowserEvent *	inEvent );
-
-static char *	DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, size_t inLen, char *outString );
-
-static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject );
-static DWORD	StringObjectToUTF8String( CString &inObject, std::string &outUTF8 );
-
-#if 0
-#pragma mark == Message Map ==
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(ChooserDialog, CDialog)
-	//{{AFX_MSG_MAP(ChooserDialog)
-	ON_WM_SYSCOMMAND()
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_DOMAIN_LIST, OnDomainListChanged)
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_SERVICE_LIST, OnServiceListChanged)
-	ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHOOSER_LIST, OnChooserListChanged)
-	ON_NOTIFY(NM_DBLCLK, IDC_CHOOSER_LIST, OnChooserListDoubleClick)
-	ON_COMMAND(ID_HELP_ABOUT, OnAbout)
-	ON_WM_INITMENUPOPUP()
-	ON_WM_ACTIVATE()
-	ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
-	ON_COMMAND(ID_FILE_EXIT, OnExit)
-	ON_WM_CLOSE()
-	ON_WM_NCDESTROY()
-	//}}AFX_MSG_MAP
-	ON_MESSAGE( WM_USER_DOMAIN_ADD, OnDomainAdd )
-	ON_MESSAGE( WM_USER_DOMAIN_REMOVE, OnDomainRemove )
-	ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd )
-	ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove )
-	ON_MESSAGE( WM_USER_RESOLVE, OnResolve )
-END_MESSAGE_MAP()
-
-#if 0
-#pragma mark == Routines ==
-#endif
-
-//===========================================================================================================================
-//	ChooserDialog
-//===========================================================================================================================
-
-ChooserDialog::ChooserDialog( CWnd *inParent )
-	: CDialog( ChooserDialog::IDD, inParent)
-{
-	//{{AFX_DATA_INIT(ChooserDialog)
-		// Note: the ClassWizard will add member initialization here
-	//}}AFX_DATA_INIT
-	
-	// Load menu accelerator table.
-
-	mMenuAcceleratorTable = ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ) );
-	assert( mMenuAcceleratorTable );
-	
-	mBrowser 			= NULL;
-	mIsServiceBrowsing	= false;
-}
-
-//===========================================================================================================================
-//	~ChooserDialog
-//===========================================================================================================================
-
-ChooserDialog::~ChooserDialog( void )
-{
-	if( mBrowser )
-	{
-		DNSStatus		err;
-		
-		err = DNSBrowserRelease( mBrowser, 0 );
-		assert( err == kDNSNoErr );
-	}
-}
-
-//===========================================================================================================================
-//	DoDataExchange
-//===========================================================================================================================
-
-void ChooserDialog::DoDataExchange( CDataExchange *pDX )
-{
-	CDialog::DoDataExchange(pDX);
-
-	//{{AFX_DATA_MAP(ChooserDialog)
-	DDX_Control(pDX, IDC_SERVICE_LIST, mServiceList);
-	DDX_Control(pDX, IDC_DOMAIN_LIST, mDomainList);
-	DDX_Control(pDX, IDC_CHOOSER_LIST, mChooserList);
-	//}}AFX_DATA_MAP
-}
-
-//===========================================================================================================================
-//	OnInitDialog
-//===========================================================================================================================
-
-BOOL	ChooserDialog::OnInitDialog( void )
-{
-	HICON			icon;
-	BOOL			result;
-	CString			tempString;
-	DNSStatus		err;
-	
-	// Initialize our parent.
-
-	CDialog::OnInitDialog();
-	
-	// Set up the window icon.
-	
-	icon = AfxGetApp()->LoadIcon( IDR_MAIN_ICON );
-	assert( icon );
-	if( icon )
-	{
-		SetIcon( icon, TRUE );		// Set big icon
-		SetIcon( icon, FALSE );		// Set small icon
-	}
-	
-	// Set up the Domain List.
-	
-	result = tempString.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME );
-	assert( result );
-	mDomainList.InsertColumn( 0, tempString, LVCFMT_LEFT, kDomainListDefaultDomainColumnWidth );
-	
-	// Set up the Service List.
-	
-	result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_TYPE );
-	assert( result );
-	mServiceList.InsertColumn( 0, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnTypeWidth );
-	
-	result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_DESC );
-	assert( result );
-	mServiceList.InsertColumn( 1, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnDescWidth );
-	
-	PopulateServicesList();
-	
-	// Set up the Chooser List.
-	
-	result = tempString.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME );
-	assert( result );
-	mChooserList.InsertColumn( 0, tempString, LVCFMT_LEFT, kChooserListDefaultNameColumnWidth );
-	
-	result = tempString.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME );
-	assert( result );
-	mChooserList.InsertColumn( 1, tempString, LVCFMT_LEFT, kChooserListDefaultIPColumnWidth );
-	
-	// Set up the other controls.
-	
-	UpdateInfoDisplay();
-	
-	// Start browsing for domains.
-	
-	err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser );
-	assert( err == kDNSNoErr );
-	
-	err = DNSBrowserStartDomainSearch( mBrowser, 0 );
-	assert( err == kDNSNoErr );
-	
-	return( true );
-}
-
-//===========================================================================================================================
-//	OnFileClose
-//===========================================================================================================================
-
-void ChooserDialog::OnFileClose() 
-{
-	OnClose();
-}
-
-//===========================================================================================================================
-//	OnActivate
-//===========================================================================================================================
-
-void ChooserDialog::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized )
-{
-	// Always make the active window the "main" window so modal dialogs work better and the app quits after closing 
-	// the last window.
-
-	gApp.m_pMainWnd = this;
-
-	CDialog::OnActivate(nState, pWndOther, bMinimized);
-}
-
-//===========================================================================================================================
-//	PostNcDestroy
-//===========================================================================================================================
-
-void	ChooserDialog::PostNcDestroy() 
-{
-	// Call the base class to do the normal cleanup.
-
-	delete this;
-}
-
-//===========================================================================================================================
-//	PreTranslateMessage
-//===========================================================================================================================
-
-BOOL	ChooserDialog::PreTranslateMessage(MSG* pMsg) 
-{
-	BOOL		result;
-	
-	result = false;
-	assert( mMenuAcceleratorTable );
-	if( mMenuAcceleratorTable )
-	{
-		result = ::TranslateAccelerator( m_hWnd, mMenuAcceleratorTable, pMsg );
-	}
-	if( !result )
-	{
-		result = CDialog::PreTranslateMessage( pMsg );
-	}
-	return( result );
-}
-
-//===========================================================================================================================
-//	OnInitMenuPopup
-//===========================================================================================================================
-
-void	ChooserDialog::OnInitMenuPopup( CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu ) 
-{
-	CDialog::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu );
-
-	switch( nIndex )
-	{
-		case kChooserMenuIndexFile:
-			break;
-
-		case kChooserMenuIndexHelp:
-			break;
-
-		default:
-			break;
-	}
-}
-
-//===========================================================================================================================
-//	OnExit
-//===========================================================================================================================
-
-void ChooserDialog::OnExit() 
-{
-	OnClose();
-}
-
-//===========================================================================================================================
-//	OnAbout
-//===========================================================================================================================
-
-void	ChooserDialog::OnAbout() 
-{
-	AboutDialog		dialog;
-	
-	dialog.DoModal();
-}
-
-//===========================================================================================================================
-//	OnSysCommand
-//===========================================================================================================================
-
-void	ChooserDialog::OnSysCommand( UINT inID, LPARAM inParam ) 
-{
-	CDialog::OnSysCommand( inID, inParam );
-}
-
-//===========================================================================================================================
-//	OnClose
-//===========================================================================================================================
-
-void ChooserDialog::OnClose() 
-{
-	StopBrowsing();
-	
-	gApp.m_pMainWnd = this;
-	DestroyWindow();
-}
-
-//===========================================================================================================================
-//	OnNcDestroy
-//===========================================================================================================================
-
-void ChooserDialog::OnNcDestroy() 
-{
-	gApp.m_pMainWnd = this;
-
-	CDialog::OnNcDestroy();
-}
-
-//===========================================================================================================================
-//	OnDomainListChanged
-//===========================================================================================================================
-
-void	ChooserDialog::OnDomainListChanged( NMHDR *pNMHDR, LRESULT *pResult ) 
-{
-	UNUSED_ALWAYS( pNMHDR );
-	
-	// Domain list changes have similar effects to service list changes so reuse that code path by calling it here.
-	
-	OnServiceListChanged( NULL, NULL );
-	
-	*pResult = 0;
-}
-
-//===========================================================================================================================
-//	OnServiceListChanged
-//===========================================================================================================================
-
-void	ChooserDialog::OnServiceListChanged( NMHDR *pNMHDR, LRESULT *pResult ) 
-{
-	int				selectedType;
-	int				selectedDomain;
-	
-	UNUSED_ALWAYS( pNMHDR );
-	
-	// Stop any existing service search.
-	
-	StopBrowsing();
-	
-	// If a domain and service type are selected, start searching for the service type on the domain.
-	
-	selectedType 	= mServiceList.GetNextItem( -1, LVNI_SELECTED );
-	selectedDomain 	= mDomainList.GetNextItem( -1, LVNI_SELECTED );
-	
-	if( ( selectedType >= 0 ) && ( selectedDomain >= 0 ) )
-	{
-		CString				s;
-		std::string			utf8;
-		const char *		type;
-		
-		s = mDomainList.GetItemText( selectedDomain, 0 );
-		StringObjectToUTF8String( s, utf8 );
-		type = mServiceTypes[ selectedType ].serviceType.c_str();
-		if( *type != '\0' )
-		{
-			StartBrowsing( type, utf8.c_str() );
-		}
-	}
-	
-	if( pResult )
-	{
-		*pResult = 0;
-	}
-}
-
-//===========================================================================================================================
-//	OnChooserListChanged
-//===========================================================================================================================
-
-void	ChooserDialog::OnChooserListChanged( NMHDR *pNMHDR, LRESULT *pResult ) 
-{
-	UNUSED_ALWAYS( pNMHDR );
-	
-	UpdateInfoDisplay();
-	*pResult = 0;
-}
-
-//===========================================================================================================================
-//	OnChooserListDoubleClick
-//===========================================================================================================================
-
-void	ChooserDialog::OnChooserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult )
-{
-	int		selectedItem;
-	
-	UNUSED_ALWAYS( pNMHDR );
-	
-	// Display the service instance if it is selected. Otherwise, clear all the info.
-	
-	selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED );
-	if( selectedItem >= 0 )
-	{
-		ServiceInstanceInfo *			p;
-		CString							url;
-		const KnownServiceEntry *		service;
-		
-		assert( selectedItem < (int) mServiceInstances.size() );
-		p = &mServiceInstances[ selectedItem ];
-		
-		// Search for a known service type entry that matches.
-		
-		for( service = kKnownServiceTable; service->serviceType; ++service )
-		{
-			if( p->type == service->serviceType )
-			{
-				break;
-			}
-		}
-		if( service->serviceType )
-		{
-			const char *		text;
-			
-			// Create a URL representing the service instance.
-			
-			if( strcmp( service->serviceType, "_smb._tcp." ) == 0 )
-			{
-				// Special case for SMB (no port number).
-				
-				url.Format( TEXT( "%s%s/" ), service->urlScheme, (const char *) p->ip.c_str() ); 
-			}
-			else if( strcmp( service->serviceType, "_ftp._tcp." ) == 0 )
-			{
-				// Special case for FTP to get login info.
-
-				LoginDialog		dialog;
-				CString			username;
-				CString			password;
-				
-				if( !dialog.GetLogin( username, password ) )
-				{
-					goto exit;
-				}
-				
-				// Build URL in the following format:
-				//
-				// ftp://[username[:password]@]<ip>
-				
-				url += service->urlScheme;
-				if( username.GetLength() > 0 )
-				{
-					url += username;
-					if( password.GetLength() > 0 )
-					{
-						url += ':';
-						url += password;
-					}
-					url += '@';
-				}
-				url += p->ip.c_str();
-			}
-			else if( strcmp( service->serviceType, "_http._tcp." ) == 0 )
-			{
-				// Special case for HTTP to exclude "path=" if present.
-				
-				text = service->useText ? p->text.c_str() : "";
-				if( strncmp( text, "path=", 5 ) == 0 )
-				{
-					text += 5;
-				}
-				if( *text != '/' )
-				{
-					url.Format( TEXT( "%s%s/%s" ), service->urlScheme, (const char *) p->ip.c_str(), text );
-				}
-				else
-				{
-					url.Format( TEXT( "%s%s%s" ), service->urlScheme, (const char *) p->ip.c_str(), text );
-				}
-			}
-			else
-			{
-				text = service->useText ? p->text.c_str() : "";
-				url.Format( TEXT( "%s%s/%s" ), service->urlScheme, (const char *) p->ip.c_str(), text ); 
-			}
-			
-			// Let the system open the URL in the correct app.
-			
-			{
-				CWaitCursor		waitCursor;
-				
-				ShellExecute( NULL, TEXT( "open" ), url, TEXT( "" ), TEXT( "c:\\" ), SW_SHOWNORMAL );
-			}
-		}
-	}
-
-exit:
-	*pResult = 0;
-}
-
-//===========================================================================================================================
-//	OnCancel
-//===========================================================================================================================
-
-void ChooserDialog::OnCancel() 
-{
-	// Do nothing.
-}
-
-//===========================================================================================================================
-//	PopulateServicesList
-//===========================================================================================================================
-
-void	ChooserDialog::PopulateServicesList( void )
-{
-	ServiceTypeVector::iterator		i;
-	CString							type;
-	CString							desc;
-	std::string						tmp;
-	
-	// Add a fixed list of known services.
-	
-	if( mServiceTypes.empty() )
-	{
-		const KnownServiceEntry *		service;
-		
-		for( service = kKnownServiceTable; service->serviceType; ++service )
-		{
-			ServiceTypeInfo		info;
-			
-			info.serviceType 	= service->serviceType;
-			info.description 	= service->description;
-			info.urlScheme 		= service->urlScheme;
-			mServiceTypes.push_back( info );
-		}
-	}
-	
-	// Add each service to the list.
-	
-	for( i = mServiceTypes.begin(); i != mServiceTypes.end(); ++i )
-	{
-		const char *		p;
-		const char *		q;
-		
-		p  = ( *i ).serviceType.c_str();
-		if( *p == '_' ) ++p;							// Skip leading '_'.
-		q  = strchr( p, '.' );							// Find first '.'.
-		if( q )	tmp.assign( p, (size_t)( q - p ) );		// Use only up to the first '.'.
-		else	tmp.assign( p );						// No '.' so use the entire string.
-		UTF8StringToStringObject( tmp.c_str(), type );
-		UTF8StringToStringObject( ( *i ).description.c_str(), desc );
-		
-		int		n;
-		
-		n = mServiceList.GetItemCount();
-		mServiceList.InsertItem( n, type );
-		mServiceList.SetItemText( n, 1, desc );
-	}
-	
-	// Select the first service type by default.
-	
-	if( !mServiceTypes.empty() )
-	{
-		mServiceList.SetItemState( 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
-	}
-}
-
-//===========================================================================================================================
-//	UpdateInfoDisplay
-//===========================================================================================================================
-
-void	ChooserDialog::UpdateInfoDisplay( void )
-{
-	int							selectedItem;
-	std::string					name;
-	CString						s;
-	std::string					ip;
-	std::string					ifIP;
-	std::string					text;
-	std::string					textNewLines;
-	std::string					hostName;
-	CWnd *						item;
-	std::string::iterator		i;
-	
-	// Display the service instance if it is selected. Otherwise, clear all the info.
-	
-	selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED );
-	if( selectedItem >= 0 )
-	{
-		ServiceInstanceInfo *		p;
-		
-		assert( selectedItem < (int) mServiceInstances.size() );
-		p = &mServiceInstances[ selectedItem ];
-		
-		name 		= p->name;
-		ip 			= p->ip;
-		ifIP 		= p->ifIP;
-		text 		= p->text;
-		hostName	= p->hostName;
-
-		// Sync up the list items with the actual data (IP address may change).
-		
-		UTF8StringToStringObject( ip.c_str(), s );
-		mChooserList.SetItemText( selectedItem, 1, s );
-	}
-	
-	// Name
-	
-	item = (CWnd *) this->GetDlgItem( IDC_INFO_NAME_TEXT );
-	assert( item );
-	UTF8StringToStringObject( name.c_str(), s );
-	item->SetWindowText( s );
-	
-	// IP
-	
-	item = (CWnd *) this->GetDlgItem( IDC_INFO_IP_TEXT );
-	assert( item );
-	UTF8StringToStringObject( ip.c_str(), s );
-	item->SetWindowText( s );
-	
-	// Interface
-	
-	item = (CWnd *) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT );
-	assert( item );
-	UTF8StringToStringObject( ifIP.c_str(), s );
-	item->SetWindowText( s );
-	
-
-	item = (CWnd *) this->GetDlgItem( IDC_INFO_HOST_NAME_TEXT );
-	assert( item );
-	UTF8StringToStringObject( hostName.c_str(), s );
-	item->SetWindowText( s );
-
-	// Text
-	
-	item = (CWnd *) this->GetDlgItem( IDC_INFO_TEXT_TEXT );
-	assert( item );
-	for( i = text.begin(); i != text.end(); ++i )
-	{
-		if( *i == '\1' )
-		{
-			textNewLines += "\r\n";
-		}
-		else
-		{
-			textNewLines += *i;
-		}
-	}
-	UTF8StringToStringObject( textNewLines.c_str(), s );
-	item->SetWindowText( s );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	OnDomainAdd
-//===========================================================================================================================
-
-LONG	ChooserDialog::OnDomainAdd( WPARAM inWParam, LPARAM inLParam )
-{
-	DomainEventInfo *						p;
-	std::auto_ptr < DomainEventInfo >		pAutoPtr;
-	int										n;
-	int										i;
-	CString									domain;
-	CString									s;
-	bool									found;
-	
-	UNUSED_ALWAYS( inWParam );
-	
-	assert( inLParam );
-	p = reinterpret_cast <DomainEventInfo *> ( inLParam );
-	pAutoPtr.reset( p );
-	
-	// Search to see if we already know about this domain. If not, add it to the list.
-	
-	found = false;
-	domain = p->domain;
-	n = mDomainList.GetItemCount();
-	for( i = 0; i < n; ++i )
-	{
-		s = mDomainList.GetItemText( i, 0 );
-		if( s == domain )
-		{
-			found = true;
-			break;
-		}
-	}
-	if( !found )
-	{
-		int		selectedItem;
-		
-		mDomainList.InsertItem( n, domain );
-		
-		// If no domains are selected and the domain being added is a default domain, select it.
-		
-		selectedItem = mDomainList.GetNextItem( -1, LVNI_SELECTED );
-		if( ( selectedItem < 0 ) && ( p->eventType == kDNSBrowserEventTypeAddDefaultDomain ) )
-		{
-			mDomainList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
-		}
-	}
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnDomainRemove
-//===========================================================================================================================
-
-LONG	ChooserDialog::OnDomainRemove( WPARAM inWParam, LPARAM inLParam )
-{
-	DomainEventInfo *						p;
-	std::auto_ptr < DomainEventInfo >		pAutoPtr;
-	int										n;
-	int										i;
-	CString									domain;
-	CString									s;
-	bool									found;
-	
-	UNUSED_ALWAYS( inWParam );
-	
-	assert( inLParam );
-	p = reinterpret_cast <DomainEventInfo *> ( inLParam );
-	pAutoPtr.reset( p );
-	
-	// Search to see if we know about this domain. If so, remove it from the list.
-	
-	found = false;
-	domain = p->domain;
-	n = mDomainList.GetItemCount();
-	for( i = 0; i < n; ++i )
-	{
-		s = mDomainList.GetItemText( i, 0 );
-		if( s == domain )
-		{
-			found = true;
-			break;
-		}
-	}
-	if( found )
-	{
-		mDomainList.DeleteItem( i );
-	}
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnServiceAdd
-//===========================================================================================================================
-
-LONG	ChooserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam )
-{
-	ServiceEventInfo *						p;
-	std::auto_ptr < ServiceEventInfo >		pAutoPtr;
-	
-	UNUSED_ALWAYS( inWParam );
-	
-	assert( inLParam );
-	p = reinterpret_cast <ServiceEventInfo *> ( inLParam );
-	pAutoPtr.reset( p );
-	
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnServiceRemove
-//===========================================================================================================================
-
-LONG	ChooserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam )
-{
-	ServiceEventInfo *						p;
-	std::auto_ptr < ServiceEventInfo >		pAutoPtr;
-	bool									found;
-	int										n;
-	int										i;
-	
-	UNUSED_ALWAYS( inWParam );
-	
-	assert( inLParam );
-	p = reinterpret_cast <ServiceEventInfo *> ( inLParam );
-	pAutoPtr.reset( p );
-	
-	// Search to see if we know about this service instance. If so, remove it from the list.
-	
-	found = false;
-	n = (int) mServiceInstances.size();
-	for( i = 0; i < n; ++i )
-	{
-		ServiceInstanceInfo *		q;
-		
-		// If the name, type, domain, and interface match, treat it as the same service instance.
-		
-		q = &mServiceInstances[ i ];
-		if( ( p->name 	== q->name ) 	&& 
-			( p->type 	== q->type ) 	&& 
-			( p->domain	== q->domain ) )
-		{
-			found = true;
-			break;
-		}
-	}
-	if( found )
-	{
-		mChooserList.DeleteItem( i );
-		assert( i < (int) mServiceInstances.size() );
-		mServiceInstances.erase( mServiceInstances.begin() + i );
-	}
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnResolve
-//===========================================================================================================================
-
-LONG	ChooserDialog::OnResolve( WPARAM inWParam, LPARAM inLParam )
-{
-	ServiceInstanceInfo *						p;
-	std::auto_ptr < ServiceInstanceInfo >		pAutoPtr;
-	int											selectedType;
-	int											n;
-	int											i;
-	bool										found;
-	
-	UNUSED_ALWAYS( inWParam );
-	
-	assert( inLParam );
-	p = reinterpret_cast <ServiceInstanceInfo *> ( inLParam );
-	pAutoPtr.reset( p );
-	
-	// Make sure it is for an item of the correct type. This handles any resolves that may have been queued up.
-	
-	selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED );
-	assert( selectedType >= 0 );
-	if( selectedType >= 0 )
-	{
-		assert( selectedType <= (int) mServiceTypes.size() );
-		if( p->type != mServiceTypes[ selectedType ].serviceType )
-		{
-			goto exit;
-		}
-	}
-	
-	// Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list.
-	
-	found = false;
-	n = (int) mServiceInstances.size();
-	for( i = 0; i < n; ++i )
-	{
-		ServiceInstanceInfo *		q;
-		
-		// If the name, type, domain, and interface matches, treat it as the same service instance.
-				
-		q = &mServiceInstances[ i ];
-		if( ( p->name 	== q->name ) 	&& 
-			( p->type 	== q->type ) 	&& 
-			( p->domain	== q->domain ) 	&& 
-			( p->ifIP 	== q->ifIP ) )
-		{
-			found = true;
-			break;
-		}
-	}
-	if( found )
-	{
-		mServiceInstances[ i ] = *p;
-	}
-	else
-	{
-		CString		s;
-		
-		mServiceInstances.push_back( *p );
-		UTF8StringToStringObject( p->name.c_str(), s );
-		mChooserList.InsertItem( n, s );
-		
-		UTF8StringToStringObject( p->ip.c_str(), s );
-		mChooserList.SetItemText( n, 1, s );
-		
-		// If this is the only item, select it.
-		
-		if( n == 0 )
-		{
-			mChooserList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
-		}
-	}
-	UpdateInfoDisplay();
-
-exit:
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	StartBrowsing
-//===========================================================================================================================
-
-void	ChooserDialog::StartBrowsing( const char *inType, const char *inDomain )
-{
-	DNSStatus		err;
-	
-	assert( mServiceInstances.empty() );
-	assert( mChooserList.GetItemCount() == 0 );
-	assert( !mIsServiceBrowsing );
-	
-	mChooserList.DeleteAllItems();
-	mServiceInstances.clear();
-	
-	mIsServiceBrowsing = true;
-	err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, inType, inDomain );
-	assert( err == kDNSNoErr );
-}
-
-//===========================================================================================================================
-//	StopBrowsing
-//===========================================================================================================================
-
-void	ChooserDialog::StopBrowsing( void )
-{
-	// If searching, stop.
-	
-	if( mIsServiceBrowsing )
-	{
-		DNSStatus		err;
-		
-		mIsServiceBrowsing = false;
-		err = DNSBrowserStopServiceSearch( mBrowser, 0 );
-		assert( err == kDNSNoErr );
-	}
-	
-	// Remove all service instances.
-	
-	mChooserList.DeleteAllItems();
-	assert( mChooserList.GetItemCount() == 0 );
-	mServiceInstances.clear();
-	assert( mServiceInstances.empty() );
-	UpdateInfoDisplay();
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	BrowserCallBack
-//===========================================================================================================================
-
-static void
-	BrowserCallBack( 
-		void *					inContext, 
-		DNSBrowserRef			inRef, 
-		DNSStatus				inStatusCode,
-		const DNSBrowserEvent *	inEvent )
-{
-	ChooserDialog *		dialog;
-	UINT 				message;
-	BOOL				posted;
-	
-	UNUSED_ALWAYS( inStatusCode );
-	UNUSED_ALWAYS( inRef );
-	
-	// Check parameters.
-	
-	assert( inContext );
-	dialog = reinterpret_cast <ChooserDialog *> ( inContext );
-	
-	try
-	{
-		switch( inEvent->type )
-		{
-			case kDNSBrowserEventTypeRelease:
-				break;
-			
-			// Domains
-			
-			case kDNSBrowserEventTypeAddDomain:
-			case kDNSBrowserEventTypeAddDefaultDomain:
-			case kDNSBrowserEventTypeRemoveDomain:
-			{
-				DomainEventInfo *						domain;
-				std::auto_ptr < DomainEventInfo >		domainAutoPtr;
-				
-				domain = new DomainEventInfo;
-				domainAutoPtr.reset( domain );
-				
-				domain->eventType 	= inEvent->type;
-				domain->domain 		= inEvent->data.addDomain.domain;
-				domain->ifIP		= inEvent->data.addDomain.interfaceIP;
-				
-				message = ( inEvent->type == kDNSBrowserEventTypeRemoveDomain ) ? WM_USER_DOMAIN_REMOVE : WM_USER_DOMAIN_ADD;
-				posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) domain );
-				assert( posted );
-				if( posted )
-				{
-					domainAutoPtr.release();
-				}
-				break;
-			}
-			
-			// Services
-			
-			case kDNSBrowserEventTypeAddService:
-			case kDNSBrowserEventTypeRemoveService:
-			{
-				ServiceEventInfo *						service;
-				std::auto_ptr < ServiceEventInfo >		serviceAutoPtr;
-				
-				service = new ServiceEventInfo;
-				serviceAutoPtr.reset( service );
-				
-				service->eventType 	= inEvent->type;
-				service->name 		= inEvent->data.addService.name;
-				service->type 		= inEvent->data.addService.type;
-				service->domain		= inEvent->data.addService.domain;
-				service->ifIP		= inEvent->data.addService.interfaceIP;
-				
-				message = ( inEvent->type == kDNSBrowserEventTypeAddService ) ? WM_USER_SERVICE_ADD : WM_USER_SERVICE_REMOVE;
-				posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) service );
-				assert( posted );
-				if( posted )
-				{
-					serviceAutoPtr.release();
-				}
-				break;
-			}
-			
-			// Resolves
-			
-			case kDNSBrowserEventTypeResolved:
-				if( inEvent->data.resolved->address.addressType == kDNSNetworkAddressTypeIPv4  )
-				{
-					ServiceInstanceInfo *						serviceInstance;
-					std::auto_ptr < ServiceInstanceInfo >		serviceInstanceAutoPtr;
-					char										s[ 32 ];
-					
-					serviceInstance = new ServiceInstanceInfo;
-					serviceInstanceAutoPtr.reset( serviceInstance );
-					
-					serviceInstance->name 		= inEvent->data.resolved->name;
-					serviceInstance->type 		= inEvent->data.resolved->type;
-					serviceInstance->domain		= inEvent->data.resolved->domain;
-					serviceInstance->ip			= DNSNetworkAddressToString( &inEvent->data.resolved->address, sizeof( s ), s );
-					serviceInstance->ifIP		= DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, sizeof( s ), s );
-					serviceInstance->text 		= inEvent->data.resolved->textRecord;
-					serviceInstance->hostName	= inEvent->data.resolved->hostName;
-
-					posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_RESOLVE, 0, (LPARAM) serviceInstance );
-					assert( posted );
-					if( posted )
-					{
-						serviceInstanceAutoPtr.release();
-					}
-				}
-				break;
-			
-			default:
-				break;
-		}
-	}
-	catch( ... )
-	{
-		// Don't let exceptions escape.
-	}
-}
-
-//===========================================================================================================================
-//	DNSNetworkAddressToString
-//
-//	Note: Currently only supports IPv4 network addresses.
-//===========================================================================================================================
-
-static char *	DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, size_t inLen, char *outString )
-{
-	const DNSUInt8 *		p;
-	DNSUInt16				port;
-	
-	p = inAddr->u.ipv4.addr.v8;
-	port = ntohs( inAddr->u.ipv4.port.v16 );
-	if( port != kDNSPortInvalid )
-	{
-		snprintf( outString, inLen, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port );
-	}
-	else
-	{
-		snprintf( outString, inLen, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
-	}
-	return( outString );
-}
-
-//===========================================================================================================================
-//	UTF8StringToStringObject
-//===========================================================================================================================
-
-static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject )
-{
-	DWORD		err;
-	int			n;
-	BSTR		unicode;
-	
-	unicode = NULL;
-	
-	n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 );
-	if( n > 0 )
-	{
-		unicode = (BSTR) malloc( (size_t)( n * sizeof( wchar_t ) ) );
-		if( !unicode )
-		{
-			err = ERROR_INSUFFICIENT_BUFFER;
-			goto exit;
-		}
-
-		n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n );
-		try
-		{
-			inObject = unicode;
-		}
-		catch( ... )
-		{
-			err = ERROR_NO_UNICODE_TRANSLATION;
-			goto exit;
-		}
-	}
-	else
-	{
-		inObject = "";
-	}
-	err = 0;
-	
-exit:
-	if( unicode )
-	{
-		free( unicode );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	StringObjectToUTF8String
-//===========================================================================================================================
-
-static DWORD	StringObjectToUTF8String( CString &inObject, std::string &outUTF8 )
-{
-	DWORD		err;
-	BSTR		unicode;
-	int			nUnicode;
-	int			n;
-	char *		utf8;
-	
-	unicode = NULL;
-	utf8	= NULL;
-	
-	nUnicode = inObject.GetLength();
-	if( nUnicode > 0 )
-	{
-		unicode = inObject.AllocSysString();
-		n = WideCharToMultiByte( CP_UTF8, 0, unicode, nUnicode, NULL, 0, NULL, NULL );
-		assert( n > 0 );
-		
-		utf8 = (char *) malloc( (size_t) n );
-		assert( utf8 );
-		if( !utf8 ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; }
-		
-		n = WideCharToMultiByte( CP_UTF8, 0, unicode, nUnicode, utf8, n, NULL, NULL );
-		assert( n > 0 );
-		
-		try
-		{
-			outUTF8.assign( utf8, n );
-		}
-		catch( ... )
-		{
-			err = ERROR_NO_UNICODE_TRANSLATION;
-			goto exit;
-		}
-	}
-	else
-	{
-		outUTF8.clear();
-	}
-	err = 0;
-	
-exit:
-	if( unicode )
-	{
-		SysFreeString( unicode );
-	}
-	if( utf8 )
-	{
-		free( utf8 );
-	}
-	return( err );
-}
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.h b/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.h
deleted file mode 100644
index 41fd827..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_)
-#define AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include	<string>
-#include	<vector>
-
-#include	"afxcmn.h"
-
-#include	"Resource.h"
-
-#include	"DNSServices.h"
-
-//===========================================================================================================================
-//	Structures
-//===========================================================================================================================
-
-struct	ServiceInstanceInfo
-{
-	std::string		name;
-	std::string		type;
-	std::string		domain;
-	std::string		ip;
-	std::string		text;
-	std::string		ifIP;
-	std::string		hostName;
-};
-
-struct	ServiceTypeInfo
-{
-	std::string		serviceType;
-	std::string		description;
-	std::string		urlScheme;
-};
-
-//===========================================================================================================================
-//	ChooserDialog
-//===========================================================================================================================
-
-class	ChooserDialog : public CDialog
-{
-	public:
-
-		ChooserDialog(CWnd* pParent = NULL);
-		virtual	~ChooserDialog( void );
-		
-		//{{AFX_DATA(ChooserDialog)
-		enum { IDD = IDD_CHOOSER_DIALOG };
-		CListCtrl mServiceList;
-		CListCtrl mDomainList;
-		CListCtrl mChooserList;
-		//}}AFX_DATA
-
-		// ClassWizard generated virtual function overrides
-		//{{AFX_VIRTUAL(ChooserDialog)
-		public:
-		virtual BOOL PreTranslateMessage(MSG* pMsg);
-		protected:
-		virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-		virtual void PostNcDestroy();
-		//}}AFX_VIRTUAL
-
-	protected:
-		
-		typedef std::vector < ServiceInstanceInfo >		ServiceInstanceVector;
-		typedef std::vector < ServiceTypeInfo >			ServiceTypeVector;
-		
-		HACCEL						mMenuAcceleratorTable;
-		DNSBrowserRef				mBrowser;
-		BOOL						mIsServiceBrowsing;
-		ServiceInstanceVector		mServiceInstances;
-		ServiceTypeVector			mServiceTypes;
-		
-	public:
-
-		void	PopulateServicesList( void );
-		void	UpdateInfoDisplay( void );
-		
-		void	StartBrowsing( const char *inType, const char *inDomain );
-		void	StopBrowsing( void );
-
-	protected:
-
-		//{{AFX_MSG(ChooserDialog)
-		virtual BOOL OnInitDialog();
-		afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
-		afx_msg void OnDomainListChanged(NMHDR* pNMHDR, LRESULT* pResult);
-		afx_msg void OnServiceListChanged(NMHDR* pNMHDR, LRESULT* pResult);
-		afx_msg void OnChooserListChanged(NMHDR* pNMHDR, LRESULT* pResult);
-		afx_msg void OnChooserListDoubleClick(NMHDR* pNMHDR, LRESULT* pResult);
-		afx_msg void OnAbout();
-		afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
-		afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
-		afx_msg void OnFileClose();
-		virtual void OnCancel();
-		afx_msg void OnExit();
-		afx_msg void OnClose();
-		afx_msg void OnNcDestroy();
-		//}}AFX_MSG
-		afx_msg LONG OnDomainAdd( WPARAM inWParam, LPARAM inLParam );
-		afx_msg LONG OnDomainRemove( WPARAM inWParam, LPARAM inLParam );
-		afx_msg LONG OnServiceAdd( WPARAM inWParam, LPARAM inLParam );
-		afx_msg LONG OnServiceRemove( WPARAM inWParam, LPARAM inLParam );
-		afx_msg LONG OnResolve( WPARAM inWParam, LPARAM inLParam );
-		DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.cpp
deleted file mode 100644
index b9a9ec9..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	<assert.h>
-#include	<stdlib.h>
-
-#include	"stdafx.h"
-
-#include	"LoginDialog.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP( LoginDialog, CDialog )
-END_MESSAGE_MAP()
-
-//===========================================================================================================================
-//	LoginDialog
-//===========================================================================================================================
-
-LoginDialog::LoginDialog( CWnd *inParent )
-	: CDialog( LoginDialog::IDD, inParent )
-{
-	//
-}
-
-//===========================================================================================================================
-//	OnInitDialog
-//===========================================================================================================================
-
-BOOL	LoginDialog::OnInitDialog( void )
-{
-	CDialog::OnInitDialog();
-	return( TRUE );
-}
-
-//===========================================================================================================================
-//	DoDataExchange
-//===========================================================================================================================
-
-void	LoginDialog::DoDataExchange( CDataExchange *inDX )
-{
-	CDialog::DoDataExchange( inDX );
-}
-
-//===========================================================================================================================
-//	OnOK
-//===========================================================================================================================
-
-void	LoginDialog::OnOK( void )
-{
-	const CWnd *		control;
-		
-	// Username
-	
-	control = GetDlgItem( IDC_LOGIN_USERNAME_TEXT );
-	assert( control );
-	if( control )
-	{
-		control->GetWindowText( mUsername );
-	}
-	
-	// Password
-	
-	control = GetDlgItem( IDC_LOGIN_PASSWORD_TEXT );
-	assert( control );
-	if( control )
-	{
-		control->GetWindowText( mPassword );
-	}
-	
-	CDialog::OnOK();
-}
-
-//===========================================================================================================================
-//	GetLogin
-//===========================================================================================================================
-
-BOOL	LoginDialog::GetLogin( CString &outUsername, CString &outPassword )
-{
-	if( DoModal() == IDOK )
-	{
-		outUsername = mUsername;
-		outPassword = mPassword;
-		return( TRUE );
-	}
-	return( FALSE );
-}
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.h b/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.h
deleted file mode 100644
index e53beb6..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/LoginDialog.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef	__LOGIN_DIALOG__
-#define	__LOGIN_DIALOG__
-
-#pragma once
-
-#include	"Resource.h"
-
-//===========================================================================================================================
-//	LoginDialog
-//===========================================================================================================================
-
-class	LoginDialog : public CDialog
-{
-	protected:
-	
-		CString		mUsername;
-		CString		mPassword;
-		
-	public:
-		
-		enum { IDD = IDD_LOGIN };
-		
-		LoginDialog( CWnd *inParent = NULL );
-		
-		virtual BOOL	GetLogin( CString &outUsername, CString &outPassword );
-	
-	protected:
-
-		virtual BOOL	OnInitDialog( void );
-		virtual void	DoDataExchange( CDataExchange *inDX );
-		virtual void	OnOK( void );
-		
-		DECLARE_MESSAGE_MAP()
-};
-
-#endif	// __LOGIN_DIALOG__
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.cpp b/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.cpp
deleted file mode 100644
index ae2ca2e..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	"stdafx.h"
diff --git a/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.h b/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.h
deleted file mode 100644
index c62bd3e..0000000
--- a/mDNSWindows/DNSServiceBrowser/Windows/Sources/StdAfx.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_)
-#define AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
-
-#ifndef WINVER				// Allow use of features specific to Windows 95 and Windows NT 4 or later.
-	#define WINVER 0x0400	// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
-#endif
-
-#include	<afxwin.h>		// MFC core and standard components
-#include	<afxext.h>		// MFC extensions
-#include	<afxdtctl.h>	// MFC support for Internet Explorer 4 Common Controls
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-	#include	<afxcmn.h>	// MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
-
-#include	<winsock2.h>
-
-#include	<stdlib.h>
-
-#include	"DNSServices.h"
-
-#include	"Application.h"
-
-#include	"ChooserDialog.h"
-
-#endif // !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/newres.h b/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/newres.h
deleted file mode 100644
index 31c3a43..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/newres.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __NEWRES_H__
-#define __NEWRES_H__
-
-#define  SHMENUBAR RCDATA
-#if !(defined(_WIN32_WCE_PSPC) && (_WIN32_WCE >= 300))
-	#undef HDS_HORZ  
-	#undef HDS_BUTTONS 
-	#undef HDS_HIDDEN 
-
-	#include <commctrl.h>
-	// for MenuBar
-	#define I_IMAGENONE		(-2)
-	#define NOMENU			0xFFFF
-	#define IDS_SHNEW		1
-	#define IDM_SHAREDNEW        10
-	#define IDM_SHAREDNEWDEFAULT 11
-
-	// for Tab Control
-	#define TCS_SCROLLOPPOSITE      0x0001   // assumes multiline tab
-	#define TCS_BOTTOM              0x0002
-	#define TCS_RIGHT               0x0002
-	#define TCS_VERTICAL            0x0080
-	#define TCS_MULTISELECT         0x0004  // allow multi-select in button mode
-	#define TCS_FLATBUTTONS         0x0008	
-#endif //_WIN32_WCE_PSPC
-
-
-#endif //__NEWRES_H__
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/resource.h b/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/resource.h
deleted file mode 100644
index 0337c56..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Resources/resource.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft eMbedded Visual C++ generated include file.
-// Used by Application.rc
-//
-#define IDD_APPLICATION_DIALOG          102
-#define IDP_SOCKETS_INIT_FAILED         103
-#define IDS_BROWSER_LIST_COLUMN_NAME    104
-#define IDR_MAINFRAME                   128
-#define IDC_BROWSE_LIST                 1000
-#define IDC_IP_TEXT                     1003
-#define IDC_TXT_TEXT                    1004
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        129
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1005
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.cpp b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.cpp
deleted file mode 100644
index 931cd95..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	"stdafx.h"
-
-#include	"DNSServices.h"
-
-#include	"BrowserDialog.h"
-
-#include	"Application.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(Application, CWinApp)
-	//{{AFX_MSG_MAP(Application)
-		// NOTE - the ClassWizard will add and remove mapping macros here.
-		//    DO NOT EDIT what you see in these blocks of generated code!
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-Application		gApp;
-
-//===========================================================================================================================
-//	Application
-//===========================================================================================================================
-
-Application::Application()
-	: CWinApp()
-{
-	//
-}
-
-//===========================================================================================================================
-//	InitInstance
-//===========================================================================================================================
-
-BOOL Application::InitInstance()
-{
-	DNSStatus			err;
-	BrowserDialog		dialog;
-	BOOL				dnsInitialized;
-	
-	dnsInitialized = FALSE;
-	
-	err = DNSServicesInitialize( kDNSFlagAdvertise, 0 );
-	if( err )
-	{
-		AfxMessageBox( IDP_SOCKETS_INIT_FAILED );
-		goto exit;
-	}
-	dnsInitialized = TRUE;
-
-	// Display the main browser dialog.
-	
-	m_pMainWnd = &dialog;
-	dialog.DoModal();
-
-	// Dialog has been closed. Return false to exit the app and not start the app's message pump.
-
-exit:
-	if( dnsInitialized )
-	{
-		DNSServicesFinalize();
-	}
-	return( FALSE );
-}
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.h b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.h
deleted file mode 100644
index cfd5429..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/Application.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_)
-#define AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#ifndef __AFXWIN_H__
-	#error include 'stdafx.h' before including this file for PCH
-#endif
-
-#include	"Resource.h"
-
-//===========================================================================================================================
-//	Application
-//===========================================================================================================================
-
-class	Application : public CWinApp
-{
-	public:
-		
-		Application();
-
-		// ClassWizard generated virtual function overrides
-		//{{AFX_VIRTUAL(Application)
-		public:
-		virtual BOOL InitInstance();
-		//}}AFX_VIRTUAL
-
-		//{{AFX_MSG(Application)
-			// NOTE - the ClassWizard will add and remove member functions here.
-			//    DO NOT EDIT what you see in these blocks of generated code !
-		//}}AFX_MSG
-		DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
deleted file mode 100644
index 67b9cb8..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
+++ /dev/null
@@ -1,394 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	"stdafx.h"
-
-#include	"Application.h"
-
-#include	"DNSServices.h"
-
-#include	"BrowserDialog.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#define	WM_USER_SERVICE_ADD			( WM_USER + 0x100 )
-#define	WM_USER_SERVICE_REMOVE		( WM_USER + 0x101 )
-
-//===========================================================================================================================
-//	Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(BrowserDialog, CDialog)
-	//{{AFX_MSG_MAP(BrowserDialog)
-	ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnBrowserListDoubleClick)
-	ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd )
-	ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove )
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject );
-
-//===========================================================================================================================
-//	BrowserDialog
-//===========================================================================================================================
-
-BrowserDialog::BrowserDialog( CWnd *inParent )
-	: CDialog( BrowserDialog::IDD, inParent )
-{
-	//{{AFX_DATA_INIT(BrowserDialog)
-		// Note: the ClassWizard will add member initialization here
-	//}}AFX_DATA_INIT
-	
-	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32.
-	
-	mIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME );
-	ASSERT( mIcon );
-}
-
-//===========================================================================================================================
-//	DoDataExchange
-//===========================================================================================================================
-
-void	BrowserDialog::DoDataExchange( CDataExchange *pDX )
-{
-	CDialog::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(BrowserDialog)
-	DDX_Control(pDX, IDC_BROWSE_LIST, mBrowserList);
-	//}}AFX_DATA_MAP
-}
-
-//===========================================================================================================================
-//	OnInitDialog
-//===========================================================================================================================
-
-BOOL	BrowserDialog::OnInitDialog()
-{
-	CString		s;
-	
-	CDialog::OnInitDialog();
-
-	// Set the icon for this dialog. The framework does this automatically when the application's main window is not a dialog.
-	
-	SetIcon( mIcon, TRUE );		// Set big icon
-	SetIcon( mIcon, FALSE );	// Set small icon
-	
-	CenterWindow( GetDesktopWindow() );
-
-	// Set up the list.
-	
-	CRect		rect;
-	
-	s.LoadString( IDS_BROWSER_LIST_COLUMN_NAME );
-	mBrowserList.GetWindowRect( rect );
-	mBrowserList.InsertColumn( 0, s, LVCFMT_LEFT, rect.Width() - 8 );
-	
-	// Start browsing for services.
-
-	DNSStatus		err;
-
-	err = DNSBrowserCreate( 0, OnBrowserCallBack, this, &mBrowser );
-	if( err )
-	{
-		AfxMessageBox( IDP_SOCKETS_INIT_FAILED );
-		goto exit;
-	}
-	
-	err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, "_http._tcp", NULL );
-	if( err )
-	{
-		AfxMessageBox( IDP_SOCKETS_INIT_FAILED );
-		goto exit;
-	}
-	
-exit:
-	return( TRUE );
-}
-
-
-//===========================================================================================================================
-//	OnBrowserListDoubleClick
-//===========================================================================================================================
-
-void	BrowserDialog::OnBrowserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult ) 
-{
-	int		selectedItem;
-
-	(void) pNMHDR;	// Unused
-
-	selectedItem = mBrowserList.GetNextItem( -1, LVNI_SELECTED );
-	if( selectedItem >= 0 )
-	{
-		BrowserEntry *		entry;
-		CString				temp;
-		CString				url;
-		
-		// Build the URL from the IP and optional TXT record.
-
-		entry = &mBrowserEntries[ selectedItem ];
-		url += "http://" + entry->ip;
-		temp = entry->text;
-		if( temp.Find( TEXT( "path=" ) ) == 0 )
-		{
-			temp.Delete( 0, 5 );
-		}
-		if( temp.Find( '/' ) != 0 )
-		{
-			url += '/';
-		}
-		url += temp;
-
-		// Let the system open the URL in the correct app.
-		
-		SHELLEXECUTEINFO		info;
-
-		info.cbSize			= sizeof( info );
-		info.fMask 			= 0;
-		info.hwnd 			= NULL;
-		info.lpVerb 		= NULL;
-		info.lpFile 		= url;
-		info.lpParameters 	= NULL;
-		info.lpDirectory 	= NULL;
-		info.nShow 			= SW_SHOWNORMAL;
-		info.hInstApp 		= NULL;
-
-		ShellExecuteEx( &info );
-	}
-	*pResult = 0;
-}
-
-//===========================================================================================================================
-//	OnBrowserCallBack [static]
-//===========================================================================================================================
-
-void
-	BrowserDialog::OnBrowserCallBack( 
-		void *					inContext, 
-		DNSBrowserRef			inRef, 
-		DNSStatus				inStatusCode,
-		const DNSBrowserEvent *	inEvent )
-{
-	BrowserDialog *		dialog;
-	BrowserEntry *		entry;
-	BOOL				posted;
-	
-	DNS_UNUSED( inStatusCode );
-	dialog = reinterpret_cast < BrowserDialog * > ( inContext );
-	ASSERT( dialog );
-	
-	switch( inEvent->type )
-	{
-		case kDNSBrowserEventTypeResolved:
-			if( inEvent->data.resolved->address.addressType == kDNSNetworkAddressTypeIPv4  )
-			{
-				char		ip[ 64 ];
-
-				snprintf( ip, sizeof( ip ), "%u.%u.%u.%u:%u", 
-					inEvent->data.resolved->address.u.ipv4.addr.v8[ 0 ], 
-					inEvent->data.resolved->address.u.ipv4.addr.v8[ 1 ], 
-					inEvent->data.resolved->address.u.ipv4.addr.v8[ 2 ], 
-					inEvent->data.resolved->address.u.ipv4.addr.v8[ 3 ], 
-					( inEvent->data.resolved->address.u.ipv4.port.v8[ 0 ] << 8 ) | 
-					  inEvent->data.resolved->address.u.ipv4.port.v8[ 1 ] );
-				
-				entry = new BrowserEntry;
-				ASSERT( entry );
-				if( entry )
-				{
-					UTF8StringToStringObject( inEvent->data.resolved->name, entry->name );
-					UTF8StringToStringObject( ip, entry->ip );
-					UTF8StringToStringObject( inEvent->data.resolved->textRecord, entry->text );
-					
-					posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_SERVICE_ADD, 0, (LPARAM) entry );
-					ASSERT( posted );
-					if( !posted )
-					{
-						delete entry;
-					}
-				}
-			}
-			break;
-
-		case kDNSBrowserEventTypeRemoveService:
-			entry = new BrowserEntry;
-			ASSERT( entry );
-			if( entry )
-			{
-				UTF8StringToStringObject( inEvent->data.removeService.name, entry->name );
-				
-				posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_SERVICE_REMOVE, 0, (LPARAM) entry );
-				ASSERT( posted );
-				if( !posted )
-				{
-					delete entry;
-				}
-			}
-			break;
-		
-		default:
-			break;
-	}
-}
-
-//===========================================================================================================================
-//	BrowserAddService
-//===========================================================================================================================
-
-LONG	BrowserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam )
-{
-	BrowserEntry *		entry;
-	INT_PTR				lo;
-	INT_PTR				hi;
-	INT_PTR				mid;
-	int					result;
-	
-	(void) inWParam;	// Unused
-	
-	entry = reinterpret_cast < BrowserEntry * > ( inLParam );
-	ASSERT( entry );
-	
-	result 	= -1;
-	mid		= 0;
-	lo 		= 0;
-	hi 		= mBrowserEntries.GetSize() - 1;
-	while( lo <= hi )
-	{
-		mid = ( lo + hi ) / 2;
-		result = entry->name.CompareNoCase( mBrowserEntries[ mid ].name );
-		if( result == 0 )
-		{
-			break;
-		}
-		else if( result < 0 )
-		{
-			hi = mid - 1;
-		}
-		else
-		{
-			lo = mid + 1;
-		}
-	}
-	if( result == 0 )
-	{
-		mBrowserEntries[ mid ].ip	= entry->ip;
-		mBrowserEntries[ mid ].text	= entry->text;
-	}
-	else
-	{
-		if( result > 0 )
-		{
-			mid += 1;
-		}
-		mBrowserEntries.InsertAt( mid, *entry );
-		mBrowserList.InsertItem( mid, entry->name );
-	}
-	delete entry;
-	return( 0 );
-}
-
-//===========================================================================================================================
-//	OnServiceRemove
-//===========================================================================================================================
-
-LONG	BrowserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam )
-{
-	BrowserEntry *		entry;
-	INT_PTR				hi;
-	INT_PTR				lo;
-	INT_PTR				mid;
-	int					result;
-
-	(void) inWParam;	// Unused
-	
-	entry = reinterpret_cast < BrowserEntry * > ( inLParam );
-	ASSERT( entry );
-	
-	result 	= -1;
-	mid		= 0;
-	lo 		= 0;
-	hi 		= mBrowserEntries.GetSize() - 1;
-	while( lo <= hi )
-	{
-		mid = ( lo + hi ) / 2;
-		result = entry->name.CompareNoCase( mBrowserEntries[ mid ].name );
-		if( result == 0 )
-		{
-			break;
-		}
-		else if( result < 0 )
-		{
-			hi = mid - 1;
-		}
-		else
-		{
-			lo = mid + 1;
-		}
-	}
-	if( result == 0 )
-	{
-		mBrowserList.DeleteItem( mid );
-		mBrowserEntries.RemoveAt( mid );
-	}
-	delete entry;
-	return( 0 );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	UTF8StringToStringObject
-//===========================================================================================================================
-
-static DWORD	UTF8StringToStringObject( const char *inUTF8, CString &inObject )
-{
-	DWORD			err;
-	int				n;
-	wchar_t *		unicode;
-	
-	unicode = NULL;
-	
-	n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 );
-	if( n > 0 )
-	{
-		unicode = (wchar_t *) malloc( (size_t)( n * sizeof( wchar_t ) ) );
-		if( !unicode ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; };
-		
-		n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n );
-		inObject = unicode;
-	}
-	else
-	{
-		inObject = "";
-	}
-	err = 0;
-	
-exit:
-	if( unicode )
-	{
-		free( unicode );
-	}
-	return( err );
-}
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h
deleted file mode 100644
index a27df91..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_)
-#define AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#include	"afxtempl.h"
-#include	"Resource.h"
-
-#include	"DNSServices.h"
-
-//===========================================================================================================================
-//	BrowserDialog
-//===========================================================================================================================
-
-class	BrowserDialog : public CDialog
-{
-	public:
-		
-		BrowserDialog( CWnd *inParent = NULL );
-		
-		//{{AFX_DATA(BrowserDialog)
-		enum { IDD = IDD_APPLICATION_DIALOG };
-		CListCtrl	mBrowserList;
-		//}}AFX_DATA
-
-		// ClassWizard generated virtual function overrides
-		//{{AFX_VIRTUAL(BrowserDialog)
-		protected:
-		virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
-		//}}AFX_VIRTUAL
-		
-		static void
-			OnBrowserCallBack( 
-				void *					inContext, 
-				DNSBrowserRef			inRef, 
-				DNSStatus				inStatusCode,  
-				const DNSBrowserEvent *	inEvent );
-		
-	protected:
-		
-		struct	BrowserEntry
-		{
-			CString		name;
-			CString		ip;
-			CString		text;
-		};
-		
-		HICON										mIcon;
-		DNSBrowserRef								mBrowser;
-		CArray < BrowserEntry, BrowserEntry >		mBrowserEntries;
-		
-		// Generated message map functions
-		//{{AFX_MSG(BrowserDialog)
-		virtual BOOL OnInitDialog();
-		afx_msg void OnBrowserListDoubleClick(NMHDR* pNMHDR, LRESULT* pResult);
-		afx_msg LONG OnServiceAdd( WPARAM inWParam, LPARAM inLParam );
-		afx_msg LONG OnServiceRemove( WPARAM inWParam, LPARAM inLParam );
-		//}}AFX_MSG
-		DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_)
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp
deleted file mode 100644
index ae2ca2e..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include	"stdafx.h"
diff --git a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h b/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h
deleted file mode 100644
index 4b14a0b..0000000
--- a/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#if !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_)
-#define AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-
-
-#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
-
-#include <afxwin.h>         // MFC core and standard components
-#include <afxext.h>         // MFC extensions
-
-#if defined(_AFXDLL)
-#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
-#endif
-
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-#include <afxcmn.h>			// MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
-
-#include <winsock2.h>
-//#include <afxsock.h>		// MFC socket extensions
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_)
diff --git a/mDNSWindows/NSPTool/NSPTool.c b/mDNSWindows/NSPTool/NSPTool.c
deleted file mode 100644
index 0be174d..0000000
--- a/mDNSWindows/NSPTool/NSPTool.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#include	<stdio.h>
-#include	<stdlib.h>
-
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-
-#include	<guiddef.h>
-#include	<ws2spi.h>
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-int  					main( int argc, char *argv[] );
-DEBUG_LOCAL void		Usage( void );
-DEBUG_LOCAL int			ProcessArgs( int argc, char *argv[] );
-DEBUG_LOCAL OSStatus	InstallNSP( const char *inName, const char *inGUID, const char *inPath );
-DEBUG_LOCAL OSStatus	RemoveNSP( const char *inGUID );
-DEBUG_LOCAL OSStatus	EnableNSP( const char *inGUID, BOOL inEnable );
-DEBUG_LOCAL OSStatus	ListNameSpaces( void );
-DEBUG_LOCAL OSStatus	ReorderNameSpaces( void );
-
-DEBUG_LOCAL WCHAR *		CharToWCharString( const char *inCharString, WCHAR *outWCharString );
-DEBUG_LOCAL char *		GUIDtoString( const GUID *inGUID, size_t inLen, char *outString );
-DEBUG_LOCAL OSStatus	StringToGUID( const char *inCharString, GUID *outGUID );
-
-DEBUG_LOCAL BOOL gToolQuietMode = FALSE;
-
-//===========================================================================================================================
-//	main
-//===========================================================================================================================
-
-int main( int argc, char *argv[] )
-{
-	OSStatus		err;
-	
-	debug_initialize( kDebugOutputTypeMetaConsole );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
-	
-	err = ProcessArgs( argc, argv );
-	return( (int) err );
-}
-
-//===========================================================================================================================
-//	Usage
-//===========================================================================================================================
-
-DEBUG_LOCAL void	Usage( void )
-{
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "NSP Tool 1.0d1\n" );
-	fprintf( stderr, "  Name Space Provider Tool\n" );
-	fprintf( stderr, "\n" );
-	
-	fprintf( stderr, "  -install <name> <guid> <path>   - Installs a Name Space Provider\n" );
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "      <name> Name of the NSP\n" );
-	fprintf( stderr, "      <guid> GUID of the NSP\n" );
-	fprintf( stderr, "      <path> Path to the NSP file\n" );
-	fprintf( stderr, "\n" );
-	
-	fprintf( stderr, "  -remove <guid>                  - Removes a Name Space Provider\n" );
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "      <guid> GUID of the NSP\n" );
-	fprintf( stderr, "\n" );
-	
-	fprintf( stderr, "  -enable/-disable <guid>         - Enables or Disables a Name Space Provider\n" );
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "      <guid> GUID of the NSP\n" );
-	fprintf( stderr, "\n" );
-	
-	fprintf( stderr, "  -list                           - Lists Name Space Providers\n" );	
-	fprintf( stderr, "  -reorder                        - Reorders Name Space Providers\n" );
-	fprintf( stderr, "  -q                              - Enable quiet mode\n" );
-	fprintf( stderr, "  -h[elp]                         - Help\n" );
-	fprintf( stderr, "\n" );
-}
-
-//===========================================================================================================================
-//	ProcessArgs
-//===========================================================================================================================
-
-DEBUG_LOCAL int ProcessArgs( int argc, char* argv[] )
-{	
-	OSStatus			err;
-	int					i;
-	const char *		name;
-	const char *		guid;
-	const char *		path;
-			
-	if( argc <= 1 )
-	{
-		Usage();
-		err = 0;
-		goto exit;
-	}
-	for( i = 1; i < argc; ++i )
-	{
-		if( strcmp( argv[ i ], "-install" ) == 0 )
-		{
-			// Install
-			
-			if( argc <= ( i + 3 ) )
-			{
-				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
-				Usage();
-				err = kParamErr;
-				goto exit;
-			}
-			name = argv[ ++i ];
-			guid = argv[ ++i ];
-			path = argv[ ++i ];
-			
-			if( *name == '\0' )
-			{
-				name = "DotLocalNSP";
-			}
-			if( *guid == '\0' )
-			{
-				guid = "B600E6E9-553B-4a19-8696-335E5C896153";
-			}
-			
-			err = InstallNSP( name, guid, path );
-			require_noerr( err, exit );
-		}
-		else if( strcmp( argv[ i ], "-remove" ) == 0 )
-		{
-			// Remove
-			
-			if( argc <= ( i + 1 ) )
-			{
-				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
-				Usage();
-				err = kParamErr;
-				goto exit;
-			}
-			guid = argv[ ++i ];
-			if( *guid == '\0' )
-			{
-				guid = "B600E6E9-553B-4a19-8696-335E5C896153";
-			}
-			
-			err = RemoveNSP( guid );
-			require_noerr( err, exit );
-		}
-		else if( ( strcmp( argv[ i ], "-enable" )  == 0 ) || 
-				 ( strcmp( argv[ i ], "-disable" ) == 0 ) )
-		{
-			BOOL		enable;
-			
-			// Enable/Disable
-			
-			enable = ( strcmp( argv[ i ], "-enable" ) == 0 );
-			if( argc <= ( i + 1 ) )
-			{
-				fprintf( stderr, "\n### ERROR: missing arguments for %s\n\n", argv[ i ] );
-				Usage();
-				err = kParamErr;
-				goto exit;
-			}
-			guid = argv[ ++i ];
-			
-			err = EnableNSP( guid, enable );
-			require_noerr( err, exit );
-		}
-		else if( strcmp( argv[ i ], "-list" ) == 0 )
-		{
-			// List
-						
-			err = ListNameSpaces();
-			require_noerr( err, exit );
-		}
-		else if( strcmp( argv[ i ], "-reorder" ) == 0 )
-		{
-			// Reorder
-			
-			err = ReorderNameSpaces();
-			require_noerr( err, exit );
-		}
-		else if( strcmp( argv[ i ], "-q" ) == 0 )
-		{
-			gToolQuietMode = TRUE;
-		}
-		else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || 
-				 ( strcmp( argv[ i ], "-h" ) == 0 ) )
-		{
-			// Help
-			
-			Usage();
-			err = 0;
-			goto exit;
-		}
-		else
-		{
-			fprintf( stderr, "\n### ERROR: unknown argment: \"%s\"\n\n", argv[ i ] );
-			Usage();
-			err = kParamErr;
-			goto exit;
-		}
-	}
-	err = kNoErr;
-	
-exit:
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	InstallNSP
-//===========================================================================================================================
-
-OSStatus	InstallNSP( const char *inName, const char *inGUID, const char *inPath )
-{
-	OSStatus		err;
-	size_t			size;
-	WSADATA			wsd;
-	WCHAR			name[ 256 ];
-	GUID			guid;
-	WCHAR			path[ MAX_PATH ];
-	
-	require_action( inName && ( *inName != '\0' ), exit, err = kParamErr );
-	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
-	require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr );
-	
-	size = strlen( inName );
-	require_action( size < sizeof_array( name ), exit, err = kSizeErr );
-	CharToWCharString( inName, name );
-	
-	err = StringToGUID( inGUID, &guid );
-	require_noerr( err, exit );
-	
-	size = strlen( inPath );
-	require_action( size < sizeof_array( path ), exit, err = kSizeErr );
-	CharToWCharString( inPath, path );
-	
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	WSACleanup();
-	require_noerr( err, exit );
-	
-	if (!gToolQuietMode)
-	{
-		fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath );
-	}
-	
-exit:
-	if( err != kNoErr )
-	{
-		fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	RemoveNSP
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	RemoveNSP( const char *inGUID )
-{
-	OSStatus		err;
-	WSADATA			wsd;
-	GUID			guid;
-	
-	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
-	
-	err = StringToGUID( inGUID, &guid );
-	require_noerr( err, exit );
-	
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	err = WSCUnInstallNameSpace( &guid );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	WSACleanup();
-	require_noerr( err, exit );
-	
-	if (!gToolQuietMode)
-	{
-		fprintf( stderr, "Removed NSP %s\n", inGUID );
-	}
-		
-exit:
-	if( err != kNoErr )
-	{
-		fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	EnableNSP
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	EnableNSP( const char *inGUID, BOOL inEnable )
-{
-	OSStatus		err;
-	WSADATA			wsd;
-	GUID			guid;
-	
-	require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr );
-	
-	err = StringToGUID( inGUID, &guid );
-	require_noerr( err, exit );
-	
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	err = WSCEnableNSProvider( &guid, inEnable );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	WSACleanup();
-	require_noerr( err, exit );
-	
-	if (!gToolQuietMode)
-	{
-		fprintf( stderr, "Removed NSP %s\n", inGUID );
-	}
-		
-exit:
-	if( err != kNoErr )
-	{
-		fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	ListNameSpaces
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	ListNameSpaces( void )
-{
-	OSStatus				err;
-	WSADATA					wsd;
-	bool					started;
-	int						n;
-	int						i;
-	DWORD					size;
-	WSANAMESPACE_INFO *		array;
-	char					s[ 256 ];
-	
-	array 	= NULL;
-	started	= false;
-	
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	started = true;
-	
-	// Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
-	
-	size = 0;
-	n = WSAEnumNameSpaceProviders( &size, NULL );
-	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
-	require_action( err == WSAEFAULT, exit, err = kUnknownErr );
-	
-	array = (WSANAMESPACE_INFO *) malloc( size );
-	require_action( array, exit, err = kNoMemoryErr );
-	
-	n = WSAEnumNameSpaceProviders( &size, array );
-	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	fprintf( stdout, "\n" );
-	for( i = 0; i < n; ++i )
-	{
-		fprintf( stdout, "Name Space %d\n", i + 1 );
-		fprintf( stdout, "    NSProviderId:   %s\n", GUIDtoString( &array[ i ].NSProviderId, sizeof( s ), s ) );
-		fprintf( stdout, "    dwNameSpace:    %d\n", array[ i ].dwNameSpace );
-		fprintf( stdout, "    fActive:        %s\n", array[ i ].fActive ? "YES" : "NO" );
-		fprintf( stdout, "    dwVersion:      %d\n", array[ i ].dwVersion );
-		fprintf( stdout, "    lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier );
-		fprintf( stdout, "\n" );
-	}
-	err = kNoErr;
-	
-exit:
-	if( array )
-	{
-		free( array );
-	}
-	if( started )
-	{
-		WSACleanup();
-	}
-	if( err != kNoErr )
-	{
-		fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	ReorderNameSpaces
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	ReorderNameSpaces( void )
-{
-	OSStatus				err;
-	WSADATA					wsd;
-	bool					started;
-	int						n;
-	int						i;
-	DWORD					size;
-	WSANAMESPACE_INFO *		array;
-	WCHAR					name[ 256 ];
-	WCHAR					path[ MAX_PATH ];
-	
-	array 	= NULL;
-	started	= false;
-		
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	started = true;
-	
-	// Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it.
-	
-	size = 0;
-	n = WSAEnumNameSpaceProviders( &size, NULL );
-	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
-	require_action( err == WSAEFAULT, exit, err = kUnknownErr );
-	
-	array = (WSANAMESPACE_INFO *) malloc( size );
-	require_action( array, exit, err = kNoMemoryErr );
-	
-	n = WSAEnumNameSpaceProviders( &size, array );
-	err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	// Find the "Tcpip" NSP.
-	
-	for( i = 0; i < n; ++i )
-	{
-		if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 )
-		{
-			break;
-		}
-	}
-	require_action( i < n, exit, err = kNotFoundErr );
-	
-	// Uninstall it then re-install it to move it to the end.
-	
-	size = (DWORD) strlen( array[ i ].lpszIdentifier );
-	require_action( size < sizeof_array( name ), exit, err = kSizeErr );
-	CharToWCharString( array[ i ].lpszIdentifier, name );
-	
-	size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" );
-	require_action( size < sizeof_array( path ), exit, err = kSizeErr );
-	CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path );
-	
-	err = WSCUnInstallNameSpace( &array[ i ].NSProviderId );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-		
-	// Success!
-	
-	fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" );	
-	err = kNoErr;
-	
-exit:
-	if( array )
-	{
-		free( array );
-	}
-	if( started )
-	{
-		WSACleanup();
-	}
-	if( err != kNoErr )
-	{
-		fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err );
-	}
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	CharToWCharString
-//===========================================================================================================================
-
-DEBUG_LOCAL WCHAR *	CharToWCharString( const char *inCharString, WCHAR *outWCharString )
-{
-	const char *		src;
-	WCHAR *				dst;
-	char				c;
-	
-	check( inCharString );
-	check( outWCharString );
-	
-	src = inCharString;
-	dst = outWCharString;
-	do
-	{
-		c = *src++;
-		*dst++ = (WCHAR) c;
-	
-	}	while( c != '\0' );
-	
-	return( outWCharString );
-}
-
-//===========================================================================================================================
-//	GUIDtoString
-//===========================================================================================================================
-
-DEBUG_LOCAL char *	GUIDtoString( const GUID *inGUID, size_t inLen, char *outString )
-{
-	check( inGUID );
-	check( outString );
-	
-	_snprintf( outString, inLen, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-		inGUID->Data1, inGUID->Data2, inGUID->Data3, 
-		inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ], 
-		inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] );
-	return( outString );
-}
-
-//===========================================================================================================================
-//	StringToGUID
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	StringToGUID( const char *inCharString, GUID *outGUID )
-{
-	OSStatus			err;
-	int					n;
-	unsigned int		v[ 8 ];
-	
-	check( inCharString );
-	check( outGUID );
-	
-	n = sscanf( inCharString, "%lX-%hX-%hX-%02X%02X-%02X%02X%02X%02X%02X%02X", 
-		&outGUID->Data1, &outGUID->Data2, &outGUID->Data3, 
-		&v[ 0 ], &v[ 1 ], &v[ 2 ], &v[ 3 ], &v[ 4 ], &v[ 5 ], &v[ 6 ], &v[ 7 ] );
-	require_action( n == 11, exit, err = kFormatErr );
-	
-	outGUID->Data4[ 0 ] = (unsigned char) v[ 0 ];
-	outGUID->Data4[ 1 ] = (unsigned char) v[ 1 ];
-	outGUID->Data4[ 2 ] = (unsigned char) v[ 2 ];
-	outGUID->Data4[ 3 ] = (unsigned char) v[ 3 ];
-	outGUID->Data4[ 4 ] = (unsigned char) v[ 4 ];
-	outGUID->Data4[ 5 ] = (unsigned char) v[ 5 ];
-	outGUID->Data4[ 6 ] = (unsigned char) v[ 6 ];
-	outGUID->Data4[ 7 ] = (unsigned char) v[ 7 ];
-	err = kNoErr;
-
-exit:
-	return( err );
-}
diff --git a/mDNSWindows/NSPTool/Prefix.h b/mDNSWindows/NSPTool/Prefix.h
deleted file mode 100644
index 3aa1cee..0000000
--- a/mDNSWindows/NSPTool/Prefix.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __PREFIX__
-#define __PREFIX__
-
-#if( defined( _DEBUG ) )
-	#define	DEBUG				1
-	#define	MDNS_DEBUGMSGS		1
-#else
-	#define	DEBUG				0
-#endif
-
-#endif	// __PREFIX__
diff --git a/mDNSWindows/NSPTool/resource.h b/mDNSWindows/NSPTool/resource.h
deleted file mode 100644
index 78c1d91..0000000
--- a/mDNSWindows/NSPTool/resource.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by NSPTool.rc
-//
-#define IDS_PROJNAME                    100
-#define IDR_WMDMLOGGER                  101
-#define IDS_LOG_SEV_INFO                201
-#define IDS_LOG_SEV_WARN                202
-#define IDS_LOG_SEV_ERROR               203
-#define IDS_LOG_DATETIME                204
-#define IDS_LOG_SRCNAME                 205
-#define IDS_DEF_LOGFILE                 301
-#define IDS_DEF_MAXSIZE                 302
-#define IDS_DEF_SHRINKTOSIZE            303
-#define IDS_DEF_LOGENABLED              304
-#define IDS_MUTEX_TIMEOUT               401
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        201
-#define _APS_NEXT_COMMAND_VALUE         32768
-#define _APS_NEXT_CONTROL_VALUE         201
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/Poll.c b/mDNSWindows/Poll.c
deleted file mode 100644
index 46d2a6d..0000000
--- a/mDNSWindows/Poll.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "Poll.h"
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <process.h>
-#include "GenLinkedList.h"
-#include "DebugServices.h"
-
-
-typedef struct PollSource_struct
-{
-	SOCKET socket;
-	HANDLE handle;
-	void   *context;
-
-	union
-	{
-		mDNSPollSocketCallback socket;
-		mDNSPollEventCallback event;
-	} callback;
-
-	struct Worker_struct		*worker;
-	struct PollSource_struct	*next;
-
-} PollSource;
-
-
-typedef struct Worker_struct
-{
-	HANDLE					thread;		// NULL for main worker
-	unsigned				id;			// 0 for main worker
-
-	HANDLE					start;		// NULL for main worker
-	HANDLE					stop;		// NULL for main worker
-	BOOL					done;		// Not used for main worker
-
-	DWORD					numSources;
-	PollSource				*sources[ MAXIMUM_WAIT_OBJECTS ];
-	HANDLE					handles[ MAXIMUM_WAIT_OBJECTS ];
-	DWORD					result;
-	struct Worker_struct	*next;
-} Worker;
-
-
-typedef struct Poll_struct
-{
-	mDNSBool		setup;
-	HANDLE			wakeup;
-	GenLinkedList	sources;
-	DWORD			numSources;
-	Worker			main;
-	GenLinkedList	workers;
-	HANDLE			workerHandles[ MAXIMUM_WAIT_OBJECTS ];
-	DWORD			numWorkers;
-
-} Poll;
-
-
-/*
- * Poll Methods
- */
-
-mDNSlocal mStatus			PollSetup();
-mDNSlocal mStatus			PollRegisterSource( PollSource *source ); 
-mDNSlocal void				PollUnregisterSource( PollSource *source );
-mDNSlocal mStatus			PollStartWorkers();
-mDNSlocal mStatus			PollStopWorkers();
-mDNSlocal void				PollRemoveWorker( Worker *worker );
-
-
-/*
- * Worker Methods
- */
-
-mDNSlocal mStatus			WorkerInit( Worker *worker );
-mDNSlocal void				WorkerFree( Worker *worker );
-mDNSlocal void				WorkerRegisterSource( Worker *worker, PollSource *source );
-mDNSlocal int				WorkerSourceToIndex( Worker *worker, PollSource *source );
-mDNSlocal void				WorkerUnregisterSource( Worker *worker, PollSource *source );
-mDNSlocal void				WorkerDispatch( Worker *worker);
-mDNSlocal void CALLBACK		WorkerWakeupNotification( HANDLE event, void *context );
-mDNSlocal unsigned WINAPI	WorkerMain( LPVOID inParam );
-
-
-static void
-ShiftDown( void * arr, size_t arraySize, size_t itemSize, int index )
-{
-    memmove( ( ( unsigned char* ) arr ) + ( ( index - 1 ) * itemSize ), ( ( unsigned char* ) arr ) + ( index * itemSize ), ( arraySize - index ) * itemSize );
-}
-
-
-#define	DEBUG_NAME	"[mDNSWin32] "
-#define gMDNSRecord mDNSStorage
-mDNSlocal Poll gPoll;
-
-#define LogErr( err, FUNC ) LogMsg( "%s:%d - %s failed: %d\n", __FUNCTION__, __LINE__, FUNC, err );
-
-
-mStatus
-mDNSPollRegisterSocket( SOCKET socket, int networkEvents, mDNSPollSocketCallback callback, void *context )
-{
-	PollSource	*source = NULL;
-	HANDLE		event = INVALID_HANDLE_VALUE;
-	mStatus		err = mStatus_NoError;
-
-	if ( !gPoll.setup )
-	{
-		err = PollSetup();
-		require_noerr( err, exit );
-	}
-
-	source = malloc( sizeof( PollSource ) );
-	require_action( source, exit, err = mStatus_NoMemoryErr );
-
-	event = WSACreateEvent();
-	require_action( event, exit, err = mStatus_NoMemoryErr );
-
-	err = WSAEventSelect( socket, event, networkEvents );
-	require_noerr( err, exit );
-
-	source->socket = socket;
-	source->handle = event;
-	source->callback.socket = callback;
-	source->context = context;
-
-	err = PollRegisterSource( source );
-	require_noerr( err, exit );
-	
-exit:
-
-	if ( err != mStatus_NoError )
-	{
-		if ( event != INVALID_HANDLE_VALUE )
-		{
-			WSACloseEvent( event );
-		}
-
-		if ( source != NULL )
-		{
-			free( source );
-		}
-	}
-
-	return err;
-}
-
-
-void
-mDNSPollUnregisterSocket( SOCKET socket )
-{
-	PollSource	*source;
-
-	for ( source = gPoll.sources.Head; source; source = source->next )
-	{
-		if ( source->socket == socket )
-		{
-			break;
-		}
-	}
-
-	if ( source )
-	{
-		WSACloseEvent( source->handle );
-		PollUnregisterSource( source );
-		free( source );
-	}
-}
-
-
-mStatus
-mDNSPollRegisterEvent( HANDLE event, mDNSPollEventCallback callback, void *context )
-{
-	PollSource	*source = NULL;
-	mStatus		err = mStatus_NoError;
-
-	if ( !gPoll.setup )
-	{
-		err = PollSetup();
-		require_noerr( err, exit );
-	}
-
-	source = malloc( sizeof( PollSource ) );
-	require_action( source, exit, err = mStatus_NoMemoryErr );
-
-	source->socket = INVALID_SOCKET;
-	source->handle = event;
-	source->callback.event = callback;
-	source->context = context;
-
-	err = PollRegisterSource( source ); 
-	require_noerr( err, exit );
-	
-exit:
-
-	if ( err != mStatus_NoError )
-	{
-		if ( source != NULL )
-		{
-			free( source );
-		}
-	}
-
-	return err;
-}
-
-
-void
-mDNSPollUnregisterEvent( HANDLE event )
-{
-	PollSource	*source;
-
-	for ( source = gPoll.sources.Head; source; source = source->next )
-	{
-		if ( source->handle == event )
-		{
-			break;
-		}
-	}
-
-	if ( source )
-	{
-		PollUnregisterSource( source );
-		free( source );
-	}
-}
-
-
-mStatus
-mDNSPoll( DWORD msec )
-{
-	mStatus err = mStatus_NoError;
-
-	if ( gPoll.numWorkers > 0 )
-	{	
-		err = PollStartWorkers();
-		require_noerr( err, exit );
-	}
-
-	gPoll.main.result = WaitForMultipleObjects( gPoll.main.numSources, gPoll.main.handles, FALSE, msec );
-	err = translate_errno( ( gPoll.main.result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "WaitForMultipleObjects()" );
-	require_action( gPoll.main.result != WAIT_FAILED, exit, err = ( mStatus ) GetLastError() );
-
-	if ( gPoll.numWorkers > 0 )
-	{
-		err = PollStopWorkers();
-		require_noerr( err, exit );
-	}
-
-	WorkerDispatch( &gPoll.main );
-
-exit:
-
-	return ( err );
-}
-
-
-mDNSlocal mStatus
-PollSetup()
-{
-	mStatus err = mStatus_NoError;
-
-	if ( !gPoll.setup )
-	{
-		memset( &gPoll, 0, sizeof( gPoll ) );
-
-		InitLinkedList( &gPoll.sources, offsetof( PollSource, next ) );
-		InitLinkedList( &gPoll.workers, offsetof( Worker, next ) );
-
-		gPoll.wakeup = CreateEvent( NULL, TRUE, FALSE, NULL );
-		require_action( gPoll.wakeup, exit, err = mStatus_NoMemoryErr );
-
-		err = WorkerInit( &gPoll.main );
-		require_noerr( err, exit );
-		
-		gPoll.setup = mDNStrue;
-	}
-
-exit:
-
-	return err;
-}
-
-
-mDNSlocal mStatus
-PollRegisterSource( PollSource *source )
-{
-	Worker	*worker = NULL;
-	mStatus err = mStatus_NoError;
-
-	AddToTail( &gPoll.sources, source );
-	gPoll.numSources++;
-
-	// First check our main worker. In most cases, we won't have to worry about threads
-
-	if ( gPoll.main.numSources < MAXIMUM_WAIT_OBJECTS )
-	{
-		WorkerRegisterSource( &gPoll.main, source );
-	}
-	else
-	{
-		// Try to find a thread to use that we've already created
-
-		for ( worker = gPoll.workers.Head; worker; worker = worker->next )
-		{
-			if ( worker->numSources < MAXIMUM_WAIT_OBJECTS )
-			{
-				WorkerRegisterSource( worker, source );
-				break;
-			}
-		}
-
-		// If not, then create a worker and make a thread to run it in
-		
-		if ( !worker )
-		{
-			worker = ( Worker* ) malloc( sizeof( Worker ) );			
-			require_action( worker, exit, err = mStatus_NoMemoryErr );
-
-			memset( worker, 0, sizeof( Worker ) );
-
-			worker->start = CreateEvent( NULL, FALSE, FALSE, NULL );
-			require_action( worker->start, exit, err = mStatus_NoMemoryErr );
-
-			worker->stop = CreateEvent( NULL, FALSE, FALSE, NULL );
-			require_action( worker->stop, exit, err = mStatus_NoMemoryErr );
-
-			err = WorkerInit( worker );
-			require_noerr( err, exit );
-
-			// Create thread with _beginthreadex() instead of CreateThread() to avoid
-			// memory leaks when using static run-time libraries.
-			// See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createthread.asp>.
-
-			worker->thread = ( HANDLE ) _beginthreadex_compat( NULL, 0, WorkerMain, worker, 0, &worker->id );
-			err = translate_errno( worker->thread, ( mStatus ) GetLastError(), kUnknownErr );
-			require_noerr( err, exit );
-
-			AddToTail( &gPoll.workers, worker );
-			gPoll.workerHandles[ gPoll.numWorkers++ ] = worker->stop;
-			
-			WorkerRegisterSource( worker, source );
-		}
-	}
-
-exit:
-
-	if ( err && worker )
-	{
-		WorkerFree( worker );
-	}
-
-	return err;
-}
-
-
-mDNSlocal void
-PollUnregisterSource( PollSource *source )
-{
-	RemoveFromList( &gPoll.sources, source );
-	gPoll.numSources--;
-
-	WorkerUnregisterSource( source->worker, source );
-}
-
-
-mDNSlocal mStatus
-PollStartWorkers()
-{
-	Worker	*worker;
-	mStatus	err = mStatus_NoError;
-	BOOL	ok;
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "starting workers\n" );
-	
-	worker = gPoll.workers.Head;
-
-	while ( worker )
-	{
-		Worker *next = worker->next;
-
-		if ( worker->numSources == 1 )
-		{
-			PollRemoveWorker( worker );
-		}
-		else
-		{
-			dlog( kDebugLevelChatty, DEBUG_NAME "waking up worker\n" );
-
-			ok = SetEvent( worker->start );
-			err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
-			if ( err ) LogErr( err, "SetEvent()" );
-
-			if ( err )
-			{
-				PollRemoveWorker( worker );
-			}
-		}
-
-		worker = next;
-	}
-
-	err = mStatus_NoError;
-
-	return err;
-}
-
-
-mDNSlocal mStatus
-PollStopWorkers()
-{
-	DWORD	result;
-	Worker	*worker;
-	BOOL	ok;
-	mStatus	err = mStatus_NoError;
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "stopping workers\n" );
-	
-	ok = SetEvent( gPoll.wakeup );
-	err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "SetEvent()" );
-
-	// Wait For 5 seconds for all the workers to wake up
-
-	result = WaitForMultipleObjects( gPoll.numWorkers, gPoll.workerHandles, TRUE, 5000 );
-	err = translate_errno( ( result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "WaitForMultipleObjects()" );
-
-	ok = ResetEvent( gPoll.wakeup );
-	err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "ResetEvent()" );
-
-	for ( worker = gPoll.workers.Head; worker; worker = worker->next )
-	{
-		WorkerDispatch( worker );
-	}
-
-	err = mStatus_NoError;
-
-	return err;
-}
-
-
-mDNSlocal void
-PollRemoveWorker( Worker *worker )
-{
-	DWORD	result;
-	mStatus	err;
-	BOOL	ok;
-	DWORD	i;
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "removing worker %d\n", worker->id );
-	
-	RemoveFromList( &gPoll.workers, worker );
-
-	// Remove handle from gPoll.workerHandles
-
-	for ( i = 0; i < gPoll.numWorkers; i++ )
-	{
-		if ( gPoll.workerHandles[ i ] == worker->stop )
-		{
-			ShiftDown( gPoll.workerHandles, gPoll.numWorkers, sizeof( gPoll.workerHandles[ 0 ] ), i + 1 );
-			break;
-		}
-	}
-
-	worker->done = TRUE;
-	gPoll.numWorkers--;
-
-	// Cause the thread to exit.
-
-	ok = SetEvent( worker->start );
-	err = translate_errno( ok, ( OSStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "SetEvent()" );
-			
-	result = WaitForSingleObject( worker->thread, 5000 );
-	err = translate_errno( result != WAIT_FAILED, ( OSStatus ) GetLastError(), kUnknownErr );
-	if ( err ) LogErr( err, "WaitForSingleObject()" );
-			
-	if ( ( result == WAIT_FAILED ) || ( result == WAIT_TIMEOUT ) )
-	{
-		ok = TerminateThread( worker->thread, 0 );
-		err = translate_errno( ok, ( OSStatus ) GetLastError(), kUnknownErr );
-		if ( err ) LogErr( err, "TerminateThread()" );
-	}
-	
-	CloseHandle( worker->thread );
-	worker->thread = NULL;
-
-	WorkerFree( worker );
-}
-
-
-mDNSlocal void
-WorkerRegisterSource( Worker *worker, PollSource *source )
-{
-	source->worker = worker;
-	worker->sources[ worker->numSources ] = source;
-	worker->handles[ worker->numSources ] = source->handle;
-	worker->numSources++;
-}
-
-
-mDNSlocal int
-WorkerSourceToIndex( Worker *worker, PollSource *source )
-{
-	int index;
-
-	for ( index = 0; index < ( int ) worker->numSources; index++ )
-	{
-		if ( worker->sources[ index ] == source )
-		{
-			break;
-		}
-	}
-
-	if ( index == ( int ) worker->numSources )
-	{
-		index = -1;
-	}
-
-	return index;
-}
-
-
-mDNSlocal void
-WorkerUnregisterSource( Worker *worker, PollSource *source )
-{
-	int sourceIndex = WorkerSourceToIndex( worker, source );
-	DWORD delta;
-
-	if ( sourceIndex == -1 )
-	{
-		LogMsg( "WorkerUnregisterSource: source not found in list" );
-		goto exit;
-	}
-
-	delta = ( worker->numSources - sourceIndex - 1 );
-
-	// If this source is not at the end of the list, then move memory
-
-	if ( delta > 0 )
-	{
-		ShiftDown( worker->sources, worker->numSources, sizeof( worker->sources[ 0 ] ), sourceIndex + 1 );
-		ShiftDown( worker->handles, worker->numSources, sizeof( worker->handles[ 0 ] ), sourceIndex + 1 );
-	}
-		         
-	worker->numSources--;
-
-exit:
-
-	return;
-}
-
-
-mDNSlocal void CALLBACK
-WorkerWakeupNotification( HANDLE event, void *context )
-{
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "Worker thread wakeup\n" );
-}
-
-
-mDNSlocal void
-WorkerDispatch( Worker *worker )
-{
-	if ( worker->result == WAIT_FAILED )
-	{
-		/* What should we do here? */
-	}
-	else if ( worker->result == WAIT_TIMEOUT )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "timeout\n" );
-	}
-	else
-	{
-		DWORD		waitItemIndex = ( DWORD )( ( ( int ) worker->result ) - WAIT_OBJECT_0 );
-		PollSource	*source = NULL;
-
-		// Sanity check
-
-		if ( waitItemIndex >= worker->numSources )
-		{
-			LogMsg( "WorkerDispatch: waitItemIndex (%d) is >= numSources (%d)", waitItemIndex, worker->numSources );
-			goto exit;
-		}
-
-		source = worker->sources[ waitItemIndex ];
-
-		if ( source->socket != INVALID_SOCKET )
-		{
-			WSANETWORKEVENTS event;
-	
-			if ( WSAEnumNetworkEvents( source->socket, source->handle, &event ) == 0 )
-			{
-				source->callback.socket( source->socket, &event, source->context );
-			}
-			else
-			{
-				source->callback.socket( source->socket, NULL, source->context );
-			}
-		}
-		else
-		{
-			source->callback.event( source->handle, source->context );
-		}
-	}
-
-exit:
-
-	return;
-}
-
-
-mDNSlocal mStatus
-WorkerInit( Worker *worker )
-{
-	PollSource *source = NULL;
-	mStatus err = mStatus_NoError;
-	
-	require_action( worker, exit, err = mStatus_BadParamErr );
-
-	source = malloc( sizeof( PollSource ) );
-	require_action( source, exit, err = mStatus_NoMemoryErr );
-
-	source->socket = INVALID_SOCKET;
-	source->handle = gPoll.wakeup;
-	source->callback.event = WorkerWakeupNotification;
-	source->context = NULL;
-	
-	WorkerRegisterSource( worker, source );
-
-exit:
-
-	return err;
-}
-	
-
-mDNSlocal void
-WorkerFree( Worker *worker )
-{
-	if ( worker->start )
-	{
-		CloseHandle( worker->start );
-		worker->start = NULL;
-	}
-
-	if ( worker->stop )
-	{
-		CloseHandle( worker->stop );
-		worker->stop = NULL;
-	}
-
-	free( worker );
-}
-
-
-mDNSlocal unsigned WINAPI
-WorkerMain( LPVOID inParam )
-{
-	Worker *worker = ( Worker* ) inParam;
-	mStatus err = mStatus_NoError;
-
-	require_action( worker, exit, err = mStatus_BadParamErr );
-
-	dlog( kDebugLevelVerbose, DEBUG_NAME, "entering WorkerMain()\n" );
-
-	while ( TRUE )
-	{
-		DWORD	result;
-		BOOL	ok;
-
-		dlog( kDebugLevelChatty, DEBUG_NAME, "worker thread %d will wait on main loop\n", worker->id );
-		
-		result = WaitForSingleObject( worker->start, INFINITE );	
-		err = translate_errno( ( result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
-		if ( err ) { LogErr( err, "WaitForSingleObject()" ); break; }
-		if ( worker->done ) break;
-
-		dlog( kDebugLevelChatty, DEBUG_NAME "worker thread %d will wait on sockets\n", worker->id );
-
-		worker->result = WaitForMultipleObjects( worker->numSources, worker->handles, FALSE, INFINITE );
-		err = translate_errno( ( worker->result != WAIT_FAILED ), ( mStatus ) GetLastError(), kUnknownErr );
-		if ( err ) { LogErr( err, "WaitForMultipleObjects()" ); break; }
-
-		dlog( kDebugLevelChatty, DEBUG_NAME "worker thread %d did wait on sockets: %d\n", worker->id, worker->result );
-
-		ok = SetEvent( gPoll.wakeup );
-		err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
-		if ( err ) { LogErr( err, "SetEvent()" ); break; }
-
-		dlog( kDebugLevelChatty, DEBUG_NAME, "worker thread %d preparing to sleep\n", worker->id );
-
-		ok = SetEvent( worker->stop );
-		err = translate_errno( ok, ( mStatus ) GetLastError(), kUnknownErr );
-		if ( err ) { LogErr( err, "SetEvent()" ); break; }
-	}
-
-	dlog( kDebugLevelVerbose, DEBUG_NAME "exiting WorkerMain()\n" );
-
-exit:
-
-	return 0;
-}
diff --git a/mDNSWindows/Poll.h b/mDNSWindows/Poll.h
deleted file mode 100644
index bd1b10f..0000000
--- a/mDNSWindows/Poll.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#ifndef _Poll_h
-#define _Poll_h
-
-#include	"CommonServices.h"
-#include	<mswsock.h>
-#include	"mDNSEmbeddedAPI.h"
-#include	"uDNS.h"
-
-
-#if defined(__cplusplus )
-extern "C" {
-#endif
-
-
-typedef void ( CALLBACK *mDNSPollSocketCallback )( SOCKET socket, LPWSANETWORKEVENTS event, void *context );
-typedef void ( CALLBACK *mDNSPollEventCallback )( HANDLE event, void *context );
-
-
-extern mStatus
-mDNSPollRegisterSocket( SOCKET socket, int networkEvents, mDNSPollSocketCallback callback, void *context );
-
-
-extern void
-mDNSPollUnregisterSocket( SOCKET socket );
-
-
-extern mStatus
-mDNSPollRegisterEvent( HANDLE event, mDNSPollEventCallback callback, void *context );
-
-
-extern void
-mDNSPollUnregisterEvent( HANDLE event );
-
-
-extern mStatus
-mDNSPoll( DWORD msec );
-
-
-#if defined(__cplusplus)
-}
-#endif
-
-
-#endif
diff --git a/mDNSWindows/PosixCompat.c b/mDNSWindows/PosixCompat.c
deleted file mode 100644
index faabd07..0000000
--- a/mDNSWindows/PosixCompat.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "PosixCompat.h"
-#include <DebugServices.h>
-
-
-typedef PCHAR (WINAPI * if_indextoname_funcptr_t)(ULONG index, PCHAR name);
-typedef ULONG (WINAPI * if_nametoindex_funcptr_t)(PCSTR name);
-
-
-unsigned
-if_nametoindex( const char * ifname )
-{
-	HMODULE library;
-	unsigned index = 0;
-
-	check( ifname );
-
-	// Try and load the IP helper library dll
-	if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
-	{
-		if_nametoindex_funcptr_t if_nametoindex_funcptr;
-
-		// On Vista and above there is a Posix like implementation of if_nametoindex
-		if ((if_nametoindex_funcptr = (if_nametoindex_funcptr_t) GetProcAddress(library, "if_nametoindex")) != NULL )
-		{
-			index = if_nametoindex_funcptr(ifname);
-		}
-
-		FreeLibrary(library);
-	}
-
-	return index;
-}
-
-
-char*
-if_indextoname( unsigned ifindex, char * ifname )
-{
-	HMODULE library;
-	char * name = NULL;
-
-	check( ifname );
-	*ifname = '\0';
-
-	// Try and load the IP helper library dll
-	if ((library = LoadLibrary(TEXT("Iphlpapi")) ) != NULL )
-	{
-		if_indextoname_funcptr_t if_indextoname_funcptr;
-
-		// On Vista and above there is a Posix like implementation of if_indextoname
-		if ((if_indextoname_funcptr = (if_indextoname_funcptr_t) GetProcAddress(library, "if_indextoname")) != NULL )
-		{
-			name = if_indextoname_funcptr(ifindex, ifname);
-		}
-
-		FreeLibrary(library);
-	}
-
-	return name;
-}
-
-
-int
-inet_pton( int family, const char * addr, void * dst )
-{
-	struct sockaddr_storage ss;
-	int sslen = sizeof( ss );
-
-	ZeroMemory( &ss, sizeof( ss ) );
-	ss.ss_family = family;
-
-	if ( WSAStringToAddressA( ( LPSTR ) addr, family, NULL, ( struct sockaddr* ) &ss, &sslen ) == 0 )
-	{
-		if ( family == AF_INET ) { memcpy( dst, &( ( struct sockaddr_in* ) &ss)->sin_addr, sizeof( IN_ADDR ) ); return 1; }
-		else if ( family == AF_INET6 ) { memcpy( dst, &( ( struct sockaddr_in6* ) &ss)->sin6_addr, sizeof( IN6_ADDR ) ); return 1; }
-		else return 0;
-	}
-    else return 0;
-}
-
-
-int
-gettimeofday( struct timeval * tv, struct timezone * tz )
-{
-#define EPOCHFILETIME (116444736000000000i64)
-
-	if ( tv != NULL )
-	{
-		FILETIME        ft;
-		LARGE_INTEGER   li;
-		__int64         t;
-
-		GetSystemTimeAsFileTime(&ft);
-		li.LowPart  = ft.dwLowDateTime;
-		li.HighPart = ft.dwHighDateTime;
-		t  = li.QuadPart;	/* In 100-nanosecond intervals */
-		t -= EPOCHFILETIME;	/* Offset to the Epoch time */
-		t /= 10;			/* In microseconds */
-		tv->tv_sec  = ( long )( t / 1000000 );
-		tv->tv_usec = ( long )( t % 1000000 );
-	}
-
-	return 0;
-}
-
-
-extern struct tm*
-localtime_r( const time_t * clock, struct tm * result )
-{
-	localtime_s( result, clock );
-	return result;
-}
diff --git a/mDNSWindows/PosixCompat.h b/mDNSWindows/PosixCompat.h
deleted file mode 100644
index 9f9d005..0000000
--- a/mDNSWindows/PosixCompat.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#pragma once
-
-#include "CommonServices.h"
-#include <winsock2.h>
-#include <time.h>
-
-
-/* 
- * Posix process compatibility
- */
-typedef int pid_t;
-#if !defined( getpid )
-#	define getpid _getpid
-#endif
-
-
-/* 
- * Posix networking compatibility
- */
-extern unsigned
-if_nametoindex( const char * ifname );
-
-
-extern char*
-if_indextoname( unsigned ifindex, char * ifname );
-
-
-extern int
-inet_pton( int family, const char * addr, void * dst );
-
-
-/* 
- * Posix time compatibility
- */
-extern int
-gettimeofday( struct timeval * tv, struct timezone * tz );
-
-
-extern struct tm*
-localtime_r( const time_t * clock, struct tm * result );
-
-
-/* 
- * Posix string compatibility
- */
-#if !defined( strcasecmp )
-#	define strcasecmp	_stricmp
-#endif
-
-#if !defined( snprintf )
-#	define snprint		_snprintf
-#endif
-
diff --git a/mDNSWindows/RegNames.h b/mDNSWindows/RegNames.h
deleted file mode 100644
index bc885d6..0000000
--- a/mDNSWindows/RegNames.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-//----------------------------------------------------------------------------------------
-//	Registry Constants
-//----------------------------------------------------------------------------------------
-
-#if defined(UNICODE)
-
-#	define kServiceParametersSoftware			L"SOFTWARE"
-#	define kServiceParametersAppleComputer		L"Apple Computer, Inc."
-#	define kServiceParametersBonjour			L"Bonjour"
-#	define kServiceParametersNode				L"SOFTWARE\\Apple Inc.\\Bonjour"
-#	define kServiceName							L"Bonjour Service"
-#	define kServiceDynDNSBrowseDomains			L"BrowseDomains"
-#	define kServiceDynDNSHostNames				L"HostNames"
-#	define kServiceDynDNSRegistrationDomains	L"RegistrationDomains"
-#	define kServiceDynDNSDomains				L"Domains"	// value is comma separated list of domains
-#	define kServiceDynDNSEnabled				L"Enabled"
-#	define kServiceDynDNSStatus					L"Status"
-#	define kServiceManageLLRouting				L"ManageLLRouting"
-#	define kServiceCacheEntryCount				L"CacheEntryCount"
-#	define kServiceManageFirewall				L"ManageFirewall"
-#	define kServiceAdvertisedServices			L"Services"
-
-# else
-
-#	define kServiceParametersSoftware			"SOFTWARE"
-#	define kServiceParametersAppleComputer		"Apple Computer, Inc."
-#	define kServiceParametersBonjour			"Bonjour"
-#	define kServiceParametersNode				"SOFTWARE\\Apple Inc.\\Bonjour"
-#	define kServiceName							"Bonjour Service"
-#	define kServiceDynDNSBrowseDomains			"BrowseDomains"
-#	define kServiceDynDNSHostNames				"HostNames"
-#	define kServiceDynDNSRegistrationDomains	"RegistrationDomains"
-#	define kServiceDynDNSDomains				"Domains"	// value is comma separated list of domains
-#	define kServiceDynDNSEnabled				"Enabled"
-#	define kServiceDynDNSStatus					"Status"
-#	define kServiceManageLLRouting				"ManageLLRouting"
-#	define kServiceCacheEntryCount				"CacheEntryCount"
-#	define kServiceManageFirewall				"ManageFirewall"
-
-#endif
diff --git a/mDNSWindows/Secret.c b/mDNSWindows/Secret.c
deleted file mode 100644
index 1f5f870..0000000
--- a/mDNSWindows/Secret.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2021 Apple 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
- * 
- *     https://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.
- */
-
-#include "Secret.h"
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <process.h>
-#include <ntsecapi.h>
-#include <lm.h>
-#include "DebugServices.h"
-
-
-mDNSlocal OSStatus MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
-mDNSlocal OSStatus MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
-
-
-mDNSBool
-LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainSize, char * outKey, unsigned outKeySize, char * outSecret, unsigned outSecretSize )
-{
-	PLSA_UNICODE_STRING		domainLSA;
-	PLSA_UNICODE_STRING		keyLSA;
-	PLSA_UNICODE_STRING		secretLSA;
-	size_t					i;
-	size_t					dlen;
-	LSA_OBJECT_ATTRIBUTES	attrs;
-	LSA_HANDLE				handle = NULL;
-	NTSTATUS				res;
-	OSStatus				err;
-
-	check( inDomain );
-	check( outDomain );
-	check( outKey );
-	check( outSecret );
-
-	// Initialize
-
-	domainLSA	= NULL;
-	keyLSA		= NULL;
-	secretLSA	= NULL;
-
-	// Make sure we have enough space to add trailing dot
-
-	dlen = strlen( inDomain );
-	err = strcpy_s( outDomain, outDomainSize - 2, inDomain );
-	require_noerr( err, exit );
-
-	// If there isn't a trailing dot, add one because the mDNSResponder
-	// presents names with the trailing dot.
-
-	if ( outDomain[ dlen - 1 ] != '.' )
-	{
-		outDomain[ dlen++ ] = '.';
-		outDomain[ dlen ] = '\0';
-	}
-
-	// Canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
-
-	for ( i = 0; i < dlen; i++ )
-	{
-		outDomain[i] = (char) tolower( outDomain[i] );  // canonicalize -> lower case
-	}
-
-	// attrs are reserved, so initialize to zeroes.
-
-	ZeroMemory( &attrs, sizeof( attrs ) );
-
-	// Get a handle to the Policy object on the local system
-
-	res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr( err, exit );
-
-	// Get the encrypted data
-
-	domainLSA = ( PLSA_UNICODE_STRING ) malloc( sizeof( LSA_UNICODE_STRING ) );
-	require_action( domainLSA != NULL, exit, err = mStatus_NoMemoryErr );
-	err = MakeLsaStringFromUTF8String( domainLSA, outDomain );
-	require_noerr( err, exit );
-
-	// Retrieve the key
-
-	res = LsaRetrievePrivateData( handle, domainLSA, &keyLSA );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr_quiet( err, exit );
-
-	// <rdar://problem/4192119> Lsa secrets use a flat naming space.  Therefore, we will prepend "$" to the keyname to
-	// make sure it doesn't conflict with a zone name.	
-	// Strip off the "$" prefix.
-
-	err = MakeUTF8StringFromLsaString( outKey, outKeySize, keyLSA );
-	require_noerr( err, exit );
-	require_action( outKey[0] == '$', exit, err = kUnknownErr );
-	memcpy( outKey, outKey + 1, strlen( outKey ) );
-
-	// Retrieve the secret
-
-	res = LsaRetrievePrivateData( handle, keyLSA, &secretLSA );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr_quiet( err, exit );
-
-	// Convert the secret to UTF8 string
-
-	err = MakeUTF8StringFromLsaString( outSecret, outSecretSize, secretLSA );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( domainLSA != NULL )
-	{
-		if ( domainLSA->Buffer != NULL )
-		{
-			free( domainLSA->Buffer );
-		}
-
-		free( domainLSA );
-	}
-
-	if ( keyLSA != NULL )
-	{
-		LsaFreeMemory( keyLSA );
-	}
-
-	if ( secretLSA != NULL )
-	{
-		LsaFreeMemory( secretLSA );
-	}
-
-	if ( handle )
-	{
-		LsaClose( handle );
-		handle = NULL;
-	}
-
-	return ( !err ) ? TRUE : FALSE;
-}
-
-
-mDNSBool
-LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret )
-{
-	size_t					inDomainLength;
-	size_t					inKeyLength;
-	char					domain[ 1024 ];
-	char					key[ 1024 ];
-	LSA_OBJECT_ATTRIBUTES	attrs;
-	LSA_HANDLE				handle = NULL;
-	NTSTATUS				res;
-	LSA_UNICODE_STRING		lucZoneName;
-	LSA_UNICODE_STRING		lucKeyName;
-	LSA_UNICODE_STRING		lucSecretName;
-	BOOL					ok = TRUE;
-	OSStatus				err;
-
-	require_action( inDomain != NULL, exit, ok = FALSE );
-	require_action( inKey != NULL, exit, ok = FALSE );
-	require_action( inSecret != NULL, exit, ok = FALSE );
-
-	// If there isn't a trailing dot, add one because the mDNSResponder
-	// presents names with the trailing dot.
-
-	ZeroMemory( domain, sizeof( domain ) );
-	inDomainLength = strlen( inDomain );
-	require_action( inDomainLength > 0, exit, ok = FALSE );
-	err = strcpy_s( domain, sizeof( domain ) - 2, inDomain );
-	require_action( !err, exit, ok = FALSE );
-
-	if ( domain[ inDomainLength - 1 ] != '.' )
-	{
-		domain[ inDomainLength++ ] = '.';
-		domain[ inDomainLength ] = '\0';
-	}
-
-	// <rdar://problem/4192119>
-	//
-	// Prepend "$" to the key name, so that there will
-	// be no conflict between the zone name and the key
-	// name
-
-	ZeroMemory( key, sizeof( key ) );
-	inKeyLength = strlen( inKey );
-	require_action( inKeyLength > 0 , exit, ok = FALSE );
-	key[ 0 ] = '$';
-	err = strcpy_s( key + 1, sizeof( key ) - 3, inKey );
-	require_action( !err, exit, ok = FALSE );
-	inKeyLength++;
-
-	if ( key[ inKeyLength - 1 ] != '.' )
-	{
-		key[ inKeyLength++ ] = '.';
-		key[ inKeyLength ] = '\0';
-	}
-
-	// attrs are reserved, so initialize to zeroes.
-
-	ZeroMemory( &attrs, sizeof( attrs ) );
-
-	// Get a handle to the Policy object on the local system
-
-	res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr( err, exit );
-
-	// Intializing PLSA_UNICODE_STRING structures
-
-	err = MakeLsaStringFromUTF8String( &lucZoneName, domain );
-	require_noerr( err, exit );
-
-	err = MakeLsaStringFromUTF8String( &lucKeyName, key );
-	require_noerr( err, exit );
-
-	err = MakeLsaStringFromUTF8String( &lucSecretName, inSecret );
-	require_noerr( err, exit );
-
-	// Store the private data.
-
-	res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr( err, exit );
-
-	res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
-	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( handle )
-	{
-		LsaClose( handle );
-		handle = NULL;
-	}
-
-	return (mDNSBool) ok;
-}
-
-
-//===========================================================================================================================
-//	MakeLsaStringFromUTF8String
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
-{
-	int			size;
-	OSStatus	err;
-	
-	check( input );
-	check( output );
-
-	output->Buffer = NULL;
-
-	size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
-	err = translate_errno( size > 0, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	output->Length = (USHORT)( size * sizeof( wchar_t ) );
-	output->Buffer = (PWCHAR) malloc( output->Length );
-	require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
-	size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
-	err = translate_errno( size > 0, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// We're going to subtrace one wchar_t from the size, because we didn't
-	// include it when we encoded the string
-
-	output->MaximumLength = output->Length;
-	output->Length		-= sizeof( wchar_t );
-	
-exit:
-
-	if ( err && output->Buffer )
-	{
-		free( output->Buffer );
-		output->Buffer = NULL;
-	}
-
-	return( err );
-}
-
-
-
-//===========================================================================================================================
-//	MakeUTF8StringFromLsaString
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
-{
-	size_t		size;
-	OSStatus	err = kNoErr;
-
-	// The Length field of this structure holds the number of bytes,
-	// but WideCharToMultiByte expects the number of wchar_t's. So
-	// we divide by sizeof(wchar_t) to get the correct number.
-
-	size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
-	err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	// Ensure that we have enough space (Add one for trailing '\0')
-
-	require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
-
-	// Convert the string
-
-	size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL);	
-	err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// have to add the trailing 0 because WideCharToMultiByte doesn't do it,
-	// although it does return the correct size
-
-	output[size] = '\0';
-
-exit:
-
-	return err;
-}
-
diff --git a/mDNSWindows/Secret.h b/mDNSWindows/Secret.h
deleted file mode 100644
index f5434f0..0000000
--- a/mDNSWindows/Secret.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2013 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.
- */
-
-#ifndef _Secret_h
-#define _Secret_h
-
-#include "mDNSEmbeddedAPI.h"
-
-
-#if defined(__cplusplus )
-extern "C" {
-#endif
-
-
-extern mDNSBool
-LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainSize, char * outKey, unsigned outKeySize, char * outSecret, unsigned outSecretSize );
-
-
-extern mDNSBool
-LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret );
-
-
-#if defined(__cplusplus)
-}
-#endif
-
-
-#endif
diff --git a/mDNSWindows/SystemService/Firewall.cpp b/mDNSWindows/SystemService/Firewall.cpp
deleted file mode 100644
index c7c96d0..0000000
--- a/mDNSWindows/SystemService/Firewall.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-// <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
-
-#if !defined(_WIN32_DCOM)
-#	define _WIN32_DCOM 
-#endif
-
-
-#include "Firewall.h"
-#include <windows.h>
-#include <crtdbg.h>
-#include <netfw.h>
-#include <objbase.h>
-#include <oleauto.h>
-
-
-static const int kMaxTries			= 30;
-static const int kRetrySleepPeriod	= 1 * 1000; // 1 second
-
-
-static OSStatus
-mDNSFirewallInitialize(OUT INetFwProfile ** fwProfile)
-{
-	INetFwMgr		*	fwMgr		= NULL;
-	INetFwPolicy	*	fwPolicy	= NULL;
-	int					numRetries	= 0;
-	HRESULT				err			= kNoErr;
-    
-	_ASSERT(fwProfile != NULL);
-
-    *fwProfile = NULL;
-
-	// Use COM to get a reference to the firewall settings manager.  This
-	// call will fail on anything other than XP SP2
-
-	err = CoCreateInstance( __uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&fwMgr );
-	require(SUCCEEDED(err) && ( fwMgr != NULL ), exit);
-
-	// Use the reference to get the local firewall policy
-
-	err = fwMgr->get_LocalPolicy(&fwPolicy);
-	require(SUCCEEDED(err) && ( fwPolicy != NULL ), exit);
-
-	// Use the reference to get the extant profile. Empirical evidence
-	// suggests that there is the potential for a race condition when a system
-	// service whose startup type is automatic calls this method.
-	// This is true even when the service declares itself to be dependent
-	// on the firewall service. Re-trying the method will succeed within
-	// a few seconds.
-
-	do
-	{
-    	err = fwPolicy->get_CurrentProfile(fwProfile);
-
-		if (err)
-		{
-			Sleep(kRetrySleepPeriod);
-		}
-	}
-	while (err && (numRetries++ < kMaxTries));
-
-	require(SUCCEEDED(err), exit);
-
-	err = kNoErr;
-
-exit:
-
-	// Release temporary COM objects
-
-    if (fwPolicy != NULL)
-    {
-        fwPolicy->Release();
-    }
-
-    if (fwMgr != NULL)
-    {
-        fwMgr->Release();
-    }
-
-    return err;
-}
-
-
-static void
-mDNSFirewallCleanup
-			(
-			IN INetFwProfile	*	fwProfile
-			)
-{
-	// Call Release on the COM reference.
-
-    if (fwProfile != NULL)
-    {
-        fwProfile->Release();
-    }
-}
-
-
-static OSStatus
-mDNSFirewallAppIsEnabled
-			(
-			IN INetFwProfile	*	fwProfile,
-			IN const wchar_t	*	fwProcessImageFileName,
-			OUT BOOL			*	fwAppEnabled    
-			)
-{
-	BSTR							fwBstrProcessImageFileName = NULL;
-	VARIANT_BOOL					fwEnabled;
-	INetFwAuthorizedApplication	*	fwApp	= NULL;
-	INetFwAuthorizedApplications*	fwApps	= NULL;
-	OSStatus						err		= kNoErr;
-    
-	_ASSERT(fwProfile != NULL);
-	_ASSERT(fwProcessImageFileName != NULL);
-	_ASSERT(fwAppEnabled != NULL);
-
-    *fwAppEnabled = FALSE;
-
-	// Get the list of authorized applications
-
-	err = fwProfile->get_AuthorizedApplications(&fwApps);
-	require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
-
-    fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
-	require_action( ( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
-
-	// Look for us
-
-    err = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
-	
-    if (SUCCEEDED(err) && ( fwApp != NULL ) )
-    {
-        // It's listed, but is it enabled?
-
-		err = fwApp->get_Enabled(&fwEnabled);
-		require(SUCCEEDED(err), exit);
-
-        if (fwEnabled != VARIANT_FALSE)
-        {
-			// Yes, it's enabled
-
-            *fwAppEnabled = TRUE;
-		}
-	}
-
-	err = kNoErr;
-
-exit:
-
-	// Deallocate the BSTR
-
-	if ( fwBstrProcessImageFileName != NULL )
-	{
-		SysFreeString(fwBstrProcessImageFileName);
-	}
-
-	// Release the COM objects
-
-    if (fwApp != NULL)
-    {
-        fwApp->Release();
-    }
-
-    if (fwApps != NULL)
-    {
-        fwApps->Release();
-    }
-
-    return err;
-}
-
-
-static OSStatus
-mDNSFirewallAddApp
-			(
-            IN INetFwProfile	*	fwProfile,
-            IN const wchar_t	*	fwProcessImageFileName,
-            IN const wchar_t	*	fwName
-            )
-{
-	BOOL							fwAppEnabled;
-	BSTR							fwBstrName = NULL;
-	BSTR							fwBstrProcessImageFileName = NULL;
-	INetFwAuthorizedApplication	*	fwApp = NULL;
-	INetFwAuthorizedApplications*	fwApps = NULL;
-	OSStatus						err = S_OK;
-    
-	_ASSERT(fwProfile != NULL);
-    _ASSERT(fwProcessImageFileName != NULL);
-    _ASSERT(fwName != NULL);
-
-    // First check to see if the application is already authorized.
-	err = mDNSFirewallAppIsEnabled( fwProfile, fwProcessImageFileName, &fwAppEnabled );
-	require_noerr(err, exit);
-
-	// Only add the application if it isn't enabled
-
-	if (!fwAppEnabled)
-	{
-		// Get the list of authorized applications
-
-        err = fwProfile->get_AuthorizedApplications(&fwApps);
-		require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
-
-        // Create an instance of an authorized application.
-
-		err = CoCreateInstance( __uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), (void**)&fwApp );
-		require(SUCCEEDED(err) && ( fwApp != NULL ), exit);
-
-        fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
-		require_action(( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
-
-		// Set the executable file name
-
-		err = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
-		require(SUCCEEDED(err), exit);
-
-		fwBstrName = SysAllocString(fwName);
-		require_action( ( fwBstrName != NULL ) && ( SysStringLen(fwBstrName) > 0 ), exit, err = kNoMemoryErr);
-
-		// Set the friendly name
-
-        err = fwApp->put_Name(fwBstrName);
-		require(SUCCEEDED(err), exit);
-
-		// Now add the application
-
-        err = fwApps->Add(fwApp);
-		require(SUCCEEDED(err), exit);
-	}
-
-	err = kNoErr;
-
-exit:
-
-	// Deallocate the BSTR objects
-
-	if ( fwBstrName != NULL )
-	{
-		SysFreeString(fwBstrName);
-	}
-
-	if ( fwBstrProcessImageFileName != NULL )
-	{
-		SysFreeString(fwBstrProcessImageFileName);
-	}
-
-    // Release the COM objects
-
-    if (fwApp != NULL)
-    {
-        fwApp->Release();
-    }
-
-    if (fwApps != NULL)
-    {
-        fwApps->Release();
-    }
-
-    return err;
-}
-
-
-
-
-
-static OSStatus
-
-mDNSFirewallIsFileAndPrintSharingEnabled
-
-	(
-
-	IN INetFwProfile	* fwProfile,
-
-	OUT BOOL			* fwServiceEnabled
-
-	)
-
-{
-
-    VARIANT_BOOL fwEnabled;
-
-    INetFwService* fwService = NULL;
-
-    INetFwServices* fwServices = NULL;
-
-	OSStatus err = S_OK;
-
-
-
-    _ASSERT(fwProfile != NULL);
-
-    _ASSERT(fwServiceEnabled != NULL);
-
-
-
-    *fwServiceEnabled = FALSE;
-
-
-
-    // Retrieve the globally open ports collection.
-
-    err = fwProfile->get_Services(&fwServices);
-
-	require( SUCCEEDED( err ), exit );
-
-
-
-    // Attempt to retrieve the globally open port.
-
-    err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);
-
-	require( SUCCEEDED( err ), exit );
-
-	
-
-	// Find out if the globally open port is enabled.
-
-    err = fwService->get_Enabled(&fwEnabled);
-
-	require( SUCCEEDED( err ), exit );
-
-	if (fwEnabled != VARIANT_FALSE)
-
-	{
-
-		*fwServiceEnabled = TRUE;
-
-	}
-
-
-
-exit:
-
-
-
-    // Release the globally open port.
-
-    if (fwService != NULL)
-
-    {
-
-        fwService->Release();
-
-    }
-
-
-
-    // Release the globally open ports collection.
-
-    if (fwServices != NULL)
-
-    {
-
-        fwServices->Release();
-
-    }
-
-
-
-    return err;
-
-}
-
-
-OSStatus
-mDNSAddToFirewall
-		(
-		LPWSTR	executable,
-		LPWSTR	name
-		)
-{
-	INetFwProfile	*	fwProfile	= NULL;
-	HRESULT				comInit		= E_FAIL;
-	OSStatus			err			= kNoErr;
-
-	// Initialize COM.
-
-	comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
-
-	// Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
-	// initialized with a different mode.
-
-	if (comInit != RPC_E_CHANGED_MODE)
-	{
-		err = comInit;
-		require(SUCCEEDED(err), exit);
-	}
-
-	// Connect to the firewall
-
-	err = mDNSFirewallInitialize(&fwProfile);
-	require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
-
-	// Add us to the list of exempt programs
-
-	err = mDNSFirewallAddApp( fwProfile, executable, name );
-	require_noerr(err, exit);
-
-exit:
-
-	// Disconnect from the firewall
-
-	if ( fwProfile != NULL )
-	{
-		mDNSFirewallCleanup(fwProfile);
-	}
-
-	// De-initialize COM
-
-	if (SUCCEEDED(comInit))
-    {
-        CoUninitialize();
-    }
-
-	return err;
-}
-
-
-BOOL
-mDNSIsFileAndPrintSharingEnabled( BOOL * retry )
-{
-	INetFwProfile	*	fwProfile					= NULL;
-	HRESULT				comInit						= E_FAIL;
-	BOOL				enabled						= FALSE;
-	OSStatus			err							= kNoErr;
-
-	// Initialize COM.
-
-	*retry = FALSE;
-	comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
-
-	// Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
-	// initialized with a different mode.
-
-	if (comInit != RPC_E_CHANGED_MODE)
-	{
-		*retry = TRUE;
-		err = comInit;
-		require(SUCCEEDED(err), exit);
-	}
-
-	// Connect to the firewall
-
-	err = mDNSFirewallInitialize(&fwProfile);
-	require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
-
-	err = mDNSFirewallIsFileAndPrintSharingEnabled( fwProfile, &enabled );
-	require_noerr( err, exit );
-
-exit:
-
-	// Disconnect from the firewall
-
-	if ( fwProfile != NULL )
-	{
-		mDNSFirewallCleanup(fwProfile);
-	}
-
-	// De-initialize COM
-
-	if (SUCCEEDED(comInit))
-    {
-        CoUninitialize();
-    }
-
-	return enabled;
-}
diff --git a/mDNSWindows/SystemService/Firewall.h b/mDNSWindows/SystemService/Firewall.h
deleted file mode 100644
index 3d7d532..0000000
--- a/mDNSWindows/SystemService/Firewall.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-
-
-#ifndef _Firewall_h
-
-#define _Firewall_h
-
-
-
-
-
-#include "CommonServices.h"
-
-#include "DebugServices.h"
-
-
-
-
-
-#if defined(__cplusplus)
-
-extern "C"
-
-{
-
-#endif
-
-
-
-
-
-OSStatus
-
-mDNSAddToFirewall
-
-		(
-
-		LPWSTR	executable,
-
-		LPWSTR	name
-
-		);
-
-
-BOOL
-mDNSIsFileAndPrintSharingEnabled( BOOL * retry );
-
-
-
-
-
-#if defined(__cplusplus)
-
-}
-
-#endif
-
-
-
-
-
-#endif
-
diff --git a/mDNSWindows/SystemService/Prefix.h b/mDNSWindows/SystemService/Prefix.h
deleted file mode 100644
index 61381d0..0000000
--- a/mDNSWindows/SystemService/Prefix.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-#ifndef __PREFIX__
-#define __PREFIX__
-
-#if( defined( _DEBUG ) )
-	#define	DEBUG					1
-	#define	MDNS_DEBUGMSGS			1
-#else
-	#define	DEBUG					0
-#endif
-
-#define	DNS_SD_CLIENT_ENABLED		0
-
-#endif	// __PREFIX__
diff --git a/mDNSWindows/SystemService/Service.c b/mDNSWindows/SystemService/Service.c
deleted file mode 100644
index c9bc22e..0000000
--- a/mDNSWindows/SystemService/Service.c
+++ /dev/null
@@ -1,2741 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2021 Apple 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
- * 
- *     https://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.
- */
-
-#include	<stdio.h>
-#include	<stdlib.h>
-#include	<crtdbg.h>
-#include	<stdarg.h>
-#include	<stddef.h>
-
-#include	"Poll.h"
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-#include	"RegNames.h"
-
-#include	"uds_daemon.h"
-#include	"GenLinkedList.h"
-#include	"Service.h"
-#include	"EventLog.h"
-
-#include	"Resource.h"
-
-#include	"mDNSEmbeddedAPI.h"
-#include	"uDNS.h"
-#include	"mDNSWin32.h"
-#include	"mDNSDebug.h"
-
-#include	"Firewall.h"
-
-#if( !TARGET_OS_WINDOWS_CE )
-	#include	<mswsock.h>
-	#include	<process.h>
-	#include	<ipExport.h>
-	#include	<ws2def.h>
-	#include	<ws2ipdef.h>
-	#include	<iphlpapi.h>
-	#include	<netioapi.h>
-	#include	<iptypes.h>
-	#include	<powrprof.h>
-#endif
-
-#ifndef HeapEnableTerminationOnCorruption
-#	define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
-#endif
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#define	DEBUG_NAME							"[mDNSWin32] "
-#define kServiceFirewallName				L"Bonjour"
-#define	kServiceDependencies				TEXT("Tcpip\0\0")
-#define	kDNSServiceCacheEntryCountDefault	512
-#define kRetryFirewallPeriod				30 * 1000
-#define kDefValueSize						MAX_PATH + 1
-#define kZeroIndex							0
-#define kDefaultRouteMetric					399
-#define kSecondsTo100NSUnits				( 10 * 1000 * 1000 )
-#define kSPSMaintenanceWakePeriod			-30
-#define kWaitToRetry						(60 * 5)
-
-#define RR_CACHE_SIZE 500
-static CacheEntity gRRCache[RR_CACHE_SIZE];
-#if 0
-#pragma mark == Structures ==
-#endif
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-static void				Usage( void );
-static BOOL WINAPI		ConsoleControlHandler( DWORD inControlEvent );
-static OSStatus			InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath );
-static OSStatus			RemoveService( LPCTSTR inName );
-static OSStatus			SetServiceParameters();
-static OSStatus			GetServiceParameters();
-static OSStatus			CheckFirewall();
-static OSStatus			SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription );
-static void				ReportStatus( int inType, const char *inFormat, ... );
-
-static void WINAPI		ServiceMain( DWORD argc, LPTSTR argv[] );
-static OSStatus			ServiceSetupEventLogging( void );
-static DWORD WINAPI		ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext );
-
-static OSStatus			ServiceRun( int argc, LPTSTR argv[] );
-static void				ServiceStop( void );
-
-static OSStatus			ServiceSpecificInitialize( int argc, LPTSTR  argv[] );
-static OSStatus			ServiceSpecificRun( int argc, LPTSTR argv[] );
-static OSStatus			ServiceSpecificStop( void );
-static void				ServiceSpecificFinalize( int argc, LPTSTR argv[] );
-static mStatus			SetupServiceEvents();
-static mStatus			TearDownServiceEvents();
-static mStatus			SetupNotifications();
-static mStatus			TearDownNotifications();
-static void CALLBACK	StopNotification( HANDLE event, void * context );
-static void CALLBACK	PowerSuspendNotification( HANDLE event, void * context );
-static void	CALLBACK	PowerResumeNotification( HANDLE event, void * context );
-static void CALLBACK	InterfaceListNotification( SOCKET socket, LPWSANETWORKEVENTS event, void *context );
-static void CALLBACK	ComputerDescriptionNotification( HANDLE event, void *context );
-static void CALLBACK	TCPChangedNotification( HANDLE event, void *context );
-static void CALLBACK	DDNSChangedNotification( HANDLE event, void *context );
-static void CALLBACK	FileSharingChangedNotification( HANDLE event, void *context );
-static void CALLBACK	FirewallChangedNotification( HANDLE event, void *context );
-static void CALLBACK	AdvertisedServicesChangedNotification( HANDLE event, void *context );
-static void CALLBACK	SPSWakeupNotification( HANDLE event, void *context );
-static void	CALLBACK	SPSSleepNotification( HANDLE event, void *context );
-static void CALLBACK	UDSAcceptNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-static void CALLBACK	UDSReadNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-static void				CoreCallback(mDNS * const inMDNS, mStatus result);
-static mDNSu8			SystemWakeForNetworkAccess( LARGE_INTEGER * timeout );
-static OSStatus			GetRouteDestination(DWORD * ifIndex, DWORD * address);
-static OSStatus			SetLLRoute( mDNS * const inMDNS );
-static bool				HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric );
-static bool				IsValidAddress( const char * addr );
-static bool				IsNortelVPN( IP_ADAPTER_INFO * pAdapter );
-static bool				IsJuniperVPN( IP_ADAPTER_INFO * pAdapter );
-static bool				IsCiscoVPN( IP_ADAPTER_INFO * pAdapter );
-static const char *		strnistr( const char * string, const char * subString, size_t max );
-
-#if defined(UNICODE)
-#	define StrLen(X)	wcslen(X)
-#	define StrCmp(X,Y)	wcscmp(X,Y)
-#else
-#	define StrLen(X)	strlen(X)
-#	define StrCmp(X,Y)	strcmp(X,Y)
-#endif
-
-
-#define kLLNetworkAddr      "169.254.0.0"
-#define kLLNetworkAddrMask  "255.255.0.0"
-
-
-#include	"mDNSEmbeddedAPI.h"
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-#define gMDNSRecord mDNSStorage
-DEBUG_LOCAL	mDNS_PlatformSupport		gPlatformStorage;
-DEBUG_LOCAL BOOL						gServiceQuietMode		= FALSE;
-DEBUG_LOCAL SERVICE_TABLE_ENTRY			gServiceDispatchTable[] = 
-{
-	{ kServiceName,	ServiceMain }, 
-	{ NULL, 		NULL }
-};
-DEBUG_LOCAL HANDLE						gStopEvent					= NULL;
-DEBUG_LOCAL HANDLE						gPowerSuspendEvent			= NULL;
-DEBUG_LOCAL HANDLE						gPowerSuspendAckEvent		= NULL;
-DEBUG_LOCAL HANDLE						gPowerResumeEvent			= NULL;
-DEBUG_LOCAL SOCKET						gInterfaceListChangedSocket	= INVALID_SOCKET;
-DEBUG_LOCAL HKEY						gDescKey					= NULL;
-DEBUG_LOCAL HANDLE						gDescChangedEvent			= NULL;	// Computer description changed event
-DEBUG_LOCAL HKEY						gTcpipKey					= NULL;
-DEBUG_LOCAL HANDLE						gTcpipChangedEvent			= NULL;	// TCP/IP config changed
-DEBUG_LOCAL HKEY						gDdnsKey					= NULL;
-DEBUG_LOCAL HANDLE						gDdnsChangedEvent			= NULL;	// DynDNS config changed
-DEBUG_LOCAL HKEY						gFileSharingKey				= NULL;
-DEBUG_LOCAL HANDLE						gFileSharingChangedEvent	= NULL;	// File Sharing changed
-DEBUG_LOCAL HKEY						gFirewallKey				= NULL;
-DEBUG_LOCAL HANDLE						gFirewallChangedEvent		= NULL;	// Firewall changed
-DEBUG_LOCAL HKEY						gAdvertisedServicesKey		= NULL;
-DEBUG_LOCAL HANDLE						gAdvertisedServicesChangedEvent	= NULL; // Advertised services changed
-DEBUG_LOCAL SERVICE_STATUS				gServiceStatus;
-DEBUG_LOCAL SERVICE_STATUS_HANDLE		gServiceStatusHandle 	= NULL;
-DEBUG_LOCAL HANDLE						gServiceEventSource		= NULL;
-DEBUG_LOCAL bool						gServiceAllowRemote		= false;
-DEBUG_LOCAL int							gServiceCacheEntryCount	= 0;	// 0 means to use the DNS-SD default.
-DEBUG_LOCAL bool						gServiceManageLLRouting = true;
-DEBUG_LOCAL HANDLE						gSPSWakeupEvent			= NULL;
-DEBUG_LOCAL HANDLE						gSPSSleepEvent			= NULL;
-DEBUG_LOCAL SocketRef					gUDSSocket				= 0;
-DEBUG_LOCAL udsEventCallback			gUDSCallback			= NULL;
-DEBUG_LOCAL BOOL						gRetryFirewall			= FALSE;
-
-typedef DWORD ( WINAPI * GetIpInterfaceEntryFunctionPtr )( PMIB_IPINTERFACE_ROW );
-mDNSlocal HMODULE								gIPHelperLibraryInstance		= NULL;
-mDNSlocal GetIpInterfaceEntryFunctionPtr		gGetIpInterfaceEntryFunctionPtr	= NULL;
-
-
-mDNSlocal HANDLE					gDNSThread = NULL;
-mDNSlocal HANDLE					gDNSThreadStopEvent = NULL;
-mDNSlocal HANDLE					gDNSThreadQuitEvent = NULL;
-
-#define	kDNSStopEvent				( WAIT_OBJECT_0 + 0 )
-
-bool gThreadStarted = false;
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	Main
-//===========================================================================================================================
-int	Main( int argc, LPTSTR argv[] )
-{
-	OSStatus		err;
-	BOOL			ok;
-	BOOL			start;
-	int				i;
-
-	HeapSetInformation( NULL, HeapEnableTerminationOnCorruption, NULL, 0 );
-
-	debug_initialize( kDebugOutputTypeMetaConsole );
-	debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelVerbose );
-
-	// Default to automatically starting the service dispatcher if no extra arguments are specified.
-	
-	start = ( argc <= 1 );
-	
-	// Parse arguments.
-	
-	for( i = 1; i < argc; ++i )
-	{
-		if( StrCmp( argv[ i ], TEXT("-install") ) == 0 )			// Install
-		{
-			TCHAR desc[ 256 ];
-			
-			desc[ 0 ] = 0;
-			LoadString( GetModuleHandle( NULL ), IDS_SERVICE_DESCRIPTION, desc, sizeof( desc ) );
-			err = InstallService( kServiceName, kServiceName, desc, argv[0] );
-			if( err )
-			{
-				ReportStatus( EVENTLOG_ERROR_TYPE, "install service failed (%d)\n", err );
-				goto exit;
-			}
-		}
-		else if( StrCmp( argv[ i ], TEXT("-remove") ) == 0 )		// Remove
-		{
-			err = RemoveService( kServiceName );
-			if( err )
-			{
-				ReportStatus( EVENTLOG_ERROR_TYPE, "remove service failed (%d)\n", err );
-				goto exit;
-			}
-		}
-		else if( StrCmp( argv[ i ], TEXT("-start") ) == 0 )		// Start
-		{
-			start = TRUE;
-		}
-		else if( StrCmp( argv[ i ], TEXT("-server") ) == 0 )		// Server
-		{
-			err = RunDirect( argc, argv );
-			if( err )
-			{
-				ReportStatus( EVENTLOG_ERROR_TYPE, "run service directly failed (%d)\n", err );
-			}
-			goto exit;
-		}
-		else if( StrCmp( argv[ i ], TEXT("-q") ) == 0 )			// Quiet Mode (toggle)
-		{
-			gServiceQuietMode = !gServiceQuietMode;
-		}
-		else if( ( StrCmp( argv[ i ], TEXT("-help") ) == 0 ) || 	// Help
-				 ( StrCmp( argv[ i ], TEXT("-h") ) == 0 ) )
-		{
-			Usage();
-			err = 0;
-			break;
-		}
-		else
-		{
-			Usage();
-			err = kParamErr;
-			break;
-		}
-	}
-	
-	// Start the service dispatcher if requested. This does not return until all services have terminated. If any 
-	// global initialization is needed, it should be done before starting the service dispatcher, but only if it 
-	// will take less than 30 seconds. Otherwise, use a separate thread for it and start the dispatcher immediately.
-	
-	if( start )
-	{
-		ok = StartServiceCtrlDispatcher( gServiceDispatchTable );
-		err = translate_errno( ok, (OSStatus) GetLastError(), kInUseErr );
-		if( err != kNoErr )
-		{
-			ReportStatus( EVENTLOG_ERROR_TYPE, "start service dispatcher failed (%d)\n", err );
-			goto exit;
-		}
-	}
-	err = 0;
-	
-exit:
-	dlog( kDebugLevelTrace, DEBUG_NAME "exited (%d %m)\n", err, err );
-	_CrtDumpMemoryLeaks();
-	return( (int) err );
-}
-
-//===========================================================================================================================
-//	Usage
-//===========================================================================================================================
-
-static void	Usage( void )
-{
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "mDNSResponder 1.0d1\n" );
-	fprintf( stderr, "\n" );
-	fprintf( stderr, "    <no args>    Runs the service normally\n" );
-	fprintf( stderr, "    -install     Creates the service and starts it\n" );
-	fprintf( stderr, "    -remove      Stops the service and deletes it\n" );
-	fprintf( stderr, "    -start       Starts the service dispatcher after processing all other arguments\n" );
-	fprintf( stderr, "    -server      Runs the service directly as a server (for debugging)\n" );
-	fprintf( stderr, "    -q           Toggles Quiet Mode (no events or output)\n" );
-	fprintf( stderr, "    -remote      Allow remote connections\n" );
-	fprintf( stderr, "    -cache n     Number of mDNS cache entries (defaults to %d)\n", kDNSServiceCacheEntryCountDefault );
-	fprintf( stderr, "    -h[elp]      Display Help/Usage\n" );
-	fprintf( stderr, "\n" );
-}
-
-//===========================================================================================================================
-//	ConsoleControlHandler
-//===========================================================================================================================
-
-static BOOL WINAPI	ConsoleControlHandler( DWORD inControlEvent )
-{
-	BOOL			handled;
-	OSStatus		err;
-	
-	handled = FALSE;
-	switch( inControlEvent )
-	{
-		case CTRL_C_EVENT:
-		case CTRL_BREAK_EVENT:
-		case CTRL_CLOSE_EVENT:
-		case CTRL_LOGOFF_EVENT:
-		case CTRL_SHUTDOWN_EVENT:
-			err = ServiceSpecificStop();
-			require_noerr( err, exit );
-			
-			handled = TRUE;
-			break;
-		
-		default:
-			break;
-	}
-	
-exit:
-	return( handled );
-}
-
-//===========================================================================================================================
-//	InstallService
-//===========================================================================================================================
-
-static OSStatus	InstallService( LPCTSTR inName, LPCTSTR inDisplayName, LPCTSTR inDescription, LPCTSTR inPath )
-{
-	OSStatus		err;
-	SC_HANDLE		scm;
-	SC_HANDLE		service;
-	BOOL			ok;
-	TCHAR			fullPath[ MAX_PATH ];
-	TCHAR *			namePtr;
-	DWORD			size;
-	
-	scm		= NULL;
-	service = NULL;
-	
-	// Get a full path to the executable since a relative path may have been specified.
-	
-	size = GetFullPathName( inPath, MAX_PATH, fullPath, &namePtr );
-	err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
-	require_noerr( err, exit );
-	
-	// Create the service and start it.
-	
-	scm = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
-	err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr );
-	require_noerr( err, exit );
-	
-	service = CreateService( scm, inName, inDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_SHARE_PROCESS, 
-							 SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, fullPath, NULL, NULL, kServiceDependencies, 
-							 NULL, NULL );
-	err = translate_errno( service, (OSStatus) GetLastError(), kDuplicateErr );
-	require_noerr( err, exit );
-
-	err = SetServiceParameters();
-	check_noerr( err );
-	
-	if( inDescription )
-	{
-		err = SetServiceInfo( scm, inName, inDescription );
-		check_noerr( err );
-	}
-
-	ok = StartService( service, 0, NULL );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kInUseErr );
-	require_noerr( err, exit );
-	
-	ReportStatus( EVENTLOG_SUCCESS, "installed service\n" );
-	err = kNoErr;
-	
-exit:
-	if( service )
-	{
-		CloseServiceHandle( service );
-	}
-	if( scm )
-	{
-		CloseServiceHandle( scm );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	RemoveService
-//===========================================================================================================================
-
-static OSStatus	RemoveService( LPCTSTR inName )
-{
-	OSStatus			err;
-	SC_HANDLE			scm;
-	SC_HANDLE			service;
-	BOOL				ok;
-	SERVICE_STATUS		status;
-	
-	scm		= NULL;
-	service = NULL;
-	
-	// Open a connection to the service.
-	
-	scm = OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
-	err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr );
-	require_noerr( err, exit );
-	
-	service = OpenService( scm, inName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE );
-	err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr );
-	require_noerr( err, exit );
-	
-	// Stop the service, if it is not already stopped, then delete it.
-	
-	ok = QueryServiceStatus( service, &status );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr );
-	require_noerr( err, exit );
-	
-	if( status.dwCurrentState != SERVICE_STOPPED )
-	{
-		ok = ControlService( service, SERVICE_CONTROL_STOP, &status );
-		check_translated_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr );
-	}
-	
-	ok = DeleteService( service );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kDeletedErr );
-	require_noerr( err, exit );
-		
-	ReportStatus( EVENTLOG_SUCCESS, "Removed service\n" );
-	err = ERROR_SUCCESS;
-	
-exit:
-	if( service )
-	{
-		CloseServiceHandle( service );
-	}
-	if( scm )
-	{
-		CloseServiceHandle( scm );
-	}
-	return( err );
-}
-
-
-
-//===========================================================================================================================
-//	SetServiceParameters
-//===========================================================================================================================
-
-static OSStatus SetServiceParameters()
-{
-	DWORD 			value;
-	DWORD			valueLen = sizeof(DWORD);
-	DWORD			type;
-	OSStatus		err;
-	HKEY			key;
-
-	key = NULL;
-
-	//
-	// Add/Open Parameters section under service entry in registry
-	//
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode, &key );
-	require_noerr( err, exit );
-	
-	//
-	// If the value isn't already there, then we create it
-	//
-	err = RegQueryValueEx(key, kServiceManageLLRouting, 0, &type, (LPBYTE) &value, &valueLen);
-
-	if (err != ERROR_SUCCESS)
-	{
-		value = 1;
-
-		err = RegSetValueEx( key, kServiceManageLLRouting, 0, REG_DWORD, (const LPBYTE) &value, sizeof(DWORD) );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return( err );
-}
-
-
-
-//===========================================================================================================================
-//	GetServiceParameters
-//===========================================================================================================================
-
-static OSStatus GetServiceParameters()
-{
-	DWORD 			value;
-	DWORD			valueLen;
-	DWORD			type;
-	OSStatus		err;
-	HKEY			key;
-
-	key = NULL;
-
-	//
-	// Add/Open Parameters section under service entry in registry
-	//
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode, &key );
-	require_noerr( err, exit );
-	
-	valueLen = sizeof(DWORD);
-	err = RegQueryValueEx(key, kServiceManageLLRouting, 0, &type, (LPBYTE) &value, &valueLen);
-	if (err == ERROR_SUCCESS)
-	{
-		gServiceManageLLRouting = (value) ? true : false;
-	}
-
-	valueLen = sizeof(DWORD);
-	err = RegQueryValueEx(key, kServiceCacheEntryCount, 0, &type, (LPBYTE) &value, &valueLen);
-	if (err == ERROR_SUCCESS)
-	{
-		gServiceCacheEntryCount = value;
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	CheckFirewall
-//===========================================================================================================================
-
-static OSStatus CheckFirewall()
-{
-	DWORD 					value;
-	DWORD					valueLen;
-	DWORD					type;
-	ENUM_SERVICE_STATUS	*	lpService = NULL;
-	SC_HANDLE				sc = NULL;
-	HKEY					key = NULL;
-	BOOL					ok;
-	DWORD					bytesNeeded = 0;
-	DWORD					srvCount;
-	DWORD					resumeHandle = 0;
-	DWORD					srvType;
-	DWORD					srvState;
-	DWORD					dwBytes = 0;
-	DWORD					i;
-	BOOL					isRunning = FALSE;
-	OSStatus				err = kUnknownErr;
-	
-	// Check to see if the firewall service is running.  If it isn't, then
-	// we want to return immediately
-
-	sc = OpenSCManager( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
-	err = translate_errno( sc, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	srvType		=	SERVICE_WIN32;
-	srvState	=	SERVICE_STATE_ALL;
-
-	for ( ;; )
-	{
-		// Call EnumServicesStatus using the handle returned by OpenSCManager
-
-		ok = EnumServicesStatus ( sc, srvType, srvState, lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle );
-
-		if ( ok || ( GetLastError() != ERROR_MORE_DATA ) )
-		{
-			break;
-		}
-
-		if ( lpService )
-		{
-			free( lpService );
-		}
-
-		dwBytes = bytesNeeded;
-
-		lpService = ( ENUM_SERVICE_STATUS* ) malloc( dwBytes );
-		require_action( lpService, exit, err = mStatus_NoMemoryErr );
-	}
-
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	for ( i = 0; i < srvCount; i++ )
-	{
-		if ( wcscmp( lpService[i].lpServiceName, L"SharedAccess" ) == 0 )
-		{
-			if ( lpService[i].ServiceStatus.dwCurrentState == SERVICE_RUNNING )
-			{
-				isRunning = TRUE;
-			}
-
-			break;
-		}
-	}
-
-	require_action( isRunning, exit, err = kUnknownErr );
-
-	// Check to see if we've managed the firewall.
-	// This package might have been installed, then
-	// the OS was upgraded to SP2 or above.  If that's
-	// the case, then we need to manipulate the firewall
-	// so networking works correctly.
-
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode, &key );
-	require_noerr( err, exit );
-
-	valueLen = sizeof(DWORD);
-	err = RegQueryValueEx(key, kServiceManageFirewall, 0, &type, (LPBYTE) &value, &valueLen);
-	
-	if ((err != ERROR_SUCCESS) || (value == 0))
-	{
-		wchar_t	fullPath[ MAX_PATH ];
-		DWORD	size;
-
-		// Get a full path to the executable
-
-		size = GetModuleFileNameW( NULL, fullPath, MAX_PATH );
-		err = translate_errno( size > 0, (OSStatus) GetLastError(), kPathErr );
-		require_noerr( err, exit );
-
-		err = mDNSAddToFirewall(fullPath, kServiceFirewallName);
-		require_noerr( err, exit );
-
-		value = 1;
-		err = RegSetValueEx( key, kServiceManageFirewall, 0, REG_DWORD, (const LPBYTE) &value, sizeof( DWORD ) );
-		require_noerr( err, exit );
-	}
-	
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-	
-	if ( lpService )
-	{
-		free( lpService );
-	}
-
-	if ( sc )
-	{
-		CloseServiceHandle ( sc );
-	}
-
-	return( err );
-}
-
-
-
-//===========================================================================================================================
-//	SetServiceInfo
-//===========================================================================================================================
-
-static OSStatus	SetServiceInfo( SC_HANDLE inSCM, LPCTSTR inServiceName, LPCTSTR inDescription )
-{
-	OSStatus				err;
-	SC_LOCK					lock;
-	SC_HANDLE				service;
-	SERVICE_DESCRIPTION		description;
-	SERVICE_FAILURE_ACTIONS	actions;
-	SC_ACTION				action;
-	BOOL					ok;
-	
-	check( inServiceName );
-	check( inDescription );
-	
-	lock 	= NULL;
-	service	= NULL;
-	
-	// Open the database (if not provided) and lock it to prevent other access while re-configuring.
-	
-	if( !inSCM )
-	{
-		inSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
-		err = translate_errno( inSCM, (OSStatus) GetLastError(), kOpenErr );
-		require_noerr( err, exit );
-	}
-	
-	lock = LockServiceDatabase( inSCM );
-	err = translate_errno( lock, (OSStatus) GetLastError(), kInUseErr );
-	require_noerr( err, exit );
-	
-	// Open a handle to the service. 
-
-	service = OpenService( inSCM, inServiceName, SERVICE_CHANGE_CONFIG|SERVICE_START );
-	err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr );
-	require_noerr( err, exit );
-	
-	// Change the description.
-	
-	description.lpDescription = (LPTSTR) inDescription;
-	ok = ChangeServiceConfig2( service, SERVICE_CONFIG_DESCRIPTION, &description );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr );
-	require_noerr( err, exit );
-	
-	actions.dwResetPeriod	=	INFINITE;
-	actions.lpRebootMsg		=	NULL;
-	actions.lpCommand		=	NULL;
-	actions.cActions		=	1;
-	actions.lpsaActions		=	&action;
-	action.Delay			=	500;
-	action.Type				=	SC_ACTION_RESTART;
-
-	ok = ChangeServiceConfig2( service, SERVICE_CONFIG_FAILURE_ACTIONS, &actions );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kParamErr );
-	require_noerr( err, exit );
-	
-	err = ERROR_SUCCESS;
-	
-exit:
-	// Close the service and release the lock.
-	
-	if( service )
-	{
-		CloseServiceHandle( service );
-	}
-	if( lock )
-	{
-		UnlockServiceDatabase( lock ); 
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	ReportStatus
-//===========================================================================================================================
-
-static void	ReportStatus( int inType, const char *inFormat, ... )
-{
-	if( !gServiceQuietMode )
-	{
-		va_list		args;
-		
-		va_start( args, inFormat );
-		if( gServiceEventSource )
-		{
-			char				s[ 1024 ];
-			BOOL				ok;
-			const char *		array[ 1 ];
-			
-			vsnprintf( s, sizeof( s ), inFormat, args );
-			array[ 0 ] = s;
-			ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, MDNSRESPONDER_LOG, NULL, 1, 0, array, NULL );
-			check_translated_errno( ok, GetLastError(), kUnknownErr );
-		}
-		else
-		{
-			int		n;
-			
-			n = vfprintf( stderr, inFormat, args );
-			check( n >= 0 );
-		}
-		va_end( args );
-	}
-}
-
-//===========================================================================================================================
-//	RunDirect
-//===========================================================================================================================
-
-mDNSlocal unsigned WINAPI
-RunDirectMain(LPVOID inParam)
-{
-	DEBUG_UNUSED(inParam);
-
-	RunDirect(0, NULL);
-	SetEvent(gDNSThreadQuitEvent);
-	_endthreadex(0);
-	return 0;
-}
-
-#if _DEBUG
-const DWORD MS_VC_EXCEPTION = 0x406D1388;
-
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
-	DWORD dwType;     // Must be 0x1000.
-	LPCSTR szName;    // Pointer to name (in user addr space).
-	DWORD dwThreadID; // Thread ID (-1=caller thread).
-	DWORD dwFlags;    // Reserved for future use, must be zero.
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-static void SetThreadName(DWORD dwThreadID, const char* threadName)
-{
-	THREADNAME_INFO info;
-	info.dwType = 0x1000;
-	info.szName = threadName;
-	info.dwThreadID = dwThreadID;
-	info.dwFlags = 0;
-#pragma warning(push)
-#pragma warning(disable: 6320 6322)
-	__try {
-		RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
-	}
-	__except (EXCEPTION_EXECUTE_HANDLER) {
-	}
-#pragma warning(pop)
-}
-#endif
-
-int DNSSD_API DNSServiceStart()
-{
-	OSStatus err = kNoErr;
-	unsigned int threadAddr;
-
-	if (!gDNSThreadStopEvent)
-	{
-		gDNSThreadStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-		require_action(gDNSThreadStopEvent != NULL, exit, err = GetLastError());
-	}
-
-	if (!gDNSThreadQuitEvent)
-	{
-		gDNSThreadQuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-		require_action(gDNSThreadQuitEvent != NULL, exit, err = GetLastError());
-	}
-
-	if (gDNSThread == NULL)
-	{
-		gDNSThread = (HANDLE)_beginthreadex(NULL, 0, RunDirectMain, NULL, 0, &threadAddr);
-		require_action(gDNSThread != NULL, exit, err = GetLastError());
-
-#if _DEBUG
-		SetThreadName(threadAddr, "mDNSResponder");
-#endif
-	}
-
-exit:
-	return err;
-}
-
-
-void DNSSD_API DNSServiceStop()
-{
-	dlog(kDebugLevelTrace, DEBUG_NAME "tearing down DNS Service thread\n");
-	SetEvent(gDNSThreadStopEvent);
-	if (WaitForSingleObject(gDNSThreadQuitEvent, 5 * 1000) == WAIT_OBJECT_0)
-	{
-		if (gDNSThreadQuitEvent)
-		{
-			CloseHandle(gDNSThreadQuitEvent);
-			gDNSThreadQuitEvent = NULL;
-		}
-
-		if (gDNSThreadStopEvent)
-		{
-			CloseHandle(gDNSThreadStopEvent);
-			gDNSThreadStopEvent = NULL;
-		}
-	}
-}
-
-
-//===========================================================================================================================
-//	RunDirect
-//===========================================================================================================================
-
-int	RunDirect( int argc, LPTSTR argv[] )
-{
-	OSStatus	err;
-	BOOL        initialized;
-	BOOL        ok;
-	
-	initialized = FALSE;
-
-	err = SetupServiceEvents();
-	require_noerr( err, exit );
-
-	// Install a Console Control Handler to handle things like control-c signals.
-	
-	ok = SetConsoleCtrlHandler( ConsoleControlHandler, TRUE );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	err = ServiceSpecificInitialize( argc, argv );
-	require_noerr( err, exit );
-	initialized = TRUE;
-	
-	// Run the service. This does not return until the service quits or is stopped.
-	
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Running service directly\n" );
-	
-	err = ServiceSpecificRun( argc, argv );
-	require_noerr( err, exit );
-	
-	// Clean up.
-	
-exit:
-	if( initialized )
-	{
-		ServiceSpecificFinalize( argc, argv );
-	}
-
-	TearDownServiceEvents();
-
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	ServiceMain
-//===========================================================================================================================
-
-static void WINAPI ServiceMain( DWORD argc, LPTSTR argv[] )
-{
-	OSStatus		err;
-	BOOL			ok;
-
-	err = SetupServiceEvents();
-	require_noerr( err, exit );
-	
-	err = ServiceSetupEventLogging();
-	check_noerr( err );
-
-	err = GetServiceParameters();
-	check_noerr( err );
-	
-	// Initialize the service status and register the service control handler with the name of the service.
-	
-	gServiceStatus.dwServiceType 				= SERVICE_WIN32_SHARE_PROCESS;
-	gServiceStatus.dwCurrentState 				= 0;
-	gServiceStatus.dwControlsAccepted 			= SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_POWEREVENT;
-	gServiceStatus.dwWin32ExitCode 				= NO_ERROR;
-	gServiceStatus.dwServiceSpecificExitCode 	= NO_ERROR;
-	gServiceStatus.dwCheckPoint 				= 0;
-	gServiceStatus.dwWaitHint 					= 0;
-	
-	gServiceStatusHandle = RegisterServiceCtrlHandlerEx( argv[ 0 ], ServiceControlHandler, NULL );
-	err = translate_errno( gServiceStatusHandle, (OSStatus) GetLastError(), kInUseErr );
-	require_noerr( err, exit );
-	
-	// Mark the service as starting.
-
-	gServiceStatus.dwCurrentState 	= SERVICE_START_PENDING;
-	gServiceStatus.dwCheckPoint	 	= 0;
-	gServiceStatus.dwWaitHint 		= 5000;	// 5 seconds
-	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-	check_translated_errno( ok, GetLastError(), kParamErr );
-	
-	// Run the service. This does not return until the service quits or is stopped.
-	
-	err = ServiceRun( (int) argc, argv );
-	if( err != kNoErr )
-	{
-		gServiceStatus.dwWin32ExitCode				= ERROR_SERVICE_SPECIFIC_ERROR;
-		gServiceStatus.dwServiceSpecificExitCode 	= (DWORD) err;
-	}
-	
-	// Service-specific work is done so mark the service as stopped.
-	
-	gServiceStatus.dwCurrentState = SERVICE_STOPPED;
-	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-	check_translated_errno( ok, GetLastError(), kParamErr );
-	
-	// Note: The service status handle should not be closed according to Microsoft documentation.
-	
-exit:
-
-	if( gServiceEventSource )
-	{
-		ok = DeregisterEventSource( gServiceEventSource );
-		check_translated_errno( ok, GetLastError(), kUnknownErr );
-		gServiceEventSource = NULL;
-	}
-
-	TearDownServiceEvents();
-}
-
-//===========================================================================================================================
-//	ServiceSetupEventLogging
-//===========================================================================================================================
-
-static OSStatus	ServiceSetupEventLogging( void )
-{
-	OSStatus			err;
-	HKEY				key;
-	LPCTSTR				s;
-	DWORD				typesSupported;
-	TCHAR				path[ MAX_PATH ];
-	DWORD 				n;
-	
-	key = NULL;
-	
-	// Add/Open source name as a sub-key under the Application key in the EventLog registry key.
-
-	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") kServiceName;
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, s, &key );
-	require_noerr( err, exit );
-	
-	// Add the name to the EventMessageFile subkey.
-
-	path[ 0 ] = '\0';
-	GetModuleFileName( NULL, path, MAX_PATH );
-	n = (DWORD) ( ( StrLen( path ) + 1 ) * sizeof( TCHAR ) );
-	err = RegSetValueEx( key, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (const LPBYTE) path, n );
-	require_noerr( err, exit );
-	
-	// Set the supported event types in the TypesSupported subkey.
-	
-	typesSupported = 0 
-					 | EVENTLOG_SUCCESS
-					 | EVENTLOG_ERROR_TYPE
-					 | EVENTLOG_WARNING_TYPE
-					 | EVENTLOG_INFORMATION_TYPE
-					 | EVENTLOG_AUDIT_SUCCESS
-					 | EVENTLOG_AUDIT_FAILURE; 
-	err = RegSetValueEx( key, TEXT("TypesSupported"), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) );
-	require_noerr( err, exit );
-	
-	// Set up the event source.
-	
-	gServiceEventSource = RegisterEventSource( NULL, kServiceName );
-	err = translate_errno( gServiceEventSource, (OSStatus) GetLastError(), kParamErr );
-	require_noerr( err, exit );
-		
-exit:
-	if( key )
-	{
-		RegCloseKey( key );
-	}
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	ServiceControlHandler
-//===========================================================================================================================
-
-static DWORD WINAPI	ServiceControlHandler( DWORD inControl, DWORD inEventType, LPVOID inEventData, LPVOID inContext )
-{
-	BOOL		setStatus;
-	OSStatus	err;
-	BOOL		ok;
-
-	DEBUG_UNUSED( inEventData );
-	DEBUG_UNUSED( inContext );
-	
-	setStatus = TRUE;
-	switch( inControl )
-	{
-		case SERVICE_CONTROL_STOP:
-		case SERVICE_CONTROL_SHUTDOWN:
-			
-			dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: SERVICE_CONTROL_STOP|SERVICE_CONTROL_SHUTDOWN\n" );
-			
-			ServiceStop();
-			setStatus = FALSE;
-			break;
-		
-		case SERVICE_CONTROL_POWEREVENT:
-
-			if (inEventType == PBT_APMSUSPEND)
-			{
-				dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMSUSPEND\n" );
-
-				if ( gPowerSuspendEvent )
-				{
-					ok = SetEvent( gPowerSuspendEvent );
-					err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-					check_noerr( err );
-
-					switch ( WaitForSingleObject( gPowerSuspendAckEvent, 5 * 1000 ) )
-					{
-						case WAIT_OBJECT_0:
-						{
-							// No error
-						}
-						break;
-
-						case WAIT_TIMEOUT:
-						{
-							dlog( kDebugLevelError, DEBUG_NAME "Timed out waiting for acknowledgement of machine sleep\n" );
-							ReportStatus( EVENTLOG_ERROR_TYPE, "Timed out waiting for acknowledgement of machine sleep" );
-						}
-						break;
-
-						default:
-						{
-							dlog( kDebugLevelError, DEBUG_NAME "Error waiting for acknowledgement of machine sleep: %d", GetLastError() );
-							ReportStatus( EVENTLOG_ERROR_TYPE, "Error waiting for acknowledgement of machine sleep: %d", GetLastError() );
-						}
-						break;
-					}
-				}
-			}
-			else if (inEventType == PBT_APMRESUMESUSPEND)
-			{
-				dlog( kDebugLevelInfo, DEBUG_NAME "ServiceControlHandler: PBT_APMRESUMESUSPEND\n" );
-
-				if ( gPowerResumeEvent )
-				{
-					ok = SetEvent( gPowerResumeEvent );
-					err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-					check_noerr( err );
-				}
-			}
-		
-			break;
-
-		default:
-			dlog( kDebugLevelNotice, DEBUG_NAME "ServiceControlHandler: event (0x%08X)\n", inControl );
-			break;
-	}
-	
-	if( setStatus && gServiceStatusHandle )
-	{
-		ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-		check_translated_errno( ok, GetLastError(), kUnknownErr );
-	}
-
-	return NO_ERROR;
-}
-
-//===========================================================================================================================
-//	ServiceRun
-//===========================================================================================================================
-
-static OSStatus	ServiceRun( int argc, LPTSTR argv[] )
-{
-	OSStatus		err;
-	BOOL			initialized;
-	BOOL			ok;
-	
-	DEBUG_UNUSED( argc );
-	DEBUG_UNUSED( argv );
-	
-	initialized = FALSE;
-	
-	// <rdar://problem/5727548> Make the service as running before we call ServiceSpecificInitialize. We've
-	// had reports that some machines with McAfee firewall installed cause a problem with iTunes installation.
-	// We think that the firewall product is interferring with code in ServiceSpecificInitialize. So as a
-	// simple workaround, we'll mark us as running *before* we call ServiceSpecificInitialize. This will unblock
-	// any installers that are waiting for our state to change.
-
-	gServiceStatus.dwCurrentState = SERVICE_RUNNING;
-	ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-	check_translated_errno( ok, GetLastError(), kParamErr );
-
-	// Initialize the service-specific stuff
-	
-	while ( 1 )
-	{
-		DWORD ret;
-
-		ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service initializing" );
-
-		err = ServiceSpecificInitialize( argc, argv );
-
-		if ( !err )
-		{
-			ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service initialized" );
-			break;
-		}
-
-		ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service initialization failed with err %d. Waiting %d seconds to retry...", err, kWaitToRetry );
-
-		ret = WaitForSingleObject( gStopEvent, 1000 * kWaitToRetry );
-
-		if ( ret == WAIT_OBJECT_0 )
-		{
-			ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service received a stop event" );
-			goto exit;
-		}
-		else if ( ret == WAIT_OBJECT_0 + 1 )
-		{
-			ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service received a power suspend event" );
-		}
-		else if ( ret == WAIT_OBJECT_0 + 2 )
-		{
-			ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service received a power resume event" );
-		}
-		else if ( ret != WAIT_TIMEOUT )
-		{
-			ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service received an error in WaitForSingleObject() : %d, %d", ret, GetLastError() );
-			goto exit;
-		}
-	}
-
-	initialized = TRUE;
-	
-	err = CheckFirewall();
-	check_noerr( err );
-
-	if ( err )
-	{
-		gRetryFirewall = TRUE;
-	}
-	
-	// Run the service-specific stuff. This does not return until the service quits or is stopped.
-
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service started\n" );
-
-	err = ServiceSpecificRun( argc, argv );
-	require_noerr( err, exit );
-
-exit:
-
-	// Service stopped. Clean up and we're done.
-	
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Service stopped (%d)\n", err );
-	
-	if( initialized )
-	{
-		ServiceSpecificFinalize( argc, argv );
-	}
-	
-	return( err );
-}
-
-//===========================================================================================================================
-//	ServiceStop
-//===========================================================================================================================
-
-static void	ServiceStop( void )
-{
-	BOOL			ok;
-	OSStatus		err;
-	
-	// Signal the event to cause the service to exit.
-	
-	if( gServiceStatusHandle )
-	{
-		gServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
-		ok = SetServiceStatus( gServiceStatusHandle, &gServiceStatus );
-		check_translated_errno( ok, GetLastError(), kParamErr );
-	}
-		
-	err = ServiceSpecificStop();
-	check_noerr( err );
-}
-
-
-#if 0
-#pragma mark -
-#pragma mark == Service Specific ==
-#endif
-
-//===========================================================================================================================
-//	ServiceSpecificInitialize
-//===========================================================================================================================
-
-static OSStatus	ServiceSpecificInitialize( int argc, LPTSTR argv[] )
-{
-	OSStatus err;
-	
-	DEBUG_UNUSED( argc );
-	DEBUG_UNUSED( argv );
-	
-	mDNSPlatformMemZero( &gMDNSRecord, sizeof gMDNSRecord);
-	mDNSPlatformMemZero( &gPlatformStorage, sizeof gPlatformStorage);
-
-	gPlatformStorage.reportStatusFunc = ReportStatus;
-
-	err = mDNS_Init( &gMDNSRecord, &gPlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses, CoreCallback, mDNS_Init_NoInitCallbackContext); 
-	require_noerr( err, exit);
-
-	err = SetupNotifications();
-	check_noerr( err );
-
-	err = udsserver_init(mDNSNULL, 0);
-	require_noerr( err, exit);
-
-	SetLLRoute( &gMDNSRecord );
-
-exit:
-	if( err != kNoErr )
-	{
-		ServiceSpecificFinalize( argc, argv );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	ServiceSpecificRun
-//===========================================================================================================================
-
-static OSStatus	ServiceSpecificRun( int argc, LPTSTR argv[] )
-{
-	mDNSBool done = mDNSfalse;
-	mStatus err = mStatus_NoError;
-	
-	DEBUG_UNUSED( argc );
-	DEBUG_UNUSED( argv );
-
-	err = SetupInterfaceList( &gMDNSRecord );
-	check( !err );
-
-	err = uDNS_SetupDNSConfig( &gMDNSRecord );
-	check( !err );
-
-	while( !done )
-	{
-#ifdef WIN32_CENTENNIAL
-		DWORD ret = WaitForSingleObjectEx(gDNSThreadStopEvent, FALSE, 0);
-		if (ret != WAIT_TIMEOUT)
-		{
-			if (ret == kDNSStopEvent)
-			{
-				break;
-			}
-		}
-#endif
-		static mDNSs32 RepeatedBusy = 0;	
-		mDNSs32 nextTimerEvent;
-
-		// Give the mDNS core a chance to do its work and determine next event time.
-
-		nextTimerEvent = udsserver_idle( mDNS_Execute( &gMDNSRecord ) - mDNS_TimeNow( &gMDNSRecord ) );
-
-		if      ( nextTimerEvent < 0)					nextTimerEvent = 0;
-		else if ( nextTimerEvent > (0x7FFFFFFF / 1000))	nextTimerEvent = 0x7FFFFFFF / mDNSPlatformOneSecond;
-		else											nextTimerEvent = ( nextTimerEvent * 1000) / mDNSPlatformOneSecond;
-
-		// Debugging sanity check, to guard against CPU spins
-			
-		if ( nextTimerEvent > 0 )
-		{
-			RepeatedBusy = 0;
-		}
-		else
-		{
-			nextTimerEvent = 1;
-
-			if ( ++RepeatedBusy >= mDNSPlatformOneSecond )
-			{
-				ShowTaskSchedulingError( &gMDNSRecord );
-				RepeatedBusy = 0;
-			}
-		}
-
-		if ( gMDNSRecord.ShutdownTime )
-		{
-			mDNSs32 now = mDNS_TimeNow( &gMDNSRecord );
-
-			if ( mDNS_ExitNow( &gMDNSRecord, now ) )
-			{
-				mDNS_FinalExit( &gMDNSRecord );
-				done = TRUE;
-				break;
-			}
-
-			if ( nextTimerEvent - gMDNSRecord.ShutdownTime >= 0 )
-			{
-				nextTimerEvent = gMDNSRecord.ShutdownTime;
-			}
-		}
-
-		err = mDNSPoll( nextTimerEvent );
-
-		if ( err )
-		{
-			Sleep( 3 * 1000 );
-				
-			err = SetupInterfaceList( &gMDNSRecord );
-			check( !err );
-
-			err = uDNS_SetupDNSConfig( &gMDNSRecord );
-			check( !err );
-				
-			break;
-		}
-	}
-
-	return ( err );
-}
-
-
-//===========================================================================================================================
-//	ServiceSpecificStop
-//===========================================================================================================================
-
-static OSStatus	ServiceSpecificStop( void )
-{
-	OSStatus    err;
-	BOOL        ok;
-
-#ifdef WIN32_CENTENNIAL
-	DNSServiceStop();
-#endif
-
-	ok = SetEvent(gStopEvent);
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-
-	return( err );
-}
-
-//===========================================================================================================================
-//	ServiceSpecificFinalize
-//===========================================================================================================================
-
-static void	ServiceSpecificFinalize( int argc, LPTSTR argv[] )
-{
-	DEBUG_UNUSED( argc );
-	DEBUG_UNUSED( argv );
-	
-	//
-	// clean up the notifications
-	//
-	TearDownNotifications();
-
-	//
-	// clean up loaded library
-	//
-
-	if( gIPHelperLibraryInstance )
-	{
-		gGetIpInterfaceEntryFunctionPtr = NULL;
-		
-		FreeLibrary( gIPHelperLibraryInstance );
-		gIPHelperLibraryInstance = NULL;
-	}
-}
-
-
-//===========================================================================================================================
-//	SetupServiceEvents
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupServiceEvents()
-{
-	mStatus err;
-	
-	// Stop Event
-
-	gStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gStopEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( err )
-	{
-		TearDownServiceEvents();
-	}
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	TearDownServiceNotifications
-//===========================================================================================================================
-
-mDNSlocal mStatus	TearDownServiceEvents()
-{
-	if ( gStopEvent )
-	{
-		CloseHandle( gStopEvent );
-		gStopEvent = NULL;
-	}
-
-	return mStatus_NoError;
-}
-
-
-//===========================================================================================================================
-//	SetupNotifications
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupNotifications()
-{
-	mStatus				err;
-	SocketRef			sock;
-	unsigned long		param;
-	int					inBuffer;
-	int					outBuffer;
-	DWORD				outSize;
-
-	require_action( gStopEvent, exit, err = kUnknownErr );
-	err = mDNSPollRegisterEvent( gStopEvent, StopNotification, NULL );
-	require_noerr( err, exit );
-
-	// Power Suspend
-
-	gPowerSuspendEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gPowerSuspendEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gPowerSuspendEvent, PowerSuspendNotification, NULL );
-	require_noerr( err, exit );
-
-	// Power Suspend Ack
-
-	gPowerSuspendAckEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-	err = translate_errno( gPowerSuspendAckEvent, ( mStatus ) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// Power Resume
-
-	gPowerResumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gPowerResumeEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gPowerResumeEvent, PowerResumeNotification, NULL );
-	require_noerr( err, exit );
-
-	// Register to listen for address list changes.
-	
-	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	gInterfaceListChangedSocket = sock;
-	
-	// Make the socket non-blocking so the WSAIoctl returns immediately with WSAEWOULDBLOCK. It will set the event 
-	// when a change to the interface list is detected.
-	
-	param = 1;
-	err = ioctlsocket( sock, FIONBIO, &param );
-	err = translate_errno( err == 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	inBuffer	= 0;
-	outBuffer	= 0;
-	err = WSAIoctl( sock, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
-	if( err < 0 )
-	{
-		check( errno_compat() == WSAEWOULDBLOCK );
-	}
-
-	err = mDNSPollRegisterSocket( sock, FD_ADDRESS_LIST_CHANGE, InterfaceListNotification, NULL );
-	require_noerr( err, exit );
-	
-	gDescChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-	err = translate_errno( gDescChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters"), 0, KEY_READ, &gDescKey);
-	check_translated_errno( err == 0, errno_compat(), kNameErr );
-
-	if ( gDescKey != NULL )
-	{
-		err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
-		require_noerr( err, exit );
-	}
-
-	err = mDNSPollRegisterEvent( gDescChangedEvent, ComputerDescriptionNotification, NULL );
-	require_noerr( err, exit );
-
-	// This will catch all changes to tcp/ip networking, including changes to the domain search list
-
-	gTcpipChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gTcpipChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &gTcpipKey );
-	require_noerr( err, exit );
-	err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE);
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gTcpipChangedEvent, TCPChangedNotification, NULL );
-	require_noerr( err, exit );
-
-	// This will catch all changes to ddns configuration
-
-	gDdnsChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gDdnsChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode TEXT("\\DynDNS\\Setup"), &gDdnsKey );
-	require_noerr( err, exit );
-	err = RegNotifyChangeKeyValue( gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gDdnsChangedEvent, DDNSChangedNotification, NULL );
-	require_noerr( err, exit );
-
-	// This will catch all changes to file sharing
-
-	gFileSharingChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-	err = translate_errno( gFileSharingChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	err = RegCreateKey( HKEY_CURRENT_USER, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), &gFileSharingKey );
-	
-	// Just to make sure that initialization doesn't fail on some old OS
-	// that doesn't have this key, we'll only add the notification if
-	// the key exists.
-
-	if ( !err )
-	{
-		err = RegNotifyChangeKeyValue( gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
-		require_noerr( err, exit );
-		err = mDNSPollRegisterEvent( gFileSharingChangedEvent, FileSharingChangedNotification, NULL );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = mStatus_NoError;
-	}
-
-	// This will catch changes to the Windows firewall
-
-	gFirewallChangedEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-	err = translate_errno( gFirewallChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-
-	// Just to make sure that initialization doesn't fail on some old OS
-	// that doesn't have this key, we'll only add the notification if
-	// the key exists.
-
-	err = RegCreateKey( HKEY_CURRENT_USER, TEXT("SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules"), &gFirewallKey );
-	
-	if ( !err )
-	{
-		err = RegNotifyChangeKeyValue( gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
-		require_noerr( err, exit );
-		err = mDNSPollRegisterEvent( gFirewallChangedEvent, FirewallChangedNotification, NULL );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		err = mStatus_NoError;
-	}
-
-	// This will catch all changes to advertised services configuration
-
-	gAdvertisedServicesChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-	err = translate_errno( gAdvertisedServicesChangedEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode TEXT("\\Services"), &gAdvertisedServicesKey );
-	require_noerr( err, exit );
-	err = RegNotifyChangeKeyValue( gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gAdvertisedServicesChangedEvent, AdvertisedServicesChangedNotification, NULL );
-	require_noerr( err, exit );
-
-	// SPSWakeup timer
-
-	gSPSWakeupEvent = CreateWaitableTimer( NULL, FALSE, NULL );
-	err = translate_errno( gSPSWakeupEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gSPSWakeupEvent, SPSWakeupNotification, NULL );
-	require_noerr( err, exit );
-
-	// SPSSleep timer
-
-	gSPSSleepEvent = CreateWaitableTimer( NULL, FALSE, NULL );
-	err = translate_errno( gSPSSleepEvent, (mStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	err = mDNSPollRegisterEvent( gSPSSleepEvent, SPSSleepNotification, NULL );
-	require_noerr( err, exit );
-
-exit:
-	if( err )
-	{
-		TearDownNotifications();
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	TearDownNotifications
-//===========================================================================================================================
-
-mDNSlocal mStatus	TearDownNotifications()
-{
-	if( IsValidSocket( gInterfaceListChangedSocket ) )
-	{
-		mDNSPollUnregisterSocket( gInterfaceListChangedSocket );
-
-		close_compat( gInterfaceListChangedSocket );
-		gInterfaceListChangedSocket = kInvalidSocketRef;
-	}
-
-	if ( gDescChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gDescChangedEvent );
-		CloseHandle( gDescChangedEvent );
-		gDescChangedEvent = NULL;
-	}
-
-	if ( gDescKey != NULL )
-	{
-		RegCloseKey( gDescKey );
-		gDescKey = NULL;
-	}
-
-	if ( gTcpipChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gTcpipChangedEvent );
-		CloseHandle( gTcpipChangedEvent );
-		gTcpipChangedEvent = NULL;
-	}
-
-	if ( gDdnsChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gDdnsChangedEvent );
-		CloseHandle( gDdnsChangedEvent );
-		gDdnsChangedEvent = NULL;
-	}
-
-	if ( gDdnsKey != NULL )
-	{
-		RegCloseKey( gDdnsKey );
-		gDdnsKey = NULL;
-	}
-
-	if ( gFileSharingChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gFileSharingChangedEvent );
-		CloseHandle( gFileSharingChangedEvent );
-		gFileSharingChangedEvent = NULL;
-	}
-
-	if ( gFileSharingKey != NULL )
-	{
-		RegCloseKey( gFileSharingKey );
-		gFileSharingKey = NULL;
-	}
-
-	if ( gFirewallChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gFirewallChangedEvent );
-		CloseHandle( gFirewallChangedEvent );
-		gFirewallChangedEvent = NULL;
-	}
-
-	if ( gFirewallKey != NULL )
-	{
-		RegCloseKey( gFirewallKey );
-		gFirewallKey = NULL;
-	}
-
-	if ( gAdvertisedServicesChangedEvent != NULL )
-	{
-		mDNSPollUnregisterEvent( gAdvertisedServicesChangedEvent );
-		CloseHandle( gAdvertisedServicesChangedEvent );
-		gAdvertisedServicesChangedEvent = NULL;
-	}
-
-	if ( gAdvertisedServicesKey != NULL )
-	{
-		RegCloseKey( gAdvertisedServicesKey );
-		gAdvertisedServicesKey = NULL;
-	}
-
-	if ( gSPSWakeupEvent )
-	{
-		mDNSPollUnregisterEvent( gSPSWakeupEvent );
-		CloseHandle( gSPSWakeupEvent );
-		gSPSWakeupEvent = NULL;
-	}
-
-	if ( gSPSSleepEvent )
-	{
-		mDNSPollUnregisterEvent( gSPSSleepEvent );
-		CloseHandle( gSPSSleepEvent );
-		gSPSSleepEvent = NULL;
-	}
-
-	if ( gPowerResumeEvent )
-	{
-		mDNSPollUnregisterEvent( gPowerResumeEvent );
-		CloseHandle( gPowerResumeEvent );
-		gPowerResumeEvent = NULL;
-	}
-
-	if ( gPowerSuspendAckEvent )
-	{
-		CloseHandle( gPowerSuspendAckEvent );
-		gPowerSuspendAckEvent = NULL;
-	}
-
-	if ( gPowerSuspendEvent )
-	{
-		mDNSPollUnregisterEvent( gPowerSuspendEvent );
-		CloseHandle( gPowerSuspendEvent );
-		gPowerSuspendEvent = NULL;
-	}
-
-	if ( gStopEvent )
-	{
-		mDNSPollUnregisterEvent( gStopEvent );
-	}
-
-	return( mStatus_NoError );
-}
-
-
-mDNSlocal void CALLBACK
-StopNotification( HANDLE event, void *context )
-{
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	dlog( kDebugLevelVerbose, DEBUG_NAME "stopping...\n" );
-	udsserver_exit();
-	mDNS_StartExit( &gMDNSRecord );
-}
-
-
-mDNSlocal void CALLBACK
-PowerSuspendNotification( HANDLE event, void * context )
-{
-	LARGE_INTEGER	timeout;
-	BOOL			ok;
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	dlog( kDebugLevelInfo, DEBUG_NAME "PowerSuspendNotification\n" );
-
-	gMDNSRecord.SystemWakeOnLANEnabled = SystemWakeForNetworkAccess( &timeout );
-				
-	if ( gMDNSRecord.SystemWakeOnLANEnabled )
-	{
-		ok = SetWaitableTimer( gSPSWakeupEvent, &timeout, 0, NULL, NULL, TRUE );
-		check( ok );
-	}
-
-	mDNSCoreMachineSleep(&gMDNSRecord, TRUE);
-
-	ok = SetEvent( gPowerSuspendAckEvent );
-
-	if ( !ok )
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "PowerSuspendNotification: error while setting acknowledgement: %d", GetLastError() );
-		ReportStatus( EVENTLOG_ERROR_TYPE, "PowerSuspendNotification: error while setting acknowledgement: %d", GetLastError() );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-PowerResumeNotification( HANDLE event, void * context )
-{
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	dlog( kDebugLevelInfo, DEBUG_NAME "PowerResumeNotification\n" );
-
-	if ( gSPSWakeupEvent )
-	{
-		CancelWaitableTimer( gSPSWakeupEvent );
-	}
-
-	if ( gSPSSleepEvent )
-	{
-		CancelWaitableTimer( gSPSSleepEvent );
-	}
-
-	mDNSCoreMachineSleep(&gMDNSRecord, FALSE);
-}
-
-
-
-mDNSlocal void CALLBACK
-InterfaceListNotification( SOCKET socket, LPWSANETWORKEVENTS event, void *context )
-{
-	int		inBuffer;
-	int		outBuffer;
-	DWORD	outSize;
-	int		err;
-
-	DEBUG_UNUSED( socket );
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	// It would be nice to come up with a more elegant solution to this, but it seems that
-	// GetAdaptersAddresses doesn't always stay in sync after network changed events.  So as
-	// as a simple workaround, we'll pause for a couple of seconds before processing the change.
-
-	// We arrived at 2 secs by trial and error. We could reproduce the problem after sleeping
-	// for 500 msec and 750 msec, but couldn't after sleeping for 1 sec.  We added another
-	// second on top of that to account for machine load or some other exigency.
-
-	Sleep( 2000 );
-
-	// Interface list changed event. Break out of the inner loop to re-setup the wait list.
-					
-	InterfaceListDidChange( &gMDNSRecord );
-
-	// reset the event handler
-	inBuffer	= 0;
-	outBuffer	= 0;
-	err = WSAIoctl( gInterfaceListChangedSocket, SIO_ADDRESS_LIST_CHANGE, &inBuffer, 0, &outBuffer, 0, &outSize, NULL, NULL );
-	if( err < 0 )
-	{
-		check( errno_compat() == WSAEWOULDBLOCK );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-ComputerDescriptionNotification( HANDLE event, void *context )
-{
-	// The computer description might have changed
-					
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	ComputerDescriptionDidChange( &gMDNSRecord );
-	udsserver_handle_configchange( &gMDNSRecord );
-
-	// and reset the event handler
-	if ( ( gDescKey != NULL ) && ( gDescChangedEvent != NULL ) )
-	{
-		int err = RegNotifyChangeKeyValue( gDescKey, TRUE, REG_NOTIFY_CHANGE_LAST_SET, gDescChangedEvent, TRUE);
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-TCPChangedNotification( HANDLE event, void *context )
-{
-	// The TCP/IP might have changed
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	TCPIPConfigDidChange( &gMDNSRecord );
-	udsserver_handle_configchange( &gMDNSRecord );
-
-	// and reset the event handler
-
-	if ( ( gTcpipKey != NULL ) && ( gTcpipChangedEvent ) )
-	{
-		int err = RegNotifyChangeKeyValue( gTcpipKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gTcpipChangedEvent, TRUE );
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-DDNSChangedNotification( HANDLE event, void *context )
-{
-	// The DynDNS config might have changed
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	DynDNSConfigDidChange( &gMDNSRecord );
-	udsserver_handle_configchange( &gMDNSRecord );
-
-	// and reset the event handler
-
-	if ((gDdnsKey != NULL) && (gDdnsChangedEvent))
-	{
-		int err = RegNotifyChangeKeyValue(gDdnsKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gDdnsChangedEvent, TRUE);
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-FileSharingChangedNotification( HANDLE event, void *context )
-{
-	// File sharing changed
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	FileSharingDidChange( &gMDNSRecord );
-
-	// and reset the event handler
-
-	if ((gFileSharingKey != NULL) && (gFileSharingChangedEvent))
-	{
-		int err = RegNotifyChangeKeyValue(gFileSharingKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFileSharingChangedEvent, TRUE);
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-FirewallChangedNotification( HANDLE event, void *context )
-{
-	// Firewall configuration changed
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	FirewallDidChange( &gMDNSRecord );
-
-	// and reset the event handler
-
-	if ((gFirewallKey != NULL) && (gFirewallChangedEvent))
-	{
-		int err = RegNotifyChangeKeyValue(gFirewallKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gFirewallChangedEvent, TRUE);
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-AdvertisedServicesChangedNotification( HANDLE event, void *context )
-{
-	// Ultimately we'll want to manage multiple services, but right now the only service
-	// we'll be managing is SMB.
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	FileSharingDidChange( &gMDNSRecord );
-
-	// and reset the event handler
-
-	if ( ( gAdvertisedServicesKey != NULL ) && ( gAdvertisedServicesChangedEvent ) )
-	{
-		int err = RegNotifyChangeKeyValue(gAdvertisedServicesKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, gAdvertisedServicesChangedEvent, TRUE);
-		check_noerr( err );
-		DEBUG_UNUSED( err );
-	}
-}
-
-
-mDNSlocal void CALLBACK
-SPSWakeupNotification( HANDLE event, void *context )
-{
-	LARGE_INTEGER timeout;
-
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Maintenance wake" );
-
-	timeout.QuadPart  = kSPSMaintenanceWakePeriod;
-	timeout.QuadPart *= kSecondsTo100NSUnits;
-
-	SetWaitableTimer( gSPSSleepEvent, &timeout, 0, NULL, NULL, TRUE );
-}
-
-
-mDNSlocal void CALLBACK
-SPSSleepNotification( HANDLE event, void *context )
-{
-	DEBUG_UNUSED( event );
-	DEBUG_UNUSED( context );
-
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "Returning to sleep after maintenance wake" );
-
-	// Calling SetSuspendState() doesn't invoke our sleep handlers, so we'll
-	// call HandlePowerSuspend() explicity.  This will reset the 
-	// maintenance wake timers.
-
-	PowerSuspendNotification( gPowerSuspendEvent, NULL );
-	SetSuspendState( FALSE, FALSE, FALSE );
-}
-
-
-//===========================================================================================================================
-//	CoreCallback
-//===========================================================================================================================
-
-static void
-CoreCallback(mDNS * const inMDNS, mStatus status)
-{
-	if (status == mStatus_ConfigChanged)
-	{
-		SetLLRoute( inMDNS );
-	}
-}
-
-
-//===========================================================================================================================
-//	UDSAcceptNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-UDSAcceptNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	( void ) sock;
-	( void ) event;
-	( void ) context;
-	
-	if ( gUDSCallback )
-	{
-		gUDSCallback( ( int ) gUDSSocket, context );
-	}
-}
-
-
-//===========================================================================================================================
-//	UDSReadNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-UDSReadNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	TCPSocket *tcpSock = ( TCPSocket* ) context;
-
-	( void ) sock;
-	( void ) event;
-
-	if ( tcpSock )
-	{
-		tcpSock->udsEventCallback( ( int ) tcpSock->fd, tcpSock->userContext );
-	}
-}
-
-
-//===========================================================================================================================
-//	udsSupportAddFDToEventLoop
-//===========================================================================================================================
-
-mStatus
-udsSupportAddFDToEventLoop( SocketRef fd, udsEventCallback callback, void *context, void **platform_data)
-{
-	mStatus err = mStatus_NoError;
-
-	// We are using some knowledge of what is being passed to us here.  If the fd is a listen socket,
-	// then the "context" parameter is NULL.  If it is an actual read/write socket, then the "context"
-	// parameter is not null.
-
-	if ( context )
-	{
-		TCPSocket * sock;
-
-		sock = malloc( sizeof( TCPSocket ) );
-		require_action( sock, exit, err = mStatus_NoMemoryErr );
-		mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
-
-		sock->fd				= (SOCKET) fd;
-		sock->udsEventCallback	= callback;
-		sock->userContext		= context;
-		sock->m					= &gMDNSRecord;
-
-		*platform_data = sock;
-
-		err = mDNSPollRegisterSocket( sock->fd, FD_READ | FD_CLOSE, UDSReadNotification, sock );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		gUDSSocket		= fd;
-		gUDSCallback	= callback;
-
-		err = mDNSPollRegisterSocket( gUDSSocket, FD_ACCEPT | FD_CLOSE, UDSAcceptNotification, NULL );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return err;
-}
-
-
-int
-udsSupportReadFD( SocketRef fd, char *buf, mDNSu32 len, int flags, void *platform_data )
-{
-	TCPSocket	*	sock;
-	mDNSBool		closed;
-	int				ret;
-
-	( void ) flags;
-
-	sock = ( TCPSocket* ) platform_data;
-	require_action( sock, exit, ret = -1 );
-	require_action( sock->fd == fd, exit, ret = -1 );
-
-	ret = mDNSPlatformReadTCP( sock, buf, len, &closed );
-
-	if ( closed )
-	{
-		ret = 0;
-	}
-	else if ( !ret && ( WSAGetLastError() == WSAEWOULDBLOCK ) )
-	{
-		// mDNSPlatformReadTCP will return 0 if it gets WSAEWOULDBLOCK, but
-		// that caller of this routine interprets that as close connection.
-		// We'll fix that by returning -1 in that case.
-
-		ret = -1;
-	}
-
-exit:
-
-	return ret;
-}
-
-
-mStatus
-udsSupportRemoveFDFromEventLoop( SocketRef fd, void *platform_data)		// Note: This also CLOSES the socket
-{
-	mStatus err = kNoErr;
-
-	mDNSPollUnregisterSocket( fd );
-
-	if ( platform_data != NULL )
-	{
-		TCPSocket * sock;
-
-		dlog( kDebugLevelInfo, DEBUG_NAME "session closed\n" );
-		sock = ( TCPSocket* ) platform_data;
-		check( sock->fd == fd );
-		mDNSPlatformTCPCloseConnection( sock );
-	}
-
-	return err;
-}
-
-
-mDNSexport void RecordUpdatedNiceLabel( mDNSs32 delay )
-{
-	(void)delay;
-	// No-op, for now
-}
-
-
-//===========================================================================================================================
-//	SystemWakeForNetworkAccess
-//===========================================================================================================================
-
-mDNSu8
-SystemWakeForNetworkAccess( LARGE_INTEGER * timeout )
-{
-	HKEY					key = NULL;
-	DWORD					dwSize;
-	DWORD					enabled;
-	mDNSu8					ok;
-	SYSTEM_POWER_STATUS		powerStatus;
-	time_t					startTime;
-	time_t					nextWakeupTime;
-	int						delta;
-	DWORD					err;
-
-	dlog( kDebugLevelInfo, DEBUG_NAME "SystemWakeForNetworkAccess\n" );
-
-	// Make sure we have a timer
-
-	require_action( gSPSWakeupEvent != NULL, exit, ok = FALSE );
-	require_action( gSPSSleepEvent != NULL, exit, ok = FALSE );
-
-	// Make sure the user enabled bonjour sleep proxy client 
-	
-	err = RegCreateKey( HKEY_CURRENT_USER, kServiceParametersNode L"\\Power Management", &key );
-	require_action( !err, exit, ok = FALSE );
-	dwSize = sizeof( DWORD );
-	err = RegQueryValueEx( key, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-	require_action( !err, exit, ok = FALSE );
-	require_action( enabled, exit, ok = FALSE );
-	
-	// Make sure machine is on AC power
-	
-	ok = ( mDNSu8 ) GetSystemPowerStatus( &powerStatus );
-	require_action( ok, exit, ok = FALSE );
-	require_action( powerStatus.ACLineStatus == AC_LINE_ONLINE, exit, ok = FALSE );
-
-	// Now make sure we have a network interface that does wake-on-lan
-
-	ok = ( mDNSu8 ) IsWOMPEnabled( &gMDNSRecord );
-	require_action( ok, exit, ok = FALSE );
-
-	// Now make sure we have advertised services. Doesn't make sense to
-	// enable sleep proxy if we have no multicast services that could
-	// potentially wake us up.
-
-	ok = ( mDNSu8 ) mDNSCoreHaveAdvertisedMulticastServices( &gMDNSRecord );
-	require_action( ok, exit, ok = FALSE );
-
-	// Calculate next wake up time
-
-	startTime		= time( NULL );					// Seconds since midnight January 1, 1970
-	nextWakeupTime	= startTime + ( 120 * 60 );		// 2 hours later
-	
-	if ( gMDNSRecord.p->nextDHCPLeaseExpires < nextWakeupTime )
-	{
-		nextWakeupTime = gMDNSRecord.p->nextDHCPLeaseExpires;
-	}
-
-	// Finally calculate the next relative wakeup time
-
-	delta = ( int )( ( ( double )( nextWakeupTime - startTime ) ) * 0.9 );
-	ReportStatus( EVENTLOG_INFORMATION_TYPE, "enabling sleep proxy client with next maintenance wake in %d seconds", delta );
-
-	// Convert seconds to 100 nanosecond units expected by SetWaitableTimer
-
-	timeout->QuadPart  = -delta;
-	timeout->QuadPart *= kSecondsTo100NSUnits;
-
-	ok = TRUE;
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return ok;
-}
-
-
-//===========================================================================================================================
-//	HaveRoute
-//===========================================================================================================================
-
-static bool
-HaveRoute( PMIB_IPFORWARDROW rowExtant, unsigned long addr, unsigned long metric )
-{
-	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
-	DWORD				dwSize			= 0;
-	BOOL				bOrder			= FALSE;
-	OSStatus			err;
-	bool				found			= false;
-	unsigned long int	i;
-
-	//
-	// Find out how big our buffer needs to be.
-	//
-	err = GetIpForwardTable(NULL, &dwSize, bOrder);
-	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
-
-	//
-	// Allocate the memory for the table
-	//
-	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
-	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
-  
-	//
-	// Now get the table.
-	//
-	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
-	require_noerr( err, exit );
-
-	//
-	// Search for the row in the table we want.
-	//
-	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
-	{
-		if ( ( pIpForwardTable->table[i].dwForwardDest == addr ) && ( !metric || ( pIpForwardTable->table[i].dwForwardMetric1 == metric ) ) )
-		{
-			memcpy( rowExtant, &(pIpForwardTable->table[i]), sizeof(*rowExtant) );
-			found = true;
-			break;
-		}
-	}
-
-exit:
-
-	if ( pIpForwardTable != NULL ) 
-	{
-		free(pIpForwardTable);
-	}
-	
-	return found;
-}
-
-
-//===========================================================================================================================
-//	IsValidAddress
-//===========================================================================================================================
-
-static bool
-IsValidAddress( const char * addr )
-{
-	return ( addr && ( strcmp( addr, "0.0.0.0" ) != 0 ) ) ? true : false;
-}	
-
-
-//===========================================================================================================================
-//	GetAdditionalMetric
-//===========================================================================================================================
-
-static ULONG
-GetAdditionalMetric( DWORD ifIndex )
-{
-	ULONG metric = 0;
-
-	if( !gIPHelperLibraryInstance )
-	{
-		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
-
-		gGetIpInterfaceEntryFunctionPtr = 
-				(GetIpInterfaceEntryFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetIpInterfaceEntry" );
-
-		if( !gGetIpInterfaceEntryFunctionPtr )
-		{		
-			BOOL ok;
-				
-			ok = FreeLibrary( gIPHelperLibraryInstance );
-			check_translated_errno( ok, GetLastError(), kUnknownErr );
-			gIPHelperLibraryInstance = NULL;
-		}
-	}
-
-	if ( gGetIpInterfaceEntryFunctionPtr )
-	{
-		MIB_IPINTERFACE_ROW row;
-		DWORD err;
-
-		ZeroMemory( &row, sizeof( MIB_IPINTERFACE_ROW ) );
-		row.Family = AF_INET;
-		row.InterfaceIndex = ifIndex;
-		err = gGetIpInterfaceEntryFunctionPtr( &row );
-		require_noerr( err, exit );
-		metric = row.Metric + 256;
-	}
-
-exit:
-
-	return metric;
-}
-
-
-//===========================================================================================================================
-//	SetLLRoute
-//===========================================================================================================================
-
-static OSStatus
-SetLLRoute( mDNS * const inMDNS )
-{
-	OSStatus err = kNoErr;
-
-	DEBUG_UNUSED( inMDNS );
-#ifndef WIN32_CENTENNIAL
-	//
-	// <rdar://problem/4096464> Don't call SetLLRoute on loopback
-	// <rdar://problem/6885843> Default route on Windows 7 breaks network connectivity
-	// 
-	// Don't mess w/ the routing table on Vista and later OSes, as 
-	// they have a permanent route to link-local addresses. Otherwise,
-	// set a route to link local addresses (169.254.0.0)
-	//
-	if ( ( inMDNS->p->osMajorVersion < 6 ) && gServiceManageLLRouting && !gPlatformStorage.registeredLoopback4 )
-	{
-		DWORD				ifIndex;
-		MIB_IPFORWARDROW	rowExtant;
-		bool				addRoute;
-		MIB_IPFORWARDROW	row;
-
-		ZeroMemory(&row, sizeof(row));
-
-		err = GetRouteDestination(&ifIndex, &row.dwForwardNextHop);
-		require_noerr( err, exit );
-		row.dwForwardDest		= inet_addr(kLLNetworkAddr);
-		row.dwForwardIfIndex	= ifIndex;
-		row.dwForwardMask		= inet_addr(kLLNetworkAddrMask);
-		row.dwForwardType		= 3;
-		row.dwForwardProto		= MIB_IPPROTO_NETMGMT;
-		row.dwForwardAge		= 0;
-		row.dwForwardPolicy		= 0;
-		row.dwForwardMetric1	= 20 + GetAdditionalMetric( ifIndex );
-		row.dwForwardMetric2	= (DWORD) - 1;
-		row.dwForwardMetric3	= (DWORD) - 1;
-		row.dwForwardMetric4	= (DWORD) - 1;
-		row.dwForwardMetric5	= (DWORD) - 1;
-
-		addRoute = true;
-
-		//
-		// check to make sure we don't already have a route
-		//
-		if ( HaveRoute( &rowExtant, inet_addr( kLLNetworkAddr ), 0 ) )
-		{
-			//
-			// set the age to 0 so that we can do a memcmp.
-			//
-			rowExtant.dwForwardAge = 0;
-
-			//
-			// check to see if this route is the same as our route
-			//
-			if (memcmp(&row, &rowExtant, sizeof(row)) != 0)
-			{
-				//
-				// if it isn't then delete this entry
-				//
-				DeleteIpForwardEntry(&rowExtant);
-			}
-			else
-			{
-				//
-				// else it is, so we don't want to create another route
-				//
-				addRoute = false;
-			}
-		}
-
-		if (addRoute && row.dwForwardNextHop)
-		{
-			err = CreateIpForwardEntry(&row);
-			check_noerr( err );
-		}
-	}
-
-exit:
-#endif
-	return ( err );
-}
-
-
-//===========================================================================================================================
-//	GetRouteDestination
-//===========================================================================================================================
-
-static OSStatus
-GetRouteDestination(DWORD * ifIndex, DWORD * address)
-{
-	struct in_addr		ia;
-	IP_ADAPTER_INFO	*	pAdapterInfo	=	NULL;
-	IP_ADAPTER_INFO	*	pAdapter		=	NULL;
-	ULONG				bufLen;
-	mDNSBool			done			=	mDNSfalse;
-	OSStatus			err;
-
-	//
-	// GetBestInterface will fail if there is no default gateway
-	// configured.  If that happens, we will just take the first
-	// interface in the list. MSDN support says there is no surefire
-	// way to manually determine what the best interface might
-	// be for a particular network address.
-	//
-	ia.s_addr	=	inet_addr(kLLNetworkAddr);
-	err			=	GetBestInterface(*(IPAddr*) &ia, ifIndex);
-
-	if (err)
-	{
-		*ifIndex = 0;
-	}
-
-	//
-	// Make an initial call to GetAdaptersInfo to get
-	// the necessary size into the bufLen variable
-	//
-	err = GetAdaptersInfo( NULL, &bufLen);
-	require_action( err == ERROR_BUFFER_OVERFLOW, exit, err = kUnknownErr );
-
-	pAdapterInfo = (IP_ADAPTER_INFO*) malloc( bufLen );
-	require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-	
-	err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-	require_noerr( err, exit );
-	
-	pAdapter	=	pAdapterInfo;
-	err			=	kUnknownErr;
-			
-	// <rdar://problem/3718122>
-	// <rdar://problem/5652098>
-	//
-	// Look for the Nortel VPN virtual interface, along with Juniper virtual interface.
-	//
-	// If these interfaces are active (i.e., has a non-zero IP Address),
-	// then we want to disable routing table modifications.
-
-	while (pAdapter)
-	{
-		if ( ( IsNortelVPN( pAdapter ) || IsJuniperVPN( pAdapter ) || IsCiscoVPN( pAdapter ) ) &&
-			 ( inet_addr( pAdapter->IpAddressList.IpAddress.String ) != 0 ) )
-		{
-			dlog( kDebugLevelTrace, DEBUG_NAME "disabling routing table management due to VPN incompatibility" );
-			goto exit;
-		}
-
-		pAdapter = pAdapter->Next;
-	}
-
-	while ( !done )
-	{
-		pAdapter	=	pAdapterInfo;
-		err			=	kUnknownErr;
-
-		while (pAdapter)
-		{
-			// If we don't have an interface selected, choose the first one that is of type ethernet and
-			// has a valid IP Address
-
-			if ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) && ( IsValidAddress( pAdapter->IpAddressList.IpAddress.String ) ) && (!(*ifIndex) || (pAdapter->Index == (*ifIndex))))
-			{
-				*address =	inet_addr( pAdapter->IpAddressList.IpAddress.String );
-				*ifIndex =  pAdapter->Index;
-				err		 =	kNoErr;
-				break;
-			}
-		
-			pAdapter = pAdapter->Next;
-		}
-
-		// If we found the right interface, or we weren't trying to find a specific interface then we're done
-
-		if ( !err || !( *ifIndex) )
-		{
-			done = mDNStrue;
-		}
-
-		// Otherwise, try again by wildcarding the interface
-
-		else
-		{
-			*ifIndex = 0;
-		}
-	} 
-
-exit:
-
-	if ( pAdapterInfo != NULL )
-	{
-		free( pAdapterInfo );
-	}
-
-	return( err );
-}
-
-
-static bool
-IsNortelVPN( IP_ADAPTER_INFO * pAdapter )
-{
-	return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
-			(pAdapter->AddressLength == 6) &&
-			(pAdapter->Address[0] == 0x44) &&
-			(pAdapter->Address[1] == 0x45) &&
-			(pAdapter->Address[2] == 0x53) &&
-			(pAdapter->Address[3] == 0x54) &&
-			(pAdapter->Address[4] == 0x42) &&
-			(pAdapter->Address[5] == 0x00)) ? true : false;
-}
-
-
-static bool
-IsJuniperVPN( IP_ADAPTER_INFO * pAdapter )
-{	
-	return ( strnistr( pAdapter->Description, "Juniper", sizeof( pAdapter->Description  ) ) != NULL ) ? true : false;
-}
-
-
-static bool
-IsCiscoVPN( IP_ADAPTER_INFO * pAdapter )
-{
-	return ((pAdapter->Type == MIB_IF_TYPE_ETHERNET) &&
-			(pAdapter->AddressLength == 6) &&
-			(pAdapter->Address[0] == 0x00) &&
-			(pAdapter->Address[1] == 0x05) &&
-			(pAdapter->Address[2] == 0x9a) &&
-			(pAdapter->Address[3] == 0x3c) &&
-			(pAdapter->Address[4] == 0x7a) &&
-			(pAdapter->Address[5] == 0x00)) ? true : false;
-}
-
-
-static const char *
-strnistr( const char * string, const char * subString, size_t max )
-{
-	size_t       subStringLen;
-	size_t       offset;
-	size_t       maxOffset;
-	size_t       stringLen;
-	const char * pPos;
-
-	if ( ( string == NULL ) || ( subString == NULL ) )
-	{
-		return string;
-	}
-
-	stringLen = ( max > strlen( string ) ) ? strlen( string ) : max;
-
-	if ( stringLen == 0 )
-	{
-		return NULL;
-	}
-	
-	subStringLen = strlen( subString );
-
-	if ( subStringLen == 0 )
-	{
-		return string;
-	}
-
-	if ( subStringLen > stringLen )
-	{
-		return NULL;
-	}
-
-	maxOffset = stringLen - subStringLen;
-	pPos      = string;
-
-	for ( offset = 0; offset <= maxOffset; offset++ )
-	{
-		if ( _strnicmp( pPos, subString, subStringLen ) == 0 )
-		{
-			return pPos;
-		}
-
-		pPos++;
-	}
-
-	return NULL;
-}
-
diff --git a/mDNSWindows/SystemService/Service.h b/mDNSWindows/SystemService/Service.h
deleted file mode 100644
index 0b806f0..0000000
--- a/mDNSWindows/SystemService/Service.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#ifndef	__MDNS_SERVICE_H__
-#define	__MDNS_SERVICE_H__
-
-
-#include <windows.h>
-
-
-extern int	RunDirect( int argc, LPTSTR argv[] );
-extern int	Main( int argc, LPTSTR argv[] );
-
-
-#endif
-
diff --git a/mDNSWindows/SystemService/dllmain.cpp b/mDNSWindows/SystemService/dllmain.cpp
deleted file mode 100644
index c87bdc8..0000000
--- a/mDNSWindows/SystemService/dllmain.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
- 
- // dllmain.cpp : Defines the entry point for the DLL application.
-#include "stdafx.h"
-
-BOOL APIENTRY DllMain( HMODULE /*hModule*/,
-					   DWORD  ul_reason_for_call,
-					   LPVOID /*lpReserved*/
-					 )
-{
-	switch (ul_reason_for_call)
-	{
-	case DLL_PROCESS_ATTACH:
-	case DLL_THREAD_ATTACH:
-	case DLL_THREAD_DETACH:
-	case DLL_PROCESS_DETACH:
-		break;
-	}
-	return TRUE;
-}
-
diff --git a/mDNSWindows/SystemService/mDNSResponderLib.h b/mDNSWindows/SystemService/mDNSResponderLib.h
deleted file mode 100644
index 217e56e..0000000
--- a/mDNSWindows/SystemService/mDNSResponderLib.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
-*
-* Copyright (c) 2002-2015 Apple 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
-*
-*     https://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.
-*/
-
-#ifndef __mDNSResponderLib_h
-#define __mDNSResponderLib_h
-
-#include "dns_sd.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-    int DNSSD_API DNSServiceStart();
-    void DNSSD_API DNSServiceStop();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/mDNSWindows/SystemService/main.c b/mDNSWindows/SystemService/main.c
deleted file mode 100644
index 33cce9e..0000000
--- a/mDNSWindows/SystemService/main.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#include "Service.h"
-
-
-//===========================================================================================================================
-//	main
-//===========================================================================================================================
-#if defined(UNICODE)
-int __cdecl wmain( int argc, wchar_t * argv[] )
-#else
-int	__cdecl main( int argc, char *argv[] )
-#endif
-{
-	return Main( argc, argv );
-}
-
diff --git a/mDNSWindows/SystemService/resource.h b/mDNSWindows/SystemService/resource.h
deleted file mode 100644
index d968af9..0000000
--- a/mDNSWindows/SystemService/resource.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by Service.rc
-//
-
-#define IDS_SERVICE_DESCRIPTION        100
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/SystemService/resrc1.h b/mDNSWindows/SystemService/resrc1.h
deleted file mode 100644
index 54a6524..0000000
--- a/mDNSWindows/SystemService/resrc1.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by Service.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/mDNSWindows/SystemService/stdafx.cpp b/mDNSWindows/SystemService/stdafx.cpp
deleted file mode 100644
index c363e6e..0000000
--- a/mDNSWindows/SystemService/stdafx.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-
-// stdafx.cpp : source file that includes just the standard includes
-// mDNSResponderDLL.pch will be the pre-compiled header
-// stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
-
-// TODO: reference any additional headers you need in STDAFX.H
-// and not in this file
diff --git a/mDNSWindows/SystemService/stdafx.h b/mDNSWindows/SystemService/stdafx.h
deleted file mode 100644
index fc2dcb0..0000000
--- a/mDNSWindows/SystemService/stdafx.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-
-// stdafx.h : include file for standard system include files,
-// or project specific include files that are used frequently, but
-// are changed infrequently
-//
-
-#pragma once
-
-#include "targetver.h"
-
-#include <windows.h>
-
-// TODO: reference additional headers your program requires here
diff --git a/mDNSWindows/SystemService/targetver.h b/mDNSWindows/SystemService/targetver.h
deleted file mode 100644
index 34b99db..0000000
--- a/mDNSWindows/SystemService/targetver.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-
-#pragma once
-
-// Including SDKDDKVer.h defines the highest available Windows platform.
-
-// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
-// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
-
-#include <SDKDDKVer.h>
diff --git a/mDNSWindows/VPCDetect.cpp b/mDNSWindows/VPCDetect.cpp
deleted file mode 100644
index 3df7c14..0000000
--- a/mDNSWindows/VPCDetect.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#define _WIN32_DCOM
-#include "VPCDetect.h"
-#include "DebugServices.h"
-#include <comdef.h>
-#include <Wbemidl.h>
-
-# pragma comment(lib, "wbemuuid.lib")
-
-static BOOL g_doneCheck = FALSE;
-static BOOL g_isVPC		= FALSE;
-
-
-mStatus
-IsVPCRunning( BOOL * inVirtualPC )
-{
-	IWbemLocator			*	pLoc 		= 0;
-	IWbemServices			*	pSvc 		= 0;
-    IEnumWbemClassObject	*	pEnumerator = NULL;
-	bool						coInit 		= false;
-	HRESULT						hres;
-	SC_HANDLE					scm			= NULL;
-	SC_HANDLE					service		= NULL;
-	SERVICE_STATUS				status;
-	mStatus						err;
-	BOOL						ok          = TRUE;
-
-	// Initialize flag
-
-	*inVirtualPC = FALSE;
-
-	// Find out if WMI is running
-
-	scm = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );
-	err = translate_errno( scm, (OSStatus) GetLastError(), kOpenErr );
-	require_noerr( err, exit );
-
-	service = OpenService( scm, TEXT( "winmgmt" ), SERVICE_QUERY_STATUS );
-	err = translate_errno( service, (OSStatus) GetLastError(), kNotFoundErr );
-	require_noerr( err, exit );
-	
-	ok = QueryServiceStatus( service, &status );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kAuthenticationErr );
-	require_noerr( err, exit );
-	require_action( status.dwCurrentState == SERVICE_RUNNING, exit, err = kUnknownErr );
-	
-    // Initialize COM.
-
-	hres = CoInitializeEx(0, COINIT_MULTITHREADED);
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
-	coInit = true;
-
-	// Initialize Security
-
-	hres =  CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL );
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
-
-                      
-    // Obtain the initial locator to Windows Management on a particular host computer.
-
-    hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc );
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
- 
-    // Connect to the root\cimv2 namespace with the
-    // current user and obtain pointer pSvc
-    // to make IWbemServices calls.
-
-	hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, WBEM_FLAG_CONNECT_USE_MAX_WAIT, 0, 0, &pSvc );
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
-    
-    // Set the IWbemServices proxy so that impersonation
-    // of the user (client) occurs.
-
-	hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
-
-    // Use the IWbemServices pointer to make requests of WMI. 
-    // Make requests here:
-
-	hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * from Win32_BaseBoard"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-    
-	require_action( SUCCEEDED( hres ), exit, err = kUnknownErr );
-
-	do
-	{
-		IWbemClassObject* pInstance = NULL;
-		ULONG dwCount = NULL;
-
-		hres = pEnumerator->Next( WBEM_INFINITE, 1, &pInstance, &dwCount);
-
-		if ( pInstance )
-		{
-			VARIANT v;
-			BSTR strClassProp = SysAllocString(L"Manufacturer");
-			HRESULT hr;
-
-			hr = pInstance->Get(strClassProp, 0, &v, 0, 0);
-			SysFreeString(strClassProp);
-
-			// check the HRESULT to see if the action succeeded.
-
-			if (SUCCEEDED(hr) && (V_VT(&v) == VT_BSTR))
-			{
-				wchar_t * wstring = wcslwr( V_BSTR( &v ) );
-
-				if (wcscmp( wstring, L"microsoft corporation" ) == 0 )
-				{
-					*inVirtualPC = TRUE;
-				}
-			}
-		
-			VariantClear(&v);
-		}
-	} while (hres == WBEM_S_NO_ERROR);
-         
-exit:
- 
-	if ( pSvc != NULL )
-	{
-    	pSvc->Release();
-	}
-
-	if ( pLoc != NULL )
-	{
-    	pLoc->Release();     
-	}
-
-	if ( coInit )
-	{
-    	CoUninitialize();
-	}
-
-	if ( service )
-	{
-		CloseServiceHandle( service );
-	}
-
-	if ( scm )
-	{
-		CloseServiceHandle( scm );
-	}
-
-	if ( *inVirtualPC )
-	{
-		dlog( kDebugLevelTrace, "Virtual PC detected" );
-	}
-
-	return err;
-}
diff --git a/mDNSWindows/VPCDetect.h b/mDNSWindows/VPCDetect.h
deleted file mode 100644
index 9f34bee..0000000
--- a/mDNSWindows/VPCDetect.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#pragma once
-
-#include <windows.h>
-#include <mDNSEmbeddedAPI.h>
-
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-
-extern mStatus
-IsVPCRunning( BOOL * inVirtualPC );
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/mDNSWindows/VisualStudioSupport.cpp b/mDNSWindows/VisualStudioSupport.cpp
deleted file mode 100644
index 693c9bf..0000000
--- a/mDNSWindows/VisualStudioSupport.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "VisualStudioSupport.h"
-
-#include <stdio.h>
-#include <string.h>
-
-// strlcpy
-// - this implementation is taken directly from the OS X sources
-//
-size_t strlcpy( char * dst, const char * src, size_t dstSize )
-{
-	// This function returns the size of the string it _tried_ to create so that
-	// callers can check for overflow themselves.  That's just the way it's defined.
-	size_t		len = strlen(src);
-
-	if (len < dstSize)
-	{
-		memcpy(dst, src, len + 1);
-	}
-	else if (dstSize != 0)
-	{
-		memcpy(dst, src, dstSize - 1);
-		dst[dstSize - 1] = '\0';
-	}
-
-	return len;
-}
-
-// strlcat
-// - this implementation is taken directly from the OS X sources
-//
-size_t strlcat( char * dst, const char * src, size_t dstSize )
-{
-	// This function returns the size of the string it _tried_ to create so that
-	// callers can check for overflow themselves.  That's just the way it's defined.
-	size_t		srcLen = strlen(src);
-	size_t		dstLen = strnlen(dst, dstSize);
-
-	if (dstLen == dstSize)
-		return (dstSize + srcLen);
-
-	if (srcLen < (dstSize - dstLen))
-	{
-		memcpy(dst + dstLen, src, srcLen + 1);
-	}
-	else
-	{
-		memcpy(dst + dstLen, src, dstSize - dstLen - 1);
-		dst[dstSize - 1] = '\0';
-	}
-
-	return (dstLen + srcLen);
-}
diff --git a/mDNSWindows/VisualStudioSupport.h b/mDNSWindows/VisualStudioSupport.h
deleted file mode 100644
index e735f12..0000000
--- a/mDNSWindows/VisualStudioSupport.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 Apple 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
- *
- *     https://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.
- */
-
-#pragma once
-
-#if defined(_MSC_VER)
-
-// VC++ runtime library equivalents
-#define strdup		_strdup
-#define strcasecmp	_stricmp
-#define strncasecmp	_strnicmp
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// strlcpy() and strlcat() are non-standard (BSD) APIs. They are safer than strncpy() and strncat()
-// (especially the latter) so we implement them for Windows here.
-size_t strlcpy( char * dst, const char * src, size_t dstSize );
-size_t strlcat( char * dst, const char * src, size_t dstSize );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	// defined(_MSC_VER)
diff --git a/mDNSWindows/WinServices.cpp b/mDNSWindows/WinServices.cpp
deleted file mode 100644
index e47c468..0000000
--- a/mDNSWindows/WinServices.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-#include "WinServices.h"
-#include <DebugServices.h>
-
-
-//===========================================================================================================================
-//	UTF8StringToStringObject
-//===========================================================================================================================
-
-OSStatus	UTF8StringToStringObject( const char *inUTF8, CString &inObject )
-{
-	OSStatus		err;
-	int				n;
-	BSTR			unicode;
-	
-	unicode = NULL;
-	
-	n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 );
-	if( n > 0 )
-	{
-		unicode = (BSTR) malloc( (size_t)( n * sizeof( wchar_t ) ) );
-		if( !unicode )
-		{
-			err = ERROR_INSUFFICIENT_BUFFER;
-			goto exit;
-		}
-
-		n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n );
-		try
-		{
-			inObject = unicode;
-		}
-		catch( ... )
-		{
-			err = ERROR_NO_UNICODE_TRANSLATION;
-			goto exit;
-		}
-	}
-	else
-	{
-		inObject = "";
-	}
-	err = ERROR_SUCCESS;
-	
-exit:
-	if( unicode )
-	{
-		free( unicode );
-	}
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	UTF8StringToStringObject
-//===========================================================================================================================
-
-OSStatus
-StringObjectToUTF8String( CString &inObject, char* outUTF8, size_t outUTF8Len )
-{
-    OSStatus err = kNoErr;
-
-	memset( outUTF8, 0, outUTF8Len );
-
-	if ( inObject.GetLength() > 0 )
-    {
-		size_t size;
-
-		size = (size_t) WideCharToMultiByte( CP_UTF8, 0, inObject.GetBuffer(), inObject.GetLength(), outUTF8, (int) outUTF8Len, NULL, NULL);
-        err = translate_errno( size != 0, GetLastError(), kUnknownErr );
-        require_noerr( err, exit );
-    }
-
-exit:
-
-	return err;
-}
diff --git a/mDNSWindows/WinServices.h b/mDNSWindows/WinServices.h
deleted file mode 100644
index f650d1d..0000000
--- a/mDNSWindows/WinServices.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 1997-2004 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.
- */
-
-
-#pragma once
-
-#include <afxwin.h>         // MFC core and standard components
-#include <afxext.h>         // MFC extensions
-#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-#	include <afxcmn.h>		// MFC support for Windows Common Controls
-#endif
-
-#include <winsock2.h>
-#include <afxsock.h>		// MFC socket extensions
-#include "CommonServices.h"
-
-
-OSStatus	UTF8StringToStringObject( const char *inUTF8, CString &outObject );
-OSStatus	StringObjectToUTF8String( CString &inObject, char* outUTF8, size_t outUTF8Len );
diff --git a/mDNSWindows/WinVersRes.h b/mDNSWindows/WinVersRes.h
deleted file mode 100644
index 2ba8d8c..0000000
--- a/mDNSWindows/WinVersRes.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2004-2021 Apple 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
- * 
- *     https://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.
- */
-
-#ifndef WINRESVERS_H
-#define WINRESVERS_H
-
-#define MASTER_PROD_NAME	"Bonjour"
-
-// Define the company name for mDNSResponder on Windows
-#define MASTER_COMPANY_NAME   "Apple Inc."
-
-// Define the product version for mDNSResponder on Windows
-#define MASTER_PROD_VERS		3,1,0,2
-#define MASTER_PROD_VERS_STR	"3,1,0,2"
-#define MASTER_PROD_VERS_STR2	"3.1.0.2"
-#define MASTER_PROD_VERS_STR3 "Explorer Plugin 3.1.0.2"
-
-// Define the legal copyright
-#define MASTER_LEGAL_COPYRIGHT "Copyright (C) 2003-2021 Apple Inc."
-
-#endif // WINRESVERS_H
diff --git a/mDNSWindows/isocode.h b/mDNSWindows/isocode.h
deleted file mode 100644
index fe04f31..0000000
--- a/mDNSWindows/isocode.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-/* isocode.h                                                             */
-/* ----------------------------------------------------------------------*/
-/* THIS FILE HAS BEEN AUTO-GENERATED.  DO NOT EDIT DIRECTLY              */
-/* If a language needs to be added, edit isocode.txt, and run isocode.pl */
-/* to generate a new version of this file                                */
-/* ----------------------------------------------------------------------*/
-/* ----------------------------------------------------------------------*/
-
-
-unsigned char ISOCODES[] = {
-12, 9, 'e','n', 0 , 0 , 0 , 0 ,
-40, 9, 'e','n', 0 , 0 , 0 , 0 ,
-16, 9, 'e','n', 0 , 0 , 0 , 0 ,
-36, 9, 'e','n', 0 , 0 , 0 , 0 ,
-24, 9, 'e','n', 0 , 0 , 0 , 0 ,
-32, 9, 'e','n', 0 , 0 , 0 , 0 ,
-20, 9, 'e','n', 0 , 0 , 0 , 0 ,
-52, 9, 'e','n', 0 , 0 , 0 , 0 ,
-28, 9, 'e','n', 0 , 0 , 0 , 0 ,
-44, 9, 'e','n', 0 , 0 , 0 , 0 ,
-8, 9, 'e','n', 0 , 0 , 0 , 0 ,
-4, 9, 'e','n', 0 , 0 , 0 , 0 ,
-48, 9, 'e','n', 0 , 0 , 0 , 0 ,
-8, 12, 'f','r', 0 , 0 , 0 , 0 ,
-44, 12, 'f','r', 0 , 0 , 0 , 0 ,
-12, 12, 'f','r', 0 , 0 , 0 , 0 ,
-36, 12, 'f','r', 0 , 0 , 0 , 0 ,
-48, 12, 'f','r', 0 , 0 , 0 , 0 ,
-4, 12, 'f','r', 0 , 0 , 0 , 0 ,
-20, 12, 'f','r', 0 , 0 , 0 , 0 ,
-52, 12, 'f','r', 0 , 0 , 0 , 0 ,
-24, 12, 'f','r', 0 , 0 , 0 , 0 ,
-40, 12, 'f','r', 0 , 0 , 0 , 0 ,
-16, 12, 'f','r', 0 , 0 , 0 , 0 ,
-28, 12, 'f','r', 0 , 0 , 0 , 0 ,
-4, 98, 'f','r', 0 , 0 , 0 , 0 ,
-12, 7, 'd','e', 0 , 0 , 0 , 0 ,
-4, 7, 'd','e', 0 , 0 , 0 , 0 ,
-20, 7, 'd','e', 0 , 0 , 0 , 0 ,
-16, 7, 'd','e', 0 , 0 , 0 , 0 ,
-8, 7, 'd','e', 0 , 0 , 0 , 0 ,
-4, 17, 'j','a', 0 , 0 , 0 , 0 ,
-8, 19, 'n','l', 0 , 0 , 0 , 0 ,
-4, 19, 'n','l', 0 , 0 , 0 , 0 ,
-4, 16, 'i','t', 0 , 0 , 0 , 0 ,
-8, 16, 'i','t', 0 , 0 , 0 , 0 ,
-44, 10, 'e','s', 0 , 0 , 0 , 0 ,
-64, 10, 'e','s', 0 , 0 , 0 , 0 ,
-52, 10, 'e','s', 0 , 0 , 0 , 0 ,
-36, 10, 'e','s', 0 , 0 , 0 , 0 ,
-20, 10, 'e','s', 0 , 0 , 0 , 0 ,
-28, 10, 'e','s', 0 , 0 , 0 , 0 ,
-48, 10, 'e','s', 0 , 0 , 0 , 0 ,
-68, 10, 'e','s', 0 , 0 , 0 , 0 ,
-16, 10, 'e','s', 0 , 0 , 0 , 0 ,
-72, 10, 'e','s', 0 , 0 , 0 , 0 ,
-12, 10, 'e','s', 0 , 0 , 0 , 0 ,
-8, 10, 'e','s', 0 , 0 , 0 , 0 ,
-76, 10, 'e','s', 0 , 0 , 0 , 0 ,
-24, 10, 'e','s', 0 , 0 , 0 , 0 ,
-60, 10, 'e','s', 0 , 0 , 0 , 0 ,
-40, 10, 'e','s', 0 , 0 , 0 , 0 ,
-80, 10, 'e','s', 0 , 0 , 0 , 0 ,
-4, 10, 'e','s', 0 , 0 , 0 , 0 ,
-56, 10, 'e','s', 0 , 0 , 0 , 0 ,
-32, 10, 'e','s', 0 , 0 , 0 , 0 ,
-8, 4, 'z','h','_','C','N', 0 ,
-16, 4, 'z','h','_','C','N', 0 ,
-12, 4, 'z','h','_','T','W', 0 ,
-20, 4, 'z','h','_','T','W', 0 ,
-4, 4, 'z','h','_','T','W', 0 ,
-4, 6, 'd','a', 0 , 0 , 0 , 0 ,
-4, 11, 'f','i', 0 , 0 , 0 , 0 ,
-4, 18, 'k','o', 0 , 0 , 0 , 0 ,
-4, 20, 'n','b', 0 , 0 , 0 , 0 ,
-8, 20, 'n','b', 0 , 0 , 0 , 0 ,
-4, 22, 'p','t', 0 , 0 , 0 , 0 ,
-4, 29, 's','v', 0 , 0 , 0 , 0 ,
-8, 29, 's','v', 0 , 0 , 0 , 0 ,
-20, 1, 'a','r', 0 , 0 , 0 , 0 ,
-60, 1, 'a','r', 0 , 0 , 0 , 0 ,
-12, 1, 'a','r', 0 , 0 , 0 , 0 ,
-8, 1, 'a','r', 0 , 0 , 0 , 0 ,
-44, 1, 'a','r', 0 , 0 , 0 , 0 ,
-52, 1, 'a','r', 0 , 0 , 0 , 0 ,
-48, 1, 'a','r', 0 , 0 , 0 , 0 ,
-16, 1, 'a','r', 0 , 0 , 0 , 0 ,
-24, 1, 'a','r', 0 , 0 , 0 , 0 ,
-32, 1, 'a','r', 0 , 0 , 0 , 0 ,
-64, 1, 'a','r', 0 , 0 , 0 , 0 ,
-4, 1, 'a','r', 0 , 0 , 0 , 0 ,
-40, 1, 'a','r', 0 , 0 , 0 , 0 ,
-28, 1, 'a','r', 0 , 0 , 0 , 0 ,
-56, 1, 'a','r', 0 , 0 , 0 , 0 ,
-36, 1, 'a','r', 0 , 0 , 0 , 0 ,
-4, 2, 'b','g', 0 , 0 , 0 , 0 ,
-4, 26, 'h','r', 0 , 0 , 0 , 0 ,
-4, 5, 'c','s', 0 , 0 , 0 , 0 ,
-4, 8, 'e','l', 0 , 0 , 0 , 0 ,
-4, 13, 'i','w', 0 , 0 , 0 , 0 ,
-4, 14, 'h','u', 0 , 0 , 0 , 0 ,
-4, 15, 'i','s', 0 , 0 , 0 , 0 ,
-4, 21, 'p','l', 0 , 0 , 0 , 0 ,
-8, 22, 'p','t','_','P','T', 0 ,
-4, 24, 'r','o', 0 , 0 , 0 , 0 ,
-8, 24, 'r','o', 0 , 0 , 0 , 0 ,
-4, 25, 'r','u', 0 , 0 , 0 , 0 ,
-8, 25, 'r','u', 0 , 0 , 0 , 0 ,
-4, 30, 't','h', 0 , 0 , 0 , 0 ,
-4, 31, 't','r', 0 , 0 , 0 , 0 ,
-4, 34, 'u','k', 0 , 0 , 0 , 0 ,
-};
-
-#define NUM_ISOCODES      101
-#define LANG_CODE_LEN     5
-#define MODULO_ISOCODES   8
-
-
diff --git a/mDNSWindows/loclibrary.c b/mDNSWindows/loclibrary.c
deleted file mode 100644
index 9744120..0000000
--- a/mDNSWindows/loclibrary.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-    
-/* loclibrary.c                                                          
- * ----------------------------------------------------------------------
- * Source for localization library                                       
- * Originally created by jsantamaria: 3 may 2004                         
- * ----------------------------------------------------------------------
- */
- 
-#include "DebugServices.h"
-#include <windows.h>
-#include <stdio.h>
-#include "isocode.h"
-#include "loclibrary.h"
-#include "Shlwapi.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <wchar.h>
-
-
-#ifdef __cplusplus
-extern "c" {
-#endif
-
-#ifdef _MSC_VER
-#define swprintf _snwprintf
-#define snprintf _snprintf
-#endif
-
-
-
-#define DEFAULT_LANG_CODE "en"
-
-// gets the user language
-static LANGID _getUserLanguage( void ) {
-	
-	return GetUserDefaultUILanguage();
-
-}
-
-
-// gets the ISO mapping
-static int _getISOCode(LANGID wLangID, char *isoLangCode, int codeLen) {
-	int i;
-	unsigned short langCode;
-
-	for (i = 0; i < NUM_ISOCODES; i++) {
-		int startIndex = i * MODULO_ISOCODES;
-		
-		langCode = (ISOCODES[startIndex] << 8);
-		langCode = langCode + ( (unsigned short) (ISOCODES[startIndex + 1]) );
-
-		if (langCode == wLangID) {
-			char *langStr = (char *)&(ISOCODES[startIndex+2]);
-			strncpy(isoLangCode, langStr, codeLen);
-			return 0;
-		}
-	}
-	return 1;
-}
-
-static char isoLangCode[LANG_CODE_LEN + 1] = "";
-static LANGID wLangID = (LANGID) -1;
-
-static void _setLanguageIfNeeded(void) {
-	
-	// get the language code if we don't have it cached
-	if (!strncmp(isoLangCode,"",LANG_CODE_LEN + 1)) {
-		
-		// if we haven't cached the language id, do the lookup
-		if (wLangID == (LANGID) -1) {
-			wLangID = _getUserLanguage();
-		}
-		
-		// if no ISOCode, set it to DEFAULT_LANG_CODE
-		if (_getISOCode(wLangID, isoLangCode, LANG_CODE_LEN + 1)) {
-			strncpy(isoLangCode, DEFAULT_LANG_CODE, LANG_CODE_LEN+1);
-		}
-	}
-
-}
-
-//// PathForResource
-
-// Gets the PathForResource for handle 0 for the current process
-
-
-static char appPathNameA[MAX_PATH] = "";
-
-int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen)
-{
-	int ret = 0;
-
-	if ( !strcmp( appPathNameA, "" ) )
-	{
-		char   folder[MAX_PATH];
-		char * ext;
-		char * app;
-
-		GetModuleFileNameA( module, folder, MAX_PATH );
-
-		// Get folder string
-		
-		app = strrchr( folder, '\\' );
-		require_action( app, exit, ret = 0 );
-		*app++ = '\0';
-
-		// Strip the extension
-
-		if ( ( ( ext = strstr( app, ".exe" ) ) != NULL ) || ( ( ext = strstr( app, ".dll" ) ) != NULL ) )
-		{
-			*ext = '\0';
-		}
-
-		snprintf( appPathNameA, MAX_PATH, "%s\\%s", folder, app );
-	}
-
-	ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
-
-exit:
-
-	return ret;
-}
-
-static wchar_t appPathNameW[MAX_PATH] = L"";
-
-int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen)
-{
-	int ret = 0;
-
-	if ( !wcscmp( appPathNameW, L"" ) )
-	{
-		wchar_t   folder[MAX_PATH];
-		wchar_t * app;
-		wchar_t * ext;
-
-		GetModuleFileNameW( module, folder, MAX_PATH);
-
-		// Get folder string
-		
-		app = wcsrchr( folder, '\\' );
-		require_action( app, exit, ret = 0 );
-		*app++ = '\0';
-
-		// Strip the extension
-
-		if ( ( ( ext = wcsstr( app, L".exe" ) ) != NULL ) || ( ( ext = wcsstr( app, L".dll" ) ) != NULL ) )
-		{
-			*ext = '\0';
-		}
-
-		swprintf( appPathNameW, MAX_PATH, L"%ls\\%ls", folder, app );
-	}
-
-	ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
-
-exit:
-
-	return ret;
-}
-
-
-//// PathForResourceWithPath
-
-#define TMP_BUF_SIZE MAX_PATH
-
-int PathForResourceWithPathA (const char *path, const char *nm, 
-									char *locFile, int locFileLen) {
-	char tmpBuffer[TMP_BUF_SIZE];
-
-	// build the path to the executable in the generic 
-	// resources folder, check there first
-	snprintf(tmpBuffer, MAX_PATH, "%s.Resources\\%s", path, nm);
-
-	if (!PathFileExistsA(tmpBuffer)) {
-
-		// didn't hit generic resource folder, so need to get language codes
-		_setLanguageIfNeeded();
-
-		// test to see if localized directory exists, 
-		// if so, we don't fall back if we don't find the file.
-		snprintf(tmpBuffer, TMP_BUF_SIZE, 
-				 "%s.Resources\\%s.lproj", path, isoLangCode);
-
-		if (PathFileExistsA(tmpBuffer)) {
-			snprintf(tmpBuffer, TMP_BUF_SIZE, "%s\\%s", tmpBuffer, nm);
-
-			if (!PathFileExistsA(tmpBuffer)) return 0;
-
-			strncpy(locFile, tmpBuffer, locFileLen);
-			return (int) strlen(locFile);
-		}
-
-		// fall back on DEFAULT_LANG_CODE if still no good
-		snprintf(tmpBuffer, TMP_BUF_SIZE, "%s.Resources\\%s.lproj\\%s", 
-				path, DEFAULT_LANG_CODE, nm);
-				
-		// we can't find the resource, so return 0
-		if (!PathFileExistsA(tmpBuffer)) return 0;
-	}
-	
-	strncpy(locFile, tmpBuffer, locFileLen);
-	return (int) strlen(locFile);
-
-}
-
-
-int PathForResourceWithPathW (const wchar_t *path, const wchar_t *nm, 
-								wchar_t *locFile, int locFileLen) {
-
-	wchar_t tmpBuffer[TMP_BUF_SIZE];
-
-	// build the path to the executable in the generic
-	// resources folder, check there first
-	swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%ls", path, nm);
-
-	if (!PathFileExistsW(tmpBuffer)) {
-		// didn't hit generic resource folder, so need to get language codes
-		_setLanguageIfNeeded();
-
-		// test to see if localized directory exists, 
-		// if so, we don't fall back if we don't find the file.
-		swprintf(tmpBuffer, TMP_BUF_SIZE, 
-				  L"%ls.Resources\\%S.lproj", path, isoLangCode);
-
-		if (PathFileExistsW(tmpBuffer)) {
-			swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls\\%ls", tmpBuffer, nm);
-
-			if (!PathFileExistsW(tmpBuffer)) return 0;
-
-			wcsncpy(locFile, tmpBuffer, locFileLen);
-			return (int) wcslen(locFile);
-		}
-
-		// fall back on DEFAULT_LANG_CODE if still no good
-		swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%S.lproj\\%ls", 
-			path, DEFAULT_LANG_CODE, nm);
-
-		// we can't find the resource, so return 0
-		if (!PathFileExistsW(tmpBuffer)) return 0;
-	}
-	
-	wcsncpy(locFile, tmpBuffer, locFileLen);
-	return (int) wcslen(locFile);
-
-
-}
-
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/mDNSWindows/loclibrary.h b/mDNSWindows/loclibrary.h
deleted file mode 100644
index 0a9b7ce..0000000
--- a/mDNSWindows/loclibrary.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-    
-/* loclibrary.h                                                      
- * ----------------------------------------------------------------------
- * Header file for localization library                                       
- * Originally created by jsantamaria: 3 may 2004                         
- * ----------------------------------------------------------------------
- */
- 
-#ifndef _loclibrary_h_
-#define _loclibrary_h_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen);
-int PathForResourceWithPathW ( const wchar_t *path, const wchar_t *name, wchar_t *locFile, int locFileLen);
-
-int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen);
-int PathForResourceWithPathA ( const char *path, const char *name, char *locFile, int locFileLen);
-
-
-#ifdef UNICODE
-#define PathForResource PathForResourceW
-#define PathForResourceWithPath PathForResourceWithPathW
-#else
-#define PathForResource PathForResourceA
-#define PathForResourceWithPath PathForResourceWithPathA
-#endif // UNICODE
-
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-
-#endif // _loclibrary_h_
diff --git a/mDNSWindows/mDNSWin32.c b/mDNSWindows/mDNSWin32.c
deleted file mode 100644
index e8d5b57..0000000
--- a/mDNSWindows/mDNSWin32.c
+++ /dev/null
@@ -1,5141 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2022 Apple 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
- * 
- *     https://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.
-
-	To Do:
-	
-	- Get unicode name of machine for nice name instead of just the host name.
-	- Use the IPv6 Internet Connection Firewall API to allow IPv6 mDNS without manually changing the firewall.
-	- Get DNS server address(es) from Windows and provide them to the uDNS layer.
-	- Implement TCP support for truncated packets (only stubs now).	
-
-*/
-
-#define _CRT_RAND_S
-
-#include	<stdarg.h>
-#include	<stddef.h>
-#include	<stdio.h>
-#include	<stdlib.h>
-#include	<crtdbg.h>
-#include	<string.h>
-
-#include	"Poll.h"
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-#include	"Firewall.h"
-#include	"RegNames.h"
-#include	"Secret.h"
-#include	<dns_sd.h>
-
-#include	<Iphlpapi.h>
-#include	<mswsock.h>
-#include	<process.h>
-#include	<ntsecapi.h>
-#include	<lm.h>
-#include	<winioctl.h>
-#include	<ntddndis.h>        // This defines the IOCTL constants.
-
-#include	"mDNSEmbeddedAPI.h"
-#include	"GenLinkedList.h"
-#include	"DNSCommon.h"
-#include	"mDNSWin32.h"
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#define	DEBUG_NAME									"[mDNSWin32] "
-
-#ifdef WIN32_CENTENNIAL
-#ifdef DEBUG
-#define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				0
-#else
-#define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				1
-#endif
-#else
-#define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				1
-#endif
-#define	MDNS_WINDOWS_ENABLE_IPV4					1
-#define	MDNS_WINDOWS_ENABLE_IPV6					1
-#define	MDNS_FIX_IPHLPAPI_PREFIX_BUG				1
-#define MDNS_SET_HINFO_STRINGS						0
-
-#define	kMDNSDefaultName							"My Computer"
-
-#define	kWinSockMajorMin							2
-#define	kWinSockMinorMin							2
-
-#define kRegistryMaxKeyLength						255
-#define kRegistryMaxValueName						16383
-
-static GUID											kWSARecvMsgGUID = WSAID_WSARECVMSG;
-
-#define kIPv6IfIndexBase							(10000000L)
-#define SMBPortAsNumber								445
-#define DEVICE_PREFIX								"\\\\.\\"
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-mDNSlocal mStatus			SetupNiceName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupHostName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
-mDNSlocal mStatus			TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
-mDNSlocal void CALLBACK		FreeInterface( mDNSInterfaceData *inIFD );
-mDNSlocal mStatus			SetupSocket( const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  );
-mDNSlocal mStatus			SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
-mDNSlocal OSStatus			GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
-mDNSlocal int				getifaddrs( struct ifaddrs **outAddrs );
-mDNSlocal void				freeifaddrs( struct ifaddrs *inAddrs );
-
-
-// Platform Accessors
-
-#ifdef	__cplusplus
-	extern "C" {
-#endif
-
-typedef struct mDNSPlatformInterfaceInfo	mDNSPlatformInterfaceInfo;
-struct	mDNSPlatformInterfaceInfo
-{
-	const char *		name;
-	mDNSAddr			ip;
-};
-
-
-mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
-mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
-
-
-// Wakeup Structs
-
-#define kMulticastWakeupNumTries			( 18 )
-#define kMulticastWakeupSleepBetweenTries	( 100 )
-
-typedef struct MulticastWakeupStruct
-{
-	mDNS					*inMDNS;
-	struct sockaddr_in		addr;
-	INT						addrLen;
-	unsigned char			data[ 102 ];
-	INT						dataLen;
-	INT						numTries;
-	INT						msecSleep;
-} MulticastWakeupStruct;
-
-
-// Utilities
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs );
-#endif
-
-mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
-
-mDNSlocal DWORD				GetPrimaryInterface();
-mDNSlocal mStatus			AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
-mDNSlocal mDNSBool			CanReceiveUnicast( void );
-mDNSlocal mDNSBool			IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr );
-
-mDNSlocal mStatus			StringToAddress( mDNSAddr * ip, LPSTR string );
-mDNSlocal mStatus			RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
-mDNSlocal struct ifaddrs*	myGetIfAddrs(int refresh);
-mDNSlocal OSStatus			TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal OSStatus			WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal void CALLBACK		TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-mDNSlocal void				TCPCloseSocket( TCPSocket * socket );
-mDNSlocal void CALLBACK		UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-mDNSlocal void				UDPCloseSocket( UDPSocket * sock );
-mDNSlocal mStatus           SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
-mDNSlocal void				GetDDNSFQDN( domainname *const fqdn );
-#ifdef UNICODE
-mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey );
-#else
-mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
-#endif
-mDNSlocal void				SetDomainSecrets( mDNS * const inMDNS );
-mDNSlocal void				SetDomainSecret( mDNS * const m, const domainname * inDomain );
-mDNSlocal VOID CALLBACK		CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
-mDNSlocal void				CheckFileShares( mDNS * const inMDNS );
-mDNSlocal void				SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
-mDNSlocal mDNSu8			IsWOMPEnabledForAdapter( const char * adapterName );
-mDNSlocal void				SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep );
-mDNSlocal void _cdecl		SendMulticastWakeupPacket( void *arg );
-
-#ifdef	__cplusplus
-	}
-#endif
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-extern mDNS		mDNSStorage;
-#define gMDNSRecord	mDNSStorage
-
-mDNSlocal mDNS_PlatformSupport	gMDNSPlatformSupport;
-mDNSs32							mDNSPlatformOneSecond	= 0;
-mDNSlocal UDPSocket		*		gUDPSockets				= NULL;
-mDNSlocal int					gUDPNumSockets			= 0;
-mDNSlocal BOOL					gEnableIPv6				= TRUE;
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-
-	typedef DWORD
-		( WINAPI * GetAdaptersAddressesFunctionPtr )( 
-			ULONG 					inFamily, 
-			DWORD 					inFlags, 
-			PVOID 					inReserved, 
-			PIP_ADAPTER_ADDRESSES 	inAdapter, 
-			PULONG					outBufferSize );
-
-	mDNSlocal HMODULE								gIPHelperLibraryInstance			= NULL;
-	mDNSlocal GetAdaptersAddressesFunctionPtr		gGetAdaptersAddressesFunctionPtr	= NULL;
-
-#endif
-
-#ifndef HCRYPTPROV
-   typedef ULONG_PTR HCRYPTPROV;    // WinCrypt.h, line 249
-#endif
-
-#ifndef CRYPT_MACHINE_KEYSET
-#	define CRYPT_MACHINE_KEYSET    0x00000020
-#endif
-
-#ifndef CRYPT_NEWKEYSET
-#	define CRYPT_NEWKEYSET         0x00000008
-#endif
-
-#ifndef PROV_RSA_FULL
-#  define PROV_RSA_FULL 1
-#endif
-
-typedef BOOL (__stdcall *fnCryptGenRandom)( HCRYPTPROV, DWORD, BYTE* ); 
-typedef BOOL (__stdcall *fnCryptAcquireContext)( HCRYPTPROV*, LPCTSTR, LPCTSTR, DWORD, DWORD);
-typedef BOOL (__stdcall *fnCryptReleaseContext)(HCRYPTPROV, DWORD);
-
-static fnCryptAcquireContext g_lpCryptAcquireContext 	= NULL;
-static fnCryptReleaseContext g_lpCryptReleaseContext 	= NULL;
-static fnCryptGenRandom		 g_lpCryptGenRandom 		= NULL;
-static HINSTANCE			 g_hAAPI32 					= NULL;
-static HCRYPTPROV			 g_hProvider 				= ( ULONG_PTR ) NULL;
-
-
-typedef DNSServiceErrorType ( DNSSD_API *DNSServiceRegisterFunc )
-	(
-	DNSServiceRef                       *sdRef,
-	DNSServiceFlags                     flags,
-	uint32_t                            interfaceIndex,
-	const char                          *name,         /* may be NULL */
-	const char                          *regtype,
-	const char                          *domain,       /* may be NULL */
-	const char                          *host,         /* may be NULL */
-	uint16_t                            port,
-	uint16_t                            txtLen,
-	const void                          *txtRecord,    /* may be NULL */
-	DNSServiceRegisterReply             callBack,      /* may be NULL */
-	void                                *context       /* may be NULL */
-	);
-
-
-typedef void ( DNSSD_API *DNSServiceRefDeallocateFunc )( DNSServiceRef sdRef );
-
-mDNSlocal HMODULE					gDNSSDLibrary				= NULL;
-mDNSlocal DNSServiceRegisterFunc	gDNSServiceRegister			= NULL;
-mDNSlocal DNSServiceRefDeallocateFunc gDNSServiceRefDeallocate	= NULL;
-mDNSlocal HANDLE					gSMBThread					= NULL;
-mDNSlocal HANDLE					gSMBThreadRegisterEvent		= NULL;
-mDNSlocal HANDLE					gSMBThreadDeregisterEvent	= NULL;
-mDNSlocal HANDLE					gSMBThreadStopEvent			= NULL;
-mDNSlocal HANDLE					gSMBThreadQuitEvent			= NULL;
-
-#define	kSMBStopEvent				( WAIT_OBJECT_0 + 0 )
-#define	kSMBRegisterEvent			( WAIT_OBJECT_0 + 1 )
-#define kSMBDeregisterEvent			( WAIT_OBJECT_0 + 2 )
-
-#if 0
-#pragma mark -
-#pragma mark == Platform Support ==
-#endif
-
-//===========================================================================================================================
-//	mDNSPlatformInit
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInit( mDNS * const inMDNS )
-{
-	mStatus		err;
-#ifndef WIN32_CENTENNIAL
-	OSVERSIONINFO osInfo;
-	BOOL ok;
-#endif
-	WSADATA		wsaData;
-	int			supported;
-	struct sockaddr_in	sa4;
-	struct sockaddr_in6 sa6;
-	int					sa4len;
-	int					sa6len;
-	DWORD				size;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
-	
-	// Initialize variables. If the PlatformSupport pointer is not null then just assume that a non-Apple client is 
-	// calling mDNS_Init and wants to provide its own storage for the platform-specific data so do not overwrite it.
-	
-	mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
-	if( !inMDNS->p ) inMDNS->p				= &gMDNSPlatformSupport;
-	inMDNS->p->mainThread					= OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
-	require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
-	inMDNS->p->checkFileSharesTimer = CreateWaitableTimer( NULL, FALSE, NULL );
-	require_action( inMDNS->p->checkFileSharesTimer, exit, err = mStatus_UnknownErr );
-	inMDNS->p->checkFileSharesTimeout		= 10;		// Retry time for CheckFileShares() in seconds
-	mDNSPlatformOneSecond 					= 1000;		// Use milliseconds as the quantum of time
-	
-#ifndef WIN32_CENTENNIAL
-	// Get OS version info
-	
-	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
-	ok = GetVersionEx( &osInfo );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	inMDNS->p->osMajorVersion = osInfo.dwMajorVersion;
-	inMDNS->p->osMinorVersion = osInfo.dwMinorVersion;
-	
-	// Don't enable IPv6 on anything less recent than Windows Vista
-
-	if ( inMDNS->p->osMajorVersion < 6 )
-	{
-		gEnableIPv6 = FALSE;
-	}
-#else
-	inMDNS->p->osMajorVersion = 6;
-	inMDNS->p->osMinorVersion = 3;
-#endif
-
-	// Startup WinSock 2.2 or later.
-	
-	err = WSAStartup( MAKEWORD( kWinSockMajorMin, kWinSockMinorMin ), &wsaData );
-	require_noerr( err, exit );
-	
-	supported = ( ( LOBYTE( wsaData.wVersion ) == kWinSockMajorMin ) && ( HIBYTE( wsaData.wVersion ) == kWinSockMinorMin ) );
-	require_action( supported, exit, err = mStatus_UnsupportedErr );
-	
-	inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
-	
-	// Setup the HINFO HW strings.
-	//<rdar://problem/7245119> device-info should have model=Windows
-
-	strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
-	inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
-	dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
-
-	// Setup the HINFO SW strings.
-#if ( MDNS_SET_HINFO_STRINGS )
-	mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2, 
-		"mDNSResponder (%s %s)", __DATE__, __TIME__ );
-	inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
-	dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
-#endif
-
-	// Set up the IPv4 unicast socket
-
-	inMDNS->p->unicastSock4.fd			= INVALID_SOCKET;
-	inMDNS->p->unicastSock4.recvMsgPtr	= NULL;
-	inMDNS->p->unicastSock4.ifd			= NULL;
-	inMDNS->p->unicastSock4.next		= NULL;
-	inMDNS->p->unicastSock4.m			= inMDNS;
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
-
-	sa4.sin_family		= AF_INET;
-	sa4.sin_addr.s_addr = INADDR_ANY;
-	err = SetupSocket( (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
-	check_noerr( err );
-	sa4len = sizeof( sa4 );
-	err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
-	require_noerr( err, exit );
-	inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
-	inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
-	err = WSAIoctl( inMDNS->p->unicastSock4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4.recvMsgPtr, sizeof( inMDNS->p->unicastSock4.recvMsgPtr ), &size, NULL, NULL );
-		
-	if ( err )
-	{
-		inMDNS->p->unicastSock4.recvMsgPtr = NULL;
-	}
-
-	err = mDNSPollRegisterSocket( inMDNS->p->unicastSock4.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock4 );
-	require_noerr( err, exit ); 
-
-#endif
-
-	// Set up the IPv6 unicast socket
-
-	inMDNS->p->unicastSock6.fd			= INVALID_SOCKET;
-	inMDNS->p->unicastSock6.recvMsgPtr	= NULL;
-	inMDNS->p->unicastSock6.ifd			= NULL;
-	inMDNS->p->unicastSock6.next		= NULL;
-	inMDNS->p->unicastSock6.m			= inMDNS;
-
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		sa6.sin6_family		= AF_INET6;
-		sa6.sin6_addr		= in6addr_any;
-		sa6.sin6_scope_id	= 0;
-
-		// This call will fail if the machine hasn't installed IPv6.  In that case,
-		// the error will be WSAEAFNOSUPPORT.
-
-		err = SetupSocket( (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
-		require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
-		err = kNoErr;
-		
-		// If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
-
-		if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
-		{
-			sa6len = sizeof( sa6 );
-			err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
-			require_noerr( err, exit );
-			inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
-			inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
-
-			err = WSAIoctl( inMDNS->p->unicastSock6.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6.recvMsgPtr, sizeof( inMDNS->p->unicastSock6.recvMsgPtr ), &size, NULL, NULL );
-			
-			if ( err != 0 )
-			{
-				inMDNS->p->unicastSock6.recvMsgPtr = NULL;
-			}
-
-			err = mDNSPollRegisterSocket( inMDNS->p->unicastSock6.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock6 );
-			require_noerr( err, exit );
-		}
-	}
-
-#endif
-
-	// Notify core of domain secret keys
-
-	SetDomainSecrets( inMDNS );
-	
-	// Success!
-
-	mDNSCoreInitComplete( inMDNS, err );
-
-	
-exit:
-
-	if ( err )
-	{
-		mDNSPlatformClose( inMDNS );
-	}
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformClose
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformClose( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
-	check( inMDNS );
-
-	if ( gSMBThread != NULL )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "tearing down smb registration thread\n" );
-		SetEvent( gSMBThreadStopEvent );
-		
-		if ( WaitForSingleObject( gSMBThreadQuitEvent, 5 * 1000 ) == WAIT_OBJECT_0 )
-		{
-			if ( gSMBThreadQuitEvent )
-			{
-				CloseHandle( gSMBThreadQuitEvent );
-				gSMBThreadQuitEvent = NULL;
-			}
-
-			if ( gSMBThreadStopEvent )
-			{
-				CloseHandle( gSMBThreadStopEvent );
-				gSMBThreadStopEvent = NULL;
-			}
-
-			if ( gSMBThreadDeregisterEvent )
-			{
-				CloseHandle( gSMBThreadDeregisterEvent );
-				gSMBThreadDeregisterEvent = NULL;
-			}
-
-			if ( gSMBThreadRegisterEvent )
-			{
-				CloseHandle( gSMBThreadRegisterEvent );
-				gSMBThreadRegisterEvent = NULL;
-			}
-
-			if ( gDNSSDLibrary )
-			{
-				FreeLibrary( gDNSSDLibrary );
-				gDNSSDLibrary = NULL;
-			}	
-		}
-		else
-		{
-			LogMsg( "Unable to stop SMBThread" );
-		}
-
-		inMDNS->p->smbFileSharing = mDNSfalse;
-		inMDNS->p->smbPrintSharing = mDNSfalse;
-	}
-
-	// Tear everything down in reverse order to how it was set up.
-	
-	err = TearDownInterfaceList( inMDNS );
-	check_noerr( err );
-	check( !inMDNS->p->inactiveInterfaceList );
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
-
-	UDPCloseSocket( &inMDNS->p->unicastSock4 );
-
-#endif
-	
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		UDPCloseSocket( &inMDNS->p->unicastSock6 );
-	}
-
-#endif
-
-	// Free the DLL needed for IPv6 support.
-	
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	if( gIPHelperLibraryInstance )
-	{
-		gGetAdaptersAddressesFunctionPtr = NULL;
-		
-		FreeLibrary( gIPHelperLibraryInstance );
-		gIPHelperLibraryInstance = NULL;
-	}
-#endif
-
-	if ( g_hAAPI32 )
-	{
-		// Release any resources
-
-		if ( g_hProvider && g_lpCryptReleaseContext )
-		{
-			( g_lpCryptReleaseContext )( g_hProvider, 0 );
-		}
-
-		// Free the AdvApi32.dll
-
-		FreeLibrary( g_hAAPI32 );
-
-		// And reset all the data
-
-		g_lpCryptAcquireContext = NULL;
-		g_lpCryptReleaseContext = NULL;
-		g_lpCryptGenRandom 		= NULL;
-		g_hProvider 			= ( ULONG_PTR ) NULL;
-		g_hAAPI32				= NULL;
-	}
-
-	WSACleanup();
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformLock
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformLock( const mDNS * const inMDNS )
-{
-	( void ) inMDNS;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformUnlock
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformUnlock( const mDNS * const inMDNS )
-{
-	( void ) inMDNS;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformStrLCopy
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformStrLCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	const char *		src = (const char *) inSrc;
-	
-	if( inSize > 0 )
-	{
-		size_t		n;
-		char *		dst = (char *) inDst;
-		
-		for( n = inSize - 1; n > 0; --n )
-		{
-			if( ( *dst++ = *src++ ) == '\0' )
-			{
-				// Null terminator encountered, so exit.
-				return;
-			}
-		}
-		*dst = '\0';
-	}
-}
-
-//===========================================================================================================================
-//	mDNSPlatformStrLen
-//===========================================================================================================================
-
-mDNSexport mDNSu32	mDNSPlatformStrLen( const void *inSrc )
-{
-	check( inSrc );
-	
-	return( (mDNSu32) strlen( (const char *) inSrc ) );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemCopy
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	memcpy( inDst, inSrc, inSize );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemSame
-//===========================================================================================================================
-
-mDNSexport mDNSBool	mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	return( (mDNSBool)( memcmp( inSrc, inDst, inSize ) == 0 ) );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemCmp
-//===========================================================================================================================
-
-mDNSexport int	mDNSPlatformMemCmp( const void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	return( memcmp( inSrc, inDst, inSize ) );
-}
-
-mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-	(void)base;
-	(void)nel;
-	(void)width;
-	(void)compar;
-}
-
-// Proxy stub functions
-mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-	(void) q;
-	(void) h;
-	(void) msg;
-	(void) ptr;
-	(void) limit;
-
-	return ptr;
-}
-
-mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
-{
-	(void) m;
-	(void) IpIfArr;
-	(void) OpIf;
-}
-
-mDNSexport void DNSProxyTerminate(mDNS *const m)
-{
-	(void) m;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemZero
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
-{
-	check( inDst );
-	
-	memset( inDst, 0, inSize );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemAllocate
-//===========================================================================================================================
-
-mDNSexport void *	mDNSPlatformMemAllocate( mDNSu32 inSize )
-{
-	void *		mem;
-	
-	check( inSize > 0 );
-	
-	mem = malloc( inSize );
-	check( mem );
-	
-	return( mem );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemAllocateClear
-//===========================================================================================================================
-
-mDNSexport void *	mDNSPlatformMemAllocateClear( mDNSu32 inSize )
-{
-	void *		mem;
-	
-	check( inSize > 0 );
-	
-	mem = calloc( 1, inSize );
-	check( mem );
-	
-	return( mem );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemFree
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemFree( void *inMem )
-{
-	check( inMem );
-	
-	free( inMem );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformRandomNumber
-//===========================================================================================================================
-
-mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
-{
-	unsigned int	randomNumber;
-	errno_t			err;
-
-	err = rand_s( &randomNumber );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( err )
-	{
-		randomNumber = rand();
-	}
-
-	return ( mDNSu32 ) randomNumber;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTimeInit
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformTimeInit( void )
-{
-	// No special setup is required on Windows -- we just use GetTickCount().
-	return( mStatus_NoError );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformRawTime
-//===========================================================================================================================
-
-mDNSexport mDNSs32	mDNSPlatformRawTime( void )
-{
-	return( (mDNSs32) GetTickCount() );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformUTC
-//===========================================================================================================================
-
-mDNSexport mDNSs32	mDNSPlatformUTC( void )
-{
-	return ( mDNSs32 ) time( NULL );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformContinuousTimeSeconds
-//===========================================================================================================================
-
-mDNSexport mDNSs32	mDNSPlatformContinuousTimeSeconds( void )
-{
-	// The caller is expecting a signed time since an epoch. This is expected to
-	// wrap at the epoch, and the epoch could be boot time or 1970, or something else;
-	// in this case it's boot time, so it would be surprising for the tick count to
-	// ever be big enough to go negative when cast to signed. However, the caller
-	// is expected to use two's complement math, so if this were to wrap, it should
-	// behave correctly. We use GetTickCount64() rather than GetTickCount() because
-	// GetTickCount() would wrap after 47 days, and two's complement comparisons
-	// wouldn't work because we're dividing by 1000.
-	return ( mDNSs32 ) (GetTickCount64( NULL ) / 1000ULL);
-}
-
-//===========================================================================================================================
-//	getlocaltimestampfromplatformtime
-//===========================================================================================================================
-
-mDNSexport void getLocalTimestampFromPlatformTime(const mDNSs32 platformTimeNow, const mDNSs32 platformTime,
-	char *const outBuffer, const mDNSu32 bufferLen)
-{
-	(void)platformTimeNow;
-	(void)platformTime;
-	if (bufferLen > 0)
-	{
-		outBuffer[0] = '\0';
-	}
-}
-
-//===========================================================================================================================
-//	getLocalTimestampNow
-//===========================================================================================================================
-
-mDNSexport void getLocalTimestampNow(char *const outBuffer, const mDNSu32 bufferLen)
-{
-	if (bufferLen > 0)
-	{
-		outBuffer[0] = '\0';
-	}
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceNameToID
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
-{
-	mStatus					err;
-	mDNSInterfaceData *		ifd;
-	
-	check( inMDNS );
-	check( inMDNS->p );
-	check( inName );
-	
-	// Search for an interface with the specified name,
-	
-	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if( strcmp( ifd->name, inName ) == 0 )
-		{
-			break;
-		}
-	}
-	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
-	
-	// Success!
-	
-	if( outID )
-	{
-		*outID = (mDNSInterfaceID) ifd;
-	}
-	err = mStatus_NoError;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIDToInfo
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
-{
-	mStatus					err;
-	mDNSInterfaceData *		ifd;
-	
-	check( inMDNS );
-	check( inID );
-	check( outInfo );
-	
-	// Search for an interface with the specified ID,
-	
-	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if( ifd == (mDNSInterfaceData *) inID )
-		{
-			break;
-		}
-	}
-	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
-	
-	// Success!
-	
-	outInfo->name 	= ifd->name;
-	outInfo->ip 	= ifd->interfaceInfo.ip;
-	err 			= mStatus_NoError;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIDfromInterfaceIndex
-//===========================================================================================================================
-
-mDNSexport mDNSInterfaceID	mDNSPlatformInterfaceIDfromInterfaceIndex( mDNS * const inMDNS, mDNSu32 inIndex )
-{
-	mDNSInterfaceID		id;
-	
-	id = mDNSNULL;
-	if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
-	{
-		id = mDNSInterface_LocalOnly;
-	}
-	else if( inIndex != 0 )
-	{
-		mDNSInterfaceData *		ifd;
-		
-		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-		{
-			if( ( ifd->scopeID == inIndex ) && ifd->interfaceInfo.InterfaceActive )
-			{
-				id = ifd->interfaceInfo.InterfaceID;
-				break;
-			}
-		}
-		check( ifd );
-	}
-	return( id );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIndexfromInterfaceID
-//===========================================================================================================================
-	
-mDNSexport mDNSu32	mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSBool suppressNetworkChange )
-{
-	mDNSu32		index;
-	
-	(void) suppressNetworkChange;
-
-	index = 0;
-	if( inID == mDNSInterface_LocalOnly )
-	{
-		index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
-	}
-	else if( inID )
-	{
-		mDNSInterfaceData *		ifd;
-		
-		// Search active interfaces.
-		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-		{
-			if( (mDNSInterfaceID) ifd == inID )
-			{
-				index = ifd->scopeID;
-				break;
-			}
-		}
-		
-		// Search inactive interfaces too so remove events for inactive interfaces report the old interface index.
-		
-		if( !ifd )
-		{
-			for( ifd = inMDNS->p->inactiveInterfaceList; ifd; ifd = ifd->next )
-			{
-				if( (mDNSInterfaceID) ifd == inID )
-				{
-					index = ifd->scopeID;
-					break;
-				}
-			}
-		}
-		check( ifd );
-	}
-	return( index );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPSocket
-//===========================================================================================================================
-
-TCPSocket *
-mDNSPlatformTCPSocket
-	(
-	TCPSocketFlags		flags,
-	mDNSAddr_Type		addrType,
-	mDNSIPPort			*	port,
-	domainname			*	hostname,
-	mDNSBool			useBackgroundTrafficClass
-	)
-{
-	TCPSocket *		sock    = NULL;
-	u_long				on		= 1;  // "on" for setsockopt
-	struct sockaddr_in	saddr;
-	int					len;
-	mStatus				err		= mStatus_NoError;
-
-	DEBUG_UNUSED( addrType );
-	DEBUG_UNUSED( hostname );
-	DEBUG_UNUSED( useBackgroundTrafficClass );
-
-	require_action( flags == 0, exit, err = mStatus_UnsupportedErr );
-
-	// Setup connection data object
-
-	sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
-	sock->fd		= INVALID_SOCKET;
-	sock->flags		= flags;
-	sock->m			= &gMDNSRecord;
-
-	mDNSPlatformMemZero(&saddr, sizeof(saddr));
-	saddr.sin_family		= AF_INET;
-	saddr.sin_addr.s_addr	= htonl( INADDR_ANY );
-	saddr.sin_port			= port->NotAnInteger;
-	
-	// Create the socket
-
-	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
-	err = translate_errno( sock->fd != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// bind
-
-	err = bind( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr )  );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// Set it to be non-blocking
-
-	err = ioctlsocket( sock->fd, FIONBIO, &on );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// Get port number
-
-	mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
-	len = sizeof( saddr );
-
-	err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	port->NotAnInteger = saddr.sin_port;
-
-exit:
-
-	if ( err && sock )
-	{
-		TCPCloseSocket( sock );
-		free( sock );
-		sock = mDNSNULL;
-	}
-
-	return sock;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPConnect
-//===========================================================================================================================
-
-mStatus
-mDNSPlatformTCPConnect
-	(
-	TCPSocket			*	sock,
-	const mDNSAddr		*	inDstIP, 
-	mDNSOpaque16 			inDstPort, 
-	mDNSInterfaceID			inInterfaceID,
-	TCPConnectionCallback	inCallback, 
-	void *					inContext
-	)
-{
-	struct sockaddr_in	saddr;
-	mStatus				err		= mStatus_NoError;
-
-	DEBUG_UNUSED( inInterfaceID );
-
-	if ( inDstIP->type != mDNSAddrType_IPv4 )
-	{
-		LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
-		return mStatus_UnknownErr;
-	}
-
-	// Setup connection data object
-
-	sock->tcpConnectionCallback = inCallback;
-	sock->userContext	= inContext;
-
-	mDNSPlatformMemZero(&saddr, sizeof(saddr));
-	saddr.sin_family	= AF_INET;
-	saddr.sin_port		= inDstPort.NotAnInteger;
-	memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
-
-	// Try and do connect
-
-	err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
-	require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
-	sock->connected	= !err ? TRUE : FALSE;
-
-	err = mDNSPollRegisterSocket( sock->fd, FD_CONNECT | FD_READ | FD_CLOSE, TCPSocketNotification, sock );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( !err )
-	{
-		err = sock->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
-	}
-
-	return err;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPAccept
-//===========================================================================================================================
-
-mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
-	{
-	TCPSocket	*	sock = NULL;
-	mStatus							err = mStatus_NoError;
-
-	require_action( !flags, exit, err = mStatus_UnsupportedErr );
-
-	sock = malloc( sizeof( TCPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	
-	mDNSPlatformMemZero( sock, sizeof( *sock ) );
-
-	sock->fd	= fd;
-	sock->flags = flags;
-
-exit:
-
-	if ( err && sock )
-	{
-		free( sock );
-		sock = NULL;
-	}
-
-	return sock;
-	}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPCloseConnection
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformTCPCloseConnection( TCPSocket *sock )
-{
-	check( sock );
-
-	if ( sock )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformTCPCloseConnection 0x%x:%d\n", sock, sock->fd );
-
-		if ( sock->fd != INVALID_SOCKET )
-		{
-			mDNSPollUnregisterSocket( sock->fd );
-			closesocket( sock->fd );
-			sock->fd = INVALID_SOCKET;
-		}
-
-		free( sock );
-	}
-}
-
-//===========================================================================================================================
-//	mDNSPlatformReadTCP
-//===========================================================================================================================
-
-mDNSexport long	mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
-{
-	int			nread;
-	OSStatus    err;
-
-	*closed = mDNSfalse;
-	nread = recv( sock->fd, inBuffer, inBufferSize, 0 );
-	err = translate_errno( ( nread >= 0 ), WSAGetLastError(), mStatus_UnknownErr );
-	
-	if ( nread > 0 )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformReadTCP: 0x%x:%d read %d bytes\n", sock, sock->fd, nread );
-	}
-	else if ( !nread )
-	{
-		*closed = mDNStrue;
-	}
-	else if ( err == WSAECONNRESET )
-	{
-		*closed = mDNStrue;
-		nread = 0;
-	}
-	else if ( err == WSAEWOULDBLOCK )
-	{
-		nread = 0;
-	}
-	else
-	{
-		LogMsg( "ERROR: mDNSPlatformReadTCP - recv: %d\n", err );
-		nread = -1;
-	}
-
-	return nread;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformWriteTCP
-//===========================================================================================================================
-
-mDNSexport long	mDNSPlatformWriteTCP( TCPSocket *sock, const char *inMsg, unsigned long inMsgSize )
-{
-	int			nsent;
-	OSStatus	err;
-
-	nsent = send( sock->fd, inMsg, inMsgSize, 0 );
-
-	err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	if ( nsent < 0)
-	{
-		nsent = 0;
-	}
-		
-exit:
-
-	return nsent;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPGetFD
-//===========================================================================================================================
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
-{
-	return ( int ) sock->fd;
-}
-
-//===========================================================================================================================
-//	TCPSocketNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	TCPSocket				*tcpSock = ( TCPSocket* ) context;
-	TCPConnectionCallback	callback;
-	int						err;
-
-	DEBUG_UNUSED( sock );
-
-	require_action( tcpSock, exit, err = mStatus_BadParamErr );
-	callback = tcpSock->tcpConnectionCallback;
-	require_action( callback, exit, err = mStatus_BadParamErr );
-
-	if ( event && ( event->lNetworkEvents & FD_CONNECT ) )
-	{
-		if ( event->iErrorCode[ FD_CONNECT_BIT ] == 0 )
-		{
-			callback( tcpSock, tcpSock->userContext, mDNStrue, 0 );
-			tcpSock->connected = mDNStrue;
-		}
-		else
-		{
-			callback( tcpSock, tcpSock->userContext, mDNSfalse, event->iErrorCode[ FD_CONNECT_BIT ] );
-		}
-	}
-	else
-	{
-		callback( tcpSock, tcpSock->userContext, mDNSfalse, 0 );
-	}
-
-exit:
-
-	return;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformUDPSocket
-//===========================================================================================================================
-
-mDNSexport UDPSocket* mDNSPlatformUDPSocket( const mDNSIPPort requestedport )
-{
-	UDPSocket*	sock	= NULL;
-	mDNSIPPort	port	= requestedport;
-	mStatus		err		= mStatus_NoError;
-	unsigned	i;
-
-	// Setup connection data object
-
-	sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	memset( sock, 0, sizeof( UDPSocket ) );
-
-	// Create the socket
-
-	sock->fd			= INVALID_SOCKET;
-	sock->recvMsgPtr	= gMDNSRecord.p->unicastSock4.recvMsgPtr;
-	sock->addr			= gMDNSRecord.p->unicastSock4.addr;
-	sock->ifd			= NULL;
-	sock->m				= &gMDNSRecord;
-
-	// Try at most 10000 times to get a unique random port
-
-	for (i=0; i<10000; i++)
-	{
-		struct sockaddr_in saddr;
-
-		saddr.sin_family		= AF_INET;
-		saddr.sin_addr.s_addr	= 0;
-
-		// The kernel doesn't do cryptographically strong random port
-		// allocation, so we do it ourselves here
-
-		if (mDNSIPPortIsZero(requestedport))
-		{
-			port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
-		}
-
-		saddr.sin_port = port.NotAnInteger;
-
-		err = SetupSocket( (struct sockaddr*) &saddr, port, &sock->fd );
-		if (!err) break;
-	}
-
-	require_noerr( err, exit );
-
-	// Set the port
-
-	sock->port = port;
-
-	// Arm the completion routine
-
-	err = mDNSPollRegisterSocket( sock->fd, FD_READ, UDPSocketNotification, sock );
-	require_noerr( err, exit ); 
-
-	// Bookkeeping
-
-	sock->next		= gUDPSockets;
-	gUDPSockets		= sock;
-	gUDPNumSockets++;
-
-exit:
-
-	if ( err && sock )
-	{
-		UDPCloseSocket( sock );
-		free( sock );
-		sock = NULL;
-	}
-
-	return sock;
-}
-	
-//===========================================================================================================================
-//	mDNSPlatformUDPClose
-//===========================================================================================================================
-	
-mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
-{
-	UDPSocket	*	current  = gUDPSockets;
-	UDPSocket	*	last = NULL;
-
-	while ( current )
-	{
-		if ( current == sock )
-		{
-			if ( last == NULL )
-			{
-				gUDPSockets = sock->next;
-			}
-			else
-			{
-				last->next = sock->next;
-			}
-
-			UDPCloseSocket( sock );
-			free( sock );
-
-			gUDPNumSockets--;
-
-			break;
-		}
-
-		last	= current;
-		current	= current->next;
-	}
-}
-
-//===========================================================================================================================
-//	mDNSPlatformSendUDP
-//===========================================================================================================================
-
-mDNSexport mStatus
-	mDNSPlatformSendUDP( 
-		const mDNS * const			inMDNS, 
-		const void * const	        inMsg, 
-		const mDNSu8 * const		inMsgEnd, 
-		mDNSInterfaceID 			inInterfaceID, 
-		UDPSocket *					inSrcSocket,
-		const mDNSAddr *			inDstIP, 
-		mDNSIPPort 					inDstPort,
-		mDNSBool 					useBackgroundTrafficClass )
-{
-	SOCKET						sendingsocket = INVALID_SOCKET;
-	mStatus						err = mStatus_NoError;
-	mDNSInterfaceData *			ifd = (mDNSInterfaceData*) inInterfaceID;
-	struct sockaddr_storage		addr;
-	int							n;
-	
-	DEBUG_USE_ONLY( inMDNS );
-	DEBUG_USE_ONLY( useBackgroundTrafficClass );
-	
-	n = (int)( inMsgEnd - ( (const mDNSu8 * const) inMsg ) );
-	check( inMDNS );
-	check( inMsg );
-	check( inMsgEnd );
-	check( inDstIP );
-	
-	dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
-	
-	if( inDstIP->type == mDNSAddrType_IPv4 )
-	{
-		struct sockaddr_in *		sa4;
-		
-		sa4						= (struct sockaddr_in *) &addr;
-		sa4->sin_family			= AF_INET;
-		sa4->sin_port			= inDstPort.NotAnInteger;
-		sa4->sin_addr.s_addr	= inDstIP->ip.v4.NotAnInteger;
-		sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
-
-		if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
-	}
-	else if( inDstIP->type == mDNSAddrType_IPv6 )
-	{
-		struct sockaddr_in6 *		sa6;
-		
-		sa6					= (struct sockaddr_in6 *) &addr;
-		sa6->sin6_family	= AF_INET6;
-		sa6->sin6_port		= inDstPort.NotAnInteger;
-		sa6->sin6_flowinfo	= 0;
-		sa6->sin6_addr		= *( (struct in6_addr *) &inDstIP->ip.v6 );
-		sa6->sin6_scope_id	= 0;	// Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
-		sendingsocket		= ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: dst is not an IPv4 or IPv6 address (type=%d)\n", __ROUTINE__, inDstIP->type );
-		err = mStatus_BadParamErr;
-		goto exit;
-	}
-	
-	if (IsValidSocket(sendingsocket))
-	{
-		n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
-		err = translate_errno( n > 0, errno_compat(), kWriteErr );
-
-		if ( err )
-		{
-			// Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
-
-			if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
-			{
-				err = mStatus_TransientErr;
-			}
-			else
-			{
-				require_noerr( err, exit );
-			}
-		}
-	}
-	
-exit:
-	return( err );
-}
-
-mDNSexport void mDNSPlatformUpdateProxyList( const mDNSInterfaceID InterfaceID )
-{
-	DEBUG_UNUSED( InterfaceID );
-}
-
-mDNSexport void mDNSPlatformSetAllowSleep( mDNSBool allowSleep, const char *reason )
-{
-	DEBUG_UNUSED( allowSleep );
-	DEBUG_UNUSED( reason );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformSendRawPacket
-//===========================================================================================================================
-
-mDNSexport void mDNSPlatformSendWakeupPacket( mDNSInterfaceID InterfaceID, char *ethaddr, char *ipaddr, int iteration )
-{
-	unsigned char			mac[ 6 ];
-	unsigned char			buf[ 102 ];
-	char					hex[ 3 ] = { 0 };
-	unsigned char			*bufPtr = buf;
-	MulticastWakeupStruct	*info;
-	int						i;
-	mStatus					err;
-
-	(void) InterfaceID; // unused
-	(void) ipaddr;      // unused
-	(void) iteration;   // unused
-
-	require_action( ethaddr, exit, err = mStatus_BadParamErr );
-
-	for ( i = 0; i < 6; i++ )
-	{
-		memcpy( hex, ethaddr + ( i * 3 ), 2 );
-		mac[ i ] = ( unsigned char ) strtoul( hex, NULL, 16 );
-	}
-
-	memset( buf, 0, sizeof( buf ) );
-
-	for ( i = 0; i < 6; i++ )
-	{
-		*bufPtr++ = 0xff;
-	}
-	
-	for ( i = 0; i < 16; i++ )
-	{
-		memcpy( bufPtr, mac, sizeof( mac ) );
-		bufPtr += sizeof( mac );
-	}
-
-	info = ( MulticastWakeupStruct* ) malloc( sizeof( MulticastWakeupStruct ) );
-	require_action( info, exit, err = mStatus_NoMemoryErr );
-	info->inMDNS = &gMDNSRecord;
-	memset( &info->addr, 0, sizeof( info->addr ) );
-	info->addr.sin_family = AF_INET;
-	info->addr.sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-	info->addr.sin_port = htons( 9 );
-	info->addrLen = sizeof( info->addr );
-	memcpy( info->data, buf, sizeof( buf ) );
-	info->dataLen = sizeof( buf );
-	info->numTries  = kMulticastWakeupNumTries;
-	info->msecSleep = kMulticastWakeupSleepBetweenTries;
-
-	_beginthread( SendMulticastWakeupPacket, 0, ( void* ) info );
-
-exit:
-
-	return;
-}
-
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
-{
-	DEBUG_UNUSED( rr );
-	DEBUG_UNUSED( InterfaceID );
-
-	return mDNStrue;
-}
- 
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-	DEBUG_UNUSED( q );
-	DEBUG_UNUSED( intf );
-
-	return mDNStrue;
-}
- 
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( msg );
-	DEBUG_UNUSED( end );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-// Used for debugging purposes. For now, just set the buffer to zero
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-	{
-	DEBUG_UNUSED( te );
-	if (bufsize) buf[0] = 0;
-	}
-
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry( const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID )
-{
-	DEBUG_UNUSED( tpa );
-	DEBUG_UNUSED( tha );
-	DEBUG_UNUSED( InterfaceID );
-}
-
-mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( msg );
-	DEBUG_UNUSED( end );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
-	{
-	DEBUG_UNUSED( tpa );
-	DEBUG_UNUSED( tha );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
-	{
-	dlog( kDebugLevelInfo, "%s\n", msg );
-	}
-
-mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, mDNSLogLevel_t level )
-	{
-	int type;
-	
-	DEBUG_UNUSED( ident );
-
-	switch (level)
-	{
-		case MDNS_LOG_FAULT:	type = EVENTLOG_ERROR_TYPE;			break;
-		case MDNS_LOG_ERROR:	type = EVENTLOG_ERROR_TYPE;			break;
-		case MDNS_LOG_WARNING:	type = EVENTLOG_WARNING_TYPE;		break;
-		case MDNS_LOG_DEFAULT:	type = EVENTLOG_INFORMATION_TYPE;	break;
-		case MDNS_LOG_INFO:		type = EVENTLOG_INFORMATION_TYPE;	break;
-		case MDNS_LOG_DEBUG:	type = EVENTLOG_INFORMATION_TYPE;	break;
-		default:				type = EVENTLOG_INFORMATION_TYPE;	break;
-	}
-
-	gMDNSRecord.p->reportStatusFunc( type, msg );
-	dlog( kDebugLevelInfo, "%s\n", msg );
-	}
-
-mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
-	{
-	DEBUG_UNUSED( src );
-	DEBUG_UNUSED( dst );
-	}
-
-//===========================================================================================================================
-//	mDNSPlatformTLSSetupCerts
-//===========================================================================================================================
-
-mDNSexport mStatus
-mDNSPlatformTLSSetupCerts(void)
-{
-	return mStatus_UnsupportedErr;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTLSTearDownCerts
-//===========================================================================================================================
-
-mDNSexport void
-mDNSPlatformTLSTearDownCerts(void)
-{
-}
-
-//===========================================================================================================================
-//	mDNSPlatformSetDNSConfig
-//===========================================================================================================================
-
-mDNSlocal void SetDNSServers( void );
-mDNSlocal void SetSearchDomainList( void );
-
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig( mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains, mDNSBool ackConfig )
-{
-	(void) ackConfig;
-
-	if (setservers) SetDNSServers();
-	if (setsearch) SetSearchDomainList();
-	
-	if ( fqdn )
-	{
-		GetDDNSFQDN( fqdn );
-	}
-
-	if ( browseDomains )
-	{
-		GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
-	}
-
-	if ( regDomains )
-	{
-		GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
-	}
-	return mDNStrue;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformDynDNSHostNameStatusChanged
-//===========================================================================================================================
-
-mDNSexport void
-mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-	char		uname[MAX_ESCAPED_DOMAIN_NAME];
-	BYTE		bStatus;
-	LPCTSTR		name;
-	HKEY		key = NULL;
-	mStatus		err;
-	char	*	p;
-	
-	ConvertDomainNameToCString(dname, uname);
-	
-	p = uname;
-
-	while (*p)
-	{
-		*p = (char) tolower(*p);
-		if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
-		p++;
-	}
-
-	check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
-	name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
-	err = RegCreateKey(HKEY_CURRENT_USER, name, &key);
-	require_noerr( err, exit );
-
-	bStatus = ( status ) ? 0 : 1;
-	err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return;
-}
-
-//===========================================================================================================================
-//	SetDomainSecrets
-//===========================================================================================================================
-
-// This routine needs to be called whenever the system secrets database changes.
-// We call it from DynDNSConfigDidChange and mDNSPlatformInit
-
-void
-SetDomainSecrets( mDNS * const m )
-{
-	DomainAuthInfo *ptr;
-	domainname		fqdn;
-	DNameListElem * regDomains = NULL;
-
-	// Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
-	// In the case where the user simultaneously removes their DDNS host name and the key
-	// for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
-	// server before it loses access to the necessary key. Otherwise, we'd leave orphaned
-	// address records behind that we no longer have permission to delete.
-	
-	for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
-		ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
-
-	GetDDNSFQDN( &fqdn );
-
-	if ( fqdn.c[ 0 ] )
-	{
-		SetDomainSecret( m, &fqdn );
-	}
-
-	GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
-
-	while ( regDomains )
-	{
-		DNameListElem * current = regDomains;
-		SetDomainSecret( m, &current->name );
-		regDomains = regDomains->next;
-		free( current );
-	}
-}
-
-//===========================================================================================================================
-//	SetSearchDomainList
-//===========================================================================================================================
-
-mDNSlocal void SetDomainFromDHCP( void );
-mDNSlocal void SetReverseMapSearchDomainList( void );
-
-mDNSlocal void
-SetSearchDomainList( void )
-{
-	char			*	searchList	= NULL;
-	DWORD				searchListLen;
-	//DNameListElem	*	head = NULL;
-	//DNameListElem	*	current = NULL;
-	char			*	tok;
-	HKEY				key;
-	mStatus				err;
-
-	err = RegCreateKey(HKEY_CURRENT_USER, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key);
-	require_noerr( err, exit );
-
-	err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
-	require_noerr( err, exit );
-
-	// Windows separates the search domains with ','
-
-	tok = strtok( searchList, "," );
-	while ( tok )
-	{
-		if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
-			mDNS_AddSearchDomain_CString(tok, mDNSNULL);
-		tok = strtok( NULL, "," );
-	}
-
-exit:
-
-	if ( searchList ) 
-	{
-		free( searchList );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	SetDomainFromDHCP();
-	SetReverseMapSearchDomainList();
-}
-
-//===========================================================================================================================
-//	SetReverseMapSearchDomainList
-//===========================================================================================================================
-
-mDNSlocal void
-SetReverseMapSearchDomainList( void )
-{
-	struct ifaddrs	*	ifa;
-
-	ifa = myGetIfAddrs( 1 );
-	while (ifa)
-	{
-		mDNSAddr addr;
-		
-		if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
-		{
-			mDNSAddr	netmask;
-			char		buffer[256];
-			
-			if (!SetupAddr(&netmask, ifa->ifa_netmask))
-			{
-				_snprintf(buffer, sizeof( buffer ), "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
-																			   addr.ip.v4.b[2] & netmask.ip.v4.b[2],
-																			   addr.ip.v4.b[1] & netmask.ip.v4.b[1],
-																			   addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
-				mDNS_AddSearchDomain_CString(buffer, mDNSNULL);
-			}
-		}
-	
-		ifa = ifa->ifa_next;
-	}
-
-	return;
-}
-
-//===========================================================================================================================
-//	SetDNSServers
-//===========================================================================================================================
-
-mDNSlocal void
-SetDNSServers( void )
-{
-	PIP_PER_ADAPTER_INFO	pAdapterInfo	=	NULL;
-	FIXED_INFO			*	fixedInfo	= NULL;
-	ULONG					bufLen		= 0;	
-	IP_ADDR_STRING		*	dnsServerList;
-	IP_ADDR_STRING		*	ipAddr;
-	DWORD					index;
-	int						i			= 0;
-	mStatus					err			= kUnknownErr;
-
-	// Get the primary interface.
-
-	index = GetPrimaryInterface();
-
-	// This should have the interface index of the primary index.  Fall back in cases where
-	// it can't be determined.
-
-	if ( index )
-	{
-		bufLen = 0;
-
-		for ( i = 0; i < 100; i++ )
-		{
-			err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
-
-			if ( err != ERROR_BUFFER_OVERFLOW )
-			{
-				break;
-			}
-
-			pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
-			require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
-		}
-
-		require_noerr( err, exit );
-
-		dnsServerList = &pAdapterInfo->DnsServerList;
-	}
-	else
-	{
-		bufLen = sizeof( FIXED_INFO );
-
-		for ( i = 0; i < 100; i++ )
-		{
-			if ( fixedInfo )
-			{
-				GlobalFree( fixedInfo );
-				fixedInfo = NULL;
-			}
-
-			fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
-			require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
-	   
-			err = GetNetworkParams( fixedInfo, &bufLen );
-
-			if ( err != ERROR_BUFFER_OVERFLOW )
-			{
-				break;
-			}
-		}
-
-		require_noerr( err, exit );
-
-		dnsServerList = &fixedInfo->DnsServerList;
-	}
-
-	for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
-	{
-		mDNSAddr addr;
-		err = StringToAddress( &addr, ipAddr->IpAddress.String );
-		if ( !err ) mDNS_AddDNSServer( &gMDNSRecord, mDNSNULL, mDNSInterface_Any, 0, &addr, UnicastDNSPort, kScopeNone, DEFAULT_UDNS_TIMEOUT, mDNSfalse, mDNSfalse, mDNSfalse, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse );
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	if ( fixedInfo )
-	{
-		GlobalFree( fixedInfo );
-	}
-}
-
-//===========================================================================================================================
-//	SetDomainFromDHCP
-//===========================================================================================================================
-
-mDNSlocal void
-SetDomainFromDHCP( void )
-{
-	int					i			= 0;
-	IP_ADAPTER_INFO *	pAdapterInfo;
-	IP_ADAPTER_INFO *	pAdapter;
-	DWORD				bufLen;
-	DWORD				index;
-	HKEY				key = NULL;
-	LPSTR				domain = NULL;
-	DWORD				dwSize;
-	mStatus				err = mStatus_NoError;
-
-	pAdapterInfo	= NULL;
-	
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-
-		if ( err != ERROR_BUFFER_OVERFLOW )
-		{
-			break;
-		}
-
-		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
-		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-	}
-
-	require_noerr( err, exit );
-
-	index = GetPrimaryInterface();
-
-	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
-	{
-		if ( pAdapter->IpAddressList.IpAddress.String[0] &&
-			 pAdapter->GatewayList.IpAddress.String[0] &&
-			 ( !index || ( pAdapter->Index == index ) ) )
-		{
-			// Found one that will work
-
-			char keyName[1024];
-
-			_snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
-
-			err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
-			require_noerr( err, exit );
-
-			err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
-			check_noerr( err );
-
-			if ( !domain || !domain[0] )
-			{
-				if ( domain )
-				{
-					free( domain );
-					domain = NULL;
-				}
-
-				err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
-				check_noerr( err );
-			}
-
-			if ( domain && domain[0] ) mDNS_AddSearchDomain_CString(domain, mDNSNULL);
-
-			break;
-		}
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	if ( domain )
-	{
-		free( domain );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-//===========================================================================================================================
-//	mDNSPlatformGetPrimaryInterface
-//===========================================================================================================================
-
-mDNSexport mStatus
-mDNSPlatformGetPrimaryInterface( mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router )
-{
-	IP_ADAPTER_INFO *	pAdapterInfo;
-	IP_ADAPTER_INFO *	pAdapter;
-	DWORD				bufLen;
-	int					i;
-	BOOL				found;
-	DWORD				index;
-	mStatus				err = mStatus_NoError;
-
-	*v6 = zeroAddr;
-
-	pAdapterInfo	= NULL;
-	bufLen			= 0;
-	found			= FALSE;
-
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-
-		if ( err != ERROR_BUFFER_OVERFLOW )
-		{
-			break;
-		}
-
-		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
-		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-	}
-
-	require_noerr( err, exit );
-
-	index = GetPrimaryInterface();
-
-	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
-	{
-		if ( pAdapter->IpAddressList.IpAddress.String[0] &&
-			 pAdapter->GatewayList.IpAddress.String[0] &&
-			 ( StringToAddress( v4, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
-			 ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
-			 ( !index || ( pAdapter->Index == index ) ) )
-		{
-			// Found one that will work
-
-			if ( pAdapter->AddressLength == sizeof( gMDNSRecord.PrimaryMAC ) )
-			{
-				memcpy( &gMDNSRecord.PrimaryMAC, pAdapter->Address, pAdapter->AddressLength );
-			}
-
-			found = TRUE;
-			break;
-		}
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	return err;
-}
-
-mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
-{
-	(void) sadd; 	// Unused
-	(void) dadd; 	// Unused
-	(void) lport; 	// Unused
-	(void) rport; 	// Unused
-	(void) seq; 	// Unused
-	(void) ack; 	// Unused
-	(void) win;		// Unused
-}
-
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr( mDNSAddr *raddr )
-{
-	(void) raddr;	// Unused
-
-	return mStatus_UnsupportedErr;
-}
-
-mDNSexport  mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
-{
-	(void) spsaddr; // Unused
-	(void) ifname;  // Unused
-
-	return mStatus_UnsupportedErr;
-}
-
-mDNSexport  mStatus    mDNSPlatformClearSPSData(void)
-{
-	return mStatus_UnsupportedErr;
-}
-
-mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length)
-{
-	(void) ifname;	// Unused
-	(void) msg;     // Unused
-	(void) length;  // Unused
-	return mStatus_UnsupportedErr;
-}
-
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo( mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti )
-{
-	(void) laddr; 	// Unused
-	(void) raddr; 	// Unused
-	(void) lport; 	// Unused
-	(void) rport; 	// Unused
-	(void) mti; 	// Unused
-
-	return mStatus_UnsupportedErr;
-}
-
-mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q)
-	{
-	(void) sock;
-	(void) transType;
-	(void) addrType;
-	(void) q;
-	}
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-	{
-	return 0;
-	}
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-	DEBUG_UNUSED( sock );
- 
-	return (mDNSu16)-1;
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-	DEBUG_UNUSED( InterfaceID );
-	
-	return mDNSfalse;
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	debugf_
-//===========================================================================================================================
-#if( MDNS_DEBUGMSGS )
-mDNSexport void	debugf_( const char *inFormat, ... )
-{
-	char		buffer[ 512 ];
-	va_list		args;
-	mDNSu32		length;
-	
-	va_start( args, inFormat );
-	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
-	va_end( args );
-	
-	dlog( kDebugLevelInfo, "%s\n", buffer );
-}
-#endif
-
-//===========================================================================================================================
-//	verbosedebugf_
-//===========================================================================================================================
-
-#if( MDNS_DEBUGMSGS > 1 )
-mDNSexport void	verbosedebugf_( const char *inFormat, ... )
-{
-	char		buffer[ 512 ];
-	va_list		args;
-	mDNSu32		length;
-	
-	va_start( args, inFormat );
-	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
-	va_end( args );
-	
-	dlog( kDebugLevelVerbose, "%s\n", buffer );
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Platform Internals  ==
-#endif
-
-//===========================================================================================================================
-//	SetupNiceName
-//===========================================================================================================================
-
-mStatus	SetupNiceName( mDNS * const inMDNS )
-{
-	HKEY		descKey = NULL;
-	char		utf8[ 256 ];
-	LPCTSTR		s;
-	LPWSTR		joinName;
-	NETSETUP_JOIN_STATUS joinStatus;
-	mStatus		err = 0;
-	DWORD		namelen;
-	BOOL		ok;
-	
-	check( inMDNS );
-	
-	// Set up the nice name.
-	utf8[0] = '\0';
-
-	// First try and open the registry key that contains the computer description value
-	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
-	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
-	check_translated_errno( err == 0, errno_compat(), kNameErr );
-
-	if ( !err )
-	{
-		TCHAR	desc[256];
-		DWORD	descSize = sizeof( desc );
-
-		// look for the computer description
-		err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
-		
-		if ( !err )
-		{
-			err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
-		}
-
-		if ( err )
-		{
-			utf8[ 0 ] = '\0';
-		}
-	}
-
-	// if we can't find it in the registry, then use the hostname of the machine
-	if ( err || ( utf8[ 0 ] == '\0' ) )
-	{
-		TCHAR hostname[256];
-		
-		namelen = sizeof( hostname ) / sizeof( TCHAR );
-
-		ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
-		err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
-		check_noerr( err );
-		
-		if( !err )
-		{
-			err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
-		}
-
-		if ( err )
-		{
-			utf8[ 0 ] = '\0';
-		}
-	}
-
-	// if we can't get the hostname
-	if ( err || ( utf8[ 0 ] == '\0' ) )
-	{
-		// Invalidate name so fall back to a default name.
-		
-		strcpy_s( utf8, sizeof( utf8 ), kMDNSDefaultName );
-	}
-
-	utf8[ sizeof( utf8 ) - 1 ]	= '\0';	
-	inMDNS->nicelabel.c[ 0 ]	= (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
-	memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
-	
-	if ( descKey )
-	{
-		RegCloseKey( descKey );
-	}
-
-	ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
-	ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
-
-	namelen = sizeof( inMDNS->p->nbname );
-	ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
-	check( ok );
-	if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
-
-	err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
-	check ( err == NERR_Success );
-	if ( err == NERR_Success )
-	{
-		if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
-		{
-			err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
-			check( !err );
-			if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
-		}
-
-		NetApiBufferFree( joinName );
-		joinName = NULL;
-	}
-
-	err = 0;
-
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupHostName
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupHostName( mDNS * const inMDNS )
-{
-	mStatus		err = 0;
-	char		tempString[ 256 ];
-	DWORD		tempStringLen;
-	domainlabel tempLabel;
-	BOOL		ok;
-	
-	check( inMDNS );
-
-	// Set up the nice name.
-	tempString[ 0 ] = '\0';
-
-	// use the hostname of the machine
-	tempStringLen = sizeof( tempString );
-	ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
-	err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
-	check_noerr( err );
-
-	// if we can't get the hostname
-	if( err || ( tempString[ 0 ] == '\0' ) )
-	{
-		// Invalidate name so fall back to a default name.
-		
-		strcpy_s( tempString, sizeof( tempString ), kMDNSDefaultName );
-	}
-
-	tempString[ sizeof( tempString ) - 1 ] = '\0';
-	tempLabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL );
-	memcpy( &tempLabel.c[ 1 ], tempString, tempLabel.c[ 0 ] );
-	
-	// Set up the host name.
-	
-	ConvertUTF8PstringToRFC1034HostLabel( tempLabel.c, &inMDNS->hostlabel );
-	if( inMDNS->hostlabel.c[ 0 ] == 0 )
-	{
-		// Nice name has no characters that are representable as an RFC1034 name (e.g. Japanese) so use the default.
-		
-		MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
-	}
-
-	check( inMDNS->hostlabel.c[ 0 ] != 0 );
-	
-	mDNS_SetFQDN( inMDNS );
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
-	
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupName
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupName( mDNS * const inMDNS )
-{
-	mStatus		err = 0;
-	
-	check( inMDNS );
-	
-	err = SetupNiceName( inMDNS );
-	check_noerr( err );
-
-	err = SetupHostName( inMDNS );
-	check_noerr( err );
-
-	return err;
-}
-
-//===========================================================================================================================
-//	SetupInterfaceList
-//===========================================================================================================================
-
-mStatus	SetupInterfaceList( mDNS * const inMDNS )
-{
-	mStatus						err;
-	mDNSInterfaceData **		next;
-	mDNSInterfaceData *			ifd;
-	struct ifaddrs *			addrs;
-	struct ifaddrs *			p;
-	struct ifaddrs *			loopbackv4;
-	struct ifaddrs *			loopbackv6;
-	u_int						flagMask;
-	u_int						flagTest;
-	mDNSBool					foundv4;
-	mDNSBool					foundv6;
-	mDNSBool					foundUnicastSock4DestAddr;
-	mDNSBool					foundUnicastSock6DestAddr;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-	
-	inMDNS->p->registeredLoopback4	= mDNSfalse;
-#if _WIN64
-	inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFFFFFFFFFF;
-#else
-	inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
-#endif
-	addrs							= NULL;
-	foundv4							= mDNSfalse;
-	foundv6							= mDNSfalse;
-	foundUnicastSock4DestAddr		= mDNSfalse;
-	foundUnicastSock6DestAddr		= mDNSfalse;
-	
-	// Tear down any existing interfaces that may be set up.
-	
-	TearDownInterfaceList( inMDNS );
-
-	// Set up the name of this machine.
-	
-	err = SetupName( inMDNS );
-	check_noerr( err );
-
-	// Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
-	// can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
-	
-	err = getifaddrs( &addrs );
-	require_noerr( err, exit );
-	
-	loopbackv4	= NULL;
-	loopbackv6	= NULL;
-	next		= &inMDNS->p->interfaceList;
-
-	flagMask = IFF_UP | IFF_MULTICAST;
-	flagTest = IFF_UP | IFF_MULTICAST;
-	
-#if( MDNS_WINDOWS_ENABLE_IPV4 )
-	for( p = addrs; p; p = p->ifa_next )
-	{
-		if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-		{
-			continue;
-		}
-		if( p->ifa_flags & IFF_LOOPBACK )
-		{
-			if( !loopbackv4 )
-			{
-				loopbackv4 = p;
-			}
-			continue;
-		}
-		dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
-		
-		err = SetupInterface( inMDNS, p, &ifd );
-		require_noerr( err, exit );
-
-		// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
-		// register him, but we also want to note that we haven't found a v4 interface
-		// so that we register loopback so same host operations work
-		
-		if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
-		{
-			foundv4 = mDNStrue;
-		}
-
-		if ( p->ifa_dhcpEnabled && ( p->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
-		{
-			inMDNS->p->nextDHCPLeaseExpires = p->ifa_dhcpLeaseExpires;
-		}
-
-		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-		// of determing the destination address of a packet that is sent to us.
-		// For multicast packets, that's easy to determine.  But for the unicast
-		// sockets, we'll fake it by taking the address of the first interface
-		// that is successfully setup.
-
-		if ( !foundUnicastSock4DestAddr )
-		{
-			inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
-			foundUnicastSock4DestAddr = TRUE;
-		}
-			
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-#endif
-	
-	// Set up IPv6 interface(s) after IPv4 is set up (see IPv4 notes above for reasoning).
-	
-#if( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		for( p = addrs; p; p = p->ifa_next )
-		{
-			if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET6 ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-			{
-				continue;
-			}
-			if( p->ifa_flags & IFF_LOOPBACK )
-			{
-				if( !loopbackv6 )
-				{
-					loopbackv6 = p;
-				}
-				continue;
-			}
-			dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-				p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
-			
-			err = SetupInterface( inMDNS, p, &ifd );
-			require_noerr( err, exit );
-					
-			// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
-			// register him, but we also want to note that we haven't found a v4 interface
-			// so that we register loopback so same host operations work
-			
-			if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
-			{
-				foundv6 = mDNStrue;
-			}
-
-			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-			// of determing the destination address of a packet that is sent to us.
-			// For multicast packets, that's easy to determine.  But for the unicast
-			// sockets, we'll fake it by taking the address of the first interface
-			// that is successfully setup.
-
-			if ( !foundUnicastSock6DestAddr )
-			{
-				inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
-				foundUnicastSock6DestAddr = TRUE;
-			}
-
-			*next = ifd;
-			next  = &ifd->next;
-			++inMDNS->p->interfaceCount;
-		}
-	}
-
-#endif
-
-	// If there are no real interfaces, but there is a loopback interface, use that so same-machine operations work.
-
-#if( !MDNS_WINDOWS_ENABLE_IPV4 && !MDNS_WINDOWS_ENABLE_IPV6 )
-	
-	flagMask |= IFF_LOOPBACK;
-	flagTest |= IFF_LOOPBACK;
-	
-	for( p = addrs; p; p = p->ifa_next )
-	{
-		if( !p->ifa_addr || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-		{
-			continue;
-		}
-		if( ( p->ifa_addr->sa_family != AF_INET ) && ( p->ifa_addr->sa_family != AF_INET6 ) )
-		{
-			continue;
-		}
-		
-		v4loopback = p;
-		break;
-	}
-	
-#endif
-	
-	if ( !foundv4 && loopbackv4 )
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
-		
-		err = SetupInterface( inMDNS, loopbackv4, &ifd );
-		require_noerr( err, exit );
-
-		inMDNS->p->registeredLoopback4 = mDNStrue;
-		
-#if( MDNS_WINDOWS_ENABLE_IPV4 )
-
-		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-		// of determing the destination address of a packet that is sent to us.
-		// For multicast packets, that's easy to determine.  But for the unicast
-		// sockets, we'll fake it by taking the address of the first interface
-		// that is successfully setup.
-
-		if ( !foundUnicastSock4DestAddr )
-		{
-			inMDNS->p->unicastSock4.addr = ifd->sock.addr;
-			foundUnicastSock4DestAddr = TRUE;
-		}
-#endif
-
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-
-	if ( !foundv6 && loopbackv6 )
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			loopbackv6->ifa_name ? loopbackv6->ifa_name : "<null>", loopbackv6->ifa_extra.index, loopbackv6->ifa_addr );
-		
-		err = SetupInterface( inMDNS, loopbackv6, &ifd );
-		require_noerr( err, exit );
-		
-#if( MDNS_WINDOWS_ENABLE_IPV6 )
-
-		if ( gEnableIPv6 )
-		{
-			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-			// of determing the destination address of a packet that is sent to us.
-			// For multicast packets, that's easy to determine.  But for the unicast
-			// sockets, we'll fake it by taking the address of the first interface
-			// that is successfully setup.
-
-			if ( !foundUnicastSock6DestAddr )
-			{
-				inMDNS->p->unicastSock6.addr = ifd->sock.addr;
-				foundUnicastSock6DestAddr = TRUE;
-			}
-		}
-
-#endif
-
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-
-	CheckFileShares( inMDNS );
-
-exit:
-	if( err )
-	{
-		TearDownInterfaceList( inMDNS );
-	}
-	if( addrs )
-	{
-		freeifaddrs( addrs );
-	}
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	TearDownInterfaceList
-//===========================================================================================================================
-
-mStatus	TearDownInterfaceList( mDNS * const inMDNS )
-{
-	mDNSInterfaceData **		p;
-	mDNSInterfaceData *		ifd;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-
-	// Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
-	// Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
-	// so that remove events that occur after an interface goes away can still report the correct interface.
-
-	p = &inMDNS->p->inactiveInterfaceList;
-	while( *p )
-	{
-		ifd = *p;
-		if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) ifd ) > 0 )
-		{
-			p = &ifd->next;
-			continue;
-		}
-		
-		dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
-		*p = ifd->next;
-
-		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
-	}
-
-	// Tear down all the interfaces.
-	
-	while( inMDNS->p->interfaceList )
-	{
-		ifd = inMDNS->p->interfaceList;
-		inMDNS->p->interfaceList = ifd->next;
-		
-		TearDownInterface( inMDNS, ifd );
-	}
-	inMDNS->p->interfaceCount = 0;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list done\n" );
-	return( mStatus_NoError );
-}
-
-//===========================================================================================================================
-//	SetupInterface
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
-{
-	mDNSInterfaceData	*	ifd;
-	mDNSInterfaceData	*	p;
-	mStatus					err;
-	
-	ifd = NULL;
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-	check( inIFA );
-	check( inIFA->ifa_addr );
-	check( outIFD );
-	
-	// Allocate memory for the interface and initialize it.
-	
-	ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
-	require_action( ifd, exit, err = mStatus_NoMemoryErr );
-	ifd->sock.fd	= kInvalidSocketRef;
-	ifd->sock.ifd	= ifd;
-	ifd->sock.next	= NULL;
-	ifd->sock.m		= inMDNS;
-	ifd->index		= inIFA->ifa_extra.index;
-	ifd->scopeID	= inIFA->ifa_extra.index;
-	check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
-	strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
-	ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
-	
-	strncpy(ifd->interfaceInfo.ifname, inIFA->ifa_name, sizeof(ifd->interfaceInfo.ifname));
-	ifd->interfaceInfo.ifname[sizeof(ifd->interfaceInfo.ifname)-1] = 0;
-	
-	// We always send and receive using IPv4, but to reduce traffic, we send and receive using IPv6 only on interfaces 
-	// that have no routable IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being 
-	// on a large configured network, which means there's a good chance that most or all the other devices on that 
-	// network should also have v4. By doing this we lose the ability to talk to true v6-only devices on that link, 
-	// but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only 
-	// devices on a large configured network, so we are willing to make that sacrifice.
-	
-	ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
-	ifd->interfaceInfo.InterfaceID = NULL;
-
-	for( p = inMDNS->p->interfaceList; p; p = p->next )
-	{
-		if ( strcmp( p->name, ifd->name ) == 0 )
-		{
-			if (!ifd->interfaceInfo.InterfaceID)
-			{
-				ifd->interfaceInfo.InterfaceID	= (mDNSInterfaceID) p;
-			}
-
-			if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
-				 ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
-				 ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
-			{
-				ifd->interfaceInfo.McastTxRx = mDNSfalse;
-			}
-
-			break;
-		}
-	}
-
-	if ( !ifd->interfaceInfo.InterfaceID )
-	{
-		ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
-	}
-
-	// Set up a socket for this interface (if needed).
-	
-	if( ifd->interfaceInfo.McastTxRx )
-	{
-		DWORD size;
-			
-		err = SetupSocket( inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
-		require_noerr( err, exit );
-		ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
-		ifd->sock.port = MulticastDNSPort;
-		
-		// Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
-
-		err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
-
-		if ( err )
-		{
-			ifd->sock.recvMsgPtr = NULL;
-		}
-	}
-
-	if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
-	{
-		inMDNS->p->nextDHCPLeaseExpires = inIFA->ifa_dhcpLeaseExpires;
-	}
-
-	ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
-
-	// Register this interface with mDNS.
-	
-	err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
-	require_noerr( err, exit );
-	
-	err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
-	require_noerr( err, exit );
-
-	memcpy( ifd->interfaceInfo.MAC.b, inIFA->ifa_physaddr, sizeof( ifd->interfaceInfo.MAC.b ) );
-	
-	ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
-
-	if ( ifd->sock.fd != kInvalidSocketRef )
-	{
-		err = mDNSPollRegisterSocket( ifd->sock.fd, FD_READ, UDPSocketNotification, &ifd->sock );
-		require_noerr( err, exit );
-	}
-
-	// If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
-	// and skip the probe phase of the probe/announce packet sequence.
-	ifd->interfaceInfo.DirectLink = mDNSfalse;
-	ifd->interfaceInfo.SupportsUnicastMDNSResponse = mDNStrue;
-
-	err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, NormalActivation );
-	require_noerr( err, exit );
-	ifd->hostRegistered = mDNStrue;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Registered interface %##a with mDNS\n", inIFA->ifa_addr );
-	
-	// Success!
-	
-	*outIFD = ifd;
-	ifd = NULL;
-	
-exit:
-
-	if( ifd )
-	{
-		TearDownInterface( inMDNS, ifd );
-	}
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	TearDownInterface
-//===========================================================================================================================
-
-mDNSlocal mStatus	TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
-{	
-	check( inMDNS );
-	check( inIFD );
-	
-	// Deregister this interface with mDNS.
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering interface %#a with mDNS\n", &inIFD->interfaceInfo.ip );
-	
-	if( inIFD->hostRegistered )
-	{
-		inIFD->hostRegistered = mDNSfalse;
-		mDNS_DeregisterInterface( inMDNS, &inIFD->interfaceInfo, NormalActivation );
-	}
-	
-	// Tear down the multicast socket.
-	
-	UDPCloseSocket( &inIFD->sock );
-
-	// If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps 
-	// the InterfaceID valid so remove events report the correct interface. If it is no longer referenced, free it.
-
-	if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) inIFD ) > 0 )
-	{
-		inIFD->next = inMDNS->p->inactiveInterfaceList;
-		inMDNS->p->inactiveInterfaceList = inIFD;
-		dlog( kDebugLevelInfo, DEBUG_NAME "deferring free of interface %#p %#a\n", inIFD, &inIFD->interfaceInfo.ip );
-	}
-	else
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
-		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
-	}
-
-	return( mStatus_NoError );
-}
-
-mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
-{
-	free( inIFD );
-}
-
-//===========================================================================================================================
-//	SetupSocket
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupSocket( const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  )
-{
-	mStatus			err;
-	SocketRef		sock;
-	int				option;
-	DWORD			bytesReturned = 0;
-	BOOL			behavior = FALSE;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up socket %##a\n", inAddr );
-	check( outSocketRef );
-	
-	// Set up an IPv4 or IPv6 UDP socket.
-	
-	sock = socket( inAddr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
-	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-		
-	// Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
-	// if we're creating a multicast socket
-	
-	if ( !mDNSIPPortIsZero( port ) )
-	{
-		option = 1;
-		err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-	}
-
-	// <rdar://problem/7894393> Bonjour for Windows broken on Windows XP
-	//
-	// Not sure why, but the default behavior for sockets is to behave incorrectly
-	// when using them in Overlapped I/O mode on XP. According to MSDN:
-	//
-	// SIO_UDP_CONNRESET (opcode setting: I, T==3)
-	//     Windows XP:  Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting.
-	//     Set to FALSE to disable reporting.
-	//
-	// Packet traces from misbehaving Bonjour installations showed that ICMP port unreachable
-	// messages were being sent to us after we sent out packets to a multicast address. This is clearly
-	// incorrect behavior, but should be harmless. However, after receiving a port unreachable error, WinSock
-	// will no longer receive any packets from that socket, which is not harmless. This behavior is only
-	// seen on XP.
-	//
-	// So we turn off port unreachable reporting to make sure our sockets that are reading
-	// multicast packets function correctly under all circumstances.
-
-	err = WSAIoctl( sock, SIO_UDP_CONNRESET, &behavior, sizeof(behavior), NULL, 0, &bytesReturned, NULL, NULL );
-	check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-	if( inAddr->sa_family == AF_INET )
-	{
-		mDNSv4Addr				ipv4;
-		struct sockaddr_in		sa4;
-		struct ip_mreq			mreqv4;
-		
-		// Bind the socket to the desired port
-		
-		ipv4.NotAnInteger 	= ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
-		mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
-		sa4.sin_family 		= AF_INET;
-		sa4.sin_port 		= port.NotAnInteger;
-		sa4.sin_addr.s_addr	= ipv4.NotAnInteger;
-		
-		err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
-		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
-		
-		// Turn on option to receive destination addresses and receiving interface.
-		
-		option = 1;
-		err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-		if ( !mDNSIPPortIsZero( port ) )
-		{
-			// Join the all-DNS multicast group so we receive Multicast DNS packets
-
-			mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-			mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
-			err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Specify the interface to send multicast packets on this socket.
-		
-			sa4.sin_addr.s_addr = ipv4.NotAnInteger;
-			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-		
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		}
-
-		// Send unicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-		// Send multicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-	}
-	else if( inAddr->sa_family == AF_INET6 )
-	{
-		struct sockaddr_in6 *		sa6p;
-		struct sockaddr_in6			sa6;
-		struct ipv6_mreq			mreqv6;
-		
-		sa6p = (struct sockaddr_in6 *) inAddr;
-		
-		// Bind the socket to the desired port
-		
-		mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
-		sa6.sin6_family		= AF_INET6;
-		sa6.sin6_port		= port.NotAnInteger;
-		sa6.sin6_flowinfo	= 0;
-		sa6.sin6_addr		= sa6p->sin6_addr;
-		sa6.sin6_scope_id	= sa6p->sin6_scope_id;
-		
-		err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
-		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
-		
-		// Turn on option to receive destination addresses and receiving interface.
-		
-		option = 1;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-		// We only want to receive IPv6 packets (not IPv4-mapped IPv6 addresses) because we have a separate socket 
-		// for IPv4, but the IPv6 stack in Windows currently doesn't support IPv4-mapped IPv6 addresses and doesn't
-		// support the IPV6_V6ONLY socket option so the following code would typically not be executed (or needed).
-		
-		#if( defined( IPV6_V6ONLY ) )
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );		
-		#endif
-		
-		if ( !mDNSIPPortIsZero( port ) )
-		{
-			// Join the all-DNS multicast group so we receive Multicast DNS packets.
-		
-			mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroup_v6.ip.v6 );
-			mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Specify the interface to send multicast packets on this socket.
-		
-			option = (int) sa6p->sin6_scope_id;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-			
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		}
-
-		// Send unicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-		// Send multicast packets with TTL 255 (helps against spoofing).
-			
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inAddr->sa_family );
-		err = kUnsupportedErr;
-		goto exit;
-	}
-	
-	// Success!
-	
-	*outSocketRef = sock;
-	sock = kInvalidSocketRef;
-	err = mStatus_NoError;
-	
-exit:
-	if( IsValidSocket( sock ) )
-	{
-		close_compat( sock );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupSocket
-//===========================================================================================================================
-
-mDNSlocal mStatus	SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort )
-{
-	mStatus		err;
-	
-	check( inSA );
-	check( outIP );
-	
-	if( inSA->sa_family == AF_INET )
-	{
-		struct sockaddr_in *		sa4;
-		
-		sa4 						= (struct sockaddr_in *) inSA;
-		outIP->type 				= mDNSAddrType_IPv4;
-		outIP->ip.v4.NotAnInteger	= sa4->sin_addr.s_addr;
-		if( outPort )
-		{
-			outPort->NotAnInteger	= sa4->sin_port;
-		}
-		err = mStatus_NoError;
-	}
-	else if( inSA->sa_family == AF_INET6 )
-	{
-		struct sockaddr_in6 *		sa6;
-		
-		sa6 			= (struct sockaddr_in6 *) inSA;
-		outIP->type 	= mDNSAddrType_IPv6;
-		outIP->ip.v6 	= *( (mDNSv6Addr *) &sa6->sin6_addr );
-		if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) )
-		{
-			outIP->ip.v6.w[ 1 ] = 0;
-		}
-		if( outPort )
-		{
-			outPort->NotAnInteger = sa6->sin6_port;
-		}
-		err = mStatus_NoError;
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family %d", __ROUTINE__, inSA->sa_family );
-		err = mStatus_BadParamErr;
-	}
-	return( err );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	UDPSocketNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	UDPSocket				*udpSock = ( UDPSocket* ) context;
-	WSAMSG					wmsg = {0};
-	WSABUF					wbuf;
-	struct sockaddr_storage	sockSrcAddr;		// This is filled in by the WSARecv* function
-	INT						sockSrcAddrLen;		// See above
-	mDNSAddr				srcAddr;
-	mDNSInterfaceID			iid;
-	mDNSIPPort				srcPort;
-	mDNSAddr				dstAddr;
-	mDNSIPPort				dstPort;
-	uint8_t					controlBuffer[ 128 ];
-	mDNSu8				*	end;
-	int						num;
-	DWORD					numTries;
-	mStatus					err;
-
-	DEBUG_UNUSED( sock );
-	DEBUG_UNUSED( event );
-
-	require_action( udpSock != NULL, exit, err = mStatus_BadStateErr );
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, udpSock->fd );
-	
-	// Initialize the buffer structure
-
-	wbuf.buf		= (char *) &udpSock->packet;
-	wbuf.len		= (u_long) sizeof( udpSock->packet );
-	sockSrcAddrLen	= sizeof( sockSrcAddr );
-
-	numTries = 0;
-
-	do
-	{
-		if ( udpSock->recvMsgPtr )
-		{
-			DWORD size;
-
-			wmsg.name			= ( LPSOCKADDR ) &sockSrcAddr;
-			wmsg.namelen		= sockSrcAddrLen;
-			wmsg.lpBuffers		= &wbuf;
-			wmsg.dwBufferCount	= 1;
-			wmsg.Control.buf	= ( CHAR* ) controlBuffer;
-			wmsg.Control.len	= sizeof( controlBuffer );
-			wmsg.dwFlags		= 0;
-
-			err = udpSock->recvMsgPtr( udpSock->fd, &wmsg, &size, NULL, NULL );
-			err = translate_errno( ( err == 0 ), (OSStatus) WSAGetLastError(), kUnknownErr ); 
-			num = ( int ) size;
-
-			// <rdar://problem/7824093> iTunes 9.1 fails to install with Bonjour service on Windows 7 Ultimate
-			//
-			// There seems to be a bug in some network device drivers that involves calling WSARecvMsg().
-			// Although all the parameters to WSARecvMsg() are correct, it returns a
-			// WSAEFAULT error code when there is no actual error. We have found experientially that falling
-			// back to using WSARecvFrom() when this happens will work correctly.
-
-			if ( err == WSAEFAULT ) udpSock->recvMsgPtr = NULL;
-		}
-		else
-		{
-			DWORD flags = 0;
-
-			num = WSARecvFrom( udpSock->fd, &wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sockSrcAddr, &sockSrcAddrLen, NULL, NULL );
-			err = translate_errno( ( num >= 0 ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
-		}
-
-		// According to MSDN <http://msdn.microsoft.com/en-us/library/ms741687(VS.85).aspx>:
-		//
-		// "WSAECONNRESET: For a UDP datagram socket, this error would indicate that a previous
-		//                 send operation resulted in an ICMP "Port Unreachable" message."
-		//
-		// Because this is the case, we want to ignore this error and try again.  Just in case
-		// this is some kind of pathological condition, we'll break out of the retry loop 
-		// after 100 iterations
-
-		require_action( !err || ( err == WSAECONNRESET ) || ( err == WSAEFAULT ), exit, err = WSAGetLastError() );
-	}
-	while ( ( ( err == WSAECONNRESET ) || ( err == WSAEFAULT ) ) && ( numTries++ < 100 ) );
-	
-	require_noerr( err, exit );
-	
-	// Translate the source of this packet into mDNS data types
-
-	SockAddrToMDNSAddr( (struct sockaddr* ) &sockSrcAddr, &srcAddr, &srcPort );
-	
-	// Initialize the destination of this packet. Just in case
-	// we can't determine this info because we couldn't call
-	// WSARecvMsg (recvMsgPtr)
-
-	dstAddr = udpSock->addr;
-	dstPort = udpSock->port;
-
-	if ( udpSock->recvMsgPtr )
-	{
-		LPWSACMSGHDR	header;
-		LPWSACMSGHDR	last = NULL;
-		int				count = 0;
-		
-		// Parse the control information. Reject packets received on the wrong interface.
-		
-		// <rdar://problem/7832196> INSTALL: Bonjour 2.0 on Windows can not start / stop
-		// 
-		// There seems to be an interaction between Bullguard and this next bit of code.
-		// When a user's machine is running Bullguard, the control information that is
-		// returned is corrupted, and the code would go into an infinite loop. We'll add
-		// two bits of defensive coding here. The first will check that each pointer to
-		// the LPWSACMSGHDR that is returned in the for loop is different than the last.
-		// This fixes the problem with Bullguard. The second will break out of this loop
-		// after 100 iterations, just in case the corruption isn't caught by the first
-		// check.
-
-		for ( header = WSA_CMSG_FIRSTHDR( &wmsg ); header; header = WSA_CMSG_NXTHDR( &wmsg, header ) )
-		{
-			if ( ( header != last ) && ( ++count < 100 ) )
-			{
-				last = header;
-					
-				if ( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
-				{
-					IN_PKTINFO * ipv4PacketInfo;
-					
-					ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
-
-					if ( udpSock->ifd != NULL )
-					{
-						require_action( ipv4PacketInfo->ipi_ifindex == udpSock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
-					}
-
-					dstAddr.type 				= mDNSAddrType_IPv4;
-					dstAddr.ip.v4.NotAnInteger	= ipv4PacketInfo->ipi_addr.s_addr;
-				}
-				else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
-				{
-					IN6_PKTINFO * ipv6PacketInfo;
-						
-					ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
-		
-					if ( udpSock->ifd != NULL )
-					{
-						require_action( ipv6PacketInfo->ipi6_ifindex == ( udpSock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
-					}
-
-					dstAddr.type	= mDNSAddrType_IPv6;
-					dstAddr.ip.v6	= *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
-				}
-			}
-			else
-			{
-				static BOOL loggedMessage = FALSE;
-
-				if ( !loggedMessage )
-				{
-					LogMsg( "UDPEndRecv: WSARecvMsg control information error." );
-					loggedMessage = TRUE;
-				}
-
-				break;
-			}
-		}
-	}
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", num );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
-	
-	if ( udpSock->ifd != NULL )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "    interface = %#a (index=0x%08X)\n", &udpSock->ifd->interfaceInfo.ip, udpSock->ifd->index );
-	}
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
-
-	iid = udpSock->ifd ? udpSock->ifd->interfaceInfo.InterfaceID : NULL;
-	end = ( (mDNSu8 *) &udpSock->packet ) + num;
-
-	mDNSCoreReceive( udpSock->m, &udpSock->packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
-
-exit:
-
-	return;
-}
-
-//===========================================================================================================================
-//	InterfaceListDidChange
-//===========================================================================================================================
-void InterfaceListDidChange( mDNS * const inMDNS )
-{
-	mStatus err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
-	check( inMDNS );
-	
-	// Tear down the existing interfaces and set up new ones using the new IP info.
-	
-	err = TearDownInterfaceList( inMDNS );
-	check_noerr( err );
-	
-	err = SetupInterfaceList( inMDNS );
-	check_noerr( err );
-		
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-	
-	// Inform clients of the change.
-	
-	mDNS_ConfigChanged(inMDNS);
-	
-	// Force mDNS to update.
-	
-	mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
-}
-
-//===========================================================================================================================
-//	ComputerDescriptionDidChange
-//===========================================================================================================================
-void ComputerDescriptionDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
-	check( inMDNS );
-
-	// redo the names
-	SetupNiceName( inMDNS );
-}
-
-//===========================================================================================================================
-//	TCPIPConfigDidChange
-//===========================================================================================================================
-void TCPIPConfigDidChange( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
-	check( inMDNS );
-
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-}
-
-//===========================================================================================================================
-//	DynDNSConfigDidChange
-//===========================================================================================================================
-void DynDNSConfigDidChange( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
-	check( inMDNS );
-
-	SetDomainSecrets( inMDNS );
-
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-}
-
-//===========================================================================================================================
-//	FileSharingDidChange
-//===========================================================================================================================
-void FileSharingDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
-	check( inMDNS );
-
-	CheckFileShares( inMDNS );
-}
-
-//===========================================================================================================================
-//	FilewallDidChange
-//===========================================================================================================================
-void FirewallDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
-	check( inMDNS );
-
-	CheckFileShares( inMDNS );
-}
-
-#if 0
-#pragma mark -
-#pragma mark == Utilities ==
-#endif
-
-//===========================================================================================================================
-//	getifaddrs
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs( struct ifaddrs **outAddrs )
-{
-	int		err;
-	
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	
-	// Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
-	// XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
-	
-	if( !gIPHelperLibraryInstance )
-	{
-		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
-		if( gIPHelperLibraryInstance )
-		{
-			gGetAdaptersAddressesFunctionPtr = 
-				(GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
-			if( !gGetAdaptersAddressesFunctionPtr )
-			{
-				BOOL		ok;
-				
-				ok = FreeLibrary( gIPHelperLibraryInstance );
-				check_translated_errno( ok, GetLastError(), kUnknownErr );
-				gIPHelperLibraryInstance = NULL;
-			}
-		}
-	}
-	
-	// Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
-	// <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
-	// <rdar://problem/6145913>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 returns no addrs
-
-	if( !gGetAdaptersAddressesFunctionPtr || ( ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) || ( ( outAddrs != NULL ) && ( *outAddrs == NULL ) ) ) )
-	{
-		err = getifaddrs_ipv4( outAddrs );
-		require_noerr( err, exit );
-	}
-	
-#else
-
-	err = getifaddrs_ipv4( outAddrs );
-	require_noerr( err, exit );
-
-#endif
-
-exit:
-	return( err );
-}
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-//===========================================================================================================================
-//	getifaddrs_ipv6
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs )
-{
-	DWORD						err;
-	int							i;
-	DWORD						flags;
-	struct ifaddrs *			head;
-	struct ifaddrs **			next;
-	IP_ADAPTER_ADDRESSES *		iaaList;
-	ULONG						iaaListSize;
-	IP_ADAPTER_ADDRESSES *		iaa;
-	size_t						size;
-	struct ifaddrs *			ifa;
-	
-	check( gGetAdaptersAddressesFunctionPtr );
-	
-	head	= NULL;
-	next	= &head;
-	iaaList	= NULL;
-	
-	// Get the list of interfaces. The first call gets the size and the second call gets the actual data.
-	// This loops to handle the case where the interface changes in the window after getting the size, but before the
-	// second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
-	
-	flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
-	i = 0;
-	for( ;; )
-	{
-		iaaListSize = 0;
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
-		check( err == ERROR_BUFFER_OVERFLOW );
-		check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
-		
-		iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
-		require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
-		
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
-		if( err == ERROR_SUCCESS ) break;
-		
-		free( iaaList );
-		iaaList = NULL;
-		++i;
-		require( i < 100, exit );
-		dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
-	}
-	
-	for( iaa = iaaList; iaa; iaa = iaa->Next )
-	{
-		int								addrIndex;
-		IP_ADAPTER_UNICAST_ADDRESS	*	addr;
-		DWORD							ipv6IfIndex;
-		IP_ADAPTER_PREFIX			*	firstPrefix;
-
-		if( iaa->IfIndex > 0xFFFFFF )
-		{
-			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv4 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->IfIndex );
-		}
-		if( iaa->Ipv6IfIndex > 0xFF )
-		{
-			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
-		}
-
-		// For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
-		// following code to crash when iterating through the prefix list.  This seems
-		// to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
-		// This shouldn't happen according to Microsoft docs which states:
-		//
-		//     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
-		//
-		// So the data structure seems to be corrupted when we return from
-		// GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
-		// sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
-		// modify iaa to have the correct values.
-
-		if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
-		{
-			ipv6IfIndex = iaa->Ipv6IfIndex;
-			firstPrefix = iaa->FirstPrefix;
-		}
-		else
-		{
-			ipv6IfIndex	= 0;
-			firstPrefix = NULL;
-		}
-
-		// Skip pseudo and tunnel interfaces.
-		
-		if( ( ( ipv6IfIndex == 1 ) && ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
-		{
-			continue;
-		}
-		
-		// Add each address as a separate interface to emulate the way getifaddrs works.
-		
-		for( addrIndex = 0, addr = iaa->FirstUnicastAddress; addr; ++addrIndex, addr = addr->Next )
-		{			
-			int						family;
-			IP_ADAPTER_PREFIX *		prefix;
-			uint32_t				ipv4Index;
-			struct sockaddr_in		ipv4Netmask;
-
-			family = addr->Address.lpSockaddr->sa_family;
-			if( ( family != AF_INET ) && ( family != AF_INET6 ) ) continue;
-			
-			// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
-			// Seems as if the problem here is a buggy implementation of some network interface
-			// driver. It is reporting that is has a link-local address when it is actually
-			// disconnected. This was causing a problem in AddressToIndexAndMask.
-			// The solution is to call AddressToIndexAndMask first, and if unable to lookup
-			// the address, to ignore that address.
-
-			ipv4Index = 0;
-			memset( &ipv4Netmask, 0, sizeof( ipv4Netmask ) );
-			
-			if ( family == AF_INET )
-			{
-				err = AddressToIndexAndMask( addr->Address.lpSockaddr, &ipv4Index, ( struct sockaddr* ) &ipv4Netmask );
-				
-				if ( err )
-				{
-					err = 0;
-					continue;
-				}
-			}
-
-			ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
-			require_action( ifa, exit, err = WSAENOBUFS );
-			
-			*next = ifa;
-			next  = &ifa->ifa_next;
-			
-			// Get the name.
-			
-			size = strlen( iaa->AdapterName ) + 1;
-			ifa->ifa_name = (char *) malloc( size );
-			require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
-			memcpy( ifa->ifa_name, iaa->AdapterName, size );
-			
-			// Get interface flags.
-			
-			ifa->ifa_flags = 0;
-			if( iaa->OperStatus == IfOperStatusUp ) 		ifa->ifa_flags |= IFF_UP;
-			if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )	ifa->ifa_flags |= IFF_LOOPBACK;
-			else if ( IsPointToPoint( addr ) )				ifa->ifa_flags |= IFF_POINTTOPOINT;
-			if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) )	ifa->ifa_flags |= IFF_MULTICAST;
-
-			
-			// <rdar://problem/4045657> Interface index being returned is 512
-			//
-			// Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes.
-			// This code used to shift the IPv4 index up to ensure uniqueness between
-			// it and IPv6 indexes.  Although this worked, it was somewhat confusing to developers, who
-			// then see interface indexes passed back that don't correspond to anything
-			// that is seen in Win32 APIs or command line tools like "route".  As a relatively
-			// small percentage of developers are actively using IPv6, it seems to 
-			// make sense to make our use of IPv4 as confusion free as possible.
-			// So now, IPv6 interface indexes will be shifted up by a
-			// constant value which will serve to uniquely identify them, and we will
-			// leave IPv4 interface indexes unmodified.
-			
-			switch( family )
-			{
-				case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex; break;
-				case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase;	 break;
-				default: break;
-			}
-
-			// Get lease lifetime
-
-			if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->ValidLifetime != 0xFFFFFFFF ) )
-			{
-				ifa->ifa_dhcpEnabled		= TRUE;
-				ifa->ifa_dhcpLeaseExpires	= time( NULL ) + addr->ValidLifetime;
-			}
-			else
-			{
-				ifa->ifa_dhcpEnabled		= FALSE;
-				ifa->ifa_dhcpLeaseExpires	= 0;
-			}
-
-			if ( iaa->PhysicalAddressLength == sizeof( ifa->ifa_physaddr ) )
-			{
-				memcpy( ifa->ifa_physaddr, iaa->PhysicalAddress, iaa->PhysicalAddressLength );
-			}
-
-			// Because we don't get notified of womp changes, we're going to just assume
-			// that all wired interfaces have it enabled. Before we go to sleep, we'll check
-			// if the interface actually supports it, and update mDNS->SystemWakeOnLANEnabled
-			// accordingly
-
-			ifa->ifa_womp = ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD ) ? mDNStrue : mDNSfalse;
-			
-			// Get address.
-			
-			switch( family )
-			{
-				case AF_INET:
-				case AF_INET6:
-					ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
-					require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
-					memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
-					break;
-				
-				default:
-					break;
-			}
-			check( ifa->ifa_addr );
-			
-			// Get subnet mask (IPv4)/link prefix (IPv6). It is specified as a bit length (e.g. 24 for 255.255.255.0).
-
-			switch ( family )
-			{
-				case AF_INET:
-				{
-					struct sockaddr_in * sa4;
-					
-					sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
-					require_action( sa4, exit, err = WSAENOBUFS );
-					sa4->sin_family = AF_INET;
-					sa4->sin_addr.s_addr = ipv4Netmask.sin_addr.s_addr;
-
-					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) );
-					ifa->ifa_netmask = (struct sockaddr *) sa4;
-					break;
-				}
-
-				case AF_INET6:
-				{
-					struct sockaddr_in6 *sa6;
-					char buf[ 256 ] = { 0 };
-					DWORD buflen = sizeof( buf );
-
-					sa6 = (struct sockaddr_in6 *) calloc( 1, sizeof( *sa6 ) );
-					require_action( sa6, exit, err = WSAENOBUFS );
-					sa6->sin6_family = AF_INET6;
-					memset( sa6->sin6_addr.s6_addr, 0xFF, sizeof( sa6->sin6_addr.s6_addr ) );
-					ifa->ifa_netmask = (struct sockaddr *) sa6;
-
-					for ( prefix = firstPrefix; prefix; prefix = prefix->Next )
-					{
-						IN6_ADDR	mask;
-						IN6_ADDR	maskedAddr;
-						int			maskIndex;
-						int			len;
-
-						// According to MSDN:
-						// "On Windows Vista and later, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
-						// include three IP adapter prefixes for each IP address assigned to the adapter. These include the host IP address prefix,
-						// the subnet IP address prefix, and the subnet broadcast IP address prefix.
-						// In addition, for each adapter there is a multicast address prefix and a broadcast address prefix.
-						// On Windows XP with SP1 and later prior to Windows Vista, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
-						// include only a single IP adapter prefix for each IP address assigned to the adapter."
-						
-						// We're only interested in the subnet IP address prefix.  We'll determine if the prefix is the
-						// subnet prefix by masking our address with a mask (computed from the prefix length) and see if that is the same
-						// as the prefix address.
-
-						if ( ( prefix->PrefixLength == 0 ) ||
-							 ( prefix->PrefixLength > 128 ) ||
-							 ( addr->Address.iSockaddrLength != prefix->Address.iSockaddrLength ) ||
-							 ( memcmp( addr->Address.lpSockaddr, prefix->Address.lpSockaddr, addr->Address.iSockaddrLength ) == 0 ) )
-						{
-							continue;
-						}
-
-						// Compute the mask
-
-						memset( mask.s6_addr, 0, sizeof( mask.s6_addr ) );
-
-						for ( len = (int) prefix->PrefixLength, maskIndex = 0; len > 0; len -= 8 )
-						{
-							uint8_t maskByte = ( len >= 8 ) ? 0xFF : (uint8_t)( ( 0xFFU << ( 8 - len ) ) & 0xFFU );
-							mask.s6_addr[ maskIndex++ ] = maskByte;
-						}
-
-						// Apply the mask
-
-						for ( i = 0; i < 16; i++ )
-						{
-							maskedAddr.s6_addr[ i ] = ( ( struct sockaddr_in6* ) addr->Address.lpSockaddr )->sin6_addr.s6_addr[ i ] & mask.s6_addr[ i ];
-						}
-
-						// Compare
-
-						if ( memcmp( ( ( struct sockaddr_in6* ) prefix->Address.lpSockaddr )->sin6_addr.s6_addr, maskedAddr.s6_addr, sizeof( maskedAddr.s6_addr ) ) == 0 )
-						{
-							memcpy( sa6->sin6_addr.s6_addr, mask.s6_addr, sizeof( mask.s6_addr ) );
-							break;
-						}
-					}
-
-					WSAAddressToStringA( ( LPSOCKADDR ) sa6, sizeof( struct sockaddr_in6 ), NULL, buf, &buflen );
-					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv6 mask = %s\n", __ROUTINE__, buf );				
-
-					break;
-				}
-				
-				default:
-					break;
-			}
-		}
-	}
-	
-	// Success!
-	
-	if( outAddrs )
-	{
-		*outAddrs = head;
-		head = NULL;
-	}
-	err = ERROR_SUCCESS;
-	
-exit:
-	if( head )
-	{
-		freeifaddrs( head );
-	}
-	if( iaaList )
-	{
-		free( iaaList );
-	}
-	return( (int) err );
-}
-
-#endif	// MDNS_WINDOWS_USE_IPV6_IF_ADDRS
-
-//===========================================================================================================================
-//	getifaddrs_ipv4
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs_ipv4( struct ifaddrs **outAddrs )
-{
-	int						err;
-	SOCKET					sock;
-	DWORD					size;
-	DWORD					actualSize;
-	INTERFACE_INFO *		buffer;
-	INTERFACE_INFO *		tempBuffer;
-	INTERFACE_INFO *		ifInfo;
-	int						n;
-	int						i;
-	struct ifaddrs *		head;
-	struct ifaddrs **		next;
-	struct ifaddrs *		ifa;
-	
-	sock	= INVALID_SOCKET;
-	buffer	= NULL;
-	head	= NULL;
-	next	= &head;
-	
-	// Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a 
-	// way to determine the size of the interface list beforehand, we have to start with an initial size guess and
-	// call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
-	
-	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-		
-	n = 0;
-	size = 16 * sizeof( INTERFACE_INFO );
-	for( ;; )
-	{
-		tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
-		require_action( tempBuffer, exit, err = WSAENOBUFS );
-		buffer = tempBuffer;
-		
-		err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
-		if( err == 0 )
-		{
-			break;
-		}
-		
-		++n;
-		require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
-		
-		size += ( 16 * sizeof( INTERFACE_INFO ) );
-	}
-	check( actualSize <= size );
-	check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
-	n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
-	
-	// Process the raw interface list and build a linked list of IPv4 interfaces.
-	
-	for( i = 0; i < n; ++i )
-	{
-		uint32_t ifIndex;
-		struct sockaddr_in netmask;
-		
-		ifInfo = &buffer[ i ];
-		if( ifInfo->iiAddress.Address.sa_family != AF_INET )
-		{
-			continue;
-		}
-		
-		// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
-		// See comment in getifaddrs_ipv6
-
-		ifIndex = 0;
-		memset( &netmask, 0, sizeof( netmask ) );
-		err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
-
-		if ( err )
-		{
-			continue;
-		}
-
-		ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
-		require_action( ifa, exit, err = WSAENOBUFS );
-		
-		*next = ifa;
-		next  = &ifa->ifa_next;
-		
-		// Get the name.
-		
-		ifa->ifa_name = (char *) malloc( 16 );
-		require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
-		_snprintf( ifa->ifa_name, 16, "%d", i + 1 );
-		
-		// Get interface flags.
-		
-		ifa->ifa_flags = (u_int) ifInfo->iiFlags;
-		
-		// Get addresses.
-		
-		if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
-		{
-			struct sockaddr_in *		sa4;
-			
-			sa4 = &ifInfo->iiAddress.AddressIn;
-			ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
-			require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
-			memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
-
-			ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
-			require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
-
-			// <rdar://problem/4076478> Service won't start on Win2K. The address
-			// family field was not being initialized.
-
-			ifa->ifa_netmask->sa_family = AF_INET;
-			( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
-			ifa->ifa_extra.index = ifIndex;
-		}
-		else
-		{
-			// Emulate an interface index.
-		
-			ifa->ifa_extra.index = (uint32_t)( i + 1 );
-		}
-	}
-	
-	// Success!
-	
-	if( outAddrs )
-	{
-		*outAddrs = head;
-		head = NULL;
-	}
-	err = 0;
-	
-exit:
-
-	if( head )
-	{
-		freeifaddrs( head );
-	}
-	if( buffer )
-	{
-		free( buffer );
-	}
-	if( sock != INVALID_SOCKET )
-	{
-		closesocket( sock );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	freeifaddrs
-//===========================================================================================================================
-
-mDNSlocal void	freeifaddrs( struct ifaddrs *inIFAs )
-{
-	struct ifaddrs *		p;
-	struct ifaddrs *		q;
-	
-	// Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
-	
-	for( p = inIFAs; p; p = q )
-	{
-		q = p->ifa_next;
-		
-		if( p->ifa_name )
-		{
-			free( p->ifa_name );
-			p->ifa_name = NULL;
-		}
-		if( p->ifa_addr )
-		{
-			free( p->ifa_addr );
-			p->ifa_addr = NULL;
-		}
-		if( p->ifa_netmask )
-		{
-			free( p->ifa_netmask );
-			p->ifa_netmask = NULL;
-		}
-		if( p->ifa_broadaddr )
-		{
-			free( p->ifa_broadaddr );
-			p->ifa_broadaddr = NULL;
-		}
-		if( p->ifa_dstaddr )
-		{
-			free( p->ifa_dstaddr );
-			p->ifa_dstaddr = NULL;
-		}
-		if( p->ifa_data )
-		{
-			free( p->ifa_data );
-			p->ifa_data = NULL;
-		}
-		free( p );
-	}
-}
-
-//===========================================================================================================================
-//	GetPrimaryInterface
-//===========================================================================================================================
-
-mDNSlocal DWORD
-GetPrimaryInterface()
-{
-	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
-	DWORD				dwSize			= 0;
-	BOOL				bOrder			= FALSE;
-	OSStatus			err;
-	DWORD				index			= 0;
-	DWORD				metric			= 0;
-	unsigned long int	i;
-
-	// Find out how big our buffer needs to be.
-
-	err = GetIpForwardTable(NULL, &dwSize, bOrder);
-	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
-
-	// Allocate the memory for the table
-
-	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
-	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
-  
-	// Now get the table.
-
-	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
-	require_noerr( err, exit );
-
-	// Search for the row in the table we want.
-
-	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
-	{
-		// Look for a default route
-
-		if ( pIpForwardTable->table[i].dwForwardDest == 0 )
-		{
-			if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) )
-			{
-				continue;
-			}
-
-			index	= pIpForwardTable->table[i].dwForwardIfIndex;
-			metric	= pIpForwardTable->table[i].dwForwardMetric1;
-		}
-	}
-
-exit:
-
-	if ( pIpForwardTable != NULL )
-	{
-		free( pIpForwardTable );
-	}
-
-	return index;
-}
-
-//===========================================================================================================================
-//	AddressToIndexAndMask
-//===========================================================================================================================
-
-mDNSlocal mStatus
-AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask  )
-{
-	// Before calling AddIPAddress we use GetIpAddrTable to get
-	// an adapter to which we can add the IP.
-	
-	PMIB_IPADDRTABLE	pIPAddrTable	= NULL;
-	DWORD				dwSize			= 0;
-	mStatus				err				= mStatus_UnknownErr;
-	DWORD				i;
-
-	// For now, this is only for IPv4 addresses.  That is why we can safely cast
-	// addr's to sockaddr_in.
-
-	require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr );
-
-	// Make an initial call to GetIpAddrTable to get the
-	// necessary size into the dwSize variable
-
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
-
-		if ( err != ERROR_INSUFFICIENT_BUFFER )
-		{
-			break;
-		}
-
-		pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize );
-		require_action( pIPAddrTable, exit, err = WSAENOBUFS );
-	}
-
-	require_noerr( err, exit );
-	err = mStatus_UnknownErr;
-
-	for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
-	{
-		if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr )
-		{
-			*ifIndex											= pIPAddrTable->table[i].dwIndex;
-			( ( struct sockaddr_in*) mask )->sin_addr.s_addr	= pIPAddrTable->table[i].dwMask;
-			err													= mStatus_NoError;
-			break;
-		}
-	}
-
-exit:
-
-	if ( pIPAddrTable )
-	{
-		free( pIPAddrTable );
-	}
-
-	return err;
-}
-
-//===========================================================================================================================
-//	CanReceiveUnicast
-//===========================================================================================================================
-
-mDNSlocal mDNSBool	CanReceiveUnicast( void )
-{
-	mDNSBool				ok;
-	SocketRef				sock;
-	struct sockaddr_in		addr;
-	
-	// Try to bind to the port without the SO_REUSEADDR option to test if someone else has already bound to it.
-	
-	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	check_translated_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	ok = IsValidSocket( sock );
-	if( ok )
-	{
-		mDNSPlatformMemZero( &addr, sizeof( addr ) );
-		addr.sin_family			= AF_INET;
-		addr.sin_port			= MulticastDNSPort.NotAnInteger;
-		addr.sin_addr.s_addr	= htonl( INADDR_ANY );
-		
-		ok = ( bind( sock, (struct sockaddr *) &addr, sizeof( addr ) ) == 0 );
-		close_compat( sock );
-	}
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Unicast UDP responses %s\n", ok ? "okay" : "*not allowed*" );
-	return( ok );
-}
-
-//===========================================================================================================================
-//	IsPointToPoint
-//===========================================================================================================================
-
-mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr )
-{
-	struct ifaddrs	*	addrs	=	NULL;
-	struct ifaddrs	*	p		=	NULL;
-	OSStatus			err;
-	mDNSBool			ret		=	mDNSfalse;
-
-	// For now, only works for IPv4 interfaces
-
-	if ( addr->Address.lpSockaddr->sa_family == AF_INET )
-	{
-		// The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags.
-
-		err = getifaddrs_ipv4( &addrs );
-		require_noerr( err, exit );
-
-		for ( p = addrs; p; p = p->ifa_next )
-		{
-			if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) &&
-				 ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) )
-			{
-				ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse;
-				break;
-			}
-		}
-	}
-
-exit:
-
-	if ( addrs )
-	{
-		freeifaddrs( addrs );
-	}
-
-	return ret;
-}
-
-//===========================================================================================================================
-//	GetWindowsVersionString
-//===========================================================================================================================
-
-mDNSlocal OSStatus	GetWindowsVersionString( char *inBuffer, size_t inBufferSize )
-{
-#if( !defined( VER_PLATFORM_WIN32_CE ) )
-	#define VER_PLATFORM_WIN32_CE		3
-#endif
-
-	OSStatus				err = 0;
-	const char *			versionString;
-#ifndef WIN32_CENTENNIAL
-	OSVERSIONINFO			osInfo;
-	BOOL					ok;
-	DWORD					platformID;
-	DWORD					majorVersion;
-	DWORD					minorVersion;
-	DWORD					buildNumber;
-	
-	versionString = "unknown Windows version";
-	
-	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
-	ok = GetVersionEx( &osInfo );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	platformID		= osInfo.dwPlatformId;
-	majorVersion	= osInfo.dwMajorVersion;
-	minorVersion	= osInfo.dwMinorVersion;
-	buildNumber		= osInfo.dwBuildNumber & 0xFFFF;
-	
-	if( ( platformID == VER_PLATFORM_WIN32_WINDOWS ) && ( majorVersion == 4 ) )
-	{
-		if( ( minorVersion < 10 ) && ( buildNumber == 950 ) )
-		{
-			versionString	= "Windows 95";
-		}
-		else if( ( minorVersion < 10 ) && ( ( buildNumber > 950 ) && ( buildNumber <= 1080 ) ) )
-		{
-			versionString	= "Windows 95 SP1";
-		}
-		else if( ( minorVersion < 10 ) && ( buildNumber > 1080 ) )
-		{
-			versionString	= "Windows 95 OSR2";
-		}
-		else if( ( minorVersion == 10 ) && ( buildNumber == 1998 ) )
-		{
-			versionString	= "Windows 98";
-		}
-		else if( ( minorVersion == 10 ) && ( ( buildNumber > 1998 ) && ( buildNumber < 2183 ) ) )
-		{
-			versionString	= "Windows 98 SP1";
-		}
-		else if( ( minorVersion == 10 ) && ( buildNumber >= 2183 ) )
-		{
-			versionString	= "Windows 98 SE";
-		}
-		else if( minorVersion == 90 )
-		{
-			versionString	= "Windows ME";
-		}
-	}
-	else if( platformID == VER_PLATFORM_WIN32_NT )
-	{
-		if( ( majorVersion == 3 ) && ( minorVersion == 51 ) )
-		{
-			versionString	= "Windows NT 3.51";
-		}
-		else if( ( majorVersion == 4 ) && ( minorVersion == 0 ) )
-		{
-			versionString	= "Windows NT 4";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 0 ) )
-		{
-			versionString	= "Windows 2000";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 1 ) )
-		{
-			versionString	= "Windows XP";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 2 ) )
-		{
-			versionString	= "Windows Server 2003";
-		}
-	}
-	else if( platformID == VER_PLATFORM_WIN32_CE )
-	{
-		versionString		= "Windows CE";
-	}
-	
-exit:
-#else
-	versionString = "Windows";
-#endif
-	if( inBuffer && ( inBufferSize > 0 ) )
-	{
-		inBufferSize -= 1;
-		strncpy( inBuffer, versionString, inBufferSize );
-		inBuffer[ inBufferSize ] = '\0';
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	RegQueryString
-//===========================================================================================================================
-
-mDNSlocal mStatus
-RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled )
-{
-	DWORD	type;
-	int		i;
-	mStatus err;
-
-	*stringLen	= MAX_ESCAPED_DOMAIN_NAME;
-	*string		= NULL;
-	i			= 0;
-
-	do
-	{
-		if ( *string )
-		{
-			free( *string );
-		}
-
-		*string = (char*) malloc( *stringLen );
-		require_action( *string, exit, err = mStatus_NoMemoryErr );
-
-		err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
-
-		i++;
-	}
-	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
-
-	require_noerr_quiet( err, exit );
-
-	if ( enabled )
-	{
-		DWORD dwSize = sizeof( DWORD );
-
-		err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize );
-		check_noerr( err );
-
-		err = kNoErr;
-	}
-
-exit:
-
-	return err;
-}
-
-//===========================================================================================================================
-//	StringToAddress
-//===========================================================================================================================
-
-mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
-{
-	struct sockaddr_in6 sa6;
-	struct sockaddr_in	sa4;
-	INT					dwSize;
-	mStatus				err;
-
-	sa6.sin6_family	= AF_INET6;
-	dwSize			= sizeof( sa6 );
-
-	err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
-
-	if ( err == mStatus_NoError )
-	{
-		err = SetupAddr( ip, (struct sockaddr*) &sa6 );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		sa4.sin_family = AF_INET;
-		dwSize = sizeof( sa4 );
-
-		err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
-		err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr );
-		require_noerr( err, exit );
-			
-		err = SetupAddr( ip, (struct sockaddr*) &sa4 );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return err;
-}
-
-//===========================================================================================================================
-//	myGetIfAddrs
-//===========================================================================================================================
-
-mDNSlocal struct ifaddrs*
-myGetIfAddrs(int refresh)
-{
-	static struct ifaddrs *ifa = NULL;
-	
-	if (refresh && ifa)
-	{
-		freeifaddrs(ifa);
-		ifa = NULL;
-	}
-	
-	if (ifa == NULL)
-	{
-		getifaddrs(&ifa);
-	}
-	
-	return ifa;
-}
-
-//===========================================================================================================================
-//	TCHARtoUTF8
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize )
-{
-#if( defined( UNICODE ) || defined( _UNICODE ) )
-	OSStatus		err;
-	int				len;
-	
-	len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-#else
-	return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) );
-#endif
-}
-
-//===========================================================================================================================
-//	WindowsLatin1toUTF8
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize )
-{
-	OSStatus		err;
-	WCHAR *			utf16;
-	int				len;
-	
-	utf16 = NULL;
-	
-	// Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first.
-	
-	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) );
-	require_action( utf16, exit, err = kNoMemoryErr );
-	
-	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	// Now convert the temporary UTF-16 to UTF-8.
-	
-	len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-	if( utf16 ) free( utf16 );
-	return( err );
-}
-
-//===========================================================================================================================
-//	TCPCloseSocket
-//===========================================================================================================================
-
-mDNSlocal void
-TCPCloseSocket( TCPSocket * sock )
-{
-	dlog( kDebugLevelChatty, DEBUG_NAME "closing TCPSocket 0x%x:%d\n", sock, sock->fd );
-
-	if ( sock->fd != INVALID_SOCKET )
-	{
-		closesocket( sock->fd );
-		sock->fd = INVALID_SOCKET;
-	}
-}
-
-//===========================================================================================================================
-//  UDPCloseSocket
-//===========================================================================================================================
-
-mDNSlocal void
-UDPCloseSocket( UDPSocket * sock )
-{
-	dlog( kDebugLevelChatty, DEBUG_NAME "closing UDPSocket %d\n", sock->fd );
-
-	if ( sock->fd != INVALID_SOCKET )
-	{
-		mDNSPollUnregisterSocket( sock->fd );
-		closesocket( sock->fd );
-		sock->fd = INVALID_SOCKET;
-	}
-}
-
-//===========================================================================================================================
-//	SetupAddr
-//===========================================================================================================================
-
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
-	{
-	if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
-
-	if (sa->sa_family == AF_INET)
-		{
-		struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
-		ip->type = mDNSAddrType_IPv4;
-		ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
-		return(mStatus_NoError);
-		}
-
-	if (sa->sa_family == AF_INET6)
-		{
-		struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
-		ip->type = mDNSAddrType_IPv6;
-		if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.u.Word[1] = 0;
-		ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
-		return(mStatus_NoError);
-		}
-
-	LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
-	return(mStatus_Invalid);
-	}
-
-mDNSlocal void GetDDNSFQDN( domainname *const fqdn )
-{
-	LPSTR		name = NULL;
-	DWORD		dwSize;
-	DWORD		enabled;
-	HKEY		key = NULL;
-	OSStatus	err;
-
-	check( fqdn );
-
-	// Initialize
-
-	fqdn->c[0] = '\0';
-
-	// Get info from Bonjour registry key
-
-	err = RegCreateKey(HKEY_CURRENT_USER, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key);
-	require_noerr( err, exit );
-
-	err = RegQueryString( key, "", &name, &dwSize, &enabled );
-	if ( !err && ( name[0] != '\0' ) && enabled )
-	{
-		if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
-		{
-			dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
-		}
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-		key = NULL;
-	}
-
-	if ( name )
-	{
-		free( name );
-		name = NULL;
-	}
-}
-
-#ifdef UNICODE
-mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
-#else
-mDNSlocal void GetDDNSConfig( DNameListElem ** domains, LPCSTR lpSubKey )
-#endif
-{
-	char		subKeyName[kRegistryMaxKeyLength + 1];
-	DWORD		cSubKeys = 0;
-	DWORD		cbMaxSubKey;
-	DWORD		cchMaxClass;
-	DWORD		dwSize;
-	HKEY		key = NULL;
-	HKEY		subKey = NULL;
-	domainname	dname;
-	DWORD		i;
-	OSStatus	err;
-
-	check( domains );
-
-	// Initialize
-
-	*domains = NULL;
-
-	err = RegCreateKey(HKEY_CURRENT_USER, lpSubKey, &key);
-	require_noerr( err, exit );
-
-	// Get information about this node
-
-	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	for ( i = 0; i < cSubKeys; i++)
-	{
-		DWORD enabled;
-
-		dwSize = kRegistryMaxKeyLength;
-		
-		err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-
-		if ( !err )
-		{
-			err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
-			require_noerr( err, exit );
-
-			dwSize = sizeof( DWORD );
-			err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-
-			if ( !err && ( subKeyName[0] != '\0' ) && enabled )
-			{
-				if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
-				{
-					dlog( kDebugLevelError, "bad DDNS domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
-				}
-				else
-				{
-					DNameListElem * domain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-					require_action( domain, exit, err = mStatus_NoMemoryErr );
-					
-					AssignDomainName(&domain->name, &dname);
-					domain->next = *domains;
-
-					*domains = domain;
-				}
-			}
-
-			RegCloseKey( subKey );
-			subKey = NULL;
-		}
-	}
-
-exit:
-
-	if ( subKey )
-	{
-		RegCloseKey( subKey );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain )
-{
-	char					domainUTF8[ 256 ];
-	DomainAuthInfo			*foundInList;
-	DomainAuthInfo			*ptr;
-	char					outDomain[ 256 ];
-	char					outKey[ 256 ];
-	char					outSecret[ 256 ];
-	OSStatus				err;
-	
-	ConvertDomainNameToCString( inDomain, domainUTF8 );
-	
-	// If we're able to find a secret for this domain
-
-	if ( LsaGetSecret( domainUTF8, outDomain, sizeof( outDomain ), outKey, sizeof( outKey ), outSecret, sizeof( outSecret ) ) )
-	{
-		domainname domain;
-		domainname key;
-
-		// Tell the core about this secret
-
-		MakeDomainNameFromDNSNameString( &domain, outDomain );
-		MakeDomainNameFromDNSNameString( &key, outKey );
-
-		for (foundInList = m->AuthInfoList; foundInList; foundInList = foundInList->next)
-			if (SameDomainName(&foundInList->domain, &domain ) ) break;
-
-		ptr = foundInList;
-	
-		if (!ptr)
-		{
-			ptr = (DomainAuthInfo*)malloc(sizeof(DomainAuthInfo));
-			require_action( ptr, exit, err = mStatus_NoMemoryErr );
-		}
-
-		err = mDNS_SetSecretForDomain(m, ptr, &domain, &key, outSecret, NULL, NULL);
-		require_action( err != mStatus_BadParamErr, exit, if (!foundInList ) mDNSPlatformMemFree( ptr ) );
-
-		debugf("Setting shared secret for zone %s with key %##s", outDomain, key.c);
-	}
-
-exit:
-
-	return;
-}
-
-mDNSlocal VOID CALLBACK
-CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
-{
-	mDNS * const m = ( mDNS * const ) arg;
-
-	( void ) dwTimerLowValue;
-	( void ) dwTimerHighValue;
-
-	CheckFileShares( m );
-}
-
-mDNSlocal unsigned __stdcall 
-SMBRegistrationThread( void * arg )
-{
-	mDNS * const m = ( mDNS * const ) arg;
-	DNSServiceRef sref = NULL;
-	HANDLE		handles[ 3 ];
-	mDNSu8		txtBuf[ 256 ];
-	mDNSu8	*	txtPtr;
-	size_t		keyLen;
-	size_t		valLen;
-	mDNSIPPort	port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
-	DNSServiceErrorType err;
-
-	DEBUG_UNUSED( arg );
-
-	handles[ 0 ] = gSMBThreadStopEvent;
-	handles[ 1 ] = gSMBThreadRegisterEvent;
-	handles[ 2 ] = gSMBThreadDeregisterEvent;
-
-	memset( txtBuf, 0, sizeof( txtBuf )  );
-	txtPtr = txtBuf;
-	keyLen = strlen( "netbios=" );
-	valLen = strlen( m->p->nbname );
-	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
-	*txtPtr++ = ( mDNSu8 ) ( keyLen + valLen );
-	memcpy( txtPtr, "netbios=", keyLen );
-	txtPtr += keyLen;
-	if ( valLen ) { memcpy( txtPtr, m->p->nbname, valLen ); txtPtr += ( mDNSu8 ) valLen; }
-	keyLen = strlen( "domain=" );
-	valLen = strlen( m->p->nbdomain );
-	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
-	*txtPtr++ = ( mDNSu8 )( keyLen + valLen );
-	memcpy( txtPtr, "domain=", keyLen );
-	txtPtr += keyLen;
-	if ( valLen ) { memcpy( txtPtr, m->p->nbdomain, valLen ); txtPtr += valLen; }
-	
-	for ( ;; )
-	{
-		DWORD ret;
-
-		ret = WaitForMultipleObjects( 3, handles, FALSE, INFINITE );
-
-		if ( ret != WAIT_FAILED )
-		{
-			if ( ret == kSMBStopEvent )
-			{
-				break;
-			}
-			else if ( ret == kSMBRegisterEvent )
-			{
-				err = gDNSServiceRegister( &sref, 0, 0, NULL, "_smb._tcp,_file", NULL, NULL, ( uint16_t ) port.NotAnInteger, ( mDNSu16 )( txtPtr - txtBuf ), txtBuf, NULL, NULL );
-
-				if ( err )
-				{
-					LogMsg( "SMBRegistrationThread: DNSServiceRegister returned %d\n", err );
-					sref = NULL;
-					break;
-				}
-			}
-			else if ( ret == kSMBDeregisterEvent )
-			{
-				if ( sref )
-				{
-					gDNSServiceRefDeallocate( sref );
-					sref = NULL;
-				}
-			}
-		}
-		else
-		{
-			LogMsg( "SMBRegistrationThread:  WaitForMultipleObjects returned %d\n", GetLastError() );
-			break;
-		}
-	}
-
-exit:
-
-	if ( sref != NULL )
-	{
-		gDNSServiceRefDeallocate( sref );
-		sref = NULL;
-	}
-
-	SetEvent( gSMBThreadQuitEvent );
-	_endthreadex( 0 );
-	return 0;
-}
-
-mDNSlocal void
-CheckFileShares( mDNS * const m )
-{
-	PSHARE_INFO_1	bufPtr = ( PSHARE_INFO_1 ) NULL;
-	DWORD			entriesRead = 0;
-	DWORD			totalEntries = 0;
-	DWORD			resume = 0;
-	mDNSBool		advertise = mDNSfalse;
-	mDNSBool		fileSharing = mDNSfalse;
-	mDNSBool		printSharing = mDNSfalse;
-	HKEY			key = NULL;
-	BOOL			retry = FALSE;
-	NET_API_STATUS  res;
-	mStatus			err;
-
-	check( m );
-
-	// Only do this if we're not shutting down
-
-	require_action_quiet( m->AdvertiseLocalAddresses && !m->ShutdownTime, exit, err = kNoErr );
-
-	err = RegCreateKey(HKEY_CURRENT_USER, kServiceParametersNode L"\\Services\\SMB", &key);
-
-	if ( !err )
-	{
-		DWORD dwSize = sizeof( DWORD );
-		RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &advertise, &dwSize );
-	}
-
-	if ( advertise && mDNSIsFileAndPrintSharingEnabled( &retry ) )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "Sharing is enabled\n" );
-
-		res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
-
-		if ( ( res == ERROR_SUCCESS ) || ( res == ERROR_MORE_DATA ) )
-		{
-			PSHARE_INFO_1 p = bufPtr;
-			DWORD i;
-
-			for( i = 0; i < entriesRead; i++ ) 
-			{
-				// We are only interested if the user is sharing anything other 
-				// than the built-in "print$" source
-
-				if ( ( p->shi1_type == STYPE_DISKTREE ) && ( wcscmp( p->shi1_netname, TEXT( "print$" ) ) != 0 ) )
-				{
-					fileSharing = mDNStrue;
-				}
-				else if ( p->shi1_type == STYPE_PRINTQ )
-				{
-					printSharing = mDNStrue;
-				}
-
-				p++;
-			}
-
-			NetApiBufferFree( bufPtr );
-			bufPtr = NULL;
-			retry = FALSE;
-		}
-		else if ( res == NERR_ServerNotStarted )
-		{
-			retry = TRUE;
-		}
-	}
-	
-	if ( retry )
-	{
-		__int64			qwTimeout;
-		LARGE_INTEGER   liTimeout;
-
-		qwTimeout = -m->p->checkFileSharesTimeout * 10000000;
-		liTimeout.LowPart  = ( DWORD )( qwTimeout & 0xFFFFFFFF );
-		liTimeout.HighPart = ( LONG )( qwTimeout >> 32 );
-
-		SetWaitableTimer( m->p->checkFileSharesTimer, &liTimeout, 0, CheckFileSharesProc, m, FALSE );
-	}
-
-	if ( !m->p->smbFileSharing && fileSharing )
-	{
-		if ( !gSMBThread )
-		{
-			if ( !gDNSSDLibrary )
-			{
-				gDNSSDLibrary = LoadLibrary( TEXT( "dnssd.dll" ) );
-				require_action( gDNSSDLibrary, exit, err = GetLastError() );
-			}
-
-			if ( !gDNSServiceRegister )
-			{
-				gDNSServiceRegister = ( DNSServiceRegisterFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRegister" );
-				require_action( gDNSServiceRegister, exit, err = GetLastError() );
-			}
-
-			if ( !gDNSServiceRefDeallocate )
-			{
-				gDNSServiceRefDeallocate = ( DNSServiceRefDeallocateFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRefDeallocate" );
-				require_action( gDNSServiceRefDeallocate, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadRegisterEvent )
-			{
-				gSMBThreadRegisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadRegisterEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadDeregisterEvent )
-			{
-				gSMBThreadDeregisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadDeregisterEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadStopEvent )
-			{
-				gSMBThreadStopEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadStopEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadQuitEvent )
-			{
-				gSMBThreadQuitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadQuitEvent != NULL, exit, err = GetLastError() );
-			}
-
-			gSMBThread = ( HANDLE ) _beginthreadex( NULL, 0, SMBRegistrationThread, m, 0, NULL );
-			require_action( gSMBThread != NULL, exit, err = GetLastError() );
-		}
-
-		SetEvent( gSMBThreadRegisterEvent );
-
-		m->p->smbFileSharing = mDNStrue;
-	}
-	else if ( m->p->smbFileSharing && !fileSharing )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
-
-		if ( gSMBThreadDeregisterEvent != NULL )
-		{
-			SetEvent( gSMBThreadDeregisterEvent );
-		}
-
-		m->p->smbFileSharing = mDNSfalse;
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-BOOL
-IsWOMPEnabled( mDNS * const m )
-{
-	BOOL enabled;
-
-	mDNSInterfaceData * ifd;
-
-	enabled = FALSE;
-
-	for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if ( IsWOMPEnabledForAdapter( ifd->name ) )
-		{
-			enabled = TRUE;
-			break;
-		}
-	}
-
-	return enabled;
-}
-
-mDNSlocal mDNSu8
-IsWOMPEnabledForAdapter( const char * adapterName )
-{
-	char						fileName[80];
-	NDIS_OID					oid;
-	DWORD						count;
-	HANDLE						handle	= INVALID_HANDLE_VALUE;
-	NDIS_PNP_CAPABILITIES	*	pNPC	= NULL;
-	int							err;
-	mDNSu8						ok		= TRUE;
-
-	require_action( adapterName != NULL, exit, ok = FALSE );
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter: %s\n", adapterName );
-	
-	// Construct a device name to pass to CreateFile
-
-	strncpy_s( fileName, sizeof( fileName ), DEVICE_PREFIX, strlen( DEVICE_PREFIX ) );
-	strcat_s( fileName, sizeof( fileName ), adapterName );
-	handle = CreateFileA( fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, INVALID_HANDLE_VALUE );
-	require_action ( handle != INVALID_HANDLE_VALUE, exit, ok = FALSE );
-
-	// We successfully opened the driver, format the IOCTL to pass the driver.
-		
-	oid = OID_PNP_CAPABILITIES;
-	pNPC = ( NDIS_PNP_CAPABILITIES * ) malloc( sizeof( NDIS_PNP_CAPABILITIES ) );
-	require_action( pNPC != NULL, exit, ok = FALSE );
-	ok = ( mDNSu8 ) DeviceIoControl( handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof( oid ), pNPC, sizeof( NDIS_PNP_CAPABILITIES ), &count, NULL );
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_action( !err, exit, ok = FALSE );
-	ok = ( mDNSu8 ) ( ( count == sizeof( NDIS_PNP_CAPABILITIES ) ) && ( pNPC->Flags & NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE ) );
-	   
-exit:
-
-	if ( pNPC != NULL )
-	{
-		free( pNPC );
-	}
-
-	if ( handle != INVALID_HANDLE_VALUE )
-	{
-		CloseHandle( handle );
-	}
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter returns %s\n", ok ? "true" : "false" );
-
-	return ( mDNSu8 ) ok;
-}
-
-mDNSlocal void
-SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep )
-{
-	mDNSBool	repeat = ( numTries == 1 ) ? mDNStrue : mDNSfalse;
-	SOCKET		sock;
-	int			num;
-	mStatus		err;
-
-	( void ) inMDNS;
-
-	sock = socket( addr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
-	require_action( sock != INVALID_SOCKET, exit, err = mStatus_UnknownErr );
-
-	while ( numTries-- )
-	{
-		num = sendto( sock, ( const char* ) buf, buflen, 0, addr, addrlen );
-
-		if ( num != buflen )
-		{
-			LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
-		}
-
-		if ( repeat )
-		{
-			num = sendto( sock, buf, buflen, 0, addr, addrlen );
-
-			if ( num != buflen )
-			{
-				LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
-			}
-		}
-
-		if ( msecSleep )
-		{
-			Sleep( msecSleep );
-		}
-	}
-
-exit:
-
-	if ( sock != INVALID_SOCKET )
-	{
-		closesocket( sock );
-	}
-} 
-
-mDNSlocal void _cdecl
-SendMulticastWakeupPacket( void *arg )
-{
-	MulticastWakeupStruct *info = ( MulticastWakeupStruct* ) arg;
-	
-	if ( info )
-	{
-		SendWakeupPacket( info->inMDNS, ( LPSOCKADDR ) &info->addr, sizeof( info->addr ), ( const char* ) info->data, sizeof( info->data ), info->numTries, info->msecSleep );
-		free( info );
-	}
-
-	_endthread();
-}
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( rr );
-	DEBUG_UNUSED( result );
-}
diff --git a/mDNSWindows/mDNSWin32.h b/mDNSWindows/mDNSWin32.h
deleted file mode 100644
index f4faa3d..0000000
--- a/mDNSWindows/mDNSWin32.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 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.
- */
-
-#ifndef	__MDNS_WIN32__
-#define	__MDNS_WIN32__
-
-#include	"CommonServices.h"
-
-#if( !defined( _WIN32_WCE ) )
-	#include	<mswsock.h>
-#endif
-
-#include	"mDNSEmbeddedAPI.h"
-#include	"uDNS.h"
-#include	"uds_daemon.h"
-
-#ifdef	__cplusplus
-	extern "C" {
-#endif
-
-
-struct TCPSocket_struct
-{
-    mDNSIPPort                  port;           // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with mDNSIPPort
-    TCPSocketFlags              flags;          // MUST BE SECOND FIELD -- mDNSCore expects every TCPSocket_struct have TCPSocketFlags flags after mDNSIPPort
-	SOCKET						fd;
-	BOOL						connected;
-	TCPConnectionCallback		tcpConnectionCallback;
-	udsEventCallback			udsEventCallback;
-	void					*	userContext;
-	BOOL						closed;
-	mDNS					*	m;
-};
-
-
-struct UDPSocket_struct
-{
-	mDNSIPPort					port; 		// MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
-	mDNSAddr					addr;		// This is initialized by our code. If we don't get the 
-											// dstAddr from WSARecvMsg we use this value instead.
-	SOCKET						fd;
-	LPFN_WSARECVMSG				recvMsgPtr;
-	DNSMessage					packet;
-	struct mDNSInterfaceData	*ifd;
-	UDPSocket					*next;
-	mDNS						*m;
-};
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@struct		mDNSInterfaceData
-
-	@abstract	Structure containing interface-specific data.
-*/
-
-typedef struct	mDNSInterfaceData	mDNSInterfaceData;
-struct	mDNSInterfaceData
-{
-	char						name[ 128 ];
-	uint32_t					index;
-	uint32_t					scopeID;
-	struct UDPSocket_struct		sock;
-	NetworkInterfaceInfo		interfaceInfo;
-	mDNSBool					hostRegistered;
-	mDNSInterfaceData		*	next;
-};
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	ReportStatusFunc
-*/
-typedef void		(*ReportStatusFunc)(int inType, const char *inFormat, ...);
-
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@struct		mDNS_PlatformSupport_struct
-
-	@abstract	Structure containing platform-specific data.
-*/
-
-struct	mDNS_PlatformSupport_struct
-{
-	HANDLE						mainThread;
-	HANDLE						checkFileSharesTimer;
-	mDNSs32						checkFileSharesTimeout;
-	ReportStatusFunc			reportStatusFunc;
-	time_t						nextDHCPLeaseExpires;
-	char						nbname[ 32 ];
-	char						nbdomain[ 32 ];
-	mDNSBool					smbFileSharing;
-	mDNSBool					smbPrintSharing;
-	ServiceRecordSet			smbSRS;
-	AuthRecord					smbSubTypes[ 2 ];
-	mDNSBool					registeredLoopback4;
-	int							interfaceCount;
-	mDNSInterfaceData *			interfaceList;
-	mDNSInterfaceData *			inactiveInterfaceList;
-	struct UDPSocket_struct		unicastSock4;
-	struct UDPSocket_struct		unicastSock6;
-	DWORD						osMajorVersion;
-	DWORD						osMinorVersion;
-};
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@struct		ifaddrs
-
-	@abstract	Interface information
-*/
-
-struct ifaddrs
-{
-	struct ifaddrs *	ifa_next;
-	char *				ifa_name;
-	u_int				ifa_flags;
-	struct sockaddr	*	ifa_addr;
-	struct sockaddr	*	ifa_netmask;
-	struct sockaddr	*	ifa_broadaddr;
-	struct sockaddr	*	ifa_dstaddr;
-	BYTE				ifa_physaddr[6];
-	BOOL				ifa_dhcpEnabled;
-	time_t				ifa_dhcpLeaseExpires;
-	mDNSu8				ifa_womp;
-	void *				ifa_data;
-	
-	struct
-	{
-		uint32_t		index;
-	
-	}	ifa_extra;
-};
-
-
-extern void		InterfaceListDidChange( mDNS * const inMDNS );
-extern void		ComputerDescriptionDidChange( mDNS * const inMDNS );
-extern void		TCPIPConfigDidChange( mDNS * const inMDNS );
-extern void		DynDNSConfigDidChange( mDNS * const inMDNS );
-extern void		FileSharingDidChange( mDNS * const inMDNS );
-extern void		FirewallDidChange( mDNS * const inMDNS );
-extern mStatus  TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock );
-extern mStatus	SetupInterfaceList( mDNS * const inMDNS );
-extern mStatus	TearDownInterfaceList( mDNS * const inMDNS );
-extern BOOL		IsWOMPEnabled();
-extern void     DispatchSocketEvents( mDNS * const inMDNS );
-
-
-#ifdef	__cplusplus
-	}
-#endif
-
-#endif	// __MDNS_WIN32__
diff --git a/mDNSWindows/mdnsNSP/mdnsNSP.c b/mDNSWindows/mdnsNSP/mdnsNSP.c
deleted file mode 100644
index 21baa86..0000000
--- a/mDNSWindows/mdnsNSP/mdnsNSP.c
+++ /dev/null
@@ -1,2433 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004 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.
- */
-
-
-#include	<stdio.h>
-#include	<stdlib.h>
-#include	<string.h>
-
-#include	"ClientCommon.h"
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-
-#include	<iphlpapi.h>
-#include	<guiddef.h>
-#include	<ws2spi.h>
-#include	<shlwapi.h>
-
-
-
-#include	"dns_sd.h"
-
-#pragma comment(lib, "DelayImp.lib")
-
-#ifdef _MSC_VER
-#define swprintf _snwprintf
-#define snprintf _snprintf
-#endif
-
-#define MAX_LABELS 128
-
-#if 0
-#pragma mark == Structures ==
-#endif
-
-//===========================================================================================================================
-//	Structures
-//===========================================================================================================================
-
-typedef struct	Query *		QueryRef;
-typedef struct	Query		Query;
-struct	Query
-{
-	QueryRef			next;
-	int					refCount;
-	DWORD				querySetFlags;
-	WSAQUERYSETW *		querySet;
-	size_t				querySetSize;
-	HANDLE				data4Event;
-	HANDLE				data6Event;
-	HANDLE				cancelEvent;
-	HANDLE				waitHandles[ 3 ];
-	DWORD				waitCount;
-	DNSServiceRef		resolver4;
-	DNSServiceRef		resolver6;
-	char				name[ kDNSServiceMaxDomainName ];
-	size_t				nameSize;
-	uint8_t				numValidAddrs;
-	uint32_t			addr4;
-	bool				addr4Valid;
-	uint8_t				addr6[16];
-	u_long				addr6ScopeId;
-	bool				addr6Valid;
-};
-
-#define BUFFER_INITIAL_SIZE		4192
-#define ALIASES_INITIAL_SIZE	5
-
-typedef struct HostsFile
-{
-	int			m_bufferSize;
-	char	*	m_buffer;
-	FILE	*	m_fp;
-} HostsFile;
-
-
-typedef struct HostsFileInfo
-{
-	struct hostent		m_host;
-	struct HostsFileInfo	*	m_next;
-} HostsFileInfo;
-
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-// DLL Exports
-
-BOOL WINAPI		DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved );
-STDAPI			DllRegisterServer( void );
-STDAPI			DllRegisterServer( void );
-
-	
-// NSP SPIs
-
-int	WSPAPI	NSPCleanup( LPGUID inProviderID );
-
-DEBUG_LOCAL int WSPAPI
-	NSPLookupServiceBegin(
-		LPGUID					inProviderID,
-		LPWSAQUERYSETW			inQuerySet,
-		LPWSASERVICECLASSINFOW	inServiceClassInfo,
-		DWORD					inFlags,   
-		LPHANDLE				outLookup );
-
-DEBUG_LOCAL int WSPAPI
-	NSPLookupServiceNext(  
-		HANDLE			inLookup,
-		DWORD			inFlags,
-		LPDWORD			ioBufferLength,
-		LPWSAQUERYSETW	outResults );
-
-DEBUG_LOCAL int WSPAPI	NSPLookupServiceEnd( HANDLE inLookup );
-
-DEBUG_LOCAL int WSPAPI
-	NSPSetService(
-		LPGUID					inProviderID,						
-		LPWSASERVICECLASSINFOW	inServiceClassInfo,   
-		LPWSAQUERYSETW			inRegInfo,				  
-		WSAESETSERVICEOP		inOperation,			   
-		DWORD					inFlags );
-
-DEBUG_LOCAL int WSPAPI	NSPInstallServiceClass( LPGUID inProviderID, LPWSASERVICECLASSINFOW inServiceClassInfo );
-DEBUG_LOCAL int WSPAPI	NSPRemoveServiceClass( LPGUID inProviderID, LPGUID inServiceClassID );
-DEBUG_LOCAL int WSPAPI	NSPGetServiceClassInfo(	LPGUID inProviderID, LPDWORD ioBufSize, LPWSASERVICECLASSINFOW ioServiceClassInfo );
-
-// Private
-
-#define	NSPLock()		EnterCriticalSection( &gLock );
-#define	NSPUnlock()		LeaveCriticalSection( &gLock );
-
-DEBUG_LOCAL OSStatus	QueryCreate( const WSAQUERYSETW *inQuerySet, DWORD inQuerySetFlags, QueryRef *outRef );
-DEBUG_LOCAL OSStatus	QueryRetain( QueryRef inRef );
-DEBUG_LOCAL OSStatus	QueryRelease( QueryRef inRef );
-
-DEBUG_LOCAL void CALLBACK_COMPAT
-	QueryRecordCallback4(
-		DNSServiceRef		inRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inErrorCode,
-		const char *		inName,    
-		uint16_t			inRRType,
-		uint16_t			inRRClass,
-		uint16_t			inRDataSize,
-		const void *		inRData,
-		uint32_t			inTTL,
-		void *				inContext );
-
-DEBUG_LOCAL void CALLBACK_COMPAT
-	QueryRecordCallback6(
-		DNSServiceRef		inRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inErrorCode,
-		const char *		inName,    
-		uint16_t			inRRType,
-		uint16_t			inRRClass,
-		uint16_t			inRDataSize,
-		const void *		inRData,
-		uint32_t			inTTL,
-		void *				inContext );
-
-DEBUG_LOCAL OSStatus
-	QueryCopyQuerySet( 
-		QueryRef 				inRef, 
-		const WSAQUERYSETW *	inQuerySet, 
-		DWORD 					inQuerySetFlags, 
-		WSAQUERYSETW **			outQuerySet, 
-		size_t *				outSize );
-
-DEBUG_LOCAL void
-	QueryCopyQuerySetTo( 
-		QueryRef 				inRef, 
-		const WSAQUERYSETW *	inQuerySet, 
-		DWORD 					inQuerySetFlags, 
-		WSAQUERYSETW *			outQuerySet );
-
-DEBUG_LOCAL size_t	QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *inQuerySet, DWORD inQuerySetFlags );
-
-#if( DEBUG )
-	void	DebugDumpQuerySet( DebugLevel inLevel, const WSAQUERYSETW *inQuerySet );
-	
-	#define	dlog_query_set( LEVEL, SET )		DebugDumpQuerySet( LEVEL, SET )
-#else
-	#define	dlog_query_set( LEVEL, SET )
-#endif
-
-DEBUG_LOCAL BOOL		InHostsTable( const char * name );
-DEBUG_LOCAL BOOL		IsLocalName( HostsFileInfo * node );
-DEBUG_LOCAL BOOL		IsSameName( HostsFileInfo * node, const char * name );
-DEBUG_LOCAL OSStatus	HostsFileOpen( HostsFile ** self, const char * fname );
-DEBUG_LOCAL OSStatus	HostsFileClose( HostsFile * self );
-DEBUG_LOCAL void		HostsFileInfoFree( HostsFileInfo * info );
-DEBUG_LOCAL OSStatus	HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo );
-DEBUG_LOCAL DWORD		GetScopeId( DWORD ifIndex );
-
-#ifdef ENABLE_REVERSE_LOOKUP
-DEBUG_LOCAL OSStatus	IsReverseLookup( LPCWSTR name, size_t size );
-#endif
-
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-// {B600E6E9-553B-4a19-8696-335E5C896153}
-DEBUG_LOCAL HINSTANCE				gInstance			= NULL;
-DEBUG_LOCAL wchar_t				*	gNSPName			= L"mdnsNSP";
-DEBUG_LOCAL GUID					gNSPGUID			= { 0xb600e6e9, 0x553b, 0x4a19, { 0x86, 0x96, 0x33, 0x5e, 0x5c, 0x89, 0x61, 0x53 } };
-DEBUG_LOCAL LONG					gRefCount			= 0;
-DEBUG_LOCAL CRITICAL_SECTION		gLock;
-DEBUG_LOCAL bool					gLockInitialized 	= false;
-DEBUG_LOCAL QueryRef				gQueryList	 		= NULL;
-DEBUG_LOCAL HostsFileInfo		*	gHostsFileInfo		= NULL;
-typedef DWORD
-	( WINAPI * GetAdaptersAddressesFunctionPtr )( 
-			ULONG 					inFamily, 
-			DWORD 					inFlags, 
-			PVOID 					inReserved, 
-			PIP_ADAPTER_ADDRESSES 	inAdapter, 
-			PULONG					outBufferSize );
-
-DEBUG_LOCAL HMODULE								gIPHelperLibraryInstance			= NULL;
-DEBUG_LOCAL GetAdaptersAddressesFunctionPtr		gGetAdaptersAddressesFunctionPtr	= NULL;
-
-
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	DllMain
-//===========================================================================================================================
-
-BOOL APIENTRY	DllMain( HINSTANCE inInstance, DWORD inReason, LPVOID inReserved )
-{
-	DEBUG_USE_ONLY( inInstance );
-	DEBUG_UNUSED( inReserved );
-
-	switch( inReason )
-	{
-		case DLL_PROCESS_ATTACH:			
-			gInstance = inInstance;		
-			gHostsFileInfo	= NULL;
-			debug_initialize( kDebugOutputTypeWindowsEventLog, "mDNS NSP", inInstance );
-			debug_set_property( kDebugPropertyTagPrintLevel, kDebugLevelNotice );
-			dlog( kDebugLevelTrace, "\n" );
-			dlog( kDebugLevelVerbose, "%s: process attach\n", __ROUTINE__ );
-
-			break;
-		
-		case DLL_PROCESS_DETACH:
-			HostsFileInfoFree( gHostsFileInfo );
-			gHostsFileInfo = NULL;
-			dlog( kDebugLevelVerbose, "%s: process detach\n", __ROUTINE__ );
-			break;
-		
-		case DLL_THREAD_ATTACH:
-			dlog( kDebugLevelVerbose, "%s: thread attach\n", __ROUTINE__ );
-			break;
-		
-		case DLL_THREAD_DETACH:
-			dlog( kDebugLevelVerbose, "%s: thread detach\n", __ROUTINE__ );
-			break;
-		
-		default:
-			dlog( kDebugLevelNotice, "%s: unknown reason code (%d)\n", __ROUTINE__, inReason );
-			break;
-	}
-
-	return( TRUE );
-}
-
-
-//===========================================================================================================================
-//	DllRegisterServer
-//===========================================================================================================================
-
-STDAPI	DllRegisterServer( void )
-{
-	WSADATA		wsd;
-	WCHAR		path[ MAX_PATH ];
-	HRESULT		err;
-	
-	dlog( kDebugLevelTrace, "DllRegisterServer\n" );
-
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-
-	// Unregister before registering to workaround an installer
-	// problem during upgrade installs.
-
-	WSCUnInstallNameSpace( &gNSPGUID );
-
-	err = GetModuleFileNameW( gInstance, path, MAX_PATH );
-	err = translate_errno( err != 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-
-	err = WSCInstallNameSpace( gNSPName, path, NS_DNS, 1, &gNSPGUID );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-exit:
-
-	WSACleanup();
-	return( err );
-}
-
-//===========================================================================================================================
-//	DllUnregisterServer
-//===========================================================================================================================
-
-STDAPI	DllUnregisterServer( void )
-{
-	WSADATA		wsd;
-	HRESULT err;
-	
-	dlog( kDebugLevelTrace, "DllUnregisterServer\n" );
-	
-	err = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	err = WSCUnInstallNameSpace( &gNSPGUID );
-	err = translate_errno( err == 0, errno_compat(), WSAEINVAL );
-	require_noerr( err, exit );
-		
-exit:
-
-	WSACleanup();
-	return err;
-}
-
-
-//===========================================================================================================================
-//	NSPStartup
-//
-//	This function is called when our namespace DLL is loaded. It sets up the NSP functions we implement and initializes us.
-//===========================================================================================================================
-
-int WSPAPI	NSPStartup( LPGUID inProviderID, LPNSP_ROUTINE outRoutines )
-{
-	OSStatus		err;
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s (GUID=%U, refCount=%ld)\n", __ROUTINE__, inProviderID, gRefCount );
-	
-	// Only initialize if this is the first time NSPStartup is called. 
-	
-	if( InterlockedIncrement( &gRefCount ) != 1 )
-	{
-		err = NO_ERROR;
-		goto exit;
-	}
-	
-	// Initialize our internal state.
-	
-	InitializeCriticalSection( &gLock );
-	gLockInitialized = true;
-	
-	// Set the size to exclude NSPIoctl because we don't implement it.
-	
-	outRoutines->cbSize					= FIELD_OFFSET( NSP_ROUTINE, NSPIoctl );
-	outRoutines->dwMajorVersion			= 4;
-	outRoutines->dwMinorVersion			= 4;
-	outRoutines->NSPCleanup				= NSPCleanup;
-	outRoutines->NSPLookupServiceBegin	= NSPLookupServiceBegin;
-	outRoutines->NSPLookupServiceNext	= NSPLookupServiceNext;
-	outRoutines->NSPLookupServiceEnd	= NSPLookupServiceEnd;
-	outRoutines->NSPSetService			= NSPSetService;
-	outRoutines->NSPInstallServiceClass	= NSPInstallServiceClass;
-	outRoutines->NSPRemoveServiceClass	= NSPRemoveServiceClass;
-	outRoutines->NSPGetServiceClassInfo	= NSPGetServiceClassInfo;
-	
-	// See if we can get the address for the GetAdaptersAddresses() API.  This is only in XP, but we want our
-	// code to run on older versions of Windows
-
-	if ( !gIPHelperLibraryInstance )
-	{
-		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
-		if( gIPHelperLibraryInstance )
-		{
-			gGetAdaptersAddressesFunctionPtr = (GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
-		}
-	}
-
-	err = NO_ERROR;
-	
-exit:
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	if( err != NO_ERROR )
-	{
-		NSPCleanup( inProviderID );
-		SetLastError( (DWORD) err );
-		return( SOCKET_ERROR );
-	}
-	return( NO_ERROR );
-}
-
-//===========================================================================================================================
-//	NSPCleanup
-//
-//	This function is called when our namespace DLL is unloaded. It cleans up anything we set up in NSPStartup.
-//===========================================================================================================================
-
-int	WSPAPI	NSPCleanup( LPGUID inProviderID )
-{
-	DEBUG_USE_ONLY( inProviderID );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s (GUID=%U, refCount=%ld)\n", __ROUTINE__, inProviderID, gRefCount );
-	
-	// Only initialize if this is the first time NSPStartup is called.
-	
-	if( InterlockedDecrement( &gRefCount ) != 0 )
-	{
-		goto exit;
-	}
-	
-	// Stop any outstanding queries.
-	
-	if( gLockInitialized )
-	{
-		NSPLock();
-	}
-	while( gQueryList )
-	{
-		check_string( gQueryList->refCount == 1, "NSPCleanup with outstanding queries!" );
-		QueryRelease( gQueryList );
-	}
-	if( gLockInitialized )
-	{
-		NSPUnlock();
-	}
-	
-	if( gLockInitialized )
-	{
-		gLockInitialized = false;
-		DeleteCriticalSection( &gLock );
-	}
-
-	if( gIPHelperLibraryInstance )
-	{
-		BOOL ok;
-				
-		ok = FreeLibrary( gIPHelperLibraryInstance );
-		check_translated_errno( ok, GetLastError(), kUnknownErr );
-		gIPHelperLibraryInstance = NULL;
-	}
-	
-exit:
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	return( NO_ERROR );
-}
-
-//===========================================================================================================================
-//	NSPLookupServiceBegin
-//
-//	This function maps to the WinSock WSALookupServiceBegin function. It starts the lookup process and returns a HANDLE 
-//	that can be used in subsequent operations. Subsequent calls only need to refer to this query by the handle as 
-//	opposed to specifying the query parameters each time.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI
-	NSPLookupServiceBegin(
-		LPGUID					inProviderID,
-		LPWSAQUERYSETW			inQuerySet,
-		LPWSASERVICECLASSINFOW	inServiceClassInfo,
-		DWORD					inFlags,   
-		LPHANDLE				outLookup )
-{
-	OSStatus		err;
-	QueryRef		obj;
-	LPCWSTR			name;
-	size_t			size;
-	LPCWSTR			p;
-	DWORD           type;
-	DWORD			n;
-	DWORD			i;
-	INT				family;
-	INT				protocol;
-	
-	DEBUG_UNUSED( inProviderID );
-	DEBUG_UNUSED( inServiceClassInfo );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	
-	obj = NULL;
-	require_action( inQuerySet, exit, err = WSAEINVAL );
-	name = inQuerySet->lpszServiceInstanceName;
-	require_action_quiet( name, exit, err = WSAEINVAL );
-	require_action( outLookup, exit, err = WSAEINVAL );
-	
-	dlog( kDebugLevelTrace, "%s (flags=0x%08X, name=\"%S\")\n", __ROUTINE__, inFlags, name );
-	dlog_query_set( kDebugLevelVerbose, inQuerySet );
-	
-	// Check if we can handle this type of request and if we support any of the protocols being requested.
-	// We only support the DNS namespace, TCP and UDP protocols, and IPv4. Only blob results are supported.
-	
-	require_action_quiet( inFlags & (LUP_RETURN_ADDR|LUP_RETURN_BLOB), exit, err = WSASERVICE_NOT_FOUND );
-	
-	type = inQuerySet->dwNameSpace;
-	require_action_quiet( ( type == NS_DNS ) || ( type == NS_ALL ), exit, err = WSASERVICE_NOT_FOUND );
-	
-	n = inQuerySet->dwNumberOfProtocols;
-	if( n > 0 )
-	{
-		require_action( inQuerySet->lpafpProtocols, exit, err = WSAEINVAL );
-		for( i = 0; i < n; ++i )
-		{
-			family = inQuerySet->lpafpProtocols[ i ].iAddressFamily;
-			protocol = inQuerySet->lpafpProtocols[ i ].iProtocol;
-			if( ( family == AF_INET ) && ( ( protocol == IPPROTO_UDP ) || ( protocol == IPPROTO_TCP ) ) )
-			{
-				break;
-			}
-		}
-		require_action_quiet( i < n, exit, err = WSASERVICE_NOT_FOUND );
-	}
-	
-	// Check if the name ends in ".local" and if not, exit with an error since we only resolve .local names.
-	// The name may or may not end with a "." (fully qualified) so handle both cases. DNS is also case 
-	// insensitive the check for .local has to be case insensitive (.LoCaL is equivalent to .local). This
-	// manually does the wchar_t strlen and stricmp to avoid needing any special wchar_t versions of the 
-	// libraries. It is probably faster to do the inline compare than invoke functions to do it anyway.
-	
-	for( p = name; *p; ++p ) {}		// Find end of string
-	size = (size_t)( p - name );
-	require_action_quiet( size > sizeof_string( ".local" ), exit, err = WSASERVICE_NOT_FOUND );
-	
-	p = name + ( size - 1 );
-	p = ( *p == '.' ) ? ( p - sizeof_string( ".local" ) ) : ( ( p - sizeof_string( ".local" ) ) + 1 );
-	if	( ( ( p[ 0 ] != '.' )						||
-		( ( p[ 1 ] != 'L' ) && ( p[ 1 ] != 'l' ) )	||
-		( ( p[ 2 ] != 'O' ) && ( p[ 2 ] != 'o' ) )	||
-		( ( p[ 3 ] != 'C' ) && ( p[ 3 ] != 'c' ) )	||
-		( ( p[ 4 ] != 'A' ) && ( p[ 4 ] != 'a' ) )	||
-		( ( p[ 5 ] != 'L' ) && ( p[ 5 ] != 'l' ) ) ) )
-	{
-#ifdef ENABLE_REVERSE_LOOKUP
-
-		err = IsReverseLookup( name, size );
-
-#else
-
-		err = WSASERVICE_NOT_FOUND;
-
-#endif
-
-		require_noerr( err, exit );
-	}
-	else
-	{
-		const char	*	replyDomain;
-		char			translated[ kDNSServiceMaxDomainName ];
-		int				n;
-		int				labels		= 0;
-		const char	*	label[MAX_LABELS];
-		char			text[64];
-
-		n = WideCharToMultiByte( CP_UTF8, 0, name, -1, translated, sizeof( translated ), NULL, NULL );
-		require_action( n > 0, exit, err = WSASERVICE_NOT_FOUND );
-
-		// <rdar://problem/4050633>
-
-		// Don't resolve multi-label name
-
-		// <rdar://problem/5914160> Eliminate use of GetNextLabel in mdnsNSP
-		// Add checks for GetNextLabel returning NULL, individual labels being greater than
-		// 64 bytes, and the number of labels being greater than MAX_LABELS
-		replyDomain = translated;
-
-		while (replyDomain && *replyDomain && labels < MAX_LABELS)
-		{
-			label[labels++]	= replyDomain;
-			replyDomain		= GetNextLabel(replyDomain, text);
-		}
-
-		require_action( labels == 2, exit, err = WSASERVICE_NOT_FOUND );
-
-		// <rdar://problem/3936771>
-		//
-		// Check to see if the name of this host is in the hosts table. If so,
-		// don't try and resolve it
-		
-		require_action( InHostsTable( translated ) == FALSE, exit, err = WSASERVICE_NOT_FOUND );
-	}
-
-	// The name ends in .local ( and isn't in the hosts table ), .0.8.e.f.ip6.arpa, or .254.169.in-addr.arpa so start the resolve operation. Lazy initialize DNS-SD if needed.
-		
-	NSPLock();
-	
-	err = QueryCreate( inQuerySet, inFlags, &obj );
-	NSPUnlock();
-	require_noerr( err, exit );
-	
-	*outLookup = (HANDLE) obj;
-	
-exit:
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	if( err != NO_ERROR )
-	{
-		SetLastError( (DWORD) err );
-		return( SOCKET_ERROR );
-	}
-	return( NO_ERROR );
-}
-
-//===========================================================================================================================
-//	NSPLookupServiceNext
-//
-//	This function maps to the Winsock call WSALookupServiceNext. This routine takes a handle to a previously defined 
-//	query and attempts to locate a service matching the criteria defined by the query. If so, that instance is returned 
-//	in the lpqsResults parameter.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI
-	NSPLookupServiceNext(  
-		HANDLE			inLookup,
-		DWORD			inFlags,
-		LPDWORD			ioSize,
-		LPWSAQUERYSETW	outResults )
-{
-	BOOL			data4;
-	BOOL			data6;
-	OSStatus		err;
-	QueryRef		obj;
-	DWORD			waitResult;
-	size_t			size;
-	
-	DEBUG_USE_ONLY( inFlags );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	
-	data4 = FALSE;
-	data6 = FALSE;
-	obj = NULL;
-	NSPLock();
-	err = QueryRetain( (QueryRef) inLookup );
-	require_noerr( err, exit );
-	obj = (QueryRef) inLookup;
-	require_action( ioSize, exit, err = WSAEINVAL );
-	require_action( outResults, exit, err = WSAEINVAL );
-	
-	dlog( kDebugLevelTrace, "%s (lookup=%#p, flags=0x%08X, *ioSize=%d)\n", __ROUTINE__, inLookup, inFlags, *ioSize );
-	
-	// Wait for data or a cancel. Release the lock while waiting. This is safe because we've retained the query.
-
-	NSPUnlock();
-	waitResult = WaitForMultipleObjects( obj->waitCount, obj->waitHandles, FALSE, 2 * 1000 );
-	NSPLock();
-	require_action_quiet( waitResult != ( WAIT_OBJECT_0 ), exit, err = WSA_E_CANCELLED );
-	err = translate_errno( ( waitResult == WAIT_OBJECT_0 + 1 ) || ( waitResult == WAIT_OBJECT_0 + 2 ), (OSStatus) GetLastError(), WSASERVICE_NOT_FOUND );
-	require_noerr_quiet( err, exit );
-
-	// If we've received an IPv4 reply, then hang out briefly for an IPv6 reply
-
-	if ( waitResult == WAIT_OBJECT_0 + 1 )
-	{
-		data4 = TRUE;
-		data6 = WaitForSingleObject( obj->data6Event, 100 ) == WAIT_OBJECT_0 ? TRUE : FALSE;
-	}
-
-	// Else we've received an IPv6 reply, so hang out briefly for an IPv4 reply
-
-	else if ( waitResult == WAIT_OBJECT_0 + 2 )
-	{
-		data4 = WaitForSingleObject( obj->data4Event, 100 ) == WAIT_OBJECT_0 ? TRUE : FALSE;
-		data6 = TRUE;
-	}
-
-	if ( data4 )
-	{
-		__try
-		{
-			err = DNSServiceProcessResult(obj->resolver4);
-		}
-		__except( EXCEPTION_EXECUTE_HANDLER )
-		{
-			err = kUnknownErr;
-		}
-
-		require_noerr( err, exit );
-	}
-
-	if ( data6 )
-	{
-		__try
-		{
-			err = DNSServiceProcessResult( obj->resolver6 );
-		}
-		__except( EXCEPTION_EXECUTE_HANDLER )
-		{
-			err = kUnknownErr;
-		}
-
-		require_noerr( err, exit );
-	}
-
-	require_action_quiet( obj->addr4Valid || obj->addr6Valid, exit, err = WSA_E_NO_MORE );
-
-	// Copy the externalized query results to the callers buffer (if it fits).
-	
-	size = QueryCopyQuerySetSize( obj, obj->querySet, obj->querySetFlags );
-	require_action( size <= (size_t) *ioSize, exit, err = WSAEFAULT );
-	
-	QueryCopyQuerySetTo( obj, obj->querySet, obj->querySetFlags, outResults );
-	outResults->dwOutputFlags = RESULT_IS_ADDED;
-	obj->addr4Valid = false;
-	obj->addr6Valid = false;
-
-exit:
-	if( obj )
-	{
-		QueryRelease( obj );
-	}
-	NSPUnlock();
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	if( err != NO_ERROR )
-	{
-		SetLastError( (DWORD) err );
-		return( SOCKET_ERROR );
-	}
-	return( NO_ERROR );
-}
-
-//===========================================================================================================================
-//	NSPLookupServiceEnd
-//
-//	This function maps to the Winsock call WSALookupServiceEnd. Once the user process has finished is query (usually 
-//	indicated when WSALookupServiceNext returns the error WSA_E_NO_MORE) a call to this function is made to release any 
-//	allocated resources associated with the query.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI	NSPLookupServiceEnd( HANDLE inLookup )
-{
-	OSStatus		err;
-
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	
-	dlog( kDebugLevelTrace, "%s (lookup=%#p)\n", __ROUTINE__, inLookup );
-	
-	NSPLock();
-	err = QueryRelease( (QueryRef) inLookup );
-	NSPUnlock();
-	require_noerr( err, exit );
-	
-exit:
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	if( err != NO_ERROR )
-	{
-		SetLastError( (DWORD) err );
-		return( SOCKET_ERROR );
-	}
-	return( NO_ERROR );
-}
-
-//===========================================================================================================================
-//	NSPSetService
-//
-//	This function maps to the Winsock call WSASetService. This routine is called when the user wants to register or 
-//	deregister an instance of a server with our service. For registration, the user needs to associate the server with a 
-//	service class. For deregistration the service class is required along with the servicename. The inRegInfo parameter 
-//	contains a WSAQUERYSET structure defining the server (such as protocol and address where it is).
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI
-	NSPSetService(
-		LPGUID					inProviderID,						
-		LPWSASERVICECLASSINFOW	inServiceClassInfo,   
-		LPWSAQUERYSETW			inRegInfo,				  
-		WSAESETSERVICEOP		inOperation,			   
-		DWORD					inFlags )
-{
-	DEBUG_UNUSED( inProviderID );
-	DEBUG_UNUSED( inServiceClassInfo );
-	DEBUG_UNUSED( inRegInfo );
-	DEBUG_UNUSED( inOperation );
-	DEBUG_UNUSED( inFlags );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s\n", __ROUTINE__ );
-	
-	// We don't allow services to be registered so always return an error.
-	
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	return( WSAEINVAL );
-}
-
-//===========================================================================================================================
-//	NSPInstallServiceClass
-//
-//	This function maps to the Winsock call WSAInstallServiceClass. This routine is used to install a service class which 
-//	is used to define certain characteristics for a group of services. After a service class is registered, an actual
-//	instance of a server may be registered.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI	NSPInstallServiceClass( LPGUID inProviderID, LPWSASERVICECLASSINFOW inServiceClassInfo )
-{
-	DEBUG_UNUSED( inProviderID );
-	DEBUG_UNUSED( inServiceClassInfo );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s\n", __ROUTINE__ );
-	
-	// We don't allow service classes to be installed so always return an error.
-
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	return( WSA_INVALID_PARAMETER );
-}
-
-//===========================================================================================================================
-//	NSPRemoveServiceClass
-//
-//	This function maps to the Winsock call WSARemoveServiceClass. This routine removes a previously registered service 
-//	class. This is accomplished by connecting to the namespace service and writing the GUID which defines the given 
-//	service class.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI	NSPRemoveServiceClass( LPGUID inProviderID, LPGUID inServiceClassID )
-{
-	DEBUG_UNUSED( inProviderID );
-	DEBUG_UNUSED( inServiceClassID );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s\n", __ROUTINE__ );
-	
-	// We don't allow service classes to be installed so always return an error.
-	
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	return( WSATYPE_NOT_FOUND );
-}
-
-//===========================================================================================================================
-//	NSPGetServiceClassInfo
-//
-//	This function maps to the Winsock call WSAGetServiceClassInfo. This routine returns the information associated with 
-//	a given service class.
-//===========================================================================================================================
-
-DEBUG_LOCAL int WSPAPI	NSPGetServiceClassInfo(	LPGUID inProviderID, LPDWORD ioSize, LPWSASERVICECLASSINFOW ioServiceClassInfo )
-{
-	DEBUG_UNUSED( inProviderID );
-	DEBUG_UNUSED( ioSize );
-	DEBUG_UNUSED( ioServiceClassInfo );
-	
-	dlog( kDebugLevelTrace, "%s begin (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	dlog( kDebugLevelTrace, "%s\n", __ROUTINE__ );
-	
-	// We don't allow service classes to be installed so always return an error.
-	
-	dlog( kDebugLevelTrace, "%s end   (ticks=%d)\n", __ROUTINE__, GetTickCount() );
-	return( WSATYPE_NOT_FOUND );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	QueryCreate
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	QueryCreate( const WSAQUERYSETW *inQuerySet, DWORD inQuerySetFlags, QueryRef *outRef )
-{
-	OSStatus		err;
-	QueryRef		obj;
-	char			name[ kDNSServiceMaxDomainName ];
-	int				n;
-	QueryRef *		p;
-	SOCKET			s4;
-	SOCKET			s6;
-
-	obj = NULL;
-	check( inQuerySet );
-	check( inQuerySet->lpszServiceInstanceName );
-	check( outRef );
-	
-	// Convert the wchar_t name to UTF-8.
-	
-	n = WideCharToMultiByte( CP_UTF8, 0, inQuerySet->lpszServiceInstanceName, -1, name, sizeof( name ), NULL, NULL );
-	err = translate_errno( n > 0, (OSStatus) GetLastError(), WSAEINVAL );
-	require_noerr( err, exit );
-	
-	// Allocate the object and append it to the list. Append immediately so releases of partial objects work.
-	
-	obj = (QueryRef) calloc( 1, sizeof( *obj ) );
-	require_action( obj, exit, err = WSA_NOT_ENOUGH_MEMORY );
-	
-	obj->refCount = 1;
-	
-	for( p = &gQueryList; *p; p = &( *p )->next ) {}	// Find the end of the list.
-	*p = obj;
-	
-	// Set up cancel event
-
-	obj->cancelEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
-	require_action( obj->cancelEvent, exit, err = WSA_NOT_ENOUGH_MEMORY );
-
-	// Set up events to signal when A record data is ready
-	
-	obj->data4Event = CreateEvent( NULL, TRUE, FALSE, NULL );
-	require_action( obj->data4Event, exit, err = WSA_NOT_ENOUGH_MEMORY );
-	
-	// Start the query.  Handle delay loaded DLL errors.
-
-	__try
-	{
-		err = DNSServiceQueryRecord( &obj->resolver4, 0, 0, name, kDNSServiceType_A, kDNSServiceClass_IN, QueryRecordCallback4, obj );
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-		err = kUnknownErr;
-	}
-
-	require_noerr( err, exit );
-
-	// Attach the socket to the event
-
-	__try
-	{
-		s4 = DNSServiceRefSockFD(obj->resolver4);
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-		s4 = INVALID_SOCKET;
-	}
-
-	err = translate_errno( s4 != INVALID_SOCKET, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-
-	WSAEventSelect(s4, obj->data4Event, FD_READ|FD_CLOSE);
-	
-	// Set up events to signal when AAAA record data is ready
-	
-	obj->data6Event = CreateEvent( NULL, TRUE, FALSE, NULL );
-	require_action( obj->data6Event, exit, err = WSA_NOT_ENOUGH_MEMORY );
-	
-	// Start the query.  Handle delay loaded DLL errors.
-
-	__try
-	{
-		err = DNSServiceQueryRecord( &obj->resolver6, 0, 0, name, kDNSServiceType_AAAA, kDNSServiceClass_IN, QueryRecordCallback6, obj );
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-		err = kUnknownErr;
-	}
-
-	require_noerr( err, exit );
-
-	// Attach the socket to the event
-
-	__try
-	{
-		s6 = DNSServiceRefSockFD(obj->resolver6);
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-		s6 = INVALID_SOCKET;
-	}
-
-	err = translate_errno( s6 != INVALID_SOCKET, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-
-	WSAEventSelect(s6, obj->data6Event, FD_READ|FD_CLOSE);
-
-	obj->waitCount = 0;
-	obj->waitHandles[ obj->waitCount++ ] = obj->cancelEvent;
-	obj->waitHandles[ obj->waitCount++ ] = obj->data4Event;
-	obj->waitHandles[ obj->waitCount++ ] = obj->data6Event;
-	
-	check( obj->waitCount == sizeof_array( obj->waitHandles ) );
-	
-	// Copy the QuerySet so it can be returned later.
-	
-	obj->querySetFlags = inQuerySetFlags;
-	inQuerySetFlags = ( inQuerySetFlags & ~( LUP_RETURN_ADDR | LUP_RETURN_BLOB ) ) | LUP_RETURN_NAME;
-	err = QueryCopyQuerySet( obj, inQuerySet, inQuerySetFlags, &obj->querySet, &obj->querySetSize );
-	require_noerr( err, exit );
-	
-	// Success!
-	
-	*outRef	= obj;
-	obj 	= NULL;
-	err 	= NO_ERROR;
-
-exit:
-	if( obj )
-	{
-		QueryRelease( obj );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	QueryRetain
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	QueryRetain( QueryRef inRef )
-{
-	OSStatus		err;
-	QueryRef		obj;
-	
-	for( obj = gQueryList; obj; obj = obj->next )
-	{
-		if( obj == inRef )
-		{
-			break;
-		}
-	}
-	require_action( obj, exit, err = WSA_INVALID_HANDLE );
-	
-	++inRef->refCount;
-	err = NO_ERROR;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	QueryRelease
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus	QueryRelease( QueryRef inRef )
-{
-	OSStatus		err;
-	QueryRef *		p;
-	BOOL			ok;
-		
-	// Find the item in the list.
-	
-	for( p = &gQueryList; *p; p = &( *p )->next )
-	{
-		if( *p == inRef )
-		{
-			break;
-		}
-	}
-	require_action( *p, exit, err = WSA_INVALID_HANDLE );
-	
-	// Signal a cancel to unblock any threads waiting for results.
-	
-	if( inRef->cancelEvent )
-	{
-		ok = SetEvent( inRef->cancelEvent );
-		check_translated_errno( ok, GetLastError(), WSAEINVAL );
-	}
-	
-	// Stop the query.
-	
-	if( inRef->resolver4 )
-	{
-		__try
-		{
-			DNSServiceRefDeallocate( inRef->resolver4 );
-		}
-		__except( EXCEPTION_EXECUTE_HANDLER )
-		{
-		}
-		
-		inRef->resolver4 = NULL;
-	}
-
-	if ( inRef->resolver6 )
-	{
-		__try
-		{
-			DNSServiceRefDeallocate( inRef->resolver6 );
-		}
-		__except( EXCEPTION_EXECUTE_HANDLER )
-		{
-		}
-
-		inRef->resolver6 = NULL;
-	}
-	
-	// Decrement the refCount. Fully release if it drops to 0. If still referenced, just exit.
-	
-	if( --inRef->refCount != 0 )
-	{
-		err = NO_ERROR;
-		goto exit;
-	}
-	*p = inRef->next;
-	
-	// Release resources.
-	
-	if( inRef->cancelEvent )
-	{
-		ok = CloseHandle( inRef->cancelEvent );
-		check_translated_errno( ok, GetLastError(), WSAEINVAL );
-	}
-	if( inRef->data4Event )
-	{
-		ok = CloseHandle( inRef->data4Event );
-		check_translated_errno( ok, GetLastError(), WSAEINVAL );
-	}
-	if( inRef->data6Event )
-	{
-		ok = CloseHandle( inRef->data6Event );
-		check_translated_errno( ok, GetLastError(), WSAEINVAL );
-	}
-	if( inRef->querySet )
-	{
-		free( inRef->querySet );
-	}
-	free( inRef );
-	err = NO_ERROR;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	QueryRecordCallback4
-//===========================================================================================================================
-
-DEBUG_LOCAL void CALLBACK_COMPAT
-	QueryRecordCallback4(
-		DNSServiceRef		inRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inErrorCode,
-		const char *		inName,    
-		uint16_t			inRRType,
-		uint16_t			inRRClass,
-		uint16_t			inRDataSize,
-		const void *		inRData,
-		uint32_t			inTTL,
-		void *				inContext )
-{
-	QueryRef			obj;
-	const char *		src;
-	char *				dst;
-	BOOL				ok;
-	
-	DEBUG_UNUSED( inFlags );
-	DEBUG_UNUSED( inInterfaceIndex );
-	DEBUG_UNUSED( inTTL );
-
-	NSPLock();
-	obj = (QueryRef) inContext;
-	check( obj );
-	require_noerr( inErrorCode, exit );
-	require_quiet( inFlags & kDNSServiceFlagsAdd, exit );
-	require( inRRClass   == kDNSServiceClass_IN, exit );
-	require( inRRType    == kDNSServiceType_A, exit );
-	require( inRDataSize == 4, exit );
-	
-	dlog( kDebugLevelTrace, "%s (flags=0x%08X, name=%s, rrType=%d, rDataSize=%d)\n", 
-		__ROUTINE__, inFlags, inName, inRRType, inRDataSize );
-		
-	// Copy the name if needed.
-	
-	if( obj->name[ 0 ] == '\0' )
-	{
-		src = inName;
-		dst = obj->name;
-		while( *src != '\0' )
-		{
-			*dst++ = *src++;
-		}
-		*dst = '\0';
-		obj->nameSize = (size_t)( dst - obj->name );
-		check( obj->nameSize < sizeof( obj->name ) );
-	}
-	
-	// Copy the data.
-	
-	memcpy( &obj->addr4, inRData, inRDataSize );
-	obj->addr4Valid = true;
-	obj->numValidAddrs++;
-	
-	// Signal that a result is ready.
-	
-	check( obj->data4Event );
-	ok = SetEvent( obj->data4Event );
-	check_translated_errno( ok, GetLastError(), WSAEINVAL );
-	
-	// Stop the resolver after the first response.
-	
-	__try
-	{
-		DNSServiceRefDeallocate( inRef );
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-	}
-
-	obj->resolver4 = NULL;
-
-exit:
-	NSPUnlock();
-}
-
-#if 0
-#pragma mark -
-#endif
-
-
-//===========================================================================================================================
-//	QueryRecordCallback6
-//===========================================================================================================================
-
-DEBUG_LOCAL void CALLBACK_COMPAT
-	QueryRecordCallback6(
-		DNSServiceRef		inRef,
-		DNSServiceFlags		inFlags,
-		uint32_t			inInterfaceIndex,
-		DNSServiceErrorType	inErrorCode,
-		const char *		inName,    
-		uint16_t			inRRType,
-		uint16_t			inRRClass,
-		uint16_t			inRDataSize,
-		const void *		inRData,
-		uint32_t			inTTL,
-		void *				inContext )
-{
-	QueryRef			obj;
-	const char *		src;
-	char *				dst;
-	BOOL				ok;
-	
-	DEBUG_UNUSED( inFlags );
-	DEBUG_UNUSED( inInterfaceIndex );
-	DEBUG_UNUSED( inTTL );
-
-	NSPLock();
-	obj = (QueryRef) inContext;
-	check( obj );
-	require_noerr( inErrorCode, exit );
-	require_quiet( inFlags & kDNSServiceFlagsAdd, exit );
-	require( inRRClass   == kDNSServiceClass_IN, exit );
-	require( inRRType    == kDNSServiceType_AAAA, exit );
-	require( inRDataSize == 16, exit );
-	
-	dlog( kDebugLevelTrace, "%s (flags=0x%08X, name=%s, rrType=%d, rDataSize=%d)\n", 
-		__ROUTINE__, inFlags, inName, inRRType, inRDataSize );
-
-	// Copy the name if needed.
-	
-	if( obj->name[ 0 ] == '\0' )
-	{
-		src = inName;
-		dst = obj->name;
-		while( *src != '\0' )
-		{
-			*dst++ = *src++;
-		}
-		*dst = '\0';
-		obj->nameSize = (size_t)( dst - obj->name );
-		check( obj->nameSize < sizeof( obj->name ) );
-	}
-	
-	// Copy the data.
-	
-	memcpy( &obj->addr6, inRData, inRDataSize );
-
-	obj->addr6ScopeId = GetScopeId( inInterfaceIndex );
-	require( obj->addr6ScopeId, exit );
-	obj->addr6Valid	  = true;
-	obj->numValidAddrs++;
-
-	// Signal that we're done
-	
-	check( obj->data6Event );
-	ok = SetEvent( obj->data6Event );
-	check_translated_errno( ok, GetLastError(), WSAEINVAL );
-
-	// Stop the resolver after the first response.
-	
-	__try
-	{
-		DNSServiceRefDeallocate( inRef );
-	}
-	__except( EXCEPTION_EXECUTE_HANDLER )
-	{
-	}
-
-	obj->resolver6 = NULL;
-
-exit:
-
-	
-	
-	NSPUnlock();
-}
-
-
-//===========================================================================================================================
-//	QueryCopyQuerySet
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus
-	QueryCopyQuerySet( 
-		QueryRef 				inRef, 
-		const WSAQUERYSETW *	inQuerySet, 
-		DWORD 					inQuerySetFlags, 
-		WSAQUERYSETW **			outQuerySet, 
-		size_t *				outSize )
-{
-	OSStatus			err;
-	size_t				size;
-	WSAQUERYSETW *		qs;
-	
-	check( inQuerySet );
-	check( outQuerySet );
-	
-	size  = QueryCopyQuerySetSize( inRef, inQuerySet, inQuerySetFlags );
-	qs = (WSAQUERYSETW *) calloc( 1, size );
-	require_action( qs, exit, err = WSA_NOT_ENOUGH_MEMORY  );
-	
-	QueryCopyQuerySetTo( inRef, inQuerySet, inQuerySetFlags, qs );
-	
-	*outQuerySet = qs;
-	if( outSize )
-	{
-		*outSize = size;
-	}
-	qs = NULL;
-	err = NO_ERROR;
-	
-exit:
-	if( qs )
-	{
-		free( qs );
-	}
-	return( err );	
-}
-
-
-
-//===========================================================================================================================
-//	QueryCopyQuerySetTo
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL void
-	QueryCopyQuerySetTo( 
-		QueryRef 				inRef, 
-		const WSAQUERYSETW *	inQuerySet, 
-		DWORD 					inQuerySetFlags, 
-		WSAQUERYSETW *			outQuerySet )
-{
-	uint8_t *		dst;
-	LPCWSTR			s;
-	LPWSTR			q;
-	DWORD			n;
-	DWORD			i;
-	
-#if( DEBUG )
-	size_t			debugSize;
-	
-	debugSize = QueryCopyQuerySetSize( inRef, inQuerySet, inQuerySetFlags );
-#endif
-
-	check( inQuerySet );
-	check( outQuerySet );
-
-	dst = (uint8_t *) outQuerySet;
-	
-	// Copy the static portion of the results.
-	
-	*outQuerySet = *inQuerySet;
-	dst += sizeof( *inQuerySet );
-	
-	if( inQuerySetFlags & LUP_RETURN_NAME )
-	{
-		s = inQuerySet->lpszServiceInstanceName;
-		if( s )
-		{
-			outQuerySet->lpszServiceInstanceName = (LPWSTR) dst;
-			q = (LPWSTR) dst;
-			while( ( *q++ = *s++ ) != 0 ) {}
-			dst = (uint8_t *) q;
-		}
-	}
-	else
-	{
-		outQuerySet->lpszServiceInstanceName = NULL;
-	}
-	
-	if( inQuerySet->lpServiceClassId )
-	{
-		outQuerySet->lpServiceClassId  = (LPGUID) dst;
-		*outQuerySet->lpServiceClassId = *inQuerySet->lpServiceClassId;
-		dst += sizeof( *inQuerySet->lpServiceClassId );
-	}
-	
-	if( inQuerySet->lpVersion )
-	{
-		outQuerySet->lpVersion  = (LPWSAVERSION) dst;
-		*outQuerySet->lpVersion = *inQuerySet->lpVersion;
-		dst += sizeof( *inQuerySet->lpVersion );
-	}
-	
-	s = inQuerySet->lpszComment;
-	if( s )
-	{
-		outQuerySet->lpszComment = (LPWSTR) dst;
-		q = (LPWSTR) dst;
-		while( ( *q++ = *s++ ) != 0 ) {}
-		dst = (uint8_t *) q;
-	}
-	
-	if( inQuerySet->lpNSProviderId )
-	{
-		outQuerySet->lpNSProviderId  = (LPGUID) dst;
-		*outQuerySet->lpNSProviderId = *inQuerySet->lpNSProviderId;
-		dst += sizeof( *inQuerySet->lpNSProviderId );
-	}
-	
-	s = inQuerySet->lpszContext;
-	if( s )
-	{
-		outQuerySet->lpszContext = (LPWSTR) dst;
-		q = (LPWSTR) dst;
-		while( ( *q++ = *s++ ) != 0 ) {}
-		dst = (uint8_t *) q;
-	}
-		
-	n = inQuerySet->dwNumberOfProtocols;
-
-	if( n > 0 )
-	{
-		check( inQuerySet->lpafpProtocols );
-		
-		outQuerySet->lpafpProtocols = (LPAFPROTOCOLS) dst;
-		for( i = 0; i < n; ++i )
-		{
-			outQuerySet->lpafpProtocols[ i ] = inQuerySet->lpafpProtocols[ i ];
-			dst += sizeof( *inQuerySet->lpafpProtocols );
-		}
-	}
-		
-	s = inQuerySet->lpszQueryString;
-	if( s )
-	{
-		outQuerySet->lpszQueryString = (LPWSTR) dst;
-		q = (LPWSTR) dst;
-		while( ( *q++ = *s++ ) != 0 ) {}
-		dst = (uint8_t *) q;
-	}
-	
-	// Copy the address(es).
-	
-	if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && ( inRef->numValidAddrs > 0 ) )
-	{
-		struct sockaddr_in	*	addr4;
-		struct sockaddr_in6	*	addr6;
-		int						index;
-		
-		outQuerySet->dwNumberOfCsAddrs	= inRef->numValidAddrs;
-		outQuerySet->lpcsaBuffer 		= (LPCSADDR_INFO) dst;
-		dst 							+= ( sizeof( *outQuerySet->lpcsaBuffer ) ) * ( inRef->numValidAddrs ) ;
-		index							= 0;
-		
-		if ( inRef->addr4Valid )
-		{	
-			outQuerySet->lpcsaBuffer[ index ].LocalAddr.lpSockaddr 			= NULL;
-			outQuerySet->lpcsaBuffer[ index ].LocalAddr.iSockaddrLength		= 0;
-		
-			outQuerySet->lpcsaBuffer[ index ].RemoteAddr.lpSockaddr 		= (LPSOCKADDR) dst;
-			outQuerySet->lpcsaBuffer[ index ].RemoteAddr.iSockaddrLength	= sizeof( struct sockaddr_in );
-		
-			addr4 															= (struct sockaddr_in *) dst;
-			memset( addr4, 0, sizeof( *addr4 ) );
-			addr4->sin_family												= AF_INET;
-			memcpy( &addr4->sin_addr, &inRef->addr4, 4 );
-			dst 															+= sizeof( *addr4 );
-		
-			outQuerySet->lpcsaBuffer[ index ].iSocketType 					= AF_INET;		// Emulate Tcpip NSP
-			outQuerySet->lpcsaBuffer[ index ].iProtocol						= IPPROTO_UDP;	// Emulate Tcpip NSP
-
-			index++;
-		}
-
-		if ( inRef->addr6Valid )
-		{
-			outQuerySet->lpcsaBuffer[ index ].LocalAddr.lpSockaddr 			= NULL;
-			outQuerySet->lpcsaBuffer[ index ].LocalAddr.iSockaddrLength		= 0;
-		
-			outQuerySet->lpcsaBuffer[ index ].RemoteAddr.lpSockaddr 		= (LPSOCKADDR) dst;
-			outQuerySet->lpcsaBuffer[ index ].RemoteAddr.iSockaddrLength	= sizeof( struct sockaddr_in6 );
-		
-			addr6 															= (struct sockaddr_in6 *) dst;
-			memset( addr6, 0, sizeof( *addr6 ) );
-			addr6->sin6_family												= AF_INET6;
-			addr6->sin6_scope_id											= inRef->addr6ScopeId;
-			memcpy( &addr6->sin6_addr, &inRef->addr6, 16 );
-			dst 															+= sizeof( *addr6 );
-		
-			outQuerySet->lpcsaBuffer[ index ].iSocketType 					= AF_INET6;		// Emulate Tcpip NSP
-			outQuerySet->lpcsaBuffer[ index ].iProtocol						= IPPROTO_UDP;	// Emulate Tcpip NSP
-		}
-	}
-	else
-	{
-		outQuerySet->dwNumberOfCsAddrs	= 0;
-		outQuerySet->lpcsaBuffer 		= NULL;
-	}
-	
-	// Copy the hostent blob.
-	
-	if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addr4Valid )
-	{
-		uint8_t *				base;
-		struct hostent *		he;
-		uintptr_t *				p;
-
-		outQuerySet->lpBlob	 = (LPBLOB) dst;
-		dst 				+= sizeof( *outQuerySet->lpBlob );
-		
-		base = dst;
-		he	 = (struct hostent *) dst;
-		dst += sizeof( *he );
-		
-		he->h_name = (char *)( dst - base );
-		memcpy( dst, inRef->name, inRef->nameSize + 1 );
-		dst += ( inRef->nameSize + 1 );
-		
-		he->h_aliases 	= (char **)( dst - base );
-		p	  			= (uintptr_t *) dst;
-		*p++  			= 0;
-		dst 		 	= (uint8_t *) p;
-		
-		he->h_addrtype 	= AF_INET;
-		he->h_length	= 4;
-		
-		he->h_addr_list	= (char **)( dst - base );
-		p	  			= (uintptr_t *) dst;
-		dst 		   += ( 2 * sizeof( *p ) );
-		*p++			= (uintptr_t)( dst - base );
-		*p++			= 0;
-		p	  			= (uintptr_t *) dst;
-		*p++			= (uintptr_t) inRef->addr4;
-		dst 		 	= (uint8_t *) p;
-		
-		outQuerySet->lpBlob->cbSize 	= (ULONG)( dst - base );
-		outQuerySet->lpBlob->pBlobData	= (BYTE *) base;
-	}
-	dlog_query_set( kDebugLevelVerbose, outQuerySet );
-
-	check( (size_t)( dst - ( (uint8_t *) outQuerySet ) ) == debugSize );
-}
-
-//===========================================================================================================================
-//	QueryCopyQuerySetSize
-//
-//	Warning: Assumes the NSP lock is held.
-//===========================================================================================================================
-
-DEBUG_LOCAL size_t	QueryCopyQuerySetSize( QueryRef inRef, const WSAQUERYSETW *inQuerySet, DWORD inQuerySetFlags )
-{
-	size_t		size;
-	LPCWSTR		s;
-	LPCWSTR		p;
-	
-	check( inRef );
-	check( inQuerySet );
-	
-	// Calculate the size of the static portion of the results.
-	
-	size = sizeof( *inQuerySet );
-	
-	if( inQuerySetFlags & LUP_RETURN_NAME )
-	{
-		s = inQuerySet->lpszServiceInstanceName;
-		if( s )
-		{
-			for( p = s; *p; ++p ) {}
-			size += (size_t)( ( ( p - s ) + 1 ) * sizeof( *p ) );
-		}
-	}
-	
-	if( inQuerySet->lpServiceClassId )
-	{
-		size += sizeof( *inQuerySet->lpServiceClassId );
-	}
-	
-	if( inQuerySet->lpVersion )
-	{
-		size += sizeof( *inQuerySet->lpVersion );
-	}
-	
-	s = inQuerySet->lpszComment;
-	if( s )
-	{
-		for( p = s; *p; ++p ) {}
-		size += (size_t)( ( ( p - s ) + 1 ) * sizeof( *p ) );
-	}
-	
-	if( inQuerySet->lpNSProviderId )
-	{
-		size += sizeof( *inQuerySet->lpNSProviderId );
-	}
-	
-	s = inQuerySet->lpszContext;
-	if( s )
-	{
-		for( p = s; *p; ++p ) {}
-		size += (size_t)( ( ( p - s ) + 1 ) * sizeof( *p ) );
-	}
-	
-	size += ( inQuerySet->dwNumberOfProtocols * sizeof( *inQuerySet->lpafpProtocols ) );
-	
-	s = inQuerySet->lpszQueryString;
-	if( s )
-	{
-		for( p = s; *p; ++p ) {}
-		size += (size_t)( ( ( p - s ) + 1 ) * sizeof( *p ) );
-	}
-	
-	// Calculate the size of the address(es).
-	
-	if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addr4Valid )
-	{
-		size += sizeof( *inQuerySet->lpcsaBuffer );
-		size += sizeof( struct sockaddr_in );
-	}
-
-	if( ( inQuerySetFlags & LUP_RETURN_ADDR ) && inRef->addr6Valid )
-	{
-		size += sizeof( *inQuerySet->lpcsaBuffer );
-		size += sizeof( struct sockaddr_in6 );
-	}
-	
-	// Calculate the size of the hostent blob.
-	
-	if( ( inQuerySetFlags & LUP_RETURN_BLOB ) && inRef->addr4Valid )
-	{
-		size += sizeof( *inQuerySet->lpBlob );	// Blob ptr/size structure
-		size += sizeof( struct hostent );		// Old-style hostent structure
-		size += ( inRef->nameSize + 1 );		// Name and null terminator
-		size += 4;								// Alias list terminator (0 offset)
-		size += 4;								// Offset to address.
-		size += 4;								// Address list terminator (0 offset)
-		size += 4;								// IPv4 address
-	}
-	return( size );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-#if( DEBUG )
-//===========================================================================================================================
-//	DebugDumpQuerySet
-//===========================================================================================================================
-
-#define	DebugSocketFamilyToString( FAM )	( ( FAM ) == AF_INET )  ? "AF_INET"  : \
-											( ( FAM ) == AF_INET6 ) ? "AF_INET6" : ""
-
-#define	DebugSocketProtocolToString( PROTO )	( ( PROTO ) == IPPROTO_UDP ) ? "IPPROTO_UDP" : \
-												( ( PROTO ) == IPPROTO_TCP ) ? "IPPROTO_TCP" : ""
-
-#define	DebugNameSpaceToString( NS )			( ( NS ) == NS_DNS ) ? "NS_DNS" : ( ( NS ) == NS_ALL ) ? "NS_ALL" : ""
-
-void	DebugDumpQuerySet( DebugLevel inLevel, const WSAQUERYSETW *inQuerySet )
-{
-	DWORD		i;
-	
-	check( inQuerySet );
-
-	// Fixed portion of the QuerySet.
-		
-	dlog( inLevel, "QuerySet:\n" );
-	dlog( inLevel, "    dwSize:                  %d (expected %d)\n", inQuerySet->dwSize, sizeof( *inQuerySet ) );
-	if( inQuerySet->lpszServiceInstanceName )
-	{
-		dlog( inLevel, "    lpszServiceInstanceName: %S\n", inQuerySet->lpszServiceInstanceName );
-	}
-	else
-	{
-		dlog( inLevel, "    lpszServiceInstanceName: <null>\n" );
-	}
-	if( inQuerySet->lpServiceClassId )
-	{
-		dlog( inLevel, "    lpServiceClassId:        %U\n", inQuerySet->lpServiceClassId );
-	}
-	else
-	{
-		dlog( inLevel, "    lpServiceClassId:        <null>\n" );
-	}
-	if( inQuerySet->lpVersion )
-	{
-		dlog( inLevel, "    lpVersion:\n" );
-		dlog( inLevel, "        dwVersion:               %d\n", inQuerySet->lpVersion->dwVersion );
-		dlog( inLevel, "        dwVersion:               %d\n", inQuerySet->lpVersion->ecHow );
-	}
-	else
-	{
-		dlog( inLevel, "    lpVersion:               <null>\n" );
-	}
-	if( inQuerySet->lpszComment )
-	{
-		dlog( inLevel, "    lpszComment:             %S\n", inQuerySet->lpszComment );
-	}
-	else
-	{
-		dlog( inLevel, "    lpszComment:             <null>\n" );
-	}
-	dlog( inLevel, "    dwNameSpace:             %d %s\n", inQuerySet->dwNameSpace, 
-		DebugNameSpaceToString( inQuerySet->dwNameSpace ) );
-	if( inQuerySet->lpNSProviderId )
-	{
-		dlog( inLevel, "    lpNSProviderId:          %U\n", inQuerySet->lpNSProviderId );
-	}
-	else
-	{
-		dlog( inLevel, "    lpNSProviderId:          <null>\n" );
-	}
-	if( inQuerySet->lpszContext )
-	{
-		dlog( inLevel, "    lpszContext:             %S\n", inQuerySet->lpszContext );
-	}
-	else
-	{
-		dlog( inLevel, "    lpszContext:             <null>\n" );
-	}
-	dlog( inLevel, "    dwNumberOfProtocols:     %d\n", inQuerySet->dwNumberOfProtocols );
-	dlog( inLevel, "    lpafpProtocols:          %s\n", inQuerySet->lpafpProtocols ? "" : "<null>" );
-	for( i = 0; i < inQuerySet->dwNumberOfProtocols; ++i )
-	{
-		if( i != 0 )
-		{
-			dlog( inLevel, "\n" );
-		}
-		dlog( inLevel, "        iAddressFamily:          %d %s\n", inQuerySet->lpafpProtocols[ i ].iAddressFamily, 
-			DebugSocketFamilyToString( inQuerySet->lpafpProtocols[ i ].iAddressFamily ) );
-		dlog( inLevel, "        iProtocol:               %d %s\n", inQuerySet->lpafpProtocols[ i ].iProtocol, 
-			DebugSocketProtocolToString( inQuerySet->lpafpProtocols[ i ].iProtocol ) );
-	}
-	if( inQuerySet->lpszQueryString )
-	{
-		dlog( inLevel, "    lpszQueryString:         %S\n", inQuerySet->lpszQueryString );
-	}
-	else
-	{
-		dlog( inLevel, "    lpszQueryString:         <null>\n" );
-	}
-	dlog( inLevel, "    dwNumberOfCsAddrs:       %d\n", inQuerySet->dwNumberOfCsAddrs );
-	dlog( inLevel, "    lpcsaBuffer:             %s\n", inQuerySet->lpcsaBuffer ? "" : "<null>" );
-	for( i = 0; i < inQuerySet->dwNumberOfCsAddrs; ++i )
-	{
-		if( i != 0 )
-		{
-			dlog( inLevel, "\n" );
-		}
-		if( inQuerySet->lpcsaBuffer[ i ].LocalAddr.lpSockaddr && 
-			( inQuerySet->lpcsaBuffer[ i ].LocalAddr.iSockaddrLength > 0 ) )
-		{
-			dlog( inLevel, "        LocalAddr:               %##a\n", 
-				inQuerySet->lpcsaBuffer[ i ].LocalAddr.lpSockaddr );
-		}
-		else
-		{
-			dlog( inLevel, "        LocalAddr:               <null/empty>\n" );
-		}
-		if( inQuerySet->lpcsaBuffer[ i ].RemoteAddr.lpSockaddr && 
-			( inQuerySet->lpcsaBuffer[ i ].RemoteAddr.iSockaddrLength > 0 ) )
-		{
-			dlog( inLevel, "        RemoteAddr:              %##a\n", 
-				inQuerySet->lpcsaBuffer[ i ].RemoteAddr.lpSockaddr );
-		}
-		else
-		{
-			dlog( inLevel, "        RemoteAddr:              <null/empty>\n" );
-		}
-		dlog( inLevel, "        iSocketType:             %d\n", inQuerySet->lpcsaBuffer[ i ].iSocketType );
-		dlog( inLevel, "        iProtocol:               %d\n", inQuerySet->lpcsaBuffer[ i ].iProtocol );
-	}
-	dlog( inLevel, "    dwOutputFlags:           %d\n", inQuerySet->dwOutputFlags );
-	
-	// Blob portion of the QuerySet.
-	
-	if( inQuerySet->lpBlob )
-	{
-		dlog( inLevel, "    lpBlob:\n" );
-		dlog( inLevel, "        cbSize:                  %ld\n", inQuerySet->lpBlob->cbSize );
-		dlog( inLevel, "        pBlobData:               %#p\n", inQuerySet->lpBlob->pBlobData );
-		dloghex( inLevel, 12, NULL, 0, 0, NULL, 0, 
-			inQuerySet->lpBlob->pBlobData, inQuerySet->lpBlob->pBlobData, inQuerySet->lpBlob->cbSize, 
-			kDebugFlagsNone, NULL, 0 );
-	}
-	else
-	{
-		dlog( inLevel, "    lpBlob:                  <null>\n" );
-	}
-}
-#endif
-
-
-//===========================================================================================================================
-//	InHostsTable
-//===========================================================================================================================
-
-DEBUG_LOCAL BOOL
-InHostsTable( const char * name )
-{
-	HostsFileInfo	*	node;
-	BOOL				ret = FALSE;
-	OSStatus			err;
-	
-	check( name );
-
-	if ( gHostsFileInfo == NULL )
-	{
-		TCHAR				systemDirectory[MAX_PATH];
-		TCHAR				hFileName[MAX_PATH];
-		HostsFile		*	hFile;
-
-		GetSystemDirectory( systemDirectory, sizeof( systemDirectory ) );
-		snprintf( hFileName, sizeof( hFileName ), "%s\\drivers\\etc\\hosts", systemDirectory );
-		err = HostsFileOpen( &hFile, hFileName );
-		require_noerr( err, exit );
-
-		while ( HostsFileNext( hFile, &node ) == 0 )
-		{
-			if ( IsLocalName( node ) )
-			{
-				node->m_next = gHostsFileInfo;
-				gHostsFileInfo = node;
-			}
-			else
-			{
-				HostsFileInfoFree( node );
-			}
-		}
-
-		HostsFileClose( hFile );
-	}
-
-	for ( node = gHostsFileInfo; node; node = node->m_next )
-	{
-		if ( IsSameName( node, name ) )
-		{
-			ret = TRUE;
-			break;
-		}
-	}
-
-exit:
-
-	return ret;
-}
-
-
-//===========================================================================================================================
-//	IsLocalName
-//===========================================================================================================================
-
-DEBUG_LOCAL BOOL
-IsLocalName( HostsFileInfo * node )
-{
-	BOOL ret = TRUE;
-
-	check( node );
-
-	if ( strstr( node->m_host.h_name, ".local" ) == NULL )
-	{
-		int i;
-
-		for ( i = 0; node->m_host.h_aliases[i]; i++ )
-		{
-			if ( strstr( node->m_host.h_aliases[i], ".local" ) )
-			{
-				goto exit;
-			}
-		}
-
-		ret = FALSE;
-	}
-
-exit:
-
-	return ret;
-}
-
-
-//===========================================================================================================================
-//	IsSameName
-//===========================================================================================================================
-
-DEBUG_LOCAL BOOL
-IsSameName( HostsFileInfo * node, const char * name )
-{
-	BOOL ret = TRUE;
-
-	check( node );
-	check( name );
-
-	if ( strcmp( node->m_host.h_name, name ) != 0 )
-	{
-		int i;
-
-		for ( i = 0; node->m_host.h_aliases[i]; i++ )
-		{
-			if ( strcmp( node->m_host.h_aliases[i], name ) == 0 )
-			{
-				goto exit;
-			}
-		}
-
-		ret = FALSE;
-	}
-
-exit:
-
-	return ret;
-}
-
-
-//===========================================================================================================================
-//	HostsFileOpen
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus
-HostsFileOpen( HostsFile ** self, const char * fname )
-{
-	OSStatus err = kNoErr;
-
-	*self = (HostsFile*) malloc( sizeof( HostsFile ) );
-	require_action( *self, exit, err = kNoMemoryErr );
-	memset( *self, 0, sizeof( HostsFile ) );
-
-	(*self)->m_bufferSize = BUFFER_INITIAL_SIZE;
-	(*self)->m_buffer = (char*) malloc( (*self)->m_bufferSize );
-	require_action( (*self)->m_buffer, exit, err = kNoMemoryErr );
-
-	// check malloc
-
-	(*self)->m_fp = fopen( fname, "r" );
-	require_action( (*self)->m_fp, exit, err = kUnknownErr );
-
-exit:
-
-	if ( err && *self )
-	{
-		HostsFileClose( *self );
-		*self = NULL;
-	}
-		
-	return err;
-}
-
-
-//===========================================================================================================================
-//	HostsFileClose
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus
-HostsFileClose( HostsFile * self )
-{
-	check( self );
-
-	if ( self->m_buffer )
-	{
-		free( self->m_buffer );
-		self->m_buffer = NULL;
-	}
-
-	if ( self->m_fp )
-	{
-		fclose( self->m_fp );
-		self->m_fp = NULL;
-	}
-
-	free( self );
-
-	return kNoErr;
-} 
-
-
-//===========================================================================================================================
-//	HostsFileInfoFree
-//===========================================================================================================================
-
-DEBUG_LOCAL void
-HostsFileInfoFree( HostsFileInfo * info )
-{
-	while ( info )
-	{
-		HostsFileInfo * next = info->m_next;
-
-		if ( info->m_host.h_addr_list )
-		{
-			if ( info->m_host.h_addr_list[0] )
-			{
-				free( info->m_host.h_addr_list[0] );
-				info->m_host.h_addr_list[0] = NULL;
-			}
-
-			free( info->m_host.h_addr_list );
-			info->m_host.h_addr_list = NULL;
-		}
-
-		if ( info->m_host.h_aliases )
-		{
-			int i;
-
-			for ( i = 0; info->m_host.h_aliases[i]; i++ )
-			{
-				free( info->m_host.h_aliases[i] );
-			}
-
-			free( info->m_host.h_aliases );
-		}
-
-		if ( info->m_host.h_name )
-		{
-			free( info->m_host.h_name );
-			info->m_host.h_name = NULL;
-		}
-			
-		free( info );
-
-		info = next;
-	}
-}
-
-
-//===========================================================================================================================
-//	HostsFileNext
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus
-HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo )
-{
-	struct sockaddr_in6	addr_6;
-	struct sockaddr_in	addr_4;
-	int					numAliases = ALIASES_INITIAL_SIZE;
-	char			*	line;
-	char			*	tok;
-	int					dwSize;
-	int					idx;
-	int					i;
-	short				family;
-	size_t				len;
-	OSStatus			err = kNoErr;
-
-	check( self );
-	check( self->m_fp );
-	check( hInfo );
-
-	idx	= 0;
-
-	*hInfo = (HostsFileInfo*) malloc( sizeof( HostsFileInfo ) );
-	require_action( *hInfo, exit, err = kNoMemoryErr );
-	memset( *hInfo, 0, sizeof( HostsFileInfo ) );
-
-	for ( ; ; )
-	{
-		line = fgets( self->m_buffer + idx, self->m_bufferSize - idx, self->m_fp );
-		
-		if ( line == NULL )
-		{
-			err = 1;
-			goto exit;
-		}
-
-		// If there's no eol and no eof, then we didn't get the whole line
-
-		if ( !strchr( line, '\n' ) && !feof( self->m_fp ) )
-		{
-			int			bufferSize;
-			char	*	buffer;
-
-			/* Try and allocate space for longer line */
-
-			bufferSize	= self->m_bufferSize * 2;
-			buffer		= (char*) realloc( self->m_buffer, bufferSize );
-			require_action( buffer, exit, err = kNoMemoryErr );
-			self->m_bufferSize	= bufferSize;
-			self->m_buffer		= buffer;
-			idx					= (int) strlen( self->m_buffer );
-
-			continue;
-		}
-
-		line	= self->m_buffer;
-		idx		= 0;
-
-		if (*line == '#')
-		{
-			continue;
-		}
-
-		// Get rid of either comments or eol characters
-
-		if (( tok = strpbrk(line, "#\n")) != NULL )
-		{
-			*tok = '\0';
-		}
-
-		// Make sure there is some whitespace on this line
-
-		if (( tok = strpbrk(line, " \t")) == NULL )
-		{
-			continue;
-		}
-
-		// Create two strings, where p == the IP Address and tok is the name list
-
-		*tok++ = '\0';
-
-		while ( *tok == ' ' || *tok == '\t')
-		{
-			tok++;
-		}
-
-		// Now we have the name
-
-		len = strlen( tok ) + 1;
-		(*hInfo)->m_host.h_name = (char*) malloc( len );
-		require_action( (*hInfo)->m_host.h_name, exit, err = kNoMemoryErr );
-		strcpy_s( (*hInfo)->m_host.h_name, len, tok );
-
-		// Now create the address (IPv6/IPv4)
-
-		addr_6.sin6_family	= family = AF_INET6;
-		dwSize				= sizeof( addr_6 );
-
-		if ( WSAStringToAddress( line, AF_INET6, NULL, ( struct sockaddr*) &addr_6, &dwSize ) != 0 )
-		{
-			addr_4.sin_family = family = AF_INET;
-			dwSize = sizeof( addr_4 );
-
-			if (WSAStringToAddress( line, AF_INET, NULL, ( struct sockaddr*) &addr_4, &dwSize ) != 0 )
-			{
-				continue;
-			}
-		}
-
-		(*hInfo)->m_host.h_addr_list = (char**) malloc( sizeof( char**) * 2 );
-		require_action( (*hInfo)->m_host.h_addr_list, exit, err = kNoMemoryErr );
-
-		if ( family == AF_INET6 )
-		{
-			(*hInfo)->m_host.h_length		= (short) sizeof( addr_6.sin6_addr );
-			(*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length );
-			require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr );
-			memmove( (*hInfo)->m_host.h_addr_list[0], &addr_6.sin6_addr, sizeof( addr_6.sin6_addr ) );
-			
-		}
-		else
-		{
-			(*hInfo)->m_host.h_length		= (short) sizeof( addr_4.sin_addr );
-			(*hInfo)->m_host.h_addr_list[0] = (char*) malloc( (*hInfo)->m_host.h_length );
-			require_action( (*hInfo)->m_host.h_addr_list[0], exit, err = kNoMemoryErr );
-			memmove( (*hInfo)->m_host.h_addr_list[0], &addr_4.sin_addr, sizeof( addr_4.sin_addr ) );
-		}
-
-		(*hInfo)->m_host.h_addr_list[1] = NULL;
-		(*hInfo)->m_host.h_addrtype		= family;
-
-		// Now get the aliases
-
-		if ((tok = strpbrk(tok, " \t")) != NULL)
-		{
-			*tok++ = '\0';
-		}
-
-		i = 0;
-
-		(*hInfo)->m_host.h_aliases		= (char**) malloc( sizeof(char**) * numAliases );
-		require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr );
-		(*hInfo)->m_host.h_aliases[0]	= NULL;
-
-		while ( tok && *tok )
-		{
-			// Skip over the whitespace, waiting for the start of the next alias name
-
-			if (*tok == ' ' || *tok == '\t')
-			{
-				tok++;
-				continue;
-			}
-
-			// Check to make sure we don't exhaust the alias buffer
-
-			if ( i >= ( numAliases - 1 ) )
-			{
-				numAliases = numAliases * 2;
-				(*hInfo)->m_host.h_aliases = (char**) realloc( (*hInfo)->m_host.h_aliases, numAliases * sizeof( char** ) );
-				require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr );
-			}
-
-			len = strlen( tok ) + 1;
-			(*hInfo)->m_host.h_aliases[i] = (char*) malloc( len );
-			require_action( (*hInfo)->m_host.h_aliases[i], exit, err = kNoMemoryErr );
-
-			strcpy_s( (*hInfo)->m_host.h_aliases[i], len, tok );
-
-			if (( tok = strpbrk( tok, " \t")) != NULL )
-			{
-				*tok++ = '\0';
-			}
-
-			(*hInfo)->m_host.h_aliases[++i] = NULL;
-		}
-
-		break;
-	}
-
-exit:
-
-	if ( err && ( *hInfo ) )
-	{
-		HostsFileInfoFree( *hInfo );
-		*hInfo = NULL;
-	}
-
-	return err;
-}
-
-
-#ifdef ENABLE_REVERSE_LOOKUP
-//===========================================================================================================================
-//	IsReverseLookup
-//===========================================================================================================================
-
-DEBUG_LOCAL OSStatus
-IsReverseLookup( LPCWSTR name, size_t size )
-{
-	LPCWSTR		p;
-	OSStatus	err = kNoErr;
-
-	// IPv6LL Reverse-mapping domains are {8,9,A,B}.E.F.ip6.arpa
-	require_action_quiet( size > sizeof_string( ".0.8.e.f.ip6.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
- 
-	p = name + ( size - 1 );
-	p = ( *p == '.' ) ? ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) : ( ( p - sizeof_string( ".0.8.e.f.ip6.arpa" ) ) + 1 );
-	
-	if	( ( ( p[ 0 ] != '.' )							||
-		( ( p[ 1 ] != '0' ) )							||
-		( ( p[ 2 ] != '.' ) )							||
-		( ( p[ 3 ] != '8' ) )							||
-		( ( p[ 4 ] != '.' ) )							||
-		( ( p[ 5 ] != 'E' ) && ( p[ 5 ] != 'e' ) )		||
-		( ( p[ 6 ] != '.' ) )							||
-		( ( p[ 7 ] != 'F' ) && ( p[ 7 ] != 'f' ) )		||
-		( ( p[ 8 ] != '.' ) )							||
-		( ( p[ 9 ] != 'I' ) && ( p[ 9 ] != 'i' ) )		||
-		( ( p[ 10 ] != 'P' ) && ( p[ 10 ] != 'p' ) )	||	
-		( ( p[ 11 ] != '6' ) )							||
-		( ( p[ 12 ] != '.' ) )							||
-		( ( p[ 13 ] != 'A' ) && ( p[ 13 ] != 'a' ) )	||
-		( ( p[ 14 ] != 'R' ) && ( p[ 14 ] != 'r' ) )	||
-		( ( p[ 15 ] != 'P' ) && ( p[ 15 ] != 'p' ) )	||
-		( ( p[ 16 ] != 'A' ) && ( p[ 16 ] != 'a' ) ) ) )
-	{
-		require_action_quiet( size > sizeof_string( ".254.169.in-addr.arpa" ), exit, err = WSASERVICE_NOT_FOUND );
- 
-		p = name + ( size - 1 );
-		p = ( *p == '.' ) ? ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) : ( ( p - sizeof_string( ".254.169.in-addr.arpa" ) ) + 1 );
-	
-		require_action_quiet( ( ( p[ 0 ] == '.' )						 &&
-								( ( p[ 1 ] == '2' ) )							&&
-								( ( p[ 2 ] == '5' ) )							&&
-								( ( p[ 3 ] == '4' ) )							&&
-								( ( p[ 4 ] == '.' ) )							&&
-								( ( p[ 5 ] == '1' ) )							&&
-								( ( p[ 6 ] == '6' ) )							&&
-								( ( p[ 7 ] == '9' ) )							&&
-								( ( p[ 8 ] == '.' ) )							&&
-								( ( p[ 9 ] == 'I' ) || ( p[ 9 ] == 'i' ) )		&&
-								( ( p[ 10 ] == 'N' ) || ( p[ 10 ] == 'n' ) )	&&	
-								( ( p[ 11 ] == '-' ) )							&&
-								( ( p[ 12 ] == 'A' ) || ( p[ 12 ] == 'a' ) )	&&
-								( ( p[ 13 ] == 'D' ) || ( p[ 13 ] == 'd' ) )	&&
-								( ( p[ 14 ] == 'D' ) || ( p[ 14 ] == 'd' ) )	&&
-								( ( p[ 15 ] == 'R' ) || ( p[ 15 ] == 'r' ) )	&&
-								( ( p[ 16 ] == '.' ) )							&&
-								( ( p[ 17 ] == 'A' ) || ( p[ 17 ] == 'a' ) )	&&
-								( ( p[ 18 ] == 'R' ) || ( p[ 18 ] == 'r' ) )	&&
-								( ( p[ 19 ] == 'P' ) || ( p[ 19 ] == 'p' ) )	&&
-								( ( p[ 20 ] == 'A' ) || ( p[ 20 ] == 'a' ) ) ),
-								exit, err = WSASERVICE_NOT_FOUND );
-	}
-
-	// It's a reverse lookup
-
-	check( err == kNoErr );
-
-exit:
-
-	return err;
-}
-#endif
-
-//===========================================================================================================================
-//	GetScopeId
-//===========================================================================================================================
-
-DEBUG_LOCAL DWORD
-GetScopeId( DWORD ifIndex )
-{
-	DWORD						err;
-	int							i;
-	DWORD						flags;
-	struct ifaddrs *			head;
-	struct ifaddrs **			next;
-	IP_ADAPTER_ADDRESSES *		iaaList;
-	ULONG						iaaListSize;
-	IP_ADAPTER_ADDRESSES *		iaa;
-	DWORD						scopeId = 0;
-	
-	head	= NULL;
-	next	= &head;
-	iaaList	= NULL;
-	
-	require( gGetAdaptersAddressesFunctionPtr, exit );
-
-	// Get the list of interfaces. The first call gets the size and the second call gets the actual data.
-	// This loops to handle the case where the interface changes in the window after getting the size, but before the
-	// second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
-	
-	flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
-	i = 0;
-	for( ;; )
-	{
-		iaaListSize = 0;
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
-		check( err == ERROR_BUFFER_OVERFLOW );
-		check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
-		
-		iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
-		require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
-		
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
-		if( err == ERROR_SUCCESS ) break;
-		
-		free( iaaList );
-		iaaList = NULL;
-		++i;
-		require( i < 100, exit );
-		dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
-	}
-	
-	for( iaa = iaaList; iaa; iaa = iaa->Next )
-	{
-		DWORD ipv6IfIndex;
-
-		if ( iaa->IfIndex > 0xFFFFFF )
-		{
-			continue;
-		}
-		if ( iaa->Ipv6IfIndex > 0xFF )
-		{
-			continue;
-		}
-
-		// For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
-		// following code to crash when iterating through the prefix list.  This seems
-		// to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
-		// This shouldn't happen according to Microsoft docs which states:
-		//
-		//     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
-		//
-		// So the data structure seems to be corrupted when we return from
-		// GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
-		// sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
-		// modify iaa to have the correct values.
-
-		if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
-		{
-			ipv6IfIndex = iaa->Ipv6IfIndex;
-		}
-		else
-		{
-			ipv6IfIndex	= 0;
-		}
-
-		// Skip psuedo and tunnel interfaces.
-		
-		if( ( ipv6IfIndex == 1 ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
-		{
-			continue;
-		}
-
-		if ( iaa->IfIndex == ifIndex )
-		{
-			scopeId = iaa->Ipv6IfIndex;
-			break;
-		}
-	} 
-
-exit:
-
-	if( iaaList )
-	{
-		free( iaaList );
-	}
-
-	return scopeId;
-}
diff --git a/mDNSWindows/mdnsNSP/resource.h b/mDNSWindows/mdnsNSP/resource.h
deleted file mode 100644
index 818f083..0000000
--- a/mDNSWindows/mdnsNSP/resource.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by mdnsNSP.rc
-//
-#define IDS_PROJNAME                    100
-#define IDR_WMDMLOGGER                  101
-#define IDS_LOG_SEV_INFO                201
-#define IDS_LOG_SEV_WARN                202
-#define IDS_LOG_SEV_ERROR               203
-#define IDS_LOG_DATETIME                204
-#define IDS_LOG_SRCNAME                 205
-#define IDS_DEF_LOGFILE                 301
-#define IDS_DEF_MAXSIZE                 302
-#define IDS_DEF_SHRINKTOSIZE            303
-#define IDS_DEF_LOGENABLED              304
-#define IDS_MUTEX_TIMEOUT               401
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        201
-#define _APS_NEXT_COMMAND_VALUE         32768
-#define _APS_NEXT_CONTROL_VALUE         201
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/unittests/daemon_ut.c b/unittests/daemon_ut.c
deleted file mode 100644
index 7ada7e9..0000000
--- a/unittests/daemon_ut.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "DNSCommon.h"
-#include "unittest_common.h"
-
-mDNSexport void init_logging_ut(void)
-{
-}
diff --git a/unittests/mdns_macosx_ut.c b/unittests/mdns_macosx_ut.c
deleted file mode 100644
index 08a0711..0000000
--- a/unittests/mdns_macosx_ut.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "DNSCommon.h"                  // Defines general DNS utility routines
-#include "unittest_common.h"
-#include "mDNSMacOSX.h"
-
-// To match *either* a v4 or v6 instance of this interface
-mDNSlocal mDNSInterfaceID SearchForInterfaceByAddr(mDNSAddr* addr)
-{
-	NetworkInterfaceInfoOSX *i;
-	for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-		if (i->Exists)
-		{
-			if ((i->ifinfo.ip.type == mDNSAddrType_IPv4) &&
-				i->ifinfo.ip.ip.v4.NotAnInteger == addr->ip.v4.NotAnInteger)
-				return i->ifinfo.InterfaceID;
-			else if ((i->ifinfo.ip.type == mDNSAddrType_IPv6) &&
-					 (i->ifinfo.ip.ip.v6.l[0] == addr->ip.v6.l[0] &&
-					  i->ifinfo.ip.ip.v6.l[1] == addr->ip.v6.l[1] &&
-					  i->ifinfo.ip.ip.v6.l[2] == addr->ip.v6.l[2] &&
-					  i->ifinfo.ip.ip.v6.l[3] == addr->ip.v6.l[3])
-					 )
-				return i->ifinfo.InterfaceID;
-		}
-	return(NULL);
-}
-
-mDNSexport void SetInterfaces_ut(mDNSInterfaceID* pri_id, mDNSAddr *pri_v4, mDNSAddr* pri_v6, mDNSAddr* pri_router)
-{
-	mDNSs32 utc = mDNSPlatformUTC();
-
-	MarkAllInterfacesInactive(utc);
-	UpdateInterfaceList(utc);
-	ClearInactiveInterfaces(utc);
-	SetupActiveInterfaces(utc);
-
-	// set primary interface info
-	{
-		mDNSAddr* addr;
-		NetworkChangedKey_IPv4         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
-		NetworkChangedKey_IPv6         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
-		NetworkChangedKey_Hostnames    = SCDynamicStoreKeyCreateHostNames(NULL);
-		NetworkChangedKey_Computername = SCDynamicStoreKeyCreateComputerName(NULL);
-		NetworkChangedKey_DNS          = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
-		NetworkChangedKey_StateInterfacePrefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, CFSTR(""), NULL);
-
-		mDNSPlatformGetPrimaryInterface(pri_v4, pri_v6, pri_router);
-		addr = (pri_v4->type == mDNSAddrType_IPv4) ? pri_v4 : pri_v6;
-		*pri_id = SearchForInterfaceByAddr(addr);
-
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_IPv4);
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_IPv6);
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_Hostnames);
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_Computername);
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_DNS);
-        MDNS_DISPOSE_CF_OBJECT(NetworkChangedKey_StateInterfacePrefix);
-	}
-}
-
-mDNSexport mDNSBool mDNSMacOSXCreateEtcHostsEntry_ut(const domainname *domain, const struct sockaddr *sa, const domainname *cname, char *ifname, AuthHash *auth)
-{
-	return mDNSMacOSXCreateEtcHostsEntry(domain, sa, cname, ifname, auth);
-}
-
-mDNSexport void UpdateEtcHosts_ut(void *context)
-{
-	mDNS_Lock(&mDNSStorage);
-	UpdateEtcHosts(&mDNSStorage, context);
-	mDNS_Unlock(&mDNSStorage);
-}
-
-mDNSexport void mDNSDomainLabelFromCFString_ut(CFStringRef cfs, domainlabel *const namelabel)
-{
-    mDNSDomainLabelFromCFString(cfs, namelabel);
-}
-
-mDNSexport mDNSu32 IndexForInterfaceByName_ut(const char *ifname)
-{
-    NetworkInterfaceInfoOSX * i = SearchForInterfaceByName(ifname, AF_UNSPEC);
-    return (i ? i->scope_id : 0);
-}
diff --git a/unittests/mdns_ut.c b/unittests/mdns_ut.c
deleted file mode 100644
index 9ca19ff..0000000
--- a/unittests/mdns_ut.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2018, 2021 Apple 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
- *
- *     https://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.
- */
-
-#include "DNSCommon.h"                  // Defines general DNS utility routines
-#include "unittest_common.h"
-#include "mDNSFeatures.h"
-
-mDNSexport mStatus mDNS_InitStorage_ut(mDNS *const m, mDNS_PlatformSupport *const p,
-									   CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
-									   mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
-{
-	return mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context);
-}
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-void
-ParseCNameChainFromMessage_ut(
-	const DNSMessage *const		response,
-	const mDNSu8 *const			limit,
-	const mDNSInterfaceID		InterfaceID,
-	const domainname *const		qname,
-	domainname					cnameChain[static const MAX_CNAME_TRAVERSAL],
-	mDNSu32  *const				outChainLen)
-{
-	ParseCNameChainFromMessage(response, limit, InterfaceID, qname, cnameChain, outChainLen);
-}
-
-void
-ParseDenialOfExistenceObjsFromMessage_ut(
-	const DNSMessage *const		response,
-	const mDNSu8 *const			limit,
-	const mDNSInterfaceID		InterfaceID,
-	dnssec_obj_rr_soa_t *const	outObjSOA,
-	dnssec_obj_rr_rrsig_t		objSOARRSIG[static const MAX_NUM_RRSIG_TO_PROCESS],
-	mDNSu8 *const				outSOARRSIGCount,
-	dnssec_obj_rr_nsec_t		outObjNSECs[static const MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-	mDNSu8 *const				outNSECCount,
-	dnssec_obj_rr_nsec3_t		outObjNSEC3s[static const MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-	mDNSu8 *const				outNSEC3Count,
-	dnssec_obj_rr_rrsig_t		outObjRRSIGs[static const MAX_NUM_RRSIG_TO_PROCESS],
-	mDNSu8 *const				outRRSIGCount)
-{
-	ParseDenialOfExistenceObjsFromMessage(response, limit, InterfaceID, outObjSOA, objSOARRSIG, outSOARRSIGCount,
-		outObjNSECs, outNSECCount, outObjNSEC3s, outNSEC3Count, outObjRRSIGs, outRRSIGCount);
-}
-
-// This function extracts the resource record from the answer section of the message, and determine what type of record
-// is contained in the answer section:
-// 1. If there are only CNAME records, kDNSType_CNAME will be returned.
-// 2. If there are DNS record other than CNAME record, the other data type will be returned.
-// 3. If no record is contained in the answer section, 0 will be returned.
-// This function is only used in the XCTest to help the test of wildcard data response since this kind of denial of
-// existence is always accompanied by the No Error data that comes from wildcard matching.
-mDNSu16
-GetRRTypeFromMessage(const DNSMessage * const response, const mDNSu8 * const limit, const mDNSInterfaceID InterfaceID)
-{
-	mDNSu16 rrtype = 0;
-	const mDNSu16 answerCount = response->h.numAnswers;
-	if (answerCount == 0) {
-		goto exit;
-	}
-
-	const mDNSu8 *ptr = LocateAnswers(response, limit);
-	if (ptr == mDNSNULL) {
-		goto exit;
-	}
-
-	mDNS *const m = &mDNSStorage;
-	for (mDNSu32 i = 0; i < answerCount && ptr < limit; mDNSCoreResetRecord(m), i++) {
-		ptr = GetLargeResourceRecord(m, response, ptr, limit, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
-		const ResourceRecord *const rr = &(m->rec.r.resrec);
-		if (rr->RecordType == kDNSRecordTypePacketNegative) {
-			continue;
-		}
-
-		if (rrtype == 0 || rrtype == kDNSType_CNAME) {
-			rrtype = rr->rrtype;
-		}
-	}
-
-exit:
-	return rrtype;
-}
-
-#endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
diff --git a/unittests/uds_daemon_ut.c b/unittests/uds_daemon_ut.c
deleted file mode 100644
index b963795..0000000
--- a/unittests/uds_daemon_ut.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "DNSCommon.h"                  // Defines general DNS utility routines
-#include "unittest_common.h"
-
-mDNSexport mStatus handle_client_request_ut(void *req)
-{
-	return handle_client_request((request_state*)req);
-}
-
-mDNSexport void LogCacheRecords_ut(mDNSs32 now, mDNSu32* retCacheUsed, mDNSu32* retCacheActive)
-{
-	mDNSu32 CacheUsed =0, CacheActive =0, slot;
-	const CacheGroup *cg;
-	const CacheRecord *cr;
-
-	LogMsgNoIdent("------------ Cache -------------");
-	LogMsgNoIdent("Slt Q     TTL if     U Type rdlen");
-	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-	{
-		for (cg = mDNSStorage.rrcache_hash[slot]; cg; cg=cg->next)
-		{
-			CacheUsed++;    // Count one cache entity for the CacheGroup object
-			for (cr = cg->members; cr; cr=cr->next)
-			{
-				const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
-				const char *ifname;
-				mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
-				if (!InterfaceID && cr->resrec.rDNSServer && (cr->resrec.rDNSServer->scopeType != kScopeNone))
-					InterfaceID = cr->resrec.rDNSServer->interface;
-				ifname = InterfaceNameForID(&mDNSStorage, InterfaceID);
-				if (cr->CRActiveQuestion) CacheActive++;
-				PrintOneCacheRecordToFD(STDOUT_FILENO, cr, slot, remain, ifname, &CacheUsed);
-				PrintCachedRecordsToFD(STDOUT_FILENO, cr, slot, remain, ifname, &CacheUsed);
-			}
-		}
-	}
-
-	*retCacheUsed = CacheUsed;
-	*retCacheActive = CacheActive;
-}
-
-mDNSexport int LogEtcHosts_ut(mDNS *const m)
-{
-	return LogEtcHostsToFD(STDOUT_FILENO, m);
-}
diff --git a/unittests/unittest.h b/unittests/unittest.h
deleted file mode 100644
index 4b6f1eb..0000000
--- a/unittests/unittest.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2015 Apple 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-#include <signal.h>
-#include "unittest_common.h"
-
-#include <MacTypes.h>
-
-#ifndef _UNITTEST_H_
-#define _UNITTEST_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define UNITTEST_SETSOCKOPT void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transType, \
-    mDNSAddr_Type addrType, const DNSQuestion *q) \
-    { \
-        (void)(sockCxt); \
-        (void)(transType); \
-        (void)(addrType); \
-        (void)(q); \
-        return; \
-    }
-
-#define UNITTEST_UDPCLOSE void mDNSPlatformUDPClose(UDPSocket *sock) \
-    { \
-        (void)(sock); \
-    }
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // ndef _UNITTEST_H_
diff --git a/unittests/unittest_common.c b/unittests/unittest_common.c
deleted file mode 100644
index 3bf7060..0000000
--- a/unittests/unittest_common.c
+++ /dev/null
@@ -1,225 +0,0 @@
-#include "unittest_common.h"
-#include "dns_sd.h"
-#include "mDNSEmbeddedAPI.h"
-#include "mDNSMacOSX.h"
-
-static mDNS_PlatformSupport PlatformStorage;
-#define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord))
-static CacheEntity gRrcachestorage[RR_CACHE_SIZE];
-
-// Primary interface info that is used when simulating the receive of the response packet
-mDNSInterfaceID primary_interfaceID;
-mDNSAddr primary_v4;
-mDNSAddr primary_v6;
-mDNSAddr primary_router;
-
-// This function sets up the minimum environement to run a unit test. It
-// initializes logging, interfaces, and timenow.
-mDNSexport mStatus init_mdns_environment(mDNSBool enableLogging)
-{
-	mDNS *m = &mDNSStorage;
-
-	init_logging_ut();
-	mDNS_LoggingEnabled = enableLogging;
-	mDNS_PacketLoggingEnabled = enableLogging;
-
-	mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
-	if (result != mStatus_NoError)
-		return result;
-
-	primary_v4 = primary_v6 = primary_router = zeroAddr;
-	SetInterfaces_ut(&primary_interfaceID, &primary_v4, &primary_v6, &primary_router);
-
-	m->timenow = mDNS_TimeNow_NoLock(m);
-	return mStatus_NoError;
-}
-
-// This function sets up the minimum environement to run a unit test. It
-// initializes logging and timenow.  This is the call to use if your
-// unit test does not use interfaces.
-mDNSexport mStatus init_mdns_storage()
-{
-	mDNS *m = &mDNSStorage;
-
-	init_logging_ut();
-	mDNS_LoggingEnabled = 1;
-	mDNS_PacketLoggingEnabled = 1;
-
-	mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
-	if (result != mStatus_NoError)
-		return result;
-
-	return mStatus_NoError;
-}
-
-mDNSlocal void init_client_request(request_state* req, const uint8_t *msgbuf, uint32_t msgSize, uint32_t op)
-{
-	// Simulate read_msg behavior since unit test does not open a socket
-	memset(req, 0, sizeof(request_state));
-
-	req->ts = t_complete;
-	req->msgbuf = mDNSNULL;
-	req->msgptr = msgbuf;
-	req->msgend = msgbuf + msgSize;
-
-	// The rest of the request values are set in order to simulate a request
-	req->sd             = client_req_sd;
-	req->uid            = client_req_uid;
-	req->hdr_bytes      = client_req_hdr_bytes;
-	req->hdr.version    = client_req_hdr_version;
-	req->hdr.op         = op; // query_request
-	req->hdr.datalen    = msgSize;
-	req->data_bytes     = msgSize;
-	req->process_id     = client_req_process_id;
-	memcpy(req->pid_name, client_req_pid_name, strlen(client_req_pid_name));
-}
-
-// This function calls the mDNSResponder handle_client_request() API.  It initializes
-// the request and query data structures.
-mDNSexport mStatus start_client_request(request_state* req, const uint8_t *msgbuf, uint32_t msgsz, uint32_t op, UDPSocket* socket)
-{
-	// Process the unit test's client request
-	init_client_request(req, msgbuf, msgsz, op);
-
-	mStatus result = handle_client_request_ut((void*)req);
-	DNSQuestion* q = &req->u.queryrecord.op.q;
-	q->LocalSocket = socket;
-	return result;
-}
-
-// This function calls the mDNSResponder mDNSCoreReceive() API.
-mDNSexport void receive_response(const request_state* req, DNSMessage *msg, size_t msgSize)
-{
-	mDNS *m = &mDNSStorage;
-	mDNSAddr srcaddr;
-	mDNSIPPort srcport, dstport;
-	const mDNSu8 * end;
-	DNSQuestion *q = (DNSQuestion *)&req->u.queryrecord.op.q;
-	UInt8* data = (UInt8*)msg;
-
-	// Used same values for DNS server as specified during init of unit test
-	srcaddr.type				= mDNSAddrType_IPv4;
-	srcaddr.ip.v4.NotAnInteger	= dns_server_ipv4.NotAnInteger;
-	srcport.NotAnInteger		= client_resp_src_port;
-
-	// Used random value for dstport
-	dstport.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
-
-	// Set DNS message (that was copied from a WireShark packet)
-	end = (const mDNSu8 *)msg + msgSize;
-
-	// Set socket info that mDNSCoreReceive uses to verify socket context
-	q->LocalSocket->ss.port.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
-	q->TargetQID.b[0] = data[0];
-	q->TargetQID.b[1] = data[1];
-
-	// Execute mDNSCoreReceive which copies two DNS records into the cache
-	mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &primary_v4, dstport, primary_interfaceID);
-}
-
-mDNSexport  size_t get_reply_len(char* name, uint16_t rdlen)
-{
-	size_t len = sizeof(DNSServiceFlags);
-	len += sizeof(mDNSu32);     // interface index
-	len += sizeof(DNSServiceErrorType);
-	len += strlen(name) + 1;
-	len += 3 * sizeof(mDNSu16); // type, class, rdlen
-	len += rdlen;
-	len += sizeof(mDNSu32);     // TTL
-	return len;
-}
-
-
-void free_req(request_state* req)
-{
-	// Cleanup request's memory usage
-	while (req->replies)
-	{
-		reply_state *reply = req->replies;
-		req->replies = req->replies->next;
-		mDNSPlatformMemFree(reply);
-	}
-	req->replies = NULL;
-	mDNSPlatformMemFree(req);
-}
-
-// Unit test support functions follow
-#define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-
-mDNSexport void get_ip(const char *const name, struct sockaddr_storage *result)
-{
-	struct addrinfo* aiList;
-	int err = getaddrinfo(name, NULL, NULL, &aiList);
-	if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
-	else memcpy(result, aiList->ai_addr, SA_LEN(aiList->ai_addr));
-	if (aiList) freeaddrinfo(aiList);
-}
-
-// The AddDNSServer_ut function adds a dns server to mDNSResponder's list.
-mDNSexport mStatus AddDNSServerScoped_ut(mDNSInterfaceID interfaceID, ScopeType scoped)
-{
-    mDNS *m = &mDNSStorage;
-    m->timenow = 0;
-    mDNS_Lock(m);
-    domainname  d;
-    mDNSAddr    addr;
-    mDNSIPPort  port;
-    mDNSs32     serviceID      = 0;
-    mDNSu32     timeout        = dns_server_timeout;
-    mDNSBool    cellIntf       = 0;
-    mDNSBool    isExpensive    = 0;
-    mDNSBool    isConstrained  = 0;
-    mDNSBool    isCLAT46       = mDNSfalse;
-    mDNSu32     resGroupID     = dns_server_resGroupID;
-    mDNSBool    reqA           = mDNStrue;
-    mDNSBool    reqAAAA        = mDNStrue;
-    mDNSBool    reqDO          = mDNSfalse;
-    d.c[0]                     = 0;
-    addr.type                  = mDNSAddrType_IPv4;
-    addr.ip.v4.NotAnInteger    = dns_server_ipv4.NotAnInteger;
-    port.NotAnInteger          = client_resp_src_port;
-    mDNS_AddDNSServer(m, &d, interfaceID, serviceID, &addr, port, scoped, timeout,
-                      cellIntf, isExpensive, isConstrained, isCLAT46, resGroupID,
-                      reqA, reqAAAA, reqDO);
-    mDNS_Unlock(m);
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus AddDNSServer_ut(void)
-{
-    return AddDNSServerScoped_ut(primary_interfaceID, kScopeNone);
-}
-
-mDNSexport mStatus  force_uDNS_SetupDNSConfig_ut(mDNS *const m)
-{
-    m->p->LastConfigGeneration = 0;
-    return uDNS_SetupDNSConfig(m);
-}
-
-mDNSexport mStatus verify_cache_addr_order_for_domain_ut(mDNS *const m, mDNSu8* octet, mDNSu32 count, const domainname *const name)
-{
-    mStatus result = mStatus_NoError;
-    const CacheGroup *cg = CacheGroupForName(m, DomainNameHashValue(name), name);
-    if (cg)
-    {
-        mDNSu32 i;
-        CacheRecord **rp = (CacheRecord **)&cg->members;
-        for (i = 0 ; *rp && i < count ; i++ )
-        {
-            if ((*rp)->resrec.rdata->u.ipv4.b[3] != octet[i])
-            {
-                LogInfo ("Octet %d compare failed %d != %d", i, (*rp)->resrec.rdata->u.ipv4.b[3], octet[i]);
-                break;
-            }
-            rp = &(*rp)->next;
-        }
-        if (i != count) result = mStatus_Invalid;
-    }
-    else
-    {
-        LogInfo ("Cache group not found");
-        result = mStatus_Invalid;
-    }
-
-    return result;
-}
diff --git a/unittests/unittest_common.h b/unittests/unittest_common.h
deleted file mode 100644
index 4115593..0000000
--- a/unittests/unittest_common.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2016-2021 Apple 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
- *
- *     https://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.
- */
-
-#ifndef UNITTEST_COMMON_H
-#define UNITTEST_COMMON_H
-
-#include "dns_sd.h"
-#include "uds_daemon.h"
-#include "uDNS.h"
-#include "dnssd_ipc.h"
-#include <netdb.h>                  // for getaddrinfo
-#include <net/if.h>
-#include <pthread.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include "mDNSFeatures.h"
-
-// Primary interface info that is used when simulating the receive of the response packet
-extern mDNSInterfaceID primary_interfaceID;
-extern mDNSAddr primary_v4;
-extern mDNSAddr primary_v6;
-extern mDNSAddr primary_router;
-
-// Arbitrary values to simulate a client_request request
-#define client_req_sd				12
-#define client_req_uid				502
-#define client_req_hdr_bytes		28
-#define client_req_hdr_version		1
-#define client_resp_src_port		13568
-#define client_resp_dst_port		49339
-#define uDNS_TargetQID				16745
-#define client_req_process_id		15418
-static char client_req_pid_name[MAXCOMLEN] = "mDNSUnitTest";
-
-//Arbitrary values to simulate a DNS server
-#define dns_server_timeout			30
-#define dns_server_resGroupID		12
-static const mDNSv4Addr dns_server_ipv4 = {{ 192, 168, 1, 20 }};
-
-extern mStatus  init_mdns_environment(mDNSBool enableLogging);
-extern mStatus  init_mdns_storage(void);
-extern size_t   get_reply_len(char* name, uint16_t rdlen);
-extern mStatus  start_client_request(request_state* req, const uint8_t *msgbuf, uint32_t msgsz, uint32_t op, UDPSocket* socket);
-extern void     receive_response(const request_state* req, DNSMessage *msg, size_t msgSize);
-extern void     get_ip(const char *const name, struct sockaddr_storage *result);
-extern void     free_req(request_state* req);
-
-extern mStatus  mDNS_InitStorage_ut(mDNS *const m, mDNS_PlatformSupport *const p,
-                                   CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
-                                   mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context);
-
-#if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
-
-#define MAX_CNAME_TRAVERSAL 11
-void
-ParseCNameChainFromMessage_ut(
-    const DNSMessage *      response,
-    const mDNSu8 *          limit,
-    const mDNSInterfaceID   InterfaceID,
-    const domainname *      qname,
-    domainname              cnameChain[static MAX_CNAME_TRAVERSAL],
-    mDNSu32  *              outChainLen);
-
-#define MAX_NUM_NSEC_NSEC3_TO_PROCESS   10
-#define MAX_NUM_RRSIG_TO_PROCESS        30
-void
-ParseDenialOfExistenceObjsFromMessage_ut(
-    const DNSMessage *      response,
-    const mDNSu8 *          limit,
-    const mDNSInterfaceID   InterfaceID,
-    dnssec_obj_rr_soa_t *   outObjSOA,
-    dnssec_obj_rr_rrsig_t   objSOARRSIG[static MAX_NUM_RRSIG_TO_PROCESS],
-    mDNSu8 *                outSOARRSIGCount,
-    dnssec_obj_rr_nsec_t    outObjNSECs[static MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-    mDNSu8 *                outNSECCount,
-    dnssec_obj_rr_nsec3_t   outObjNSEC3s[static MAX_NUM_NSEC_NSEC3_TO_PROCESS],
-    mDNSu8 *                outNSEC3Count,
-    dnssec_obj_rr_rrsig_t   outObjRRSIGs[static MAX_NUM_RRSIG_TO_PROCESS],
-    mDNSu8 *                outRRSIGCount);
-
-mDNSu16
-GetRRTypeFromMessage(const DNSMessage *response, const mDNSu8 *limit, mDNSInterfaceID InterfaceID);
-
-#endif
-
-extern void     init_logging_ut(void);
-extern void     SetInterfaces_ut(mDNSInterfaceID* primary_interfaceID, mDNSAddr *primary_v4,
-                                 mDNSAddr* primary_v6, mDNSAddr* primary_router);
-extern mStatus  handle_client_request_ut(void *req);
-extern void     LogCacheRecords_ut(mDNSs32 now, mDNSu32* retCacheUsed, mDNSu32* retCacheActive);
-extern int      LogEtcHosts_ut(mDNS *const m);
-extern mDNSBool mDNSMacOSXCreateEtcHostsEntry_ut(const domainname *domain, const struct sockaddr *sa,
-                                                 const domainname *cname, char *ifname, AuthHash *auth);
-extern void     UpdateEtcHosts_ut(void *context);
-extern mStatus  AddDNSServer_ut(void);
-extern mStatus  AddDNSServerScoped_ut(mDNSInterfaceID interfaceID, ScopeType scoped);
-extern mStatus  force_uDNS_SetupDNSConfig_ut(mDNS *const m);
-extern mStatus  verify_cache_addr_order_for_domain_ut(mDNS *const m, mDNSu8* octet, mDNSu32 count, const domainname *const name);
-
-// HelperFunctionTest
-extern void mDNSDomainLabelFromCFString_ut(CFStringRef cfs, domainlabel *const namelabel);
-mDNSexport mDNSu32 IndexForInterfaceByName_ut(const char *ifname);
-
-#endif /* UNITTEST_COMMON_H */