• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16 
17 	To Do:
18 
19 	- Get unicode name of machine for nice name instead of just the host name.
20 	- Use the IPv6 Internet Connection Firewall API to allow IPv6 mDNS without manually changing the firewall.
21 	- Get DNS server address(es) from Windows and provide them to the uDNS layer.
22 	- Implement TCP support for truncated packets (only stubs now).
23 
24 */
25 
26 #include	<stdarg.h>
27 #include	<stddef.h>
28 #include	<stdio.h>
29 #include	<stdlib.h>
30 #include	<crtdbg.h>
31 #include	<string.h>
32 
33 #include	"CommonServices.h"
34 #include	"DebugServices.h"
35 #include	"Firewall.h"
36 #include	"RegNames.h"
37 #include	"Secret.h"
38 #include	<dns_sd.h>
39 
40 #include	<Iphlpapi.h>
41 #include	<mswsock.h>
42 #include	<process.h>
43 #include	<ntsecapi.h>
44 #include	<lm.h>
45 #include	<winioctl.h>
46 #include	<ntddndis.h>        // This defines the IOCTL constants.
47 
48 #include	"mDNSEmbeddedAPI.h"
49 #include	"GenLinkedList.h"
50 #include	"DNSCommon.h"
51 #include	"mDNSWin32.h"
52 
53 #if 0
54 #pragma mark == Constants ==
55 #endif
56 
57 //===========================================================================================================================
58 //	Constants
59 //===========================================================================================================================
60 
61 #define	DEBUG_NAME									"[mDNSWin32] "
62 
63 #define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				1
64 #define	MDNS_WINDOWS_ENABLE_IPV4					1
65 #define	MDNS_WINDOWS_ENABLE_IPV6					1
66 #define	MDNS_FIX_IPHLPAPI_PREFIX_BUG				1
67 #define MDNS_SET_HINFO_STRINGS						0
68 
69 #define	kMDNSDefaultName							"My Computer"
70 
71 #define	kWinSockMajorMin							2
72 #define	kWinSockMinorMin							2
73 
74 #define kRegistryMaxKeyLength						255
75 #define kRegistryMaxValueName						16383
76 
77 static GUID											kWSARecvMsgGUID = WSAID_WSARECVMSG;
78 
79 #define kIPv6IfIndexBase							(10000000L)
80 #define SMBPortAsNumber								445
81 #define DEVICE_PREFIX								"\\\\.\\"
82 
83 #if 0
84 #pragma mark == Prototypes ==
85 #endif
86 
87 //===========================================================================================================================
88 //	Prototypes
89 //===========================================================================================================================
90 
91 mDNSlocal mStatus			SetupNiceName( mDNS * const inMDNS );
92 mDNSlocal mStatus			SetupHostName( mDNS * const inMDNS );
93 mDNSlocal mStatus			SetupName( mDNS * const inMDNS );
94 mDNSlocal mStatus			SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
95 mDNSlocal mStatus			TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
96 mDNSlocal void CALLBACK		FreeInterface( mDNSInterfaceData *inIFD );
97 mDNSlocal mStatus			SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  );
98 mDNSlocal mStatus			SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
99 mDNSlocal OSStatus			GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
100 mDNSlocal int				getifaddrs( struct ifaddrs **outAddrs );
101 mDNSlocal void				freeifaddrs( struct ifaddrs *inAddrs );
102 
103 
104 
105 // Platform Accessors
106 
107 #ifdef	__cplusplus
108 	extern "C" {
109 #endif
110 
111 typedef struct mDNSPlatformInterfaceInfo	mDNSPlatformInterfaceInfo;
112 struct	mDNSPlatformInterfaceInfo
113 {
114 	const char *		name;
115 	mDNSAddr			ip;
116 };
117 
118 
119 mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
120 mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
121 
122 // Utilities
123 
124 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
125 	mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs );
126 #endif
127 
128 mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
129 
130 
131 mDNSlocal DWORD				GetPrimaryInterface();
132 mDNSlocal mStatus			AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
133 mDNSlocal mDNSBool			CanReceiveUnicast( void );
134 mDNSlocal mDNSBool			IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr );
135 
136 mDNSlocal mStatus			StringToAddress( mDNSAddr * ip, LPSTR string );
137 mDNSlocal mStatus			RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
138 mDNSlocal struct ifaddrs*	myGetIfAddrs(int refresh);
139 mDNSlocal OSStatus			TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
140 mDNSlocal OSStatus			WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
141 mDNSlocal void				TCPDidConnect( mDNS * const inMDNS, HANDLE event, void * context );
142 mDNSlocal void				TCPCanRead( TCPSocket * sock );
143 mDNSlocal mStatus			TCPBeginRecv( TCPSocket * sock );
144 mDNSlocal void CALLBACK		TCPEndRecv( DWORD error, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags );
145 mDNSlocal void				TCPCloseSocket( TCPSocket * socket );
146 mDNSlocal void CALLBACK		TCPFreeSocket( TCPSocket *sock );
147 mDNSlocal OSStatus			UDPBeginRecv( UDPSocket * socket );
148 mDNSlocal void CALLBACK		UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags );
149 mDNSlocal void				UDPCloseSocket( UDPSocket * sock );
150 mDNSlocal void CALLBACK		UDPFreeSocket( UDPSocket * sock );
151 mDNSlocal mStatus           SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
152 mDNSlocal void				GetDDNSFQDN( domainname *const fqdn );
153 #ifdef UNICODE
154 mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey );
155 #else
156 mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
157 #endif
158 mDNSlocal void				SetDomainSecrets( mDNS * const inMDNS );
159 mDNSlocal void				SetDomainSecret( mDNS * const m, const domainname * inDomain );
160 mDNSlocal VOID CALLBACK		CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
161 mDNSlocal void				CheckFileShares( mDNS * const inMDNS );
162 mDNSlocal void				SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
163 mDNSlocal mDNSu8			IsWOMPEnabledForAdapter( const char * adapterName );
164 mDNSlocal void				DispatchUDPEvent( mDNS * const m, UDPSocket * sock );
165 mDNSlocal void				DispatchTCPEvent( mDNS * const m, TCPSocket * sock );
166 
167 #ifdef	__cplusplus
168 	}
169 #endif
170 
171 #if 0
172 #pragma mark == Globals ==
173 #endif
174 
175 //===========================================================================================================================
176 //	Globals
177 //===========================================================================================================================
178 
179 mDNSlocal mDNS_PlatformSupport	gMDNSPlatformSupport;
180 mDNSs32							mDNSPlatformOneSecond	= 0;
181 mDNSlocal UDPSocket		*		gUDPSockets				= NULL;
182 mDNSlocal int					gUDPNumSockets			= 0;
183 mDNSlocal GenLinkedList			gUDPDispatchableSockets;
184 mDNSlocal GenLinkedList			gTCPDispatchableSockets;
185 
186 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
187 
188 	typedef DWORD
189 		( WINAPI * GetAdaptersAddressesFunctionPtr )(
190 			ULONG 					inFamily,
191 			DWORD 					inFlags,
192 			PVOID 					inReserved,
193 			PIP_ADAPTER_ADDRESSES 	inAdapter,
194 			PULONG					outBufferSize );
195 
196 	mDNSlocal HMODULE								gIPHelperLibraryInstance			= NULL;
197 	mDNSlocal GetAdaptersAddressesFunctionPtr		gGetAdaptersAddressesFunctionPtr	= NULL;
198 
199 #endif
200 
201 
202 #ifndef HCRYPTPROV
203    typedef ULONG_PTR HCRYPTPROV;    // WinCrypt.h, line 249
204 #endif
205 
206 
207 #ifndef CRYPT_MACHINE_KEYSET
208 #	define CRYPT_MACHINE_KEYSET    0x00000020
209 #endif
210 
211 #ifndef CRYPT_NEWKEYSET
212 #	define CRYPT_NEWKEYSET         0x00000008
213 #endif
214 
215 #ifndef PROV_RSA_FULL
216 #  define PROV_RSA_FULL 1
217 #endif
218 
219 typedef BOOL (__stdcall *fnCryptGenRandom)( HCRYPTPROV, DWORD, BYTE* );
220 typedef BOOL (__stdcall *fnCryptAcquireContext)( HCRYPTPROV*, LPCTSTR, LPCTSTR, DWORD, DWORD);
221 typedef BOOL (__stdcall *fnCryptReleaseContext)(HCRYPTPROV, DWORD);
222 
223 static fnCryptAcquireContext g_lpCryptAcquireContext 	= NULL;
224 static fnCryptReleaseContext g_lpCryptReleaseContext 	= NULL;
225 static fnCryptGenRandom		 g_lpCryptGenRandom 		= NULL;
226 static HINSTANCE			 g_hAAPI32 					= NULL;
227 static HCRYPTPROV			 g_hProvider 				= ( ULONG_PTR ) NULL;
228 
229 
230 typedef DNSServiceErrorType ( DNSSD_API *DNSServiceRegisterFunc )
231     (
232     DNSServiceRef                       *sdRef,
233     DNSServiceFlags                     flags,
234     uint32_t                            interfaceIndex,
235     const char                          *name,         /* may be NULL */
236     const char                          *regtype,
237     const char                          *domain,       /* may be NULL */
238     const char                          *host,         /* may be NULL */
239     uint16_t                            port,
240     uint16_t                            txtLen,
241     const void                          *txtRecord,    /* may be NULL */
242     DNSServiceRegisterReply             callBack,      /* may be NULL */
243     void                                *context       /* may be NULL */
244     );
245 
246 
247 typedef void ( DNSSD_API *DNSServiceRefDeallocateFunc )( DNSServiceRef sdRef );
248 
249 mDNSlocal HMODULE					gDNSSDLibrary				= NULL;
250 mDNSlocal DNSServiceRegisterFunc	gDNSServiceRegister			= NULL;
251 mDNSlocal DNSServiceRefDeallocateFunc gDNSServiceRefDeallocate	= NULL;
252 mDNSlocal HANDLE					gSMBThread					= NULL;
253 mDNSlocal HANDLE					gSMBThreadRegisterEvent		= NULL;
254 mDNSlocal HANDLE					gSMBThreadDeregisterEvent	= NULL;
255 mDNSlocal HANDLE					gSMBThreadStopEvent			= NULL;
256 mDNSlocal HANDLE					gSMBThreadQuitEvent			= NULL;
257 
258 #define	kSMBStopEvent				( WAIT_OBJECT_0 + 0 )
259 #define	kSMBRegisterEvent			( WAIT_OBJECT_0 + 1 )
260 #define kSMBDeregisterEvent			( WAIT_OBJECT_0 + 2 )
261 
262 
263 #if 0
264 #pragma mark -
265 #pragma mark == Platform Support ==
266 #endif
267 
268 //===========================================================================================================================
269 //	mDNSPlatformInit
270 //===========================================================================================================================
271 
mDNSPlatformInit(mDNS * const inMDNS)272 mDNSexport mStatus	mDNSPlatformInit( mDNS * const inMDNS )
273 {
274 	mStatus		err;
275 	WSADATA		wsaData;
276 	int			supported;
277 	struct sockaddr_in	sa4;
278 	struct sockaddr_in6 sa6;
279 	int					sa4len;
280 	int					sa6len;
281 	DWORD				size;
282 	DWORD				val;
283 
284 	dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
285 
286 	// Initialize variables. If the PlatformSupport pointer is not null then just assume that a non-Apple client is
287 	// calling mDNS_Init and wants to provide its own storage for the platform-specific data so do not overwrite it.
288 
289 	mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
290 	if( !inMDNS->p ) inMDNS->p				= &gMDNSPlatformSupport;
291 	inMDNS->p->mainThread					= OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
292 	require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
293 	inMDNS->p->checkFileSharesTimer = CreateWaitableTimer( NULL, FALSE, NULL );
294 	require_action( inMDNS->p->checkFileSharesTimer, exit, err = mStatus_UnknownErr );
295 	inMDNS->p->checkFileSharesTimeout		= 10;		// Retry time for CheckFileShares() in seconds
296 	mDNSPlatformOneSecond 					= 1000;		// Use milliseconds as the quantum of time
297 	InitLinkedList( &gTCPDispatchableSockets, offsetof( TCPSocket, nextDispatchable ) );
298 	InitLinkedList( &gUDPDispatchableSockets, offsetof( UDPSocket, nextDispatchable ) );
299 
300 	// Startup WinSock 2.2 or later.
301 
302 	err = WSAStartup( MAKEWORD( kWinSockMajorMin, kWinSockMinorMin ), &wsaData );
303 	require_noerr( err, exit );
304 
305 	supported = ( ( LOBYTE( wsaData.wVersion ) == kWinSockMajorMin ) && ( HIBYTE( wsaData.wVersion ) == kWinSockMinorMin ) );
306 	require_action( supported, exit, err = mStatus_UnsupportedErr );
307 
308 	inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
309 
310 	// Setup the HINFO HW strings.
311 	//<rdar://problem/7245119> device-info should have model=Windows
312 
313 	strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
314 	inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
315 	dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
316 
317 	// Setup the HINFO SW strings.
318 #if ( MDNS_SET_HINFO_STRINGS )
319 	mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2,
320 		"mDNSResponder (%s %s)", __DATE__, __TIME__ );
321 	inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
322 	dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
323 #endif
324 
325 	// Set the thread global overlapped flag
326 
327 	val = 0;
328 	err = setsockopt( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, ( char* ) &val, sizeof( val ) );
329 	err = translate_errno( err != SOCKET_ERROR, WSAGetLastError(), kUnknownErr );
330 	require_noerr( err, exit );
331 
332 	// Set up the IPv4 unicast socket
333 
334 	inMDNS->p->unicastSock4.fd			= INVALID_SOCKET;
335 	inMDNS->p->unicastSock4.recvMsgPtr	= NULL;
336 	inMDNS->p->unicastSock4.ifd			= NULL;
337 	inMDNS->p->unicastSock4.overlapped.pending = FALSE;
338 	inMDNS->p->unicastSock4.next		= NULL;
339 	inMDNS->p->unicastSock4.m			= inMDNS;
340 
341 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
342 
343 	sa4.sin_family		= AF_INET;
344 	sa4.sin_addr.s_addr = INADDR_ANY;
345 	err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
346 	check_noerr( err );
347 	sa4len = sizeof( sa4 );
348 	err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
349 	require_noerr( err, exit );
350 	inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
351 	inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
352 	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 );
353 
354 	if ( err )
355 	{
356 		inMDNS->p->unicastSock4.recvMsgPtr = NULL;
357 	}
358 
359 	err = UDPBeginRecv( &inMDNS->p->unicastSock4 );
360 	require_noerr( err, exit );
361 
362 #endif
363 
364 	// Set up the IPv6 unicast socket
365 
366 	inMDNS->p->unicastSock6.fd			= INVALID_SOCKET;
367 	inMDNS->p->unicastSock6.recvMsgPtr	= NULL;
368 	inMDNS->p->unicastSock6.ifd			= NULL;
369 	inMDNS->p->unicastSock6.overlapped.pending = FALSE;
370 	inMDNS->p->unicastSock6.next		= NULL;
371 	inMDNS->p->unicastSock6.m			= inMDNS;
372 
373 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
374 
375 	sa6.sin6_family		= AF_INET6;
376 	sa6.sin6_addr		= in6addr_any;
377 	sa6.sin6_scope_id	= 0;
378 
379 	// This call will fail if the machine hasn't installed IPv6.  In that case,
380 	// the error will be WSAEAFNOSUPPORT.
381 
382 	err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
383 	require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
384 	err = kNoErr;
385 
386 	// If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
387 
388 	if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
389 	{
390 		sa6len = sizeof( sa6 );
391 		err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
392 		require_noerr( err, exit );
393 		inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
394 		inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
395 
396 		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 );
397 
398 		if ( err != 0 )
399 		{
400 			inMDNS->p->unicastSock6.recvMsgPtr = NULL;
401 		}
402 
403 		err = UDPBeginRecv( &inMDNS->p->unicastSock6 );
404 		require_noerr( err, exit );
405 	}
406 
407 #endif
408 
409 	// Notify core of domain secret keys
410 
411 	SetDomainSecrets( inMDNS );
412 
413 	// Success!
414 
415 	mDNSCoreInitComplete( inMDNS, err );
416 
417 
418 exit:
419 
420 	if ( err )
421 	{
422 		mDNSPlatformClose( inMDNS );
423 	}
424 
425 	dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
426 	return( err );
427 }
428 
429 //===========================================================================================================================
430 //	mDNSPlatformClose
431 //===========================================================================================================================
432 
mDNSPlatformClose(mDNS * const inMDNS)433 mDNSexport void	mDNSPlatformClose( mDNS * const inMDNS )
434 {
435 	mStatus		err;
436 
437 	dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
438 	check( inMDNS );
439 
440 	if ( gSMBThread != NULL )
441 	{
442 		dlog( kDebugLevelTrace, DEBUG_NAME "tearing down smb registration thread\n" );
443 		SetEvent( gSMBThreadStopEvent );
444 
445 		if ( WaitForSingleObject( gSMBThreadQuitEvent, 5 * 1000 ) == WAIT_OBJECT_0 )
446 		{
447 			if ( gSMBThreadQuitEvent )
448 			{
449 				CloseHandle( gSMBThreadQuitEvent );
450 				gSMBThreadQuitEvent = NULL;
451 			}
452 
453 			if ( gSMBThreadStopEvent )
454 			{
455 				CloseHandle( gSMBThreadStopEvent );
456 				gSMBThreadStopEvent = NULL;
457 			}
458 
459 			if ( gSMBThreadDeregisterEvent )
460 			{
461 				CloseHandle( gSMBThreadDeregisterEvent );
462 				gSMBThreadDeregisterEvent = NULL;
463 			}
464 
465 			if ( gSMBThreadRegisterEvent )
466 			{
467 				CloseHandle( gSMBThreadRegisterEvent );
468 				gSMBThreadRegisterEvent = NULL;
469 			}
470 
471 			if ( gDNSSDLibrary )
472 			{
473 				FreeLibrary( gDNSSDLibrary );
474 				gDNSSDLibrary = NULL;
475 			}
476 		}
477 		else
478 		{
479 			LogMsg( "Unable to stop SMBThread" );
480 		}
481 
482 		inMDNS->p->smbFileSharing = mDNSfalse;
483 		inMDNS->p->smbPrintSharing = mDNSfalse;
484 	}
485 
486 	// Tear everything down in reverse order to how it was set up.
487 
488 	err = TearDownInterfaceList( inMDNS );
489 	check_noerr( err );
490 	check( !inMDNS->p->inactiveInterfaceList );
491 
492 #if ( MDNS_WINDOWS_ENABLE_IPV4 )
493 
494 	UDPCloseSocket( &inMDNS->p->unicastSock4 );
495 
496 #endif
497 
498 #if ( MDNS_WINDOWS_ENABLE_IPV6 )
499 
500 	UDPCloseSocket( &inMDNS->p->unicastSock6 );
501 
502 #endif
503 
504 	// Free the DLL needed for IPv6 support.
505 
506 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
507 	if( gIPHelperLibraryInstance )
508 	{
509 		gGetAdaptersAddressesFunctionPtr = NULL;
510 
511 		FreeLibrary( gIPHelperLibraryInstance );
512 		gIPHelperLibraryInstance = NULL;
513 	}
514 #endif
515 
516 	if ( g_hAAPI32 )
517 	{
518 		// Release any resources
519 
520 		if ( g_hProvider && g_lpCryptReleaseContext )
521 		{
522 			( g_lpCryptReleaseContext )( g_hProvider, 0 );
523 		}
524 
525 		// Free the AdvApi32.dll
526 
527 		FreeLibrary( g_hAAPI32 );
528 
529 		// And reset all the data
530 
531 		g_lpCryptAcquireContext = NULL;
532 		g_lpCryptReleaseContext = NULL;
533 		g_lpCryptGenRandom 		= NULL;
534 		g_hProvider 			= ( ULONG_PTR ) NULL;
535 		g_hAAPI32				= NULL;
536 	}
537 
538 	// Clear out the APC queue
539 
540 	while ( SleepEx( 0, TRUE ) == WAIT_IO_COMPLETION )
541 	{
542 		DispatchSocketEvents( inMDNS );
543 	}
544 
545 	WSACleanup();
546 
547 	dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
548 }
549 
550 
551 //===========================================================================================================================
552 //	mDNSPlatformLock
553 //===========================================================================================================================
554 
mDNSPlatformLock(const mDNS * const inMDNS)555 mDNSexport void	mDNSPlatformLock( const mDNS * const inMDNS )
556 {
557 	( void ) inMDNS;
558 }
559 
560 //===========================================================================================================================
561 //	mDNSPlatformUnlock
562 //===========================================================================================================================
563 
mDNSPlatformUnlock(const mDNS * const inMDNS)564 mDNSexport void	mDNSPlatformUnlock( const mDNS * const inMDNS )
565 {
566 	( void ) inMDNS;
567 }
568 
569 //===========================================================================================================================
570 //	mDNSPlatformStrCopy
571 //===========================================================================================================================
572 
mDNSPlatformStrCopy(void * inDst,const void * inSrc)573 mDNSexport void	mDNSPlatformStrCopy( void *inDst, const void *inSrc )
574 {
575 	check( inSrc );
576 	check( inDst );
577 
578 	strcpy( (char *) inDst, (const char*) inSrc );
579 }
580 
581 //===========================================================================================================================
582 //	mDNSPlatformStrLCopy
583 //===========================================================================================================================
584 
mDNSPlatformStrLCopy(void * inDst,const void * inSrc,mDNSu32 inSize)585 mDNSexport mDNSu32 mDNSPlatformStrLCopy(void *inDst, const void *inSrc, mDNSu32 inSize)
586 {
587 	const char *		src = (const char *) inSrc;
588 
589 	if( inSize > 0 )
590 	{
591 		size_t		n;
592 		char *		dst = (char *) inDst;
593 
594 		for( n = inSize - 1; n > 0; --n )
595 		{
596 			if( ( *dst++ = *src++ ) == '\0' )
597 			{
598 				// Null terminator encountered, so exit.
599 				goto exit;
600 			}
601 		}
602 		*dst = '\0';
603 	}
604 
605 	while( *src++ != '\0' )
606 	{
607 		// Stop at null terminator.
608 	}
609 
610 exit:
611 	return( (mDNSu32)( src - (const char *) inSrc ) - 1 );
612 }
613 
614 //===========================================================================================================================
615 //	mDNSPlatformStrLen
616 //===========================================================================================================================
617 
mDNSPlatformStrLen(const void * inSrc)618 mDNSexport mDNSu32	mDNSPlatformStrLen( const void *inSrc )
619 {
620 	check( inSrc );
621 
622 	return( (mDNSu32) strlen( (const char *) inSrc ) );
623 }
624 
625 //===========================================================================================================================
626 //	mDNSPlatformMemCopy
627 //===========================================================================================================================
628 
mDNSPlatformMemCopy(void * inDst,const void * inSrc,mDNSu32 inSize)629 mDNSexport void	mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
630 {
631 	check( inSrc );
632 	check( inDst );
633 
634 	memcpy( inDst, inSrc, inSize );
635 }
636 
637 //===========================================================================================================================
638 //	mDNSPlatformMemSame
639 //===========================================================================================================================
640 
mDNSPlatformMemSame(const void * inDst,const void * inSrc,mDNSu32 inSize)641 mDNSexport mDNSBool	mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize )
642 {
643 	check( inSrc );
644 	check( inDst );
645 
646 	return( (mDNSBool)( memcmp( inSrc, inDst, inSize ) == 0 ) );
647 }
648 
649 //===========================================================================================================================
650 //	mDNSPlatformMemZero
651 //===========================================================================================================================
652 
mDNSPlatformMemZero(void * inDst,mDNSu32 inSize)653 mDNSexport void	mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
654 {
655 	check( inDst );
656 
657 	memset( inDst, 0, inSize );
658 }
659 
660 //===========================================================================================================================
661 //	mDNSPlatformMemAllocate
662 //===========================================================================================================================
663 
mDNSPlatformMemAllocate(mDNSu32 inSize)664 mDNSexport void *	mDNSPlatformMemAllocate( mDNSu32 inSize )
665 {
666 	void *		mem;
667 
668 	check( inSize > 0 );
669 
670 	mem = malloc( inSize );
671 	check( mem );
672 
673 	return( mem );
674 }
675 
676 //===========================================================================================================================
677 //	mDNSPlatformMemFree
678 //===========================================================================================================================
679 
mDNSPlatformMemFree(void * inMem)680 mDNSexport void	mDNSPlatformMemFree( void *inMem )
681 {
682 	check( inMem );
683 
684 	free( inMem );
685 }
686 
687 //===========================================================================================================================
688 //	mDNSPlatformRandomNumber
689 //===========================================================================================================================
690 
mDNSPlatformRandomNumber(void)691 mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
692 {
693 	mDNSu32		randomNumber = 0;
694 	BOOL		bResult;
695 	OSStatus	err = 0;
696 
697 	if ( !g_hAAPI32 )
698 	{
699 		g_hAAPI32 = LoadLibrary( TEXT("AdvAPI32.dll") );
700 		err = translate_errno( g_hAAPI32 != NULL, GetLastError(), mStatus_UnknownErr );
701 		require_noerr( err, exit );
702 	}
703 
704 	// Function Pointer: CryptAcquireContext
705 
706 	if ( !g_lpCryptAcquireContext )
707 	{
708 		g_lpCryptAcquireContext = ( fnCryptAcquireContext )
709 #ifdef UNICODE
710 			( GetProcAddress( g_hAAPI32, "CryptAcquireContextW" ) );
711 #else
712 			( GetProcAddress( g_hAAPI32, "CryptAcquireContextA" ) );
713 #endif
714 		err = translate_errno( g_lpCryptAcquireContext != NULL, GetLastError(), mStatus_UnknownErr );
715 		require_noerr( err, exit );
716 	}
717 
718 	// Function Pointer: CryptReleaseContext
719 
720 	if ( !g_lpCryptReleaseContext )
721 	{
722 		g_lpCryptReleaseContext = ( fnCryptReleaseContext )
723          ( GetProcAddress( g_hAAPI32, "CryptReleaseContext" ) );
724 		err = translate_errno( g_lpCryptReleaseContext != NULL, GetLastError(), mStatus_UnknownErr );
725 		require_noerr( err, exit );
726 	}
727 
728 	// Function Pointer: CryptGenRandom
729 
730 	if ( !g_lpCryptGenRandom )
731 	{
732 		g_lpCryptGenRandom = ( fnCryptGenRandom )
733           ( GetProcAddress( g_hAAPI32, "CryptGenRandom" ) );
734 		err = translate_errno( g_lpCryptGenRandom != NULL, GetLastError(), mStatus_UnknownErr );
735 		require_noerr( err, exit );
736 	}
737 
738 	// Setup
739 
740 	if ( !g_hProvider )
741 	{
742 		bResult = (*g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET );
743 
744 		if ( !bResult )
745 		{
746 			bResult =  ( *g_lpCryptAcquireContext)( &g_hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET );
747 			err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
748 			require_noerr( err, exit );
749 		}
750 	}
751 
752 	bResult = (*g_lpCryptGenRandom)( g_hProvider, sizeof( randomNumber ), ( BYTE* ) &randomNumber );
753 	err = translate_errno( bResult, GetLastError(), mStatus_UnknownErr );
754 	require_noerr( err, exit );
755 
756 exit:
757 
758 	if ( err )
759 	{
760 		randomNumber = rand();
761 	}
762 
763 	return randomNumber;
764 }
765 
766 //===========================================================================================================================
767 //	mDNSPlatformTimeInit
768 //===========================================================================================================================
769 
mDNSPlatformTimeInit(void)770 mDNSexport mStatus	mDNSPlatformTimeInit( void )
771 {
772 	// No special setup is required on Windows -- we just use GetTickCount().
773 	return( mStatus_NoError );
774 }
775 
776 //===========================================================================================================================
777 //	mDNSPlatformRawTime
778 //===========================================================================================================================
779 
mDNSPlatformRawTime(void)780 mDNSexport mDNSs32	mDNSPlatformRawTime( void )
781 {
782 	return( (mDNSs32) GetTickCount() );
783 }
784 
785 //===========================================================================================================================
786 //	mDNSPlatformUTC
787 //===========================================================================================================================
788 
mDNSPlatformUTC(void)789 mDNSexport mDNSs32	mDNSPlatformUTC( void )
790 {
791 	return ( mDNSs32 ) time( NULL );
792 }
793 
794 //===========================================================================================================================
795 //	mDNSPlatformInterfaceNameToID
796 //===========================================================================================================================
797 
mDNSPlatformInterfaceNameToID(mDNS * const inMDNS,const char * inName,mDNSInterfaceID * outID)798 mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
799 {
800 	mStatus					err;
801 	mDNSInterfaceData *		ifd;
802 
803 	check( inMDNS );
804 	check( inMDNS->p );
805 	check( inName );
806 
807 	// Search for an interface with the specified name,
808 
809 	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
810 	{
811 		if( strcmp( ifd->name, inName ) == 0 )
812 		{
813 			break;
814 		}
815 	}
816 	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
817 
818 	// Success!
819 
820 	if( outID )
821 	{
822 		*outID = (mDNSInterfaceID) ifd;
823 	}
824 	err = mStatus_NoError;
825 
826 exit:
827 	return( err );
828 }
829 
830 //===========================================================================================================================
831 //	mDNSPlatformInterfaceIDToInfo
832 //===========================================================================================================================
833 
mDNSPlatformInterfaceIDToInfo(mDNS * const inMDNS,mDNSInterfaceID inID,mDNSPlatformInterfaceInfo * outInfo)834 mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
835 {
836 	mStatus					err;
837 	mDNSInterfaceData *		ifd;
838 
839 	check( inMDNS );
840 	check( inID );
841 	check( outInfo );
842 
843 	// Search for an interface with the specified ID,
844 
845 	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
846 	{
847 		if( ifd == (mDNSInterfaceData *) inID )
848 		{
849 			break;
850 		}
851 	}
852 	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
853 
854 	// Success!
855 
856 	outInfo->name 	= ifd->name;
857 	outInfo->ip 	= ifd->interfaceInfo.ip;
858 	err 			= mStatus_NoError;
859 
860 exit:
861 	return( err );
862 }
863 
864 //===========================================================================================================================
865 //	mDNSPlatformInterfaceIDfromInterfaceIndex
866 //===========================================================================================================================
867 
mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS * const inMDNS,mDNSu32 inIndex)868 mDNSexport mDNSInterfaceID	mDNSPlatformInterfaceIDfromInterfaceIndex( mDNS * const inMDNS, mDNSu32 inIndex )
869 {
870 	mDNSInterfaceID		id;
871 
872 	id = mDNSNULL;
873 	if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
874 	{
875 		id = mDNSInterface_LocalOnly;
876 	}
877 	/* uncomment if Windows ever supports P2P
878 	else if( inIndex == kDNSServiceInterfaceIndexP2P )
879 	{
880 		id = mDNSInterface_P2P;
881 	}
882 	*/
883 	else if( inIndex != 0 )
884 	{
885 		mDNSInterfaceData *		ifd;
886 
887 		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
888 		{
889 			if( ( ifd->scopeID == inIndex ) && ifd->interfaceInfo.InterfaceActive )
890 			{
891 				id = ifd->interfaceInfo.InterfaceID;
892 				break;
893 			}
894 		}
895 		check( ifd );
896 	}
897 	return( id );
898 }
899 
900 //===========================================================================================================================
901 //	mDNSPlatformInterfaceIndexfromInterfaceID
902 //===========================================================================================================================
903 
mDNSPlatformInterfaceIndexfromInterfaceID(mDNS * const inMDNS,mDNSInterfaceID inID,mDNSBool suppressNetworkChange)904 mDNSexport mDNSu32	mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSBool suppressNetworkChange )
905 {
906 	mDNSu32		index;
907 	(void) suppressNetworkChange; // Unused
908 
909 	index = 0;
910 	if( inID == mDNSInterface_LocalOnly )
911 	{
912 		index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
913 	}
914 	/* uncomment if Windows ever supports P2P
915 	else if( inID == mDNSInterface_P2P )
916 	{
917 		index = (mDNSu32) kDNSServiceInterfaceIndexP2P;
918 	}
919 	*/
920 	else if( inID )
921 	{
922 		mDNSInterfaceData *		ifd;
923 
924 		// Search active interfaces.
925 		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
926 		{
927 			if( (mDNSInterfaceID) ifd == inID )
928 			{
929 				index = ifd->scopeID;
930 				break;
931 			}
932 		}
933 
934 		// Search inactive interfaces too so remove events for inactive interfaces report the old interface index.
935 
936 		if( !ifd )
937 		{
938 			for( ifd = inMDNS->p->inactiveInterfaceList; ifd; ifd = ifd->next )
939 			{
940 				if( (mDNSInterfaceID) ifd == inID )
941 				{
942 					index = ifd->scopeID;
943 					break;
944 				}
945 			}
946 		}
947 		check( ifd );
948 	}
949 	return( index );
950 }
951 
952 
953 //===========================================================================================================================
954 //	mDNSPlatformTCPSocket
955 //===========================================================================================================================
956 
957 TCPSocket *
mDNSPlatformTCPSocket(mDNS * const m,TCPSocketFlags flags,mDNSIPPort * port)958 mDNSPlatformTCPSocket
959 	(
960 	mDNS			* const m,
961 	TCPSocketFlags		flags,
962 	mDNSIPPort			*	port
963 	)
964 {
965 	TCPSocket *		sock    = NULL;
966 	u_long				on		= 1;  // "on" for setsockopt
967 	struct sockaddr_in	saddr;
968 	int					len;
969 	mStatus				err		= mStatus_NoError;
970 
971 	DEBUG_UNUSED( m );
972 
973 	require_action( flags == 0, exit, err = mStatus_UnsupportedErr );
974 
975 	// Setup connection data object
976 
977 	sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
978 	require_action( sock, exit, err = mStatus_NoMemoryErr );
979 	mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
980 	sock->fd		= INVALID_SOCKET;
981 	sock->flags		= flags;
982 	sock->m			= m;
983 
984 	mDNSPlatformMemZero(&saddr, sizeof(saddr));
985 	saddr.sin_family		= AF_INET;
986 	saddr.sin_addr.s_addr	= htonl( INADDR_ANY );
987 	saddr.sin_port			= port->NotAnInteger;
988 
989 	// Create the socket
990 
991 	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
992 	err = translate_errno( sock->fd != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
993 	require_noerr( err, exit );
994 
995 	// bind
996 
997 	err = bind( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr )  );
998 	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
999 	require_noerr( err, exit );
1000 
1001 	// Set it to be non-blocking
1002 
1003 	err = ioctlsocket( sock->fd, FIONBIO, &on );
1004 	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
1005 	require_noerr( err, exit );
1006 
1007 	// Get port number
1008 
1009 	mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
1010 	len = sizeof( saddr );
1011 
1012 	err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
1013 	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
1014 	require_noerr( err, exit );
1015 
1016 	port->NotAnInteger = saddr.sin_port;
1017 
1018 exit:
1019 
1020 	if ( err && sock )
1021 	{
1022 		TCPFreeSocket( sock );
1023 		sock = mDNSNULL;
1024 	}
1025 
1026 	return sock;
1027 }
1028 
1029 //===========================================================================================================================
1030 //	mDNSPlatformTCPConnect
1031 //===========================================================================================================================
1032 
1033 mStatus
mDNSPlatformTCPConnect(TCPSocket * sock,const mDNSAddr * inDstIP,mDNSOpaque16 inDstPort,domainname * hostname,mDNSInterfaceID inInterfaceID,TCPConnectionCallback inCallback,void * inContext)1034 mDNSPlatformTCPConnect
1035 	(
1036 	TCPSocket			*	sock,
1037 	const mDNSAddr		*	inDstIP,
1038 	mDNSOpaque16 			inDstPort,
1039 	domainname          *   hostname,
1040 	mDNSInterfaceID			inInterfaceID,
1041 	TCPConnectionCallback	inCallback,
1042 	void *					inContext
1043 	)
1044 {
1045 	struct sockaddr_in	saddr;
1046 	mStatus				err		= mStatus_NoError;
1047 
1048 	DEBUG_UNUSED( inInterfaceID );
1049 	( void ) hostname;
1050 
1051 	if ( inDstIP->type != mDNSAddrType_IPv4 )
1052 	{
1053 		LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
1054 		return mStatus_UnknownErr;
1055 	}
1056 
1057 	// Setup connection data object
1058 
1059 	sock->readEventHandler	= TCPCanRead;
1060 	sock->userCallback		= inCallback;
1061 	sock->userContext		= inContext;
1062 
1063 	mDNSPlatformMemZero(&saddr, sizeof(saddr));
1064 	saddr.sin_family	= AF_INET;
1065 	saddr.sin_port		= inDstPort.NotAnInteger;
1066 	memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
1067 
1068 	// Try and do connect
1069 
1070 	err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
1071 	require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
1072 	sock->connected	= !err ? TRUE : FALSE;
1073 
1074 	if ( sock->connected )
1075 	{
1076 		err = TCPAddSocket( sock->m, sock );
1077 		require_noerr( err, exit );
1078 	}
1079 	else
1080 	{
1081 		require_action( sock->m->p->registerWaitableEventFunc != NULL, exit, err = mStatus_ConnFailed );
1082 
1083 		sock->connectEvent	= CreateEvent( NULL, FALSE, FALSE, NULL );
1084 		err = translate_errno( sock->connectEvent, GetLastError(), mStatus_UnknownErr );
1085 		require_noerr( err, exit );
1086 
1087 		err = WSAEventSelect( sock->fd, sock->connectEvent, FD_CONNECT );
1088 		require_noerr( err, exit );
1089 
1090 		err = sock->m->p->registerWaitableEventFunc( sock->m, sock->connectEvent, sock, TCPDidConnect );
1091 		require_noerr( err, exit );
1092 	}
1093 
1094 exit:
1095 
1096 	if ( !err )
1097 	{
1098 		err = sock->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
1099 	}
1100 
1101 	return err;
1102 }
1103 
1104 //===========================================================================================================================
1105 //	mDNSPlatformTCPAccept
1106 //===========================================================================================================================
1107 
1108 mDNSexport
mDNSPlatformTCPAccept(TCPSocketFlags flags,int fd)1109 mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
1110 	{
1111 	TCPSocket	*	sock = NULL;
1112 	mStatus							err = mStatus_NoError;
1113 
1114 	require_action( !flags, exit, err = mStatus_UnsupportedErr );
1115 
1116 	sock = malloc( sizeof( TCPSocket ) );
1117 	require_action( sock, exit, err = mStatus_NoMemoryErr );
1118 
1119 	mDNSPlatformMemZero( sock, sizeof( *sock ) );
1120 
1121 	sock->fd	= fd;
1122 	sock->flags = flags;
1123 
1124 exit:
1125 
1126 	if ( err && sock )
1127 	{
1128 		free( sock );
1129 		sock = NULL;
1130 	}
1131 
1132 	return sock;
1133 	}
1134 
1135 
1136 //===========================================================================================================================
1137 //	mDNSPlatformTCPCloseConnection
1138 //===========================================================================================================================
1139 
mDNSPlatformTCPCloseConnection(TCPSocket * sock)1140 mDNSexport void	mDNSPlatformTCPCloseConnection( TCPSocket *sock )
1141 {
1142 	check( sock );
1143 
1144 	if ( sock->connectEvent && sock->m->p->unregisterWaitableEventFunc )
1145 	{
1146 		sock->m->p->unregisterWaitableEventFunc( sock->m, sock->connectEvent );
1147 	}
1148 
1149 	if ( sock->fd != INVALID_SOCKET )
1150 	{
1151 		TCPCloseSocket( sock );
1152 
1153 		QueueUserAPC( ( PAPCFUNC ) TCPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
1154 	}
1155 }
1156 
1157 
1158 //===========================================================================================================================
1159 //	mDNSPlatformReadTCP
1160 //===========================================================================================================================
1161 
mDNSPlatformReadTCP(TCPSocket * sock,void * inBuffer,unsigned long inBufferSize,mDNSBool * closed)1162 mDNSexport long	mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
1163 {
1164 	unsigned long	bytesLeft;
1165 	int				wsaError;
1166 	long			ret;
1167 
1168 	*closed = sock->closed;
1169 	wsaError = sock->lastError;
1170 	ret = -1;
1171 
1172 	if ( *closed )
1173 	{
1174 		ret = 0;
1175 	}
1176 	else if ( sock->lastError == 0 )
1177 	{
1178 		// First check to see if we have any data left in our buffer
1179 
1180 		bytesLeft = ( DWORD ) ( sock->eptr - sock->bptr );
1181 
1182 		if ( bytesLeft )
1183 		{
1184 			unsigned long bytesToCopy = ( bytesLeft < inBufferSize ) ? bytesLeft : inBufferSize;
1185 
1186 			memcpy( inBuffer, sock->bptr, bytesToCopy );
1187 			sock->bptr += bytesToCopy;
1188 
1189 			if ( !sock->overlapped.pending && ( sock->bptr == sock->eptr ) )
1190 			{
1191 				sock->bptr = sock->bbuf;
1192 				sock->eptr = sock->bbuf;
1193 			}
1194 
1195 			ret = bytesToCopy;
1196 		}
1197 		else
1198 		{
1199 			wsaError = WSAEWOULDBLOCK;
1200 		}
1201 	}
1202 
1203 	// Always set the last winsock error, so that we don't inadvertently use a previous one
1204 
1205 	WSASetLastError( wsaError );
1206 
1207 	return ret;
1208 }
1209 
1210 
1211 //===========================================================================================================================
1212 //	mDNSPlatformWriteTCP
1213 //===========================================================================================================================
1214 
mDNSPlatformWriteTCP(TCPSocket * sock,const char * inMsg,unsigned long inMsgSize)1215 mDNSexport long	mDNSPlatformWriteTCP( TCPSocket *sock, const char *inMsg, unsigned long inMsgSize )
1216 {
1217 	int			nsent;
1218 	OSStatus	err;
1219 
1220 	nsent = send( sock->fd, inMsg, inMsgSize, 0 );
1221 
1222 	err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
1223 	require_noerr( err, exit );
1224 
1225 	if ( nsent < 0)
1226 	{
1227 		nsent = 0;
1228 	}
1229 
1230 exit:
1231 
1232 	return nsent;
1233 }
1234 
1235 //===========================================================================================================================
1236 //	mDNSPlatformTCPGetFD
1237 //===========================================================================================================================
1238 
mDNSPlatformTCPGetFD(TCPSocket * sock)1239 mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
1240 {
1241 	return ( int ) sock->fd;
1242 }
1243 
1244 
1245 //===========================================================================================================================
1246 //	TCPAddConnection
1247 //===========================================================================================================================
1248 
TCPAddSocket(mDNS * const inMDNS,TCPSocket * sock)1249 mStatus TCPAddSocket( mDNS * const inMDNS, TCPSocket *sock )
1250 {
1251 	mStatus err;
1252 
1253 	( void ) inMDNS;
1254 
1255 	sock->bptr	= sock->bbuf;
1256 	sock->eptr	= sock->bbuf;
1257 	sock->ebuf	= sock->bbuf + sizeof( sock->bbuf );
1258 
1259 	dlog( kDebugLevelChatty, DEBUG_NAME "adding TCPSocket 0x%x:%d\n", sock, sock->fd );
1260 	err = TCPBeginRecv( sock );
1261 	require_noerr( err, exit );
1262 
1263 exit:
1264 
1265 	return err;
1266 }
1267 
1268 
1269 //===========================================================================================================================
1270 //	TCPDidConnect
1271 //===========================================================================================================================
1272 
TCPDidConnect(mDNS * const inMDNS,HANDLE event,void * context)1273 mDNSlocal void TCPDidConnect( mDNS * const inMDNS, HANDLE event, void * context )
1274 {
1275 	TCPSocket * sock = ( TCPSocket* ) context;
1276 	TCPConnectionCallback callback = NULL;
1277 	WSANETWORKEVENTS sockEvent;
1278 	int err = kNoErr;
1279 
1280 	if ( inMDNS->p->unregisterWaitableEventFunc )
1281 	{
1282 		inMDNS->p->unregisterWaitableEventFunc( inMDNS, event );
1283 	}
1284 
1285 	if ( sock )
1286 	{
1287 		callback = ( TCPConnectionCallback ) sock->userCallback;
1288 		err = WSAEnumNetworkEvents( sock->fd, sock->connectEvent, &sockEvent );
1289 		require_noerr( err, exit );
1290 		require_action( sockEvent.lNetworkEvents & FD_CONNECT, exit, err = mStatus_UnknownErr );
1291 		require_action( sockEvent.iErrorCode[ FD_CONNECT_BIT ] == 0, exit, err = sockEvent.iErrorCode[ FD_CONNECT_BIT ] );
1292 
1293 		sock->connected	= mDNStrue;
1294 
1295 		if ( sock->fd != INVALID_SOCKET )
1296 		{
1297 			err = TCPAddSocket( sock->m, sock );
1298 			require_noerr( err, exit );
1299 		}
1300 
1301 		if ( callback )
1302 		{
1303 			callback( sock, sock->userContext, TRUE, 0 );
1304 		}
1305 	}
1306 
1307 exit:
1308 
1309 	if ( err && callback )
1310 	{
1311 		callback( sock, sock->userContext, TRUE, err );
1312 	}
1313 }
1314 
1315 
1316 
1317 //===========================================================================================================================
1318 //	TCPCanRead
1319 //===========================================================================================================================
1320 
TCPCanRead(TCPSocket * sock)1321 mDNSlocal void TCPCanRead( TCPSocket * sock )
1322 {
1323 	TCPConnectionCallback callback = ( TCPConnectionCallback ) sock->userCallback;
1324 
1325 	if ( callback )
1326 	{
1327 		callback( sock, sock->userContext, mDNSfalse, sock->lastError );
1328 	}
1329 }
1330 
1331 
1332 //===========================================================================================================================
1333 //	TCPBeginRecv
1334 //===========================================================================================================================
1335 
TCPBeginRecv(TCPSocket * sock)1336 mDNSlocal mStatus TCPBeginRecv( TCPSocket * sock )
1337 {
1338 	DWORD	bytesReceived	= 0;
1339 	DWORD	flags			= 0;
1340 	mStatus err;
1341 
1342 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, sock->fd );
1343 
1344 	check( !sock->overlapped.pending );
1345 
1346 	ZeroMemory( &sock->overlapped.data, sizeof( sock->overlapped.data ) );
1347 	sock->overlapped.data.hEvent = sock;
1348 
1349 	sock->overlapped.wbuf.buf = ( char* ) sock->eptr;
1350 	sock->overlapped.wbuf.len = ( ULONG) ( sock->ebuf - sock->eptr );
1351 
1352 	err = WSARecv( sock->fd, &sock->overlapped.wbuf, 1, &bytesReceived, &flags, &sock->overlapped.data, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) TCPEndRecv );
1353 	err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), WSAGetLastError(), kUnknownErr );
1354 	require_noerr( err, exit );
1355 
1356 	sock->overlapped.pending = TRUE;
1357 
1358 exit:
1359 
1360 	return err;
1361 }
1362 
1363 
1364 //===========================================================================================================================
1365 //	TCPEndRecv
1366 //===========================================================================================================================
1367 
TCPEndRecv(DWORD error,DWORD bytesTransferred,LPWSAOVERLAPPED overlapped,DWORD flags)1368 mDNSlocal void CALLBACK TCPEndRecv( DWORD error, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
1369 {
1370 	TCPSocket * sock;
1371 
1372 	( void ) flags;
1373 
1374 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: error = %d, bytesTransferred = %d\n", __ROUTINE__, error, bytesTransferred );
1375 	sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
1376 	require_action( sock, exit, error = ( DWORD ) mStatus_BadStateErr );
1377 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, sock->fd );
1378 	sock->overlapped.error				= error;
1379 	sock->overlapped.bytesTransferred	= bytesTransferred;
1380 	check( sock->overlapped.pending );
1381 	sock->overlapped.pending			= FALSE;
1382 
1383 	// Queue this socket
1384 
1385 	AddToTail( &gTCPDispatchableSockets, sock );
1386 
1387 exit:
1388 
1389 	return;
1390 }
1391 
1392 
1393 
1394 //===========================================================================================================================
1395 //	mDNSPlatformUDPSocket
1396 //===========================================================================================================================
1397 
mDNSPlatformUDPSocket(mDNS * const m,const mDNSIPPort requestedport)1398 mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
1399 {
1400 	UDPSocket*	sock	= NULL;
1401 	mDNSIPPort	port	= requestedport;
1402 	mStatus		err		= mStatus_NoError;
1403 	unsigned	i;
1404 
1405 	// Setup connection data object
1406 
1407 	sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
1408 	require_action( sock, exit, err = mStatus_NoMemoryErr );
1409 	memset( sock, 0, sizeof( UDPSocket ) );
1410 
1411 	// Create the socket
1412 
1413 	sock->fd					= INVALID_SOCKET;
1414 	sock->recvMsgPtr			= m->p->unicastSock4.recvMsgPtr;
1415 	sock->addr					= m->p->unicastSock4.addr;
1416 	sock->ifd					= NULL;
1417 	sock->overlapped.pending	= FALSE;
1418 	sock->m						= m;
1419 
1420 	// Try at most 10000 times to get a unique random port
1421 
1422 	for (i=0; i<10000; i++)
1423 	{
1424 		struct sockaddr_in saddr;
1425 
1426 		saddr.sin_family		= AF_INET;
1427 		saddr.sin_addr.s_addr	= 0;
1428 
1429 		// The kernel doesn't do cryptographically strong random port
1430 		// allocation, so we do it ourselves here
1431 
1432         if (mDNSIPPortIsZero(requestedport))
1433 		{
1434 			port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
1435 		}
1436 
1437 		saddr.sin_port = port.NotAnInteger;
1438 
1439         err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->fd );
1440         if (!err) break;
1441 	}
1442 
1443 	require_noerr( err, exit );
1444 
1445 	// Set the port
1446 
1447 	sock->port = port;
1448 
1449 	// Arm the completion routine
1450 
1451 	err = UDPBeginRecv( sock );
1452 	require_noerr( err, exit );
1453 
1454 	// Bookkeeping
1455 
1456 	sock->next		= gUDPSockets;
1457 	gUDPSockets		= sock;
1458 	gUDPNumSockets++;
1459 
1460 exit:
1461 
1462 	if ( err && sock )
1463 	{
1464 		UDPFreeSocket( sock );
1465 		sock = NULL;
1466 	}
1467 
1468 	return sock;
1469 }
1470 
1471 //===========================================================================================================================
1472 //	mDNSPlatformUDPClose
1473 //===========================================================================================================================
1474 
mDNSPlatformUDPClose(UDPSocket * sock)1475 mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
1476 {
1477 	UDPSocket	*	current  = gUDPSockets;
1478 	UDPSocket	*	last = NULL;
1479 
1480 	while ( current )
1481 	{
1482 		if ( current == sock )
1483 		{
1484 			if ( last == NULL )
1485 			{
1486 				gUDPSockets = sock->next;
1487 			}
1488 			else
1489 			{
1490 				last->next = sock->next;
1491 			}
1492 
1493 			// Alertable I/O is great, except not so much when it comes to closing
1494 			// the socket.  Anything that has been previously queued for this socket
1495 			// will stay in the queue after you close the socket.  This is problematic
1496 			// for obvious reasons. So we'll attempt to workaround this by closing
1497 			// the socket which will prevent any further queued packets and then not calling
1498 			// UDPFreeSocket directly, but by queueing it using QueueUserAPC.  The queues
1499 			// are FIFO, so that will execute *after* any other previous items in the queue
1500 			//
1501 			// UDPEndRecv will check if the socket is valid, and if not, it will ignore
1502 			// the packet
1503 
1504 			UDPCloseSocket( sock );
1505 
1506 			QueueUserAPC( ( PAPCFUNC ) UDPFreeSocket, sock->m->p->mainThread, ( ULONG_PTR ) sock );
1507 
1508 			gUDPNumSockets--;
1509 
1510 			break;
1511 		}
1512 
1513 		last	= current;
1514 		current	= current->next;
1515 	}
1516 }
1517 
1518 
1519 //===========================================================================================================================
1520 //	mDNSPlatformSendUDP
1521 //===========================================================================================================================
1522 
1523 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS * const inMDNS,const void * const inMsg,const mDNSu8 * const inMsgEnd,mDNSInterfaceID inInterfaceID,UDPSocket * inSrcSocket,const mDNSAddr * inDstIP,mDNSIPPort inDstPort)1524 	mDNSPlatformSendUDP(
1525 		const mDNS * const			inMDNS,
1526 		const void * const	        inMsg,
1527 		const mDNSu8 * const		inMsgEnd,
1528 		mDNSInterfaceID 			inInterfaceID,
1529 		UDPSocket *					inSrcSocket,
1530 		const mDNSAddr *			inDstIP,
1531 		mDNSIPPort 					inDstPort )
1532 {
1533 	SOCKET						sendingsocket = INVALID_SOCKET;
1534 	mStatus						err = mStatus_NoError;
1535 	mDNSInterfaceData *			ifd = (mDNSInterfaceData*) inInterfaceID;
1536 	struct sockaddr_storage		addr;
1537 	int							n;
1538 
1539 	DEBUG_USE_ONLY( inMDNS );
1540 
1541 	n = (int)( inMsgEnd - ( (const mDNSu8 * const) inMsg ) );
1542 	check( inMDNS );
1543 	check( inMsg );
1544 	check( inMsgEnd );
1545 	check( inDstIP );
1546 
1547 	dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
1548 
1549 	if( inDstIP->type == mDNSAddrType_IPv4 )
1550 	{
1551 		struct sockaddr_in *		sa4;
1552 
1553 		sa4						= (struct sockaddr_in *) &addr;
1554 		sa4->sin_family			= AF_INET;
1555 		sa4->sin_port			= inDstPort.NotAnInteger;
1556 		sa4->sin_addr.s_addr	= inDstIP->ip.v4.NotAnInteger;
1557 		sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
1558 
1559 		if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
1560 	}
1561 	else if( inDstIP->type == mDNSAddrType_IPv6 )
1562 	{
1563 		struct sockaddr_in6 *		sa6;
1564 
1565 		sa6					= (struct sockaddr_in6 *) &addr;
1566 		sa6->sin6_family	= AF_INET6;
1567 		sa6->sin6_port		= inDstPort.NotAnInteger;
1568 		sa6->sin6_flowinfo	= 0;
1569 		sa6->sin6_addr		= *( (struct in6_addr *) &inDstIP->ip.v6 );
1570 		sa6->sin6_scope_id	= 0;	// Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
1571 		sendingsocket		= ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
1572 	}
1573 	else
1574 	{
1575 		dlog( kDebugLevelError, DEBUG_NAME "%s: dst is not an IPv4 or IPv6 address (type=%d)\n", __ROUTINE__, inDstIP->type );
1576 		err = mStatus_BadParamErr;
1577 		goto exit;
1578 	}
1579 
1580 	if (IsValidSocket(sendingsocket))
1581 	{
1582 		n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
1583 		err = translate_errno( n > 0, errno_compat(), kWriteErr );
1584 
1585 		if ( err )
1586 		{
1587 			// Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1588 
1589 			if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
1590 			{
1591 				err = mStatus_TransientErr;
1592 			}
1593 			else
1594 			{
1595 				require_noerr( err, exit );
1596 			}
1597 		}
1598 	}
1599 
1600 exit:
1601 	return( err );
1602 }
1603 
1604 
mDNSPlatformUpdateProxyList(mDNS * const m,const mDNSInterfaceID InterfaceID)1605 mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
1606 	{
1607 	DEBUG_UNUSED( m );
1608 	DEBUG_UNUSED( InterfaceID );
1609 	}
1610 
1611 //===========================================================================================================================
1612 //	mDNSPlatformSendRawPacket
1613 //===========================================================================================================================
1614 
mDNSPlatformSetAllowSleep(mDNS * const m,mDNSBool allowSleep,const char * reason)1615 mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
1616     {
1617     DEBUG_UNUSED( m );
1618 	DEBUG_UNUSED( allowSleep );
1619 	DEBUG_UNUSED( reason );
1620     }
1621 
mDNSPlatformSendRawPacket(const void * const msg,const mDNSu8 * const end,mDNSInterfaceID InterfaceID)1622 mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1623 	{
1624 	DEBUG_UNUSED( msg );
1625 	DEBUG_UNUSED( end );
1626 	DEBUG_UNUSED( InterfaceID );
1627 	}
1628 
mDNSPlatformReceiveRawPacket(const void * const msg,const mDNSu8 * const end,mDNSInterfaceID InterfaceID)1629 mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1630 	{
1631 	DEBUG_UNUSED( msg );
1632 	DEBUG_UNUSED( end );
1633 	DEBUG_UNUSED( InterfaceID );
1634 	}
1635 
mDNSPlatformSetLocalAddressCacheEntry(mDNS * const m,const mDNSAddr * const tpa,const mDNSEthAddr * const tha,mDNSInterfaceID InterfaceID)1636 mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
1637 	{
1638 	DEBUG_UNUSED( m );
1639 	DEBUG_UNUSED( tpa );
1640 	DEBUG_UNUSED( tha );
1641 	DEBUG_UNUSED( InterfaceID );
1642 	}
1643 
mDNSPlatformWriteDebugMsg(const char * msg)1644 mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
1645 	{
1646 	dlog( kDebugLevelInfo, "%s\n", msg );
1647 	}
1648 
mDNSPlatformWriteLogMsg(const char * ident,const char * msg,mDNSLogLevel_t loglevel)1649 mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, mDNSLogLevel_t loglevel )
1650 	{
1651 	extern mDNS mDNSStorage;
1652 	int type;
1653 
1654 	DEBUG_UNUSED( ident );
1655 
1656 	type = EVENTLOG_ERROR_TYPE;
1657 
1658 	switch (loglevel)
1659 	{
1660 		case MDNS_LOG_MSG:       type = EVENTLOG_ERROR_TYPE;		break;
1661 		case MDNS_LOG_OPERATION: type = EVENTLOG_WARNING_TYPE;		break;
1662 		case MDNS_LOG_SPS:       type = EVENTLOG_INFORMATION_TYPE;  break;
1663 		case MDNS_LOG_INFO:      type = EVENTLOG_INFORMATION_TYPE;	break;
1664 		case MDNS_LOG_DEBUG:     type = EVENTLOG_INFORMATION_TYPE;	break;
1665 		default:
1666 			fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
1667 			fflush(stderr);
1668 			}
1669 
1670 	mDNSStorage.p->reportStatusFunc( type, msg );
1671 	dlog( kDebugLevelInfo, "%s\n", msg );
1672 	}
1673 
mDNSPlatformSourceAddrForDest(mDNSAddr * const src,const mDNSAddr * const dst)1674 mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
1675 	{
1676 	DEBUG_UNUSED( src );
1677 	DEBUG_UNUSED( dst );
1678 	}
1679 
1680 //===========================================================================================================================
1681 //	mDNSPlatformTLSSetupCerts
1682 //===========================================================================================================================
1683 
1684 mDNSexport mStatus
mDNSPlatformTLSSetupCerts(void)1685 mDNSPlatformTLSSetupCerts(void)
1686 {
1687 	return mStatus_UnsupportedErr;
1688 }
1689 
1690 //===========================================================================================================================
1691 //	mDNSPlatformTLSTearDownCerts
1692 //===========================================================================================================================
1693 
1694 mDNSexport void
mDNSPlatformTLSTearDownCerts(void)1695 mDNSPlatformTLSTearDownCerts(void)
1696 {
1697 }
1698 
1699 //===========================================================================================================================
1700 //	mDNSPlatformSetDNSConfig
1701 //===========================================================================================================================
1702 
1703 mDNSlocal void SetDNSServers( mDNS *const m );
1704 mDNSlocal void SetSearchDomainList( void );
1705 
mDNSPlatformSetDNSConfig(mDNS * const m,mDNSBool setservers,mDNSBool setsearch,domainname * const fqdn,DNameListElem ** regDomains,DNameListElem ** browseDomains)1706 mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains)
1707 {
1708 	if (setservers) SetDNSServers(m);
1709 	if (setsearch) SetSearchDomainList();
1710 
1711 	if ( fqdn )
1712 	{
1713 		GetDDNSFQDN( fqdn );
1714 	}
1715 
1716 	if ( browseDomains )
1717 	{
1718 		GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
1719 	}
1720 
1721 	if ( regDomains )
1722 	{
1723 		GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
1724 	}
1725 }
1726 
1727 
1728 //===========================================================================================================================
1729 //	mDNSPlatformDynDNSHostNameStatusChanged
1730 //===========================================================================================================================
1731 
1732 mDNSexport void
mDNSPlatformDynDNSHostNameStatusChanged(const domainname * const dname,const mStatus status)1733 mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
1734 {
1735 	char		uname[MAX_ESCAPED_DOMAIN_NAME];
1736 	BYTE		bStatus;
1737 	LPCTSTR		name;
1738 	HKEY		key = NULL;
1739 	mStatus		err;
1740 	char	*	p;
1741 
1742 	ConvertDomainNameToCString(dname, uname);
1743 
1744 	p = uname;
1745 
1746 	while (*p)
1747 	{
1748 		*p = (char) tolower(*p);
1749 		if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
1750 		p++;
1751 	}
1752 
1753 	check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
1754 	name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
1755 	err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
1756 	require_noerr( err, exit );
1757 
1758 	bStatus = ( status ) ? 0 : 1;
1759 	err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
1760 	require_noerr( err, exit );
1761 
1762 exit:
1763 
1764 	if ( key )
1765 	{
1766 		RegCloseKey( key );
1767 	}
1768 
1769 	return;
1770 }
1771 
1772 
FreeEtcHosts(mDNS * const m,AuthRecord * const rr,mStatus result)1773 mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
1774     {
1775     (void)m;  // unused
1776     (void)rr;
1777     (void)result;
1778     }
1779 
1780 
1781 
1782 //===========================================================================================================================
1783 //	SetDomainSecrets
1784 //===========================================================================================================================
1785 
1786 // This routine needs to be called whenever the system secrets database changes.
1787 // We call it from DynDNSConfigDidChange and mDNSPlatformInit
1788 
1789 void
SetDomainSecrets(mDNS * const m)1790 SetDomainSecrets( mDNS * const m )
1791 {
1792 	DomainAuthInfo *ptr;
1793 	domainname		fqdn;
1794 	DNameListElem * regDomains = NULL;
1795 
1796 	// Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
1797 	// In the case where the user simultaneously removes their DDNS host name and the key
1798 	// for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
1799 	// server before it loses access to the necessary key. Otherwise, we'd leave orphaned
1800 	// address records behind that we no longer have permission to delete.
1801 
1802 	for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
1803 		ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
1804 
1805 	GetDDNSFQDN( &fqdn );
1806 
1807 	if ( fqdn.c[ 0 ] )
1808 	{
1809 		SetDomainSecret( m, &fqdn );
1810 	}
1811 
1812 	GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
1813 
1814 	while ( regDomains )
1815 	{
1816 		DNameListElem * current = regDomains;
1817 		SetDomainSecret( m, &current->name );
1818 		regDomains = regDomains->next;
1819 		free( current );
1820 	}
1821 }
1822 
1823 
1824 //===========================================================================================================================
1825 //	SetSearchDomainList
1826 //===========================================================================================================================
1827 
1828 mDNSlocal void SetDomainFromDHCP( void );
1829 mDNSlocal void SetReverseMapSearchDomainList( void );
1830 
1831 mDNSlocal void
SetSearchDomainList(void)1832 SetSearchDomainList( void )
1833 {
1834 	char			*	searchList	= NULL;
1835 	DWORD				searchListLen;
1836 	//DNameListElem	*	head = NULL;
1837 	//DNameListElem	*	current = NULL;
1838 	char			*	tok;
1839 	HKEY				key;
1840 	mStatus				err;
1841 
1842 	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key );
1843 	require_noerr( err, exit );
1844 
1845 	err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
1846 	require_noerr( err, exit );
1847 
1848 	// Windows separates the search domains with ','
1849 
1850 	tok = strtok( searchList, "," );
1851 	while ( tok )
1852 	{
1853 		if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
1854 			mDNS_AddSearchDomain_CString(tok, mDNSNULL);
1855 		tok = strtok( NULL, "," );
1856 	}
1857 
1858 exit:
1859 
1860 	if ( searchList )
1861 	{
1862 		free( searchList );
1863 	}
1864 
1865 	if ( key )
1866 	{
1867 		RegCloseKey( key );
1868 	}
1869 
1870 	SetDomainFromDHCP();
1871 	SetReverseMapSearchDomainList();
1872 }
1873 
1874 
1875 //===========================================================================================================================
1876 //	SetReverseMapSearchDomainList
1877 //===========================================================================================================================
1878 
1879 mDNSlocal void
SetReverseMapSearchDomainList(void)1880 SetReverseMapSearchDomainList( void )
1881 {
1882 	struct ifaddrs	*	ifa;
1883 
1884 	ifa = myGetIfAddrs( 1 );
1885 	while (ifa)
1886 	{
1887 		mDNSAddr addr;
1888 
1889 		if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
1890 		{
1891 			mDNSAddr	netmask;
1892 			char		buffer[256];
1893 
1894 			if (!SetupAddr(&netmask, ifa->ifa_netmask))
1895 			{
1896 				sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
1897                                                              addr.ip.v4.b[2] & netmask.ip.v4.b[2],
1898                                                              addr.ip.v4.b[1] & netmask.ip.v4.b[1],
1899                                                              addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
1900 				mDNS_AddSearchDomain_CString(buffer, mDNSNULL);
1901 			}
1902 		}
1903 
1904 		ifa = ifa->ifa_next;
1905 	}
1906 
1907 	return;
1908 }
1909 
1910 
1911 //===========================================================================================================================
1912 //	SetDNSServers
1913 //===========================================================================================================================
1914 
1915 mDNSlocal void
SetDNSServers(mDNS * const m)1916 SetDNSServers( mDNS *const m )
1917 {
1918 	PIP_PER_ADAPTER_INFO	pAdapterInfo	=	NULL;
1919 	FIXED_INFO			*	fixedInfo	= NULL;
1920 	ULONG					bufLen		= 0;
1921 	IP_ADDR_STRING		*	dnsServerList;
1922 	IP_ADDR_STRING		*	ipAddr;
1923 	DWORD					index;
1924 	int						i			= 0;
1925 	mStatus					err			= kUnknownErr;
1926 
1927 	// Get the primary interface.
1928 
1929 	index = GetPrimaryInterface();
1930 
1931 	// This should have the interface index of the primary index.  Fall back in cases where
1932 	// it can't be determined.
1933 
1934 	if ( index )
1935 	{
1936 		bufLen = 0;
1937 
1938 		for ( i = 0; i < 100; i++ )
1939 		{
1940 			err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
1941 
1942 			if ( err != ERROR_BUFFER_OVERFLOW )
1943 			{
1944 				break;
1945 			}
1946 
1947 			pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
1948 			require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
1949 		}
1950 
1951 		require_noerr( err, exit );
1952 
1953 		dnsServerList = &pAdapterInfo->DnsServerList;
1954 	}
1955 	else
1956 	{
1957 		bufLen = sizeof( FIXED_INFO );
1958 
1959 		for ( i = 0; i < 100; i++ )
1960 		{
1961 			if ( fixedInfo )
1962 			{
1963 				GlobalFree( fixedInfo );
1964 				fixedInfo = NULL;
1965 			}
1966 
1967 			fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
1968 			require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
1969 
1970 			err = GetNetworkParams( fixedInfo, &bufLen );
1971 
1972 			if ( err != ERROR_BUFFER_OVERFLOW )
1973 			{
1974 				break;
1975 			}
1976 		}
1977 
1978 		require_noerr( err, exit );
1979 
1980 		dnsServerList = &fixedInfo->DnsServerList;
1981 	}
1982 
1983 	for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
1984 	{
1985 		mDNSAddr addr;
1986 		err = StringToAddress( &addr, ipAddr->IpAddress.String );
1987 		if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort, mDNSfalse, 0);
1988 	}
1989 
1990 exit:
1991 
1992 	if ( pAdapterInfo )
1993 	{
1994 		free( pAdapterInfo );
1995 	}
1996 
1997 	if ( fixedInfo )
1998 	{
1999 		GlobalFree( fixedInfo );
2000 	}
2001 }
2002 
2003 
2004 //===========================================================================================================================
2005 //	SetDomainFromDHCP
2006 //===========================================================================================================================
2007 
2008 mDNSlocal void
SetDomainFromDHCP(void)2009 SetDomainFromDHCP( void )
2010 {
2011 	int					i			= 0;
2012 	IP_ADAPTER_INFO *	pAdapterInfo;
2013 	IP_ADAPTER_INFO *	pAdapter;
2014 	DWORD				bufLen;
2015 	DWORD				index;
2016 	HKEY				key = NULL;
2017 	LPSTR				domain = NULL;
2018 	DWORD				dwSize;
2019 	mStatus				err = mStatus_NoError;
2020 
2021 	pAdapterInfo	= NULL;
2022 
2023 	for ( i = 0; i < 100; i++ )
2024 	{
2025 		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
2026 
2027 		if ( err != ERROR_BUFFER_OVERFLOW )
2028 		{
2029 			break;
2030 		}
2031 
2032 		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
2033 		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
2034 	}
2035 
2036 	require_noerr( err, exit );
2037 
2038 	index = GetPrimaryInterface();
2039 
2040 	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
2041 	{
2042 		if ( pAdapter->IpAddressList.IpAddress.String &&
2043 		     pAdapter->IpAddressList.IpAddress.String[0] &&
2044 		     pAdapter->GatewayList.IpAddress.String &&
2045 		     pAdapter->GatewayList.IpAddress.String[0] &&
2046 		     ( !index || ( pAdapter->Index == index ) ) )
2047 		{
2048 			// Found one that will work
2049 
2050 			char keyName[1024];
2051 
2052 			_snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
2053 
2054 			err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
2055 			require_noerr( err, exit );
2056 
2057 			err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
2058 			check_noerr( err );
2059 
2060 			if ( !domain || !domain[0] )
2061 			{
2062 				if ( domain )
2063 				{
2064 					free( domain );
2065 					domain = NULL;
2066 				}
2067 
2068 				err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
2069 				check_noerr( err );
2070 			}
2071 
2072 			if ( domain && domain[0] ) mDNS_AddSearchDomain_CString(domain, mDNSNULL);
2073 
2074 			break;
2075 		}
2076 	}
2077 
2078 exit:
2079 
2080 	if ( pAdapterInfo )
2081 	{
2082 		free( pAdapterInfo );
2083 	}
2084 
2085 	if ( domain )
2086 	{
2087 		free( domain );
2088 	}
2089 
2090 	if ( key )
2091 	{
2092 		RegCloseKey( key );
2093 	}
2094 }
2095 
2096 
2097 //===========================================================================================================================
2098 //	mDNSPlatformGetPrimaryInterface
2099 //===========================================================================================================================
2100 
2101 mDNSexport mStatus
mDNSPlatformGetPrimaryInterface(mDNS * const m,mDNSAddr * v4,mDNSAddr * v6,mDNSAddr * router)2102 mDNSPlatformGetPrimaryInterface( mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router )
2103 {
2104 	IP_ADAPTER_INFO *	pAdapterInfo;
2105 	IP_ADAPTER_INFO *	pAdapter;
2106 	DWORD				bufLen;
2107 	int					i;
2108 	BOOL				found;
2109 	DWORD				index;
2110 	mStatus				err = mStatus_NoError;
2111 
2112 	DEBUG_UNUSED( m );
2113 
2114 	*v6 = zeroAddr;
2115 
2116 	pAdapterInfo	= NULL;
2117 	bufLen			= 0;
2118 	found			= FALSE;
2119 
2120 	for ( i = 0; i < 100; i++ )
2121 	{
2122 		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
2123 
2124 		if ( err != ERROR_BUFFER_OVERFLOW )
2125 		{
2126 			break;
2127 		}
2128 
2129 		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
2130 		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
2131 	}
2132 
2133 	require_noerr( err, exit );
2134 
2135 	index = GetPrimaryInterface();
2136 
2137 	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
2138 	{
2139 		if ( pAdapter->IpAddressList.IpAddress.String &&
2140 		     pAdapter->IpAddressList.IpAddress.String[0] &&
2141 		     pAdapter->GatewayList.IpAddress.String &&
2142 		     pAdapter->GatewayList.IpAddress.String[0] &&
2143 		     ( StringToAddress( v4, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
2144 		     ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
2145 		     ( !index || ( pAdapter->Index == index ) ) )
2146 		{
2147 			// Found one that will work
2148 
2149 			if ( pAdapter->AddressLength == sizeof( m->PrimaryMAC ) )
2150 			{
2151 				memcpy( &m->PrimaryMAC, pAdapter->Address, pAdapter->AddressLength );
2152 			}
2153 
2154 			found = TRUE;
2155 			break;
2156 		}
2157 	}
2158 
2159 exit:
2160 
2161 	if ( pAdapterInfo )
2162 	{
2163 		free( pAdapterInfo );
2164 	}
2165 
2166 	return err;
2167 }
2168 
mDNSPlatformSendWakeupPacket(mDNS * const m,mDNSInterfaceID InterfaceID,char * EthAddr,char * IPAddr,int iteration)2169 mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
2170 	{
2171 	(void) m;
2172 	(void) InterfaceID;
2173 	(void) EthAddr;
2174 	(void) IPAddr;
2175 	(void) iteration;
2176 	}
2177 
mDNSPlatformValidRecordForInterface(AuthRecord * rr,const NetworkInterfaceInfo * intf)2178 mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
2179 	{
2180 	(void) rr;
2181 	(void) intf;
2182 
2183 	return 1;
2184 	}
2185 
2186 
2187 #if 0
2188 #pragma mark -
2189 #endif
2190 
2191 //===========================================================================================================================
2192 //	debugf_
2193 //===========================================================================================================================
2194 #if( MDNS_DEBUGMSGS )
debugf_(const char * inFormat,...)2195 mDNSexport void	debugf_( const char *inFormat, ... )
2196 {
2197 	char		buffer[ 512 ];
2198     va_list		args;
2199     mDNSu32		length;
2200 
2201 	va_start( args, inFormat );
2202 	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
2203 	va_end( args );
2204 
2205 	dlog( kDebugLevelInfo, "%s\n", buffer );
2206 }
2207 #endif
2208 
2209 //===========================================================================================================================
2210 //	verbosedebugf_
2211 //===========================================================================================================================
2212 
2213 #if( MDNS_DEBUGMSGS > 1 )
verbosedebugf_(const char * inFormat,...)2214 mDNSexport void	verbosedebugf_( const char *inFormat, ... )
2215 {
2216 	char		buffer[ 512 ];
2217     va_list		args;
2218     mDNSu32		length;
2219 
2220 	va_start( args, inFormat );
2221 	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
2222 	va_end( args );
2223 
2224 	dlog( kDebugLevelVerbose, "%s\n", buffer );
2225 }
2226 #endif
2227 
2228 
2229 #if 0
2230 #pragma mark -
2231 #pragma mark == Platform Internals  ==
2232 #endif
2233 
2234 
2235 //===========================================================================================================================
2236 //	SetupNiceName
2237 //===========================================================================================================================
2238 
SetupNiceName(mDNS * const inMDNS)2239 mStatus	SetupNiceName( mDNS * const inMDNS )
2240 {
2241 	HKEY		descKey = NULL;
2242 	char		utf8[ 256 ];
2243 	LPCTSTR		s;
2244 	LPWSTR		joinName;
2245 	NETSETUP_JOIN_STATUS joinStatus;
2246 	mStatus		err = 0;
2247 	DWORD		namelen;
2248 	BOOL		ok;
2249 
2250 	check( inMDNS );
2251 
2252 	// Set up the nice name.
2253 	utf8[0] = '\0';
2254 
2255 	// First try and open the registry key that contains the computer description value
2256 	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
2257 	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
2258 	check_translated_errno( err == 0, errno_compat(), kNameErr );
2259 
2260 	if ( !err )
2261 	{
2262 		TCHAR	desc[256];
2263 		DWORD	descSize = sizeof( desc );
2264 
2265 		// look for the computer description
2266 		err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
2267 
2268 		if ( !err )
2269 		{
2270 			err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
2271 		}
2272 
2273 		if ( err )
2274 		{
2275 			utf8[ 0 ] = '\0';
2276 		}
2277 	}
2278 
2279 	// if we can't find it in the registry, then use the hostname of the machine
2280 	if ( err || ( utf8[ 0 ] == '\0' ) )
2281 	{
2282 		TCHAR hostname[256];
2283 
2284 		namelen = sizeof( hostname ) / sizeof( TCHAR );
2285 
2286 		ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
2287 		err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
2288 		check_noerr( err );
2289 
2290 		if( !err )
2291 		{
2292 			err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
2293 		}
2294 
2295 		if ( err )
2296 		{
2297 			utf8[ 0 ] = '\0';
2298 		}
2299 	}
2300 
2301 	// if we can't get the hostname
2302 	if ( err || ( utf8[ 0 ] == '\0' ) )
2303 	{
2304 		// Invalidate name so fall back to a default name.
2305 
2306 		strcpy( utf8, kMDNSDefaultName );
2307 	}
2308 
2309 	utf8[ sizeof( utf8 ) - 1 ]	= '\0';
2310 	inMDNS->nicelabel.c[ 0 ]	= (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
2311 	memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
2312 
2313 	dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
2314 
2315 	if ( descKey )
2316 	{
2317 		RegCloseKey( descKey );
2318 	}
2319 
2320 	ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
2321 	ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
2322 
2323 	namelen = sizeof( inMDNS->p->nbname );
2324 	ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
2325 	check( ok );
2326 	if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
2327 
2328 	err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
2329 	check ( err == NERR_Success );
2330 	if ( err == NERR_Success )
2331 	{
2332 		if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
2333 		{
2334 			err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
2335 			check( !err );
2336 			if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
2337 		}
2338 
2339 		NetApiBufferFree( joinName );
2340 		joinName = NULL;
2341 	}
2342 
2343 	err = 0;
2344 
2345 	return( err );
2346 }
2347 
2348 //===========================================================================================================================
2349 //	SetupHostName
2350 //===========================================================================================================================
2351 
SetupHostName(mDNS * const inMDNS)2352 mDNSlocal mStatus	SetupHostName( mDNS * const inMDNS )
2353 {
2354 	mStatus		err = 0;
2355 	char		tempString[ 256 ];
2356 	DWORD		tempStringLen;
2357 	domainlabel tempLabel;
2358 	BOOL		ok;
2359 
2360 	check( inMDNS );
2361 
2362 	// Set up the nice name.
2363 	tempString[ 0 ] = '\0';
2364 
2365 	// use the hostname of the machine
2366 	tempStringLen = sizeof( tempString );
2367 	ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
2368 	err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
2369 	check_noerr( err );
2370 
2371 	// if we can't get the hostname
2372 	if( err || ( tempString[ 0 ] == '\0' ) )
2373 	{
2374 		// Invalidate name so fall back to a default name.
2375 
2376 		strcpy( tempString, kMDNSDefaultName );
2377 	}
2378 
2379 	tempString[ sizeof( tempString ) - 1 ] = '\0';
2380 	tempLabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL );
2381 	memcpy( &tempLabel.c[ 1 ], tempString, tempLabel.c[ 0 ] );
2382 
2383 	// Set up the host name.
2384 
2385 	ConvertUTF8PstringToRFC1034HostLabel( tempLabel.c, &inMDNS->hostlabel );
2386 	if( inMDNS->hostlabel.c[ 0 ] == 0 )
2387 	{
2388 		// Nice name has no characters that are representable as an RFC1034 name (e.g. Japanese) so use the default.
2389 
2390 		MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
2391 	}
2392 
2393 	check( inMDNS->hostlabel.c[ 0 ] != 0 );
2394 
2395 	mDNS_SetFQDN( inMDNS );
2396 
2397 	dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
2398 
2399 	return( err );
2400 }
2401 
2402 //===========================================================================================================================
2403 //	SetupName
2404 //===========================================================================================================================
2405 
SetupName(mDNS * const inMDNS)2406 mDNSlocal mStatus	SetupName( mDNS * const inMDNS )
2407 {
2408 	mStatus		err = 0;
2409 
2410 	check( inMDNS );
2411 
2412 	err = SetupNiceName( inMDNS );
2413 	check_noerr( err );
2414 
2415 	err = SetupHostName( inMDNS );
2416 	check_noerr( err );
2417 
2418 	return err;
2419 }
2420 
2421 
2422 //===========================================================================================================================
2423 //	SetupInterfaceList
2424 //===========================================================================================================================
2425 
SetupInterfaceList(mDNS * const inMDNS)2426 mStatus	SetupInterfaceList( mDNS * const inMDNS )
2427 {
2428 	mStatus						err;
2429 	mDNSInterfaceData **		next;
2430 	mDNSInterfaceData *			ifd;
2431 	struct ifaddrs *			addrs;
2432 	struct ifaddrs *			p;
2433 	struct ifaddrs *			loopbackv4;
2434 	struct ifaddrs *			loopbackv6;
2435 	u_int						flagMask;
2436 	u_int						flagTest;
2437 	mDNSBool					foundv4;
2438 	mDNSBool					foundv6;
2439 	mDNSBool					foundUnicastSock4DestAddr;
2440 	mDNSBool					foundUnicastSock6DestAddr;
2441 
2442 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
2443 	check( inMDNS );
2444 	check( inMDNS->p );
2445 
2446 	inMDNS->p->registeredLoopback4	= mDNSfalse;
2447 	inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
2448 	addrs							= NULL;
2449 	foundv4							= mDNSfalse;
2450 	foundv6							= mDNSfalse;
2451 	foundUnicastSock4DestAddr		= mDNSfalse;
2452 	foundUnicastSock6DestAddr		= mDNSfalse;
2453 
2454 	// Tear down any existing interfaces that may be set up.
2455 
2456 	TearDownInterfaceList( inMDNS );
2457 
2458 	// Set up the name of this machine.
2459 
2460 	err = SetupName( inMDNS );
2461 	check_noerr( err );
2462 
2463 	// Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
2464 	// can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
2465 
2466 	err = getifaddrs( &addrs );
2467 	require_noerr( err, exit );
2468 
2469 	loopbackv4	= NULL;
2470 	loopbackv6	= NULL;
2471 	next		= &inMDNS->p->interfaceList;
2472 
2473 	flagMask = IFF_UP | IFF_MULTICAST;
2474 	flagTest = IFF_UP | IFF_MULTICAST;
2475 
2476 #if( MDNS_WINDOWS_ENABLE_IPV4 )
2477 	for( p = addrs; p; p = p->ifa_next )
2478 	{
2479 		if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2480 		{
2481 			continue;
2482 		}
2483 		if( p->ifa_flags & IFF_LOOPBACK )
2484 		{
2485 			if( !loopbackv4 )
2486 			{
2487 				loopbackv4 = p;
2488 			}
2489 			continue;
2490 		}
2491 		dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n",
2492 			p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
2493 
2494 		err = SetupInterface( inMDNS, p, &ifd );
2495 		require_noerr( err, exit );
2496 
2497 		// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
2498 		// register him, but we also want to note that we haven't found a v4 interface
2499 		// so that we register loopback so same host operations work
2500 
2501 		if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
2502 		{
2503 			foundv4 = mDNStrue;
2504 		}
2505 
2506 		if ( p->ifa_dhcpEnabled && ( p->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
2507 		{
2508 			inMDNS->p->nextDHCPLeaseExpires = p->ifa_dhcpLeaseExpires;
2509 		}
2510 
2511 		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
2512 		// of determing the destination address of a packet that is sent to us.
2513 		// For multicast packets, that's easy to determine.  But for the unicast
2514 		// sockets, we'll fake it by taking the address of the first interface
2515 		// that is successfully setup.
2516 
2517 		if ( !foundUnicastSock4DestAddr )
2518 		{
2519 			inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
2520 			foundUnicastSock4DestAddr = TRUE;
2521 		}
2522 
2523 		*next = ifd;
2524 		next  = &ifd->next;
2525 		++inMDNS->p->interfaceCount;
2526 	}
2527 #endif
2528 
2529 	// Set up IPv6 interface(s) after IPv4 is set up (see IPv4 notes above for reasoning).
2530 
2531 #if( MDNS_WINDOWS_ENABLE_IPV6 )
2532 	for( p = addrs; p; p = p->ifa_next )
2533 	{
2534 		if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET6 ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2535 		{
2536 			continue;
2537 		}
2538 		if( p->ifa_flags & IFF_LOOPBACK )
2539 		{
2540 			if( !loopbackv6 )
2541 			{
2542 				loopbackv6 = p;
2543 			}
2544 			continue;
2545 		}
2546 		dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n",
2547 			p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
2548 
2549 		err = SetupInterface( inMDNS, p, &ifd );
2550 		require_noerr( err, exit );
2551 
2552 		// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
2553 		// register him, but we also want to note that we haven't found a v4 interface
2554 		// so that we register loopback so same host operations work
2555 
2556 		if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
2557 		{
2558 			foundv6 = mDNStrue;
2559 		}
2560 
2561 		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
2562 		// of determing the destination address of a packet that is sent to us.
2563 		// For multicast packets, that's easy to determine.  But for the unicast
2564 		// sockets, we'll fake it by taking the address of the first interface
2565 		// that is successfully setup.
2566 
2567 		if ( !foundUnicastSock6DestAddr )
2568 		{
2569 			inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
2570 			foundUnicastSock6DestAddr = TRUE;
2571 		}
2572 
2573 		*next = ifd;
2574 		next  = &ifd->next;
2575 		++inMDNS->p->interfaceCount;
2576 	}
2577 #endif
2578 
2579 	// If there are no real interfaces, but there is a loopback interface, use that so same-machine operations work.
2580 
2581 #if( !MDNS_WINDOWS_ENABLE_IPV4 && !MDNS_WINDOWS_ENABLE_IPV6 )
2582 
2583 	flagMask |= IFF_LOOPBACK;
2584 	flagTest |= IFF_LOOPBACK;
2585 
2586 	for( p = addrs; p; p = p->ifa_next )
2587 	{
2588 		if( !p->ifa_addr || ( ( p->ifa_flags & flagMask ) != flagTest ) )
2589 		{
2590 			continue;
2591 		}
2592 		if( ( p->ifa_addr->sa_family != AF_INET ) && ( p->ifa_addr->sa_family != AF_INET6 ) )
2593 		{
2594 			continue;
2595 		}
2596 
2597 		v4loopback = p;
2598 		break;
2599 	}
2600 
2601 #endif
2602 
2603 	if ( !foundv4 && loopbackv4 )
2604 	{
2605 		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n",
2606 			loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
2607 
2608 		err = SetupInterface( inMDNS, loopbackv4, &ifd );
2609 		require_noerr( err, exit );
2610 
2611 		inMDNS->p->registeredLoopback4 = mDNStrue;
2612 
2613 #if( MDNS_WINDOWS_ENABLE_IPV4 )
2614 
2615 		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
2616 		// of determing the destination address of a packet that is sent to us.
2617 		// For multicast packets, that's easy to determine.  But for the unicast
2618 		// sockets, we'll fake it by taking the address of the first interface
2619 		// that is successfully setup.
2620 
2621 		if ( !foundUnicastSock4DestAddr )
2622 		{
2623 			inMDNS->p->unicastSock4.addr = ifd->sock.addr;
2624 			foundUnicastSock4DestAddr = TRUE;
2625 		}
2626 #endif
2627 
2628 		*next = ifd;
2629 		next  = &ifd->next;
2630 		++inMDNS->p->interfaceCount;
2631 	}
2632 
2633 	if ( !foundv6 && loopbackv6 )
2634 	{
2635 		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n",
2636 			loopbackv6->ifa_name ? loopbackv6->ifa_name : "<null>", loopbackv6->ifa_extra.index, loopbackv6->ifa_addr );
2637 
2638 		err = SetupInterface( inMDNS, loopbackv6, &ifd );
2639 		require_noerr( err, exit );
2640 
2641 #if( MDNS_WINDOWS_ENABLE_IPV6 )
2642 
2643 		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
2644 		// of determing the destination address of a packet that is sent to us.
2645 		// For multicast packets, that's easy to determine.  But for the unicast
2646 		// sockets, we'll fake it by taking the address of the first interface
2647 		// that is successfully setup.
2648 
2649 		if ( !foundUnicastSock6DestAddr )
2650 		{
2651 			inMDNS->p->unicastSock6.addr = ifd->sock.addr;
2652 			foundUnicastSock6DestAddr = TRUE;
2653 		}
2654 #endif
2655 
2656 		*next = ifd;
2657 		next  = &ifd->next;
2658 		++inMDNS->p->interfaceCount;
2659 	}
2660 
2661 	CheckFileShares( inMDNS );
2662 
2663 exit:
2664 	if( err )
2665 	{
2666 		TearDownInterfaceList( inMDNS );
2667 	}
2668 	if( addrs )
2669 	{
2670 		freeifaddrs( addrs );
2671 	}
2672 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list done (err=%d %m)\n", err, err );
2673 	return( err );
2674 }
2675 
2676 //===========================================================================================================================
2677 //	TearDownInterfaceList
2678 //===========================================================================================================================
2679 
TearDownInterfaceList(mDNS * const inMDNS)2680 mStatus	TearDownInterfaceList( mDNS * const inMDNS )
2681 {
2682 	mDNSInterfaceData **		p;
2683 	mDNSInterfaceData *		ifd;
2684 
2685 	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
2686 	check( inMDNS );
2687 	check( inMDNS->p );
2688 
2689 	// Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
2690 	// Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
2691 	// so that remove events that occur after an interface goes away can still report the correct interface.
2692 
2693 	p = &inMDNS->p->inactiveInterfaceList;
2694 	while( *p )
2695 	{
2696 		ifd = *p;
2697 		if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) ifd ) > 0 )
2698 		{
2699 			p = &ifd->next;
2700 			continue;
2701 		}
2702 
2703 		dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
2704 		*p = ifd->next;
2705 
2706 		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
2707 	}
2708 
2709 	// Tear down all the interfaces.
2710 
2711 	while( inMDNS->p->interfaceList )
2712 	{
2713 		ifd = inMDNS->p->interfaceList;
2714 		inMDNS->p->interfaceList = ifd->next;
2715 
2716 		TearDownInterface( inMDNS, ifd );
2717 	}
2718 	inMDNS->p->interfaceCount = 0;
2719 
2720 	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list done\n" );
2721 	return( mStatus_NoError );
2722 }
2723 
2724 //===========================================================================================================================
2725 //	SetupInterface
2726 //===========================================================================================================================
2727 
SetupInterface(mDNS * const inMDNS,const struct ifaddrs * inIFA,mDNSInterfaceData ** outIFD)2728 mDNSlocal mStatus	SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
2729 {
2730 	mDNSInterfaceData	*	ifd;
2731 	mDNSInterfaceData	*	p;
2732 	mStatus					err;
2733 
2734 	ifd = NULL;
2735 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
2736 	check( inMDNS );
2737 	check( inMDNS->p );
2738 	check( inIFA );
2739 	check( inIFA->ifa_addr );
2740 	check( outIFD );
2741 
2742 	// Allocate memory for the interface and initialize it.
2743 
2744 	ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
2745 	require_action( ifd, exit, err = mStatus_NoMemoryErr );
2746 	ifd->sock.fd		= kInvalidSocketRef;
2747 	ifd->sock.overlapped.pending = FALSE;
2748 	ifd->sock.ifd		= ifd;
2749 	ifd->sock.next		= NULL;
2750 	ifd->sock.m			= inMDNS;
2751 	ifd->index			= inIFA->ifa_extra.index;
2752 	ifd->scopeID		= inIFA->ifa_extra.index;
2753 	check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
2754 	strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
2755 	ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
2756 
2757 	strncpy(ifd->interfaceInfo.ifname, inIFA->ifa_name, sizeof(ifd->interfaceInfo.ifname));
2758 	ifd->interfaceInfo.ifname[sizeof(ifd->interfaceInfo.ifname)-1] = 0;
2759 
2760 	// We always send and receive using IPv4, but to reduce traffic, we send and receive using IPv6 only on interfaces
2761 	// that have no routable IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being
2762 	// on a large configured network, which means there's a good chance that most or all the other devices on that
2763 	// network should also have v4. By doing this we lose the ability to talk to true v6-only devices on that link,
2764 	// but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only
2765 	// devices on a large configured network, so we are willing to make that sacrifice.
2766 
2767 	ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
2768 	ifd->interfaceInfo.InterfaceID = NULL;
2769 
2770 	for( p = inMDNS->p->interfaceList; p; p = p->next )
2771 	{
2772 		if ( strcmp( p->name, ifd->name ) == 0 )
2773 		{
2774 			if (!ifd->interfaceInfo.InterfaceID)
2775 			{
2776 				ifd->interfaceInfo.InterfaceID	= (mDNSInterfaceID) p;
2777 			}
2778 
2779 			if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
2780 			     ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
2781 			     ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
2782 			{
2783 				ifd->interfaceInfo.McastTxRx = mDNSfalse;
2784 			}
2785 
2786 			break;
2787 		}
2788 	}
2789 
2790 	if ( !ifd->interfaceInfo.InterfaceID )
2791 	{
2792 		ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
2793 	}
2794 
2795 	// Set up a socket for this interface (if needed).
2796 
2797 	if( ifd->interfaceInfo.McastTxRx )
2798 	{
2799 		DWORD size;
2800 
2801 		err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
2802 		require_noerr( err, exit );
2803 		ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
2804 		ifd->sock.port = MulticastDNSPort;
2805 
2806 		// Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
2807 
2808 		err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
2809 
2810 		if ( err )
2811 		{
2812 			ifd->sock.recvMsgPtr = NULL;
2813 		}
2814 	}
2815 
2816 	if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
2817 	{
2818 		inMDNS->p->nextDHCPLeaseExpires = inIFA->ifa_dhcpLeaseExpires;
2819 	}
2820 
2821 	ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
2822 
2823 	// Register this interface with mDNS.
2824 
2825 	err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
2826 	require_noerr( err, exit );
2827 
2828 	err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
2829 	require_noerr( err, exit );
2830 
2831 	memcpy( ifd->interfaceInfo.MAC.b, inIFA->ifa_physaddr, sizeof( ifd->interfaceInfo.MAC.b ) );
2832 
2833 	ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
2834 
2835 	if ( ifd->sock.fd != kInvalidSocketRef )
2836 	{
2837 		err = UDPBeginRecv( &ifd->sock );
2838 		require_noerr( err, exit );
2839 	}
2840 
2841 	err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
2842 	require_noerr( err, exit );
2843 	ifd->hostRegistered = mDNStrue;
2844 
2845 	dlog( kDebugLevelInfo, DEBUG_NAME "Registered interface %##a with mDNS\n", inIFA->ifa_addr );
2846 
2847 	// Success!
2848 
2849 	*outIFD = ifd;
2850 	ifd = NULL;
2851 
2852 exit:
2853 
2854 	if( ifd )
2855 	{
2856 		TearDownInterface( inMDNS, ifd );
2857 	}
2858 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface done (err=%d %m)\n", err, err );
2859 	return( err );
2860 }
2861 
2862 //===========================================================================================================================
2863 //	TearDownInterface
2864 //===========================================================================================================================
2865 
TearDownInterface(mDNS * const inMDNS,mDNSInterfaceData * inIFD)2866 mDNSlocal mStatus	TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
2867 {
2868 	check( inMDNS );
2869 	check( inIFD );
2870 
2871 	// Deregister this interface with mDNS.
2872 
2873 	dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering interface %#a with mDNS\n", &inIFD->interfaceInfo.ip );
2874 
2875 	if( inIFD->hostRegistered )
2876 	{
2877 		inIFD->hostRegistered = mDNSfalse;
2878 		mDNS_DeregisterInterface( inMDNS, &inIFD->interfaceInfo, mDNSfalse );
2879 	}
2880 
2881 	// Tear down the multicast socket.
2882 
2883 	UDPCloseSocket( &inIFD->sock );
2884 
2885 	// If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps
2886 	// the InterfaceID valid so remove events report the correct interface. If it is no longer referenced, free it.
2887 
2888 	if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) inIFD ) > 0 )
2889 	{
2890 		inIFD->next = inMDNS->p->inactiveInterfaceList;
2891 		inMDNS->p->inactiveInterfaceList = inIFD;
2892 		dlog( kDebugLevelInfo, DEBUG_NAME "deferring free of interface %#p %#a\n", inIFD, &inIFD->interfaceInfo.ip );
2893 	}
2894 	else
2895 	{
2896 		dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
2897 		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
2898 	}
2899 
2900 	return( mStatus_NoError );
2901 }
2902 
FreeInterface(mDNSInterfaceData * inIFD)2903 mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
2904 {
2905 	free( inIFD );
2906 }
2907 
2908 //===========================================================================================================================
2909 //	SetupSocket
2910 //===========================================================================================================================
2911 
SetupSocket(mDNS * const inMDNS,const struct sockaddr * inAddr,mDNSIPPort port,SocketRef * outSocketRef)2912 mDNSlocal mStatus	SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  )
2913 {
2914 	mStatus			err;
2915 	SocketRef		sock;
2916 	int				option;
2917 	DWORD			bytesReturned = 0;
2918 	BOOL			behavior = FALSE;
2919 
2920 	DEBUG_UNUSED( inMDNS );
2921 
2922 	dlog( kDebugLevelTrace, DEBUG_NAME "setting up socket %##a\n", inAddr );
2923 	check( inMDNS );
2924 	check( outSocketRef );
2925 
2926 	// Set up an IPv4 or IPv6 UDP socket.
2927 
2928 	sock = socket( inAddr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
2929 	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
2930 	require_noerr( err, exit );
2931 
2932 	// Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
2933 	// if we're creating a multicast socket
2934 
2935 	if ( port.NotAnInteger )
2936 	{
2937 		option = 1;
2938 		err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
2939 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
2940 	}
2941 
2942 	// <rdar://problem/7894393> Bonjour for Windows broken on Windows XP
2943 	//
2944 	// Not sure why, but the default behavior for sockets is to behave incorrectly
2945 	// when using them in Overlapped I/O mode on XP. According to MSDN:
2946 	//
2947 	// SIO_UDP_CONNRESET (opcode setting: I, T==3)
2948 	//     Windows XP:  Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting.
2949 	//     Set to FALSE to disable reporting.
2950 	//
2951 	// Packet traces from misbehaving Bonjour installations showed that ICMP port unreachable
2952 	// messages were being sent to us after we sent out packets to a multicast address. This is clearly
2953 	// incorrect behavior, but should be harmless. However, after receiving a port unreachable error, WinSock
2954 	// will no longer receive any packets from that socket, which is not harmless. This behavior is only
2955 	// seen on XP.
2956 	//
2957 	// So we turn off port unreachable reporting to make sure our sockets that are reading
2958 	// multicast packets function correctly under all circumstances.
2959 
2960 	err = WSAIoctl( sock, SIO_UDP_CONNRESET, &behavior, sizeof(behavior), NULL, 0, &bytesReturned, NULL, NULL );
2961 	check_translated_errno( err == 0, errno_compat(), kOptionErr );
2962 
2963 	if( inAddr->sa_family == AF_INET )
2964 	{
2965 		mDNSv4Addr				ipv4;
2966 		struct sockaddr_in		sa4;
2967 		struct ip_mreq			mreqv4;
2968 
2969 		// Bind the socket to the desired port
2970 
2971 		ipv4.NotAnInteger 	= ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
2972 		mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
2973 		sa4.sin_family 		= AF_INET;
2974 		sa4.sin_port 		= port.NotAnInteger;
2975 		sa4.sin_addr.s_addr	= ipv4.NotAnInteger;
2976 
2977 		err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
2978 		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
2979 
2980 		// Turn on option to receive destination addresses and receiving interface.
2981 
2982 		option = 1;
2983 		err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
2984 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
2985 
2986 		if (port.NotAnInteger)
2987 		{
2988 			// Join the all-DNS multicast group so we receive Multicast DNS packets
2989 
2990 			mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
2991 			mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
2992 			err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
2993 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
2994 
2995 			// Specify the interface to send multicast packets on this socket.
2996 
2997 			sa4.sin_addr.s_addr = ipv4.NotAnInteger;
2998 			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
2999 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3000 
3001 			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
3002 
3003 			option = 1;
3004 			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
3005 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3006 		}
3007 
3008 		// Send unicast packets with TTL 255 (helps against spoofing).
3009 
3010 		option = 255;
3011 		err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
3012 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
3013 
3014 		// Send multicast packets with TTL 255 (helps against spoofing).
3015 
3016 		option = 255;
3017 		err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
3018 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
3019 
3020 	}
3021 	else if( inAddr->sa_family == AF_INET6 )
3022 	{
3023 		struct sockaddr_in6 *		sa6p;
3024 		struct sockaddr_in6			sa6;
3025 		struct ipv6_mreq			mreqv6;
3026 
3027 		sa6p = (struct sockaddr_in6 *) inAddr;
3028 
3029 		// Bind the socket to the desired port
3030 
3031 		mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
3032 		sa6.sin6_family		= AF_INET6;
3033 		sa6.sin6_port		= port.NotAnInteger;
3034 		sa6.sin6_flowinfo	= 0;
3035 		sa6.sin6_addr		= sa6p->sin6_addr;
3036 		sa6.sin6_scope_id	= sa6p->sin6_scope_id;
3037 
3038 		err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
3039 		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
3040 
3041 		// Turn on option to receive destination addresses and receiving interface.
3042 
3043 		option = 1;
3044 		err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &option, sizeof( option ) );
3045 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
3046 
3047 		// We only want to receive IPv6 packets (not IPv4-mapped IPv6 addresses) because we have a separate socket
3048 		// for IPv4, but the IPv6 stack in Windows currently doesn't support IPv4-mapped IPv6 addresses and doesn't
3049 		// support the IPV6_V6ONLY socket option so the following code would typically not be executed (or needed).
3050 
3051 		#if( defined( IPV6_V6ONLY ) )
3052 			option = 1;
3053 			err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, sizeof( option ) );
3054 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3055 		#endif
3056 
3057 		if ( port.NotAnInteger )
3058 		{
3059 			// Join the all-DNS multicast group so we receive Multicast DNS packets.
3060 
3061 			mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroup_v6.ip.v6 );
3062 			mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
3063 			err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
3064 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3065 
3066 			// Specify the interface to send multicast packets on this socket.
3067 
3068 			option = (int) sa6p->sin6_scope_id;
3069 			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
3070 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3071 
3072 			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
3073 
3074 			option = 1;
3075 			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
3076 			check_translated_errno( err == 0, errno_compat(), kOptionErr );
3077 		}
3078 
3079 		// Send unicast packets with TTL 255 (helps against spoofing).
3080 
3081 		option = 255;
3082 		err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
3083 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
3084 
3085 		// Send multicast packets with TTL 255 (helps against spoofing).
3086 
3087 		option = 255;
3088 		err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
3089 		check_translated_errno( err == 0, errno_compat(), kOptionErr );
3090 	}
3091 	else
3092 	{
3093 		dlog( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inAddr->sa_family );
3094 		err = kUnsupportedErr;
3095 		goto exit;
3096 	}
3097 
3098 	// Success!
3099 
3100 	*outSocketRef = sock;
3101 	sock = kInvalidSocketRef;
3102 	err = mStatus_NoError;
3103 
3104 exit:
3105 	if( IsValidSocket( sock ) )
3106 	{
3107 		close_compat( sock );
3108 	}
3109 	return( err );
3110 }
3111 
3112 //===========================================================================================================================
3113 //	SetupSocket
3114 //===========================================================================================================================
3115 
SockAddrToMDNSAddr(const struct sockaddr * const inSA,mDNSAddr * outIP,mDNSIPPort * outPort)3116 mDNSlocal mStatus	SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort )
3117 {
3118 	mStatus		err;
3119 
3120 	check( inSA );
3121 	check( outIP );
3122 
3123 	if( inSA->sa_family == AF_INET )
3124 	{
3125 		struct sockaddr_in *		sa4;
3126 
3127 		sa4 						= (struct sockaddr_in *) inSA;
3128 		outIP->type 				= mDNSAddrType_IPv4;
3129 		outIP->ip.v4.NotAnInteger	= sa4->sin_addr.s_addr;
3130 		if( outPort )
3131 		{
3132 			outPort->NotAnInteger	= sa4->sin_port;
3133 		}
3134 		err = mStatus_NoError;
3135 	}
3136 	else if( inSA->sa_family == AF_INET6 )
3137 	{
3138 		struct sockaddr_in6 *		sa6;
3139 
3140 		sa6 			= (struct sockaddr_in6 *) inSA;
3141 		outIP->type 	= mDNSAddrType_IPv6;
3142 		outIP->ip.v6 	= *( (mDNSv6Addr *) &sa6->sin6_addr );
3143 		if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) )
3144 		{
3145 			outIP->ip.v6.w[ 1 ] = 0;
3146 		}
3147 		if( outPort )
3148 		{
3149 			outPort->NotAnInteger = sa6->sin6_port;
3150 		}
3151 		err = mStatus_NoError;
3152 	}
3153 	else
3154 	{
3155 		dlog( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family %d", __ROUTINE__, inSA->sa_family );
3156 		err = mStatus_BadParamErr;
3157 	}
3158 	return( err );
3159 }
3160 
3161 
3162 #if 0
3163 #pragma mark -
3164 #endif
3165 
3166 //===========================================================================================================================
3167 //	UDPBeginRecv
3168 //===========================================================================================================================
3169 
UDPBeginRecv(UDPSocket * sock)3170 mDNSlocal OSStatus UDPBeginRecv( UDPSocket * sock )
3171 {
3172 	DWORD	size;
3173 	DWORD	numTries;
3174 	mStatus	err;
3175 
3176 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, sock->fd );
3177 
3178 	require_action( sock != NULL, exit, err = mStatus_BadStateErr );
3179 	check( !sock->overlapped.pending );
3180 
3181 	// Initialize the buffer structure
3182 
3183 	sock->overlapped.wbuf.buf	= (char *) &sock->packet;
3184 	sock->overlapped.wbuf.len	= (u_long) sizeof( sock->packet );
3185 	sock->srcAddrLen			= sizeof( sock->srcAddr );
3186 
3187 	// Initialize the overlapped structure
3188 
3189 	ZeroMemory( &sock->overlapped.data, sizeof( OVERLAPPED ) );
3190 	sock->overlapped.data.hEvent = sock;
3191 
3192 	numTries = 0;
3193 
3194 	do
3195 	{
3196 		if ( sock->recvMsgPtr )
3197 		{
3198 			sock->wmsg.name				= ( LPSOCKADDR ) &sock->srcAddr;
3199 			sock->wmsg.namelen			= sock->srcAddrLen;
3200 			sock->wmsg.lpBuffers		= &sock->overlapped.wbuf;
3201 			sock->wmsg.dwBufferCount	= 1;
3202 			sock->wmsg.Control.buf		= ( CHAR* ) sock->controlBuffer;
3203 			sock->wmsg.Control.len		= sizeof( sock->controlBuffer );
3204 			sock->wmsg.dwFlags			= 0;
3205 
3206 			err = sock->recvMsgPtr( sock->fd, &sock->wmsg, &size, &sock->overlapped.data, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
3207 			err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), (OSStatus) WSAGetLastError(), kUnknownErr );
3208 
3209 			// <rdar://problem/7824093> iTunes 9.1 fails to install with Bonjour service on Windows 7 Ultimate
3210 			//
3211 			// There seems to be a bug in some network device drivers that involves calling WSARecvMsg() in
3212 			// overlapped i/o mode. Although all the parameters to WSARecvMsg() are correct, it returns a
3213 			// WSAEFAULT error code when there is no actual error. We have found experientially that falling
3214 			// back to using WSARecvFrom() when this happens will work correctly.
3215 
3216 			if ( err == WSAEFAULT ) sock->recvMsgPtr = NULL;
3217 		}
3218 		else
3219 		{
3220 			DWORD flags = 0;
3221 
3222 			err = WSARecvFrom( sock->fd, &sock->overlapped.wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sock->srcAddr, &sock->srcAddrLen, &sock->overlapped.data, ( LPWSAOVERLAPPED_COMPLETION_ROUTINE ) UDPEndRecv );
3223 			err = translate_errno( ( err == 0 ) || ( WSAGetLastError() == WSA_IO_PENDING ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
3224 		}
3225 
3226 		// According to MSDN <http://msdn.microsoft.com/en-us/library/ms741687(VS.85).aspx>:
3227 		//
3228 		// "WSAECONNRESET: For a UDP datagram socket, this error would indicate that a previous
3229 		//                 send operation resulted in an ICMP "Port Unreachable" message."
3230 		//
3231 		// Because this is the case, we want to ignore this error and try again.  Just in case
3232 		// this is some kind of pathological condition, we'll break out of the retry loop
3233 		// after 100 iterations
3234 
3235 		require_action( !err || ( err == WSAECONNRESET ) || ( err == WSAEFAULT ), exit, err = WSAGetLastError() );
3236 	}
3237 	while ( ( ( err == WSAECONNRESET ) || ( err == WSAEFAULT ) ) && ( numTries++ < 100 ) );
3238 
3239 	sock->overlapped.pending = TRUE;
3240 
3241 exit:
3242 
3243 	if ( err )
3244 	{
3245 		LogMsg( "WSARecvMsg failed (%d)\n", err );
3246 	}
3247 
3248 	return err;
3249 }
3250 
3251 
3252 //===========================================================================================================================
3253 //	UDPEndRecv
3254 //===========================================================================================================================
3255 
UDPEndRecv(DWORD err,DWORD bytesTransferred,LPWSAOVERLAPPED overlapped,DWORD flags)3256 mDNSlocal void CALLBACK UDPEndRecv( DWORD err, DWORD bytesTransferred, LPWSAOVERLAPPED overlapped, DWORD flags )
3257 {
3258 	UDPSocket * sock = NULL;
3259 
3260 	( void ) flags;
3261 
3262 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: err = %d, bytesTransferred = %d\n", __ROUTINE__, err, bytesTransferred );
3263 	require_action_quiet( err != WSA_OPERATION_ABORTED, exit, err = ( DWORD ) kUnknownErr );
3264 	require_noerr( err, exit );
3265 	sock = ( overlapped != NULL ) ? overlapped->hEvent : NULL;
3266 	require_action( sock != NULL, exit, err = ( DWORD ) kUnknownErr );
3267 	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, sock->fd );
3268 	sock->overlapped.error				= err;
3269 	sock->overlapped.bytesTransferred	= bytesTransferred;
3270 	check( sock->overlapped.pending );
3271 	sock->overlapped.pending			= FALSE;
3272 
3273 	// Translate the source of this packet into mDNS data types
3274 
3275 	SockAddrToMDNSAddr( (struct sockaddr *) &sock->srcAddr, &sock->overlapped.srcAddr, &sock->overlapped.srcPort );
3276 
3277 	// Initialize the destination of this packet. Just in case
3278 	// we can't determine this info because we couldn't call
3279 	// WSARecvMsg (recvMsgPtr)
3280 
3281 	sock->overlapped.dstAddr = sock->addr;
3282 	sock->overlapped.dstPort = sock->port;
3283 
3284 	if ( sock->recvMsgPtr )
3285 	{
3286 		LPWSACMSGHDR	header;
3287 		LPWSACMSGHDR	last = NULL;
3288 		int				count = 0;
3289 
3290 		// Parse the control information. Reject packets received on the wrong interface.
3291 
3292 		// <rdar://problem/7832196> INSTALL: Bonjour 2.0 on Windows can not start / stop
3293 		//
3294 		// There seems to be an interaction between Bullguard and this next bit of code.
3295 		// When a user's machine is running Bullguard, the control information that is
3296 		// returned is corrupted, and the code would go into an infinite loop. We'll add
3297 		// two bits of defensive coding here. The first will check that each pointer to
3298 		// the LPWSACMSGHDR that is returned in the for loop is different than the last.
3299 		// This fixes the problem with Bullguard. The second will break out of this loop
3300 		// after 100 iterations, just in case the corruption isn't caught by the first
3301 		// check.
3302 
3303 		for ( header = WSA_CMSG_FIRSTHDR( &sock->wmsg ); header; header = WSA_CMSG_NXTHDR( &sock->wmsg, header ) )
3304 		{
3305 			if ( ( header != last ) && ( ++count < 100 ) )
3306 			{
3307 				last = header;
3308 
3309 				if ( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
3310 				{
3311 					IN_PKTINFO * ipv4PacketInfo;
3312 
3313 					ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
3314 
3315 					if ( sock->ifd != NULL )
3316 					{
3317 						require_action( ipv4PacketInfo->ipi_ifindex == sock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
3318 					}
3319 
3320 					sock->overlapped.dstAddr.type 				= mDNSAddrType_IPv4;
3321 					sock->overlapped.dstAddr.ip.v4.NotAnInteger	= ipv4PacketInfo->ipi_addr.s_addr;
3322 				}
3323 				else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
3324 				{
3325 					IN6_PKTINFO * ipv6PacketInfo;
3326 
3327 					ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
3328 
3329 					if ( sock->ifd != NULL )
3330 					{
3331 						require_action( ipv6PacketInfo->ipi6_ifindex == ( sock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
3332 					}
3333 
3334 					sock->overlapped.dstAddr.type	= mDNSAddrType_IPv6;
3335 					sock->overlapped.dstAddr.ip.v6	= *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
3336 				}
3337 			}
3338 			else
3339 			{
3340 				static BOOL loggedMessage = FALSE;
3341 
3342 				if ( !loggedMessage )
3343 				{
3344 					LogMsg( "UDPEndRecv: WSARecvMsg control information error." );
3345 					loggedMessage = TRUE;
3346 				}
3347 
3348 				break;
3349 			}
3350 		}
3351 	}
3352 
3353 	dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
3354 	dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", bytesTransferred );
3355 	dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %#a:%u\n", &sock->overlapped.srcAddr, ntohs( sock->overlapped.srcPort.NotAnInteger ) );
3356 	dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %#a:%u\n", &sock->overlapped.dstAddr, ntohs( sock->overlapped.dstPort.NotAnInteger ) );
3357 
3358 	if ( sock->ifd != NULL )
3359 	{
3360 		dlog( kDebugLevelChatty, DEBUG_NAME "    interface = %#a (index=0x%08X)\n", &sock->ifd->interfaceInfo.ip, sock->ifd->index );
3361 	}
3362 
3363 	dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
3364 
3365 	// Queue this socket
3366 
3367 	AddToTail( &gUDPDispatchableSockets, sock );
3368 
3369 exit:
3370 
3371 	return;
3372 }
3373 
3374 
3375 //===========================================================================================================================
3376 //	InterfaceListDidChange
3377 //===========================================================================================================================
InterfaceListDidChange(mDNS * const inMDNS)3378 void InterfaceListDidChange( mDNS * const inMDNS )
3379 {
3380 	mStatus err;
3381 
3382 	dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
3383 	check( inMDNS );
3384 
3385 	// Tear down the existing interfaces and set up new ones using the new IP info.
3386 
3387 	err = TearDownInterfaceList( inMDNS );
3388 	check_noerr( err );
3389 
3390 	err = SetupInterfaceList( inMDNS );
3391 	check_noerr( err );
3392 
3393 	err = uDNS_SetupDNSConfig( inMDNS );
3394 	check_noerr( err );
3395 
3396 	// Inform clients of the change.
3397 
3398 	mDNS_ConfigChanged(inMDNS);
3399 
3400 	// Force mDNS to update.
3401 
3402 	mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
3403 }
3404 
3405 
3406 //===========================================================================================================================
3407 //	ComputerDescriptionDidChange
3408 //===========================================================================================================================
ComputerDescriptionDidChange(mDNS * const inMDNS)3409 void ComputerDescriptionDidChange( mDNS * const inMDNS )
3410 {
3411 	dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
3412 	check( inMDNS );
3413 
3414 	// redo the names
3415 	SetupNiceName( inMDNS );
3416 }
3417 
3418 
3419 //===========================================================================================================================
3420 //	TCPIPConfigDidChange
3421 //===========================================================================================================================
TCPIPConfigDidChange(mDNS * const inMDNS)3422 void TCPIPConfigDidChange( mDNS * const inMDNS )
3423 {
3424 	mStatus		err;
3425 
3426 	dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
3427 	check( inMDNS );
3428 
3429 	err = uDNS_SetupDNSConfig( inMDNS );
3430 	check_noerr( err );
3431 }
3432 
3433 
3434 //===========================================================================================================================
3435 //	DynDNSConfigDidChange
3436 //===========================================================================================================================
DynDNSConfigDidChange(mDNS * const inMDNS)3437 void DynDNSConfigDidChange( mDNS * const inMDNS )
3438 {
3439 	mStatus		err;
3440 
3441 	dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
3442 	check( inMDNS );
3443 
3444 	SetDomainSecrets( inMDNS );
3445 
3446 	err = uDNS_SetupDNSConfig( inMDNS );
3447 	check_noerr( err );
3448 }
3449 
3450 
3451 //===========================================================================================================================
3452 //	FileSharingDidChange
3453 //===========================================================================================================================
FileSharingDidChange(mDNS * const inMDNS)3454 void FileSharingDidChange( mDNS * const inMDNS )
3455 {
3456 	dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
3457 	check( inMDNS );
3458 
3459 	CheckFileShares( inMDNS );
3460 }
3461 
3462 
3463 //===========================================================================================================================
3464 //	FilewallDidChange
3465 //===========================================================================================================================
FirewallDidChange(mDNS * const inMDNS)3466 void FirewallDidChange( mDNS * const inMDNS )
3467 {
3468 	dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
3469 	check( inMDNS );
3470 
3471 	CheckFileShares( inMDNS );
3472 }
3473 
3474 
3475 #if 0
3476 #pragma mark -
3477 #pragma mark == Utilities ==
3478 #endif
3479 
3480 //===========================================================================================================================
3481 //	getifaddrs
3482 //===========================================================================================================================
3483 
getifaddrs(struct ifaddrs ** outAddrs)3484 mDNSlocal int	getifaddrs( struct ifaddrs **outAddrs )
3485 {
3486 	int		err;
3487 
3488 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
3489 
3490 	// Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
3491 	// XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
3492 
3493 	if( !gIPHelperLibraryInstance )
3494 	{
3495 		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
3496 		if( gIPHelperLibraryInstance )
3497 		{
3498 			gGetAdaptersAddressesFunctionPtr =
3499 				(GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
3500 			if( !gGetAdaptersAddressesFunctionPtr )
3501 			{
3502 				BOOL		ok;
3503 
3504 				ok = FreeLibrary( gIPHelperLibraryInstance );
3505 				check_translated_errno( ok, GetLastError(), kUnknownErr );
3506 				gIPHelperLibraryInstance = NULL;
3507 			}
3508 		}
3509 	}
3510 
3511 	// Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
3512 	// <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
3513 	// <rdar://problem/6145913>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 returns no addrs
3514 
3515 	if( !gGetAdaptersAddressesFunctionPtr || ( ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) || ( ( outAddrs != NULL ) && ( *outAddrs == NULL ) ) ) )
3516 	{
3517 		err = getifaddrs_ipv4( outAddrs );
3518 		require_noerr( err, exit );
3519 	}
3520 
3521 #else
3522 
3523 	err = getifaddrs_ipv4( outAddrs );
3524 	require_noerr( err, exit );
3525 
3526 #endif
3527 
3528 exit:
3529 	return( err );
3530 }
3531 
3532 #if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
3533 //===========================================================================================================================
3534 //	getifaddrs_ipv6
3535 //===========================================================================================================================
3536 
getifaddrs_ipv6(struct ifaddrs ** outAddrs)3537 mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs )
3538 {
3539 	DWORD						err;
3540 	int							i;
3541 	DWORD						flags;
3542 	struct ifaddrs *			head;
3543 	struct ifaddrs **			next;
3544 	IP_ADAPTER_ADDRESSES *		iaaList;
3545 	ULONG						iaaListSize;
3546 	IP_ADAPTER_ADDRESSES *		iaa;
3547 	size_t						size;
3548 	struct ifaddrs *			ifa;
3549 
3550 	check( gGetAdaptersAddressesFunctionPtr );
3551 
3552 	head	= NULL;
3553 	next	= &head;
3554 	iaaList	= NULL;
3555 
3556 	// Get the list of interfaces. The first call gets the size and the second call gets the actual data.
3557 	// This loops to handle the case where the interface changes in the window after getting the size, but before the
3558 	// second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
3559 
3560 	flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
3561 	i = 0;
3562 	for( ;; )
3563 	{
3564 		iaaListSize = 0;
3565 		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
3566 		check( err == ERROR_BUFFER_OVERFLOW );
3567 		check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
3568 
3569 		iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
3570 		require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
3571 
3572 		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
3573 		if( err == ERROR_SUCCESS ) break;
3574 
3575 		free( iaaList );
3576 		iaaList = NULL;
3577 		++i;
3578 		require( i < 100, exit );
3579 		dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
3580 	}
3581 
3582 	for( iaa = iaaList; iaa; iaa = iaa->Next )
3583 	{
3584 		int								addrIndex;
3585 		IP_ADAPTER_UNICAST_ADDRESS	*	addr;
3586 		DWORD							ipv6IfIndex;
3587 		IP_ADAPTER_PREFIX			*	firstPrefix;
3588 
3589 		if( iaa->IfIndex > 0xFFFFFF )
3590 		{
3591 			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv4 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->IfIndex );
3592 		}
3593 		if( iaa->Ipv6IfIndex > 0xFF )
3594 		{
3595 			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
3596 		}
3597 
3598 		// For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the
3599 		// following code to crash when iterating through the prefix list.  This seems
3600 		// to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
3601 		// This shouldn't happen according to Microsoft docs which states:
3602 		//
3603 		//     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
3604 		//
3605 		// So the data structure seems to be corrupted when we return from
3606 		// GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
3607 		// sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
3608 		// modify iaa to have the correct values.
3609 
3610 		if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
3611 		{
3612 			ipv6IfIndex = iaa->Ipv6IfIndex;
3613 			firstPrefix = iaa->FirstPrefix;
3614 		}
3615 		else
3616 		{
3617 			ipv6IfIndex	= 0;
3618 			firstPrefix = NULL;
3619 		}
3620 
3621 		// Skip pseudo and tunnel interfaces.
3622 
3623 		if( ( ( ipv6IfIndex == 1 ) && ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
3624 		{
3625 			continue;
3626 		}
3627 
3628 		// Add each address as a separate interface to emulate the way getifaddrs works.
3629 
3630 		for( addrIndex = 0, addr = iaa->FirstUnicastAddress; addr; ++addrIndex, addr = addr->Next )
3631 		{
3632 			int						family;
3633 			int						prefixIndex;
3634 			IP_ADAPTER_PREFIX *		prefix;
3635 			ULONG					prefixLength;
3636 			uint32_t				ipv4Index;
3637 			struct sockaddr_in		ipv4Netmask;
3638 
3639 			family = addr->Address.lpSockaddr->sa_family;
3640 			if( ( family != AF_INET ) && ( family != AF_INET6 ) ) continue;
3641 
3642 			// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
3643 			// Seems as if the problem here is a buggy implementation of some network interface
3644 			// driver. It is reporting that is has a link-local address when it is actually
3645 			// disconnected. This was causing a problem in AddressToIndexAndMask.
3646 			// The solution is to call AddressToIndexAndMask first, and if unable to lookup
3647 			// the address, to ignore that address.
3648 
3649 			ipv4Index = 0;
3650 			memset( &ipv4Netmask, 0, sizeof( ipv4Netmask ) );
3651 
3652 			if ( family == AF_INET )
3653 			{
3654 				err = AddressToIndexAndMask( addr->Address.lpSockaddr, &ipv4Index, ( struct sockaddr* ) &ipv4Netmask );
3655 
3656 				if ( err )
3657 				{
3658 					err = 0;
3659 					continue;
3660 				}
3661 			}
3662 
3663 			ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
3664 			require_action( ifa, exit, err = WSAENOBUFS );
3665 
3666 			*next = ifa;
3667 			next  = &ifa->ifa_next;
3668 
3669 			// Get the name.
3670 
3671 			size = strlen( iaa->AdapterName ) + 1;
3672 			ifa->ifa_name = (char *) malloc( size );
3673 			require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
3674 			memcpy( ifa->ifa_name, iaa->AdapterName, size );
3675 
3676 			// Get interface flags.
3677 
3678 			ifa->ifa_flags = 0;
3679 			if( iaa->OperStatus == IfOperStatusUp ) 		ifa->ifa_flags |= IFF_UP;
3680 			if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )	ifa->ifa_flags |= IFF_LOOPBACK;
3681 			else if ( IsPointToPoint( addr ) )				ifa->ifa_flags |= IFF_POINTTOPOINT;
3682 			if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) )	ifa->ifa_flags |= IFF_MULTICAST;
3683 
3684 
3685 			// <rdar://problem/4045657> Interface index being returned is 512
3686 			//
3687 			// Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes.
3688 			// This code used to shift the IPv4 index up to ensure uniqueness between
3689 			// it and IPv6 indexes.  Although this worked, it was somewhat confusing to developers, who
3690 			// then see interface indexes passed back that don't correspond to anything
3691 			// that is seen in Win32 APIs or command line tools like "route".  As a relatively
3692 			// small percentage of developers are actively using IPv6, it seems to
3693 			// make sense to make our use of IPv4 as confusion free as possible.
3694 			// So now, IPv6 interface indexes will be shifted up by a
3695 			// constant value which will serve to uniquely identify them, and we will
3696 			// leave IPv4 interface indexes unmodified.
3697 
3698 			switch( family )
3699 			{
3700 				case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex; break;
3701 				case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase;	 break;
3702 				default: break;
3703 			}
3704 
3705 			// Get lease lifetime
3706 
3707 			if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->ValidLifetime != 0xFFFFFFFF ) )
3708 			{
3709 				ifa->ifa_dhcpEnabled		= TRUE;
3710 				ifa->ifa_dhcpLeaseExpires	= time( NULL ) + addr->ValidLifetime;
3711 			}
3712 			else
3713 			{
3714 				ifa->ifa_dhcpEnabled		= FALSE;
3715 				ifa->ifa_dhcpLeaseExpires	= 0;
3716 			}
3717 
3718 			if ( iaa->PhysicalAddressLength == sizeof( ifa->ifa_physaddr ) )
3719 			{
3720 				memcpy( ifa->ifa_physaddr, iaa->PhysicalAddress, iaa->PhysicalAddressLength );
3721 			}
3722 
3723 			// Because we don't get notified of womp changes, we're going to just assume
3724 			// that all wired interfaces have it enabled. Before we go to sleep, we'll check
3725 			// if the interface actually supports it, and update mDNS->SystemWakeOnLANEnabled
3726 			// accordingly
3727 
3728 			ifa->ifa_womp = ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD ) ? mDNStrue : mDNSfalse;
3729 
3730 			// Get address.
3731 
3732 			switch( family )
3733 			{
3734 				case AF_INET:
3735 				case AF_INET6:
3736 					ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
3737 					require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
3738 					memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
3739 					break;
3740 
3741 				default:
3742 					break;
3743 			}
3744 			check( ifa->ifa_addr );
3745 
3746 			// Get subnet mask (IPv4)/link prefix (IPv6). It is specified as a bit length (e.g. 24 for 255.255.255.0).
3747 
3748 			prefixLength = 0;
3749 			for( prefixIndex = 0, prefix = firstPrefix; prefix; ++prefixIndex, prefix = prefix->Next )
3750 			{
3751 				if( ( prefix->Address.lpSockaddr->sa_family == family ) && ( prefixIndex == addrIndex ) )
3752 				{
3753 					check_string( prefix->Address.lpSockaddr->sa_family == family, "addr family != netmask family" );
3754 					prefixLength = prefix->PrefixLength;
3755 					break;
3756 				}
3757 			}
3758 			switch( family )
3759 			{
3760 				case AF_INET:
3761 				{
3762 					struct sockaddr_in * sa4;
3763 
3764 					sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
3765 					require_action( sa4, exit, err = WSAENOBUFS );
3766 					sa4->sin_family = AF_INET;
3767 					sa4->sin_addr.s_addr = ipv4Netmask.sin_addr.s_addr;
3768 
3769 					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) );
3770 					ifa->ifa_netmask = (struct sockaddr *) sa4;
3771 					break;
3772 				}
3773 
3774 				case AF_INET6:
3775 				{
3776 					struct sockaddr_in6 *		sa6;
3777 					int							len;
3778 					int							maskIndex;
3779 					uint8_t						maskByte;
3780 
3781 					require_action( prefixLength <= 128, exit, err = ERROR_INVALID_DATA );
3782 
3783 					sa6 = (struct sockaddr_in6 *) calloc( 1, sizeof( *sa6 ) );
3784 					require_action( sa6, exit, err = WSAENOBUFS );
3785 					sa6->sin6_family = AF_INET6;
3786 
3787 					if( prefixLength == 0 )
3788 					{
3789 						dlog( kDebugLevelWarning, DEBUG_NAME "%s: IPv6 link prefix 0, defaulting to /128\n", __ROUTINE__ );
3790 						prefixLength = 128;
3791 					}
3792 					maskIndex = 0;
3793 					for( len = (int) prefixLength; len > 0; len -= 8 )
3794 					{
3795 						if( len >= 8 ) maskByte = 0xFF;
3796 						else		   maskByte = (uint8_t)( ( 0xFFU << ( 8 - len ) ) & 0xFFU );
3797 						sa6->sin6_addr.s6_addr[ maskIndex++ ] = maskByte;
3798 					}
3799 					ifa->ifa_netmask = (struct sockaddr *) sa6;
3800 					break;
3801 				}
3802 
3803 				default:
3804 					break;
3805 			}
3806 		}
3807 	}
3808 
3809 	// Success!
3810 
3811 	if( outAddrs )
3812 	{
3813 		*outAddrs = head;
3814 		head = NULL;
3815 	}
3816 	err = ERROR_SUCCESS;
3817 
3818 exit:
3819 	if( head )
3820 	{
3821 		freeifaddrs( head );
3822 	}
3823 	if( iaaList )
3824 	{
3825 		free( iaaList );
3826 	}
3827 	return( (int) err );
3828 }
3829 
3830 #endif	// MDNS_WINDOWS_USE_IPV6_IF_ADDRS
3831 
3832 //===========================================================================================================================
3833 //	getifaddrs_ipv4
3834 //===========================================================================================================================
3835 
getifaddrs_ipv4(struct ifaddrs ** outAddrs)3836 mDNSlocal int	getifaddrs_ipv4( struct ifaddrs **outAddrs )
3837 {
3838 	int						err;
3839 	SOCKET					sock;
3840 	DWORD					size;
3841 	DWORD					actualSize;
3842 	INTERFACE_INFO *		buffer;
3843 	INTERFACE_INFO *		tempBuffer;
3844 	INTERFACE_INFO *		ifInfo;
3845 	int						n;
3846 	int						i;
3847 	struct ifaddrs *		head;
3848 	struct ifaddrs **		next;
3849 	struct ifaddrs *		ifa;
3850 
3851 	sock	= INVALID_SOCKET;
3852 	buffer	= NULL;
3853 	head	= NULL;
3854 	next	= &head;
3855 
3856 	// Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a
3857 	// way to determine the size of the interface list beforehand, we have to start with an initial size guess and
3858 	// call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
3859 
3860 	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
3861 	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
3862 	require_noerr( err, exit );
3863 
3864 	n = 0;
3865 	size = 16 * sizeof( INTERFACE_INFO );
3866 	for( ;; )
3867 	{
3868 		tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
3869 		require_action( tempBuffer, exit, err = WSAENOBUFS );
3870 		buffer = tempBuffer;
3871 
3872 		err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
3873 		if( err == 0 )
3874 		{
3875 			break;
3876 		}
3877 
3878 		++n;
3879 		require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
3880 
3881 		size += ( 16 * sizeof( INTERFACE_INFO ) );
3882 	}
3883 	check( actualSize <= size );
3884 	check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
3885 	n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
3886 
3887 	// Process the raw interface list and build a linked list of IPv4 interfaces.
3888 
3889 	for( i = 0; i < n; ++i )
3890 	{
3891 		uint32_t ifIndex;
3892 		struct sockaddr_in netmask;
3893 
3894 		ifInfo = &buffer[ i ];
3895 		if( ifInfo->iiAddress.Address.sa_family != AF_INET )
3896 		{
3897 			continue;
3898 		}
3899 
3900 		// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
3901 		// See comment in getifaddrs_ipv6
3902 
3903 		ifIndex = 0;
3904 		memset( &netmask, 0, sizeof( netmask ) );
3905 		err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
3906 
3907 		if ( err )
3908 		{
3909 			continue;
3910 		}
3911 
3912 		ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
3913 		require_action( ifa, exit, err = WSAENOBUFS );
3914 
3915 		*next = ifa;
3916 		next  = &ifa->ifa_next;
3917 
3918 		// Get the name.
3919 
3920 		ifa->ifa_name = (char *) malloc( 16 );
3921 		require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
3922 		sprintf( ifa->ifa_name, "%d", i + 1 );
3923 
3924 		// Get interface flags.
3925 
3926 		ifa->ifa_flags = (u_int) ifInfo->iiFlags;
3927 
3928 		// Get addresses.
3929 
3930 		if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
3931 		{
3932 			struct sockaddr_in *		sa4;
3933 
3934 			sa4 = &ifInfo->iiAddress.AddressIn;
3935 			ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
3936 			require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
3937 			memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
3938 
3939 			ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
3940 			require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
3941 
3942 			// <rdar://problem/4076478> Service won't start on Win2K. The address
3943 			// family field was not being initialized.
3944 
3945 			ifa->ifa_netmask->sa_family = AF_INET;
3946 			( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
3947 			ifa->ifa_extra.index = ifIndex;
3948 		}
3949 		else
3950 		{
3951 			// Emulate an interface index.
3952 
3953 			ifa->ifa_extra.index = (uint32_t)( i + 1 );
3954 		}
3955 	}
3956 
3957 	// Success!
3958 
3959 	if( outAddrs )
3960 	{
3961 		*outAddrs = head;
3962 		head = NULL;
3963 	}
3964 	err = 0;
3965 
3966 exit:
3967 
3968 	if( head )
3969 	{
3970 		freeifaddrs( head );
3971 	}
3972 	if( buffer )
3973 	{
3974 		free( buffer );
3975 	}
3976 	if( sock != INVALID_SOCKET )
3977 	{
3978 		closesocket( sock );
3979 	}
3980 	return( err );
3981 }
3982 
3983 //===========================================================================================================================
3984 //	freeifaddrs
3985 //===========================================================================================================================
3986 
freeifaddrs(struct ifaddrs * inIFAs)3987 mDNSlocal void	freeifaddrs( struct ifaddrs *inIFAs )
3988 {
3989 	struct ifaddrs *		p;
3990 	struct ifaddrs *		q;
3991 
3992 	// Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
3993 
3994 	for( p = inIFAs; p; p = q )
3995 	{
3996 		q = p->ifa_next;
3997 
3998 		if( p->ifa_name )
3999 		{
4000 			free( p->ifa_name );
4001 			p->ifa_name = NULL;
4002 		}
4003 		if( p->ifa_addr )
4004 		{
4005 			free( p->ifa_addr );
4006 			p->ifa_addr = NULL;
4007 		}
4008 		if( p->ifa_netmask )
4009 		{
4010 			free( p->ifa_netmask );
4011 			p->ifa_netmask = NULL;
4012 		}
4013 		if( p->ifa_broadaddr )
4014 		{
4015 			free( p->ifa_broadaddr );
4016 			p->ifa_broadaddr = NULL;
4017 		}
4018 		if( p->ifa_dstaddr )
4019 		{
4020 			free( p->ifa_dstaddr );
4021 			p->ifa_dstaddr = NULL;
4022 		}
4023 		if( p->ifa_data )
4024 		{
4025 			free( p->ifa_data );
4026 			p->ifa_data = NULL;
4027 		}
4028 		free( p );
4029 	}
4030 }
4031 
4032 
4033 //===========================================================================================================================
4034 //	GetPrimaryInterface
4035 //===========================================================================================================================
4036 
4037 mDNSlocal DWORD
GetPrimaryInterface()4038 GetPrimaryInterface()
4039 {
4040 	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
4041 	DWORD				dwSize			= 0;
4042 	BOOL				bOrder			= FALSE;
4043 	OSStatus			err;
4044 	DWORD				index			= 0;
4045 	DWORD				metric			= 0;
4046 	unsigned long int	i;
4047 
4048 	// Find out how big our buffer needs to be.
4049 
4050 	err = GetIpForwardTable(NULL, &dwSize, bOrder);
4051 	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
4052 
4053 	// Allocate the memory for the table
4054 
4055 	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
4056 	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
4057 
4058 	// Now get the table.
4059 
4060 	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
4061 	require_noerr( err, exit );
4062 
4063 
4064 	// Search for the row in the table we want.
4065 
4066 	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
4067 	{
4068 		// Look for a default route
4069 
4070 		if ( pIpForwardTable->table[i].dwForwardDest == 0 )
4071 		{
4072 			if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) )
4073 			{
4074 				continue;
4075 			}
4076 
4077 			index	= pIpForwardTable->table[i].dwForwardIfIndex;
4078 			metric	= pIpForwardTable->table[i].dwForwardMetric1;
4079 		}
4080 	}
4081 
4082 exit:
4083 
4084 	if ( pIpForwardTable != NULL )
4085 	{
4086 		free( pIpForwardTable );
4087 	}
4088 
4089 	return index;
4090 }
4091 
4092 
4093 //===========================================================================================================================
4094 //	AddressToIndexAndMask
4095 //===========================================================================================================================
4096 
4097 mDNSlocal mStatus
AddressToIndexAndMask(struct sockaddr * addr,uint32_t * ifIndex,struct sockaddr * mask)4098 AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask  )
4099 {
4100 	// Before calling AddIPAddress we use GetIpAddrTable to get
4101 	// an adapter to which we can add the IP.
4102 
4103 	PMIB_IPADDRTABLE	pIPAddrTable	= NULL;
4104 	DWORD				dwSize			= 0;
4105 	mStatus				err				= mStatus_UnknownErr;
4106 	DWORD				i;
4107 
4108 	// For now, this is only for IPv4 addresses.  That is why we can safely cast
4109 	// addr's to sockaddr_in.
4110 
4111 	require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr );
4112 
4113 	// Make an initial call to GetIpAddrTable to get the
4114 	// necessary size into the dwSize variable
4115 
4116 	for ( i = 0; i < 100; i++ )
4117 	{
4118 		err = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
4119 
4120 		if ( err != ERROR_INSUFFICIENT_BUFFER )
4121 		{
4122 			break;
4123 		}
4124 
4125 		pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize );
4126 		require_action( pIPAddrTable, exit, err = WSAENOBUFS );
4127 	}
4128 
4129 	require_noerr( err, exit );
4130 	err = mStatus_UnknownErr;
4131 
4132 	for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
4133 	{
4134 		if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr )
4135 		{
4136 			*ifIndex											= pIPAddrTable->table[i].dwIndex;
4137 			( ( struct sockaddr_in*) mask )->sin_addr.s_addr	= pIPAddrTable->table[i].dwMask;
4138 			err													= mStatus_NoError;
4139 			break;
4140 		}
4141 	}
4142 
4143 exit:
4144 
4145 	if ( pIPAddrTable )
4146 	{
4147 		free( pIPAddrTable );
4148 	}
4149 
4150 	return err;
4151 }
4152 
4153 
4154 //===========================================================================================================================
4155 //	CanReceiveUnicast
4156 //===========================================================================================================================
4157 
CanReceiveUnicast(void)4158 mDNSlocal mDNSBool	CanReceiveUnicast( void )
4159 {
4160 	mDNSBool				ok;
4161 	SocketRef				sock;
4162 	struct sockaddr_in		addr;
4163 
4164 	// Try to bind to the port without the SO_REUSEADDR option to test if someone else has already bound to it.
4165 
4166 	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
4167 	check_translated_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
4168 	ok = IsValidSocket( sock );
4169 	if( ok )
4170 	{
4171 		mDNSPlatformMemZero( &addr, sizeof( addr ) );
4172 		addr.sin_family			= AF_INET;
4173 		addr.sin_port			= MulticastDNSPort.NotAnInteger;
4174 		addr.sin_addr.s_addr	= htonl( INADDR_ANY );
4175 
4176 		ok = ( bind( sock, (struct sockaddr *) &addr, sizeof( addr ) ) == 0 );
4177 		close_compat( sock );
4178 	}
4179 
4180 	dlog( kDebugLevelInfo, DEBUG_NAME "Unicast UDP responses %s\n", ok ? "okay" : "*not allowed*" );
4181 	return( ok );
4182 }
4183 
4184 
4185 //===========================================================================================================================
4186 //	IsPointToPoint
4187 //===========================================================================================================================
4188 
IsPointToPoint(IP_ADAPTER_UNICAST_ADDRESS * addr)4189 mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr )
4190 {
4191 	struct ifaddrs	*	addrs	=	NULL;
4192 	struct ifaddrs	*	p		=	NULL;
4193 	OSStatus			err;
4194 	mDNSBool			ret		=	mDNSfalse;
4195 
4196 	// For now, only works for IPv4 interfaces
4197 
4198 	if ( addr->Address.lpSockaddr->sa_family == AF_INET )
4199 	{
4200 		// The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags.
4201 
4202 		err = getifaddrs_ipv4( &addrs );
4203 		require_noerr( err, exit );
4204 
4205 		for ( p = addrs; p; p = p->ifa_next )
4206 		{
4207 			if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) &&
4208 			     ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) )
4209 			{
4210 				ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse;
4211 				break;
4212 			}
4213 		}
4214 	}
4215 
4216 exit:
4217 
4218 	if ( addrs )
4219 	{
4220 		freeifaddrs( addrs );
4221 	}
4222 
4223 	return ret;
4224 }
4225 
4226 
4227 //===========================================================================================================================
4228 //	GetWindowsVersionString
4229 //===========================================================================================================================
4230 
GetWindowsVersionString(char * inBuffer,size_t inBufferSize)4231 mDNSlocal OSStatus	GetWindowsVersionString( char *inBuffer, size_t inBufferSize )
4232 {
4233 #if( !defined( VER_PLATFORM_WIN32_CE ) )
4234 	#define VER_PLATFORM_WIN32_CE		3
4235 #endif
4236 
4237 	OSStatus				err;
4238 	OSVERSIONINFO			osInfo;
4239 	BOOL					ok;
4240 	const char *			versionString;
4241 	DWORD					platformID;
4242 	DWORD					majorVersion;
4243 	DWORD					minorVersion;
4244 	DWORD					buildNumber;
4245 
4246 	versionString = "unknown Windows version";
4247 
4248 	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
4249 	ok = GetVersionEx( &osInfo );
4250 	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
4251 	require_noerr( err, exit );
4252 
4253 	platformID		= osInfo.dwPlatformId;
4254 	majorVersion	= osInfo.dwMajorVersion;
4255 	minorVersion	= osInfo.dwMinorVersion;
4256 	buildNumber		= osInfo.dwBuildNumber & 0xFFFF;
4257 
4258 	if( ( platformID == VER_PLATFORM_WIN32_WINDOWS ) && ( majorVersion == 4 ) )
4259 	{
4260 		if( ( minorVersion < 10 ) && ( buildNumber == 950 ) )
4261 		{
4262 			versionString	= "Windows 95";
4263 		}
4264 		else if( ( minorVersion < 10 ) && ( ( buildNumber > 950 ) && ( buildNumber <= 1080 ) ) )
4265 		{
4266 			versionString	= "Windows 95 SP1";
4267 		}
4268 		else if( ( minorVersion < 10 ) && ( buildNumber > 1080 ) )
4269 		{
4270 			versionString	= "Windows 95 OSR2";
4271 		}
4272 		else if( ( minorVersion == 10 ) && ( buildNumber == 1998 ) )
4273 		{
4274 			versionString	= "Windows 98";
4275 		}
4276 		else if( ( minorVersion == 10 ) && ( ( buildNumber > 1998 ) && ( buildNumber < 2183 ) ) )
4277 		{
4278 			versionString	= "Windows 98 SP1";
4279 		}
4280 		else if( ( minorVersion == 10 ) && ( buildNumber >= 2183 ) )
4281 		{
4282 			versionString	= "Windows 98 SE";
4283 		}
4284 		else if( minorVersion == 90 )
4285 		{
4286 			versionString	= "Windows ME";
4287 		}
4288 	}
4289 	else if( platformID == VER_PLATFORM_WIN32_NT )
4290 	{
4291 		if( ( majorVersion == 3 ) && ( minorVersion == 51 ) )
4292 		{
4293 			versionString	= "Windows NT 3.51";
4294 		}
4295 		else if( ( majorVersion == 4 ) && ( minorVersion == 0 ) )
4296 		{
4297 			versionString	= "Windows NT 4";
4298 		}
4299 		else if( ( majorVersion == 5 ) && ( minorVersion == 0 ) )
4300 		{
4301 			versionString	= "Windows 2000";
4302 		}
4303 		else if( ( majorVersion == 5 ) && ( minorVersion == 1 ) )
4304 		{
4305 			versionString	= "Windows XP";
4306 		}
4307 		else if( ( majorVersion == 5 ) && ( minorVersion == 2 ) )
4308 		{
4309 			versionString	= "Windows Server 2003";
4310 		}
4311 	}
4312 	else if( platformID == VER_PLATFORM_WIN32_CE )
4313 	{
4314 		versionString		= "Windows CE";
4315 	}
4316 
4317 exit:
4318 	if( inBuffer && ( inBufferSize > 0 ) )
4319 	{
4320 		inBufferSize -= 1;
4321 		strncpy( inBuffer, versionString, inBufferSize );
4322 		inBuffer[ inBufferSize ] = '\0';
4323 	}
4324 	return( err );
4325 }
4326 
4327 
4328 //===========================================================================================================================
4329 //	RegQueryString
4330 //===========================================================================================================================
4331 
4332 mDNSlocal mStatus
RegQueryString(HKEY key,LPCSTR valueName,LPSTR * string,DWORD * stringLen,DWORD * enabled)4333 RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled )
4334 {
4335 	DWORD	type;
4336 	int		i;
4337 	mStatus err;
4338 
4339 	*stringLen	= MAX_ESCAPED_DOMAIN_NAME;
4340 	*string		= NULL;
4341 	i			= 0;
4342 
4343 	do
4344 	{
4345 		if ( *string )
4346 		{
4347 			free( *string );
4348 		}
4349 
4350 		*string = (char*) malloc( *stringLen );
4351 		require_action( *string, exit, err = mStatus_NoMemoryErr );
4352 
4353 		err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
4354 
4355 		i++;
4356 	}
4357 	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
4358 
4359 	require_noerr_quiet( err, exit );
4360 
4361 	if ( enabled )
4362 	{
4363 		DWORD dwSize = sizeof( DWORD );
4364 
4365 		err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize );
4366 		check_noerr( err );
4367 
4368 		err = kNoErr;
4369 	}
4370 
4371 exit:
4372 
4373 	return err;
4374 }
4375 
4376 
4377 //===========================================================================================================================
4378 //	StringToAddress
4379 //===========================================================================================================================
4380 
StringToAddress(mDNSAddr * ip,LPSTR string)4381 mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
4382 {
4383 	struct sockaddr_in6 sa6;
4384 	struct sockaddr_in	sa4;
4385 	INT					dwSize;
4386 	mStatus				err;
4387 
4388 	sa6.sin6_family	= AF_INET6;
4389 	dwSize			= sizeof( sa6 );
4390 
4391 	err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
4392 
4393 	if ( err == mStatus_NoError )
4394 	{
4395 		err = SetupAddr( ip, (struct sockaddr*) &sa6 );
4396 		require_noerr( err, exit );
4397 	}
4398 	else
4399 	{
4400 		sa4.sin_family = AF_INET;
4401 		dwSize = sizeof( sa4 );
4402 
4403 		err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
4404 		err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr );
4405 		require_noerr( err, exit );
4406 
4407 		err = SetupAddr( ip, (struct sockaddr*) &sa4 );
4408 		require_noerr( err, exit );
4409 	}
4410 
4411 exit:
4412 
4413 	return err;
4414 }
4415 
4416 
4417 //===========================================================================================================================
4418 //	myGetIfAddrs
4419 //===========================================================================================================================
4420 
4421 mDNSlocal struct ifaddrs*
myGetIfAddrs(int refresh)4422 myGetIfAddrs(int refresh)
4423 {
4424 	static struct ifaddrs *ifa = NULL;
4425 
4426 	if (refresh && ifa)
4427 	{
4428 		freeifaddrs(ifa);
4429 		ifa = NULL;
4430 	}
4431 
4432 	if (ifa == NULL)
4433 	{
4434 		getifaddrs(&ifa);
4435 	}
4436 
4437 	return ifa;
4438 }
4439 
4440 
4441 //===========================================================================================================================
4442 //	TCHARtoUTF8
4443 //===========================================================================================================================
4444 
4445 mDNSlocal OSStatus
TCHARtoUTF8(const TCHAR * inString,char * inBuffer,size_t inBufferSize)4446 TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize )
4447 {
4448 #if( defined( UNICODE ) || defined( _UNICODE ) )
4449 	OSStatus		err;
4450 	int				len;
4451 
4452 	len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL );
4453 	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
4454 	require_noerr( err, exit );
4455 
4456 exit:
4457 	return( err );
4458 #else
4459 	return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) );
4460 #endif
4461 }
4462 
4463 
4464 //===========================================================================================================================
4465 //	WindowsLatin1toUTF8
4466 //===========================================================================================================================
4467 
4468 mDNSlocal OSStatus
WindowsLatin1toUTF8(const char * inString,char * inBuffer,size_t inBufferSize)4469 WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize )
4470 {
4471 	OSStatus		err;
4472 	WCHAR *			utf16;
4473 	int				len;
4474 
4475 	utf16 = NULL;
4476 
4477 	// Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first.
4478 
4479 	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 );
4480 	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
4481 	require_noerr( err, exit );
4482 
4483 	utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) );
4484 	require_action( utf16, exit, err = kNoMemoryErr );
4485 
4486 	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len );
4487 	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
4488 	require_noerr( err, exit );
4489 
4490 	// Now convert the temporary UTF-16 to UTF-8.
4491 
4492 	len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL );
4493 	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
4494 	require_noerr( err, exit );
4495 
4496 exit:
4497 	if( utf16 ) free( utf16 );
4498 	return( err );
4499 }
4500 
4501 
4502 //===========================================================================================================================
4503 //	TCPCloseSocket
4504 //===========================================================================================================================
4505 
4506 mDNSlocal void
TCPCloseSocket(TCPSocket * sock)4507 TCPCloseSocket( TCPSocket * sock )
4508 {
4509 	dlog( kDebugLevelChatty, DEBUG_NAME "closing TCPSocket 0x%x:%d\n", sock, sock->fd );
4510 
4511 	RemoveFromList( &gTCPDispatchableSockets, sock );
4512 
4513 	if ( sock->fd != INVALID_SOCKET )
4514 	{
4515 		closesocket( sock->fd );
4516 		sock->fd = INVALID_SOCKET;
4517 	}
4518 }
4519 
4520 
4521 //===========================================================================================================================
4522 //	TCPFreeSocket
4523 //===========================================================================================================================
4524 
4525 mDNSlocal void CALLBACK
TCPFreeSocket(TCPSocket * sock)4526 TCPFreeSocket( TCPSocket *sock )
4527 {
4528 	check( sock );
4529 
4530 	dlog( kDebugLevelChatty, DEBUG_NAME "freeing TCPSocket 0x%x:%d\n", sock, sock->fd );
4531 
4532 	if ( sock->connectEvent )
4533 	{
4534 		CloseHandle( sock->connectEvent );
4535 		sock->connectEvent = NULL;
4536 	}
4537 
4538 	if ( sock->fd != INVALID_SOCKET )
4539 	{
4540 		closesocket( sock->fd );
4541 		sock->fd = INVALID_SOCKET;
4542 	}
4543 
4544 	free( sock );
4545 }
4546 
4547 
4548 //===========================================================================================================================
4549 //  UDPCloseSocket
4550 //===========================================================================================================================
4551 
4552 mDNSlocal void
UDPCloseSocket(UDPSocket * sock)4553 UDPCloseSocket( UDPSocket * sock )
4554 {
4555 	dlog( kDebugLevelChatty, DEBUG_NAME "closing UDPSocket %d\n", sock->fd );
4556 
4557 	RemoveFromList( &gUDPDispatchableSockets, sock );
4558 
4559 	if ( sock->fd != INVALID_SOCKET )
4560 	{
4561 		closesocket( sock->fd );
4562 		sock->fd = INVALID_SOCKET;
4563 	}
4564 }
4565 
4566 
4567 //===========================================================================================================================
4568 //  UDPFreeSocket
4569 //===========================================================================================================================
4570 
4571 mDNSlocal void CALLBACK
UDPFreeSocket(UDPSocket * sock)4572 UDPFreeSocket( UDPSocket * sock )
4573 {
4574     check( sock );
4575 
4576 	dlog( kDebugLevelChatty, DEBUG_NAME "freeing UDPSocket %d\n", sock->fd );
4577 
4578     if ( sock->fd != INVALID_SOCKET )
4579     {
4580         closesocket( sock->fd );
4581 		sock->fd = INVALID_SOCKET;
4582     }
4583 
4584     free( sock );
4585 }
4586 
4587 //===========================================================================================================================
4588 //	SetupAddr
4589 //===========================================================================================================================
4590 
SetupAddr(mDNSAddr * ip,const struct sockaddr * const sa)4591 mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
4592 	{
4593 	if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
4594 
4595 	if (sa->sa_family == AF_INET)
4596 		{
4597 		struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
4598 		ip->type = mDNSAddrType_IPv4;
4599 		ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
4600 		return(mStatus_NoError);
4601 		}
4602 
4603 	if (sa->sa_family == AF_INET6)
4604 		{
4605 		struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
4606 		ip->type = mDNSAddrType_IPv6;
4607 		if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.u.Word[1] = 0;
4608 		ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
4609 		return(mStatus_NoError);
4610 		}
4611 
4612 	LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
4613 	return(mStatus_Invalid);
4614 	}
4615 
4616 
GetDDNSFQDN(domainname * const fqdn)4617 mDNSlocal void GetDDNSFQDN( domainname *const fqdn )
4618 {
4619 	LPSTR		name = NULL;
4620 	DWORD		dwSize;
4621 	DWORD		enabled;
4622 	HKEY		key = NULL;
4623 	OSStatus	err;
4624 
4625 	check( fqdn );
4626 
4627 	// Initialize
4628 
4629 	fqdn->c[0] = '\0';
4630 
4631 	// Get info from Bonjour registry key
4632 
4633 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
4634 	require_noerr( err, exit );
4635 
4636 	err = RegQueryString( key, "", &name, &dwSize, &enabled );
4637 	if ( !err && ( name[0] != '\0' ) && enabled )
4638 	{
4639 		if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
4640 		{
4641 			dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
4642 		}
4643 	}
4644 
4645 exit:
4646 
4647 	if ( key )
4648 	{
4649 		RegCloseKey( key );
4650 		key = NULL;
4651 	}
4652 
4653 	if ( name )
4654 	{
4655 		free( name );
4656 		name = NULL;
4657 	}
4658 }
4659 
4660 
4661 #ifdef UNICODE
GetDDNSDomains(DNameListElem ** domains,LPCWSTR lpSubKey)4662 mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
4663 #else
4664 mDNSlocal void GetDDNSConfig( DNameListElem ** domains, LPCSTR lpSubKey )
4665 #endif
4666 {
4667 	char		subKeyName[kRegistryMaxKeyLength + 1];
4668 	DWORD		cSubKeys = 0;
4669 	DWORD		cbMaxSubKey;
4670 	DWORD		cchMaxClass;
4671 	DWORD		dwSize;
4672 	HKEY		key = NULL;
4673 	HKEY		subKey = NULL;
4674 	domainname	dname;
4675 	DWORD		i;
4676 	OSStatus	err;
4677 
4678 	check( domains );
4679 
4680 	// Initialize
4681 
4682 	*domains = NULL;
4683 
4684 	err = RegCreateKey( HKEY_LOCAL_MACHINE, lpSubKey, &key );
4685 	require_noerr( err, exit );
4686 
4687 	// Get information about this node
4688 
4689 	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );
4690 	require_noerr( err, exit );
4691 
4692 	for ( i = 0; i < cSubKeys; i++)
4693 	{
4694 		DWORD enabled;
4695 
4696 		dwSize = kRegistryMaxKeyLength;
4697 
4698 		err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
4699 
4700 		if ( !err )
4701 		{
4702 			err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
4703 			require_noerr( err, exit );
4704 
4705 			dwSize = sizeof( DWORD );
4706 			err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
4707 
4708 			if ( !err && ( subKeyName[0] != '\0' ) && enabled )
4709 			{
4710 				if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
4711 				{
4712 					dlog( kDebugLevelError, "bad DDNS domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
4713 				}
4714 				else
4715 				{
4716 					DNameListElem * domain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
4717 					require_action( domain, exit, err = mStatus_NoMemoryErr );
4718 
4719 					AssignDomainName(&domain->name, &dname);
4720 					domain->next = *domains;
4721 
4722 					*domains = domain;
4723 				}
4724 			}
4725 
4726 			RegCloseKey( subKey );
4727 			subKey = NULL;
4728 		}
4729 	}
4730 
4731 exit:
4732 
4733 	if ( subKey )
4734 	{
4735 		RegCloseKey( subKey );
4736 	}
4737 
4738 	if ( key )
4739 	{
4740 		RegCloseKey( key );
4741 	}
4742 }
4743 
4744 
SetDomainSecret(mDNS * const m,const domainname * inDomain)4745 mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain )
4746 {
4747 	char					domainUTF8[ 256 ];
4748 	DomainAuthInfo			*foundInList;
4749 	DomainAuthInfo			*ptr;
4750 	char					outDomain[ 256 ];
4751 	char					outKey[ 256 ];
4752 	char					outSecret[ 256 ];
4753 	OSStatus				err;
4754 
4755 	ConvertDomainNameToCString( inDomain, domainUTF8 );
4756 
4757 	// If we're able to find a secret for this domain
4758 
4759 	if ( LsaGetSecret( domainUTF8, outDomain, sizeof( outDomain ), outKey, sizeof( outKey ), outSecret, sizeof( outSecret ) ) )
4760 	{
4761 		domainname domain;
4762 		domainname key;
4763 
4764 		// Tell the core about this secret
4765 
4766 		MakeDomainNameFromDNSNameString( &domain, outDomain );
4767 		MakeDomainNameFromDNSNameString( &key, outKey );
4768 
4769 		for (foundInList = m->AuthInfoList; foundInList; foundInList = foundInList->next)
4770 			if (SameDomainName(&foundInList->domain, &domain ) ) break;
4771 
4772 		ptr = foundInList;
4773 
4774 		if (!ptr)
4775 		{
4776 			ptr = (DomainAuthInfo*)malloc(sizeof(DomainAuthInfo));
4777 			require_action( ptr, exit, err = mStatus_NoMemoryErr );
4778 		}
4779 
4780 		err = mDNS_SetSecretForDomain(m, ptr, &domain, &key, outSecret, NULL, 0, NULL );
4781 		require_action( err != mStatus_BadParamErr, exit, if (!foundInList ) mDNSPlatformMemFree( ptr ) );
4782 
4783 		debugf("Setting shared secret for zone %s with key %##s", outDomain, key.c);
4784 	}
4785 
4786 exit:
4787 
4788 	return;
4789 }
4790 
4791 
4792 mDNSlocal VOID CALLBACK
CheckFileSharesProc(LPVOID arg,DWORD dwTimerLowValue,DWORD dwTimerHighValue)4793 CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
4794 {
4795 	mDNS * const m = ( mDNS * const ) arg;
4796 
4797 	( void ) dwTimerLowValue;
4798 	( void ) dwTimerHighValue;
4799 
4800 	CheckFileShares( m );
4801 }
4802 
4803 
4804 mDNSlocal unsigned __stdcall
SMBRegistrationThread(void * arg)4805 SMBRegistrationThread( void * arg )
4806 {
4807 	mDNS * const m = ( mDNS * const ) arg;
4808 	DNSServiceRef sref = NULL;
4809 	HANDLE		handles[ 3 ];
4810 	mDNSu8		txtBuf[ 256 ];
4811 	mDNSu8	*	txtPtr;
4812 	size_t		keyLen;
4813 	size_t		valLen;
4814 	mDNSIPPort	port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
4815 	DNSServiceErrorType err;
4816 
4817 	DEBUG_UNUSED( arg );
4818 
4819 	handles[ 0 ] = gSMBThreadStopEvent;
4820 	handles[ 1 ] = gSMBThreadRegisterEvent;
4821 	handles[ 2 ] = gSMBThreadDeregisterEvent;
4822 
4823 	memset( txtBuf, 0, sizeof( txtBuf )  );
4824 	txtPtr = txtBuf;
4825 	keyLen = strlen( "netbios=" );
4826 	valLen = strlen( m->p->nbname );
4827 	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
4828 	*txtPtr++ = ( mDNSu8 ) ( keyLen + valLen );
4829 	memcpy( txtPtr, "netbios=", keyLen );
4830 	txtPtr += keyLen;
4831 	if ( valLen ) { memcpy( txtPtr, m->p->nbname, valLen ); txtPtr += ( mDNSu8 ) valLen; }
4832 	keyLen = strlen( "domain=" );
4833 	valLen = strlen( m->p->nbdomain );
4834 	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
4835 	*txtPtr++ = ( mDNSu8 )( keyLen + valLen );
4836 	memcpy( txtPtr, "domain=", keyLen );
4837 	txtPtr += keyLen;
4838 	if ( valLen ) { memcpy( txtPtr, m->p->nbdomain, valLen ); txtPtr += valLen; }
4839 
4840 	for ( ;; )
4841 	{
4842 		DWORD ret;
4843 
4844 		ret = WaitForMultipleObjects( 3, handles, FALSE, INFINITE );
4845 
4846 		if ( ret != WAIT_FAILED )
4847 		{
4848 			if ( ret == kSMBStopEvent )
4849 			{
4850 				break;
4851 			}
4852 			else if ( ret == kSMBRegisterEvent )
4853 			{
4854 				err = gDNSServiceRegister( &sref, 0, 0, NULL, "_smb._tcp,_file", NULL, NULL, ( uint16_t ) port.NotAnInteger, ( mDNSu16 )( txtPtr - txtBuf ), txtBuf, NULL, NULL );
4855 
4856 				if ( err )
4857 				{
4858 					LogMsg( "SMBRegistrationThread: DNSServiceRegister returned %d\n", err );
4859 					sref = NULL;
4860 					break;
4861 				}
4862 			}
4863 			else if ( ret == kSMBDeregisterEvent )
4864 			{
4865 				if ( sref )
4866 				{
4867 					gDNSServiceRefDeallocate( sref );
4868 					sref = NULL;
4869 				}
4870 			}
4871 		}
4872 		else
4873 		{
4874 			LogMsg( "SMBRegistrationThread:  WaitForMultipleObjects returned %d\n", GetLastError() );
4875 			break;
4876 		}
4877 	}
4878 
4879 exit:
4880 
4881 	if ( sref != NULL )
4882 	{
4883 		gDNSServiceRefDeallocate( sref );
4884 		sref = NULL;
4885 	}
4886 
4887 	SetEvent( gSMBThreadQuitEvent );
4888 	_endthreadex( 0 );
4889 	return 0;
4890 }
4891 
4892 
4893 mDNSlocal void
CheckFileShares(mDNS * const m)4894 CheckFileShares( mDNS * const m )
4895 {
4896 	PSHARE_INFO_1	bufPtr = ( PSHARE_INFO_1 ) NULL;
4897 	DWORD			entriesRead = 0;
4898 	DWORD			totalEntries = 0;
4899 	DWORD			resume = 0;
4900 	mDNSBool		advertise = mDNSfalse;
4901 	mDNSBool		fileSharing = mDNSfalse;
4902 	mDNSBool		printSharing = mDNSfalse;
4903 	HKEY			key = NULL;
4904 	BOOL			retry = FALSE;
4905 	NET_API_STATUS  res;
4906 	mStatus			err;
4907 
4908 	check( m );
4909 
4910 	// Only do this if we're not shutting down
4911 
4912 	require_action_quiet( m->AdvertiseLocalAddresses && !m->ShutdownTime, exit, err = kNoErr );
4913 
4914 	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", &key );
4915 
4916 	if ( !err )
4917 	{
4918 		DWORD dwSize = sizeof( DWORD );
4919 		RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &advertise, &dwSize );
4920 	}
4921 
4922 	if ( advertise && mDNSIsFileAndPrintSharingEnabled( &retry ) )
4923 	{
4924 		dlog( kDebugLevelTrace, DEBUG_NAME "Sharing is enabled\n" );
4925 
4926 		res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
4927 
4928 		if ( ( res == ERROR_SUCCESS ) || ( res == ERROR_MORE_DATA ) )
4929 		{
4930 			PSHARE_INFO_1 p = bufPtr;
4931 			DWORD i;
4932 
4933 			for( i = 0; i < entriesRead; i++ )
4934 			{
4935 				// We are only interested if the user is sharing anything other
4936 				// than the built-in "print$" source
4937 
4938 				if ( ( p->shi1_type == STYPE_DISKTREE ) && ( wcscmp( p->shi1_netname, TEXT( "print$" ) ) != 0 ) )
4939 				{
4940 					fileSharing = mDNStrue;
4941 				}
4942 				else if ( p->shi1_type == STYPE_PRINTQ )
4943 				{
4944 					printSharing = mDNStrue;
4945 				}
4946 
4947 				p++;
4948 			}
4949 
4950 			NetApiBufferFree( bufPtr );
4951 			bufPtr = NULL;
4952 			retry = FALSE;
4953 		}
4954 		else if ( res == NERR_ServerNotStarted )
4955 		{
4956 			retry = TRUE;
4957 		}
4958 	}
4959 
4960 	if ( retry )
4961 	{
4962 		__int64			qwTimeout;
4963 		LARGE_INTEGER   liTimeout;
4964 
4965 		qwTimeout = -m->p->checkFileSharesTimeout * 10000000;
4966 		liTimeout.LowPart  = ( DWORD )( qwTimeout & 0xFFFFFFFF );
4967 		liTimeout.HighPart = ( LONG )( qwTimeout >> 32 );
4968 
4969 		SetWaitableTimer( m->p->checkFileSharesTimer, &liTimeout, 0, CheckFileSharesProc, m, FALSE );
4970 	}
4971 
4972 	if ( !m->p->smbFileSharing && fileSharing )
4973 	{
4974 		if ( !gSMBThread )
4975 		{
4976 			if ( !gDNSSDLibrary )
4977 			{
4978 				gDNSSDLibrary = LoadLibrary( TEXT( "dnssd.dll" ) );
4979 				require_action( gDNSSDLibrary, exit, err = GetLastError() );
4980 			}
4981 
4982 			if ( !gDNSServiceRegister )
4983 			{
4984 				gDNSServiceRegister = ( DNSServiceRegisterFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRegister" );
4985 				require_action( gDNSServiceRegister, exit, err = GetLastError() );
4986 			}
4987 
4988 			if ( !gDNSServiceRefDeallocate )
4989 			{
4990 				gDNSServiceRefDeallocate = ( DNSServiceRefDeallocateFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRefDeallocate" );
4991 				require_action( gDNSServiceRefDeallocate, exit, err = GetLastError() );
4992 			}
4993 
4994 			if ( !gSMBThreadRegisterEvent )
4995 			{
4996 				gSMBThreadRegisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
4997 				require_action( gSMBThreadRegisterEvent != NULL, exit, err = GetLastError() );
4998 			}
4999 
5000 			if ( !gSMBThreadDeregisterEvent )
5001 			{
5002 				gSMBThreadDeregisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
5003 				require_action( gSMBThreadDeregisterEvent != NULL, exit, err = GetLastError() );
5004 			}
5005 
5006 			if ( !gSMBThreadStopEvent )
5007 			{
5008 				gSMBThreadStopEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
5009 				require_action( gSMBThreadStopEvent != NULL, exit, err = GetLastError() );
5010 			}
5011 
5012 			if ( !gSMBThreadQuitEvent )
5013 			{
5014 				gSMBThreadQuitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
5015 				require_action( gSMBThreadQuitEvent != NULL, exit, err = GetLastError() );
5016 			}
5017 
5018 			gSMBThread = ( HANDLE ) _beginthreadex( NULL, 0, SMBRegistrationThread, m, 0, NULL );
5019 			require_action( gSMBThread != NULL, exit, err = GetLastError() );
5020 		}
5021 
5022 		SetEvent( gSMBThreadRegisterEvent );
5023 
5024 		m->p->smbFileSharing = mDNStrue;
5025 	}
5026 	else if ( m->p->smbFileSharing && !fileSharing )
5027 	{
5028 		dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
5029 
5030 		if ( gSMBThreadDeregisterEvent != NULL )
5031 		{
5032 			SetEvent( gSMBThreadDeregisterEvent );
5033 		}
5034 
5035 		m->p->smbFileSharing = mDNSfalse;
5036 	}
5037 
5038 exit:
5039 
5040 	if ( key )
5041 	{
5042 		RegCloseKey( key );
5043 	}
5044 }
5045 
5046 
5047 BOOL
IsWOMPEnabled(mDNS * const m)5048 IsWOMPEnabled( mDNS * const m )
5049 {
5050 	BOOL enabled;
5051 
5052 	mDNSInterfaceData * ifd;
5053 
5054 	enabled = FALSE;
5055 
5056 	for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
5057 	{
5058 		if ( IsWOMPEnabledForAdapter( ifd->name ) )
5059 		{
5060 			enabled = TRUE;
5061 			break;
5062 		}
5063 	}
5064 
5065 	return enabled;
5066 }
5067 
5068 
5069 mDNSlocal mDNSu8
IsWOMPEnabledForAdapter(const char * adapterName)5070 IsWOMPEnabledForAdapter( const char * adapterName )
5071 {
5072 	char						fileName[80];
5073 	NDIS_OID					oid;
5074     DWORD						count;
5075     HANDLE						handle	= INVALID_HANDLE_VALUE;
5076 	NDIS_PNP_CAPABILITIES	*	pNPC	= NULL;
5077 	int							err;
5078 	mDNSu8						ok		= TRUE;
5079 
5080 	require_action( adapterName != NULL, exit, ok = FALSE );
5081 
5082 	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter: %s\n", adapterName );
5083 
5084     // Construct a device name to pass to CreateFile
5085 
5086 	strncpy_s( fileName, sizeof( fileName ), DEVICE_PREFIX, strlen( DEVICE_PREFIX ) );
5087 	strcat_s( fileName, sizeof( fileName ), adapterName );
5088     handle = CreateFileA( fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, INVALID_HANDLE_VALUE );
5089 	require_action ( handle != INVALID_HANDLE_VALUE, exit, ok = FALSE );
5090 
5091 	// We successfully opened the driver, format the IOCTL to pass the driver.
5092 
5093 	oid = OID_PNP_CAPABILITIES;
5094 	pNPC = ( NDIS_PNP_CAPABILITIES * ) malloc( sizeof( NDIS_PNP_CAPABILITIES ) );
5095 	require_action( pNPC != NULL, exit, ok = FALSE );
5096 	ok = ( mDNSu8 ) DeviceIoControl( handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof( oid ), pNPC, sizeof( NDIS_PNP_CAPABILITIES ), &count, NULL );
5097 	err = translate_errno( ok, GetLastError(), kUnknownErr );
5098 	require_action( !err, exit, ok = FALSE );
5099 	ok = ( mDNSu8 ) ( ( count == sizeof( NDIS_PNP_CAPABILITIES ) ) && ( pNPC->Flags & NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE ) );
5100 
5101 exit:
5102 
5103 	if ( pNPC != NULL )
5104 	{
5105 		free( pNPC );
5106 	}
5107 
5108     if ( handle != INVALID_HANDLE_VALUE )
5109     {
5110 		CloseHandle( handle );
5111     }
5112 
5113 	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter returns %s\n", ok ? "true" : "false" );
5114 
5115 	return ( mDNSu8 ) ok;
5116 }
5117 
5118 
5119 void
DispatchSocketEvents(mDNS * const inMDNS)5120 DispatchSocketEvents( mDNS * const inMDNS )
5121 {
5122 	UDPSocket * udpSock;
5123 	TCPSocket * tcpSock;
5124 
5125 	while ( ( udpSock = ( UDPSocket* ) gUDPDispatchableSockets.Head ) != NULL )
5126 	{
5127 		dlog( kDebugLevelChatty, DEBUG_NAME "%s: calling DispatchUDPEvent on socket %d, error = %d, bytesTransferred = %d\n",
5128 		                                     __ROUTINE__, udpSock->fd, udpSock->overlapped.error, udpSock->overlapped.bytesTransferred );
5129 		RemoveFromList( &gUDPDispatchableSockets, udpSock );
5130 		DispatchUDPEvent( inMDNS, udpSock );
5131 	}
5132 
5133 	while ( ( tcpSock = ( TCPSocket* ) gTCPDispatchableSockets.Head ) != NULL )
5134 	{
5135 		dlog( kDebugLevelChatty, DEBUG_NAME "%s: calling DispatchTCPEvent on socket %d, error = %d, bytesTransferred = %d\n",
5136 		                                     __ROUTINE__, tcpSock->fd, tcpSock->overlapped.error, tcpSock->overlapped.bytesTransferred );
5137 		RemoveFromList( &gTCPDispatchableSockets, tcpSock );
5138 		DispatchTCPEvent( inMDNS, tcpSock );
5139 	}
5140 }
5141 
5142 
5143 mDNSlocal void
DispatchUDPEvent(mDNS * const inMDNS,UDPSocket * sock)5144 DispatchUDPEvent( mDNS * const inMDNS, UDPSocket * sock )
5145 {
5146 	( void ) inMDNS;
5147 
5148 	// If we've closed the socket, then we want to ignore
5149 	// this read.  The packet might have been queued before
5150 	// the socket was closed.
5151 
5152 	if ( sock->fd != INVALID_SOCKET )
5153 	{
5154 		const mDNSInterfaceID	iid = sock->ifd ? sock->ifd->interfaceInfo.InterfaceID : NULL;
5155 		mDNSu8				*	end = ( (mDNSu8 *) &sock->packet ) + sock->overlapped.bytesTransferred;
5156 
5157 		dlog( kDebugLevelChatty, DEBUG_NAME "calling mDNSCoreReceive on socket: %d\n", sock->fd );
5158 		mDNSCoreReceive( sock->m, &sock->packet, end, &sock->overlapped.srcAddr, sock->overlapped.srcPort, &sock->overlapped.dstAddr, sock->overlapped.dstPort, iid );
5159 	}
5160 
5161 	// If the socket is still good, then start up another asynchronous read
5162 
5163 	if ( sock->fd != INVALID_SOCKET )
5164 	{
5165 		int err = UDPBeginRecv( sock );
5166 		check_noerr( err );
5167 	}
5168 }
5169 
5170 
5171 mDNSlocal void
DispatchTCPEvent(mDNS * const inMDNS,TCPSocket * sock)5172 DispatchTCPEvent( mDNS * const inMDNS, TCPSocket * sock )
5173 {
5174 	( void ) inMDNS;
5175 
5176 	if ( sock->fd != INVALID_SOCKET )
5177 	{
5178 		sock->eptr += sock->overlapped.bytesTransferred;
5179 		sock->lastError = sock->overlapped.error;
5180 
5181 		if ( !sock->overlapped.error && !sock->overlapped.bytesTransferred )
5182 		{
5183 			sock->closed = TRUE;
5184 		}
5185 
5186 		if ( sock->readEventHandler != NULL )
5187 		{
5188 			dlog( kDebugLevelChatty, DEBUG_NAME "calling TCP read handler  on socket: %d\n", sock->fd );
5189 			sock->readEventHandler( sock );
5190 		}
5191 	}
5192 
5193 	// If the socket is still good, then start up another asynchronous read
5194 
5195 	if ( !sock->closed && ( sock->fd != INVALID_SOCKET ) )
5196 	{
5197 		int err = TCPBeginRecv( sock );
5198 		check_noerr( err );
5199 	}
5200 }
5201